From af7d69980f03dbff4a7c3b1fcc02d40596da7f34 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 1 Jul 2026 21:16:40 +0200 Subject: [PATCH] Start from scratch --- .envrc | 9 +- .gitignore | 16 + .gitmodules | 3 - .pre-commit-config.yaml | 2 +- Cargo.lock | 982 ++++ Cargo.toml | 27 + api/Analyze Album.bru | 22 - api/Get Album.bru | 22 - api/Get Artist Albums.bru | 22 - api/Get Artists.bru | 20 - api/Hello Echo.bru | 23 - api/Hello Ping.bru | 21 - api/Indexer/Capabilities.bru | 24 - api/Indexer/Search.bru | 25 - api/Indexer/folder.bru | 8 - api/Jackett/Capabilities.bru | 20 - api/Jackett/Search.bru | 23 - api/Jackett/folder.bru | 8 - api/Metadata Agregator/Get Album.bru | 22 - api/Metadata Agregator/Get Artist Albums.bru | 22 - api/Metadata Agregator/Get Artist.bru | 22 - api/Metadata Agregator/Search Albums.bru | 30 - api/Metadata Agregator/Search Artists.bru | 22 - api/Metadata Agregator/folder.bru | 8 - api/Monitor Album.bru | 26 - api/SearchArtists.bru | 22 - api/bruno.json | 27 - api/collection.bru | 0 buf.gen.yaml | 33 +- cmd/music-agregator/main.go | 268 - config.example.yaml | 31 - config.test.yaml | 22 - .../database/music-agregator/002_schema.sql | 112 - .../music-agregator/003_event_bus.sql | 33 - containers/docker-compose.yml | 63 - devenv.lock | 124 + devenv.nix | 43 + devenv.yaml | 13 + docs/research/lidarr/erd.puml | 362 -- docs/research/lidarr/research_summary.md | 93 - flake.lock | 40 +- gen/metadata/v1/metadata.pb.go | 2098 -------- gen/metadata/v1/metadata_grpc.pb.go | 387 -- gen/music_agregator/hello/v1/service.pb.go | 252 - .../hello/v1/service_grpc.pb.go | 159 - gen/music_agregator/indexer/v1/indexer.pb.go | 1179 ----- .../indexer/v1/indexer_grpc.pb.go | 159 - .../metadata/v1/metadata.pb.go | 60 - .../metadata/v1/metadata_grpc.pb.go | 76 - gen/music_agregator/torrent/v1/torrent.pb.go | 713 --- .../torrent/v1/torrent_grpc.pb.go | 159 - gen/music_agregator/v1/music_agregator.pb.go | 4364 ----------------- .../v1/music_agregator_grpc.pb.go | 426 -- gen/musicfs.pb.go | 3274 ------------- gen/musicfs/v1/musicfs.pb.go | 3274 ------------- gen/musicfs/v1/musicfs_grpc.pb.go | 775 --- gen/musicfs_grpc.pb.go | 775 --- go.mod | 174 - go.sum | 710 --- internal/analysis/analyzer.go | 285 -- internal/audio/analyzer.go | 35 - internal/audio/flac.go | 27 - internal/audio/mp3.go | 54 - internal/config/config.go | 85 - internal/database/album_event_repository.go | 116 - internal/database/album_release_repository.go | 91 - internal/database/album_repository.go | 178 - internal/database/artist_repository.go | 100 - internal/database/db.go | 40 - internal/database/download_file_repository.go | 104 - internal/database/download_repository.go | 227 - internal/database/torrent_repository.go | 104 - internal/database/track_release_repository.go | 79 - internal/database/track_repository.go | 68 - internal/database/workflow_run_repository.go | 123 - internal/event_publisher.go | 260 - internal/eventbus/bus.go | 116 - internal/eventbus/bus_test.go | 168 - internal/eventbus/ring.go | 56 - internal/eventbus/ring_test.go | 109 - internal/hello/server.go | 32 - internal/indexer/cache.go | 79 - internal/indexer/cache_worker.go | 71 - internal/indexer/cached_indexer.go | 90 - internal/indexer/filter.go | 5 - internal/indexer/indexer.go | 8 - internal/indexer/indexer_capabilities.go | 103 - internal/indexer/jackett.go | 139 - internal/indexer/search.go | 140 - internal/indexer/server.go | 67 - internal/indexer/service.go | 66 - internal/matcher/album.go | 135 - internal/matcher/album_test.go | 95 - internal/metadata/client.go | 24 - internal/metadata/server.go | 77 - internal/metadata/service.go | 235 - internal/monitor_workflow.go | 456 -- internal/musicfs/client.go | 32 - internal/musicfs/enricher.go | 92 - internal/musicfs/subdir.go | 20 - internal/musicfs/subdir_test.go | 60 - internal/musicfs/sync.go | 62 - internal/registrable.go | 7 - internal/release/release.go | 218 - internal/server.go | 330 -- internal/service.go | 1454 ------ internal/torrent/client.go | 50 - internal/torrent/factory.go | 36 - internal/torrent/path_mapper.go | 88 - internal/torrent/qbittorrent_client.go | 373 -- internal/torrent/server.go | 39 - internal/torrent/service.go | 199 - internal/tracker/generic_parser.go | 351 -- internal/tracker/generic_parser_test.go | 572 --- internal/tracker/magnet.go | 154 - internal/workers/poll_download.go | 282 -- internal/workflow_registry.go | 100 - internal/workflow_registry_test.go | 144 - justfile | 9 +- nix/default.nix | 68 - nix/jackett.nix | 75 - nix/metadata-agregator.nix | 142 - nix/music-agregator.nix | 275 -- nix/musicfs.nix | 142 - nix/postgres.nix | 237 - nix/qbittorrent.nix | 136 - nix/sql/metadata/001_schema.sql | 194 - nix/sql/music/001_river.sql | 286 -- nix/sql/music/002_schema.sql | 166 - nix/sql/music/003_event_bus.sql | 33 - nix/vpn.nix | 48 - package.nix | 26 - proto/hello.proto | 16 + proto/music_agregator/hello/v1/service.proto | 22 - .../music_agregator/indexer/v1/indexer.proto | 109 - .../music_agregator/torrent/v1/torrent.proto | 72 - .../music_agregator/v1/music_agregator.proto | 410 -- src/generated/hello/hello.rs | 78 + src/generated/hello/hello.serde.rs | 185 + src/generated/hello/hello.tonic.rs | 270 + src/generated/metadata/v1/metadata.v1.rs | 1282 +++++ .../metadata/v1/metadata.v1.serde.rs | 3596 ++++++++++++++ .../metadata/v1/metadata.v1.tonic.rs | 705 +++ src/generated/mod.rs | 7 + src/generated/musicfs/musicfs.rs | 842 ++++ src/generated/musicfs/musicfs.serde.rs | 2443 +++++++++ src/generated/musicfs/musicfs.tonic.rs | 1157 +++++ src/main.rs | 44 + test/component/fixtures_test.go | 83 - test/component/mocks_test.go | 167 - test/component/monitor_album_stream_test.go | 2071 -------- test/component/monitor_album_test.go | 1200 ----- test/component/setup_test.go | 198 - test/component/subscribe_events_test.go | 362 -- test/component/workflow_event_test.go | 422 -- test/unit/generic_parser_test.go | 577 --- tests/simple-test.nix | 104 - 157 files changed, 11876 insertions(+), 37022 deletions(-) delete mode 100644 .gitmodules create mode 100644 Cargo.lock create mode 100644 Cargo.toml delete mode 100644 api/Analyze Album.bru delete mode 100644 api/Get Album.bru delete mode 100644 api/Get Artist Albums.bru delete mode 100644 api/Get Artists.bru delete mode 100644 api/Hello Echo.bru delete mode 100644 api/Hello Ping.bru delete mode 100644 api/Indexer/Capabilities.bru delete mode 100644 api/Indexer/Search.bru delete mode 100644 api/Indexer/folder.bru delete mode 100644 api/Jackett/Capabilities.bru delete mode 100644 api/Jackett/Search.bru delete mode 100644 api/Jackett/folder.bru delete mode 100644 api/Metadata Agregator/Get Album.bru delete mode 100644 api/Metadata Agregator/Get Artist Albums.bru delete mode 100644 api/Metadata Agregator/Get Artist.bru delete mode 100644 api/Metadata Agregator/Search Albums.bru delete mode 100644 api/Metadata Agregator/Search Artists.bru delete mode 100644 api/Metadata Agregator/folder.bru delete mode 100644 api/Monitor Album.bru delete mode 100644 api/SearchArtists.bru delete mode 100644 api/bruno.json delete mode 100644 api/collection.bru delete mode 100644 cmd/music-agregator/main.go delete mode 100644 config.example.yaml delete mode 100644 config.test.yaml delete mode 100644 containers/database/music-agregator/002_schema.sql delete mode 100644 containers/database/music-agregator/003_event_bus.sql delete mode 100644 containers/docker-compose.yml create mode 100644 devenv.lock create mode 100644 devenv.nix create mode 100644 devenv.yaml delete mode 100644 docs/research/lidarr/erd.puml delete mode 100644 docs/research/lidarr/research_summary.md delete mode 100644 gen/metadata/v1/metadata.pb.go delete mode 100644 gen/metadata/v1/metadata_grpc.pb.go delete mode 100644 gen/music_agregator/hello/v1/service.pb.go delete mode 100644 gen/music_agregator/hello/v1/service_grpc.pb.go delete mode 100644 gen/music_agregator/indexer/v1/indexer.pb.go delete mode 100644 gen/music_agregator/indexer/v1/indexer_grpc.pb.go delete mode 100644 gen/music_agregator/metadata/v1/metadata.pb.go delete mode 100644 gen/music_agregator/metadata/v1/metadata_grpc.pb.go delete mode 100644 gen/music_agregator/torrent/v1/torrent.pb.go delete mode 100644 gen/music_agregator/torrent/v1/torrent_grpc.pb.go delete mode 100644 gen/music_agregator/v1/music_agregator.pb.go delete mode 100644 gen/music_agregator/v1/music_agregator_grpc.pb.go delete mode 100644 gen/musicfs.pb.go delete mode 100644 gen/musicfs/v1/musicfs.pb.go delete mode 100644 gen/musicfs/v1/musicfs_grpc.pb.go delete mode 100644 gen/musicfs_grpc.pb.go delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100644 internal/analysis/analyzer.go delete mode 100644 internal/audio/analyzer.go delete mode 100644 internal/audio/flac.go delete mode 100644 internal/audio/mp3.go delete mode 100644 internal/config/config.go delete mode 100644 internal/database/album_event_repository.go delete mode 100644 internal/database/album_release_repository.go delete mode 100644 internal/database/album_repository.go delete mode 100644 internal/database/artist_repository.go delete mode 100644 internal/database/db.go delete mode 100644 internal/database/download_file_repository.go delete mode 100644 internal/database/download_repository.go delete mode 100644 internal/database/torrent_repository.go delete mode 100644 internal/database/track_release_repository.go delete mode 100644 internal/database/track_repository.go delete mode 100644 internal/database/workflow_run_repository.go delete mode 100644 internal/event_publisher.go delete mode 100644 internal/eventbus/bus.go delete mode 100644 internal/eventbus/bus_test.go delete mode 100644 internal/eventbus/ring.go delete mode 100644 internal/eventbus/ring_test.go delete mode 100644 internal/hello/server.go delete mode 100644 internal/indexer/cache.go delete mode 100644 internal/indexer/cache_worker.go delete mode 100644 internal/indexer/cached_indexer.go delete mode 100644 internal/indexer/filter.go delete mode 100644 internal/indexer/indexer.go delete mode 100644 internal/indexer/indexer_capabilities.go delete mode 100644 internal/indexer/jackett.go delete mode 100644 internal/indexer/search.go delete mode 100644 internal/indexer/server.go delete mode 100644 internal/indexer/service.go delete mode 100644 internal/matcher/album.go delete mode 100644 internal/matcher/album_test.go delete mode 100644 internal/metadata/client.go delete mode 100644 internal/metadata/server.go delete mode 100644 internal/metadata/service.go delete mode 100644 internal/monitor_workflow.go delete mode 100644 internal/musicfs/client.go delete mode 100644 internal/musicfs/enricher.go delete mode 100644 internal/musicfs/subdir.go delete mode 100644 internal/musicfs/subdir_test.go delete mode 100644 internal/musicfs/sync.go delete mode 100644 internal/registrable.go delete mode 100644 internal/release/release.go delete mode 100644 internal/server.go delete mode 100644 internal/service.go delete mode 100644 internal/torrent/client.go delete mode 100644 internal/torrent/factory.go delete mode 100644 internal/torrent/path_mapper.go delete mode 100644 internal/torrent/qbittorrent_client.go delete mode 100644 internal/torrent/server.go delete mode 100644 internal/torrent/service.go delete mode 100644 internal/tracker/generic_parser.go delete mode 100644 internal/tracker/generic_parser_test.go delete mode 100644 internal/tracker/magnet.go delete mode 100644 internal/workers/poll_download.go delete mode 100644 internal/workflow_registry.go delete mode 100644 internal/workflow_registry_test.go delete mode 100644 nix/default.nix delete mode 100644 nix/jackett.nix delete mode 100644 nix/metadata-agregator.nix delete mode 100644 nix/music-agregator.nix delete mode 100644 nix/musicfs.nix delete mode 100644 nix/postgres.nix delete mode 100644 nix/qbittorrent.nix delete mode 100644 nix/sql/metadata/001_schema.sql delete mode 100644 nix/sql/music/001_river.sql delete mode 100644 nix/sql/music/002_schema.sql delete mode 100644 nix/sql/music/003_event_bus.sql delete mode 100644 nix/vpn.nix delete mode 100644 package.nix create mode 100644 proto/hello.proto delete mode 100644 proto/music_agregator/hello/v1/service.proto delete mode 100644 proto/music_agregator/indexer/v1/indexer.proto delete mode 100644 proto/music_agregator/torrent/v1/torrent.proto delete mode 100644 proto/music_agregator/v1/music_agregator.proto create mode 100644 src/generated/hello/hello.rs create mode 100644 src/generated/hello/hello.serde.rs create mode 100644 src/generated/hello/hello.tonic.rs create mode 100644 src/generated/metadata/v1/metadata.v1.rs create mode 100644 src/generated/metadata/v1/metadata.v1.serde.rs create mode 100644 src/generated/metadata/v1/metadata.v1.tonic.rs create mode 100644 src/generated/mod.rs create mode 100644 src/generated/musicfs/musicfs.rs create mode 100644 src/generated/musicfs/musicfs.serde.rs create mode 100644 src/generated/musicfs/musicfs.tonic.rs create mode 100644 src/main.rs delete mode 100644 test/component/fixtures_test.go delete mode 100644 test/component/mocks_test.go delete mode 100644 test/component/monitor_album_stream_test.go delete mode 100644 test/component/monitor_album_test.go delete mode 100644 test/component/setup_test.go delete mode 100644 test/component/subscribe_events_test.go delete mode 100644 test/component/workflow_event_test.go delete mode 100644 test/unit/generic_parser_test.go delete mode 100644 tests/simple-test.nix diff --git a/.envrc b/.envrc index 3550a30..3036deb 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,8 @@ -use flake +#!/usr/bin/env bash +export GIT_CONFIG_GLOBAL=/dev/null + +eval "$(devenv direnvrc)" + +# You can pass flags to the devenv command +# For example: use devenv --impure --option services.postgres.enable:bool true +use devenv diff --git a/.gitignore b/.gitignore index 4ea24c4..3d55041 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,19 @@ config.yaml # Protobuf generated Go code — committed for reproducible builds # Regenerate with: buf generate # gen/ + +# Devenv +.devenv* +devenv.local.nix +devenv.local.yaml + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml + + +# Added by cargo + +/target diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 3c650e1..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "beetfs"] - path = beetfs - url = git@github.com:LichHunter/beetfs.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fb5f9a2..25eaebc 120000 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1 +1 @@ -/nix/store/mchzk3cbvp456fd3nbajm120nrry3pls-pre-commit-config.json \ No newline at end of file +/nix/store/gd69vhx5mbadafs4bwhh66b5mnp3wvyg-pre-commit-config.json \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..fa5925f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,982 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "axum" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +dependencies = [ + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "bytes" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "num-traits", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "h2" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "http" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "music-agregator" +version = "0.1.0" +dependencies = [ + "bytes", + "pbjson", + "pbjson-types", + "prost", + "serde", + "tokio", + "tonic", + "tonic-prost", + "tonic-reflection", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pbjson" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "898bac3fa00d0ba57a4e8289837e965baa2dee8c3749f3b11d45a64b4223d9c3" +dependencies = [ + "base64", + "serde", +] + +[[package]] +name = "pbjson-build" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af22d08a625a2213a78dbb0ffa253318c5c79ce3133d32d296655a7bdfb02095" +dependencies = [ + "heck", + "itertools", + "prost", + "prost-types", +] + +[[package]] +name = "pbjson-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e748e28374f10a330ee3bb9f29b828c0ac79831a32bab65015ad9b661ead526" +dependencies = [ + "bytes", + "chrono", + "pbjson", + "pbjson-build", + "prost", + "prost-build", + "serde", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", +] + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" +dependencies = [ + "heck", + "itertools", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" +dependencies = [ + "prost", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "socket2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "tokio" +version = "1.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" +dependencies = [ + "async-trait", + "axum", + "base64", + "bytes", + "flate2", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "socket2", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-prost" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" +dependencies = [ + "bytes", + "prost", + "tonic", +] + +[[package]] +name = "tonic-reflection" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acccd136a4bf19810a1fde9c74edc6129b42a66b44d0c1c8aaa67aeb49a146a7" +dependencies = [ + "prost", + "prost-types", + "tokio", + "tokio-stream", + "tonic", + "tonic-prost", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..88d9e91 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "music-agregator" +version = "0.1.0" +edition = "2024" + +[features] +default = ["proto_full", "serde"] +serde = ["dep:serde"] +# @@protoc_deletion_point(features) +# This section is automatically generated by protoc-gen-prost-crate. +# Changes in this area may be lost on regeneration. +proto_full = ["musicfs"] +"musicfs" = [] +# @@protoc_insertion_point(features) + +[dependencies] +bytes = "1.11.1" +prost = "0.14.1" +pbjson = "0.8.0" +pbjson-types = "0.8.0" +serde = { version = "1.0.228", optional = true } +tonic = { version = "0.14.2", features = ["gzip"] } +tonic-prost = "0.14.2" +tokio = { version = "1.52.3", features = [ "macros", "rt-multi-thread" ] } +tonic-reflection = "0.14.6" + +[workspace] diff --git a/api/Analyze Album.bru b/api/Analyze Album.bru deleted file mode 100644 index a1eed1c..0000000 --- a/api/Analyze Album.bru +++ /dev/null @@ -1,22 +0,0 @@ -meta { - name: Analyze Album - type: grpc - seq: 10 -} - -grpc { - url: localhost:3000 - method: /music_agregator.v1.MusicAgregatorService/AnalyzeAlbumRelease - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "album_id": "1d51e4a7-1a8b-4160-bd08-1aee658a991a" - } - ''' -} diff --git a/api/Get Album.bru b/api/Get Album.bru deleted file mode 100644 index f26370e..0000000 --- a/api/Get Album.bru +++ /dev/null @@ -1,22 +0,0 @@ -meta { - name: Get Album - type: grpc - seq: 9 -} - -grpc { - url: localhost:3000 - method: /music_agregator.v1.MusicAgregatorService/GetAlbum - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "album_id": "1d51e4a7-1a8b-4160-bd08-1aee658a991a" - } - ''' -} diff --git a/api/Get Artist Albums.bru b/api/Get Artist Albums.bru deleted file mode 100644 index e3a305b..0000000 --- a/api/Get Artist Albums.bru +++ /dev/null @@ -1,22 +0,0 @@ -meta { - name: Get Artist Albums - type: grpc - seq: 11 -} - -grpc { - url: localhost:3000 - method: /music_agregator.v1.MusicAgregatorService/GetArtistAlbums - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "artist_id": "3b497c6b-e676-4242-bcad-0a03125faaaa" - } - ''' -} diff --git a/api/Get Artists.bru b/api/Get Artists.bru deleted file mode 100644 index 6b275aa..0000000 --- a/api/Get Artists.bru +++ /dev/null @@ -1,20 +0,0 @@ -meta { - name: Get Artists - type: grpc - seq: 7 -} - -grpc { - url: localhost:3000 - method: /music_agregator.v1.MusicAgregatorService/GetArtists - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - {} - ''' -} diff --git a/api/Hello Echo.bru b/api/Hello Echo.bru deleted file mode 100644 index 30c4f2c..0000000 --- a/api/Hello Echo.bru +++ /dev/null @@ -1,23 +0,0 @@ -meta { - name: Hello Echo - type: grpc - seq: 3 -} - -grpc { - url: localhost:3000 - method: /music_agregator.hello.v1.HelloService/Echo - body: grpc - protoPath: ../proto/music_agregator/hello/v1/service.proto - auth: none - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "msg": "hello" - } - ''' -} diff --git a/api/Hello Ping.bru b/api/Hello Ping.bru deleted file mode 100644 index cd050ee..0000000 --- a/api/Hello Ping.bru +++ /dev/null @@ -1,21 +0,0 @@ -meta { - name: Hello Ping - type: grpc - seq: 1 -} - -grpc { - url: localhost:8081 - method: /music_agregator.hello.v1.HelloService/Ping - body: grpc - protoPath: ../proto/music_agregator/hello/v1/service.proto - auth: none - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - {} - ''' -} diff --git a/api/Indexer/Capabilities.bru b/api/Indexer/Capabilities.bru deleted file mode 100644 index 89fb2fa..0000000 --- a/api/Indexer/Capabilities.bru +++ /dev/null @@ -1,24 +0,0 @@ -meta { - name: Capabilities - type: grpc - seq: 1 -} - -grpc { - url: localhost:3000 - method: /music_agregator.indexer.v1.IndexerService/Capabilities - body: grpc - protoPath: ../proto/music_agregator/indexer/v1/indexer.proto - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "indexer": "rutracker" - - } - ''' -} diff --git a/api/Indexer/Search.bru b/api/Indexer/Search.bru deleted file mode 100644 index 3f0e1f9..0000000 --- a/api/Indexer/Search.bru +++ /dev/null @@ -1,25 +0,0 @@ -meta { - name: Search - type: grpc - seq: 2 -} - -grpc { - url: localhost:3000 - method: /music_agregator.indexer.v1.IndexerService/Search - body: grpc - protoPath: ../proto/music_agregator/indexer/v1/indexer.proto - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "tracker": "", - "query": "Metallica", - "limit": 1 - } - ''' -} diff --git a/api/Indexer/folder.bru b/api/Indexer/folder.bru deleted file mode 100644 index 059f94d..0000000 --- a/api/Indexer/folder.bru +++ /dev/null @@ -1,8 +0,0 @@ -meta { - name: Indexer - seq: 7 -} - -auth { - mode: inherit -} diff --git a/api/Jackett/Capabilities.bru b/api/Jackett/Capabilities.bru deleted file mode 100644 index 9f62643..0000000 --- a/api/Jackett/Capabilities.bru +++ /dev/null @@ -1,20 +0,0 @@ -meta { - name: Capabilities - type: http - seq: 2 -} - -get { - url: http://localhost:9117/api/v2.0/indexers/rutracker/results/torznab/api?apikey=3jfvdvt1etzz36drkw5id5sb95sc47fi&t=caps - body: none - auth: inherit -} - -params:query { - apikey: 3jfvdvt1etzz36drkw5id5sb95sc47fi - t: caps -} - -settings { - encodeUrl: true -} diff --git a/api/Jackett/Search.bru b/api/Jackett/Search.bru deleted file mode 100644 index 4772a76..0000000 --- a/api/Jackett/Search.bru +++ /dev/null @@ -1,23 +0,0 @@ -meta { - name: Search - type: http - seq: 1 -} - -get { - url: http://localhost:9117/api/v2.0/indexers/all/results/torznab?apikey=3jfvdvt1etzz36drkw5id5sb95sc47fi&limit=2&q=Metallica&t=search - body: none - auth: inherit -} - -params:query { - apikey: 3jfvdvt1etzz36drkw5id5sb95sc47fi - limit: 2 - q: Metallica - t: search -} - -settings { - encodeUrl: true - timeout: 0 -} diff --git a/api/Jackett/folder.bru b/api/Jackett/folder.bru deleted file mode 100644 index 8f1a658..0000000 --- a/api/Jackett/folder.bru +++ /dev/null @@ -1,8 +0,0 @@ -meta { - name: Jackett - seq: 5 -} - -auth { - mode: inherit -} diff --git a/api/Metadata Agregator/Get Album.bru b/api/Metadata Agregator/Get Album.bru deleted file mode 100644 index 0fb0625..0000000 --- a/api/Metadata Agregator/Get Album.bru +++ /dev/null @@ -1,22 +0,0 @@ -meta { - name: Get Album - type: grpc - seq: 4 -} - -grpc { - url: localhost:3000 - method: /metadata.v1.MetadataService/GetAlbum - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "id": "a0b7b436-94db-4df6-8c5f-bc0e5932a90e" - } - ''' -} diff --git a/api/Metadata Agregator/Get Artist Albums.bru b/api/Metadata Agregator/Get Artist Albums.bru deleted file mode 100644 index 7c9674b..0000000 --- a/api/Metadata Agregator/Get Artist Albums.bru +++ /dev/null @@ -1,22 +0,0 @@ -meta { - name: Get Artist Albums - type: grpc - seq: 3 -} - -grpc { - url: localhost:3000 - method: /metadata.v1.MetadataService/GetArtistAlbums - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "artist_id": "65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab" - } - ''' -} diff --git a/api/Metadata Agregator/Get Artist.bru b/api/Metadata Agregator/Get Artist.bru deleted file mode 100644 index add9880..0000000 --- a/api/Metadata Agregator/Get Artist.bru +++ /dev/null @@ -1,22 +0,0 @@ -meta { - name: Get Artist - type: grpc - seq: 2 -} - -grpc { - url: localhost:3000 - method: /metadata.v1.MetadataService/GetArtist - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "id": "65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab" - } - ''' -} diff --git a/api/Metadata Agregator/Search Albums.bru b/api/Metadata Agregator/Search Albums.bru deleted file mode 100644 index 1290c77..0000000 --- a/api/Metadata Agregator/Search Albums.bru +++ /dev/null @@ -1,30 +0,0 @@ -meta { - name: Search Albums - type: grpc - seq: 5 -} - -grpc { - url: localhost:3000 - method: /metadata.v1.MetadataService/SearchAlbums - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "query": "desidero", - "artist": "corrigo", - "limit": 770, - "offset": 396, - "provider": 0, - "album_types": [ - "spiculum", - "spiculum" - ] - } - ''' -} diff --git a/api/Metadata Agregator/Search Artists.bru b/api/Metadata Agregator/Search Artists.bru deleted file mode 100644 index 26cf468..0000000 --- a/api/Metadata Agregator/Search Artists.bru +++ /dev/null @@ -1,22 +0,0 @@ -meta { - name: Search Artists - type: grpc - seq: 1 -} - -grpc { - url: localhost:3000 - method: /metadata.v1.MetadataService/SearchArtists - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "query": "Metallica" - } - ''' -} diff --git a/api/Metadata Agregator/folder.bru b/api/Metadata Agregator/folder.bru deleted file mode 100644 index 746a658..0000000 --- a/api/Metadata Agregator/folder.bru +++ /dev/null @@ -1,8 +0,0 @@ -meta { - name: Metadata Agregator - seq: 6 -} - -auth { - mode: inherit -} diff --git a/api/Monitor Album.bru b/api/Monitor Album.bru deleted file mode 100644 index 7d63470..0000000 --- a/api/Monitor Album.bru +++ /dev/null @@ -1,26 +0,0 @@ -meta { - name: Monitor Album - type: grpc - seq: 5 -} - -grpc { - url: localhost:3000 - method: /music_agregator.v1.MusicAgregatorService/MonitorAlbum - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "album_id": "a0b7b436-94db-4df6-8c5f-bc0e5932a90e", - "indexer_options": { - "tracker": "" - }, - "quality_type": 1 - } - ''' -} diff --git a/api/SearchArtists.bru b/api/SearchArtists.bru deleted file mode 100644 index a190840..0000000 --- a/api/SearchArtists.bru +++ /dev/null @@ -1,22 +0,0 @@ -meta { - name: SearchArtists - type: grpc - seq: 10 -} - -grpc { - url: localhost:3000 - method: /music_agregator.v1.MusicAgregatorService/SearchArtists - body: grpc - auth: inherit - methodType: unary -} - -body:grpc { - name: message 1 - content: ''' - { - "query": "metal" - } - ''' -} diff --git a/api/bruno.json b/api/bruno.json deleted file mode 100644 index 72756d2..0000000 --- a/api/bruno.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "version": "1", - "name": "Music Agregator", - "type": "collection", - "protobuf": { - "importPaths": [ - { - "path": "../proto", - "enabled": true - } - ], - "protoFiles": [ - { - "path": "../proto/music_agregator/hello/v1/service.proto", - "type": "file" - }, - { - "path": "../proto/music_agregator/indexer/v1/indexer.proto", - "type": "file" - } - ] - }, - "presets": { - "requestType": "grpc", - "requestUrl": "" - } -} \ No newline at end of file diff --git a/api/collection.bru b/api/collection.bru deleted file mode 100644 index e69de29..0000000 diff --git a/buf.gen.yaml b/buf.gen.yaml index 328095c..a4745d0 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -2,11 +2,30 @@ version: v2 inputs: - directory: proto - directory: ../metadata-agregator/proto - - directory: ../musicfs/crates/musicfs-grpc/proto + - directory: ../musicfs/proto plugins: - - local: protoc-gen-go - out: gen - opt: paths=source_relative - - local: protoc-gen-go-grpc - out: gen - opt: paths=source_relative + - local: protoc-gen-prost + #path: ../../target/debug/protoc-gen-prost + out: src/generated + opt: +# - bytes=. + - compile_well_known_types + - extern_path=.google.protobuf=::pbjson_types + - file_descriptor_set + - enable_type_names + - local: protoc-gen-prost-serde + #path: ../../target/debug/protoc-gen-prost-serde + out: src/generated + - local: protoc-gen-tonic + #path: ../../target/debug/protoc-gen-tonic + out: src/generated + opt: + - compile_well_known_types + - extern_path=.google.protobuf=::pbjson_types + - local: protoc-gen-prost-crate + #path: ../../target/debug/protoc-gen-prost-crate + out: . + strategy: all + opt: + - include_file=src/generated/mod.rs + - gen_crate diff --git a/cmd/music-agregator/main.go b/cmd/music-agregator/main.go deleted file mode 100644 index a64dde3..0000000 --- a/cmd/music-agregator/main.go +++ /dev/null @@ -1,268 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "net" - "net/http" - "os" - - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery" - "github.com/jackc/pgx/v5" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/riverqueue/river" - "github.com/riverqueue/river/riverdriver/riverpgxv5" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/reflection" - "google.golang.org/grpc/status" - "gopkg.in/yaml.v2" - - grpcprom "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus" - - "homelab.lan/music-agregator/internal" - "homelab.lan/music-agregator/internal/analysis" - "homelab.lan/music-agregator/internal/config" - "homelab.lan/music-agregator/internal/database" - "homelab.lan/music-agregator/internal/eventbus" - "homelab.lan/music-agregator/internal/hello" - "homelab.lan/music-agregator/internal/indexer" - "homelab.lan/music-agregator/internal/metadata" - "homelab.lan/music-agregator/internal/musicfs" - "homelab.lan/music-agregator/internal/torrent" - "homelab.lan/music-agregator/internal/workers" -) - -func main() { - log.Logger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr}). - With().Timestamp().Logger() - - configPath := flag.String("config", "", "Path to the config file") - flag.Parse() - - cfg, err := parseConfig(configPath) - if err != nil { - log.Fatal().Err(err).Msg("Failed to load config") - } - log.Info().Interface("config", cfg).Msg("Loaded config") - - serveGrpc(*cfg) -} - -func interceptorLogger(l zerolog.Logger) logging.Logger { - return logging.LoggerFunc(func(ctx context.Context, lvl logging.Level, msg string, fields ...any) { - l := l.With().Fields(fields).Logger() - switch lvl { - case logging.LevelDebug: - l.Debug().Msg(msg) - case logging.LevelInfo: - l.Info().Msg(msg) - case logging.LevelWarn: - l.Warn().Msg(msg) - case logging.LevelError: - l.Error().Msg(msg) - default: - l.Info().Msg(msg) - } - }) -} - -func setupDatabase(ctx context.Context, cfg config.Config) *database.DB { - db, err := database.New(ctx, cfg.Database.URL) - if err != nil { - log.Fatal().Err(err).Msg("failed to connect to database") - } - return db -} - -type riverSetup struct { - client *river.Client[pgx.Tx] - cacheRefreshWorker *indexer.CacheRefreshWorker -} - -func setupRiver(ctx context.Context, cfg config.Config, db *database.DB, torrentClient torrent.TorrentClient, pathMapper *torrent.PathMapper, musicfsClient *musicfs.Client, metadataService *metadata.MetadataService, bus *eventbus.EventBus) *riverSetup { - cacheWorker := &indexer.CacheRefreshWorker{} - pollWorker := &workers.PollDownloadWorker{ - Downloads: database.NewDownloadRepository(db.Pool), - DownloadFiles: database.NewDownloadFileRepository(db.Pool), - AlbumReleases: database.NewAlbumReleaseRepository(db.Pool), - TrackReleases: database.NewTrackReleaseRepository(db.Pool), - TorrentClient: torrentClient, - PathMapper: pathMapper, - Analyzer: analysis.NewReleaseAnalyzer(db), - MusicFSClient: musicfsClient, - MusicFSOriginID: cfg.MusicFS.OriginID, - MusicFSOriginRoot: cfg.MusicFS.OriginRoot, - MetadataService: metadataService, - EventBus: bus, - AlbumEvents: database.NewAlbumEventRepository(db.Pool), - } - - riverWorkers := river.NewWorkers() - river.AddWorker(riverWorkers, cacheWorker) - river.AddWorker(riverWorkers, pollWorker) - - riverClient, err := river.NewClient(riverpgxv5.New(db.Pool), &river.Config{ - Queues: map[string]river.QueueConfig{ - river.QueueDefault: {MaxWorkers: 4}, - }, - Workers: riverWorkers, - }) - if err != nil { - log.Fatal().Err(err).Msg("failed to create River client") - } - - cacheWorker.RiverClient = riverClient - pollWorker.RiverClient = riverClient - - if err := riverClient.Start(ctx); err != nil { - log.Fatal().Err(err).Msg("failed to start River client") - } - - log.Info().Msg("River queue started") - - pollWorker.RecoverOrphanedDownloads(ctx) - - return &riverSetup{ - client: riverClient, - cacheRefreshWorker: cacheWorker, - } -} - -func serveGrpc(config config.Config) { - srvMetrics := grpcprom.NewServerMetrics( - grpcprom.WithServerHandlingTimeHistogram( - grpcprom.WithHistogramBuckets([]float64{0.001, 0.01, 0.1, 0.3, 0.6, 1, 3, 6, 10, 30}), - ), - ) - - logOpts := []logging.Option{ - logging.WithLogOnEvents(logging.StartCall, logging.FinishCall), - } - - recoveryOpts := []recovery.Option{ - recovery.WithRecoveryHandler(func(p any) (err error) { - log.Error().Interface("panic", p).Msg("recovered from panic") - return status.Errorf(codes.Internal, "internal error") - }), - } - - server := grpc.NewServer( - grpc.ChainUnaryInterceptor( - srvMetrics.UnaryServerInterceptor(), - logging.UnaryServerInterceptor(interceptorLogger(log.Logger), logOpts...), - recovery.UnaryServerInterceptor(recoveryOpts...), - ), - grpc.ChainStreamInterceptor( - srvMetrics.StreamServerInterceptor(), - logging.StreamServerInterceptor(interceptorLogger(log.Logger), logOpts...), - recovery.StreamServerInterceptor(recoveryOpts...), - ), - ) - - ctx := context.Background() - db := setupDatabase(ctx, config) - defer db.Close() - - torrentClient, err := torrent.NewTorrentClient(config) - if err != nil { - log.Fatal().Err(err).Msg("failed to create torrent client") - } - - pathMapper, err := torrent.NewPathMapper(config.Torrent.ContainerName, torrentClient) - if err != nil { - log.Fatal().Err(err).Msg("failed to create path mapper") - } - - var musicfsClient *musicfs.Client - if config.MusicFS.Enabled { - client, conn, err := musicfs.NewClient(config.MusicFS.Endpoint) - if err != nil { - log.Warn().Err(err).Msg("failed to connect to musicfs, continuing without it") - } else { - musicfsClient = client - defer conn.Close() - } - } - - metadataClient, metadataConn, err := metadata.NewMetadataClient(config.Metadata.Endpoint) - if err != nil { - log.Fatal().Err(err).Msg("failed to connect to metadata service") - } - defer metadataConn.Close() - metadataService := metadata.NewMetadataService(metadataClient, db) - - bus := eventbus.New() - - rs := setupRiver(ctx, config, db, torrentClient, pathMapper, musicfsClient, metadataService, bus) - - musiscAgregatorSeerver, err := internal.NewMusicAgregatorServer(config, rs.client, torrentClient, pathMapper, db, bus, musicfsClient) - if err != nil { - log.Fatal().Err(err).Msg("failed to create MusicAgregatorServer") - } - indexerServer, err := indexer.NewIndexerServer(config, rs.client, rs.cacheRefreshWorker) - if err != nil { - log.Fatal().Err(err).Msg("failed to create IndexerServer") - } - torrentServer := torrent.NewTorrentServer(torrentClient) - metadataServer, err := metadata.NewMetadataServer(config) - if err != nil { - log.Fatal().Err(err).Msg("failed to create MetadataServer") - } - - services := []internal.Registrable{ - hello.NewHelloServer(), - indexerServer, - torrentServer, - metadataServer, - musiscAgregatorSeerver, - } - - for _, service := range services { - service.Register(server) - } - - srvMetrics.InitializeMetrics(server) - prometheus.MustRegister(srvMetrics) - reflection.Register(server) - - go func() { - mux := http.NewServeMux() - mux.Handle("/metrics", promhttp.Handler()) - log.Info().Msg("Prometheus metrics available at :9090/metrics") - if err := http.ListenAndServe(":9090", mux); err != nil { - log.Fatal().Err(err).Msg("Failed to start metrics server") - } - }() - - listener, err := net.Listen("tcp", fmt.Sprintf("%v:%v", config.App.Host, config.App.Port)) - if err != nil { - log.Fatal().Err(err).Msg("Failed to listen") - } - - log.Info().Str("addr", listener.Addr().String()).Msg("gRPC server listening") - server.Serve(listener) -} - -func parseConfig(path *string) (*config.Config, error) { - f, err := os.Open(*path) - if err != nil { - log.Error().Str("path", *path).Msg("Unable to opent config by path") - return nil, err - } - defer f.Close() - - cfg := config.NewConfig() - decoder := yaml.NewDecoder(f) - err = decoder.Decode(&cfg) - if err != nil { - // processError(err) - } - - return cfg, nil -} diff --git a/config.example.yaml b/config.example.yaml deleted file mode 100644 index 37fba6f..0000000 --- a/config.example.yaml +++ /dev/null @@ -1,31 +0,0 @@ -app: - port: 3000 - -database: - url: "postgresql://music:music@localhost:5433/music_aggregator" - -metadata: - endpoint: "http://localhost:50051" - -indexer: - name: "Jackett" - indexer_type: jackett # jackett, prowlarr, or torznab - url: "http://localhost:9117" - api_key: "your-jackett-api-key" - -# Torrent client - choose one of: qbittorrent, stub, none -torrent: - client_type: qbittorrent - url: "http://localhost:8080" - username: "admin" - password: "changeme" - -# Alternative: stub client for testing -# torrent: -# client_type: stub -# log_path: "/tmp/torrent-stub.log" -# save_path: "/tmp/downloads" - -# Alternative: no torrent client -# torrent: -# client_type: none diff --git a/config.test.yaml b/config.test.yaml deleted file mode 100644 index f34e796..0000000 --- a/config.test.yaml +++ /dev/null @@ -1,22 +0,0 @@ -app: - port: 3000 - -database: - url: "postgresql://music:music@localhost:5433/music_aggregator" - -metadata: - endpoint: "http://localhost:50051" - -indexers: - - name: "Jackett" - indexer_type: jackett - url: "http://localhost:9117" - api_key: "apmtthy50kiu47wth8i1we22k5sn8ut6" - -torrent: - client_type: stub - save_path: "/tmp/music-downloads" - log_path: "/tmp/torrent-stub.log" - -storage: - base_path: "/tmp/music-library-test" diff --git a/containers/database/music-agregator/002_schema.sql b/containers/database/music-agregator/002_schema.sql deleted file mode 100644 index fd09b65..0000000 --- a/containers/database/music-agregator/002_schema.sql +++ /dev/null @@ -1,112 +0,0 @@ -CREATE TYPE monitor_state AS ENUM ('unmonitored', 'monitored', 'excluded'); -CREATE TYPE download_state AS ENUM ('pending', 'downloading', 'completed', 'failed', 'seeding'); - -CREATE TABLE artists ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - external_id VARCHAR(255) NOT NULL UNIQUE, - name VARCHAR(255) NOT NULL, - artist_type VARCHAR(50) NOT NULL, - country VARCHAR(10), - genres TEXT[] NOT NULL DEFAULT '{}', - image_url TEXT, - monitor_state monitor_state NOT NULL DEFAULT 'unmonitored', - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_artists_monitor_state ON artists(monitor_state); - -CREATE TABLE albums ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - external_id VARCHAR(255) NOT NULL UNIQUE, - artist_id UUID NOT NULL REFERENCES artists(id) ON DELETE CASCADE, - title VARCHAR(255) NOT NULL, - album_type VARCHAR(50) NOT NULL, - release_date DATE, - total_tracks INTEGER NOT NULL DEFAULT 0, - total_discs INTEGER NOT NULL DEFAULT 1, - label VARCHAR(255), - genres TEXT[] NOT NULL DEFAULT '{}', - cover_url TEXT, - monitor_state monitor_state NOT NULL DEFAULT 'unmonitored', - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_albums_artist_id ON albums(artist_id); -CREATE INDEX idx_albums_monitor_state ON albums(monitor_state); - -CREATE TABLE tracks ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - external_id VARCHAR(255) NOT NULL UNIQUE, - album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE, - title VARCHAR(255) NOT NULL, - duration_ms INTEGER NOT NULL DEFAULT 0, - isrc VARCHAR(20), - disc_number INTEGER NOT NULL DEFAULT 1, - track_number INTEGER NOT NULL DEFAULT 1, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_tracks_album_id ON tracks(album_id); - -CREATE TABLE torrents ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE, - info_hash VARCHAR(64) NOT NULL UNIQUE, - tracker VARCHAR(100) NOT NULL, - title TEXT NOT NULL, - format VARCHAR(20) NOT NULL, - quality VARCHAR(20) NOT NULL, - source VARCHAR(50), - bit_depth INTEGER, - sample_rate INTEGER, - seeders INTEGER NOT NULL DEFAULT 0, - peers INTEGER NOT NULL DEFAULT 0, - size BIGINT NOT NULL DEFAULT 0, - track_count INTEGER NOT NULL DEFAULT 0, - has_cover_art BOOLEAN NOT NULL DEFAULT false, - has_cue_sheet BOOLEAN NOT NULL DEFAULT false, - has_rip_log BOOLEAN NOT NULL DEFAULT false, - download_link TEXT, - torrent_file BYTEA, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_torrents_album_id ON torrents(album_id); - -CREATE TABLE downloads ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - torrent_id UUID NOT NULL REFERENCES torrents(id) ON DELETE CASCADE, - album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE, - format VARCHAR(20) NOT NULL, - quality VARCHAR(20) NOT NULL, - state download_state NOT NULL DEFAULT 'pending', - qbit_hash VARCHAR(64), - save_path TEXT, - error_message TEXT, - queued_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - started_at TIMESTAMPTZ, - completed_at TIMESTAMPTZ, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_downloads_album_id ON downloads(album_id); -CREATE INDEX idx_downloads_torrent_id ON downloads(torrent_id); -CREATE INDEX idx_downloads_state ON downloads(state); - -CREATE TABLE download_files ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - download_id UUID NOT NULL REFERENCES downloads(id) ON DELETE CASCADE, - track_id UUID REFERENCES tracks(id) ON DELETE SET NULL, - file_path TEXT NOT NULL, - file_size BIGINT NOT NULL DEFAULT 0, - file_type VARCHAR(50) NOT NULL, - sha256_hash VARCHAR(64), - verified_at TIMESTAMPTZ, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_download_files_download_id ON download_files(download_id); diff --git a/containers/database/music-agregator/003_event_bus.sql b/containers/database/music-agregator/003_event_bus.sql deleted file mode 100644 index 6e8ec7c..0000000 --- a/containers/database/music-agregator/003_event_bus.sql +++ /dev/null @@ -1,33 +0,0 @@ -CREATE TABLE workflow_runs ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE, - quality VARCHAR(20) NOT NULL, - status VARCHAR(20) NOT NULL DEFAULT 'running', - error_message TEXT, - started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - completed_at TIMESTAMPTZ, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - running_lock BOOLEAN GENERATED ALWAYS AS (CASE WHEN status = 'running' THEN TRUE ELSE NULL END) STORED, - CONSTRAINT idx_workflow_runs_active UNIQUE (album_id, quality, running_lock) -); - -CREATE INDEX idx_workflow_runs_status ON workflow_runs(status); - -CREATE TABLE album_events ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - seq BIGSERIAL NOT NULL, - workflow_run_id UUID NOT NULL REFERENCES workflow_runs(id) ON DELETE CASCADE, - album_id UUID NOT NULL, - event_type VARCHAR(20) NOT NULL, - step VARCHAR(50) NOT NULL, - message TEXT NOT NULL, - data_json JSONB, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_album_events_workflow ON album_events(workflow_run_id); -CREATE INDEX idx_album_events_album ON album_events(album_id); -CREATE INDEX idx_album_events_seq ON album_events(seq); - -ALTER TYPE download_state ADD VALUE IF NOT EXISTS 'cancelled'; diff --git a/containers/docker-compose.yml b/containers/docker-compose.yml deleted file mode 100644 index c53d2c4..0000000 --- a/containers/docker-compose.yml +++ /dev/null @@ -1,63 +0,0 @@ -services: - jackett: - image: lscr.io/linuxserver/jackett:latest - container_name: music-aggregator-jackett - restart: unless-stopped - environment: - - PUID=1000 - - PGID=1000 - - TZ=Europe/Warsaw - - AUTO_UPDATE=true - volumes: - - jackett_config:/config - - jackett_downloads:/downloads - ports: - - "9117:9117" - - gluetun: - image: qmcgaw/gluetun:latest - container_name: music-aggregator-vpn - restart: unless-stopped - cap_add: - - NET_ADMIN - devices: - - /dev/net/tun:/dev/net/tun - environment: - - VPN_SERVICE_PROVIDER=custom - - VPN_TYPE=wireguard - - TZ=Europe/Warsaw - volumes: - - ./wg.conf:/gluetun/wireguard/wg0.conf:ro - ports: - - "8080:8080" - - "6881:6881" - - "6881:6881/udp" - healthcheck: - test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost:9999"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 15s - - qbittorrent: - image: lscr.io/linuxserver/qbittorrent:latest - container_name: music-aggregator-qbittorrent - restart: unless-stopped - network_mode: "service:gluetun" - depends_on: - gluetun: - condition: service_healthy - environment: - - PUID=1000 - - PGID=1000 - - TZ=Europe/Warsaw - - WEBUI_PORT=8080 - volumes: - - qbittorrent_config:/config - - downloads:/downloads - -volumes: - jackett_config: - jackett_downloads: - qbittorrent_config: - downloads: diff --git a/devenv.lock b/devenv.lock new file mode 100644 index 0000000..9531f4e --- /dev/null +++ b/devenv.lock @@ -0,0 +1,124 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1782920231, + "narHash": "sha256-hE3aMd68LTOfoG+wxZFLi2LXp6xaDsxLLeluuNpQPLE=", + "owner": "cachix", + "repo": "devenv", + "rev": "9c262553e2d71f3b6c60b24405bd8567f28f384c", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "NixOS", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "flake-compat", + "type": "github" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1782908218, + "narHash": "sha256-wLMOrPgVyeF3XmP+qfYcLqnVdTxikdcSvbIY7rA9jTA=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "9f7e99119ece7705299595299f3b031f39356de1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "nixpkgs": { + "inputs": { + "nixpkgs-src": "nixpkgs-src" + }, + "locked": { + "lastModified": 1782924808, + "narHash": "sha256-tn2ahNv3ZNXyVHdPx/uw+N0xa7YSMtXUr6OEvu+s8ng=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "e2c881cb8d5f1cac6cef9d71f0d450a55691b999", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs-src": { + "flake": false, + "locked": { + "lastModified": 1782636521, + "narHash": "sha256-OG8laCOGtkxlB1JH3XqOnXxnkGJme4mQdXo5hkhCQIY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e1c1b84752fb0897897380a3cae9dc7fcab91ca3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "git-hooks": "git-hooks", + "nixpkgs": "nixpkgs", + "treefmt-nix": "treefmt-nix" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1780220602, + "narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "db947814a175b7ca6ded66e21383d938df01c227", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} \ No newline at end of file diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 0000000..8b672f4 --- /dev/null +++ b/devenv.nix @@ -0,0 +1,43 @@ +{ + pkgs, + lib, + config, + inputs, + ... +}: + +{ + languages.rust.enable = true; + + git-hooks.hooks = { + clippy = { + enable = true; + settings.allFeatures = true; + }; + treefmt.enable = true; + }; + + treefmt = { + enable = true; + config.programs = { + nixfmt.enable = true; + rustfmt.enable = true; + }; + }; + + packages = with pkgs; [ + git + just + protobuf + buf + grpcurl + + # Protobuf generators + protoc-gen-prost-crate + protoc-gen-prost-serde + protoc-gen-tonic + protoc-gen-prost + + opencode + ]; +} diff --git a/devenv.yaml b/devenv.yaml new file mode 100644 index 0000000..ee5a179 --- /dev/null +++ b/devenv.yaml @@ -0,0 +1,13 @@ +inputs: + git-hooks: + url: github:cachix/git-hooks.nix + inputs: + nixpkgs: + follows: nixpkgs + nixpkgs: + url: github:cachix/devenv-nixpkgs/rolling + treefmt-nix: + url: github:numtide/treefmt-nix + inputs: + nixpkgs: + follows: nixpkgs diff --git a/docs/research/lidarr/erd.puml b/docs/research/lidarr/erd.puml deleted file mode 100644 index e4fd54f..0000000 --- a/docs/research/lidarr/erd.puml +++ /dev/null @@ -1,362 +0,0 @@ -@startuml Lidarr-Style Music Aggregator ERD - -skinparam linetype ortho -skinparam ranksep 60 -skinparam nodesep 40 - -skinparam entity { - BackgroundColor White - BorderColor #333333 -} - -skinparam package { - BackgroundColor #FAFAFA - BorderColor #DDDDDD -} - -title Music Aggregator - Lidarr-Style Database Structure - -' ══════════════════════════════════════════════════════════════ -' CORE MUSIC ENTITIES -' ══════════════════════════════════════════════════════════════ - -package "Core Music Entities" #E3F2FD { - entity "artist_metadata" { - * id : UUID <> - -- - foreign_artist_id : TEXT <> - name : TEXT - sort_name : TEXT - disambiguation : TEXT - artist_type : TEXT - status : TEXT - overview : TEXT - images : JSONB - links : JSONB - genres : JSONB - ratings : JSONB - members : JSONB - -- - created_at : TIMESTAMPTZ - updated_at : TIMESTAMPTZ - } - - entity "artists" { - * id : UUID <> - -- - metadata_id : UUID <> - quality_profile_id : UUID <> - metadata_profile_id : UUID <> - root_folder_id : UUID <> - -- - path : TEXT - monitored : BOOLEAN - monitor_new_items : TEXT - -- - last_info_sync : TIMESTAMPTZ - added_at : TIMESTAMPTZ - tags : INT[] - } - - entity "albums" { - * id : UUID <> - -- - artist_metadata_id : UUID <> - -- - foreign_album_id : TEXT <> - title : TEXT - clean_title : TEXT - disambiguation : TEXT - overview : TEXT - album_type : TEXT - secondary_types : JSONB - release_date : DATE - images : JSONB - links : JSONB - genres : JSONB - ratings : JSONB - -- - monitored : BOOLEAN - any_release_ok : BOOLEAN - last_search_time : TIMESTAMPTZ - added_at : TIMESTAMPTZ - } - - entity "album_releases" { - * id : UUID <> - -- - album_id : UUID <> - -- - foreign_release_id : TEXT <> - title : TEXT - disambiguation : TEXT - status : TEXT - duration_ms : INT - release_date : DATE - country : TEXT[] - label : TEXT[] - media : JSONB - track_count : INT - -- - monitored : BOOLEAN - } - - entity "tracks" { - * id : UUID <> - -- - album_release_id : UUID <> - artist_metadata_id : UUID <> - track_file_id : UUID <> - -- - foreign_track_id : TEXT <> - foreign_recording_id : TEXT - title : TEXT - track_number : INT - disc_number : INT - duration_ms : INT - explicit : BOOLEAN - ratings : JSONB - } - - entity "track_files" { - * id : UUID <> - -- - album_id : UUID <> - -- - path : TEXT - relative_path : TEXT - size : BIGINT - quality : JSONB - media_info : JSONB - audio_tags : JSONB - -- - scene_name : TEXT - release_group : TEXT - -- - date_added : TIMESTAMPTZ - modified_at : TIMESTAMPTZ - } -} - -' ══════════════════════════════════════════════════════════════ -' CONFIGURATION -' ══════════════════════════════════════════════════════════════ - -package "Configuration" #FFF3E0 { - entity "quality_profiles" { - * id : UUID <> - -- - name : TEXT <> - cutoff : INT - items : JSONB - upgrade_allowed : BOOLEAN - min_format_score : INT - cutoff_format_score : INT - } - - entity "metadata_profiles" { - * id : UUID <> - -- - name : TEXT <> - primary_album_types : JSONB - secondary_album_types : JSONB - release_statuses : JSONB - } - - entity "root_folders" { - * id : UUID <> - -- - name : TEXT - path : TEXT <> - default_quality_profile_id : UUID <> - default_metadata_profile_id : UUID <> - default_monitor_option : TEXT - default_tags : INT[] - } - - entity "tags" { - * id : SERIAL <> - -- - label : TEXT <> - } - - entity "indexers" { - * id : UUID <> - -- - name : TEXT - implementation : TEXT - settings : JSONB - enable_rss : BOOLEAN - enable_search : BOOLEAN - priority : INT - tags : INT[] - } - - entity "download_clients" { - * id : UUID <> - -- - name : TEXT - implementation : TEXT - settings : JSONB - protocol : TEXT - priority : INT - remove_completed : BOOLEAN - remove_failed : BOOLEAN - tags : INT[] - enabled : BOOLEAN - } -} - -' ══════════════════════════════════════════════════════════════ -' DOWNLOAD TRACKING -' ══════════════════════════════════════════════════════════════ - -package "Download Tracking" #E8F5E9 { - entity "download_queue" { - * id : UUID <> - -- - artist_id : UUID <> - album_id : UUID <> - -- - download_id : TEXT - title : TEXT - size : BIGINT - size_left : BIGINT - time_left : INTERVAL - estimated_completion : TIMESTAMPTZ - -- - status : TEXT - state : TEXT - status_messages : JSONB - -- - protocol : TEXT - indexer : TEXT - download_client : TEXT - output_path : TEXT - download_forced : BOOLEAN - -- - added_at : TIMESTAMPTZ - } - - entity "pending_releases" { - * id : UUID <> - -- - artist_id : UUID <> - album_id : UUID <> - -- - title : TEXT - release : JSONB - parsed_album_info : JSONB - reason : TEXT - additional_info : JSONB - -- - added_at : TIMESTAMPTZ - } - - entity "download_history" { - * id : UUID <> - -- - artist_id : UUID <> - album_id : UUID <> - -- - event_type : TEXT - download_id : TEXT - source_title : TEXT - protocol : TEXT - indexer_id : UUID - download_client_id : UUID - release : JSONB - data : JSONB - -- - date : TIMESTAMPTZ - } - - entity "blocklist" { - * id : UUID <> - -- - artist_id : UUID <> - album_ids : UUID[] - -- - source_title : TEXT - quality : JSONB - size : BIGINT - protocol : TEXT - indexer : TEXT - message : TEXT - torrent_hash : TEXT - -- - published_date : TIMESTAMPTZ - date : TIMESTAMPTZ - } -} - -' ══════════════════════════════════════════════════════════════ -' HISTORY & TRACKING -' ══════════════════════════════════════════════════════════════ - -package "History & Tracking" #FCE4EC { - entity "history" { - * id : UUID <> - -- - artist_id : UUID <> - album_id : UUID <> - track_id : UUID <> - -- - event_type : TEXT - source_title : TEXT - quality : JSONB - download_id : TEXT - data : JSONB - -- - date : TIMESTAMPTZ - } - - entity "wanted_albums" { - ' View/materialized view for missing albums - * album_id : UUID <> - -- - artist_id : UUID - title : TEXT - release_date : DATE - monitored : BOOLEAN - track_count : INT - track_file_count : INT - } -} - -' ══════════════════════════════════════════════════════════════ -' RELATIONSHIPS -' ══════════════════════════════════════════════════════════════ - -' Core music relationships -artist_metadata ||--|| artists : "has config" -artist_metadata ||--o{ albums : "released" -albums ||--o{ album_releases : "has releases" -album_releases ||--o{ tracks : "contains" -tracks }o--o| track_files : "stored in" -track_files }o--|| albums : "belongs to" - -' Artist relationships -artists }o--|| quality_profiles : "uses" -artists }o--o| metadata_profiles : "uses" -artists }o--o| root_folders : "stored in" - -' Configuration relationships -root_folders }o--o| quality_profiles : "default" -root_folders }o--o| metadata_profiles : "default" - -' Download tracking relationships -download_queue }o--o| artists : "for" -download_queue }o--o| albums : "for" -pending_releases }o--|| artists : "for" -pending_releases }o--o| albums : "for" -download_history }o--|| artists : "for" -download_history }o--o| albums : "for" -blocklist }o--|| artists : "for" - -' History relationships -history }o--|| artists : "for" -history }o--o| albums : "for" -history }o--o| tracks : "for" - -@enduml diff --git a/docs/research/lidarr/research_summary.md b/docs/research/lidarr/research_summary.md deleted file mode 100644 index 42a334f..0000000 --- a/docs/research/lidarr/research_summary.md +++ /dev/null @@ -1,93 +0,0 @@ -# Lidarr Database Research Summary - -## Overview - -Lidarr is a music collection manager that uses a **Release-based** system. Key design principles: - -1. **Metadata Separation** - Artist metadata separated from configuration -2. **Release-Centric** - Works with releases, not loose tracks -3. **Monitoring Hierarchy** - Artist → Album → Release (only one release monitored per album) -4. **Quality Profiles** - Separate profiles for quality and metadata preferences -5. **Download Lifecycle** - Pending → Queue → Imported → History/Blocklist - -## Core Entity Hierarchy - -``` -ArtistMetadata (1) ←→ (1) Artist (1) ←→ (N) Albums - ↓ - (N) AlbumReleases (only 1 monitored) - ↓ - (N) Tracks (N) ←→ (1) TrackFile -``` - -## Key Entities - -### Music Entities -- **Artists** - Configuration (path, monitoring, profiles) -- **ArtistMetadata** - Metadata (name, images, genres, members) -- **Albums** - Album info with monitoring and search tracking -- **AlbumReleases** - Physical releases (CD, Vinyl, Digital) - only ONE monitored per album -- **Tracks** - Individual tracks linked to releases -- **TrackFiles** - Actual files on disk with quality info - -### Configuration -- **QualityProfiles** - Acceptable formats and upgrade cutoff -- **MetadataProfiles** - Which album types to include (Studio, EP, Live, etc.) -- **RootFolders** - Storage locations with defaults - -### Download Tracking -- **PendingReleases** - Delayed downloads (waiting for better quality) -- **DownloadHistory** - Download lifecycle events -- **Blocklist** - Failed/rejected releases (prevent re-download) -- **History** - Complete audit trail of all events - -### System -- **Indexers** - Search sources (Newznab/Torznab) -- **DownloadClients** - Torrent/Usenet clients -- **ImportLists** - Auto-import from Spotify, Last.fm, etc. -- **Tags** - Categorization - -## Monitoring States - -### Artist Level -- `monitored` - Is artist being tracked -- `monitor_new_items` - Policy for new releases (All/Future/Missing/Existing/None) - -### Album Level -- `monitored` - Should we look for this album -- `any_release_ok` - Auto-switch releases during import - -### Release Level -- `monitored` - Is this the release we want (exactly ONE per album) - -## Download States - -``` -TrackedDownloadState: - Downloading → ImportPending → Importing → Imported - → Ignored - → DownloadFailed → DownloadFailedPending -``` - -## History Event Types - -- Grabbed - Download started -- TrackFileImported - File imported to library -- DownloadFailed - Download failed -- TrackFileDeleted - File removed -- TrackFileRenamed - File renamed -- TrackFileRetagged - Metadata updated -- AlbumImportIncomplete - Partial import -- DownloadIgnored - Download skipped - -## Sources - -- GitHub: Lidarr/Lidarr -- Key files: - - `src/NzbDrone.Core/Music/Model/Artist.cs` - - `src/NzbDrone.Core/Music/Model/Album.cs` - - `src/NzbDrone.Core/Music/Model/Release.cs` (AlbumRelease) - - `src/NzbDrone.Core/Music/Model/Track.cs` - - `src/NzbDrone.Core/MediaFiles/TrackFile.cs` - - `src/NzbDrone.Core/Datastore/Migration/001_initial_setup.cs` - - `src/NzbDrone.Core/Datastore/Migration/023_add_release_groups_etc.cs` diff --git a/flake.lock b/flake.lock index 62f241f..eafc6f6 100644 --- a/flake.lock +++ b/flake.lock @@ -21,11 +21,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1777988971, - "narHash": "sha256-qIoWPDs+0/8JecyYgE3gpKQxW/4bLW/gp45vow9ioCQ=", + "lastModified": 1778716662, + "narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "0678d8986be1661af6bb555f3489f2fdfc31f6ff", + "rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb", "type": "github" }, "original": { @@ -37,15 +37,14 @@ "git-hooks": { "inputs": { "flake-compat": "flake-compat", - "gitignore": "gitignore", "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1776796298, - "narHash": "sha256-PcRvlWayisPSjd0UcRQbhG8Oqw78AcPE6x872cPRHN8=", + "lastModified": 1782908218, + "narHash": "sha256-wLMOrPgVyeF3XmP+qfYcLqnVdTxikdcSvbIY7rA9jTA=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "3cfd774b0a530725a077e17354fbdb87ea1c4aad", + "rev": "9f7e99119ece7705299595299f3b031f39356de1", "type": "github" }, "original": { @@ -54,27 +53,6 @@ "type": "github" } }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "git-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, "nixpkgs": { "locked": { "lastModified": 1770073757, @@ -108,11 +86,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1778095059, - "narHash": "sha256-LW2nru9+O0oyR3lfzgzFLwTibhINoIL/dx2/1dBMKWU=", + "lastModified": 1782929431, + "narHash": "sha256-Ys6O7G+rrgcvhyuEER7KkFjhAXXHpFCmsBzVaRFYe1s=", "owner": "nixos", "repo": "nixpkgs", - "rev": "94a37dc9da62b41f0c70a91da739bc318d049c11", + "rev": "1b56c1483c5fd996da3180b7f2023ec8d2c8cc0f", "type": "github" }, "original": { diff --git a/gen/metadata/v1/metadata.pb.go b/gen/metadata/v1/metadata.pb.go deleted file mode 100644 index 362148a..0000000 --- a/gen/metadata/v1/metadata.pb.go +++ /dev/null @@ -1,2098 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc (unknown) -// source: metadata/v1/metadata.proto - -package metadatav1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Provider int32 - -const ( - Provider_PROVIDER_UNSPECIFIED Provider = 0 - Provider_PROVIDER_MUSICBRAINZ Provider = 1 -) - -// Enum value maps for Provider. -var ( - Provider_name = map[int32]string{ - 0: "PROVIDER_UNSPECIFIED", - 1: "PROVIDER_MUSICBRAINZ", - } - Provider_value = map[string]int32{ - "PROVIDER_UNSPECIFIED": 0, - "PROVIDER_MUSICBRAINZ": 1, - } -) - -func (x Provider) Enum() *Provider { - p := new(Provider) - *p = x - return p -} - -func (x Provider) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Provider) Descriptor() protoreflect.EnumDescriptor { - return file_metadata_v1_metadata_proto_enumTypes[0].Descriptor() -} - -func (Provider) Type() protoreflect.EnumType { - return &file_metadata_v1_metadata_proto_enumTypes[0] -} - -func (x Provider) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Provider.Descriptor instead. -func (Provider) EnumDescriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{0} -} - -type GetArtistRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Types that are valid to be assigned to Identifier: - // - // *GetArtistRequest_Id - // *GetArtistRequest_External - Identifier isGetArtistRequest_Identifier `protobuf_oneof:"identifier"` - Provider Provider `protobuf:"varint,3,opt,name=provider,proto3,enum=metadata.v1.Provider" json:"provider,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetArtistRequest) Reset() { - *x = GetArtistRequest{} - mi := &file_metadata_v1_metadata_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetArtistRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetArtistRequest) ProtoMessage() {} - -func (x *GetArtistRequest) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetArtistRequest.ProtoReflect.Descriptor instead. -func (*GetArtistRequest) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{0} -} - -func (x *GetArtistRequest) GetIdentifier() isGetArtistRequest_Identifier { - if x != nil { - return x.Identifier - } - return nil -} - -func (x *GetArtistRequest) GetId() string { - if x != nil { - if x, ok := x.Identifier.(*GetArtistRequest_Id); ok { - return x.Id - } - } - return "" -} - -func (x *GetArtistRequest) GetExternal() *ExternalID { - if x != nil { - if x, ok := x.Identifier.(*GetArtistRequest_External); ok { - return x.External - } - } - return nil -} - -func (x *GetArtistRequest) GetProvider() Provider { - if x != nil { - return x.Provider - } - return Provider_PROVIDER_UNSPECIFIED -} - -type isGetArtistRequest_Identifier interface { - isGetArtistRequest_Identifier() -} - -type GetArtistRequest_Id struct { - Id string `protobuf:"bytes,1,opt,name=id,proto3,oneof"` -} - -type GetArtistRequest_External struct { - External *ExternalID `protobuf:"bytes,2,opt,name=external,proto3,oneof"` -} - -func (*GetArtistRequest_Id) isGetArtistRequest_Identifier() {} - -func (*GetArtistRequest_External) isGetArtistRequest_Identifier() {} - -type SearchArtistsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` - Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` - Offset int32 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"` - Provider Provider `protobuf:"varint,4,opt,name=provider,proto3,enum=metadata.v1.Provider" json:"provider,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchArtistsRequest) Reset() { - *x = SearchArtistsRequest{} - mi := &file_metadata_v1_metadata_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchArtistsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchArtistsRequest) ProtoMessage() {} - -func (x *SearchArtistsRequest) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchArtistsRequest.ProtoReflect.Descriptor instead. -func (*SearchArtistsRequest) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{1} -} - -func (x *SearchArtistsRequest) GetQuery() string { - if x != nil { - return x.Query - } - return "" -} - -func (x *SearchArtistsRequest) GetLimit() int32 { - if x != nil { - return x.Limit - } - return 0 -} - -func (x *SearchArtistsRequest) GetOffset() int32 { - if x != nil { - return x.Offset - } - return 0 -} - -func (x *SearchArtistsRequest) GetProvider() Provider { - if x != nil { - return x.Provider - } - return Provider_PROVIDER_UNSPECIFIED -} - -type GetAlbumRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Types that are valid to be assigned to Identifier: - // - // *GetAlbumRequest_Id - // *GetAlbumRequest_External - Identifier isGetAlbumRequest_Identifier `protobuf_oneof:"identifier"` - Provider Provider `protobuf:"varint,3,opt,name=provider,proto3,enum=metadata.v1.Provider" json:"provider,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetAlbumRequest) Reset() { - *x = GetAlbumRequest{} - mi := &file_metadata_v1_metadata_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetAlbumRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAlbumRequest) ProtoMessage() {} - -func (x *GetAlbumRequest) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetAlbumRequest.ProtoReflect.Descriptor instead. -func (*GetAlbumRequest) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{2} -} - -func (x *GetAlbumRequest) GetIdentifier() isGetAlbumRequest_Identifier { - if x != nil { - return x.Identifier - } - return nil -} - -func (x *GetAlbumRequest) GetId() string { - if x != nil { - if x, ok := x.Identifier.(*GetAlbumRequest_Id); ok { - return x.Id - } - } - return "" -} - -func (x *GetAlbumRequest) GetExternal() *ExternalID { - if x != nil { - if x, ok := x.Identifier.(*GetAlbumRequest_External); ok { - return x.External - } - } - return nil -} - -func (x *GetAlbumRequest) GetProvider() Provider { - if x != nil { - return x.Provider - } - return Provider_PROVIDER_UNSPECIFIED -} - -type isGetAlbumRequest_Identifier interface { - isGetAlbumRequest_Identifier() -} - -type GetAlbumRequest_Id struct { - Id string `protobuf:"bytes,1,opt,name=id,proto3,oneof"` -} - -type GetAlbumRequest_External struct { - External *ExternalID `protobuf:"bytes,2,opt,name=external,proto3,oneof"` -} - -func (*GetAlbumRequest_Id) isGetAlbumRequest_Identifier() {} - -func (*GetAlbumRequest_External) isGetAlbumRequest_Identifier() {} - -type GetArtistAlbumsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - ArtistId string `protobuf:"bytes,1,opt,name=artist_id,json=artistId,proto3" json:"artist_id,omitempty"` - Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` - Offset int32 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"` - Provider Provider `protobuf:"varint,4,opt,name=provider,proto3,enum=metadata.v1.Provider" json:"provider,omitempty"` - AlbumTypes []string `protobuf:"bytes,5,rep,name=album_types,json=albumTypes,proto3" json:"album_types,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetArtistAlbumsRequest) Reset() { - *x = GetArtistAlbumsRequest{} - mi := &file_metadata_v1_metadata_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetArtistAlbumsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetArtistAlbumsRequest) ProtoMessage() {} - -func (x *GetArtistAlbumsRequest) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetArtistAlbumsRequest.ProtoReflect.Descriptor instead. -func (*GetArtistAlbumsRequest) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{3} -} - -func (x *GetArtistAlbumsRequest) GetArtistId() string { - if x != nil { - return x.ArtistId - } - return "" -} - -func (x *GetArtistAlbumsRequest) GetLimit() int32 { - if x != nil { - return x.Limit - } - return 0 -} - -func (x *GetArtistAlbumsRequest) GetOffset() int32 { - if x != nil { - return x.Offset - } - return 0 -} - -func (x *GetArtistAlbumsRequest) GetProvider() Provider { - if x != nil { - return x.Provider - } - return Provider_PROVIDER_UNSPECIFIED -} - -func (x *GetArtistAlbumsRequest) GetAlbumTypes() []string { - if x != nil { - return x.AlbumTypes - } - return nil -} - -type GetTrackRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Types that are valid to be assigned to Identifier: - // - // *GetTrackRequest_Id - // *GetTrackRequest_External - // *GetTrackRequest_Isrc - Identifier isGetTrackRequest_Identifier `protobuf_oneof:"identifier"` - Provider Provider `protobuf:"varint,4,opt,name=provider,proto3,enum=metadata.v1.Provider" json:"provider,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetTrackRequest) Reset() { - *x = GetTrackRequest{} - mi := &file_metadata_v1_metadata_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetTrackRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetTrackRequest) ProtoMessage() {} - -func (x *GetTrackRequest) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetTrackRequest.ProtoReflect.Descriptor instead. -func (*GetTrackRequest) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{4} -} - -func (x *GetTrackRequest) GetIdentifier() isGetTrackRequest_Identifier { - if x != nil { - return x.Identifier - } - return nil -} - -func (x *GetTrackRequest) GetId() string { - if x != nil { - if x, ok := x.Identifier.(*GetTrackRequest_Id); ok { - return x.Id - } - } - return "" -} - -func (x *GetTrackRequest) GetExternal() *ExternalID { - if x != nil { - if x, ok := x.Identifier.(*GetTrackRequest_External); ok { - return x.External - } - } - return nil -} - -func (x *GetTrackRequest) GetIsrc() string { - if x != nil { - if x, ok := x.Identifier.(*GetTrackRequest_Isrc); ok { - return x.Isrc - } - } - return "" -} - -func (x *GetTrackRequest) GetProvider() Provider { - if x != nil { - return x.Provider - } - return Provider_PROVIDER_UNSPECIFIED -} - -type isGetTrackRequest_Identifier interface { - isGetTrackRequest_Identifier() -} - -type GetTrackRequest_Id struct { - Id string `protobuf:"bytes,1,opt,name=id,proto3,oneof"` -} - -type GetTrackRequest_External struct { - External *ExternalID `protobuf:"bytes,2,opt,name=external,proto3,oneof"` -} - -type GetTrackRequest_Isrc struct { - Isrc string `protobuf:"bytes,3,opt,name=isrc,proto3,oneof"` -} - -func (*GetTrackRequest_Id) isGetTrackRequest_Identifier() {} - -func (*GetTrackRequest_External) isGetTrackRequest_Identifier() {} - -func (*GetTrackRequest_Isrc) isGetTrackRequest_Identifier() {} - -type GetAlbumTracksRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - AlbumId string `protobuf:"bytes,1,opt,name=album_id,json=albumId,proto3" json:"album_id,omitempty"` - Provider Provider `protobuf:"varint,2,opt,name=provider,proto3,enum=metadata.v1.Provider" json:"provider,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetAlbumTracksRequest) Reset() { - *x = GetAlbumTracksRequest{} - mi := &file_metadata_v1_metadata_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetAlbumTracksRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAlbumTracksRequest) ProtoMessage() {} - -func (x *GetAlbumTracksRequest) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetAlbumTracksRequest.ProtoReflect.Descriptor instead. -func (*GetAlbumTracksRequest) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{5} -} - -func (x *GetAlbumTracksRequest) GetAlbumId() string { - if x != nil { - return x.AlbumId - } - return "" -} - -func (x *GetAlbumTracksRequest) GetProvider() Provider { - if x != nil { - return x.Provider - } - return Provider_PROVIDER_UNSPECIFIED -} - -type SearchAlbumsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` - Artist string `protobuf:"bytes,2,opt,name=artist,proto3" json:"artist,omitempty"` - Limit int32 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"` - Offset int32 `protobuf:"varint,4,opt,name=offset,proto3" json:"offset,omitempty"` - Provider Provider `protobuf:"varint,5,opt,name=provider,proto3,enum=metadata.v1.Provider" json:"provider,omitempty"` - AlbumTypes []string `protobuf:"bytes,6,rep,name=album_types,json=albumTypes,proto3" json:"album_types,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchAlbumsRequest) Reset() { - *x = SearchAlbumsRequest{} - mi := &file_metadata_v1_metadata_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchAlbumsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchAlbumsRequest) ProtoMessage() {} - -func (x *SearchAlbumsRequest) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchAlbumsRequest.ProtoReflect.Descriptor instead. -func (*SearchAlbumsRequest) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{6} -} - -func (x *SearchAlbumsRequest) GetQuery() string { - if x != nil { - return x.Query - } - return "" -} - -func (x *SearchAlbumsRequest) GetArtist() string { - if x != nil { - return x.Artist - } - return "" -} - -func (x *SearchAlbumsRequest) GetLimit() int32 { - if x != nil { - return x.Limit - } - return 0 -} - -func (x *SearchAlbumsRequest) GetOffset() int32 { - if x != nil { - return x.Offset - } - return 0 -} - -func (x *SearchAlbumsRequest) GetProvider() Provider { - if x != nil { - return x.Provider - } - return Provider_PROVIDER_UNSPECIFIED -} - -func (x *SearchAlbumsRequest) GetAlbumTypes() []string { - if x != nil { - return x.AlbumTypes - } - return nil -} - -type SyncArtistRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Types that are valid to be assigned to Target: - // - // *SyncArtistRequest_Name - // *SyncArtistRequest_External - Target isSyncArtistRequest_Target `protobuf_oneof:"target"` - Provider Provider `protobuf:"varint,3,opt,name=provider,proto3,enum=metadata.v1.Provider" json:"provider,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SyncArtistRequest) Reset() { - *x = SyncArtistRequest{} - mi := &file_metadata_v1_metadata_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SyncArtistRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncArtistRequest) ProtoMessage() {} - -func (x *SyncArtistRequest) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SyncArtistRequest.ProtoReflect.Descriptor instead. -func (*SyncArtistRequest) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{7} -} - -func (x *SyncArtistRequest) GetTarget() isSyncArtistRequest_Target { - if x != nil { - return x.Target - } - return nil -} - -func (x *SyncArtistRequest) GetName() string { - if x != nil { - if x, ok := x.Target.(*SyncArtistRequest_Name); ok { - return x.Name - } - } - return "" -} - -func (x *SyncArtistRequest) GetExternal() *ExternalID { - if x != nil { - if x, ok := x.Target.(*SyncArtistRequest_External); ok { - return x.External - } - } - return nil -} - -func (x *SyncArtistRequest) GetProvider() Provider { - if x != nil { - return x.Provider - } - return Provider_PROVIDER_UNSPECIFIED -} - -type isSyncArtistRequest_Target interface { - isSyncArtistRequest_Target() -} - -type SyncArtistRequest_Name struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3,oneof"` -} - -type SyncArtistRequest_External struct { - External *ExternalID `protobuf:"bytes,2,opt,name=external,proto3,oneof"` -} - -func (*SyncArtistRequest_Name) isSyncArtistRequest_Target() {} - -func (*SyncArtistRequest_External) isSyncArtistRequest_Target() {} - -type GetArtistResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Artist *Artist `protobuf:"bytes,1,opt,name=artist,proto3" json:"artist,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetArtistResponse) Reset() { - *x = GetArtistResponse{} - mi := &file_metadata_v1_metadata_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetArtistResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetArtistResponse) ProtoMessage() {} - -func (x *GetArtistResponse) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetArtistResponse.ProtoReflect.Descriptor instead. -func (*GetArtistResponse) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{8} -} - -func (x *GetArtistResponse) GetArtist() *Artist { - if x != nil { - return x.Artist - } - return nil -} - -type SearchArtistsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Artists []*Artist `protobuf:"bytes,1,rep,name=artists,proto3" json:"artists,omitempty"` - Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchArtistsResponse) Reset() { - *x = SearchArtistsResponse{} - mi := &file_metadata_v1_metadata_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchArtistsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchArtistsResponse) ProtoMessage() {} - -func (x *SearchArtistsResponse) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchArtistsResponse.ProtoReflect.Descriptor instead. -func (*SearchArtistsResponse) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{9} -} - -func (x *SearchArtistsResponse) GetArtists() []*Artist { - if x != nil { - return x.Artists - } - return nil -} - -func (x *SearchArtistsResponse) GetTotal() int32 { - if x != nil { - return x.Total - } - return 0 -} - -type GetAlbumResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Album *Album `protobuf:"bytes,1,opt,name=album,proto3" json:"album,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetAlbumResponse) Reset() { - *x = GetAlbumResponse{} - mi := &file_metadata_v1_metadata_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetAlbumResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAlbumResponse) ProtoMessage() {} - -func (x *GetAlbumResponse) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetAlbumResponse.ProtoReflect.Descriptor instead. -func (*GetAlbumResponse) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{10} -} - -func (x *GetAlbumResponse) GetAlbum() *Album { - if x != nil { - return x.Album - } - return nil -} - -type GetArtistAlbumsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Albums []*Album `protobuf:"bytes,1,rep,name=albums,proto3" json:"albums,omitempty"` - Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetArtistAlbumsResponse) Reset() { - *x = GetArtistAlbumsResponse{} - mi := &file_metadata_v1_metadata_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetArtistAlbumsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetArtistAlbumsResponse) ProtoMessage() {} - -func (x *GetArtistAlbumsResponse) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[11] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetArtistAlbumsResponse.ProtoReflect.Descriptor instead. -func (*GetArtistAlbumsResponse) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{11} -} - -func (x *GetArtistAlbumsResponse) GetAlbums() []*Album { - if x != nil { - return x.Albums - } - return nil -} - -func (x *GetArtistAlbumsResponse) GetTotal() int32 { - if x != nil { - return x.Total - } - return 0 -} - -type GetTrackResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Track *Track `protobuf:"bytes,1,opt,name=track,proto3" json:"track,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetTrackResponse) Reset() { - *x = GetTrackResponse{} - mi := &file_metadata_v1_metadata_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetTrackResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetTrackResponse) ProtoMessage() {} - -func (x *GetTrackResponse) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[12] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetTrackResponse.ProtoReflect.Descriptor instead. -func (*GetTrackResponse) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{12} -} - -func (x *GetTrackResponse) GetTrack() *Track { - if x != nil { - return x.Track - } - return nil -} - -type GetAlbumTracksResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Tracks []*Track `protobuf:"bytes,1,rep,name=tracks,proto3" json:"tracks,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetAlbumTracksResponse) Reset() { - *x = GetAlbumTracksResponse{} - mi := &file_metadata_v1_metadata_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetAlbumTracksResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAlbumTracksResponse) ProtoMessage() {} - -func (x *GetAlbumTracksResponse) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[13] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetAlbumTracksResponse.ProtoReflect.Descriptor instead. -func (*GetAlbumTracksResponse) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{13} -} - -func (x *GetAlbumTracksResponse) GetTracks() []*Track { - if x != nil { - return x.Tracks - } - return nil -} - -type SearchAlbumsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Albums []*Album `protobuf:"bytes,1,rep,name=albums,proto3" json:"albums,omitempty"` - Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchAlbumsResponse) Reset() { - *x = SearchAlbumsResponse{} - mi := &file_metadata_v1_metadata_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchAlbumsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchAlbumsResponse) ProtoMessage() {} - -func (x *SearchAlbumsResponse) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[14] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchAlbumsResponse.ProtoReflect.Descriptor instead. -func (*SearchAlbumsResponse) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{14} -} - -func (x *SearchAlbumsResponse) GetAlbums() []*Album { - if x != nil { - return x.Albums - } - return nil -} - -func (x *SearchAlbumsResponse) GetTotal() int32 { - if x != nil { - return x.Total - } - return 0 -} - -type SyncArtistResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Artist *Artist `protobuf:"bytes,1,opt,name=artist,proto3" json:"artist,omitempty"` - AlbumsSynced int32 `protobuf:"varint,2,opt,name=albums_synced,json=albumsSynced,proto3" json:"albums_synced,omitempty"` - TracksSynced int32 `protobuf:"varint,3,opt,name=tracks_synced,json=tracksSynced,proto3" json:"tracks_synced,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SyncArtistResponse) Reset() { - *x = SyncArtistResponse{} - mi := &file_metadata_v1_metadata_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SyncArtistResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncArtistResponse) ProtoMessage() {} - -func (x *SyncArtistResponse) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[15] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SyncArtistResponse.ProtoReflect.Descriptor instead. -func (*SyncArtistResponse) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{15} -} - -func (x *SyncArtistResponse) GetArtist() *Artist { - if x != nil { - return x.Artist - } - return nil -} - -func (x *SyncArtistResponse) GetAlbumsSynced() int32 { - if x != nil { - return x.AlbumsSynced - } - return 0 -} - -func (x *SyncArtistResponse) GetTracksSynced() int32 { - if x != nil { - return x.TracksSynced - } - return 0 -} - -type Artist struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - SortName string `protobuf:"bytes,3,opt,name=sort_name,json=sortName,proto3" json:"sort_name,omitempty"` - ArtistType string `protobuf:"bytes,4,opt,name=artist_type,json=artistType,proto3" json:"artist_type,omitempty"` - Country string `protobuf:"bytes,5,opt,name=country,proto3" json:"country,omitempty"` - FormedDate string `protobuf:"bytes,6,opt,name=formed_date,json=formedDate,proto3" json:"formed_date,omitempty"` - DisbandedDate string `protobuf:"bytes,7,opt,name=disbanded_date,json=disbandedDate,proto3" json:"disbanded_date,omitempty"` - Description string `protobuf:"bytes,8,opt,name=description,proto3" json:"description,omitempty"` - ImageUrl string `protobuf:"bytes,9,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` - Genres []*Genre `protobuf:"bytes,10,rep,name=genres,proto3" json:"genres,omitempty"` - ExternalIds []*ExternalID `protobuf:"bytes,11,rep,name=external_ids,json=externalIds,proto3" json:"external_ids,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Artist) Reset() { - *x = Artist{} - mi := &file_metadata_v1_metadata_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Artist) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Artist) ProtoMessage() {} - -func (x *Artist) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[16] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Artist.ProtoReflect.Descriptor instead. -func (*Artist) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{16} -} - -func (x *Artist) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Artist) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Artist) GetSortName() string { - if x != nil { - return x.SortName - } - return "" -} - -func (x *Artist) GetArtistType() string { - if x != nil { - return x.ArtistType - } - return "" -} - -func (x *Artist) GetCountry() string { - if x != nil { - return x.Country - } - return "" -} - -func (x *Artist) GetFormedDate() string { - if x != nil { - return x.FormedDate - } - return "" -} - -func (x *Artist) GetDisbandedDate() string { - if x != nil { - return x.DisbandedDate - } - return "" -} - -func (x *Artist) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *Artist) GetImageUrl() string { - if x != nil { - return x.ImageUrl - } - return "" -} - -func (x *Artist) GetGenres() []*Genre { - if x != nil { - return x.Genres - } - return nil -} - -func (x *Artist) GetExternalIds() []*ExternalID { - if x != nil { - return x.ExternalIds - } - return nil -} - -type Album struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` - AlbumType string `protobuf:"bytes,3,opt,name=album_type,json=albumType,proto3" json:"album_type,omitempty"` - ReleaseDate string `protobuf:"bytes,4,opt,name=release_date,json=releaseDate,proto3" json:"release_date,omitempty"` - Upc string `protobuf:"bytes,5,opt,name=upc,proto3" json:"upc,omitempty"` - TotalTracks int32 `protobuf:"varint,6,opt,name=total_tracks,json=totalTracks,proto3" json:"total_tracks,omitempty"` - TotalDiscs int32 `protobuf:"varint,7,opt,name=total_discs,json=totalDiscs,proto3" json:"total_discs,omitempty"` - CoverUrl string `protobuf:"bytes,8,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` - Artists []*ArtistCredit `protobuf:"bytes,9,rep,name=artists,proto3" json:"artists,omitempty"` - Label *Label `protobuf:"bytes,10,opt,name=label,proto3" json:"label,omitempty"` - Genres []*Genre `protobuf:"bytes,11,rep,name=genres,proto3" json:"genres,omitempty"` - ExternalIds []*ExternalID `protobuf:"bytes,12,rep,name=external_ids,json=externalIds,proto3" json:"external_ids,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Album) Reset() { - *x = Album{} - mi := &file_metadata_v1_metadata_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Album) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Album) ProtoMessage() {} - -func (x *Album) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[17] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Album.ProtoReflect.Descriptor instead. -func (*Album) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{17} -} - -func (x *Album) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Album) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *Album) GetAlbumType() string { - if x != nil { - return x.AlbumType - } - return "" -} - -func (x *Album) GetReleaseDate() string { - if x != nil { - return x.ReleaseDate - } - return "" -} - -func (x *Album) GetUpc() string { - if x != nil { - return x.Upc - } - return "" -} - -func (x *Album) GetTotalTracks() int32 { - if x != nil { - return x.TotalTracks - } - return 0 -} - -func (x *Album) GetTotalDiscs() int32 { - if x != nil { - return x.TotalDiscs - } - return 0 -} - -func (x *Album) GetCoverUrl() string { - if x != nil { - return x.CoverUrl - } - return "" -} - -func (x *Album) GetArtists() []*ArtistCredit { - if x != nil { - return x.Artists - } - return nil -} - -func (x *Album) GetLabel() *Label { - if x != nil { - return x.Label - } - return nil -} - -func (x *Album) GetGenres() []*Genre { - if x != nil { - return x.Genres - } - return nil -} - -func (x *Album) GetExternalIds() []*ExternalID { - if x != nil { - return x.ExternalIds - } - return nil -} - -type Track struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` - DurationMs int32 `protobuf:"varint,3,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - Isrc string `protobuf:"bytes,4,opt,name=isrc,proto3" json:"isrc,omitempty"` - Explicit bool `protobuf:"varint,5,opt,name=explicit,proto3" json:"explicit,omitempty"` - DiscNumber int32 `protobuf:"varint,6,opt,name=disc_number,json=discNumber,proto3" json:"disc_number,omitempty"` - TrackNumber int32 `protobuf:"varint,7,opt,name=track_number,json=trackNumber,proto3" json:"track_number,omitempty"` - Artists []*ArtistCredit `protobuf:"bytes,8,rep,name=artists,proto3" json:"artists,omitempty"` - Work *Work `protobuf:"bytes,9,opt,name=work,proto3" json:"work,omitempty"` - ExternalIds []*ExternalID `protobuf:"bytes,10,rep,name=external_ids,json=externalIds,proto3" json:"external_ids,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Track) Reset() { - *x = Track{} - mi := &file_metadata_v1_metadata_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Track) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Track) ProtoMessage() {} - -func (x *Track) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[18] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Track.ProtoReflect.Descriptor instead. -func (*Track) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{18} -} - -func (x *Track) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Track) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *Track) GetDurationMs() int32 { - if x != nil { - return x.DurationMs - } - return 0 -} - -func (x *Track) GetIsrc() string { - if x != nil { - return x.Isrc - } - return "" -} - -func (x *Track) GetExplicit() bool { - if x != nil { - return x.Explicit - } - return false -} - -func (x *Track) GetDiscNumber() int32 { - if x != nil { - return x.DiscNumber - } - return 0 -} - -func (x *Track) GetTrackNumber() int32 { - if x != nil { - return x.TrackNumber - } - return 0 -} - -func (x *Track) GetArtists() []*ArtistCredit { - if x != nil { - return x.Artists - } - return nil -} - -func (x *Track) GetWork() *Work { - if x != nil { - return x.Work - } - return nil -} - -func (x *Track) GetExternalIds() []*ExternalID { - if x != nil { - return x.ExternalIds - } - return nil -} - -type Work struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` - WorkType string `protobuf:"bytes,3,opt,name=work_type,json=workType,proto3" json:"work_type,omitempty"` - Language string `protobuf:"bytes,4,opt,name=language,proto3" json:"language,omitempty"` - Composers []*ArtistCredit `protobuf:"bytes,5,rep,name=composers,proto3" json:"composers,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Work) Reset() { - *x = Work{} - mi := &file_metadata_v1_metadata_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Work) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Work) ProtoMessage() {} - -func (x *Work) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[19] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Work.ProtoReflect.Descriptor instead. -func (*Work) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{19} -} - -func (x *Work) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Work) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *Work) GetWorkType() string { - if x != nil { - return x.WorkType - } - return "" -} - -func (x *Work) GetLanguage() string { - if x != nil { - return x.Language - } - return "" -} - -func (x *Work) GetComposers() []*ArtistCredit { - if x != nil { - return x.Composers - } - return nil -} - -type Label struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Country string `protobuf:"bytes,3,opt,name=country,proto3" json:"country,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Label) Reset() { - *x = Label{} - mi := &file_metadata_v1_metadata_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Label) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Label) ProtoMessage() {} - -func (x *Label) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[20] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Label.ProtoReflect.Descriptor instead. -func (*Label) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{20} -} - -func (x *Label) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Label) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Label) GetCountry() string { - if x != nil { - return x.Country - } - return "" -} - -type Genre struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Genre) Reset() { - *x = Genre{} - mi := &file_metadata_v1_metadata_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Genre) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Genre) ProtoMessage() {} - -func (x *Genre) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[21] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Genre.ProtoReflect.Descriptor instead. -func (*Genre) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{21} -} - -func (x *Genre) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Genre) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -type ArtistCredit struct { - state protoimpl.MessageState `protogen:"open.v1"` - Artist *Artist `protobuf:"bytes,1,opt,name=artist,proto3" json:"artist,omitempty"` - Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` - Position int32 `protobuf:"varint,3,opt,name=position,proto3" json:"position,omitempty"` - JoinPhrase string `protobuf:"bytes,4,opt,name=join_phrase,json=joinPhrase,proto3" json:"join_phrase,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ArtistCredit) Reset() { - *x = ArtistCredit{} - mi := &file_metadata_v1_metadata_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ArtistCredit) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ArtistCredit) ProtoMessage() {} - -func (x *ArtistCredit) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[22] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ArtistCredit.ProtoReflect.Descriptor instead. -func (*ArtistCredit) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{22} -} - -func (x *ArtistCredit) GetArtist() *Artist { - if x != nil { - return x.Artist - } - return nil -} - -func (x *ArtistCredit) GetRole() string { - if x != nil { - return x.Role - } - return "" -} - -func (x *ArtistCredit) GetPosition() int32 { - if x != nil { - return x.Position - } - return 0 -} - -func (x *ArtistCredit) GetJoinPhrase() string { - if x != nil { - return x.JoinPhrase - } - return "" -} - -type ExternalID struct { - state protoimpl.MessageState `protogen:"open.v1"` - Source string `protobuf:"bytes,1,opt,name=source,proto3" json:"source,omitempty"` - SourceId string `protobuf:"bytes,2,opt,name=source_id,json=sourceId,proto3" json:"source_id,omitempty"` - Url string `protobuf:"bytes,3,opt,name=url,proto3" json:"url,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ExternalID) Reset() { - *x = ExternalID{} - mi := &file_metadata_v1_metadata_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ExternalID) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExternalID) ProtoMessage() {} - -func (x *ExternalID) ProtoReflect() protoreflect.Message { - mi := &file_metadata_v1_metadata_proto_msgTypes[23] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExternalID.ProtoReflect.Descriptor instead. -func (*ExternalID) Descriptor() ([]byte, []int) { - return file_metadata_v1_metadata_proto_rawDescGZIP(), []int{23} -} - -func (x *ExternalID) GetSource() string { - if x != nil { - return x.Source - } - return "" -} - -func (x *ExternalID) GetSourceId() string { - if x != nil { - return x.SourceId - } - return "" -} - -func (x *ExternalID) GetUrl() string { - if x != nil { - return x.Url - } - return "" -} - -var File_metadata_v1_metadata_proto protoreflect.FileDescriptor - -const file_metadata_v1_metadata_proto_rawDesc = "" + - "\n" + - "\x1ametadata/v1/metadata.proto\x12\vmetadata.v1\"\x9c\x01\n" + - "\x10GetArtistRequest\x12\x10\n" + - "\x02id\x18\x01 \x01(\tH\x00R\x02id\x125\n" + - "\bexternal\x18\x02 \x01(\v2\x17.metadata.v1.ExternalIDH\x00R\bexternal\x121\n" + - "\bprovider\x18\x03 \x01(\x0e2\x15.metadata.v1.ProviderR\bproviderB\f\n" + - "\n" + - "identifier\"\x8d\x01\n" + - "\x14SearchArtistsRequest\x12\x14\n" + - "\x05query\x18\x01 \x01(\tR\x05query\x12\x14\n" + - "\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x16\n" + - "\x06offset\x18\x03 \x01(\x05R\x06offset\x121\n" + - "\bprovider\x18\x04 \x01(\x0e2\x15.metadata.v1.ProviderR\bprovider\"\x9b\x01\n" + - "\x0fGetAlbumRequest\x12\x10\n" + - "\x02id\x18\x01 \x01(\tH\x00R\x02id\x125\n" + - "\bexternal\x18\x02 \x01(\v2\x17.metadata.v1.ExternalIDH\x00R\bexternal\x121\n" + - "\bprovider\x18\x03 \x01(\x0e2\x15.metadata.v1.ProviderR\bproviderB\f\n" + - "\n" + - "identifier\"\xb7\x01\n" + - "\x16GetArtistAlbumsRequest\x12\x1b\n" + - "\tartist_id\x18\x01 \x01(\tR\bartistId\x12\x14\n" + - "\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x16\n" + - "\x06offset\x18\x03 \x01(\x05R\x06offset\x121\n" + - "\bprovider\x18\x04 \x01(\x0e2\x15.metadata.v1.ProviderR\bprovider\x12\x1f\n" + - "\valbum_types\x18\x05 \x03(\tR\n" + - "albumTypes\"\xb1\x01\n" + - "\x0fGetTrackRequest\x12\x10\n" + - "\x02id\x18\x01 \x01(\tH\x00R\x02id\x125\n" + - "\bexternal\x18\x02 \x01(\v2\x17.metadata.v1.ExternalIDH\x00R\bexternal\x12\x14\n" + - "\x04isrc\x18\x03 \x01(\tH\x00R\x04isrc\x121\n" + - "\bprovider\x18\x04 \x01(\x0e2\x15.metadata.v1.ProviderR\bproviderB\f\n" + - "\n" + - "identifier\"e\n" + - "\x15GetAlbumTracksRequest\x12\x19\n" + - "\balbum_id\x18\x01 \x01(\tR\aalbumId\x121\n" + - "\bprovider\x18\x02 \x01(\x0e2\x15.metadata.v1.ProviderR\bprovider\"\xc5\x01\n" + - "\x13SearchAlbumsRequest\x12\x14\n" + - "\x05query\x18\x01 \x01(\tR\x05query\x12\x16\n" + - "\x06artist\x18\x02 \x01(\tR\x06artist\x12\x14\n" + - "\x05limit\x18\x03 \x01(\x05R\x05limit\x12\x16\n" + - "\x06offset\x18\x04 \x01(\x05R\x06offset\x121\n" + - "\bprovider\x18\x05 \x01(\x0e2\x15.metadata.v1.ProviderR\bprovider\x12\x1f\n" + - "\valbum_types\x18\x06 \x03(\tR\n" + - "albumTypes\"\x9d\x01\n" + - "\x11SyncArtistRequest\x12\x14\n" + - "\x04name\x18\x01 \x01(\tH\x00R\x04name\x125\n" + - "\bexternal\x18\x02 \x01(\v2\x17.metadata.v1.ExternalIDH\x00R\bexternal\x121\n" + - "\bprovider\x18\x03 \x01(\x0e2\x15.metadata.v1.ProviderR\bproviderB\b\n" + - "\x06target\"@\n" + - "\x11GetArtistResponse\x12+\n" + - "\x06artist\x18\x01 \x01(\v2\x13.metadata.v1.ArtistR\x06artist\"\\\n" + - "\x15SearchArtistsResponse\x12-\n" + - "\aartists\x18\x01 \x03(\v2\x13.metadata.v1.ArtistR\aartists\x12\x14\n" + - "\x05total\x18\x02 \x01(\x05R\x05total\"<\n" + - "\x10GetAlbumResponse\x12(\n" + - "\x05album\x18\x01 \x01(\v2\x12.metadata.v1.AlbumR\x05album\"[\n" + - "\x17GetArtistAlbumsResponse\x12*\n" + - "\x06albums\x18\x01 \x03(\v2\x12.metadata.v1.AlbumR\x06albums\x12\x14\n" + - "\x05total\x18\x02 \x01(\x05R\x05total\"<\n" + - "\x10GetTrackResponse\x12(\n" + - "\x05track\x18\x01 \x01(\v2\x12.metadata.v1.TrackR\x05track\"D\n" + - "\x16GetAlbumTracksResponse\x12*\n" + - "\x06tracks\x18\x01 \x03(\v2\x12.metadata.v1.TrackR\x06tracks\"X\n" + - "\x14SearchAlbumsResponse\x12*\n" + - "\x06albums\x18\x01 \x03(\v2\x12.metadata.v1.AlbumR\x06albums\x12\x14\n" + - "\x05total\x18\x02 \x01(\x05R\x05total\"\x8b\x01\n" + - "\x12SyncArtistResponse\x12+\n" + - "\x06artist\x18\x01 \x01(\v2\x13.metadata.v1.ArtistR\x06artist\x12#\n" + - "\ralbums_synced\x18\x02 \x01(\x05R\falbumsSynced\x12#\n" + - "\rtracks_synced\x18\x03 \x01(\x05R\ftracksSynced\"\xf3\x02\n" + - "\x06Artist\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x1b\n" + - "\tsort_name\x18\x03 \x01(\tR\bsortName\x12\x1f\n" + - "\vartist_type\x18\x04 \x01(\tR\n" + - "artistType\x12\x18\n" + - "\acountry\x18\x05 \x01(\tR\acountry\x12\x1f\n" + - "\vformed_date\x18\x06 \x01(\tR\n" + - "formedDate\x12%\n" + - "\x0edisbanded_date\x18\a \x01(\tR\rdisbandedDate\x12 \n" + - "\vdescription\x18\b \x01(\tR\vdescription\x12\x1b\n" + - "\timage_url\x18\t \x01(\tR\bimageUrl\x12*\n" + - "\x06genres\x18\n" + - " \x03(\v2\x12.metadata.v1.GenreR\x06genres\x12:\n" + - "\fexternal_ids\x18\v \x03(\v2\x17.metadata.v1.ExternalIDR\vexternalIds\"\xa9\x03\n" + - "\x05Album\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" + - "\x05title\x18\x02 \x01(\tR\x05title\x12\x1d\n" + - "\n" + - "album_type\x18\x03 \x01(\tR\talbumType\x12!\n" + - "\frelease_date\x18\x04 \x01(\tR\vreleaseDate\x12\x10\n" + - "\x03upc\x18\x05 \x01(\tR\x03upc\x12!\n" + - "\ftotal_tracks\x18\x06 \x01(\x05R\vtotalTracks\x12\x1f\n" + - "\vtotal_discs\x18\a \x01(\x05R\n" + - "totalDiscs\x12\x1b\n" + - "\tcover_url\x18\b \x01(\tR\bcoverUrl\x123\n" + - "\aartists\x18\t \x03(\v2\x19.metadata.v1.ArtistCreditR\aartists\x12(\n" + - "\x05label\x18\n" + - " \x01(\v2\x12.metadata.v1.LabelR\x05label\x12*\n" + - "\x06genres\x18\v \x03(\v2\x12.metadata.v1.GenreR\x06genres\x12:\n" + - "\fexternal_ids\x18\f \x03(\v2\x17.metadata.v1.ExternalIDR\vexternalIds\"\xda\x02\n" + - "\x05Track\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" + - "\x05title\x18\x02 \x01(\tR\x05title\x12\x1f\n" + - "\vduration_ms\x18\x03 \x01(\x05R\n" + - "durationMs\x12\x12\n" + - "\x04isrc\x18\x04 \x01(\tR\x04isrc\x12\x1a\n" + - "\bexplicit\x18\x05 \x01(\bR\bexplicit\x12\x1f\n" + - "\vdisc_number\x18\x06 \x01(\x05R\n" + - "discNumber\x12!\n" + - "\ftrack_number\x18\a \x01(\x05R\vtrackNumber\x123\n" + - "\aartists\x18\b \x03(\v2\x19.metadata.v1.ArtistCreditR\aartists\x12%\n" + - "\x04work\x18\t \x01(\v2\x11.metadata.v1.WorkR\x04work\x12:\n" + - "\fexternal_ids\x18\n" + - " \x03(\v2\x17.metadata.v1.ExternalIDR\vexternalIds\"\x9e\x01\n" + - "\x04Work\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" + - "\x05title\x18\x02 \x01(\tR\x05title\x12\x1b\n" + - "\twork_type\x18\x03 \x01(\tR\bworkType\x12\x1a\n" + - "\blanguage\x18\x04 \x01(\tR\blanguage\x127\n" + - "\tcomposers\x18\x05 \x03(\v2\x19.metadata.v1.ArtistCreditR\tcomposers\"E\n" + - "\x05Label\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x18\n" + - "\acountry\x18\x03 \x01(\tR\acountry\"+\n" + - "\x05Genre\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\"\x8c\x01\n" + - "\fArtistCredit\x12+\n" + - "\x06artist\x18\x01 \x01(\v2\x13.metadata.v1.ArtistR\x06artist\x12\x12\n" + - "\x04role\x18\x02 \x01(\tR\x04role\x12\x1a\n" + - "\bposition\x18\x03 \x01(\x05R\bposition\x12\x1f\n" + - "\vjoin_phrase\x18\x04 \x01(\tR\n" + - "joinPhrase\"S\n" + - "\n" + - "ExternalID\x12\x16\n" + - "\x06source\x18\x01 \x01(\tR\x06source\x12\x1b\n" + - "\tsource_id\x18\x02 \x01(\tR\bsourceId\x12\x10\n" + - "\x03url\x18\x03 \x01(\tR\x03url*>\n" + - "\bProvider\x12\x18\n" + - "\x14PROVIDER_UNSPECIFIED\x10\x00\x12\x18\n" + - "\x14PROVIDER_MUSICBRAINZ\x10\x012\xa4\x05\n" + - "\x0fMetadataService\x12J\n" + - "\tGetArtist\x12\x1d.metadata.v1.GetArtistRequest\x1a\x1e.metadata.v1.GetArtistResponse\x12V\n" + - "\rSearchArtists\x12!.metadata.v1.SearchArtistsRequest\x1a\".metadata.v1.SearchArtistsResponse\x12G\n" + - "\bGetAlbum\x12\x1c.metadata.v1.GetAlbumRequest\x1a\x1d.metadata.v1.GetAlbumResponse\x12\\\n" + - "\x0fGetArtistAlbums\x12#.metadata.v1.GetArtistAlbumsRequest\x1a$.metadata.v1.GetArtistAlbumsResponse\x12G\n" + - "\bGetTrack\x12\x1c.metadata.v1.GetTrackRequest\x1a\x1d.metadata.v1.GetTrackResponse\x12Y\n" + - "\x0eGetAlbumTracks\x12\".metadata.v1.GetAlbumTracksRequest\x1a#.metadata.v1.GetAlbumTracksResponse\x12S\n" + - "\fSearchAlbums\x12 .metadata.v1.SearchAlbumsRequest\x1a!.metadata.v1.SearchAlbumsResponse\x12M\n" + - "\n" + - "SyncArtist\x12\x1e.metadata.v1.SyncArtistRequest\x1a\x1f.metadata.v1.SyncArtistResponseB>Z metadata.v1.ExternalID - 0, // 1: metadata.v1.GetArtistRequest.provider:type_name -> metadata.v1.Provider - 0, // 2: metadata.v1.SearchArtistsRequest.provider:type_name -> metadata.v1.Provider - 24, // 3: metadata.v1.GetAlbumRequest.external:type_name -> metadata.v1.ExternalID - 0, // 4: metadata.v1.GetAlbumRequest.provider:type_name -> metadata.v1.Provider - 0, // 5: metadata.v1.GetArtistAlbumsRequest.provider:type_name -> metadata.v1.Provider - 24, // 6: metadata.v1.GetTrackRequest.external:type_name -> metadata.v1.ExternalID - 0, // 7: metadata.v1.GetTrackRequest.provider:type_name -> metadata.v1.Provider - 0, // 8: metadata.v1.GetAlbumTracksRequest.provider:type_name -> metadata.v1.Provider - 0, // 9: metadata.v1.SearchAlbumsRequest.provider:type_name -> metadata.v1.Provider - 24, // 10: metadata.v1.SyncArtistRequest.external:type_name -> metadata.v1.ExternalID - 0, // 11: metadata.v1.SyncArtistRequest.provider:type_name -> metadata.v1.Provider - 17, // 12: metadata.v1.GetArtistResponse.artist:type_name -> metadata.v1.Artist - 17, // 13: metadata.v1.SearchArtistsResponse.artists:type_name -> metadata.v1.Artist - 18, // 14: metadata.v1.GetAlbumResponse.album:type_name -> metadata.v1.Album - 18, // 15: metadata.v1.GetArtistAlbumsResponse.albums:type_name -> metadata.v1.Album - 19, // 16: metadata.v1.GetTrackResponse.track:type_name -> metadata.v1.Track - 19, // 17: metadata.v1.GetAlbumTracksResponse.tracks:type_name -> metadata.v1.Track - 18, // 18: metadata.v1.SearchAlbumsResponse.albums:type_name -> metadata.v1.Album - 17, // 19: metadata.v1.SyncArtistResponse.artist:type_name -> metadata.v1.Artist - 22, // 20: metadata.v1.Artist.genres:type_name -> metadata.v1.Genre - 24, // 21: metadata.v1.Artist.external_ids:type_name -> metadata.v1.ExternalID - 23, // 22: metadata.v1.Album.artists:type_name -> metadata.v1.ArtistCredit - 21, // 23: metadata.v1.Album.label:type_name -> metadata.v1.Label - 22, // 24: metadata.v1.Album.genres:type_name -> metadata.v1.Genre - 24, // 25: metadata.v1.Album.external_ids:type_name -> metadata.v1.ExternalID - 23, // 26: metadata.v1.Track.artists:type_name -> metadata.v1.ArtistCredit - 20, // 27: metadata.v1.Track.work:type_name -> metadata.v1.Work - 24, // 28: metadata.v1.Track.external_ids:type_name -> metadata.v1.ExternalID - 23, // 29: metadata.v1.Work.composers:type_name -> metadata.v1.ArtistCredit - 17, // 30: metadata.v1.ArtistCredit.artist:type_name -> metadata.v1.Artist - 1, // 31: metadata.v1.MetadataService.GetArtist:input_type -> metadata.v1.GetArtistRequest - 2, // 32: metadata.v1.MetadataService.SearchArtists:input_type -> metadata.v1.SearchArtistsRequest - 3, // 33: metadata.v1.MetadataService.GetAlbum:input_type -> metadata.v1.GetAlbumRequest - 4, // 34: metadata.v1.MetadataService.GetArtistAlbums:input_type -> metadata.v1.GetArtistAlbumsRequest - 5, // 35: metadata.v1.MetadataService.GetTrack:input_type -> metadata.v1.GetTrackRequest - 6, // 36: metadata.v1.MetadataService.GetAlbumTracks:input_type -> metadata.v1.GetAlbumTracksRequest - 7, // 37: metadata.v1.MetadataService.SearchAlbums:input_type -> metadata.v1.SearchAlbumsRequest - 8, // 38: metadata.v1.MetadataService.SyncArtist:input_type -> metadata.v1.SyncArtistRequest - 9, // 39: metadata.v1.MetadataService.GetArtist:output_type -> metadata.v1.GetArtistResponse - 10, // 40: metadata.v1.MetadataService.SearchArtists:output_type -> metadata.v1.SearchArtistsResponse - 11, // 41: metadata.v1.MetadataService.GetAlbum:output_type -> metadata.v1.GetAlbumResponse - 12, // 42: metadata.v1.MetadataService.GetArtistAlbums:output_type -> metadata.v1.GetArtistAlbumsResponse - 13, // 43: metadata.v1.MetadataService.GetTrack:output_type -> metadata.v1.GetTrackResponse - 14, // 44: metadata.v1.MetadataService.GetAlbumTracks:output_type -> metadata.v1.GetAlbumTracksResponse - 15, // 45: metadata.v1.MetadataService.SearchAlbums:output_type -> metadata.v1.SearchAlbumsResponse - 16, // 46: metadata.v1.MetadataService.SyncArtist:output_type -> metadata.v1.SyncArtistResponse - 39, // [39:47] is the sub-list for method output_type - 31, // [31:39] is the sub-list for method input_type - 31, // [31:31] is the sub-list for extension type_name - 31, // [31:31] is the sub-list for extension extendee - 0, // [0:31] is the sub-list for field type_name -} - -func init() { file_metadata_v1_metadata_proto_init() } -func file_metadata_v1_metadata_proto_init() { - if File_metadata_v1_metadata_proto != nil { - return - } - file_metadata_v1_metadata_proto_msgTypes[0].OneofWrappers = []any{ - (*GetArtistRequest_Id)(nil), - (*GetArtistRequest_External)(nil), - } - file_metadata_v1_metadata_proto_msgTypes[2].OneofWrappers = []any{ - (*GetAlbumRequest_Id)(nil), - (*GetAlbumRequest_External)(nil), - } - file_metadata_v1_metadata_proto_msgTypes[4].OneofWrappers = []any{ - (*GetTrackRequest_Id)(nil), - (*GetTrackRequest_External)(nil), - (*GetTrackRequest_Isrc)(nil), - } - file_metadata_v1_metadata_proto_msgTypes[7].OneofWrappers = []any{ - (*SyncArtistRequest_Name)(nil), - (*SyncArtistRequest_External)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_metadata_v1_metadata_proto_rawDesc), len(file_metadata_v1_metadata_proto_rawDesc)), - NumEnums: 1, - NumMessages: 24, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_metadata_v1_metadata_proto_goTypes, - DependencyIndexes: file_metadata_v1_metadata_proto_depIdxs, - EnumInfos: file_metadata_v1_metadata_proto_enumTypes, - MessageInfos: file_metadata_v1_metadata_proto_msgTypes, - }.Build() - File_metadata_v1_metadata_proto = out.File - file_metadata_v1_metadata_proto_goTypes = nil - file_metadata_v1_metadata_proto_depIdxs = nil -} diff --git a/gen/metadata/v1/metadata_grpc.pb.go b/gen/metadata/v1/metadata_grpc.pb.go deleted file mode 100644 index f382674..0000000 --- a/gen/metadata/v1/metadata_grpc.pb.go +++ /dev/null @@ -1,387 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.1 -// - protoc (unknown) -// source: metadata/v1/metadata.proto - -package metadatav1 - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - MetadataService_GetArtist_FullMethodName = "/metadata.v1.MetadataService/GetArtist" - MetadataService_SearchArtists_FullMethodName = "/metadata.v1.MetadataService/SearchArtists" - MetadataService_GetAlbum_FullMethodName = "/metadata.v1.MetadataService/GetAlbum" - MetadataService_GetArtistAlbums_FullMethodName = "/metadata.v1.MetadataService/GetArtistAlbums" - MetadataService_GetTrack_FullMethodName = "/metadata.v1.MetadataService/GetTrack" - MetadataService_GetAlbumTracks_FullMethodName = "/metadata.v1.MetadataService/GetAlbumTracks" - MetadataService_SearchAlbums_FullMethodName = "/metadata.v1.MetadataService/SearchAlbums" - MetadataService_SyncArtist_FullMethodName = "/metadata.v1.MetadataService/SyncArtist" -) - -// MetadataServiceClient is the client API for MetadataService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type MetadataServiceClient interface { - GetArtist(ctx context.Context, in *GetArtistRequest, opts ...grpc.CallOption) (*GetArtistResponse, error) - SearchArtists(ctx context.Context, in *SearchArtistsRequest, opts ...grpc.CallOption) (*SearchArtistsResponse, error) - GetAlbum(ctx context.Context, in *GetAlbumRequest, opts ...grpc.CallOption) (*GetAlbumResponse, error) - GetArtistAlbums(ctx context.Context, in *GetArtistAlbumsRequest, opts ...grpc.CallOption) (*GetArtistAlbumsResponse, error) - GetTrack(ctx context.Context, in *GetTrackRequest, opts ...grpc.CallOption) (*GetTrackResponse, error) - GetAlbumTracks(ctx context.Context, in *GetAlbumTracksRequest, opts ...grpc.CallOption) (*GetAlbumTracksResponse, error) - SearchAlbums(ctx context.Context, in *SearchAlbumsRequest, opts ...grpc.CallOption) (*SearchAlbumsResponse, error) - SyncArtist(ctx context.Context, in *SyncArtistRequest, opts ...grpc.CallOption) (*SyncArtistResponse, error) -} - -type metadataServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewMetadataServiceClient(cc grpc.ClientConnInterface) MetadataServiceClient { - return &metadataServiceClient{cc} -} - -func (c *metadataServiceClient) GetArtist(ctx context.Context, in *GetArtistRequest, opts ...grpc.CallOption) (*GetArtistResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetArtistResponse) - err := c.cc.Invoke(ctx, MetadataService_GetArtist_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) SearchArtists(ctx context.Context, in *SearchArtistsRequest, opts ...grpc.CallOption) (*SearchArtistsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SearchArtistsResponse) - err := c.cc.Invoke(ctx, MetadataService_SearchArtists_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) GetAlbum(ctx context.Context, in *GetAlbumRequest, opts ...grpc.CallOption) (*GetAlbumResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetAlbumResponse) - err := c.cc.Invoke(ctx, MetadataService_GetAlbum_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) GetArtistAlbums(ctx context.Context, in *GetArtistAlbumsRequest, opts ...grpc.CallOption) (*GetArtistAlbumsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetArtistAlbumsResponse) - err := c.cc.Invoke(ctx, MetadataService_GetArtistAlbums_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) GetTrack(ctx context.Context, in *GetTrackRequest, opts ...grpc.CallOption) (*GetTrackResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetTrackResponse) - err := c.cc.Invoke(ctx, MetadataService_GetTrack_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) GetAlbumTracks(ctx context.Context, in *GetAlbumTracksRequest, opts ...grpc.CallOption) (*GetAlbumTracksResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetAlbumTracksResponse) - err := c.cc.Invoke(ctx, MetadataService_GetAlbumTracks_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) SearchAlbums(ctx context.Context, in *SearchAlbumsRequest, opts ...grpc.CallOption) (*SearchAlbumsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SearchAlbumsResponse) - err := c.cc.Invoke(ctx, MetadataService_SearchAlbums_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) SyncArtist(ctx context.Context, in *SyncArtistRequest, opts ...grpc.CallOption) (*SyncArtistResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SyncArtistResponse) - err := c.cc.Invoke(ctx, MetadataService_SyncArtist_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -// MetadataServiceServer is the server API for MetadataService service. -// All implementations must embed UnimplementedMetadataServiceServer -// for forward compatibility. -type MetadataServiceServer interface { - GetArtist(context.Context, *GetArtistRequest) (*GetArtistResponse, error) - SearchArtists(context.Context, *SearchArtistsRequest) (*SearchArtistsResponse, error) - GetAlbum(context.Context, *GetAlbumRequest) (*GetAlbumResponse, error) - GetArtistAlbums(context.Context, *GetArtistAlbumsRequest) (*GetArtistAlbumsResponse, error) - GetTrack(context.Context, *GetTrackRequest) (*GetTrackResponse, error) - GetAlbumTracks(context.Context, *GetAlbumTracksRequest) (*GetAlbumTracksResponse, error) - SearchAlbums(context.Context, *SearchAlbumsRequest) (*SearchAlbumsResponse, error) - SyncArtist(context.Context, *SyncArtistRequest) (*SyncArtistResponse, error) - mustEmbedUnimplementedMetadataServiceServer() -} - -// UnimplementedMetadataServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedMetadataServiceServer struct{} - -func (UnimplementedMetadataServiceServer) GetArtist(context.Context, *GetArtistRequest) (*GetArtistResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetArtist not implemented") -} -func (UnimplementedMetadataServiceServer) SearchArtists(context.Context, *SearchArtistsRequest) (*SearchArtistsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SearchArtists not implemented") -} -func (UnimplementedMetadataServiceServer) GetAlbum(context.Context, *GetAlbumRequest) (*GetAlbumResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetAlbum not implemented") -} -func (UnimplementedMetadataServiceServer) GetArtistAlbums(context.Context, *GetArtistAlbumsRequest) (*GetArtistAlbumsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetArtistAlbums not implemented") -} -func (UnimplementedMetadataServiceServer) GetTrack(context.Context, *GetTrackRequest) (*GetTrackResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetTrack not implemented") -} -func (UnimplementedMetadataServiceServer) GetAlbumTracks(context.Context, *GetAlbumTracksRequest) (*GetAlbumTracksResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetAlbumTracks not implemented") -} -func (UnimplementedMetadataServiceServer) SearchAlbums(context.Context, *SearchAlbumsRequest) (*SearchAlbumsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SearchAlbums not implemented") -} -func (UnimplementedMetadataServiceServer) SyncArtist(context.Context, *SyncArtistRequest) (*SyncArtistResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SyncArtist not implemented") -} -func (UnimplementedMetadataServiceServer) mustEmbedUnimplementedMetadataServiceServer() {} -func (UnimplementedMetadataServiceServer) testEmbeddedByValue() {} - -// UnsafeMetadataServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to MetadataServiceServer will -// result in compilation errors. -type UnsafeMetadataServiceServer interface { - mustEmbedUnimplementedMetadataServiceServer() -} - -func RegisterMetadataServiceServer(s grpc.ServiceRegistrar, srv MetadataServiceServer) { - // If the following call panics, it indicates UnimplementedMetadataServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&MetadataService_ServiceDesc, srv) -} - -func _MetadataService_GetArtist_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetArtistRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).GetArtist(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_GetArtist_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).GetArtist(ctx, req.(*GetArtistRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_SearchArtists_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SearchArtistsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).SearchArtists(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_SearchArtists_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).SearchArtists(ctx, req.(*SearchArtistsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_GetAlbum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetAlbumRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).GetAlbum(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_GetAlbum_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).GetAlbum(ctx, req.(*GetAlbumRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_GetArtistAlbums_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetArtistAlbumsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).GetArtistAlbums(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_GetArtistAlbums_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).GetArtistAlbums(ctx, req.(*GetArtistAlbumsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_GetTrack_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetTrackRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).GetTrack(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_GetTrack_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).GetTrack(ctx, req.(*GetTrackRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_GetAlbumTracks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetAlbumTracksRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).GetAlbumTracks(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_GetAlbumTracks_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).GetAlbumTracks(ctx, req.(*GetAlbumTracksRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_SearchAlbums_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SearchAlbumsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).SearchAlbums(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_SearchAlbums_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).SearchAlbums(ctx, req.(*SearchAlbumsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_SyncArtist_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SyncArtistRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).SyncArtist(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_SyncArtist_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).SyncArtist(ctx, req.(*SyncArtistRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// MetadataService_ServiceDesc is the grpc.ServiceDesc for MetadataService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var MetadataService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "metadata.v1.MetadataService", - HandlerType: (*MetadataServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetArtist", - Handler: _MetadataService_GetArtist_Handler, - }, - { - MethodName: "SearchArtists", - Handler: _MetadataService_SearchArtists_Handler, - }, - { - MethodName: "GetAlbum", - Handler: _MetadataService_GetAlbum_Handler, - }, - { - MethodName: "GetArtistAlbums", - Handler: _MetadataService_GetArtistAlbums_Handler, - }, - { - MethodName: "GetTrack", - Handler: _MetadataService_GetTrack_Handler, - }, - { - MethodName: "GetAlbumTracks", - Handler: _MetadataService_GetAlbumTracks_Handler, - }, - { - MethodName: "SearchAlbums", - Handler: _MetadataService_SearchAlbums_Handler, - }, - { - MethodName: "SyncArtist", - Handler: _MetadataService_SyncArtist_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "metadata/v1/metadata.proto", -} diff --git a/gen/music_agregator/hello/v1/service.pb.go b/gen/music_agregator/hello/v1/service.pb.go deleted file mode 100644 index 6d91364..0000000 --- a/gen/music_agregator/hello/v1/service.pb.go +++ /dev/null @@ -1,252 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc (unknown) -// source: music_agregator/hello/v1/service.proto - -package hello - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type PingRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PingRequest) Reset() { - *x = PingRequest{} - mi := &file_music_agregator_hello_v1_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PingRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PingRequest) ProtoMessage() {} - -func (x *PingRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_hello_v1_service_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. -func (*PingRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_hello_v1_service_proto_rawDescGZIP(), []int{0} -} - -type PongResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PongResponse) Reset() { - *x = PongResponse{} - mi := &file_music_agregator_hello_v1_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PongResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PongResponse) ProtoMessage() {} - -func (x *PongResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_hello_v1_service_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PongResponse.ProtoReflect.Descriptor instead. -func (*PongResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_hello_v1_service_proto_rawDescGZIP(), []int{1} -} - -type EchoRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *EchoRequest) Reset() { - *x = EchoRequest{} - mi := &file_music_agregator_hello_v1_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *EchoRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EchoRequest) ProtoMessage() {} - -func (x *EchoRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_hello_v1_service_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EchoRequest.ProtoReflect.Descriptor instead. -func (*EchoRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_hello_v1_service_proto_rawDescGZIP(), []int{2} -} - -func (x *EchoRequest) GetMsg() string { - if x != nil { - return x.Msg - } - return "" -} - -type EchoResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Response string `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *EchoResponse) Reset() { - *x = EchoResponse{} - mi := &file_music_agregator_hello_v1_service_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *EchoResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EchoResponse) ProtoMessage() {} - -func (x *EchoResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_hello_v1_service_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EchoResponse.ProtoReflect.Descriptor instead. -func (*EchoResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_hello_v1_service_proto_rawDescGZIP(), []int{3} -} - -func (x *EchoResponse) GetResponse() string { - if x != nil { - return x.Response - } - return "" -} - -var File_music_agregator_hello_v1_service_proto protoreflect.FileDescriptor - -const file_music_agregator_hello_v1_service_proto_rawDesc = "" + - "\n" + - "&music_agregator/hello/v1/service.proto\x12\x18music_agregator.hello.v1\"\r\n" + - "\vPingRequest\"\x0e\n" + - "\fPongResponse\"\x1f\n" + - "\vEchoRequest\x12\x10\n" + - "\x03msg\x18\x01 \x01(\tR\x03msg\"*\n" + - "\fEchoResponse\x12\x1a\n" + - "\bresponse\x18\x01 \x01(\tR\bresponse2\xc0\x01\n" + - "\fHelloService\x12W\n" + - "\x04Ping\x12%.music_agregator.hello.v1.PingRequest\x1a&.music_agregator.hello.v1.PongResponse\"\x00\x12W\n" + - "\x04Echo\x12%.music_agregator.hello.v1.EchoRequest\x1a&.music_agregator.hello.v1.EchoResponse\"\x00B:Z8homelab.lan/music-agregator/gen/music_agregator/v1/hellob\x06proto3" - -var ( - file_music_agregator_hello_v1_service_proto_rawDescOnce sync.Once - file_music_agregator_hello_v1_service_proto_rawDescData []byte -) - -func file_music_agregator_hello_v1_service_proto_rawDescGZIP() []byte { - file_music_agregator_hello_v1_service_proto_rawDescOnce.Do(func() { - file_music_agregator_hello_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_music_agregator_hello_v1_service_proto_rawDesc), len(file_music_agregator_hello_v1_service_proto_rawDesc))) - }) - return file_music_agregator_hello_v1_service_proto_rawDescData -} - -var file_music_agregator_hello_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_music_agregator_hello_v1_service_proto_goTypes = []any{ - (*PingRequest)(nil), // 0: music_agregator.hello.v1.PingRequest - (*PongResponse)(nil), // 1: music_agregator.hello.v1.PongResponse - (*EchoRequest)(nil), // 2: music_agregator.hello.v1.EchoRequest - (*EchoResponse)(nil), // 3: music_agregator.hello.v1.EchoResponse -} -var file_music_agregator_hello_v1_service_proto_depIdxs = []int32{ - 0, // 0: music_agregator.hello.v1.HelloService.Ping:input_type -> music_agregator.hello.v1.PingRequest - 2, // 1: music_agregator.hello.v1.HelloService.Echo:input_type -> music_agregator.hello.v1.EchoRequest - 1, // 2: music_agregator.hello.v1.HelloService.Ping:output_type -> music_agregator.hello.v1.PongResponse - 3, // 3: music_agregator.hello.v1.HelloService.Echo:output_type -> music_agregator.hello.v1.EchoResponse - 2, // [2:4] is the sub-list for method output_type - 0, // [0:2] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_music_agregator_hello_v1_service_proto_init() } -func file_music_agregator_hello_v1_service_proto_init() { - if File_music_agregator_hello_v1_service_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_music_agregator_hello_v1_service_proto_rawDesc), len(file_music_agregator_hello_v1_service_proto_rawDesc)), - NumEnums: 0, - NumMessages: 4, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_music_agregator_hello_v1_service_proto_goTypes, - DependencyIndexes: file_music_agregator_hello_v1_service_proto_depIdxs, - MessageInfos: file_music_agregator_hello_v1_service_proto_msgTypes, - }.Build() - File_music_agregator_hello_v1_service_proto = out.File - file_music_agregator_hello_v1_service_proto_goTypes = nil - file_music_agregator_hello_v1_service_proto_depIdxs = nil -} diff --git a/gen/music_agregator/hello/v1/service_grpc.pb.go b/gen/music_agregator/hello/v1/service_grpc.pb.go deleted file mode 100644 index 99f8568..0000000 --- a/gen/music_agregator/hello/v1/service_grpc.pb.go +++ /dev/null @@ -1,159 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.1 -// - protoc (unknown) -// source: music_agregator/hello/v1/service.proto - -package hello - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - HelloService_Ping_FullMethodName = "/music_agregator.hello.v1.HelloService/Ping" - HelloService_Echo_FullMethodName = "/music_agregator.hello.v1.HelloService/Echo" -) - -// HelloServiceClient is the client API for HelloService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type HelloServiceClient interface { - Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error) - Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) -} - -type helloServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewHelloServiceClient(cc grpc.ClientConnInterface) HelloServiceClient { - return &helloServiceClient{cc} -} - -func (c *helloServiceClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(PongResponse) - err := c.cc.Invoke(ctx, HelloService_Ping_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *helloServiceClient) Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(EchoResponse) - err := c.cc.Invoke(ctx, HelloService_Echo_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -// HelloServiceServer is the server API for HelloService service. -// All implementations must embed UnimplementedHelloServiceServer -// for forward compatibility. -type HelloServiceServer interface { - Ping(context.Context, *PingRequest) (*PongResponse, error) - Echo(context.Context, *EchoRequest) (*EchoResponse, error) - mustEmbedUnimplementedHelloServiceServer() -} - -// UnimplementedHelloServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedHelloServiceServer struct{} - -func (UnimplementedHelloServiceServer) Ping(context.Context, *PingRequest) (*PongResponse, error) { - return nil, status.Error(codes.Unimplemented, "method Ping not implemented") -} -func (UnimplementedHelloServiceServer) Echo(context.Context, *EchoRequest) (*EchoResponse, error) { - return nil, status.Error(codes.Unimplemented, "method Echo not implemented") -} -func (UnimplementedHelloServiceServer) mustEmbedUnimplementedHelloServiceServer() {} -func (UnimplementedHelloServiceServer) testEmbeddedByValue() {} - -// UnsafeHelloServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to HelloServiceServer will -// result in compilation errors. -type UnsafeHelloServiceServer interface { - mustEmbedUnimplementedHelloServiceServer() -} - -func RegisterHelloServiceServer(s grpc.ServiceRegistrar, srv HelloServiceServer) { - // If the following call panics, it indicates UnimplementedHelloServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&HelloService_ServiceDesc, srv) -} - -func _HelloService_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PingRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(HelloServiceServer).Ping(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: HelloService_Ping_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(HelloServiceServer).Ping(ctx, req.(*PingRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _HelloService_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(EchoRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(HelloServiceServer).Echo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: HelloService_Echo_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(HelloServiceServer).Echo(ctx, req.(*EchoRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// HelloService_ServiceDesc is the grpc.ServiceDesc for HelloService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var HelloService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "music_agregator.hello.v1.HelloService", - HandlerType: (*HelloServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Ping", - Handler: _HelloService_Ping_Handler, - }, - { - MethodName: "Echo", - Handler: _HelloService_Echo_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "music_agregator/hello/v1/service.proto", -} diff --git a/gen/music_agregator/indexer/v1/indexer.pb.go b/gen/music_agregator/indexer/v1/indexer.pb.go deleted file mode 100644 index aeba0e1..0000000 --- a/gen/music_agregator/indexer/v1/indexer.pb.go +++ /dev/null @@ -1,1179 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc (unknown) -// source: music_agregator/indexer/v1/indexer.proto - -package indexer - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type SearchRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` - Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` - Tracker string `protobuf:"bytes,3,opt,name=tracker,proto3" json:"tracker,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchRequest) Reset() { - *x = SearchRequest{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchRequest) ProtoMessage() {} - -func (x *SearchRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchRequest.ProtoReflect.Descriptor instead. -func (*SearchRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{0} -} - -func (x *SearchRequest) GetQuery() string { - if x != nil { - return x.Query - } - return "" -} - -func (x *SearchRequest) GetLimit() int32 { - if x != nil { - return x.Limit - } - return 0 -} - -func (x *SearchRequest) GetTracker() string { - if x != nil { - return x.Tracker - } - return "" -} - -type SearchResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result []*SearchItem `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchResponse) Reset() { - *x = SearchResponse{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchResponse) ProtoMessage() {} - -func (x *SearchResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchResponse.ProtoReflect.Descriptor instead. -func (*SearchResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{1} -} - -func (x *SearchResponse) GetResult() []*SearchItem { - if x != nil { - return x.Result - } - return nil -} - -type SearchItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` - DownloadLink string `protobuf:"bytes,2,opt,name=download_link,json=downloadLink,proto3" json:"download_link,omitempty"` - TorrentPageUrl string `protobuf:"bytes,3,opt,name=torrent_page_url,json=torrentPageUrl,proto3" json:"torrent_page_url,omitempty"` - PubDate string `protobuf:"bytes,4,opt,name=pub_date,json=pubDate,proto3" json:"pub_date,omitempty"` - Size int64 `protobuf:"varint,5,opt,name=size,proto3" json:"size,omitempty"` - Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` - Categories []string `protobuf:"bytes,7,rep,name=categories,proto3" json:"categories,omitempty"` - Enclosure *Enclosure `protobuf:"bytes,8,opt,name=enclosure,proto3" json:"enclosure,omitempty"` - TorznabAttrs []*TorznabAttr `protobuf:"bytes,9,rep,name=torznab_attrs,json=torznabAttrs,proto3" json:"torznab_attrs,omitempty"` - Release *Release `protobuf:"bytes,10,opt,name=release,proto3" json:"release,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchItem) Reset() { - *x = SearchItem{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchItem) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchItem) ProtoMessage() {} - -func (x *SearchItem) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchItem.ProtoReflect.Descriptor instead. -func (*SearchItem) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{2} -} - -func (x *SearchItem) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *SearchItem) GetDownloadLink() string { - if x != nil { - return x.DownloadLink - } - return "" -} - -func (x *SearchItem) GetTorrentPageUrl() string { - if x != nil { - return x.TorrentPageUrl - } - return "" -} - -func (x *SearchItem) GetPubDate() string { - if x != nil { - return x.PubDate - } - return "" -} - -func (x *SearchItem) GetSize() int64 { - if x != nil { - return x.Size - } - return 0 -} - -func (x *SearchItem) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *SearchItem) GetCategories() []string { - if x != nil { - return x.Categories - } - return nil -} - -func (x *SearchItem) GetEnclosure() *Enclosure { - if x != nil { - return x.Enclosure - } - return nil -} - -func (x *SearchItem) GetTorznabAttrs() []*TorznabAttr { - if x != nil { - return x.TorznabAttrs - } - return nil -} - -func (x *SearchItem) GetRelease() *Release { - if x != nil { - return x.Release - } - return nil -} - -type Release struct { - state protoimpl.MessageState `protogen:"open.v1"` - RawTitle string `protobuf:"bytes,1,opt,name=raw_title,json=rawTitle,proto3" json:"raw_title,omitempty"` - Artist string `protobuf:"bytes,2,opt,name=artist,proto3" json:"artist,omitempty"` - Album string `protobuf:"bytes,3,opt,name=album,proto3" json:"album,omitempty"` - Year int32 `protobuf:"varint,4,opt,name=year,proto3" json:"year,omitempty"` - YearEnd int32 `protobuf:"varint,5,opt,name=year_end,json=yearEnd,proto3" json:"year_end,omitempty"` - Type string `protobuf:"bytes,6,opt,name=type,proto3" json:"type,omitempty"` - Genres []string `protobuf:"bytes,7,rep,name=genres,proto3" json:"genres,omitempty"` - Format string `protobuf:"bytes,8,opt,name=format,proto3" json:"format,omitempty"` - Source string `protobuf:"bytes,9,opt,name=source,proto3" json:"source,omitempty"` - Bitrate string `protobuf:"bytes,10,opt,name=bitrate,proto3" json:"bitrate,omitempty"` - BitDepth int32 `protobuf:"varint,11,opt,name=bit_depth,json=bitDepth,proto3" json:"bit_depth,omitempty"` - SampleRate int32 `protobuf:"varint,12,opt,name=sample_rate,json=sampleRate,proto3" json:"sample_rate,omitempty"` - RipType string `protobuf:"bytes,13,opt,name=rip_type,json=ripType,proto3" json:"rip_type,omitempty"` - ReleaseCount int32 `protobuf:"varint,14,opt,name=release_count,json=releaseCount,proto3" json:"release_count,omitempty"` - Tags []string `protobuf:"bytes,15,rep,name=tags,proto3" json:"tags,omitempty"` - Label string `protobuf:"bytes,16,opt,name=label,proto3" json:"label,omitempty"` - CatalogNum string `protobuf:"bytes,17,opt,name=catalog_num,json=catalogNum,proto3" json:"catalog_num,omitempty"` - ParsedSuccessfully bool `protobuf:"varint,18,opt,name=parsed_successfully,json=parsedSuccessfully,proto3" json:"parsed_successfully,omitempty"` - ParseErrors []string `protobuf:"bytes,19,rep,name=parse_errors,json=parseErrors,proto3" json:"parse_errors,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Release) Reset() { - *x = Release{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Release) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Release) ProtoMessage() {} - -func (x *Release) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Release.ProtoReflect.Descriptor instead. -func (*Release) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{3} -} - -func (x *Release) GetRawTitle() string { - if x != nil { - return x.RawTitle - } - return "" -} - -func (x *Release) GetArtist() string { - if x != nil { - return x.Artist - } - return "" -} - -func (x *Release) GetAlbum() string { - if x != nil { - return x.Album - } - return "" -} - -func (x *Release) GetYear() int32 { - if x != nil { - return x.Year - } - return 0 -} - -func (x *Release) GetYearEnd() int32 { - if x != nil { - return x.YearEnd - } - return 0 -} - -func (x *Release) GetType() string { - if x != nil { - return x.Type - } - return "" -} - -func (x *Release) GetGenres() []string { - if x != nil { - return x.Genres - } - return nil -} - -func (x *Release) GetFormat() string { - if x != nil { - return x.Format - } - return "" -} - -func (x *Release) GetSource() string { - if x != nil { - return x.Source - } - return "" -} - -func (x *Release) GetBitrate() string { - if x != nil { - return x.Bitrate - } - return "" -} - -func (x *Release) GetBitDepth() int32 { - if x != nil { - return x.BitDepth - } - return 0 -} - -func (x *Release) GetSampleRate() int32 { - if x != nil { - return x.SampleRate - } - return 0 -} - -func (x *Release) GetRipType() string { - if x != nil { - return x.RipType - } - return "" -} - -func (x *Release) GetReleaseCount() int32 { - if x != nil { - return x.ReleaseCount - } - return 0 -} - -func (x *Release) GetTags() []string { - if x != nil { - return x.Tags - } - return nil -} - -func (x *Release) GetLabel() string { - if x != nil { - return x.Label - } - return "" -} - -func (x *Release) GetCatalogNum() string { - if x != nil { - return x.CatalogNum - } - return "" -} - -func (x *Release) GetParsedSuccessfully() bool { - if x != nil { - return x.ParsedSuccessfully - } - return false -} - -func (x *Release) GetParseErrors() []string { - if x != nil { - return x.ParseErrors - } - return nil -} - -type Enclosure struct { - state protoimpl.MessageState `protogen:"open.v1"` - Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` - Length int64 `protobuf:"varint,2,opt,name=length,proto3" json:"length,omitempty"` - Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Enclosure) Reset() { - *x = Enclosure{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Enclosure) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Enclosure) ProtoMessage() {} - -func (x *Enclosure) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Enclosure.ProtoReflect.Descriptor instead. -func (*Enclosure) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{4} -} - -func (x *Enclosure) GetUrl() string { - if x != nil { - return x.Url - } - return "" -} - -func (x *Enclosure) GetLength() int64 { - if x != nil { - return x.Length - } - return 0 -} - -func (x *Enclosure) GetType() string { - if x != nil { - return x.Type - } - return "" -} - -type TorznabAttr struct { - state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TorznabAttr) Reset() { - *x = TorznabAttr{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TorznabAttr) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TorznabAttr) ProtoMessage() {} - -func (x *TorznabAttr) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TorznabAttr.ProtoReflect.Descriptor instead. -func (*TorznabAttr) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{5} -} - -func (x *TorznabAttr) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *TorznabAttr) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type CapabilitiesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Indexer string `protobuf:"bytes,1,opt,name=indexer,proto3" json:"indexer,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CapabilitiesRequest) Reset() { - *x = CapabilitiesRequest{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CapabilitiesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CapabilitiesRequest) ProtoMessage() {} - -func (x *CapabilitiesRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CapabilitiesRequest.ProtoReflect.Descriptor instead. -func (*CapabilitiesRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{6} -} - -func (x *CapabilitiesRequest) GetIndexer() string { - if x != nil { - return x.Indexer - } - return "" -} - -type CapabilitiesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Server *Server `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` - Limits *Limits `protobuf:"bytes,2,opt,name=limits,proto3" json:"limits,omitempty"` - Searching *Searching `protobuf:"bytes,3,opt,name=searching,proto3" json:"searching,omitempty"` - Categories []*Category `protobuf:"bytes,4,rep,name=categories,proto3" json:"categories,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CapabilitiesResponse) Reset() { - *x = CapabilitiesResponse{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CapabilitiesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CapabilitiesResponse) ProtoMessage() {} - -func (x *CapabilitiesResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CapabilitiesResponse.ProtoReflect.Descriptor instead. -func (*CapabilitiesResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{7} -} - -func (x *CapabilitiesResponse) GetServer() *Server { - if x != nil { - return x.Server - } - return nil -} - -func (x *CapabilitiesResponse) GetLimits() *Limits { - if x != nil { - return x.Limits - } - return nil -} - -func (x *CapabilitiesResponse) GetSearching() *Searching { - if x != nil { - return x.Searching - } - return nil -} - -func (x *CapabilitiesResponse) GetCategories() []*Category { - if x != nil { - return x.Categories - } - return nil -} - -type Server struct { - state protoimpl.MessageState `protogen:"open.v1"` - Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Server) Reset() { - *x = Server{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Server) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Server) ProtoMessage() {} - -func (x *Server) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Server.ProtoReflect.Descriptor instead. -func (*Server) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{8} -} - -func (x *Server) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -type Limits struct { - state protoimpl.MessageState `protogen:"open.v1"` - Default int32 `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty"` - Max int32 `protobuf:"varint,2,opt,name=max,proto3" json:"max,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Limits) Reset() { - *x = Limits{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Limits) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Limits) ProtoMessage() {} - -func (x *Limits) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Limits.ProtoReflect.Descriptor instead. -func (*Limits) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{9} -} - -func (x *Limits) GetDefault() int32 { - if x != nil { - return x.Default - } - return 0 -} - -func (x *Limits) GetMax() int32 { - if x != nil { - return x.Max - } - return 0 -} - -type Searching struct { - state protoimpl.MessageState `protogen:"open.v1"` - Search *SearchCapability `protobuf:"bytes,1,opt,name=search,proto3" json:"search,omitempty"` - TvSearch *SearchCapability `protobuf:"bytes,2,opt,name=tv_search,json=tvSearch,proto3" json:"tv_search,omitempty"` - MovieSearch *SearchCapability `protobuf:"bytes,3,opt,name=movie_search,json=movieSearch,proto3" json:"movie_search,omitempty"` - MusicSearch *SearchCapability `protobuf:"bytes,4,opt,name=music_search,json=musicSearch,proto3" json:"music_search,omitempty"` - AudioSearch *SearchCapability `protobuf:"bytes,5,opt,name=audio_search,json=audioSearch,proto3" json:"audio_search,omitempty"` - BookSearch *SearchCapability `protobuf:"bytes,6,opt,name=book_search,json=bookSearch,proto3" json:"book_search,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Searching) Reset() { - *x = Searching{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Searching) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Searching) ProtoMessage() {} - -func (x *Searching) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Searching.ProtoReflect.Descriptor instead. -func (*Searching) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{10} -} - -func (x *Searching) GetSearch() *SearchCapability { - if x != nil { - return x.Search - } - return nil -} - -func (x *Searching) GetTvSearch() *SearchCapability { - if x != nil { - return x.TvSearch - } - return nil -} - -func (x *Searching) GetMovieSearch() *SearchCapability { - if x != nil { - return x.MovieSearch - } - return nil -} - -func (x *Searching) GetMusicSearch() *SearchCapability { - if x != nil { - return x.MusicSearch - } - return nil -} - -func (x *Searching) GetAudioSearch() *SearchCapability { - if x != nil { - return x.AudioSearch - } - return nil -} - -func (x *Searching) GetBookSearch() *SearchCapability { - if x != nil { - return x.BookSearch - } - return nil -} - -type SearchCapability struct { - state protoimpl.MessageState `protogen:"open.v1"` - Available bool `protobuf:"varint,1,opt,name=available,proto3" json:"available,omitempty"` - SupportedParams []string `protobuf:"bytes,2,rep,name=supported_params,json=supportedParams,proto3" json:"supported_params,omitempty"` - SearchEngine string `protobuf:"bytes,3,opt,name=search_engine,json=searchEngine,proto3" json:"search_engine,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchCapability) Reset() { - *x = SearchCapability{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchCapability) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchCapability) ProtoMessage() {} - -func (x *SearchCapability) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[11] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchCapability.ProtoReflect.Descriptor instead. -func (*SearchCapability) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{11} -} - -func (x *SearchCapability) GetAvailable() bool { - if x != nil { - return x.Available - } - return false -} - -func (x *SearchCapability) GetSupportedParams() []string { - if x != nil { - return x.SupportedParams - } - return nil -} - -func (x *SearchCapability) GetSearchEngine() string { - if x != nil { - return x.SearchEngine - } - return "" -} - -type Category struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Subcats []*Subcat `protobuf:"bytes,3,rep,name=subcats,proto3" json:"subcats,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Category) Reset() { - *x = Category{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Category) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Category) ProtoMessage() {} - -func (x *Category) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[12] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Category.ProtoReflect.Descriptor instead. -func (*Category) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{12} -} - -func (x *Category) GetId() int32 { - if x != nil { - return x.Id - } - return 0 -} - -func (x *Category) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Category) GetSubcats() []*Subcat { - if x != nil { - return x.Subcats - } - return nil -} - -type Subcat struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Subcat) Reset() { - *x = Subcat{} - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Subcat) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Subcat) ProtoMessage() {} - -func (x *Subcat) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_indexer_v1_indexer_proto_msgTypes[13] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Subcat.ProtoReflect.Descriptor instead. -func (*Subcat) Descriptor() ([]byte, []int) { - return file_music_agregator_indexer_v1_indexer_proto_rawDescGZIP(), []int{13} -} - -func (x *Subcat) GetId() int32 { - if x != nil { - return x.Id - } - return 0 -} - -func (x *Subcat) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -var File_music_agregator_indexer_v1_indexer_proto protoreflect.FileDescriptor - -const file_music_agregator_indexer_v1_indexer_proto_rawDesc = "" + - "\n" + - "(music_agregator/indexer/v1/indexer.proto\x12\x1amusic_agregator.indexer.v1\"U\n" + - "\rSearchRequest\x12\x14\n" + - "\x05query\x18\x01 \x01(\tR\x05query\x12\x14\n" + - "\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x18\n" + - "\atracker\x18\x03 \x01(\tR\atracker\"P\n" + - "\x0eSearchResponse\x12>\n" + - "\x06result\x18\x01 \x03(\v2&.music_agregator.indexer.v1.SearchItemR\x06result\"\xb4\x03\n" + - "\n" + - "SearchItem\x12\x14\n" + - "\x05title\x18\x01 \x01(\tR\x05title\x12#\n" + - "\rdownload_link\x18\x02 \x01(\tR\fdownloadLink\x12(\n" + - "\x10torrent_page_url\x18\x03 \x01(\tR\x0etorrentPageUrl\x12\x19\n" + - "\bpub_date\x18\x04 \x01(\tR\apubDate\x12\x12\n" + - "\x04size\x18\x05 \x01(\x03R\x04size\x12 \n" + - "\vdescription\x18\x06 \x01(\tR\vdescription\x12\x1e\n" + - "\n" + - "categories\x18\a \x03(\tR\n" + - "categories\x12C\n" + - "\tenclosure\x18\b \x01(\v2%.music_agregator.indexer.v1.EnclosureR\tenclosure\x12L\n" + - "\rtorznab_attrs\x18\t \x03(\v2'.music_agregator.indexer.v1.TorznabAttrR\ftorznabAttrs\x12=\n" + - "\arelease\x18\n" + - " \x01(\v2#.music_agregator.indexer.v1.ReleaseR\arelease\"\x96\x04\n" + - "\aRelease\x12\x1b\n" + - "\traw_title\x18\x01 \x01(\tR\brawTitle\x12\x16\n" + - "\x06artist\x18\x02 \x01(\tR\x06artist\x12\x14\n" + - "\x05album\x18\x03 \x01(\tR\x05album\x12\x12\n" + - "\x04year\x18\x04 \x01(\x05R\x04year\x12\x19\n" + - "\byear_end\x18\x05 \x01(\x05R\ayearEnd\x12\x12\n" + - "\x04type\x18\x06 \x01(\tR\x04type\x12\x16\n" + - "\x06genres\x18\a \x03(\tR\x06genres\x12\x16\n" + - "\x06format\x18\b \x01(\tR\x06format\x12\x16\n" + - "\x06source\x18\t \x01(\tR\x06source\x12\x18\n" + - "\abitrate\x18\n" + - " \x01(\tR\abitrate\x12\x1b\n" + - "\tbit_depth\x18\v \x01(\x05R\bbitDepth\x12\x1f\n" + - "\vsample_rate\x18\f \x01(\x05R\n" + - "sampleRate\x12\x19\n" + - "\brip_type\x18\r \x01(\tR\aripType\x12#\n" + - "\rrelease_count\x18\x0e \x01(\x05R\freleaseCount\x12\x12\n" + - "\x04tags\x18\x0f \x03(\tR\x04tags\x12\x14\n" + - "\x05label\x18\x10 \x01(\tR\x05label\x12\x1f\n" + - "\vcatalog_num\x18\x11 \x01(\tR\n" + - "catalogNum\x12/\n" + - "\x13parsed_successfully\x18\x12 \x01(\bR\x12parsedSuccessfully\x12!\n" + - "\fparse_errors\x18\x13 \x03(\tR\vparseErrors\"I\n" + - "\tEnclosure\x12\x10\n" + - "\x03url\x18\x01 \x01(\tR\x03url\x12\x16\n" + - "\x06length\x18\x02 \x01(\x03R\x06length\x12\x12\n" + - "\x04type\x18\x03 \x01(\tR\x04type\"7\n" + - "\vTorznabAttr\x12\x12\n" + - "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value\"/\n" + - "\x13CapabilitiesRequest\x12\x18\n" + - "\aindexer\x18\x01 \x01(\tR\aindexer\"\x99\x02\n" + - "\x14CapabilitiesResponse\x12:\n" + - "\x06server\x18\x01 \x01(\v2\".music_agregator.indexer.v1.ServerR\x06server\x12:\n" + - "\x06limits\x18\x02 \x01(\v2\".music_agregator.indexer.v1.LimitsR\x06limits\x12C\n" + - "\tsearching\x18\x03 \x01(\v2%.music_agregator.indexer.v1.SearchingR\tsearching\x12D\n" + - "\n" + - "categories\x18\x04 \x03(\v2$.music_agregator.indexer.v1.CategoryR\n" + - "categories\"\x1e\n" + - "\x06Server\x12\x14\n" + - "\x05title\x18\x01 \x01(\tR\x05title\"4\n" + - "\x06Limits\x12\x18\n" + - "\adefault\x18\x01 \x01(\x05R\adefault\x12\x10\n" + - "\x03max\x18\x02 \x01(\x05R\x03max\"\xde\x03\n" + - "\tSearching\x12D\n" + - "\x06search\x18\x01 \x01(\v2,.music_agregator.indexer.v1.SearchCapabilityR\x06search\x12I\n" + - "\ttv_search\x18\x02 \x01(\v2,.music_agregator.indexer.v1.SearchCapabilityR\btvSearch\x12O\n" + - "\fmovie_search\x18\x03 \x01(\v2,.music_agregator.indexer.v1.SearchCapabilityR\vmovieSearch\x12O\n" + - "\fmusic_search\x18\x04 \x01(\v2,.music_agregator.indexer.v1.SearchCapabilityR\vmusicSearch\x12O\n" + - "\faudio_search\x18\x05 \x01(\v2,.music_agregator.indexer.v1.SearchCapabilityR\vaudioSearch\x12M\n" + - "\vbook_search\x18\x06 \x01(\v2,.music_agregator.indexer.v1.SearchCapabilityR\n" + - "bookSearch\"\x80\x01\n" + - "\x10SearchCapability\x12\x1c\n" + - "\tavailable\x18\x01 \x01(\bR\tavailable\x12)\n" + - "\x10supported_params\x18\x02 \x03(\tR\x0fsupportedParams\x12#\n" + - "\rsearch_engine\x18\x03 \x01(\tR\fsearchEngine\"l\n" + - "\bCategory\x12\x0e\n" + - "\x02id\x18\x01 \x01(\x05R\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12<\n" + - "\asubcats\x18\x03 \x03(\v2\".music_agregator.indexer.v1.SubcatR\asubcats\",\n" + - "\x06Subcat\x12\x0e\n" + - "\x02id\x18\x01 \x01(\x05R\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name2\xe8\x01\n" + - "\x0eIndexerService\x12a\n" + - "\x06Search\x12).music_agregator.indexer.v1.SearchRequest\x1a*.music_agregator.indexer.v1.SearchResponse\"\x00\x12s\n" + - "\fCapabilities\x12/.music_agregator.indexer.v1.CapabilitiesRequest\x1a0.music_agregator.indexer.v1.CapabilitiesResponse\"\x00B music_agregator.indexer.v1.SearchItem - 4, // 1: music_agregator.indexer.v1.SearchItem.enclosure:type_name -> music_agregator.indexer.v1.Enclosure - 5, // 2: music_agregator.indexer.v1.SearchItem.torznab_attrs:type_name -> music_agregator.indexer.v1.TorznabAttr - 3, // 3: music_agregator.indexer.v1.SearchItem.release:type_name -> music_agregator.indexer.v1.Release - 8, // 4: music_agregator.indexer.v1.CapabilitiesResponse.server:type_name -> music_agregator.indexer.v1.Server - 9, // 5: music_agregator.indexer.v1.CapabilitiesResponse.limits:type_name -> music_agregator.indexer.v1.Limits - 10, // 6: music_agregator.indexer.v1.CapabilitiesResponse.searching:type_name -> music_agregator.indexer.v1.Searching - 12, // 7: music_agregator.indexer.v1.CapabilitiesResponse.categories:type_name -> music_agregator.indexer.v1.Category - 11, // 8: music_agregator.indexer.v1.Searching.search:type_name -> music_agregator.indexer.v1.SearchCapability - 11, // 9: music_agregator.indexer.v1.Searching.tv_search:type_name -> music_agregator.indexer.v1.SearchCapability - 11, // 10: music_agregator.indexer.v1.Searching.movie_search:type_name -> music_agregator.indexer.v1.SearchCapability - 11, // 11: music_agregator.indexer.v1.Searching.music_search:type_name -> music_agregator.indexer.v1.SearchCapability - 11, // 12: music_agregator.indexer.v1.Searching.audio_search:type_name -> music_agregator.indexer.v1.SearchCapability - 11, // 13: music_agregator.indexer.v1.Searching.book_search:type_name -> music_agregator.indexer.v1.SearchCapability - 13, // 14: music_agregator.indexer.v1.Category.subcats:type_name -> music_agregator.indexer.v1.Subcat - 0, // 15: music_agregator.indexer.v1.IndexerService.Search:input_type -> music_agregator.indexer.v1.SearchRequest - 6, // 16: music_agregator.indexer.v1.IndexerService.Capabilities:input_type -> music_agregator.indexer.v1.CapabilitiesRequest - 1, // 17: music_agregator.indexer.v1.IndexerService.Search:output_type -> music_agregator.indexer.v1.SearchResponse - 7, // 18: music_agregator.indexer.v1.IndexerService.Capabilities:output_type -> music_agregator.indexer.v1.CapabilitiesResponse - 17, // [17:19] is the sub-list for method output_type - 15, // [15:17] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name -} - -func init() { file_music_agregator_indexer_v1_indexer_proto_init() } -func file_music_agregator_indexer_v1_indexer_proto_init() { - if File_music_agregator_indexer_v1_indexer_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_music_agregator_indexer_v1_indexer_proto_rawDesc), len(file_music_agregator_indexer_v1_indexer_proto_rawDesc)), - NumEnums: 0, - NumMessages: 14, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_music_agregator_indexer_v1_indexer_proto_goTypes, - DependencyIndexes: file_music_agregator_indexer_v1_indexer_proto_depIdxs, - MessageInfos: file_music_agregator_indexer_v1_indexer_proto_msgTypes, - }.Build() - File_music_agregator_indexer_v1_indexer_proto = out.File - file_music_agregator_indexer_v1_indexer_proto_goTypes = nil - file_music_agregator_indexer_v1_indexer_proto_depIdxs = nil -} diff --git a/gen/music_agregator/indexer/v1/indexer_grpc.pb.go b/gen/music_agregator/indexer/v1/indexer_grpc.pb.go deleted file mode 100644 index 79df169..0000000 --- a/gen/music_agregator/indexer/v1/indexer_grpc.pb.go +++ /dev/null @@ -1,159 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.1 -// - protoc (unknown) -// source: music_agregator/indexer/v1/indexer.proto - -package indexer - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - IndexerService_Search_FullMethodName = "/music_agregator.indexer.v1.IndexerService/Search" - IndexerService_Capabilities_FullMethodName = "/music_agregator.indexer.v1.IndexerService/Capabilities" -) - -// IndexerServiceClient is the client API for IndexerService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type IndexerServiceClient interface { - Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) - Capabilities(ctx context.Context, in *CapabilitiesRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error) -} - -type indexerServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewIndexerServiceClient(cc grpc.ClientConnInterface) IndexerServiceClient { - return &indexerServiceClient{cc} -} - -func (c *indexerServiceClient) Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SearchResponse) - err := c.cc.Invoke(ctx, IndexerService_Search_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *indexerServiceClient) Capabilities(ctx context.Context, in *CapabilitiesRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(CapabilitiesResponse) - err := c.cc.Invoke(ctx, IndexerService_Capabilities_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -// IndexerServiceServer is the server API for IndexerService service. -// All implementations must embed UnimplementedIndexerServiceServer -// for forward compatibility. -type IndexerServiceServer interface { - Search(context.Context, *SearchRequest) (*SearchResponse, error) - Capabilities(context.Context, *CapabilitiesRequest) (*CapabilitiesResponse, error) - mustEmbedUnimplementedIndexerServiceServer() -} - -// UnimplementedIndexerServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedIndexerServiceServer struct{} - -func (UnimplementedIndexerServiceServer) Search(context.Context, *SearchRequest) (*SearchResponse, error) { - return nil, status.Error(codes.Unimplemented, "method Search not implemented") -} -func (UnimplementedIndexerServiceServer) Capabilities(context.Context, *CapabilitiesRequest) (*CapabilitiesResponse, error) { - return nil, status.Error(codes.Unimplemented, "method Capabilities not implemented") -} -func (UnimplementedIndexerServiceServer) mustEmbedUnimplementedIndexerServiceServer() {} -func (UnimplementedIndexerServiceServer) testEmbeddedByValue() {} - -// UnsafeIndexerServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to IndexerServiceServer will -// result in compilation errors. -type UnsafeIndexerServiceServer interface { - mustEmbedUnimplementedIndexerServiceServer() -} - -func RegisterIndexerServiceServer(s grpc.ServiceRegistrar, srv IndexerServiceServer) { - // If the following call panics, it indicates UnimplementedIndexerServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&IndexerService_ServiceDesc, srv) -} - -func _IndexerService_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SearchRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(IndexerServiceServer).Search(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: IndexerService_Search_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(IndexerServiceServer).Search(ctx, req.(*SearchRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _IndexerService_Capabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CapabilitiesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(IndexerServiceServer).Capabilities(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: IndexerService_Capabilities_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(IndexerServiceServer).Capabilities(ctx, req.(*CapabilitiesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// IndexerService_ServiceDesc is the grpc.ServiceDesc for IndexerService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var IndexerService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "music_agregator.indexer.v1.IndexerService", - HandlerType: (*IndexerServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Search", - Handler: _IndexerService_Search_Handler, - }, - { - MethodName: "Capabilities", - Handler: _IndexerService_Capabilities_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "music_agregator/indexer/v1/indexer.proto", -} diff --git a/gen/music_agregator/metadata/v1/metadata.pb.go b/gen/music_agregator/metadata/v1/metadata.pb.go deleted file mode 100644 index d0c7691..0000000 --- a/gen/music_agregator/metadata/v1/metadata.pb.go +++ /dev/null @@ -1,60 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc (unknown) -// source: music_agregator/metadata/v1/metadata.proto - -package metadata - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -var File_music_agregator_metadata_v1_metadata_proto protoreflect.FileDescriptor - -const file_music_agregator_metadata_v1_metadata_proto_rawDesc = "" + - "\n" + - "*music_agregator/metadata/v1/metadata.proto\x12\x1bmusic_agregator.metadata.v12\x11\n" + - "\x0fMetadataServiceB=Z;homelab.lan/music-agregator/gen/music_agregator/v1/metadatab\x06proto3" - -var file_music_agregator_metadata_v1_metadata_proto_goTypes = []any{} -var file_music_agregator_metadata_v1_metadata_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_music_agregator_metadata_v1_metadata_proto_init() } -func file_music_agregator_metadata_v1_metadata_proto_init() { - if File_music_agregator_metadata_v1_metadata_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_music_agregator_metadata_v1_metadata_proto_rawDesc), len(file_music_agregator_metadata_v1_metadata_proto_rawDesc)), - NumEnums: 0, - NumMessages: 0, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_music_agregator_metadata_v1_metadata_proto_goTypes, - DependencyIndexes: file_music_agregator_metadata_v1_metadata_proto_depIdxs, - }.Build() - File_music_agregator_metadata_v1_metadata_proto = out.File - file_music_agregator_metadata_v1_metadata_proto_goTypes = nil - file_music_agregator_metadata_v1_metadata_proto_depIdxs = nil -} diff --git a/gen/music_agregator/metadata/v1/metadata_grpc.pb.go b/gen/music_agregator/metadata/v1/metadata_grpc.pb.go deleted file mode 100644 index ebbbb0c..0000000 --- a/gen/music_agregator/metadata/v1/metadata_grpc.pb.go +++ /dev/null @@ -1,76 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.1 -// - protoc (unknown) -// source: music_agregator/metadata/v1/metadata.proto - -package metadata - -import ( - grpc "google.golang.org/grpc" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -// MetadataServiceClient is the client API for MetadataService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type MetadataServiceClient interface { -} - -type metadataServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewMetadataServiceClient(cc grpc.ClientConnInterface) MetadataServiceClient { - return &metadataServiceClient{cc} -} - -// MetadataServiceServer is the server API for MetadataService service. -// All implementations must embed UnimplementedMetadataServiceServer -// for forward compatibility. -type MetadataServiceServer interface { - mustEmbedUnimplementedMetadataServiceServer() -} - -// UnimplementedMetadataServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedMetadataServiceServer struct{} - -func (UnimplementedMetadataServiceServer) mustEmbedUnimplementedMetadataServiceServer() {} -func (UnimplementedMetadataServiceServer) testEmbeddedByValue() {} - -// UnsafeMetadataServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to MetadataServiceServer will -// result in compilation errors. -type UnsafeMetadataServiceServer interface { - mustEmbedUnimplementedMetadataServiceServer() -} - -func RegisterMetadataServiceServer(s grpc.ServiceRegistrar, srv MetadataServiceServer) { - // If the following call panics, it indicates UnimplementedMetadataServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&MetadataService_ServiceDesc, srv) -} - -// MetadataService_ServiceDesc is the grpc.ServiceDesc for MetadataService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var MetadataService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "music_agregator.metadata.v1.MetadataService", - HandlerType: (*MetadataServiceServer)(nil), - Methods: []grpc.MethodDesc{}, - Streams: []grpc.StreamDesc{}, - Metadata: "music_agregator/metadata/v1/metadata.proto", -} diff --git a/gen/music_agregator/torrent/v1/torrent.pb.go b/gen/music_agregator/torrent/v1/torrent.pb.go deleted file mode 100644 index 314d69e..0000000 --- a/gen/music_agregator/torrent/v1/torrent.pb.go +++ /dev/null @@ -1,713 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc (unknown) -// source: music_agregator/torrent/v1/torrent.proto - -package torrent - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ListRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - ClientName string `protobuf:"bytes,1,opt,name=client_name,json=clientName,proto3" json:"client_name,omitempty"` - Filter string `protobuf:"bytes,2,opt,name=filter,proto3" json:"filter,omitempty"` - Category string `protobuf:"bytes,3,opt,name=category,proto3" json:"category,omitempty"` - Tag string `protobuf:"bytes,4,opt,name=tag,proto3" json:"tag,omitempty"` - Sort string `protobuf:"bytes,5,opt,name=sort,proto3" json:"sort,omitempty"` - Reverse bool `protobuf:"varint,6,opt,name=reverse,proto3" json:"reverse,omitempty"` - Limit int32 `protobuf:"varint,7,opt,name=limit,proto3" json:"limit,omitempty"` - Offset int32 `protobuf:"varint,8,opt,name=offset,proto3" json:"offset,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListRequest) Reset() { - *x = ListRequest{} - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListRequest) ProtoMessage() {} - -func (x *ListRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListRequest.ProtoReflect.Descriptor instead. -func (*ListRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_torrent_v1_torrent_proto_rawDescGZIP(), []int{0} -} - -func (x *ListRequest) GetClientName() string { - if x != nil { - return x.ClientName - } - return "" -} - -func (x *ListRequest) GetFilter() string { - if x != nil { - return x.Filter - } - return "" -} - -func (x *ListRequest) GetCategory() string { - if x != nil { - return x.Category - } - return "" -} - -func (x *ListRequest) GetTag() string { - if x != nil { - return x.Tag - } - return "" -} - -func (x *ListRequest) GetSort() string { - if x != nil { - return x.Sort - } - return "" -} - -func (x *ListRequest) GetReverse() bool { - if x != nil { - return x.Reverse - } - return false -} - -func (x *ListRequest) GetLimit() int32 { - if x != nil { - return x.Limit - } - return 0 -} - -func (x *ListRequest) GetOffset() int32 { - if x != nil { - return x.Offset - } - return 0 -} - -type ListResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Items []*ListItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListResponse) Reset() { - *x = ListResponse{} - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListResponse) ProtoMessage() {} - -func (x *ListResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListResponse.ProtoReflect.Descriptor instead. -func (*ListResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_torrent_v1_torrent_proto_rawDescGZIP(), []int{1} -} - -func (x *ListResponse) GetItems() []*ListItem { - if x != nil { - return x.Items - } - return nil -} - -type ListItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"` - Progress float64 `protobuf:"fixed64,4,opt,name=progress,proto3" json:"progress,omitempty"` - Dlspeed int64 `protobuf:"varint,5,opt,name=dlspeed,proto3" json:"dlspeed,omitempty"` - Upspeed int64 `protobuf:"varint,6,opt,name=upspeed,proto3" json:"upspeed,omitempty"` - NumSeeds int32 `protobuf:"varint,7,opt,name=num_seeds,json=numSeeds,proto3" json:"num_seeds,omitempty"` - NumLeechs int32 `protobuf:"varint,8,opt,name=num_leechs,json=numLeechs,proto3" json:"num_leechs,omitempty"` - State string `protobuf:"bytes,9,opt,name=state,proto3" json:"state,omitempty"` - Eta int64 `protobuf:"varint,10,opt,name=eta,proto3" json:"eta,omitempty"` - Ratio float64 `protobuf:"fixed64,11,opt,name=ratio,proto3" json:"ratio,omitempty"` - Category string `protobuf:"bytes,12,opt,name=category,proto3" json:"category,omitempty"` - Tags string `protobuf:"bytes,13,opt,name=tags,proto3" json:"tags,omitempty"` - AddedOn int64 `protobuf:"varint,14,opt,name=added_on,json=addedOn,proto3" json:"added_on,omitempty"` - CompletionOn int64 `protobuf:"varint,15,opt,name=completion_on,json=completionOn,proto3" json:"completion_on,omitempty"` - SavePath string `protobuf:"bytes,16,opt,name=save_path,json=savePath,proto3" json:"save_path,omitempty"` - ContentPath string `protobuf:"bytes,17,opt,name=content_path,json=contentPath,proto3" json:"content_path,omitempty"` - Downloaded int64 `protobuf:"varint,18,opt,name=downloaded,proto3" json:"downloaded,omitempty"` - Uploaded int64 `protobuf:"varint,19,opt,name=uploaded,proto3" json:"uploaded,omitempty"` - Tracker string `protobuf:"bytes,20,opt,name=tracker,proto3" json:"tracker,omitempty"` - SeedingTime int64 `protobuf:"varint,21,opt,name=seeding_time,json=seedingTime,proto3" json:"seeding_time,omitempty"` - AmountLeft int64 `protobuf:"varint,22,opt,name=amount_left,json=amountLeft,proto3" json:"amount_left,omitempty"` - Availability float64 `protobuf:"fixed64,23,opt,name=availability,proto3" json:"availability,omitempty"` - SizeFormatted string `protobuf:"bytes,100,opt,name=size_formatted,json=sizeFormatted,proto3" json:"size_formatted,omitempty"` - ProgressFormatted string `protobuf:"bytes,101,opt,name=progress_formatted,json=progressFormatted,proto3" json:"progress_formatted,omitempty"` - DlspeedFormatted string `protobuf:"bytes,102,opt,name=dlspeed_formatted,json=dlspeedFormatted,proto3" json:"dlspeed_formatted,omitempty"` - UpspeedFormatted string `protobuf:"bytes,103,opt,name=upspeed_formatted,json=upspeedFormatted,proto3" json:"upspeed_formatted,omitempty"` - AddedOnFormatted string `protobuf:"bytes,104,opt,name=added_on_formatted,json=addedOnFormatted,proto3" json:"added_on_formatted,omitempty"` - CompletionOnFormatted string `protobuf:"bytes,105,opt,name=completion_on_formatted,json=completionOnFormatted,proto3" json:"completion_on_formatted,omitempty"` - DownloadedFormatted string `protobuf:"bytes,106,opt,name=downloaded_formatted,json=downloadedFormatted,proto3" json:"downloaded_formatted,omitempty"` - UploadedFormatted string `protobuf:"bytes,107,opt,name=uploaded_formatted,json=uploadedFormatted,proto3" json:"uploaded_formatted,omitempty"` - AmountLeftFormatted string `protobuf:"bytes,108,opt,name=amount_left_formatted,json=amountLeftFormatted,proto3" json:"amount_left_formatted,omitempty"` - AvailabilityFormatted string `protobuf:"bytes,109,opt,name=availability_formatted,json=availabilityFormatted,proto3" json:"availability_formatted,omitempty"` - EtaFormatted string `protobuf:"bytes,110,opt,name=eta_formatted,json=etaFormatted,proto3" json:"eta_formatted,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListItem) Reset() { - *x = ListItem{} - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListItem) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListItem) ProtoMessage() {} - -func (x *ListItem) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListItem.ProtoReflect.Descriptor instead. -func (*ListItem) Descriptor() ([]byte, []int) { - return file_music_agregator_torrent_v1_torrent_proto_rawDescGZIP(), []int{2} -} - -func (x *ListItem) GetHash() string { - if x != nil { - return x.Hash - } - return "" -} - -func (x *ListItem) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *ListItem) GetSize() int64 { - if x != nil { - return x.Size - } - return 0 -} - -func (x *ListItem) GetProgress() float64 { - if x != nil { - return x.Progress - } - return 0 -} - -func (x *ListItem) GetDlspeed() int64 { - if x != nil { - return x.Dlspeed - } - return 0 -} - -func (x *ListItem) GetUpspeed() int64 { - if x != nil { - return x.Upspeed - } - return 0 -} - -func (x *ListItem) GetNumSeeds() int32 { - if x != nil { - return x.NumSeeds - } - return 0 -} - -func (x *ListItem) GetNumLeechs() int32 { - if x != nil { - return x.NumLeechs - } - return 0 -} - -func (x *ListItem) GetState() string { - if x != nil { - return x.State - } - return "" -} - -func (x *ListItem) GetEta() int64 { - if x != nil { - return x.Eta - } - return 0 -} - -func (x *ListItem) GetRatio() float64 { - if x != nil { - return x.Ratio - } - return 0 -} - -func (x *ListItem) GetCategory() string { - if x != nil { - return x.Category - } - return "" -} - -func (x *ListItem) GetTags() string { - if x != nil { - return x.Tags - } - return "" -} - -func (x *ListItem) GetAddedOn() int64 { - if x != nil { - return x.AddedOn - } - return 0 -} - -func (x *ListItem) GetCompletionOn() int64 { - if x != nil { - return x.CompletionOn - } - return 0 -} - -func (x *ListItem) GetSavePath() string { - if x != nil { - return x.SavePath - } - return "" -} - -func (x *ListItem) GetContentPath() string { - if x != nil { - return x.ContentPath - } - return "" -} - -func (x *ListItem) GetDownloaded() int64 { - if x != nil { - return x.Downloaded - } - return 0 -} - -func (x *ListItem) GetUploaded() int64 { - if x != nil { - return x.Uploaded - } - return 0 -} - -func (x *ListItem) GetTracker() string { - if x != nil { - return x.Tracker - } - return "" -} - -func (x *ListItem) GetSeedingTime() int64 { - if x != nil { - return x.SeedingTime - } - return 0 -} - -func (x *ListItem) GetAmountLeft() int64 { - if x != nil { - return x.AmountLeft - } - return 0 -} - -func (x *ListItem) GetAvailability() float64 { - if x != nil { - return x.Availability - } - return 0 -} - -func (x *ListItem) GetSizeFormatted() string { - if x != nil { - return x.SizeFormatted - } - return "" -} - -func (x *ListItem) GetProgressFormatted() string { - if x != nil { - return x.ProgressFormatted - } - return "" -} - -func (x *ListItem) GetDlspeedFormatted() string { - if x != nil { - return x.DlspeedFormatted - } - return "" -} - -func (x *ListItem) GetUpspeedFormatted() string { - if x != nil { - return x.UpspeedFormatted - } - return "" -} - -func (x *ListItem) GetAddedOnFormatted() string { - if x != nil { - return x.AddedOnFormatted - } - return "" -} - -func (x *ListItem) GetCompletionOnFormatted() string { - if x != nil { - return x.CompletionOnFormatted - } - return "" -} - -func (x *ListItem) GetDownloadedFormatted() string { - if x != nil { - return x.DownloadedFormatted - } - return "" -} - -func (x *ListItem) GetUploadedFormatted() string { - if x != nil { - return x.UploadedFormatted - } - return "" -} - -func (x *ListItem) GetAmountLeftFormatted() string { - if x != nil { - return x.AmountLeftFormatted - } - return "" -} - -func (x *ListItem) GetAvailabilityFormatted() string { - if x != nil { - return x.AvailabilityFormatted - } - return "" -} - -func (x *ListItem) GetEtaFormatted() string { - if x != nil { - return x.EtaFormatted - } - return "" -} - -type AddRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - DownloadUrl string `protobuf:"bytes,1,opt,name=download_url,json=downloadUrl,proto3" json:"download_url,omitempty"` - Filename string `protobuf:"bytes,2,opt,name=filename,proto3" json:"filename,omitempty"` - TorrentData []byte `protobuf:"bytes,3,opt,name=torrent_data,json=torrentData,proto3" json:"torrent_data,omitempty"` - SavePath string `protobuf:"bytes,4,opt,name=save_path,json=savePath,proto3" json:"save_path,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AddRequest) Reset() { - *x = AddRequest{} - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AddRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddRequest) ProtoMessage() {} - -func (x *AddRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddRequest.ProtoReflect.Descriptor instead. -func (*AddRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_torrent_v1_torrent_proto_rawDescGZIP(), []int{3} -} - -func (x *AddRequest) GetDownloadUrl() string { - if x != nil { - return x.DownloadUrl - } - return "" -} - -func (x *AddRequest) GetFilename() string { - if x != nil { - return x.Filename - } - return "" -} - -func (x *AddRequest) GetTorrentData() []byte { - if x != nil { - return x.TorrentData - } - return nil -} - -func (x *AddRequest) GetSavePath() string { - if x != nil { - return x.SavePath - } - return "" -} - -type AddResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Item *ListItem `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AddResponse) Reset() { - *x = AddResponse{} - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AddResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddResponse) ProtoMessage() {} - -func (x *AddResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_torrent_v1_torrent_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddResponse.ProtoReflect.Descriptor instead. -func (*AddResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_torrent_v1_torrent_proto_rawDescGZIP(), []int{4} -} - -func (x *AddResponse) GetItem() *ListItem { - if x != nil { - return x.Item - } - return nil -} - -var File_music_agregator_torrent_v1_torrent_proto protoreflect.FileDescriptor - -const file_music_agregator_torrent_v1_torrent_proto_rawDesc = "" + - "\n" + - "(music_agregator/torrent/v1/torrent.proto\x12\x1amusic_agregator.torrent.v1\"\xd0\x01\n" + - "\vListRequest\x12\x1f\n" + - "\vclient_name\x18\x01 \x01(\tR\n" + - "clientName\x12\x16\n" + - "\x06filter\x18\x02 \x01(\tR\x06filter\x12\x1a\n" + - "\bcategory\x18\x03 \x01(\tR\bcategory\x12\x10\n" + - "\x03tag\x18\x04 \x01(\tR\x03tag\x12\x12\n" + - "\x04sort\x18\x05 \x01(\tR\x04sort\x12\x18\n" + - "\areverse\x18\x06 \x01(\bR\areverse\x12\x14\n" + - "\x05limit\x18\a \x01(\x05R\x05limit\x12\x16\n" + - "\x06offset\x18\b \x01(\x05R\x06offset\"J\n" + - "\fListResponse\x12:\n" + - "\x05items\x18\x01 \x03(\v2$.music_agregator.torrent.v1.ListItemR\x05items\"\x86\t\n" + - "\bListItem\x12\x12\n" + - "\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" + - "\x04size\x18\x03 \x01(\x03R\x04size\x12\x1a\n" + - "\bprogress\x18\x04 \x01(\x01R\bprogress\x12\x18\n" + - "\adlspeed\x18\x05 \x01(\x03R\adlspeed\x12\x18\n" + - "\aupspeed\x18\x06 \x01(\x03R\aupspeed\x12\x1b\n" + - "\tnum_seeds\x18\a \x01(\x05R\bnumSeeds\x12\x1d\n" + - "\n" + - "num_leechs\x18\b \x01(\x05R\tnumLeechs\x12\x14\n" + - "\x05state\x18\t \x01(\tR\x05state\x12\x10\n" + - "\x03eta\x18\n" + - " \x01(\x03R\x03eta\x12\x14\n" + - "\x05ratio\x18\v \x01(\x01R\x05ratio\x12\x1a\n" + - "\bcategory\x18\f \x01(\tR\bcategory\x12\x12\n" + - "\x04tags\x18\r \x01(\tR\x04tags\x12\x19\n" + - "\badded_on\x18\x0e \x01(\x03R\aaddedOn\x12#\n" + - "\rcompletion_on\x18\x0f \x01(\x03R\fcompletionOn\x12\x1b\n" + - "\tsave_path\x18\x10 \x01(\tR\bsavePath\x12!\n" + - "\fcontent_path\x18\x11 \x01(\tR\vcontentPath\x12\x1e\n" + - "\n" + - "downloaded\x18\x12 \x01(\x03R\n" + - "downloaded\x12\x1a\n" + - "\buploaded\x18\x13 \x01(\x03R\buploaded\x12\x18\n" + - "\atracker\x18\x14 \x01(\tR\atracker\x12!\n" + - "\fseeding_time\x18\x15 \x01(\x03R\vseedingTime\x12\x1f\n" + - "\vamount_left\x18\x16 \x01(\x03R\n" + - "amountLeft\x12\"\n" + - "\favailability\x18\x17 \x01(\x01R\favailability\x12%\n" + - "\x0esize_formatted\x18d \x01(\tR\rsizeFormatted\x12-\n" + - "\x12progress_formatted\x18e \x01(\tR\x11progressFormatted\x12+\n" + - "\x11dlspeed_formatted\x18f \x01(\tR\x10dlspeedFormatted\x12+\n" + - "\x11upspeed_formatted\x18g \x01(\tR\x10upspeedFormatted\x12,\n" + - "\x12added_on_formatted\x18h \x01(\tR\x10addedOnFormatted\x126\n" + - "\x17completion_on_formatted\x18i \x01(\tR\x15completionOnFormatted\x121\n" + - "\x14downloaded_formatted\x18j \x01(\tR\x13downloadedFormatted\x12-\n" + - "\x12uploaded_formatted\x18k \x01(\tR\x11uploadedFormatted\x122\n" + - "\x15amount_left_formatted\x18l \x01(\tR\x13amountLeftFormatted\x125\n" + - "\x16availability_formatted\x18m \x01(\tR\x15availabilityFormatted\x12#\n" + - "\reta_formatted\x18n \x01(\tR\fetaFormatted\"\x8b\x01\n" + - "\n" + - "AddRequest\x12!\n" + - "\fdownload_url\x18\x01 \x01(\tR\vdownloadUrl\x12\x1a\n" + - "\bfilename\x18\x02 \x01(\tR\bfilename\x12!\n" + - "\ftorrent_data\x18\x03 \x01(\fR\vtorrentData\x12\x1b\n" + - "\tsave_path\x18\x04 \x01(\tR\bsavePath\"G\n" + - "\vAddResponse\x128\n" + - "\x04item\x18\x01 \x01(\v2$.music_agregator.torrent.v1.ListItemR\x04item2\xc7\x01\n" + - "\x0eTorrentService\x12[\n" + - "\x04List\x12'.music_agregator.torrent.v1.ListRequest\x1a(.music_agregator.torrent.v1.ListResponse\"\x00\x12X\n" + - "\x03Add\x12&.music_agregator.torrent.v1.AddRequest\x1a'.music_agregator.torrent.v1.AddResponse\"\x00B music_agregator.torrent.v1.ListItem - 2, // 1: music_agregator.torrent.v1.AddResponse.item:type_name -> music_agregator.torrent.v1.ListItem - 0, // 2: music_agregator.torrent.v1.TorrentService.List:input_type -> music_agregator.torrent.v1.ListRequest - 3, // 3: music_agregator.torrent.v1.TorrentService.Add:input_type -> music_agregator.torrent.v1.AddRequest - 1, // 4: music_agregator.torrent.v1.TorrentService.List:output_type -> music_agregator.torrent.v1.ListResponse - 4, // 5: music_agregator.torrent.v1.TorrentService.Add:output_type -> music_agregator.torrent.v1.AddResponse - 4, // [4:6] is the sub-list for method output_type - 2, // [2:4] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_music_agregator_torrent_v1_torrent_proto_init() } -func file_music_agregator_torrent_v1_torrent_proto_init() { - if File_music_agregator_torrent_v1_torrent_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_music_agregator_torrent_v1_torrent_proto_rawDesc), len(file_music_agregator_torrent_v1_torrent_proto_rawDesc)), - NumEnums: 0, - NumMessages: 5, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_music_agregator_torrent_v1_torrent_proto_goTypes, - DependencyIndexes: file_music_agregator_torrent_v1_torrent_proto_depIdxs, - MessageInfos: file_music_agregator_torrent_v1_torrent_proto_msgTypes, - }.Build() - File_music_agregator_torrent_v1_torrent_proto = out.File - file_music_agregator_torrent_v1_torrent_proto_goTypes = nil - file_music_agregator_torrent_v1_torrent_proto_depIdxs = nil -} diff --git a/gen/music_agregator/torrent/v1/torrent_grpc.pb.go b/gen/music_agregator/torrent/v1/torrent_grpc.pb.go deleted file mode 100644 index d312344..0000000 --- a/gen/music_agregator/torrent/v1/torrent_grpc.pb.go +++ /dev/null @@ -1,159 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.1 -// - protoc (unknown) -// source: music_agregator/torrent/v1/torrent.proto - -package torrent - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - TorrentService_List_FullMethodName = "/music_agregator.torrent.v1.TorrentService/List" - TorrentService_Add_FullMethodName = "/music_agregator.torrent.v1.TorrentService/Add" -) - -// TorrentServiceClient is the client API for TorrentService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type TorrentServiceClient interface { - List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) - Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) -} - -type torrentServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewTorrentServiceClient(cc grpc.ClientConnInterface) TorrentServiceClient { - return &torrentServiceClient{cc} -} - -func (c *torrentServiceClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ListResponse) - err := c.cc.Invoke(ctx, TorrentService_List_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *torrentServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(AddResponse) - err := c.cc.Invoke(ctx, TorrentService_Add_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -// TorrentServiceServer is the server API for TorrentService service. -// All implementations must embed UnimplementedTorrentServiceServer -// for forward compatibility. -type TorrentServiceServer interface { - List(context.Context, *ListRequest) (*ListResponse, error) - Add(context.Context, *AddRequest) (*AddResponse, error) - mustEmbedUnimplementedTorrentServiceServer() -} - -// UnimplementedTorrentServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedTorrentServiceServer struct{} - -func (UnimplementedTorrentServiceServer) List(context.Context, *ListRequest) (*ListResponse, error) { - return nil, status.Error(codes.Unimplemented, "method List not implemented") -} -func (UnimplementedTorrentServiceServer) Add(context.Context, *AddRequest) (*AddResponse, error) { - return nil, status.Error(codes.Unimplemented, "method Add not implemented") -} -func (UnimplementedTorrentServiceServer) mustEmbedUnimplementedTorrentServiceServer() {} -func (UnimplementedTorrentServiceServer) testEmbeddedByValue() {} - -// UnsafeTorrentServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to TorrentServiceServer will -// result in compilation errors. -type UnsafeTorrentServiceServer interface { - mustEmbedUnimplementedTorrentServiceServer() -} - -func RegisterTorrentServiceServer(s grpc.ServiceRegistrar, srv TorrentServiceServer) { - // If the following call panics, it indicates UnimplementedTorrentServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&TorrentService_ServiceDesc, srv) -} - -func _TorrentService_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TorrentServiceServer).List(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: TorrentService_List_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TorrentServiceServer).List(ctx, req.(*ListRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _TorrentService_Add_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AddRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TorrentServiceServer).Add(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: TorrentService_Add_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TorrentServiceServer).Add(ctx, req.(*AddRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// TorrentService_ServiceDesc is the grpc.ServiceDesc for TorrentService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var TorrentService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "music_agregator.torrent.v1.TorrentService", - HandlerType: (*TorrentServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "List", - Handler: _TorrentService_List_Handler, - }, - { - MethodName: "Add", - Handler: _TorrentService_Add_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "music_agregator/torrent/v1/torrent.proto", -} diff --git a/gen/music_agregator/v1/music_agregator.pb.go b/gen/music_agregator/v1/music_agregator.pb.go deleted file mode 100644 index 1cbb9b8..0000000 --- a/gen/music_agregator/v1/music_agregator.pb.go +++ /dev/null @@ -1,4364 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc (unknown) -// source: music_agregator/v1/music_agregator.proto - -package v1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type QualityType int32 - -const ( - QualityType_QUALITY_UNSPECIFIED QualityType = 0 - QualityType_QUALITY_LOSSLESS QualityType = 1 - QualityType_QUALITY_LOSSY QualityType = 2 -) - -// Enum value maps for QualityType. -var ( - QualityType_name = map[int32]string{ - 0: "QUALITY_UNSPECIFIED", - 1: "QUALITY_LOSSLESS", - 2: "QUALITY_LOSSY", - } - QualityType_value = map[string]int32{ - "QUALITY_UNSPECIFIED": 0, - "QUALITY_LOSSLESS": 1, - "QUALITY_LOSSY": 2, - } -) - -func (x QualityType) Enum() *QualityType { - p := new(QualityType) - *p = x - return p -} - -func (x QualityType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (QualityType) Descriptor() protoreflect.EnumDescriptor { - return file_music_agregator_v1_music_agregator_proto_enumTypes[0].Descriptor() -} - -func (QualityType) Type() protoreflect.EnumType { - return &file_music_agregator_v1_music_agregator_proto_enumTypes[0] -} - -func (x QualityType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use QualityType.Descriptor instead. -func (QualityType) EnumDescriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{0} -} - -type MonitorState int32 - -const ( - MonitorState_MONITOR_STATE_UNSPECIFIED MonitorState = 0 - MonitorState_MONITOR_STATE_MONITORED MonitorState = 1 - MonitorState_MONITOR_STATE_UNMONITORED MonitorState = 2 - MonitorState_MONITOR_STATE_EXCLUDED MonitorState = 3 -) - -// Enum value maps for MonitorState. -var ( - MonitorState_name = map[int32]string{ - 0: "MONITOR_STATE_UNSPECIFIED", - 1: "MONITOR_STATE_MONITORED", - 2: "MONITOR_STATE_UNMONITORED", - 3: "MONITOR_STATE_EXCLUDED", - } - MonitorState_value = map[string]int32{ - "MONITOR_STATE_UNSPECIFIED": 0, - "MONITOR_STATE_MONITORED": 1, - "MONITOR_STATE_UNMONITORED": 2, - "MONITOR_STATE_EXCLUDED": 3, - } -) - -func (x MonitorState) Enum() *MonitorState { - p := new(MonitorState) - *p = x - return p -} - -func (x MonitorState) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MonitorState) Descriptor() protoreflect.EnumDescriptor { - return file_music_agregator_v1_music_agregator_proto_enumTypes[1].Descriptor() -} - -func (MonitorState) Type() protoreflect.EnumType { - return &file_music_agregator_v1_music_agregator_proto_enumTypes[1] -} - -func (x MonitorState) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MonitorState.Descriptor instead. -func (MonitorState) EnumDescriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{1} -} - -type InteractionMode int32 - -const ( - InteractionMode_INTERACTION_MODE_AUTOMATIC InteractionMode = 0 - InteractionMode_INTERACTION_MODE_MANUAL InteractionMode = 1 -) - -// Enum value maps for InteractionMode. -var ( - InteractionMode_name = map[int32]string{ - 0: "INTERACTION_MODE_AUTOMATIC", - 1: "INTERACTION_MODE_MANUAL", - } - InteractionMode_value = map[string]int32{ - "INTERACTION_MODE_AUTOMATIC": 0, - "INTERACTION_MODE_MANUAL": 1, - } -) - -func (x InteractionMode) Enum() *InteractionMode { - p := new(InteractionMode) - *p = x - return p -} - -func (x InteractionMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (InteractionMode) Descriptor() protoreflect.EnumDescriptor { - return file_music_agregator_v1_music_agregator_proto_enumTypes[2].Descriptor() -} - -func (InteractionMode) Type() protoreflect.EnumType { - return &file_music_agregator_v1_music_agregator_proto_enumTypes[2] -} - -func (x InteractionMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use InteractionMode.Descriptor instead. -func (InteractionMode) EnumDescriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{2} -} - -type MonitorStep int32 - -const ( - MonitorStep_MONITOR_STEP_UNSPECIFIED MonitorStep = 0 - MonitorStep_MONITOR_STEP_FETCHING_METADATA MonitorStep = 1 - MonitorStep_MONITOR_STEP_CHECKING_OWNED MonitorStep = 2 - MonitorStep_MONITOR_STEP_SEARCHING_INDEXER MonitorStep = 3 - MonitorStep_MONITOR_STEP_PARSING_RESULTS MonitorStep = 4 - MonitorStep_MONITOR_STEP_FILTERING_QUALITY MonitorStep = 5 - MonitorStep_MONITOR_STEP_SELECTING_RELEASE MonitorStep = 6 - MonitorStep_MONITOR_STEP_ADDING_TORRENT MonitorStep = 7 - MonitorStep_MONITOR_STEP_SAVING MonitorStep = 8 - MonitorStep_MONITOR_STEP_COMPLETE MonitorStep = 9 -) - -// Enum value maps for MonitorStep. -var ( - MonitorStep_name = map[int32]string{ - 0: "MONITOR_STEP_UNSPECIFIED", - 1: "MONITOR_STEP_FETCHING_METADATA", - 2: "MONITOR_STEP_CHECKING_OWNED", - 3: "MONITOR_STEP_SEARCHING_INDEXER", - 4: "MONITOR_STEP_PARSING_RESULTS", - 5: "MONITOR_STEP_FILTERING_QUALITY", - 6: "MONITOR_STEP_SELECTING_RELEASE", - 7: "MONITOR_STEP_ADDING_TORRENT", - 8: "MONITOR_STEP_SAVING", - 9: "MONITOR_STEP_COMPLETE", - } - MonitorStep_value = map[string]int32{ - "MONITOR_STEP_UNSPECIFIED": 0, - "MONITOR_STEP_FETCHING_METADATA": 1, - "MONITOR_STEP_CHECKING_OWNED": 2, - "MONITOR_STEP_SEARCHING_INDEXER": 3, - "MONITOR_STEP_PARSING_RESULTS": 4, - "MONITOR_STEP_FILTERING_QUALITY": 5, - "MONITOR_STEP_SELECTING_RELEASE": 6, - "MONITOR_STEP_ADDING_TORRENT": 7, - "MONITOR_STEP_SAVING": 8, - "MONITOR_STEP_COMPLETE": 9, - } -) - -func (x MonitorStep) Enum() *MonitorStep { - p := new(MonitorStep) - *p = x - return p -} - -func (x MonitorStep) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MonitorStep) Descriptor() protoreflect.EnumDescriptor { - return file_music_agregator_v1_music_agregator_proto_enumTypes[3].Descriptor() -} - -func (MonitorStep) Type() protoreflect.EnumType { - return &file_music_agregator_v1_music_agregator_proto_enumTypes[3] -} - -func (x MonitorStep) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MonitorStep.Descriptor instead. -func (MonitorStep) EnumDescriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{3} -} - -type PromptType int32 - -const ( - PromptType_PROMPT_TYPE_UNSPECIFIED PromptType = 0 - PromptType_PROMPT_TYPE_CONFIRM PromptType = 1 - PromptType_PROMPT_TYPE_SELECT_ONE PromptType = 2 - PromptType_PROMPT_TYPE_SELECT_MANY PromptType = 3 -) - -// Enum value maps for PromptType. -var ( - PromptType_name = map[int32]string{ - 0: "PROMPT_TYPE_UNSPECIFIED", - 1: "PROMPT_TYPE_CONFIRM", - 2: "PROMPT_TYPE_SELECT_ONE", - 3: "PROMPT_TYPE_SELECT_MANY", - } - PromptType_value = map[string]int32{ - "PROMPT_TYPE_UNSPECIFIED": 0, - "PROMPT_TYPE_CONFIRM": 1, - "PROMPT_TYPE_SELECT_ONE": 2, - "PROMPT_TYPE_SELECT_MANY": 3, - } -) - -func (x PromptType) Enum() *PromptType { - p := new(PromptType) - *p = x - return p -} - -func (x PromptType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (PromptType) Descriptor() protoreflect.EnumDescriptor { - return file_music_agregator_v1_music_agregator_proto_enumTypes[4].Descriptor() -} - -func (PromptType) Type() protoreflect.EnumType { - return &file_music_agregator_v1_music_agregator_proto_enumTypes[4] -} - -func (x PromptType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use PromptType.Descriptor instead. -func (PromptType) EnumDescriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{4} -} - -type ResyncAlbumRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - AlbumId string `protobuf:"bytes,1,opt,name=album_id,json=albumId,proto3" json:"album_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ResyncAlbumRequest) Reset() { - *x = ResyncAlbumRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ResyncAlbumRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResyncAlbumRequest) ProtoMessage() {} - -func (x *ResyncAlbumRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ResyncAlbumRequest.ProtoReflect.Descriptor instead. -func (*ResyncAlbumRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{0} -} - -func (x *ResyncAlbumRequest) GetAlbumId() string { - if x != nil { - return x.AlbumId - } - return "" -} - -type ResyncAlbumResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - FilesSynced int32 `protobuf:"varint,1,opt,name=files_synced,json=filesSynced,proto3" json:"files_synced,omitempty"` - FilesEnriched int32 `protobuf:"varint,2,opt,name=files_enriched,json=filesEnriched,proto3" json:"files_enriched,omitempty"` - BytesSynced uint64 `protobuf:"varint,3,opt,name=bytes_synced,json=bytesSynced,proto3" json:"bytes_synced,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ResyncAlbumResponse) Reset() { - *x = ResyncAlbumResponse{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ResyncAlbumResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResyncAlbumResponse) ProtoMessage() {} - -func (x *ResyncAlbumResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ResyncAlbumResponse.ProtoReflect.Descriptor instead. -func (*ResyncAlbumResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{1} -} - -func (x *ResyncAlbumResponse) GetFilesSynced() int32 { - if x != nil { - return x.FilesSynced - } - return 0 -} - -func (x *ResyncAlbumResponse) GetFilesEnriched() int32 { - if x != nil { - return x.FilesEnriched - } - return 0 -} - -func (x *ResyncAlbumResponse) GetBytesSynced() uint64 { - if x != nil { - return x.BytesSynced - } - return 0 -} - -type MonitorAlbumRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - AlbumId string `protobuf:"bytes,1,opt,name=album_id,json=albumId,proto3" json:"album_id,omitempty"` - IndexerOptions *IndexerOptions `protobuf:"bytes,2,opt,name=indexer_options,json=indexerOptions,proto3" json:"indexer_options,omitempty"` - Quality QualityType `protobuf:"varint,3,opt,name=quality,proto3,enum=music_agregator.v1.QualityType" json:"quality,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MonitorAlbumRequest) Reset() { - *x = MonitorAlbumRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MonitorAlbumRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MonitorAlbumRequest) ProtoMessage() {} - -func (x *MonitorAlbumRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MonitorAlbumRequest.ProtoReflect.Descriptor instead. -func (*MonitorAlbumRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{2} -} - -func (x *MonitorAlbumRequest) GetAlbumId() string { - if x != nil { - return x.AlbumId - } - return "" -} - -func (x *MonitorAlbumRequest) GetIndexerOptions() *IndexerOptions { - if x != nil { - return x.IndexerOptions - } - return nil -} - -func (x *MonitorAlbumRequest) GetQuality() QualityType { - if x != nil { - return x.Quality - } - return QualityType_QUALITY_UNSPECIFIED -} - -type IndexerOptions struct { - state protoimpl.MessageState `protogen:"open.v1"` - Tracker string `protobuf:"bytes,1,opt,name=tracker,proto3" json:"tracker,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *IndexerOptions) Reset() { - *x = IndexerOptions{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *IndexerOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IndexerOptions) ProtoMessage() {} - -func (x *IndexerOptions) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IndexerOptions.ProtoReflect.Descriptor instead. -func (*IndexerOptions) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{3} -} - -func (x *IndexerOptions) GetTracker() string { - if x != nil { - return x.Tracker - } - return "" -} - -type MonitorAlbumResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Album *AlbumDetail `protobuf:"bytes,1,opt,name=album,proto3" json:"album,omitempty"` - Artist *ArtistSummary `protobuf:"bytes,2,opt,name=artist,proto3" json:"artist,omitempty"` - Release *MonitoredRelease `protobuf:"bytes,3,opt,name=release,proto3" json:"release,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MonitorAlbumResponse) Reset() { - *x = MonitorAlbumResponse{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MonitorAlbumResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MonitorAlbumResponse) ProtoMessage() {} - -func (x *MonitorAlbumResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MonitorAlbumResponse.ProtoReflect.Descriptor instead. -func (*MonitorAlbumResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{4} -} - -func (x *MonitorAlbumResponse) GetAlbum() *AlbumDetail { - if x != nil { - return x.Album - } - return nil -} - -func (x *MonitorAlbumResponse) GetArtist() *ArtistSummary { - if x != nil { - return x.Artist - } - return nil -} - -func (x *MonitorAlbumResponse) GetRelease() *MonitoredRelease { - if x != nil { - return x.Release - } - return nil -} - -type GetArtistsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetArtistsRequest) Reset() { - *x = GetArtistsRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetArtistsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetArtistsRequest) ProtoMessage() {} - -func (x *GetArtistsRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetArtistsRequest.ProtoReflect.Descriptor instead. -func (*GetArtistsRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{5} -} - -type GetArtistsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Artists []*ArtistSummary `protobuf:"bytes,1,rep,name=artists,proto3" json:"artists,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetArtistsResponse) Reset() { - *x = GetArtistsResponse{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetArtistsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetArtistsResponse) ProtoMessage() {} - -func (x *GetArtistsResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetArtistsResponse.ProtoReflect.Descriptor instead. -func (*GetArtistsResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{6} -} - -func (x *GetArtistsResponse) GetArtists() []*ArtistSummary { - if x != nil { - return x.Artists - } - return nil -} - -type ArtistSummary struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - ExternalId string `protobuf:"bytes,2,opt,name=external_id,json=externalId,proto3" json:"external_id,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - ArtistType string `protobuf:"bytes,4,opt,name=artist_type,json=artistType,proto3" json:"artist_type,omitempty"` - Country string `protobuf:"bytes,5,opt,name=country,proto3" json:"country,omitempty"` - Genres []string `protobuf:"bytes,6,rep,name=genres,proto3" json:"genres,omitempty"` - ImageUrl string `protobuf:"bytes,7,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` - MonitorState MonitorState `protobuf:"varint,8,opt,name=monitor_state,json=monitorState,proto3,enum=music_agregator.v1.MonitorState" json:"monitor_state,omitempty"` - Albums []*AlbumDetail `protobuf:"bytes,9,rep,name=albums,proto3" json:"albums,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ArtistSummary) Reset() { - *x = ArtistSummary{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ArtistSummary) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ArtistSummary) ProtoMessage() {} - -func (x *ArtistSummary) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ArtistSummary.ProtoReflect.Descriptor instead. -func (*ArtistSummary) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{7} -} - -func (x *ArtistSummary) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *ArtistSummary) GetExternalId() string { - if x != nil { - return x.ExternalId - } - return "" -} - -func (x *ArtistSummary) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *ArtistSummary) GetArtistType() string { - if x != nil { - return x.ArtistType - } - return "" -} - -func (x *ArtistSummary) GetCountry() string { - if x != nil { - return x.Country - } - return "" -} - -func (x *ArtistSummary) GetGenres() []string { - if x != nil { - return x.Genres - } - return nil -} - -func (x *ArtistSummary) GetImageUrl() string { - if x != nil { - return x.ImageUrl - } - return "" -} - -func (x *ArtistSummary) GetMonitorState() MonitorState { - if x != nil { - return x.MonitorState - } - return MonitorState_MONITOR_STATE_UNSPECIFIED -} - -func (x *ArtistSummary) GetAlbums() []*AlbumDetail { - if x != nil { - return x.Albums - } - return nil -} - -type AlbumDetail struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - ExternalId string `protobuf:"bytes,2,opt,name=external_id,json=externalId,proto3" json:"external_id,omitempty"` - Title string `protobuf:"bytes,3,opt,name=title,proto3" json:"title,omitempty"` - AlbumType string `protobuf:"bytes,4,opt,name=album_type,json=albumType,proto3" json:"album_type,omitempty"` - ReleaseDate string `protobuf:"bytes,5,opt,name=release_date,json=releaseDate,proto3" json:"release_date,omitempty"` - TotalTracks int32 `protobuf:"varint,6,opt,name=total_tracks,json=totalTracks,proto3" json:"total_tracks,omitempty"` - TotalDiscs int32 `protobuf:"varint,7,opt,name=total_discs,json=totalDiscs,proto3" json:"total_discs,omitempty"` - CoverUrl string `protobuf:"bytes,8,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` - Genres []string `protobuf:"bytes,9,rep,name=genres,proto3" json:"genres,omitempty"` - Label string `protobuf:"bytes,10,opt,name=label,proto3" json:"label,omitempty"` - MonitorState MonitorState `protobuf:"varint,11,opt,name=monitor_state,json=monitorState,proto3,enum=music_agregator.v1.MonitorState" json:"monitor_state,omitempty"` - Downloads []*DownloadInfo `protobuf:"bytes,12,rep,name=downloads,proto3" json:"downloads,omitempty"` - Release *AlbumReleaseDetail `protobuf:"bytes,13,opt,name=release,proto3" json:"release,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlbumDetail) Reset() { - *x = AlbumDetail{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlbumDetail) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlbumDetail) ProtoMessage() {} - -func (x *AlbumDetail) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlbumDetail.ProtoReflect.Descriptor instead. -func (*AlbumDetail) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{8} -} - -func (x *AlbumDetail) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *AlbumDetail) GetExternalId() string { - if x != nil { - return x.ExternalId - } - return "" -} - -func (x *AlbumDetail) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *AlbumDetail) GetAlbumType() string { - if x != nil { - return x.AlbumType - } - return "" -} - -func (x *AlbumDetail) GetReleaseDate() string { - if x != nil { - return x.ReleaseDate - } - return "" -} - -func (x *AlbumDetail) GetTotalTracks() int32 { - if x != nil { - return x.TotalTracks - } - return 0 -} - -func (x *AlbumDetail) GetTotalDiscs() int32 { - if x != nil { - return x.TotalDiscs - } - return 0 -} - -func (x *AlbumDetail) GetCoverUrl() string { - if x != nil { - return x.CoverUrl - } - return "" -} - -func (x *AlbumDetail) GetGenres() []string { - if x != nil { - return x.Genres - } - return nil -} - -func (x *AlbumDetail) GetLabel() string { - if x != nil { - return x.Label - } - return "" -} - -func (x *AlbumDetail) GetMonitorState() MonitorState { - if x != nil { - return x.MonitorState - } - return MonitorState_MONITOR_STATE_UNSPECIFIED -} - -func (x *AlbumDetail) GetDownloads() []*DownloadInfo { - if x != nil { - return x.Downloads - } - return nil -} - -func (x *AlbumDetail) GetRelease() *AlbumReleaseDetail { - if x != nil { - return x.Release - } - return nil -} - -type DownloadInfo struct { - state protoimpl.MessageState `protogen:"open.v1"` - State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` - Format string `protobuf:"bytes,2,opt,name=format,proto3" json:"format,omitempty"` - Quality string `protobuf:"bytes,3,opt,name=quality,proto3" json:"quality,omitempty"` - SavePath string `protobuf:"bytes,4,opt,name=save_path,json=savePath,proto3" json:"save_path,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *DownloadInfo) Reset() { - *x = DownloadInfo{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *DownloadInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DownloadInfo) ProtoMessage() {} - -func (x *DownloadInfo) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DownloadInfo.ProtoReflect.Descriptor instead. -func (*DownloadInfo) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{9} -} - -func (x *DownloadInfo) GetState() string { - if x != nil { - return x.State - } - return "" -} - -func (x *DownloadInfo) GetFormat() string { - if x != nil { - return x.Format - } - return "" -} - -func (x *DownloadInfo) GetQuality() string { - if x != nil { - return x.Quality - } - return "" -} - -func (x *DownloadInfo) GetSavePath() string { - if x != nil { - return x.SavePath - } - return "" -} - -type GetAlbumRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - AlbumId string `protobuf:"bytes,1,opt,name=album_id,json=albumId,proto3" json:"album_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetAlbumRequest) Reset() { - *x = GetAlbumRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetAlbumRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAlbumRequest) ProtoMessage() {} - -func (x *GetAlbumRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetAlbumRequest.ProtoReflect.Descriptor instead. -func (*GetAlbumRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{10} -} - -func (x *GetAlbumRequest) GetAlbumId() string { - if x != nil { - return x.AlbumId - } - return "" -} - -type AlbumInfo struct { - state protoimpl.MessageState `protogen:"open.v1"` - Album *AlbumDetail `protobuf:"bytes,1,opt,name=album,proto3" json:"album,omitempty"` - Tracks []*TrackDetail `protobuf:"bytes,2,rep,name=tracks,proto3" json:"tracks,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlbumInfo) Reset() { - *x = AlbumInfo{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlbumInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlbumInfo) ProtoMessage() {} - -func (x *AlbumInfo) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[11] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlbumInfo.ProtoReflect.Descriptor instead. -func (*AlbumInfo) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{11} -} - -func (x *AlbumInfo) GetAlbum() *AlbumDetail { - if x != nil { - return x.Album - } - return nil -} - -func (x *AlbumInfo) GetTracks() []*TrackDetail { - if x != nil { - return x.Tracks - } - return nil -} - -type GetAlbumResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Info *AlbumInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetAlbumResponse) Reset() { - *x = GetAlbumResponse{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetAlbumResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAlbumResponse) ProtoMessage() {} - -func (x *GetAlbumResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[12] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetAlbumResponse.ProtoReflect.Descriptor instead. -func (*GetAlbumResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{12} -} - -func (x *GetAlbumResponse) GetInfo() *AlbumInfo { - if x != nil { - return x.Info - } - return nil -} - -type AnalyzeAlbumReleaseRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - AlbumId string `protobuf:"bytes,1,opt,name=album_id,json=albumId,proto3" json:"album_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AnalyzeAlbumReleaseRequest) Reset() { - *x = AnalyzeAlbumReleaseRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AnalyzeAlbumReleaseRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AnalyzeAlbumReleaseRequest) ProtoMessage() {} - -func (x *AnalyzeAlbumReleaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[13] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AnalyzeAlbumReleaseRequest.ProtoReflect.Descriptor instead. -func (*AnalyzeAlbumReleaseRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{13} -} - -func (x *AnalyzeAlbumReleaseRequest) GetAlbumId() string { - if x != nil { - return x.AlbumId - } - return "" -} - -type AnalyzeAlbumReleaseResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Info *AlbumInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AnalyzeAlbumReleaseResponse) Reset() { - *x = AnalyzeAlbumReleaseResponse{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AnalyzeAlbumReleaseResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AnalyzeAlbumReleaseResponse) ProtoMessage() {} - -func (x *AnalyzeAlbumReleaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[14] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AnalyzeAlbumReleaseResponse.ProtoReflect.Descriptor instead. -func (*AnalyzeAlbumReleaseResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{14} -} - -func (x *AnalyzeAlbumReleaseResponse) GetInfo() *AlbumInfo { - if x != nil { - return x.Info - } - return nil -} - -type TrackDetail struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - ExternalId string `protobuf:"bytes,2,opt,name=external_id,json=externalId,proto3" json:"external_id,omitempty"` - Title string `protobuf:"bytes,3,opt,name=title,proto3" json:"title,omitempty"` - DurationMs int32 `protobuf:"varint,4,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - DiscNumber int32 `protobuf:"varint,5,opt,name=disc_number,json=discNumber,proto3" json:"disc_number,omitempty"` - TrackNumber int32 `protobuf:"varint,6,opt,name=track_number,json=trackNumber,proto3" json:"track_number,omitempty"` - Isrc string `protobuf:"bytes,7,opt,name=isrc,proto3" json:"isrc,omitempty"` - Explicit bool `protobuf:"varint,8,opt,name=explicit,proto3" json:"explicit,omitempty"` - Artists []*ArtistCredit `protobuf:"bytes,9,rep,name=artists,proto3" json:"artists,omitempty"` - FilePath string `protobuf:"bytes,10,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"` - FileSize int64 `protobuf:"varint,11,opt,name=file_size,json=fileSize,proto3" json:"file_size,omitempty"` - Format string `protobuf:"bytes,12,opt,name=format,proto3" json:"format,omitempty"` - BitDepth int32 `protobuf:"varint,13,opt,name=bit_depth,json=bitDepth,proto3" json:"bit_depth,omitempty"` - SampleRate int32 `protobuf:"varint,14,opt,name=sample_rate,json=sampleRate,proto3" json:"sample_rate,omitempty"` - Channels int32 `protobuf:"varint,15,opt,name=channels,proto3" json:"channels,omitempty"` - BitrateKbps int32 `protobuf:"varint,16,opt,name=bitrate_kbps,json=bitrateKbps,proto3" json:"bitrate_kbps,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TrackDetail) Reset() { - *x = TrackDetail{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TrackDetail) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TrackDetail) ProtoMessage() {} - -func (x *TrackDetail) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[15] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TrackDetail.ProtoReflect.Descriptor instead. -func (*TrackDetail) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{15} -} - -func (x *TrackDetail) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *TrackDetail) GetExternalId() string { - if x != nil { - return x.ExternalId - } - return "" -} - -func (x *TrackDetail) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *TrackDetail) GetDurationMs() int32 { - if x != nil { - return x.DurationMs - } - return 0 -} - -func (x *TrackDetail) GetDiscNumber() int32 { - if x != nil { - return x.DiscNumber - } - return 0 -} - -func (x *TrackDetail) GetTrackNumber() int32 { - if x != nil { - return x.TrackNumber - } - return 0 -} - -func (x *TrackDetail) GetIsrc() string { - if x != nil { - return x.Isrc - } - return "" -} - -func (x *TrackDetail) GetExplicit() bool { - if x != nil { - return x.Explicit - } - return false -} - -func (x *TrackDetail) GetArtists() []*ArtistCredit { - if x != nil { - return x.Artists - } - return nil -} - -func (x *TrackDetail) GetFilePath() string { - if x != nil { - return x.FilePath - } - return "" -} - -func (x *TrackDetail) GetFileSize() int64 { - if x != nil { - return x.FileSize - } - return 0 -} - -func (x *TrackDetail) GetFormat() string { - if x != nil { - return x.Format - } - return "" -} - -func (x *TrackDetail) GetBitDepth() int32 { - if x != nil { - return x.BitDepth - } - return 0 -} - -func (x *TrackDetail) GetSampleRate() int32 { - if x != nil { - return x.SampleRate - } - return 0 -} - -func (x *TrackDetail) GetChannels() int32 { - if x != nil { - return x.Channels - } - return 0 -} - -func (x *TrackDetail) GetBitrateKbps() int32 { - if x != nil { - return x.BitrateKbps - } - return 0 -} - -type ArtistCredit struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ArtistCredit) Reset() { - *x = ArtistCredit{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ArtistCredit) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ArtistCredit) ProtoMessage() {} - -func (x *ArtistCredit) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[16] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ArtistCredit.ProtoReflect.Descriptor instead. -func (*ArtistCredit) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{16} -} - -func (x *ArtistCredit) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *ArtistCredit) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -type AlbumReleaseDetail struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Format string `protobuf:"bytes,2,opt,name=format,proto3" json:"format,omitempty"` - BitDepth int32 `protobuf:"varint,3,opt,name=bit_depth,json=bitDepth,proto3" json:"bit_depth,omitempty"` - SampleRate int32 `protobuf:"varint,4,opt,name=sample_rate,json=sampleRate,proto3" json:"sample_rate,omitempty"` - Channels int32 `protobuf:"varint,5,opt,name=channels,proto3" json:"channels,omitempty"` - IsLossless bool `protobuf:"varint,6,opt,name=is_lossless,json=isLossless,proto3" json:"is_lossless,omitempty"` - Source string `protobuf:"bytes,7,opt,name=source,proto3" json:"source,omitempty"` - TotalSize int64 `protobuf:"varint,8,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"` - TotalDurationMs int32 `protobuf:"varint,9,opt,name=total_duration_ms,json=totalDurationMs,proto3" json:"total_duration_ms,omitempty"` - TrackCount int32 `protobuf:"varint,10,opt,name=track_count,json=trackCount,proto3" json:"track_count,omitempty"` - HasCoverArt bool `protobuf:"varint,11,opt,name=has_cover_art,json=hasCoverArt,proto3" json:"has_cover_art,omitempty"` - HasCueSheet bool `protobuf:"varint,12,opt,name=has_cue_sheet,json=hasCueSheet,proto3" json:"has_cue_sheet,omitempty"` - HasRipLog bool `protobuf:"varint,13,opt,name=has_rip_log,json=hasRipLog,proto3" json:"has_rip_log,omitempty"` - Path string `protobuf:"bytes,14,opt,name=path,proto3" json:"path,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlbumReleaseDetail) Reset() { - *x = AlbumReleaseDetail{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlbumReleaseDetail) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlbumReleaseDetail) ProtoMessage() {} - -func (x *AlbumReleaseDetail) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[17] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlbumReleaseDetail.ProtoReflect.Descriptor instead. -func (*AlbumReleaseDetail) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{17} -} - -func (x *AlbumReleaseDetail) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *AlbumReleaseDetail) GetFormat() string { - if x != nil { - return x.Format - } - return "" -} - -func (x *AlbumReleaseDetail) GetBitDepth() int32 { - if x != nil { - return x.BitDepth - } - return 0 -} - -func (x *AlbumReleaseDetail) GetSampleRate() int32 { - if x != nil { - return x.SampleRate - } - return 0 -} - -func (x *AlbumReleaseDetail) GetChannels() int32 { - if x != nil { - return x.Channels - } - return 0 -} - -func (x *AlbumReleaseDetail) GetIsLossless() bool { - if x != nil { - return x.IsLossless - } - return false -} - -func (x *AlbumReleaseDetail) GetSource() string { - if x != nil { - return x.Source - } - return "" -} - -func (x *AlbumReleaseDetail) GetTotalSize() int64 { - if x != nil { - return x.TotalSize - } - return 0 -} - -func (x *AlbumReleaseDetail) GetTotalDurationMs() int32 { - if x != nil { - return x.TotalDurationMs - } - return 0 -} - -func (x *AlbumReleaseDetail) GetTrackCount() int32 { - if x != nil { - return x.TrackCount - } - return 0 -} - -func (x *AlbumReleaseDetail) GetHasCoverArt() bool { - if x != nil { - return x.HasCoverArt - } - return false -} - -func (x *AlbumReleaseDetail) GetHasCueSheet() bool { - if x != nil { - return x.HasCueSheet - } - return false -} - -func (x *AlbumReleaseDetail) GetHasRipLog() bool { - if x != nil { - return x.HasRipLog - } - return false -} - -func (x *AlbumReleaseDetail) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -type MonitoredRelease struct { - state protoimpl.MessageState `protogen:"open.v1"` - InfoHash string `protobuf:"bytes,1,opt,name=info_hash,json=infoHash,proto3" json:"info_hash,omitempty"` - Artist string `protobuf:"bytes,2,opt,name=artist,proto3" json:"artist,omitempty"` - Album string `protobuf:"bytes,3,opt,name=album,proto3" json:"album,omitempty"` - Year int32 `protobuf:"varint,4,opt,name=year,proto3" json:"year,omitempty"` - Format string `protobuf:"bytes,5,opt,name=format,proto3" json:"format,omitempty"` - Lossless bool `protobuf:"varint,6,opt,name=lossless,proto3" json:"lossless,omitempty"` - BitDepth int32 `protobuf:"varint,7,opt,name=bit_depth,json=bitDepth,proto3" json:"bit_depth,omitempty"` - SampleRate int32 `protobuf:"varint,8,opt,name=sample_rate,json=sampleRate,proto3" json:"sample_rate,omitempty"` - Source string `protobuf:"bytes,9,opt,name=source,proto3" json:"source,omitempty"` - TrackCount int32 `protobuf:"varint,10,opt,name=track_count,json=trackCount,proto3" json:"track_count,omitempty"` - TrackNames []string `protobuf:"bytes,11,rep,name=track_names,json=trackNames,proto3" json:"track_names,omitempty"` - HasCoverArt bool `protobuf:"varint,12,opt,name=has_cover_art,json=hasCoverArt,proto3" json:"has_cover_art,omitempty"` - HasCueSheet bool `protobuf:"varint,13,opt,name=has_cue_sheet,json=hasCueSheet,proto3" json:"has_cue_sheet,omitempty"` - HasRipLog bool `protobuf:"varint,14,opt,name=has_rip_log,json=hasRipLog,proto3" json:"has_rip_log,omitempty"` - TotalAudioSize int64 `protobuf:"varint,15,opt,name=total_audio_size,json=totalAudioSize,proto3" json:"total_audio_size,omitempty"` - DownloadLink string `protobuf:"bytes,16,opt,name=download_link,json=downloadLink,proto3" json:"download_link,omitempty"` - Seeders int32 `protobuf:"varint,17,opt,name=seeders,proto3" json:"seeders,omitempty"` - Tracker string `protobuf:"bytes,18,opt,name=tracker,proto3" json:"tracker,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MonitoredRelease) Reset() { - *x = MonitoredRelease{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MonitoredRelease) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MonitoredRelease) ProtoMessage() {} - -func (x *MonitoredRelease) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[18] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MonitoredRelease.ProtoReflect.Descriptor instead. -func (*MonitoredRelease) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{18} -} - -func (x *MonitoredRelease) GetInfoHash() string { - if x != nil { - return x.InfoHash - } - return "" -} - -func (x *MonitoredRelease) GetArtist() string { - if x != nil { - return x.Artist - } - return "" -} - -func (x *MonitoredRelease) GetAlbum() string { - if x != nil { - return x.Album - } - return "" -} - -func (x *MonitoredRelease) GetYear() int32 { - if x != nil { - return x.Year - } - return 0 -} - -func (x *MonitoredRelease) GetFormat() string { - if x != nil { - return x.Format - } - return "" -} - -func (x *MonitoredRelease) GetLossless() bool { - if x != nil { - return x.Lossless - } - return false -} - -func (x *MonitoredRelease) GetBitDepth() int32 { - if x != nil { - return x.BitDepth - } - return 0 -} - -func (x *MonitoredRelease) GetSampleRate() int32 { - if x != nil { - return x.SampleRate - } - return 0 -} - -func (x *MonitoredRelease) GetSource() string { - if x != nil { - return x.Source - } - return "" -} - -func (x *MonitoredRelease) GetTrackCount() int32 { - if x != nil { - return x.TrackCount - } - return 0 -} - -func (x *MonitoredRelease) GetTrackNames() []string { - if x != nil { - return x.TrackNames - } - return nil -} - -func (x *MonitoredRelease) GetHasCoverArt() bool { - if x != nil { - return x.HasCoverArt - } - return false -} - -func (x *MonitoredRelease) GetHasCueSheet() bool { - if x != nil { - return x.HasCueSheet - } - return false -} - -func (x *MonitoredRelease) GetHasRipLog() bool { - if x != nil { - return x.HasRipLog - } - return false -} - -func (x *MonitoredRelease) GetTotalAudioSize() int64 { - if x != nil { - return x.TotalAudioSize - } - return 0 -} - -func (x *MonitoredRelease) GetDownloadLink() string { - if x != nil { - return x.DownloadLink - } - return "" -} - -func (x *MonitoredRelease) GetSeeders() int32 { - if x != nil { - return x.Seeders - } - return 0 -} - -func (x *MonitoredRelease) GetTracker() string { - if x != nil { - return x.Tracker - } - return "" -} - -type SearchArtistsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` - Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` - Offset int32 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchArtistsRequest) Reset() { - *x = SearchArtistsRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchArtistsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchArtistsRequest) ProtoMessage() {} - -func (x *SearchArtistsRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[19] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchArtistsRequest.ProtoReflect.Descriptor instead. -func (*SearchArtistsRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{19} -} - -func (x *SearchArtistsRequest) GetQuery() string { - if x != nil { - return x.Query - } - return "" -} - -func (x *SearchArtistsRequest) GetLimit() int32 { - if x != nil { - return x.Limit - } - return 0 -} - -func (x *SearchArtistsRequest) GetOffset() int32 { - if x != nil { - return x.Offset - } - return 0 -} - -type SearchArtistsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Artists []*SearchArtistResult `protobuf:"bytes,1,rep,name=artists,proto3" json:"artists,omitempty"` - Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchArtistsResponse) Reset() { - *x = SearchArtistsResponse{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchArtistsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchArtistsResponse) ProtoMessage() {} - -func (x *SearchArtistsResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[20] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchArtistsResponse.ProtoReflect.Descriptor instead. -func (*SearchArtistsResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{20} -} - -func (x *SearchArtistsResponse) GetArtists() []*SearchArtistResult { - if x != nil { - return x.Artists - } - return nil -} - -func (x *SearchArtistsResponse) GetTotal() int32 { - if x != nil { - return x.Total - } - return 0 -} - -type SearchArtistResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - SortName string `protobuf:"bytes,3,opt,name=sort_name,json=sortName,proto3" json:"sort_name,omitempty"` - ArtistType string `protobuf:"bytes,4,opt,name=artist_type,json=artistType,proto3" json:"artist_type,omitempty"` - Country string `protobuf:"bytes,5,opt,name=country,proto3" json:"country,omitempty"` - FormedDate string `protobuf:"bytes,6,opt,name=formed_date,json=formedDate,proto3" json:"formed_date,omitempty"` - DisbandedDate string `protobuf:"bytes,7,opt,name=disbanded_date,json=disbandedDate,proto3" json:"disbanded_date,omitempty"` - Description string `protobuf:"bytes,8,opt,name=description,proto3" json:"description,omitempty"` - ImageUrl string `protobuf:"bytes,9,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` - Genres []string `protobuf:"bytes,10,rep,name=genres,proto3" json:"genres,omitempty"` - ExternalIds []*ExternalId `protobuf:"bytes,11,rep,name=external_ids,json=externalIds,proto3" json:"external_ids,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchArtistResult) Reset() { - *x = SearchArtistResult{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchArtistResult) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchArtistResult) ProtoMessage() {} - -func (x *SearchArtistResult) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[21] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchArtistResult.ProtoReflect.Descriptor instead. -func (*SearchArtistResult) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{21} -} - -func (x *SearchArtistResult) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *SearchArtistResult) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *SearchArtistResult) GetSortName() string { - if x != nil { - return x.SortName - } - return "" -} - -func (x *SearchArtistResult) GetArtistType() string { - if x != nil { - return x.ArtistType - } - return "" -} - -func (x *SearchArtistResult) GetCountry() string { - if x != nil { - return x.Country - } - return "" -} - -func (x *SearchArtistResult) GetFormedDate() string { - if x != nil { - return x.FormedDate - } - return "" -} - -func (x *SearchArtistResult) GetDisbandedDate() string { - if x != nil { - return x.DisbandedDate - } - return "" -} - -func (x *SearchArtistResult) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *SearchArtistResult) GetImageUrl() string { - if x != nil { - return x.ImageUrl - } - return "" -} - -func (x *SearchArtistResult) GetGenres() []string { - if x != nil { - return x.Genres - } - return nil -} - -func (x *SearchArtistResult) GetExternalIds() []*ExternalId { - if x != nil { - return x.ExternalIds - } - return nil -} - -type ExternalId struct { - state protoimpl.MessageState `protogen:"open.v1"` - Provider string `protobuf:"bytes,1,opt,name=provider,proto3" json:"provider,omitempty"` - Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ExternalId) Reset() { - *x = ExternalId{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ExternalId) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExternalId) ProtoMessage() {} - -func (x *ExternalId) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[22] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExternalId.ProtoReflect.Descriptor instead. -func (*ExternalId) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{22} -} - -func (x *ExternalId) GetProvider() string { - if x != nil { - return x.Provider - } - return "" -} - -func (x *ExternalId) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -type GetArtistAlbumsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - ArtistId string `protobuf:"bytes,1,opt,name=artist_id,json=artistId,proto3" json:"artist_id,omitempty"` - Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` - Offset int32 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetArtistAlbumsRequest) Reset() { - *x = GetArtistAlbumsRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetArtistAlbumsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetArtistAlbumsRequest) ProtoMessage() {} - -func (x *GetArtistAlbumsRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[23] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetArtistAlbumsRequest.ProtoReflect.Descriptor instead. -func (*GetArtistAlbumsRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{23} -} - -func (x *GetArtistAlbumsRequest) GetArtistId() string { - if x != nil { - return x.ArtistId - } - return "" -} - -func (x *GetArtistAlbumsRequest) GetLimit() int32 { - if x != nil { - return x.Limit - } - return 0 -} - -func (x *GetArtistAlbumsRequest) GetOffset() int32 { - if x != nil { - return x.Offset - } - return 0 -} - -type GetArtistAlbumsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Albums []*AlbumResult `protobuf:"bytes,1,rep,name=albums,proto3" json:"albums,omitempty"` - Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetArtistAlbumsResponse) Reset() { - *x = GetArtistAlbumsResponse{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetArtistAlbumsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetArtistAlbumsResponse) ProtoMessage() {} - -func (x *GetArtistAlbumsResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[24] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetArtistAlbumsResponse.ProtoReflect.Descriptor instead. -func (*GetArtistAlbumsResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{24} -} - -func (x *GetArtistAlbumsResponse) GetAlbums() []*AlbumResult { - if x != nil { - return x.Albums - } - return nil -} - -func (x *GetArtistAlbumsResponse) GetTotal() int32 { - if x != nil { - return x.Total - } - return 0 -} - -type AlbumResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` - AlbumType string `protobuf:"bytes,3,opt,name=album_type,json=albumType,proto3" json:"album_type,omitempty"` - ReleaseDate string `protobuf:"bytes,4,opt,name=release_date,json=releaseDate,proto3" json:"release_date,omitempty"` - Upc string `protobuf:"bytes,5,opt,name=upc,proto3" json:"upc,omitempty"` - TotalTracks int32 `protobuf:"varint,6,opt,name=total_tracks,json=totalTracks,proto3" json:"total_tracks,omitempty"` - TotalDiscs int32 `protobuf:"varint,7,opt,name=total_discs,json=totalDiscs,proto3" json:"total_discs,omitempty"` - CoverUrl string `protobuf:"bytes,8,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` - Artists []*AlbumArtistCredit `protobuf:"bytes,9,rep,name=artists,proto3" json:"artists,omitempty"` - Label *AlbumLabel `protobuf:"bytes,10,opt,name=label,proto3" json:"label,omitempty"` - Genres []string `protobuf:"bytes,11,rep,name=genres,proto3" json:"genres,omitempty"` - ExternalIds []*ExternalId `protobuf:"bytes,12,rep,name=external_ids,json=externalIds,proto3" json:"external_ids,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlbumResult) Reset() { - *x = AlbumResult{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlbumResult) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlbumResult) ProtoMessage() {} - -func (x *AlbumResult) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[25] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlbumResult.ProtoReflect.Descriptor instead. -func (*AlbumResult) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{25} -} - -func (x *AlbumResult) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *AlbumResult) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *AlbumResult) GetAlbumType() string { - if x != nil { - return x.AlbumType - } - return "" -} - -func (x *AlbumResult) GetReleaseDate() string { - if x != nil { - return x.ReleaseDate - } - return "" -} - -func (x *AlbumResult) GetUpc() string { - if x != nil { - return x.Upc - } - return "" -} - -func (x *AlbumResult) GetTotalTracks() int32 { - if x != nil { - return x.TotalTracks - } - return 0 -} - -func (x *AlbumResult) GetTotalDiscs() int32 { - if x != nil { - return x.TotalDiscs - } - return 0 -} - -func (x *AlbumResult) GetCoverUrl() string { - if x != nil { - return x.CoverUrl - } - return "" -} - -func (x *AlbumResult) GetArtists() []*AlbumArtistCredit { - if x != nil { - return x.Artists - } - return nil -} - -func (x *AlbumResult) GetLabel() *AlbumLabel { - if x != nil { - return x.Label - } - return nil -} - -func (x *AlbumResult) GetGenres() []string { - if x != nil { - return x.Genres - } - return nil -} - -func (x *AlbumResult) GetExternalIds() []*ExternalId { - if x != nil { - return x.ExternalIds - } - return nil -} - -type AlbumArtistCredit struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Role string `protobuf:"bytes,3,opt,name=role,proto3" json:"role,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlbumArtistCredit) Reset() { - *x = AlbumArtistCredit{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlbumArtistCredit) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlbumArtistCredit) ProtoMessage() {} - -func (x *AlbumArtistCredit) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[26] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlbumArtistCredit.ProtoReflect.Descriptor instead. -func (*AlbumArtistCredit) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{26} -} - -func (x *AlbumArtistCredit) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *AlbumArtistCredit) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *AlbumArtistCredit) GetRole() string { - if x != nil { - return x.Role - } - return "" -} - -type AlbumLabel struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Country string `protobuf:"bytes,3,opt,name=country,proto3" json:"country,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlbumLabel) Reset() { - *x = AlbumLabel{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlbumLabel) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlbumLabel) ProtoMessage() {} - -func (x *AlbumLabel) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[27] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlbumLabel.ProtoReflect.Descriptor instead. -func (*AlbumLabel) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{27} -} - -func (x *AlbumLabel) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *AlbumLabel) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *AlbumLabel) GetCountry() string { - if x != nil { - return x.Country - } - return "" -} - -type SubscribeEventsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - SinceSeq int64 `protobuf:"varint,1,opt,name=since_seq,json=sinceSeq,proto3" json:"since_seq,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubscribeEventsRequest) Reset() { - *x = SubscribeEventsRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubscribeEventsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubscribeEventsRequest) ProtoMessage() {} - -func (x *SubscribeEventsRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[28] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubscribeEventsRequest.ProtoReflect.Descriptor instead. -func (*SubscribeEventsRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{28} -} - -func (x *SubscribeEventsRequest) GetSinceSeq() int64 { - if x != nil { - return x.SinceSeq - } - return 0 -} - -type AlbumEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - Seq int64 `protobuf:"varint,1,opt,name=seq,proto3" json:"seq,omitempty"` - WorkflowRunId string `protobuf:"bytes,2,opt,name=workflow_run_id,json=workflowRunId,proto3" json:"workflow_run_id,omitempty"` - AlbumId string `protobuf:"bytes,3,opt,name=album_id,json=albumId,proto3" json:"album_id,omitempty"` - Quality string `protobuf:"bytes,4,opt,name=quality,proto3" json:"quality,omitempty"` - EventType string `protobuf:"bytes,5,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` - Step string `protobuf:"bytes,6,opt,name=step,proto3" json:"step,omitempty"` - Message string `protobuf:"bytes,7,opt,name=message,proto3" json:"message,omitempty"` - DataJson []byte `protobuf:"bytes,8,opt,name=data_json,json=dataJson,proto3" json:"data_json,omitempty"` - TimestampMs int64 `protobuf:"varint,9,opt,name=timestamp_ms,json=timestampMs,proto3" json:"timestamp_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlbumEvent) Reset() { - *x = AlbumEvent{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlbumEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlbumEvent) ProtoMessage() {} - -func (x *AlbumEvent) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[29] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlbumEvent.ProtoReflect.Descriptor instead. -func (*AlbumEvent) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{29} -} - -func (x *AlbumEvent) GetSeq() int64 { - if x != nil { - return x.Seq - } - return 0 -} - -func (x *AlbumEvent) GetWorkflowRunId() string { - if x != nil { - return x.WorkflowRunId - } - return "" -} - -func (x *AlbumEvent) GetAlbumId() string { - if x != nil { - return x.AlbumId - } - return "" -} - -func (x *AlbumEvent) GetQuality() string { - if x != nil { - return x.Quality - } - return "" -} - -func (x *AlbumEvent) GetEventType() string { - if x != nil { - return x.EventType - } - return "" -} - -func (x *AlbumEvent) GetStep() string { - if x != nil { - return x.Step - } - return "" -} - -func (x *AlbumEvent) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -func (x *AlbumEvent) GetDataJson() []byte { - if x != nil { - return x.DataJson - } - return nil -} - -func (x *AlbumEvent) GetTimestampMs() int64 { - if x != nil { - return x.TimestampMs - } - return 0 -} - -type MonitorAlbumStreamRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Types that are valid to be assigned to Message: - // - // *MonitorAlbumStreamRequest_Start - // *MonitorAlbumStreamRequest_Decision - // *MonitorAlbumStreamRequest_Cancel - Message isMonitorAlbumStreamRequest_Message `protobuf_oneof:"message"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MonitorAlbumStreamRequest) Reset() { - *x = MonitorAlbumStreamRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MonitorAlbumStreamRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MonitorAlbumStreamRequest) ProtoMessage() {} - -func (x *MonitorAlbumStreamRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[30] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MonitorAlbumStreamRequest.ProtoReflect.Descriptor instead. -func (*MonitorAlbumStreamRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{30} -} - -func (x *MonitorAlbumStreamRequest) GetMessage() isMonitorAlbumStreamRequest_Message { - if x != nil { - return x.Message - } - return nil -} - -func (x *MonitorAlbumStreamRequest) GetStart() *StartMonitorRequest { - if x != nil { - if x, ok := x.Message.(*MonitorAlbumStreamRequest_Start); ok { - return x.Start - } - } - return nil -} - -func (x *MonitorAlbumStreamRequest) GetDecision() *UserDecision { - if x != nil { - if x, ok := x.Message.(*MonitorAlbumStreamRequest_Decision); ok { - return x.Decision - } - } - return nil -} - -func (x *MonitorAlbumStreamRequest) GetCancel() *CancelRequest { - if x != nil { - if x, ok := x.Message.(*MonitorAlbumStreamRequest_Cancel); ok { - return x.Cancel - } - } - return nil -} - -type isMonitorAlbumStreamRequest_Message interface { - isMonitorAlbumStreamRequest_Message() -} - -type MonitorAlbumStreamRequest_Start struct { - Start *StartMonitorRequest `protobuf:"bytes,1,opt,name=start,proto3,oneof"` -} - -type MonitorAlbumStreamRequest_Decision struct { - Decision *UserDecision `protobuf:"bytes,2,opt,name=decision,proto3,oneof"` -} - -type MonitorAlbumStreamRequest_Cancel struct { - Cancel *CancelRequest `protobuf:"bytes,3,opt,name=cancel,proto3,oneof"` -} - -func (*MonitorAlbumStreamRequest_Start) isMonitorAlbumStreamRequest_Message() {} - -func (*MonitorAlbumStreamRequest_Decision) isMonitorAlbumStreamRequest_Message() {} - -func (*MonitorAlbumStreamRequest_Cancel) isMonitorAlbumStreamRequest_Message() {} - -type StartMonitorRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - AlbumId string `protobuf:"bytes,1,opt,name=album_id,json=albumId,proto3" json:"album_id,omitempty"` - IndexerOptions *IndexerOptions `protobuf:"bytes,2,opt,name=indexer_options,json=indexerOptions,proto3" json:"indexer_options,omitempty"` - Quality QualityType `protobuf:"varint,3,opt,name=quality,proto3,enum=music_agregator.v1.QualityType" json:"quality,omitempty"` - Mode InteractionMode `protobuf:"varint,4,opt,name=mode,proto3,enum=music_agregator.v1.InteractionMode" json:"mode,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *StartMonitorRequest) Reset() { - *x = StartMonitorRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *StartMonitorRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StartMonitorRequest) ProtoMessage() {} - -func (x *StartMonitorRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[31] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StartMonitorRequest.ProtoReflect.Descriptor instead. -func (*StartMonitorRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{31} -} - -func (x *StartMonitorRequest) GetAlbumId() string { - if x != nil { - return x.AlbumId - } - return "" -} - -func (x *StartMonitorRequest) GetIndexerOptions() *IndexerOptions { - if x != nil { - return x.IndexerOptions - } - return nil -} - -func (x *StartMonitorRequest) GetQuality() QualityType { - if x != nil { - return x.Quality - } - return QualityType_QUALITY_UNSPECIFIED -} - -func (x *StartMonitorRequest) GetMode() InteractionMode { - if x != nil { - return x.Mode - } - return InteractionMode_INTERACTION_MODE_AUTOMATIC -} - -type UserDecision struct { - state protoimpl.MessageState `protogen:"open.v1"` - PromptId string `protobuf:"bytes,1,opt,name=prompt_id,json=promptId,proto3" json:"prompt_id,omitempty"` - // Types that are valid to be assigned to Decision: - // - // *UserDecision_Confirm - // *UserDecision_SelectedId - // *UserDecision_SelectedIds - Decision isUserDecision_Decision `protobuf_oneof:"decision"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *UserDecision) Reset() { - *x = UserDecision{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[32] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *UserDecision) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UserDecision) ProtoMessage() {} - -func (x *UserDecision) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[32] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UserDecision.ProtoReflect.Descriptor instead. -func (*UserDecision) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{32} -} - -func (x *UserDecision) GetPromptId() string { - if x != nil { - return x.PromptId - } - return "" -} - -func (x *UserDecision) GetDecision() isUserDecision_Decision { - if x != nil { - return x.Decision - } - return nil -} - -func (x *UserDecision) GetConfirm() bool { - if x != nil { - if x, ok := x.Decision.(*UserDecision_Confirm); ok { - return x.Confirm - } - } - return false -} - -func (x *UserDecision) GetSelectedId() string { - if x != nil { - if x, ok := x.Decision.(*UserDecision_SelectedId); ok { - return x.SelectedId - } - } - return "" -} - -func (x *UserDecision) GetSelectedIds() *SelectedIds { - if x != nil { - if x, ok := x.Decision.(*UserDecision_SelectedIds); ok { - return x.SelectedIds - } - } - return nil -} - -type isUserDecision_Decision interface { - isUserDecision_Decision() -} - -type UserDecision_Confirm struct { - Confirm bool `protobuf:"varint,2,opt,name=confirm,proto3,oneof"` -} - -type UserDecision_SelectedId struct { - SelectedId string `protobuf:"bytes,3,opt,name=selected_id,json=selectedId,proto3,oneof"` -} - -type UserDecision_SelectedIds struct { - SelectedIds *SelectedIds `protobuf:"bytes,4,opt,name=selected_ids,json=selectedIds,proto3,oneof"` -} - -func (*UserDecision_Confirm) isUserDecision_Decision() {} - -func (*UserDecision_SelectedId) isUserDecision_Decision() {} - -func (*UserDecision_SelectedIds) isUserDecision_Decision() {} - -type SelectedIds struct { - state protoimpl.MessageState `protogen:"open.v1"` - Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SelectedIds) Reset() { - *x = SelectedIds{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[33] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SelectedIds) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SelectedIds) ProtoMessage() {} - -func (x *SelectedIds) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[33] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SelectedIds.ProtoReflect.Descriptor instead. -func (*SelectedIds) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{33} -} - -func (x *SelectedIds) GetIds() []string { - if x != nil { - return x.Ids - } - return nil -} - -type CancelRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CancelRequest) Reset() { - *x = CancelRequest{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[34] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CancelRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CancelRequest) ProtoMessage() {} - -func (x *CancelRequest) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[34] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CancelRequest.ProtoReflect.Descriptor instead. -func (*CancelRequest) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{34} -} - -type MonitorAlbumStreamResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Types that are valid to be assigned to Message: - // - // *MonitorAlbumStreamResponse_Status - // *MonitorAlbumStreamResponse_Prompt - // *MonitorAlbumStreamResponse_Result - // *MonitorAlbumStreamResponse_Error - Message isMonitorAlbumStreamResponse_Message `protobuf_oneof:"message"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MonitorAlbumStreamResponse) Reset() { - *x = MonitorAlbumStreamResponse{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[35] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MonitorAlbumStreamResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MonitorAlbumStreamResponse) ProtoMessage() {} - -func (x *MonitorAlbumStreamResponse) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[35] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MonitorAlbumStreamResponse.ProtoReflect.Descriptor instead. -func (*MonitorAlbumStreamResponse) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{35} -} - -func (x *MonitorAlbumStreamResponse) GetMessage() isMonitorAlbumStreamResponse_Message { - if x != nil { - return x.Message - } - return nil -} - -func (x *MonitorAlbumStreamResponse) GetStatus() *StatusUpdate { - if x != nil { - if x, ok := x.Message.(*MonitorAlbumStreamResponse_Status); ok { - return x.Status - } - } - return nil -} - -func (x *MonitorAlbumStreamResponse) GetPrompt() *PromptForDecision { - if x != nil { - if x, ok := x.Message.(*MonitorAlbumStreamResponse_Prompt); ok { - return x.Prompt - } - } - return nil -} - -func (x *MonitorAlbumStreamResponse) GetResult() *MonitorAlbumResponse { - if x != nil { - if x, ok := x.Message.(*MonitorAlbumStreamResponse_Result); ok { - return x.Result - } - } - return nil -} - -func (x *MonitorAlbumStreamResponse) GetError() *ErrorUpdate { - if x != nil { - if x, ok := x.Message.(*MonitorAlbumStreamResponse_Error); ok { - return x.Error - } - } - return nil -} - -type isMonitorAlbumStreamResponse_Message interface { - isMonitorAlbumStreamResponse_Message() -} - -type MonitorAlbumStreamResponse_Status struct { - Status *StatusUpdate `protobuf:"bytes,1,opt,name=status,proto3,oneof"` -} - -type MonitorAlbumStreamResponse_Prompt struct { - Prompt *PromptForDecision `protobuf:"bytes,2,opt,name=prompt,proto3,oneof"` -} - -type MonitorAlbumStreamResponse_Result struct { - Result *MonitorAlbumResponse `protobuf:"bytes,3,opt,name=result,proto3,oneof"` -} - -type MonitorAlbumStreamResponse_Error struct { - Error *ErrorUpdate `protobuf:"bytes,4,opt,name=error,proto3,oneof"` -} - -func (*MonitorAlbumStreamResponse_Status) isMonitorAlbumStreamResponse_Message() {} - -func (*MonitorAlbumStreamResponse_Prompt) isMonitorAlbumStreamResponse_Message() {} - -func (*MonitorAlbumStreamResponse_Result) isMonitorAlbumStreamResponse_Message() {} - -func (*MonitorAlbumStreamResponse_Error) isMonitorAlbumStreamResponse_Message() {} - -type StatusUpdate struct { - state protoimpl.MessageState `protogen:"open.v1"` - Step MonitorStep `protobuf:"varint,1,opt,name=step,proto3,enum=music_agregator.v1.MonitorStep" json:"step,omitempty"` - Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` - // Types that are valid to be assigned to Data: - // - // *StatusUpdate_AlbumInfo - // *StatusUpdate_Torrents - // *StatusUpdate_ReleaseInfo - Data isStatusUpdate_Data `protobuf_oneof:"data"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *StatusUpdate) Reset() { - *x = StatusUpdate{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[36] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *StatusUpdate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StatusUpdate) ProtoMessage() {} - -func (x *StatusUpdate) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[36] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StatusUpdate.ProtoReflect.Descriptor instead. -func (*StatusUpdate) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{36} -} - -func (x *StatusUpdate) GetStep() MonitorStep { - if x != nil { - return x.Step - } - return MonitorStep_MONITOR_STEP_UNSPECIFIED -} - -func (x *StatusUpdate) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -func (x *StatusUpdate) GetData() isStatusUpdate_Data { - if x != nil { - return x.Data - } - return nil -} - -func (x *StatusUpdate) GetAlbumInfo() *StreamAlbumInfo { - if x != nil { - if x, ok := x.Data.(*StatusUpdate_AlbumInfo); ok { - return x.AlbumInfo - } - } - return nil -} - -func (x *StatusUpdate) GetTorrents() *TorrentList { - if x != nil { - if x, ok := x.Data.(*StatusUpdate_Torrents); ok { - return x.Torrents - } - } - return nil -} - -func (x *StatusUpdate) GetReleaseInfo() *ReleaseInfo { - if x != nil { - if x, ok := x.Data.(*StatusUpdate_ReleaseInfo); ok { - return x.ReleaseInfo - } - } - return nil -} - -type isStatusUpdate_Data interface { - isStatusUpdate_Data() -} - -type StatusUpdate_AlbumInfo struct { - AlbumInfo *StreamAlbumInfo `protobuf:"bytes,10,opt,name=album_info,json=albumInfo,proto3,oneof"` -} - -type StatusUpdate_Torrents struct { - Torrents *TorrentList `protobuf:"bytes,11,opt,name=torrents,proto3,oneof"` -} - -type StatusUpdate_ReleaseInfo struct { - ReleaseInfo *ReleaseInfo `protobuf:"bytes,12,opt,name=release_info,json=releaseInfo,proto3,oneof"` -} - -func (*StatusUpdate_AlbumInfo) isStatusUpdate_Data() {} - -func (*StatusUpdate_Torrents) isStatusUpdate_Data() {} - -func (*StatusUpdate_ReleaseInfo) isStatusUpdate_Data() {} - -type PromptForDecision struct { - state protoimpl.MessageState `protogen:"open.v1"` - PromptId string `protobuf:"bytes,1,opt,name=prompt_id,json=promptId,proto3" json:"prompt_id,omitempty"` - Type PromptType `protobuf:"varint,2,opt,name=type,proto3,enum=music_agregator.v1.PromptType" json:"type,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` - TimeoutSeconds int32 `protobuf:"varint,4,opt,name=timeout_seconds,json=timeoutSeconds,proto3" json:"timeout_seconds,omitempty"` - // Types that are valid to be assigned to Options: - // - // *PromptForDecision_Confirm - // *PromptForDecision_SelectOne - // *PromptForDecision_SelectMany - Options isPromptForDecision_Options `protobuf_oneof:"options"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PromptForDecision) Reset() { - *x = PromptForDecision{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[37] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PromptForDecision) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PromptForDecision) ProtoMessage() {} - -func (x *PromptForDecision) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[37] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PromptForDecision.ProtoReflect.Descriptor instead. -func (*PromptForDecision) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{37} -} - -func (x *PromptForDecision) GetPromptId() string { - if x != nil { - return x.PromptId - } - return "" -} - -func (x *PromptForDecision) GetType() PromptType { - if x != nil { - return x.Type - } - return PromptType_PROMPT_TYPE_UNSPECIFIED -} - -func (x *PromptForDecision) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -func (x *PromptForDecision) GetTimeoutSeconds() int32 { - if x != nil { - return x.TimeoutSeconds - } - return 0 -} - -func (x *PromptForDecision) GetOptions() isPromptForDecision_Options { - if x != nil { - return x.Options - } - return nil -} - -func (x *PromptForDecision) GetConfirm() *ConfirmPrompt { - if x != nil { - if x, ok := x.Options.(*PromptForDecision_Confirm); ok { - return x.Confirm - } - } - return nil -} - -func (x *PromptForDecision) GetSelectOne() *SelectOnePrompt { - if x != nil { - if x, ok := x.Options.(*PromptForDecision_SelectOne); ok { - return x.SelectOne - } - } - return nil -} - -func (x *PromptForDecision) GetSelectMany() *SelectManyPrompt { - if x != nil { - if x, ok := x.Options.(*PromptForDecision_SelectMany); ok { - return x.SelectMany - } - } - return nil -} - -type isPromptForDecision_Options interface { - isPromptForDecision_Options() -} - -type PromptForDecision_Confirm struct { - Confirm *ConfirmPrompt `protobuf:"bytes,10,opt,name=confirm,proto3,oneof"` -} - -type PromptForDecision_SelectOne struct { - SelectOne *SelectOnePrompt `protobuf:"bytes,11,opt,name=select_one,json=selectOne,proto3,oneof"` -} - -type PromptForDecision_SelectMany struct { - SelectMany *SelectManyPrompt `protobuf:"bytes,12,opt,name=select_many,json=selectMany,proto3,oneof"` -} - -func (*PromptForDecision_Confirm) isPromptForDecision_Options() {} - -func (*PromptForDecision_SelectOne) isPromptForDecision_Options() {} - -func (*PromptForDecision_SelectMany) isPromptForDecision_Options() {} - -type ErrorUpdate struct { - state protoimpl.MessageState `protogen:"open.v1"` - FailedStep MonitorStep `protobuf:"varint,1,opt,name=failed_step,json=failedStep,proto3,enum=music_agregator.v1.MonitorStep" json:"failed_step,omitempty"` - Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` - Recoverable bool `protobuf:"varint,3,opt,name=recoverable,proto3" json:"recoverable,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ErrorUpdate) Reset() { - *x = ErrorUpdate{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[38] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ErrorUpdate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ErrorUpdate) ProtoMessage() {} - -func (x *ErrorUpdate) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[38] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ErrorUpdate.ProtoReflect.Descriptor instead. -func (*ErrorUpdate) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{38} -} - -func (x *ErrorUpdate) GetFailedStep() MonitorStep { - if x != nil { - return x.FailedStep - } - return MonitorStep_MONITOR_STEP_UNSPECIFIED -} - -func (x *ErrorUpdate) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -func (x *ErrorUpdate) GetRecoverable() bool { - if x != nil { - return x.Recoverable - } - return false -} - -type StreamAlbumInfo struct { - state protoimpl.MessageState `protogen:"open.v1"` - Artist string `protobuf:"bytes,1,opt,name=artist,proto3" json:"artist,omitempty"` - Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` - ReleaseDate string `protobuf:"bytes,3,opt,name=release_date,json=releaseDate,proto3" json:"release_date,omitempty"` - AlreadyOwned bool `protobuf:"varint,4,opt,name=already_owned,json=alreadyOwned,proto3" json:"already_owned,omitempty"` - OwnedQuality string `protobuf:"bytes,5,opt,name=owned_quality,json=ownedQuality,proto3" json:"owned_quality,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *StreamAlbumInfo) Reset() { - *x = StreamAlbumInfo{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[39] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *StreamAlbumInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StreamAlbumInfo) ProtoMessage() {} - -func (x *StreamAlbumInfo) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[39] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StreamAlbumInfo.ProtoReflect.Descriptor instead. -func (*StreamAlbumInfo) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{39} -} - -func (x *StreamAlbumInfo) GetArtist() string { - if x != nil { - return x.Artist - } - return "" -} - -func (x *StreamAlbumInfo) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *StreamAlbumInfo) GetReleaseDate() string { - if x != nil { - return x.ReleaseDate - } - return "" -} - -func (x *StreamAlbumInfo) GetAlreadyOwned() bool { - if x != nil { - return x.AlreadyOwned - } - return false -} - -func (x *StreamAlbumInfo) GetOwnedQuality() string { - if x != nil { - return x.OwnedQuality - } - return "" -} - -type TorrentList struct { - state protoimpl.MessageState `protogen:"open.v1"` - Torrents []*TorrentSummary `protobuf:"bytes,1,rep,name=torrents,proto3" json:"torrents,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TorrentList) Reset() { - *x = TorrentList{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[40] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TorrentList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TorrentList) ProtoMessage() {} - -func (x *TorrentList) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[40] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TorrentList.ProtoReflect.Descriptor instead. -func (*TorrentList) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{40} -} - -func (x *TorrentList) GetTorrents() []*TorrentSummary { - if x != nil { - return x.Torrents - } - return nil -} - -type TorrentSummary struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` - Tracker string `protobuf:"bytes,3,opt,name=tracker,proto3" json:"tracker,omitempty"` - Seeders int32 `protobuf:"varint,4,opt,name=seeders,proto3" json:"seeders,omitempty"` - Format string `protobuf:"bytes,5,opt,name=format,proto3" json:"format,omitempty"` - Lossless bool `protobuf:"varint,6,opt,name=lossless,proto3" json:"lossless,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TorrentSummary) Reset() { - *x = TorrentSummary{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[41] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TorrentSummary) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TorrentSummary) ProtoMessage() {} - -func (x *TorrentSummary) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[41] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TorrentSummary.ProtoReflect.Descriptor instead. -func (*TorrentSummary) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{41} -} - -func (x *TorrentSummary) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *TorrentSummary) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *TorrentSummary) GetTracker() string { - if x != nil { - return x.Tracker - } - return "" -} - -func (x *TorrentSummary) GetSeeders() int32 { - if x != nil { - return x.Seeders - } - return 0 -} - -func (x *TorrentSummary) GetFormat() string { - if x != nil { - return x.Format - } - return "" -} - -func (x *TorrentSummary) GetLossless() bool { - if x != nil { - return x.Lossless - } - return false -} - -type ReleaseInfo struct { - state protoimpl.MessageState `protogen:"open.v1"` - InfoHash string `protobuf:"bytes,1,opt,name=info_hash,json=infoHash,proto3" json:"info_hash,omitempty"` - Format string `protobuf:"bytes,2,opt,name=format,proto3" json:"format,omitempty"` - BitDepth int32 `protobuf:"varint,3,opt,name=bit_depth,json=bitDepth,proto3" json:"bit_depth,omitempty"` - SampleRate int32 `protobuf:"varint,4,opt,name=sample_rate,json=sampleRate,proto3" json:"sample_rate,omitempty"` - Seeders int32 `protobuf:"varint,5,opt,name=seeders,proto3" json:"seeders,omitempty"` - Tracker string `protobuf:"bytes,6,opt,name=tracker,proto3" json:"tracker,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ReleaseInfo) Reset() { - *x = ReleaseInfo{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[42] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ReleaseInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReleaseInfo) ProtoMessage() {} - -func (x *ReleaseInfo) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[42] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReleaseInfo.ProtoReflect.Descriptor instead. -func (*ReleaseInfo) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{42} -} - -func (x *ReleaseInfo) GetInfoHash() string { - if x != nil { - return x.InfoHash - } - return "" -} - -func (x *ReleaseInfo) GetFormat() string { - if x != nil { - return x.Format - } - return "" -} - -func (x *ReleaseInfo) GetBitDepth() int32 { - if x != nil { - return x.BitDepth - } - return 0 -} - -func (x *ReleaseInfo) GetSampleRate() int32 { - if x != nil { - return x.SampleRate - } - return 0 -} - -func (x *ReleaseInfo) GetSeeders() int32 { - if x != nil { - return x.Seeders - } - return 0 -} - -func (x *ReleaseInfo) GetTracker() string { - if x != nil { - return x.Tracker - } - return "" -} - -type ConfirmPrompt struct { - state protoimpl.MessageState `protogen:"open.v1"` - ConfirmLabel string `protobuf:"bytes,1,opt,name=confirm_label,json=confirmLabel,proto3" json:"confirm_label,omitempty"` - CancelLabel string `protobuf:"bytes,2,opt,name=cancel_label,json=cancelLabel,proto3" json:"cancel_label,omitempty"` - DefaultValue bool `protobuf:"varint,3,opt,name=default_value,json=defaultValue,proto3" json:"default_value,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ConfirmPrompt) Reset() { - *x = ConfirmPrompt{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[43] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ConfirmPrompt) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConfirmPrompt) ProtoMessage() {} - -func (x *ConfirmPrompt) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[43] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConfirmPrompt.ProtoReflect.Descriptor instead. -func (*ConfirmPrompt) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{43} -} - -func (x *ConfirmPrompt) GetConfirmLabel() string { - if x != nil { - return x.ConfirmLabel - } - return "" -} - -func (x *ConfirmPrompt) GetCancelLabel() string { - if x != nil { - return x.CancelLabel - } - return "" -} - -func (x *ConfirmPrompt) GetDefaultValue() bool { - if x != nil { - return x.DefaultValue - } - return false -} - -type SelectOnePrompt struct { - state protoimpl.MessageState `protogen:"open.v1"` - Options []*SelectOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` - DefaultId string `protobuf:"bytes,2,opt,name=default_id,json=defaultId,proto3" json:"default_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SelectOnePrompt) Reset() { - *x = SelectOnePrompt{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[44] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SelectOnePrompt) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SelectOnePrompt) ProtoMessage() {} - -func (x *SelectOnePrompt) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[44] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SelectOnePrompt.ProtoReflect.Descriptor instead. -func (*SelectOnePrompt) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{44} -} - -func (x *SelectOnePrompt) GetOptions() []*SelectOption { - if x != nil { - return x.Options - } - return nil -} - -func (x *SelectOnePrompt) GetDefaultId() string { - if x != nil { - return x.DefaultId - } - return "" -} - -type SelectManyPrompt struct { - state protoimpl.MessageState `protogen:"open.v1"` - Options []*SelectOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` - DefaultIds []string `protobuf:"bytes,2,rep,name=default_ids,json=defaultIds,proto3" json:"default_ids,omitempty"` - MinSelections int32 `protobuf:"varint,3,opt,name=min_selections,json=minSelections,proto3" json:"min_selections,omitempty"` - MaxSelections int32 `protobuf:"varint,4,opt,name=max_selections,json=maxSelections,proto3" json:"max_selections,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SelectManyPrompt) Reset() { - *x = SelectManyPrompt{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[45] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SelectManyPrompt) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SelectManyPrompt) ProtoMessage() {} - -func (x *SelectManyPrompt) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[45] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SelectManyPrompt.ProtoReflect.Descriptor instead. -func (*SelectManyPrompt) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{45} -} - -func (x *SelectManyPrompt) GetOptions() []*SelectOption { - if x != nil { - return x.Options - } - return nil -} - -func (x *SelectManyPrompt) GetDefaultIds() []string { - if x != nil { - return x.DefaultIds - } - return nil -} - -func (x *SelectManyPrompt) GetMinSelections() int32 { - if x != nil { - return x.MinSelections - } - return 0 -} - -func (x *SelectManyPrompt) GetMaxSelections() int32 { - if x != nil { - return x.MaxSelections - } - return 0 -} - -type SelectOption struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"` - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SelectOption) Reset() { - *x = SelectOption{} - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[46] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SelectOption) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SelectOption) ProtoMessage() {} - -func (x *SelectOption) ProtoReflect() protoreflect.Message { - mi := &file_music_agregator_v1_music_agregator_proto_msgTypes[46] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SelectOption.ProtoReflect.Descriptor instead. -func (*SelectOption) Descriptor() ([]byte, []int) { - return file_music_agregator_v1_music_agregator_proto_rawDescGZIP(), []int{46} -} - -func (x *SelectOption) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *SelectOption) GetLabel() string { - if x != nil { - return x.Label - } - return "" -} - -func (x *SelectOption) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -var File_music_agregator_v1_music_agregator_proto protoreflect.FileDescriptor - -const file_music_agregator_v1_music_agregator_proto_rawDesc = "" + - "\n" + - "(music_agregator/v1/music_agregator.proto\x12\x12music_agregator.v1\"/\n" + - "\x12ResyncAlbumRequest\x12\x19\n" + - "\balbum_id\x18\x01 \x01(\tR\aalbumId\"\x82\x01\n" + - "\x13ResyncAlbumResponse\x12!\n" + - "\ffiles_synced\x18\x01 \x01(\x05R\vfilesSynced\x12%\n" + - "\x0efiles_enriched\x18\x02 \x01(\x05R\rfilesEnriched\x12!\n" + - "\fbytes_synced\x18\x03 \x01(\x04R\vbytesSynced\"\xb8\x01\n" + - "\x13MonitorAlbumRequest\x12\x19\n" + - "\balbum_id\x18\x01 \x01(\tR\aalbumId\x12K\n" + - "\x0findexer_options\x18\x02 \x01(\v2\".music_agregator.v1.IndexerOptionsR\x0eindexerOptions\x129\n" + - "\aquality\x18\x03 \x01(\x0e2\x1f.music_agregator.v1.QualityTypeR\aquality\"*\n" + - "\x0eIndexerOptions\x12\x18\n" + - "\atracker\x18\x01 \x01(\tR\atracker\"\xc8\x01\n" + - "\x14MonitorAlbumResponse\x125\n" + - "\x05album\x18\x01 \x01(\v2\x1f.music_agregator.v1.AlbumDetailR\x05album\x129\n" + - "\x06artist\x18\x02 \x01(\v2!.music_agregator.v1.ArtistSummaryR\x06artist\x12>\n" + - "\arelease\x18\x03 \x01(\v2$.music_agregator.v1.MonitoredReleaseR\arelease\"\x13\n" + - "\x11GetArtistsRequest\"Q\n" + - "\x12GetArtistsResponse\x12;\n" + - "\aartists\x18\x01 \x03(\v2!.music_agregator.v1.ArtistSummaryR\aartists\"\xc4\x02\n" + - "\rArtistSummary\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + - "\vexternal_id\x18\x02 \x01(\tR\n" + - "externalId\x12\x12\n" + - "\x04name\x18\x03 \x01(\tR\x04name\x12\x1f\n" + - "\vartist_type\x18\x04 \x01(\tR\n" + - "artistType\x12\x18\n" + - "\acountry\x18\x05 \x01(\tR\acountry\x12\x16\n" + - "\x06genres\x18\x06 \x03(\tR\x06genres\x12\x1b\n" + - "\timage_url\x18\a \x01(\tR\bimageUrl\x12E\n" + - "\rmonitor_state\x18\b \x01(\x0e2 .music_agregator.v1.MonitorStateR\fmonitorState\x127\n" + - "\x06albums\x18\t \x03(\v2\x1f.music_agregator.v1.AlbumDetailR\x06albums\"\xee\x03\n" + - "\vAlbumDetail\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + - "\vexternal_id\x18\x02 \x01(\tR\n" + - "externalId\x12\x14\n" + - "\x05title\x18\x03 \x01(\tR\x05title\x12\x1d\n" + - "\n" + - "album_type\x18\x04 \x01(\tR\talbumType\x12!\n" + - "\frelease_date\x18\x05 \x01(\tR\vreleaseDate\x12!\n" + - "\ftotal_tracks\x18\x06 \x01(\x05R\vtotalTracks\x12\x1f\n" + - "\vtotal_discs\x18\a \x01(\x05R\n" + - "totalDiscs\x12\x1b\n" + - "\tcover_url\x18\b \x01(\tR\bcoverUrl\x12\x16\n" + - "\x06genres\x18\t \x03(\tR\x06genres\x12\x14\n" + - "\x05label\x18\n" + - " \x01(\tR\x05label\x12E\n" + - "\rmonitor_state\x18\v \x01(\x0e2 .music_agregator.v1.MonitorStateR\fmonitorState\x12>\n" + - "\tdownloads\x18\f \x03(\v2 .music_agregator.v1.DownloadInfoR\tdownloads\x12@\n" + - "\arelease\x18\r \x01(\v2&.music_agregator.v1.AlbumReleaseDetailR\arelease\"s\n" + - "\fDownloadInfo\x12\x14\n" + - "\x05state\x18\x01 \x01(\tR\x05state\x12\x16\n" + - "\x06format\x18\x02 \x01(\tR\x06format\x12\x18\n" + - "\aquality\x18\x03 \x01(\tR\aquality\x12\x1b\n" + - "\tsave_path\x18\x04 \x01(\tR\bsavePath\",\n" + - "\x0fGetAlbumRequest\x12\x19\n" + - "\balbum_id\x18\x01 \x01(\tR\aalbumId\"{\n" + - "\tAlbumInfo\x125\n" + - "\x05album\x18\x01 \x01(\v2\x1f.music_agregator.v1.AlbumDetailR\x05album\x127\n" + - "\x06tracks\x18\x02 \x03(\v2\x1f.music_agregator.v1.TrackDetailR\x06tracks\"E\n" + - "\x10GetAlbumResponse\x121\n" + - "\x04info\x18\x01 \x01(\v2\x1d.music_agregator.v1.AlbumInfoR\x04info\"7\n" + - "\x1aAnalyzeAlbumReleaseRequest\x12\x19\n" + - "\balbum_id\x18\x01 \x01(\tR\aalbumId\"P\n" + - "\x1bAnalyzeAlbumReleaseResponse\x121\n" + - "\x04info\x18\x01 \x01(\v2\x1d.music_agregator.v1.AlbumInfoR\x04info\"\xf4\x03\n" + - "\vTrackDetail\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + - "\vexternal_id\x18\x02 \x01(\tR\n" + - "externalId\x12\x14\n" + - "\x05title\x18\x03 \x01(\tR\x05title\x12\x1f\n" + - "\vduration_ms\x18\x04 \x01(\x05R\n" + - "durationMs\x12\x1f\n" + - "\vdisc_number\x18\x05 \x01(\x05R\n" + - "discNumber\x12!\n" + - "\ftrack_number\x18\x06 \x01(\x05R\vtrackNumber\x12\x12\n" + - "\x04isrc\x18\a \x01(\tR\x04isrc\x12\x1a\n" + - "\bexplicit\x18\b \x01(\bR\bexplicit\x12:\n" + - "\aartists\x18\t \x03(\v2 .music_agregator.v1.ArtistCreditR\aartists\x12\x1b\n" + - "\tfile_path\x18\n" + - " \x01(\tR\bfilePath\x12\x1b\n" + - "\tfile_size\x18\v \x01(\x03R\bfileSize\x12\x16\n" + - "\x06format\x18\f \x01(\tR\x06format\x12\x1b\n" + - "\tbit_depth\x18\r \x01(\x05R\bbitDepth\x12\x1f\n" + - "\vsample_rate\x18\x0e \x01(\x05R\n" + - "sampleRate\x12\x1a\n" + - "\bchannels\x18\x0f \x01(\x05R\bchannels\x12!\n" + - "\fbitrate_kbps\x18\x10 \x01(\x05R\vbitrateKbps\"2\n" + - "\fArtistCredit\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\"\xb7\x03\n" + - "\x12AlbumReleaseDetail\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n" + - "\x06format\x18\x02 \x01(\tR\x06format\x12\x1b\n" + - "\tbit_depth\x18\x03 \x01(\x05R\bbitDepth\x12\x1f\n" + - "\vsample_rate\x18\x04 \x01(\x05R\n" + - "sampleRate\x12\x1a\n" + - "\bchannels\x18\x05 \x01(\x05R\bchannels\x12\x1f\n" + - "\vis_lossless\x18\x06 \x01(\bR\n" + - "isLossless\x12\x16\n" + - "\x06source\x18\a \x01(\tR\x06source\x12\x1d\n" + - "\n" + - "total_size\x18\b \x01(\x03R\ttotalSize\x12*\n" + - "\x11total_duration_ms\x18\t \x01(\x05R\x0ftotalDurationMs\x12\x1f\n" + - "\vtrack_count\x18\n" + - " \x01(\x05R\n" + - "trackCount\x12\"\n" + - "\rhas_cover_art\x18\v \x01(\bR\vhasCoverArt\x12\"\n" + - "\rhas_cue_sheet\x18\f \x01(\bR\vhasCueSheet\x12\x1e\n" + - "\vhas_rip_log\x18\r \x01(\bR\thasRipLog\x12\x12\n" + - "\x04path\x18\x0e \x01(\tR\x04path\"\xa8\x04\n" + - "\x10MonitoredRelease\x12\x1b\n" + - "\tinfo_hash\x18\x01 \x01(\tR\binfoHash\x12\x16\n" + - "\x06artist\x18\x02 \x01(\tR\x06artist\x12\x14\n" + - "\x05album\x18\x03 \x01(\tR\x05album\x12\x12\n" + - "\x04year\x18\x04 \x01(\x05R\x04year\x12\x16\n" + - "\x06format\x18\x05 \x01(\tR\x06format\x12\x1a\n" + - "\blossless\x18\x06 \x01(\bR\blossless\x12\x1b\n" + - "\tbit_depth\x18\a \x01(\x05R\bbitDepth\x12\x1f\n" + - "\vsample_rate\x18\b \x01(\x05R\n" + - "sampleRate\x12\x16\n" + - "\x06source\x18\t \x01(\tR\x06source\x12\x1f\n" + - "\vtrack_count\x18\n" + - " \x01(\x05R\n" + - "trackCount\x12\x1f\n" + - "\vtrack_names\x18\v \x03(\tR\n" + - "trackNames\x12\"\n" + - "\rhas_cover_art\x18\f \x01(\bR\vhasCoverArt\x12\"\n" + - "\rhas_cue_sheet\x18\r \x01(\bR\vhasCueSheet\x12\x1e\n" + - "\vhas_rip_log\x18\x0e \x01(\bR\thasRipLog\x12(\n" + - "\x10total_audio_size\x18\x0f \x01(\x03R\x0etotalAudioSize\x12#\n" + - "\rdownload_link\x18\x10 \x01(\tR\fdownloadLink\x12\x18\n" + - "\aseeders\x18\x11 \x01(\x05R\aseeders\x12\x18\n" + - "\atracker\x18\x12 \x01(\tR\atracker\"Z\n" + - "\x14SearchArtistsRequest\x12\x14\n" + - "\x05query\x18\x01 \x01(\tR\x05query\x12\x14\n" + - "\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x16\n" + - "\x06offset\x18\x03 \x01(\x05R\x06offset\"o\n" + - "\x15SearchArtistsResponse\x12@\n" + - "\aartists\x18\x01 \x03(\v2&.music_agregator.v1.SearchArtistResultR\aartists\x12\x14\n" + - "\x05total\x18\x02 \x01(\x05R\x05total\"\xf2\x02\n" + - "\x12SearchArtistResult\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x1b\n" + - "\tsort_name\x18\x03 \x01(\tR\bsortName\x12\x1f\n" + - "\vartist_type\x18\x04 \x01(\tR\n" + - "artistType\x12\x18\n" + - "\acountry\x18\x05 \x01(\tR\acountry\x12\x1f\n" + - "\vformed_date\x18\x06 \x01(\tR\n" + - "formedDate\x12%\n" + - "\x0edisbanded_date\x18\a \x01(\tR\rdisbandedDate\x12 \n" + - "\vdescription\x18\b \x01(\tR\vdescription\x12\x1b\n" + - "\timage_url\x18\t \x01(\tR\bimageUrl\x12\x16\n" + - "\x06genres\x18\n" + - " \x03(\tR\x06genres\x12A\n" + - "\fexternal_ids\x18\v \x03(\v2\x1e.music_agregator.v1.ExternalIdR\vexternalIds\"8\n" + - "\n" + - "ExternalId\x12\x1a\n" + - "\bprovider\x18\x01 \x01(\tR\bprovider\x12\x0e\n" + - "\x02id\x18\x02 \x01(\tR\x02id\"c\n" + - "\x16GetArtistAlbumsRequest\x12\x1b\n" + - "\tartist_id\x18\x01 \x01(\tR\bartistId\x12\x14\n" + - "\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x16\n" + - "\x06offset\x18\x03 \x01(\x05R\x06offset\"h\n" + - "\x17GetArtistAlbumsResponse\x127\n" + - "\x06albums\x18\x01 \x03(\v2\x1f.music_agregator.v1.AlbumResultR\x06albums\x12\x14\n" + - "\x05total\x18\x02 \x01(\x05R\x05total\"\xba\x03\n" + - "\vAlbumResult\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" + - "\x05title\x18\x02 \x01(\tR\x05title\x12\x1d\n" + - "\n" + - "album_type\x18\x03 \x01(\tR\talbumType\x12!\n" + - "\frelease_date\x18\x04 \x01(\tR\vreleaseDate\x12\x10\n" + - "\x03upc\x18\x05 \x01(\tR\x03upc\x12!\n" + - "\ftotal_tracks\x18\x06 \x01(\x05R\vtotalTracks\x12\x1f\n" + - "\vtotal_discs\x18\a \x01(\x05R\n" + - "totalDiscs\x12\x1b\n" + - "\tcover_url\x18\b \x01(\tR\bcoverUrl\x12?\n" + - "\aartists\x18\t \x03(\v2%.music_agregator.v1.AlbumArtistCreditR\aartists\x124\n" + - "\x05label\x18\n" + - " \x01(\v2\x1e.music_agregator.v1.AlbumLabelR\x05label\x12\x16\n" + - "\x06genres\x18\v \x03(\tR\x06genres\x12A\n" + - "\fexternal_ids\x18\f \x03(\v2\x1e.music_agregator.v1.ExternalIdR\vexternalIds\"K\n" + - "\x11AlbumArtistCredit\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" + - "\x04role\x18\x03 \x01(\tR\x04role\"J\n" + - "\n" + - "AlbumLabel\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x18\n" + - "\acountry\x18\x03 \x01(\tR\acountry\"5\n" + - "\x16SubscribeEventsRequest\x12\x1b\n" + - "\tsince_seq\x18\x01 \x01(\x03R\bsinceSeq\"\x88\x02\n" + - "\n" + - "AlbumEvent\x12\x10\n" + - "\x03seq\x18\x01 \x01(\x03R\x03seq\x12&\n" + - "\x0fworkflow_run_id\x18\x02 \x01(\tR\rworkflowRunId\x12\x19\n" + - "\balbum_id\x18\x03 \x01(\tR\aalbumId\x12\x18\n" + - "\aquality\x18\x04 \x01(\tR\aquality\x12\x1d\n" + - "\n" + - "event_type\x18\x05 \x01(\tR\teventType\x12\x12\n" + - "\x04step\x18\x06 \x01(\tR\x04step\x12\x18\n" + - "\amessage\x18\a \x01(\tR\amessage\x12\x1b\n" + - "\tdata_json\x18\b \x01(\fR\bdataJson\x12!\n" + - "\ftimestamp_ms\x18\t \x01(\x03R\vtimestampMs\"\xe4\x01\n" + - "\x19MonitorAlbumStreamRequest\x12?\n" + - "\x05start\x18\x01 \x01(\v2'.music_agregator.v1.StartMonitorRequestH\x00R\x05start\x12>\n" + - "\bdecision\x18\x02 \x01(\v2 .music_agregator.v1.UserDecisionH\x00R\bdecision\x12;\n" + - "\x06cancel\x18\x03 \x01(\v2!.music_agregator.v1.CancelRequestH\x00R\x06cancelB\t\n" + - "\amessage\"\xf1\x01\n" + - "\x13StartMonitorRequest\x12\x19\n" + - "\balbum_id\x18\x01 \x01(\tR\aalbumId\x12K\n" + - "\x0findexer_options\x18\x02 \x01(\v2\".music_agregator.v1.IndexerOptionsR\x0eindexerOptions\x129\n" + - "\aquality\x18\x03 \x01(\x0e2\x1f.music_agregator.v1.QualityTypeR\aquality\x127\n" + - "\x04mode\x18\x04 \x01(\x0e2#.music_agregator.v1.InteractionModeR\x04mode\"\xbc\x01\n" + - "\fUserDecision\x12\x1b\n" + - "\tprompt_id\x18\x01 \x01(\tR\bpromptId\x12\x1a\n" + - "\aconfirm\x18\x02 \x01(\bH\x00R\aconfirm\x12!\n" + - "\vselected_id\x18\x03 \x01(\tH\x00R\n" + - "selectedId\x12D\n" + - "\fselected_ids\x18\x04 \x01(\v2\x1f.music_agregator.v1.SelectedIdsH\x00R\vselectedIdsB\n" + - "\n" + - "\bdecision\"\x1f\n" + - "\vSelectedIds\x12\x10\n" + - "\x03ids\x18\x01 \x03(\tR\x03ids\"\x0f\n" + - "\rCancelRequest\"\xa1\x02\n" + - "\x1aMonitorAlbumStreamResponse\x12:\n" + - "\x06status\x18\x01 \x01(\v2 .music_agregator.v1.StatusUpdateH\x00R\x06status\x12?\n" + - "\x06prompt\x18\x02 \x01(\v2%.music_agregator.v1.PromptForDecisionH\x00R\x06prompt\x12B\n" + - "\x06result\x18\x03 \x01(\v2(.music_agregator.v1.MonitorAlbumResponseH\x00R\x06result\x127\n" + - "\x05error\x18\x04 \x01(\v2\x1f.music_agregator.v1.ErrorUpdateH\x00R\x05errorB\t\n" + - "\amessage\"\xb0\x02\n" + - "\fStatusUpdate\x123\n" + - "\x04step\x18\x01 \x01(\x0e2\x1f.music_agregator.v1.MonitorStepR\x04step\x12\x18\n" + - "\amessage\x18\x02 \x01(\tR\amessage\x12D\n" + - "\n" + - "album_info\x18\n" + - " \x01(\v2#.music_agregator.v1.StreamAlbumInfoH\x00R\talbumInfo\x12=\n" + - "\btorrents\x18\v \x01(\v2\x1f.music_agregator.v1.TorrentListH\x00R\btorrents\x12D\n" + - "\frelease_info\x18\f \x01(\v2\x1f.music_agregator.v1.ReleaseInfoH\x00R\vreleaseInfoB\x06\n" + - "\x04data\"\x80\x03\n" + - "\x11PromptForDecision\x12\x1b\n" + - "\tprompt_id\x18\x01 \x01(\tR\bpromptId\x122\n" + - "\x04type\x18\x02 \x01(\x0e2\x1e.music_agregator.v1.PromptTypeR\x04type\x12\x18\n" + - "\amessage\x18\x03 \x01(\tR\amessage\x12'\n" + - "\x0ftimeout_seconds\x18\x04 \x01(\x05R\x0etimeoutSeconds\x12=\n" + - "\aconfirm\x18\n" + - " \x01(\v2!.music_agregator.v1.ConfirmPromptH\x00R\aconfirm\x12D\n" + - "\n" + - "select_one\x18\v \x01(\v2#.music_agregator.v1.SelectOnePromptH\x00R\tselectOne\x12G\n" + - "\vselect_many\x18\f \x01(\v2$.music_agregator.v1.SelectManyPromptH\x00R\n" + - "selectManyB\t\n" + - "\aoptions\"\x8b\x01\n" + - "\vErrorUpdate\x12@\n" + - "\vfailed_step\x18\x01 \x01(\x0e2\x1f.music_agregator.v1.MonitorStepR\n" + - "failedStep\x12\x18\n" + - "\amessage\x18\x02 \x01(\tR\amessage\x12 \n" + - "\vrecoverable\x18\x03 \x01(\bR\vrecoverable\"\xac\x01\n" + - "\x0fStreamAlbumInfo\x12\x16\n" + - "\x06artist\x18\x01 \x01(\tR\x06artist\x12\x14\n" + - "\x05title\x18\x02 \x01(\tR\x05title\x12!\n" + - "\frelease_date\x18\x03 \x01(\tR\vreleaseDate\x12#\n" + - "\ralready_owned\x18\x04 \x01(\bR\falreadyOwned\x12#\n" + - "\rowned_quality\x18\x05 \x01(\tR\fownedQuality\"M\n" + - "\vTorrentList\x12>\n" + - "\btorrents\x18\x01 \x03(\v2\".music_agregator.v1.TorrentSummaryR\btorrents\"\x9e\x01\n" + - "\x0eTorrentSummary\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" + - "\x05title\x18\x02 \x01(\tR\x05title\x12\x18\n" + - "\atracker\x18\x03 \x01(\tR\atracker\x12\x18\n" + - "\aseeders\x18\x04 \x01(\x05R\aseeders\x12\x16\n" + - "\x06format\x18\x05 \x01(\tR\x06format\x12\x1a\n" + - "\blossless\x18\x06 \x01(\bR\blossless\"\xb4\x01\n" + - "\vReleaseInfo\x12\x1b\n" + - "\tinfo_hash\x18\x01 \x01(\tR\binfoHash\x12\x16\n" + - "\x06format\x18\x02 \x01(\tR\x06format\x12\x1b\n" + - "\tbit_depth\x18\x03 \x01(\x05R\bbitDepth\x12\x1f\n" + - "\vsample_rate\x18\x04 \x01(\x05R\n" + - "sampleRate\x12\x18\n" + - "\aseeders\x18\x05 \x01(\x05R\aseeders\x12\x18\n" + - "\atracker\x18\x06 \x01(\tR\atracker\"|\n" + - "\rConfirmPrompt\x12#\n" + - "\rconfirm_label\x18\x01 \x01(\tR\fconfirmLabel\x12!\n" + - "\fcancel_label\x18\x02 \x01(\tR\vcancelLabel\x12#\n" + - "\rdefault_value\x18\x03 \x01(\bR\fdefaultValue\"l\n" + - "\x0fSelectOnePrompt\x12:\n" + - "\aoptions\x18\x01 \x03(\v2 .music_agregator.v1.SelectOptionR\aoptions\x12\x1d\n" + - "\n" + - "default_id\x18\x02 \x01(\tR\tdefaultId\"\xbd\x01\n" + - "\x10SelectManyPrompt\x12:\n" + - "\aoptions\x18\x01 \x03(\v2 .music_agregator.v1.SelectOptionR\aoptions\x12\x1f\n" + - "\vdefault_ids\x18\x02 \x03(\tR\n" + - "defaultIds\x12%\n" + - "\x0emin_selections\x18\x03 \x01(\x05R\rminSelections\x12%\n" + - "\x0emax_selections\x18\x04 \x01(\x05R\rmaxSelections\"V\n" + - "\fSelectOption\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n" + - "\x05label\x18\x02 \x01(\tR\x05label\x12 \n" + - "\vdescription\x18\x03 \x01(\tR\vdescription*O\n" + - "\vQualityType\x12\x17\n" + - "\x13QUALITY_UNSPECIFIED\x10\x00\x12\x14\n" + - "\x10QUALITY_LOSSLESS\x10\x01\x12\x11\n" + - "\rQUALITY_LOSSY\x10\x02*\x85\x01\n" + - "\fMonitorState\x12\x1d\n" + - "\x19MONITOR_STATE_UNSPECIFIED\x10\x00\x12\x1b\n" + - "\x17MONITOR_STATE_MONITORED\x10\x01\x12\x1d\n" + - "\x19MONITOR_STATE_UNMONITORED\x10\x02\x12\x1a\n" + - "\x16MONITOR_STATE_EXCLUDED\x10\x03*N\n" + - "\x0fInteractionMode\x12\x1e\n" + - "\x1aINTERACTION_MODE_AUTOMATIC\x10\x00\x12\x1b\n" + - "\x17INTERACTION_MODE_MANUAL\x10\x01*\xd3\x02\n" + - "\vMonitorStep\x12\x1c\n" + - "\x18MONITOR_STEP_UNSPECIFIED\x10\x00\x12\"\n" + - "\x1eMONITOR_STEP_FETCHING_METADATA\x10\x01\x12\x1f\n" + - "\x1bMONITOR_STEP_CHECKING_OWNED\x10\x02\x12\"\n" + - "\x1eMONITOR_STEP_SEARCHING_INDEXER\x10\x03\x12 \n" + - "\x1cMONITOR_STEP_PARSING_RESULTS\x10\x04\x12\"\n" + - "\x1eMONITOR_STEP_FILTERING_QUALITY\x10\x05\x12\"\n" + - "\x1eMONITOR_STEP_SELECTING_RELEASE\x10\x06\x12\x1f\n" + - "\x1bMONITOR_STEP_ADDING_TORRENT\x10\a\x12\x17\n" + - "\x13MONITOR_STEP_SAVING\x10\b\x12\x19\n" + - "\x15MONITOR_STEP_COMPLETE\x10\t*{\n" + - "\n" + - "PromptType\x12\x1b\n" + - "\x17PROMPT_TYPE_UNSPECIFIED\x10\x00\x12\x17\n" + - "\x13PROMPT_TYPE_CONFIRM\x10\x01\x12\x1a\n" + - "\x16PROMPT_TYPE_SELECT_ONE\x10\x02\x12\x1b\n" + - "\x17PROMPT_TYPE_SELECT_MANY\x10\x032\xc7\a\n" + - "\x15MusicAgregatorService\x12f\n" + - "\fMonitorAlbum\x12'.music_agregator.v1.MonitorAlbumRequest\x1a(.music_agregator.v1.MonitorAlbumResponse\"\x03\x88\x02\x01\x12y\n" + - "\x12MonitorAlbumStream\x12-.music_agregator.v1.MonitorAlbumStreamRequest\x1a..music_agregator.v1.MonitorAlbumStreamResponse\"\x00(\x010\x01\x12]\n" + - "\n" + - "GetArtists\x12%.music_agregator.v1.GetArtistsRequest\x1a&.music_agregator.v1.GetArtistsResponse\"\x00\x12W\n" + - "\bGetAlbum\x12#.music_agregator.v1.GetAlbumRequest\x1a$.music_agregator.v1.GetAlbumResponse\"\x00\x12x\n" + - "\x13AnalyzeAlbumRelease\x12..music_agregator.v1.AnalyzeAlbumReleaseRequest\x1a/.music_agregator.v1.AnalyzeAlbumReleaseResponse\"\x00\x12f\n" + - "\rSearchArtists\x12(.music_agregator.v1.SearchArtistsRequest\x1a).music_agregator.v1.SearchArtistsResponse\"\x00\x12l\n" + - "\x0fGetArtistAlbums\x12*.music_agregator.v1.GetArtistAlbumsRequest\x1a+.music_agregator.v1.GetArtistAlbumsResponse\"\x00\x12a\n" + - "\x0fSubscribeEvents\x12*.music_agregator.v1.SubscribeEventsRequest\x1a\x1e.music_agregator.v1.AlbumEvent\"\x000\x01\x12`\n" + - "\vResyncAlbum\x12&.music_agregator.v1.ResyncAlbumRequest\x1a'.music_agregator.v1.ResyncAlbumResponse\"\x00B5Z3homelab.lan/music-agregator/gen/music_agregator/v1/b\x06proto3" - -var ( - file_music_agregator_v1_music_agregator_proto_rawDescOnce sync.Once - file_music_agregator_v1_music_agregator_proto_rawDescData []byte -) - -func file_music_agregator_v1_music_agregator_proto_rawDescGZIP() []byte { - file_music_agregator_v1_music_agregator_proto_rawDescOnce.Do(func() { - file_music_agregator_v1_music_agregator_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_music_agregator_v1_music_agregator_proto_rawDesc), len(file_music_agregator_v1_music_agregator_proto_rawDesc))) - }) - return file_music_agregator_v1_music_agregator_proto_rawDescData -} - -var file_music_agregator_v1_music_agregator_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_music_agregator_v1_music_agregator_proto_msgTypes = make([]protoimpl.MessageInfo, 47) -var file_music_agregator_v1_music_agregator_proto_goTypes = []any{ - (QualityType)(0), // 0: music_agregator.v1.QualityType - (MonitorState)(0), // 1: music_agregator.v1.MonitorState - (InteractionMode)(0), // 2: music_agregator.v1.InteractionMode - (MonitorStep)(0), // 3: music_agregator.v1.MonitorStep - (PromptType)(0), // 4: music_agregator.v1.PromptType - (*ResyncAlbumRequest)(nil), // 5: music_agregator.v1.ResyncAlbumRequest - (*ResyncAlbumResponse)(nil), // 6: music_agregator.v1.ResyncAlbumResponse - (*MonitorAlbumRequest)(nil), // 7: music_agregator.v1.MonitorAlbumRequest - (*IndexerOptions)(nil), // 8: music_agregator.v1.IndexerOptions - (*MonitorAlbumResponse)(nil), // 9: music_agregator.v1.MonitorAlbumResponse - (*GetArtistsRequest)(nil), // 10: music_agregator.v1.GetArtistsRequest - (*GetArtistsResponse)(nil), // 11: music_agregator.v1.GetArtistsResponse - (*ArtistSummary)(nil), // 12: music_agregator.v1.ArtistSummary - (*AlbumDetail)(nil), // 13: music_agregator.v1.AlbumDetail - (*DownloadInfo)(nil), // 14: music_agregator.v1.DownloadInfo - (*GetAlbumRequest)(nil), // 15: music_agregator.v1.GetAlbumRequest - (*AlbumInfo)(nil), // 16: music_agregator.v1.AlbumInfo - (*GetAlbumResponse)(nil), // 17: music_agregator.v1.GetAlbumResponse - (*AnalyzeAlbumReleaseRequest)(nil), // 18: music_agregator.v1.AnalyzeAlbumReleaseRequest - (*AnalyzeAlbumReleaseResponse)(nil), // 19: music_agregator.v1.AnalyzeAlbumReleaseResponse - (*TrackDetail)(nil), // 20: music_agregator.v1.TrackDetail - (*ArtistCredit)(nil), // 21: music_agregator.v1.ArtistCredit - (*AlbumReleaseDetail)(nil), // 22: music_agregator.v1.AlbumReleaseDetail - (*MonitoredRelease)(nil), // 23: music_agregator.v1.MonitoredRelease - (*SearchArtistsRequest)(nil), // 24: music_agregator.v1.SearchArtistsRequest - (*SearchArtistsResponse)(nil), // 25: music_agregator.v1.SearchArtistsResponse - (*SearchArtistResult)(nil), // 26: music_agregator.v1.SearchArtistResult - (*ExternalId)(nil), // 27: music_agregator.v1.ExternalId - (*GetArtistAlbumsRequest)(nil), // 28: music_agregator.v1.GetArtistAlbumsRequest - (*GetArtistAlbumsResponse)(nil), // 29: music_agregator.v1.GetArtistAlbumsResponse - (*AlbumResult)(nil), // 30: music_agregator.v1.AlbumResult - (*AlbumArtistCredit)(nil), // 31: music_agregator.v1.AlbumArtistCredit - (*AlbumLabel)(nil), // 32: music_agregator.v1.AlbumLabel - (*SubscribeEventsRequest)(nil), // 33: music_agregator.v1.SubscribeEventsRequest - (*AlbumEvent)(nil), // 34: music_agregator.v1.AlbumEvent - (*MonitorAlbumStreamRequest)(nil), // 35: music_agregator.v1.MonitorAlbumStreamRequest - (*StartMonitorRequest)(nil), // 36: music_agregator.v1.StartMonitorRequest - (*UserDecision)(nil), // 37: music_agregator.v1.UserDecision - (*SelectedIds)(nil), // 38: music_agregator.v1.SelectedIds - (*CancelRequest)(nil), // 39: music_agregator.v1.CancelRequest - (*MonitorAlbumStreamResponse)(nil), // 40: music_agregator.v1.MonitorAlbumStreamResponse - (*StatusUpdate)(nil), // 41: music_agregator.v1.StatusUpdate - (*PromptForDecision)(nil), // 42: music_agregator.v1.PromptForDecision - (*ErrorUpdate)(nil), // 43: music_agregator.v1.ErrorUpdate - (*StreamAlbumInfo)(nil), // 44: music_agregator.v1.StreamAlbumInfo - (*TorrentList)(nil), // 45: music_agregator.v1.TorrentList - (*TorrentSummary)(nil), // 46: music_agregator.v1.TorrentSummary - (*ReleaseInfo)(nil), // 47: music_agregator.v1.ReleaseInfo - (*ConfirmPrompt)(nil), // 48: music_agregator.v1.ConfirmPrompt - (*SelectOnePrompt)(nil), // 49: music_agregator.v1.SelectOnePrompt - (*SelectManyPrompt)(nil), // 50: music_agregator.v1.SelectManyPrompt - (*SelectOption)(nil), // 51: music_agregator.v1.SelectOption -} -var file_music_agregator_v1_music_agregator_proto_depIdxs = []int32{ - 8, // 0: music_agregator.v1.MonitorAlbumRequest.indexer_options:type_name -> music_agregator.v1.IndexerOptions - 0, // 1: music_agregator.v1.MonitorAlbumRequest.quality:type_name -> music_agregator.v1.QualityType - 13, // 2: music_agregator.v1.MonitorAlbumResponse.album:type_name -> music_agregator.v1.AlbumDetail - 12, // 3: music_agregator.v1.MonitorAlbumResponse.artist:type_name -> music_agregator.v1.ArtistSummary - 23, // 4: music_agregator.v1.MonitorAlbumResponse.release:type_name -> music_agregator.v1.MonitoredRelease - 12, // 5: music_agregator.v1.GetArtistsResponse.artists:type_name -> music_agregator.v1.ArtistSummary - 1, // 6: music_agregator.v1.ArtistSummary.monitor_state:type_name -> music_agregator.v1.MonitorState - 13, // 7: music_agregator.v1.ArtistSummary.albums:type_name -> music_agregator.v1.AlbumDetail - 1, // 8: music_agregator.v1.AlbumDetail.monitor_state:type_name -> music_agregator.v1.MonitorState - 14, // 9: music_agregator.v1.AlbumDetail.downloads:type_name -> music_agregator.v1.DownloadInfo - 22, // 10: music_agregator.v1.AlbumDetail.release:type_name -> music_agregator.v1.AlbumReleaseDetail - 13, // 11: music_agregator.v1.AlbumInfo.album:type_name -> music_agregator.v1.AlbumDetail - 20, // 12: music_agregator.v1.AlbumInfo.tracks:type_name -> music_agregator.v1.TrackDetail - 16, // 13: music_agregator.v1.GetAlbumResponse.info:type_name -> music_agregator.v1.AlbumInfo - 16, // 14: music_agregator.v1.AnalyzeAlbumReleaseResponse.info:type_name -> music_agregator.v1.AlbumInfo - 21, // 15: music_agregator.v1.TrackDetail.artists:type_name -> music_agregator.v1.ArtistCredit - 26, // 16: music_agregator.v1.SearchArtistsResponse.artists:type_name -> music_agregator.v1.SearchArtistResult - 27, // 17: music_agregator.v1.SearchArtistResult.external_ids:type_name -> music_agregator.v1.ExternalId - 30, // 18: music_agregator.v1.GetArtistAlbumsResponse.albums:type_name -> music_agregator.v1.AlbumResult - 31, // 19: music_agregator.v1.AlbumResult.artists:type_name -> music_agregator.v1.AlbumArtistCredit - 32, // 20: music_agregator.v1.AlbumResult.label:type_name -> music_agregator.v1.AlbumLabel - 27, // 21: music_agregator.v1.AlbumResult.external_ids:type_name -> music_agregator.v1.ExternalId - 36, // 22: music_agregator.v1.MonitorAlbumStreamRequest.start:type_name -> music_agregator.v1.StartMonitorRequest - 37, // 23: music_agregator.v1.MonitorAlbumStreamRequest.decision:type_name -> music_agregator.v1.UserDecision - 39, // 24: music_agregator.v1.MonitorAlbumStreamRequest.cancel:type_name -> music_agregator.v1.CancelRequest - 8, // 25: music_agregator.v1.StartMonitorRequest.indexer_options:type_name -> music_agregator.v1.IndexerOptions - 0, // 26: music_agregator.v1.StartMonitorRequest.quality:type_name -> music_agregator.v1.QualityType - 2, // 27: music_agregator.v1.StartMonitorRequest.mode:type_name -> music_agregator.v1.InteractionMode - 38, // 28: music_agregator.v1.UserDecision.selected_ids:type_name -> music_agregator.v1.SelectedIds - 41, // 29: music_agregator.v1.MonitorAlbumStreamResponse.status:type_name -> music_agregator.v1.StatusUpdate - 42, // 30: music_agregator.v1.MonitorAlbumStreamResponse.prompt:type_name -> music_agregator.v1.PromptForDecision - 9, // 31: music_agregator.v1.MonitorAlbumStreamResponse.result:type_name -> music_agregator.v1.MonitorAlbumResponse - 43, // 32: music_agregator.v1.MonitorAlbumStreamResponse.error:type_name -> music_agregator.v1.ErrorUpdate - 3, // 33: music_agregator.v1.StatusUpdate.step:type_name -> music_agregator.v1.MonitorStep - 44, // 34: music_agregator.v1.StatusUpdate.album_info:type_name -> music_agregator.v1.StreamAlbumInfo - 45, // 35: music_agregator.v1.StatusUpdate.torrents:type_name -> music_agregator.v1.TorrentList - 47, // 36: music_agregator.v1.StatusUpdate.release_info:type_name -> music_agregator.v1.ReleaseInfo - 4, // 37: music_agregator.v1.PromptForDecision.type:type_name -> music_agregator.v1.PromptType - 48, // 38: music_agregator.v1.PromptForDecision.confirm:type_name -> music_agregator.v1.ConfirmPrompt - 49, // 39: music_agregator.v1.PromptForDecision.select_one:type_name -> music_agregator.v1.SelectOnePrompt - 50, // 40: music_agregator.v1.PromptForDecision.select_many:type_name -> music_agregator.v1.SelectManyPrompt - 3, // 41: music_agregator.v1.ErrorUpdate.failed_step:type_name -> music_agregator.v1.MonitorStep - 46, // 42: music_agregator.v1.TorrentList.torrents:type_name -> music_agregator.v1.TorrentSummary - 51, // 43: music_agregator.v1.SelectOnePrompt.options:type_name -> music_agregator.v1.SelectOption - 51, // 44: music_agregator.v1.SelectManyPrompt.options:type_name -> music_agregator.v1.SelectOption - 7, // 45: music_agregator.v1.MusicAgregatorService.MonitorAlbum:input_type -> music_agregator.v1.MonitorAlbumRequest - 35, // 46: music_agregator.v1.MusicAgregatorService.MonitorAlbumStream:input_type -> music_agregator.v1.MonitorAlbumStreamRequest - 10, // 47: music_agregator.v1.MusicAgregatorService.GetArtists:input_type -> music_agregator.v1.GetArtistsRequest - 15, // 48: music_agregator.v1.MusicAgregatorService.GetAlbum:input_type -> music_agregator.v1.GetAlbumRequest - 18, // 49: music_agregator.v1.MusicAgregatorService.AnalyzeAlbumRelease:input_type -> music_agregator.v1.AnalyzeAlbumReleaseRequest - 24, // 50: music_agregator.v1.MusicAgregatorService.SearchArtists:input_type -> music_agregator.v1.SearchArtistsRequest - 28, // 51: music_agregator.v1.MusicAgregatorService.GetArtistAlbums:input_type -> music_agregator.v1.GetArtistAlbumsRequest - 33, // 52: music_agregator.v1.MusicAgregatorService.SubscribeEvents:input_type -> music_agregator.v1.SubscribeEventsRequest - 5, // 53: music_agregator.v1.MusicAgregatorService.ResyncAlbum:input_type -> music_agregator.v1.ResyncAlbumRequest - 9, // 54: music_agregator.v1.MusicAgregatorService.MonitorAlbum:output_type -> music_agregator.v1.MonitorAlbumResponse - 40, // 55: music_agregator.v1.MusicAgregatorService.MonitorAlbumStream:output_type -> music_agregator.v1.MonitorAlbumStreamResponse - 11, // 56: music_agregator.v1.MusicAgregatorService.GetArtists:output_type -> music_agregator.v1.GetArtistsResponse - 17, // 57: music_agregator.v1.MusicAgregatorService.GetAlbum:output_type -> music_agregator.v1.GetAlbumResponse - 19, // 58: music_agregator.v1.MusicAgregatorService.AnalyzeAlbumRelease:output_type -> music_agregator.v1.AnalyzeAlbumReleaseResponse - 25, // 59: music_agregator.v1.MusicAgregatorService.SearchArtists:output_type -> music_agregator.v1.SearchArtistsResponse - 29, // 60: music_agregator.v1.MusicAgregatorService.GetArtistAlbums:output_type -> music_agregator.v1.GetArtistAlbumsResponse - 34, // 61: music_agregator.v1.MusicAgregatorService.SubscribeEvents:output_type -> music_agregator.v1.AlbumEvent - 6, // 62: music_agregator.v1.MusicAgregatorService.ResyncAlbum:output_type -> music_agregator.v1.ResyncAlbumResponse - 54, // [54:63] is the sub-list for method output_type - 45, // [45:54] is the sub-list for method input_type - 45, // [45:45] is the sub-list for extension type_name - 45, // [45:45] is the sub-list for extension extendee - 0, // [0:45] is the sub-list for field type_name -} - -func init() { file_music_agregator_v1_music_agregator_proto_init() } -func file_music_agregator_v1_music_agregator_proto_init() { - if File_music_agregator_v1_music_agregator_proto != nil { - return - } - file_music_agregator_v1_music_agregator_proto_msgTypes[30].OneofWrappers = []any{ - (*MonitorAlbumStreamRequest_Start)(nil), - (*MonitorAlbumStreamRequest_Decision)(nil), - (*MonitorAlbumStreamRequest_Cancel)(nil), - } - file_music_agregator_v1_music_agregator_proto_msgTypes[32].OneofWrappers = []any{ - (*UserDecision_Confirm)(nil), - (*UserDecision_SelectedId)(nil), - (*UserDecision_SelectedIds)(nil), - } - file_music_agregator_v1_music_agregator_proto_msgTypes[35].OneofWrappers = []any{ - (*MonitorAlbumStreamResponse_Status)(nil), - (*MonitorAlbumStreamResponse_Prompt)(nil), - (*MonitorAlbumStreamResponse_Result)(nil), - (*MonitorAlbumStreamResponse_Error)(nil), - } - file_music_agregator_v1_music_agregator_proto_msgTypes[36].OneofWrappers = []any{ - (*StatusUpdate_AlbumInfo)(nil), - (*StatusUpdate_Torrents)(nil), - (*StatusUpdate_ReleaseInfo)(nil), - } - file_music_agregator_v1_music_agregator_proto_msgTypes[37].OneofWrappers = []any{ - (*PromptForDecision_Confirm)(nil), - (*PromptForDecision_SelectOne)(nil), - (*PromptForDecision_SelectMany)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_music_agregator_v1_music_agregator_proto_rawDesc), len(file_music_agregator_v1_music_agregator_proto_rawDesc)), - NumEnums: 5, - NumMessages: 47, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_music_agregator_v1_music_agregator_proto_goTypes, - DependencyIndexes: file_music_agregator_v1_music_agregator_proto_depIdxs, - EnumInfos: file_music_agregator_v1_music_agregator_proto_enumTypes, - MessageInfos: file_music_agregator_v1_music_agregator_proto_msgTypes, - }.Build() - File_music_agregator_v1_music_agregator_proto = out.File - file_music_agregator_v1_music_agregator_proto_goTypes = nil - file_music_agregator_v1_music_agregator_proto_depIdxs = nil -} diff --git a/gen/music_agregator/v1/music_agregator_grpc.pb.go b/gen/music_agregator/v1/music_agregator_grpc.pb.go deleted file mode 100644 index 54e6347..0000000 --- a/gen/music_agregator/v1/music_agregator_grpc.pb.go +++ /dev/null @@ -1,426 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.1 -// - protoc (unknown) -// source: music_agregator/v1/music_agregator.proto - -package v1 - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - MusicAgregatorService_MonitorAlbum_FullMethodName = "/music_agregator.v1.MusicAgregatorService/MonitorAlbum" - MusicAgregatorService_MonitorAlbumStream_FullMethodName = "/music_agregator.v1.MusicAgregatorService/MonitorAlbumStream" - MusicAgregatorService_GetArtists_FullMethodName = "/music_agregator.v1.MusicAgregatorService/GetArtists" - MusicAgregatorService_GetAlbum_FullMethodName = "/music_agregator.v1.MusicAgregatorService/GetAlbum" - MusicAgregatorService_AnalyzeAlbumRelease_FullMethodName = "/music_agregator.v1.MusicAgregatorService/AnalyzeAlbumRelease" - MusicAgregatorService_SearchArtists_FullMethodName = "/music_agregator.v1.MusicAgregatorService/SearchArtists" - MusicAgregatorService_GetArtistAlbums_FullMethodName = "/music_agregator.v1.MusicAgregatorService/GetArtistAlbums" - MusicAgregatorService_SubscribeEvents_FullMethodName = "/music_agregator.v1.MusicAgregatorService/SubscribeEvents" - MusicAgregatorService_ResyncAlbum_FullMethodName = "/music_agregator.v1.MusicAgregatorService/ResyncAlbum" -) - -// MusicAgregatorServiceClient is the client API for MusicAgregatorService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type MusicAgregatorServiceClient interface { - // Deprecated: Do not use. - MonitorAlbum(ctx context.Context, in *MonitorAlbumRequest, opts ...grpc.CallOption) (*MonitorAlbumResponse, error) - MonitorAlbumStream(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[MonitorAlbumStreamRequest, MonitorAlbumStreamResponse], error) - GetArtists(ctx context.Context, in *GetArtistsRequest, opts ...grpc.CallOption) (*GetArtistsResponse, error) - GetAlbum(ctx context.Context, in *GetAlbumRequest, opts ...grpc.CallOption) (*GetAlbumResponse, error) - AnalyzeAlbumRelease(ctx context.Context, in *AnalyzeAlbumReleaseRequest, opts ...grpc.CallOption) (*AnalyzeAlbumReleaseResponse, error) - SearchArtists(ctx context.Context, in *SearchArtistsRequest, opts ...grpc.CallOption) (*SearchArtistsResponse, error) - GetArtistAlbums(ctx context.Context, in *GetArtistAlbumsRequest, opts ...grpc.CallOption) (*GetArtistAlbumsResponse, error) - SubscribeEvents(ctx context.Context, in *SubscribeEventsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[AlbumEvent], error) - ResyncAlbum(ctx context.Context, in *ResyncAlbumRequest, opts ...grpc.CallOption) (*ResyncAlbumResponse, error) -} - -type musicAgregatorServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewMusicAgregatorServiceClient(cc grpc.ClientConnInterface) MusicAgregatorServiceClient { - return &musicAgregatorServiceClient{cc} -} - -// Deprecated: Do not use. -func (c *musicAgregatorServiceClient) MonitorAlbum(ctx context.Context, in *MonitorAlbumRequest, opts ...grpc.CallOption) (*MonitorAlbumResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(MonitorAlbumResponse) - err := c.cc.Invoke(ctx, MusicAgregatorService_MonitorAlbum_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicAgregatorServiceClient) MonitorAlbumStream(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[MonitorAlbumStreamRequest, MonitorAlbumStreamResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicAgregatorService_ServiceDesc.Streams[0], MusicAgregatorService_MonitorAlbumStream_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[MonitorAlbumStreamRequest, MonitorAlbumStreamResponse]{ClientStream: stream} - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicAgregatorService_MonitorAlbumStreamClient = grpc.BidiStreamingClient[MonitorAlbumStreamRequest, MonitorAlbumStreamResponse] - -func (c *musicAgregatorServiceClient) GetArtists(ctx context.Context, in *GetArtistsRequest, opts ...grpc.CallOption) (*GetArtistsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetArtistsResponse) - err := c.cc.Invoke(ctx, MusicAgregatorService_GetArtists_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicAgregatorServiceClient) GetAlbum(ctx context.Context, in *GetAlbumRequest, opts ...grpc.CallOption) (*GetAlbumResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetAlbumResponse) - err := c.cc.Invoke(ctx, MusicAgregatorService_GetAlbum_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicAgregatorServiceClient) AnalyzeAlbumRelease(ctx context.Context, in *AnalyzeAlbumReleaseRequest, opts ...grpc.CallOption) (*AnalyzeAlbumReleaseResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(AnalyzeAlbumReleaseResponse) - err := c.cc.Invoke(ctx, MusicAgregatorService_AnalyzeAlbumRelease_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicAgregatorServiceClient) SearchArtists(ctx context.Context, in *SearchArtistsRequest, opts ...grpc.CallOption) (*SearchArtistsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SearchArtistsResponse) - err := c.cc.Invoke(ctx, MusicAgregatorService_SearchArtists_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicAgregatorServiceClient) GetArtistAlbums(ctx context.Context, in *GetArtistAlbumsRequest, opts ...grpc.CallOption) (*GetArtistAlbumsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetArtistAlbumsResponse) - err := c.cc.Invoke(ctx, MusicAgregatorService_GetArtistAlbums_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicAgregatorServiceClient) SubscribeEvents(ctx context.Context, in *SubscribeEventsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[AlbumEvent], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicAgregatorService_ServiceDesc.Streams[1], MusicAgregatorService_SubscribeEvents_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[SubscribeEventsRequest, AlbumEvent]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicAgregatorService_SubscribeEventsClient = grpc.ServerStreamingClient[AlbumEvent] - -func (c *musicAgregatorServiceClient) ResyncAlbum(ctx context.Context, in *ResyncAlbumRequest, opts ...grpc.CallOption) (*ResyncAlbumResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ResyncAlbumResponse) - err := c.cc.Invoke(ctx, MusicAgregatorService_ResyncAlbum_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -// MusicAgregatorServiceServer is the server API for MusicAgregatorService service. -// All implementations must embed UnimplementedMusicAgregatorServiceServer -// for forward compatibility. -type MusicAgregatorServiceServer interface { - // Deprecated: Do not use. - MonitorAlbum(context.Context, *MonitorAlbumRequest) (*MonitorAlbumResponse, error) - MonitorAlbumStream(grpc.BidiStreamingServer[MonitorAlbumStreamRequest, MonitorAlbumStreamResponse]) error - GetArtists(context.Context, *GetArtistsRequest) (*GetArtistsResponse, error) - GetAlbum(context.Context, *GetAlbumRequest) (*GetAlbumResponse, error) - AnalyzeAlbumRelease(context.Context, *AnalyzeAlbumReleaseRequest) (*AnalyzeAlbumReleaseResponse, error) - SearchArtists(context.Context, *SearchArtistsRequest) (*SearchArtistsResponse, error) - GetArtistAlbums(context.Context, *GetArtistAlbumsRequest) (*GetArtistAlbumsResponse, error) - SubscribeEvents(*SubscribeEventsRequest, grpc.ServerStreamingServer[AlbumEvent]) error - ResyncAlbum(context.Context, *ResyncAlbumRequest) (*ResyncAlbumResponse, error) - mustEmbedUnimplementedMusicAgregatorServiceServer() -} - -// UnimplementedMusicAgregatorServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedMusicAgregatorServiceServer struct{} - -func (UnimplementedMusicAgregatorServiceServer) MonitorAlbum(context.Context, *MonitorAlbumRequest) (*MonitorAlbumResponse, error) { - return nil, status.Error(codes.Unimplemented, "method MonitorAlbum not implemented") -} -func (UnimplementedMusicAgregatorServiceServer) MonitorAlbumStream(grpc.BidiStreamingServer[MonitorAlbumStreamRequest, MonitorAlbumStreamResponse]) error { - return status.Error(codes.Unimplemented, "method MonitorAlbumStream not implemented") -} -func (UnimplementedMusicAgregatorServiceServer) GetArtists(context.Context, *GetArtistsRequest) (*GetArtistsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetArtists not implemented") -} -func (UnimplementedMusicAgregatorServiceServer) GetAlbum(context.Context, *GetAlbumRequest) (*GetAlbumResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetAlbum not implemented") -} -func (UnimplementedMusicAgregatorServiceServer) AnalyzeAlbumRelease(context.Context, *AnalyzeAlbumReleaseRequest) (*AnalyzeAlbumReleaseResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AnalyzeAlbumRelease not implemented") -} -func (UnimplementedMusicAgregatorServiceServer) SearchArtists(context.Context, *SearchArtistsRequest) (*SearchArtistsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SearchArtists not implemented") -} -func (UnimplementedMusicAgregatorServiceServer) GetArtistAlbums(context.Context, *GetArtistAlbumsRequest) (*GetArtistAlbumsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetArtistAlbums not implemented") -} -func (UnimplementedMusicAgregatorServiceServer) SubscribeEvents(*SubscribeEventsRequest, grpc.ServerStreamingServer[AlbumEvent]) error { - return status.Error(codes.Unimplemented, "method SubscribeEvents not implemented") -} -func (UnimplementedMusicAgregatorServiceServer) ResyncAlbum(context.Context, *ResyncAlbumRequest) (*ResyncAlbumResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ResyncAlbum not implemented") -} -func (UnimplementedMusicAgregatorServiceServer) mustEmbedUnimplementedMusicAgregatorServiceServer() {} -func (UnimplementedMusicAgregatorServiceServer) testEmbeddedByValue() {} - -// UnsafeMusicAgregatorServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to MusicAgregatorServiceServer will -// result in compilation errors. -type UnsafeMusicAgregatorServiceServer interface { - mustEmbedUnimplementedMusicAgregatorServiceServer() -} - -func RegisterMusicAgregatorServiceServer(s grpc.ServiceRegistrar, srv MusicAgregatorServiceServer) { - // If the following call panics, it indicates UnimplementedMusicAgregatorServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&MusicAgregatorService_ServiceDesc, srv) -} - -func _MusicAgregatorService_MonitorAlbum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MonitorAlbumRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicAgregatorServiceServer).MonitorAlbum(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicAgregatorService_MonitorAlbum_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicAgregatorServiceServer).MonitorAlbum(ctx, req.(*MonitorAlbumRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicAgregatorService_MonitorAlbumStream_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(MusicAgregatorServiceServer).MonitorAlbumStream(&grpc.GenericServerStream[MonitorAlbumStreamRequest, MonitorAlbumStreamResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicAgregatorService_MonitorAlbumStreamServer = grpc.BidiStreamingServer[MonitorAlbumStreamRequest, MonitorAlbumStreamResponse] - -func _MusicAgregatorService_GetArtists_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetArtistsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicAgregatorServiceServer).GetArtists(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicAgregatorService_GetArtists_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicAgregatorServiceServer).GetArtists(ctx, req.(*GetArtistsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicAgregatorService_GetAlbum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetAlbumRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicAgregatorServiceServer).GetAlbum(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicAgregatorService_GetAlbum_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicAgregatorServiceServer).GetAlbum(ctx, req.(*GetAlbumRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicAgregatorService_AnalyzeAlbumRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AnalyzeAlbumReleaseRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicAgregatorServiceServer).AnalyzeAlbumRelease(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicAgregatorService_AnalyzeAlbumRelease_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicAgregatorServiceServer).AnalyzeAlbumRelease(ctx, req.(*AnalyzeAlbumReleaseRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicAgregatorService_SearchArtists_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SearchArtistsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicAgregatorServiceServer).SearchArtists(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicAgregatorService_SearchArtists_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicAgregatorServiceServer).SearchArtists(ctx, req.(*SearchArtistsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicAgregatorService_GetArtistAlbums_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetArtistAlbumsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicAgregatorServiceServer).GetArtistAlbums(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicAgregatorService_GetArtistAlbums_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicAgregatorServiceServer).GetArtistAlbums(ctx, req.(*GetArtistAlbumsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicAgregatorService_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SubscribeEventsRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MusicAgregatorServiceServer).SubscribeEvents(m, &grpc.GenericServerStream[SubscribeEventsRequest, AlbumEvent]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicAgregatorService_SubscribeEventsServer = grpc.ServerStreamingServer[AlbumEvent] - -func _MusicAgregatorService_ResyncAlbum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ResyncAlbumRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicAgregatorServiceServer).ResyncAlbum(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicAgregatorService_ResyncAlbum_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicAgregatorServiceServer).ResyncAlbum(ctx, req.(*ResyncAlbumRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// MusicAgregatorService_ServiceDesc is the grpc.ServiceDesc for MusicAgregatorService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var MusicAgregatorService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "music_agregator.v1.MusicAgregatorService", - HandlerType: (*MusicAgregatorServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "MonitorAlbum", - Handler: _MusicAgregatorService_MonitorAlbum_Handler, - }, - { - MethodName: "GetArtists", - Handler: _MusicAgregatorService_GetArtists_Handler, - }, - { - MethodName: "GetAlbum", - Handler: _MusicAgregatorService_GetAlbum_Handler, - }, - { - MethodName: "AnalyzeAlbumRelease", - Handler: _MusicAgregatorService_AnalyzeAlbumRelease_Handler, - }, - { - MethodName: "SearchArtists", - Handler: _MusicAgregatorService_SearchArtists_Handler, - }, - { - MethodName: "GetArtistAlbums", - Handler: _MusicAgregatorService_GetArtistAlbums_Handler, - }, - { - MethodName: "ResyncAlbum", - Handler: _MusicAgregatorService_ResyncAlbum_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "MonitorAlbumStream", - Handler: _MusicAgregatorService_MonitorAlbumStream_Handler, - ServerStreams: true, - ClientStreams: true, - }, - { - StreamName: "SubscribeEvents", - Handler: _MusicAgregatorService_SubscribeEvents_Handler, - ServerStreams: true, - }, - }, - Metadata: "music_agregator/v1/music_agregator.proto", -} diff --git a/gen/musicfs.pb.go b/gen/musicfs.pb.go deleted file mode 100644 index 677a490..0000000 --- a/gen/musicfs.pb.go +++ /dev/null @@ -1,3274 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc (unknown) -// source: musicfs.proto - -package musicfsv1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type MountState int32 - -const ( - MountState_MOUNT_UNKNOWN MountState = 0 - MountState_MOUNT_MOUNTING MountState = 1 - MountState_MOUNT_READY MountState = 2 - MountState_MOUNT_SYNCING MountState = 3 - MountState_MOUNT_DEGRADED MountState = 4 - MountState_MOUNT_UNMOUNTING MountState = 5 -) - -// Enum value maps for MountState. -var ( - MountState_name = map[int32]string{ - 0: "MOUNT_UNKNOWN", - 1: "MOUNT_MOUNTING", - 2: "MOUNT_READY", - 3: "MOUNT_SYNCING", - 4: "MOUNT_DEGRADED", - 5: "MOUNT_UNMOUNTING", - } - MountState_value = map[string]int32{ - "MOUNT_UNKNOWN": 0, - "MOUNT_MOUNTING": 1, - "MOUNT_READY": 2, - "MOUNT_SYNCING": 3, - "MOUNT_DEGRADED": 4, - "MOUNT_UNMOUNTING": 5, - } -) - -func (x MountState) Enum() *MountState { - p := new(MountState) - *p = x - return p -} - -func (x MountState) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MountState) Descriptor() protoreflect.EnumDescriptor { - return file_musicfs_proto_enumTypes[0].Descriptor() -} - -func (MountState) Type() protoreflect.EnumType { - return &file_musicfs_proto_enumTypes[0] -} - -func (x MountState) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MountState.Descriptor instead. -func (MountState) EnumDescriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{0} -} - -type HealthStatus int32 - -const ( - HealthStatus_HEALTH_UNKNOWN HealthStatus = 0 - HealthStatus_HEALTH_HEALTHY HealthStatus = 1 - HealthStatus_HEALTH_DEGRADED HealthStatus = 2 - HealthStatus_HEALTH_UNHEALTHY HealthStatus = 3 -) - -// Enum value maps for HealthStatus. -var ( - HealthStatus_name = map[int32]string{ - 0: "HEALTH_UNKNOWN", - 1: "HEALTH_HEALTHY", - 2: "HEALTH_DEGRADED", - 3: "HEALTH_UNHEALTHY", - } - HealthStatus_value = map[string]int32{ - "HEALTH_UNKNOWN": 0, - "HEALTH_HEALTHY": 1, - "HEALTH_DEGRADED": 2, - "HEALTH_UNHEALTHY": 3, - } -) - -func (x HealthStatus) Enum() *HealthStatus { - p := new(HealthStatus) - *p = x - return p -} - -func (x HealthStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HealthStatus) Descriptor() protoreflect.EnumDescriptor { - return file_musicfs_proto_enumTypes[1].Descriptor() -} - -func (HealthStatus) Type() protoreflect.EnumType { - return &file_musicfs_proto_enumTypes[1] -} - -func (x HealthStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HealthStatus.Descriptor instead. -func (HealthStatus) EnumDescriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{1} -} - -type Empty struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Empty) Reset() { - *x = Empty{} - mi := &file_musicfs_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Empty) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Empty) ProtoMessage() {} - -func (x *Empty) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Empty.ProtoReflect.Descriptor instead. -func (*Empty) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{0} -} - -type SearchRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` - Limit *uint32 `protobuf:"varint,2,opt,name=limit,proto3,oneof" json:"limit,omitempty"` - Offset *uint32 `protobuf:"varint,3,opt,name=offset,proto3,oneof" json:"offset,omitempty"` - OriginId *string `protobuf:"bytes,4,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchRequest) Reset() { - *x = SearchRequest{} - mi := &file_musicfs_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchRequest) ProtoMessage() {} - -func (x *SearchRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchRequest.ProtoReflect.Descriptor instead. -func (*SearchRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{1} -} - -func (x *SearchRequest) GetQuery() string { - if x != nil { - return x.Query - } - return "" -} - -func (x *SearchRequest) GetLimit() uint32 { - if x != nil && x.Limit != nil { - return *x.Limit - } - return 0 -} - -func (x *SearchRequest) GetOffset() uint32 { - if x != nil && x.Offset != nil { - return *x.Offset - } - return 0 -} - -func (x *SearchRequest) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -type SearchResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Results []*SearchResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` - TotalMatches uint64 `protobuf:"varint,2,opt,name=total_matches,json=totalMatches,proto3" json:"total_matches,omitempty"` - QueryTimeMs uint32 `protobuf:"varint,3,opt,name=query_time_ms,json=queryTimeMs,proto3" json:"query_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchResponse) Reset() { - *x = SearchResponse{} - mi := &file_musicfs_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchResponse) ProtoMessage() {} - -func (x *SearchResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchResponse.ProtoReflect.Descriptor instead. -func (*SearchResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{2} -} - -func (x *SearchResponse) GetResults() []*SearchResult { - if x != nil { - return x.Results - } - return nil -} - -func (x *SearchResponse) GetTotalMatches() uint64 { - if x != nil { - return x.TotalMatches - } - return 0 -} - -func (x *SearchResponse) GetQueryTimeMs() uint32 { - if x != nil { - return x.QueryTimeMs - } - return 0 -} - -type SearchResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - VirtualPath string `protobuf:"bytes,2,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"` - Artist *string `protobuf:"bytes,3,opt,name=artist,proto3,oneof" json:"artist,omitempty"` - Album *string `protobuf:"bytes,4,opt,name=album,proto3,oneof" json:"album,omitempty"` - Title *string `protobuf:"bytes,5,opt,name=title,proto3,oneof" json:"title,omitempty"` - Score float32 `protobuf:"fixed32,6,opt,name=score,proto3" json:"score,omitempty"` - Highlights map[string]string `protobuf:"bytes,7,rep,name=highlights,proto3" json:"highlights,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchResult) Reset() { - *x = SearchResult{} - mi := &file_musicfs_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchResult) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchResult) ProtoMessage() {} - -func (x *SearchResult) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchResult.ProtoReflect.Descriptor instead. -func (*SearchResult) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{3} -} - -func (x *SearchResult) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *SearchResult) GetVirtualPath() string { - if x != nil { - return x.VirtualPath - } - return "" -} - -func (x *SearchResult) GetArtist() string { - if x != nil && x.Artist != nil { - return *x.Artist - } - return "" -} - -func (x *SearchResult) GetAlbum() string { - if x != nil && x.Album != nil { - return *x.Album - } - return "" -} - -func (x *SearchResult) GetTitle() string { - if x != nil && x.Title != nil { - return *x.Title - } - return "" -} - -func (x *SearchResult) GetScore() float32 { - if x != nil { - return x.Score - } - return 0 -} - -func (x *SearchResult) GetHighlights() map[string]string { - if x != nil { - return x.Highlights - } - return nil -} - -type StatusResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` - UptimeSecs uint64 `protobuf:"varint,2,opt,name=uptime_secs,json=uptimeSecs,proto3" json:"uptime_secs,omitempty"` - MountPoint string `protobuf:"bytes,3,opt,name=mount_point,json=mountPoint,proto3" json:"mount_point,omitempty"` - State MountState `protobuf:"varint,4,opt,name=state,proto3,enum=musicfs.v1.MountState" json:"state,omitempty"` - OpenFileHandles uint32 `protobuf:"varint,5,opt,name=open_file_handles,json=openFileHandles,proto3" json:"open_file_handles,omitempty"` - FuseOpsTotal uint64 `protobuf:"varint,6,opt,name=fuse_ops_total,json=fuseOpsTotal,proto3" json:"fuse_ops_total,omitempty"` - FilesIndexed uint64 `protobuf:"varint,7,opt,name=files_indexed,json=filesIndexed,proto3" json:"files_indexed,omitempty"` - CacheSizeBytes uint64 `protobuf:"varint,8,opt,name=cache_size_bytes,json=cacheSizeBytes,proto3" json:"cache_size_bytes,omitempty"` - Origins []*OriginStatus `protobuf:"bytes,9,rep,name=origins,proto3" json:"origins,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *StatusResponse) Reset() { - *x = StatusResponse{} - mi := &file_musicfs_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *StatusResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StatusResponse) ProtoMessage() {} - -func (x *StatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead. -func (*StatusResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{4} -} - -func (x *StatusResponse) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -func (x *StatusResponse) GetUptimeSecs() uint64 { - if x != nil { - return x.UptimeSecs - } - return 0 -} - -func (x *StatusResponse) GetMountPoint() string { - if x != nil { - return x.MountPoint - } - return "" -} - -func (x *StatusResponse) GetState() MountState { - if x != nil { - return x.State - } - return MountState_MOUNT_UNKNOWN -} - -func (x *StatusResponse) GetOpenFileHandles() uint32 { - if x != nil { - return x.OpenFileHandles - } - return 0 -} - -func (x *StatusResponse) GetFuseOpsTotal() uint64 { - if x != nil { - return x.FuseOpsTotal - } - return 0 -} - -func (x *StatusResponse) GetFilesIndexed() uint64 { - if x != nil { - return x.FilesIndexed - } - return 0 -} - -func (x *StatusResponse) GetCacheSizeBytes() uint64 { - if x != nil { - return x.CacheSizeBytes - } - return 0 -} - -func (x *StatusResponse) GetOrigins() []*OriginStatus { - if x != nil { - return x.Origins - } - return nil -} - -type OriginStatus struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - OriginType string `protobuf:"bytes,2,opt,name=origin_type,json=originType,proto3" json:"origin_type,omitempty"` - Health HealthStatus `protobuf:"varint,3,opt,name=health,proto3,enum=musicfs.v1.HealthStatus" json:"health,omitempty"` - FilesCount uint64 `protobuf:"varint,4,opt,name=files_count,json=filesCount,proto3" json:"files_count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginStatus) Reset() { - *x = OriginStatus{} - mi := &file_musicfs_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginStatus) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginStatus) ProtoMessage() {} - -func (x *OriginStatus) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginStatus.ProtoReflect.Descriptor instead. -func (*OriginStatus) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{5} -} - -func (x *OriginStatus) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *OriginStatus) GetOriginType() string { - if x != nil { - return x.OriginType - } - return "" -} - -func (x *OriginStatus) GetHealth() HealthStatus { - if x != nil { - return x.Health - } - return HealthStatus_HEALTH_UNKNOWN -} - -func (x *OriginStatus) GetFilesCount() uint64 { - if x != nil { - return x.FilesCount - } - return 0 -} - -type ShutdownRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Graceful bool `protobuf:"varint,1,opt,name=graceful,proto3" json:"graceful,omitempty"` - TimeoutSecs uint32 `protobuf:"varint,2,opt,name=timeout_secs,json=timeoutSecs,proto3" json:"timeout_secs,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ShutdownRequest) Reset() { - *x = ShutdownRequest{} - mi := &file_musicfs_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ShutdownRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ShutdownRequest) ProtoMessage() {} - -func (x *ShutdownRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ShutdownRequest.ProtoReflect.Descriptor instead. -func (*ShutdownRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{6} -} - -func (x *ShutdownRequest) GetGraceful() bool { - if x != nil { - return x.Graceful - } - return false -} - -func (x *ShutdownRequest) GetTimeoutSecs() uint32 { - if x != nil { - return x.TimeoutSecs - } - return 0 -} - -type TierStats struct { - state protoimpl.MessageState `protogen:"open.v1"` - Entries uint64 `protobuf:"varint,1,opt,name=entries,proto3" json:"entries,omitempty"` - SizeBytes uint64 `protobuf:"varint,2,opt,name=size_bytes,json=sizeBytes,proto3" json:"size_bytes,omitempty"` - Hits uint64 `protobuf:"varint,3,opt,name=hits,proto3" json:"hits,omitempty"` - Misses uint64 `protobuf:"varint,4,opt,name=misses,proto3" json:"misses,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TierStats) Reset() { - *x = TierStats{} - mi := &file_musicfs_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TierStats) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TierStats) ProtoMessage() {} - -func (x *TierStats) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TierStats.ProtoReflect.Descriptor instead. -func (*TierStats) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{7} -} - -func (x *TierStats) GetEntries() uint64 { - if x != nil { - return x.Entries - } - return 0 -} - -func (x *TierStats) GetSizeBytes() uint64 { - if x != nil { - return x.SizeBytes - } - return 0 -} - -func (x *TierStats) GetHits() uint64 { - if x != nil { - return x.Hits - } - return 0 -} - -func (x *TierStats) GetMisses() uint64 { - if x != nil { - return x.Misses - } - return 0 -} - -type CacheStats struct { - state protoimpl.MessageState `protogen:"open.v1"` - TotalSizeBytes uint64 `protobuf:"varint,1,opt,name=total_size_bytes,json=totalSizeBytes,proto3" json:"total_size_bytes,omitempty"` - UsedSizeBytes uint64 `protobuf:"varint,2,opt,name=used_size_bytes,json=usedSizeBytes,proto3" json:"used_size_bytes,omitempty"` - SizeLimitBytes uint64 `protobuf:"varint,3,opt,name=size_limit_bytes,json=sizeLimitBytes,proto3" json:"size_limit_bytes,omitempty"` - ChunkCount uint64 `protobuf:"varint,4,opt,name=chunk_count,json=chunkCount,proto3" json:"chunk_count,omitempty"` - ChunksUnique uint64 `protobuf:"varint,5,opt,name=chunks_unique,json=chunksUnique,proto3" json:"chunks_unique,omitempty"` - DedupRatio float64 `protobuf:"fixed64,6,opt,name=dedup_ratio,json=dedupRatio,proto3" json:"dedup_ratio,omitempty"` - HitCount uint64 `protobuf:"varint,7,opt,name=hit_count,json=hitCount,proto3" json:"hit_count,omitempty"` - MissCount uint64 `protobuf:"varint,8,opt,name=miss_count,json=missCount,proto3" json:"miss_count,omitempty"` - HitRatio float64 `protobuf:"fixed64,9,opt,name=hit_ratio,json=hitRatio,proto3" json:"hit_ratio,omitempty"` - MetadataEntries uint64 `protobuf:"varint,10,opt,name=metadata_entries,json=metadataEntries,proto3" json:"metadata_entries,omitempty"` - MetadataBytes uint64 `protobuf:"varint,11,opt,name=metadata_bytes,json=metadataBytes,proto3" json:"metadata_bytes,omitempty"` - L1Metadata *TierStats `protobuf:"bytes,12,opt,name=l1_metadata,json=l1Metadata,proto3" json:"l1_metadata,omitempty"` - L2Headers *TierStats `protobuf:"bytes,13,opt,name=l2_headers,json=l2Headers,proto3" json:"l2_headers,omitempty"` - L3Chunks *TierStats `protobuf:"bytes,14,opt,name=l3_chunks,json=l3Chunks,proto3" json:"l3_chunks,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CacheStats) Reset() { - *x = CacheStats{} - mi := &file_musicfs_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CacheStats) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CacheStats) ProtoMessage() {} - -func (x *CacheStats) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CacheStats.ProtoReflect.Descriptor instead. -func (*CacheStats) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{8} -} - -func (x *CacheStats) GetTotalSizeBytes() uint64 { - if x != nil { - return x.TotalSizeBytes - } - return 0 -} - -func (x *CacheStats) GetUsedSizeBytes() uint64 { - if x != nil { - return x.UsedSizeBytes - } - return 0 -} - -func (x *CacheStats) GetSizeLimitBytes() uint64 { - if x != nil { - return x.SizeLimitBytes - } - return 0 -} - -func (x *CacheStats) GetChunkCount() uint64 { - if x != nil { - return x.ChunkCount - } - return 0 -} - -func (x *CacheStats) GetChunksUnique() uint64 { - if x != nil { - return x.ChunksUnique - } - return 0 -} - -func (x *CacheStats) GetDedupRatio() float64 { - if x != nil { - return x.DedupRatio - } - return 0 -} - -func (x *CacheStats) GetHitCount() uint64 { - if x != nil { - return x.HitCount - } - return 0 -} - -func (x *CacheStats) GetMissCount() uint64 { - if x != nil { - return x.MissCount - } - return 0 -} - -func (x *CacheStats) GetHitRatio() float64 { - if x != nil { - return x.HitRatio - } - return 0 -} - -func (x *CacheStats) GetMetadataEntries() uint64 { - if x != nil { - return x.MetadataEntries - } - return 0 -} - -func (x *CacheStats) GetMetadataBytes() uint64 { - if x != nil { - return x.MetadataBytes - } - return 0 -} - -func (x *CacheStats) GetL1Metadata() *TierStats { - if x != nil { - return x.L1Metadata - } - return nil -} - -func (x *CacheStats) GetL2Headers() *TierStats { - if x != nil { - return x.L2Headers - } - return nil -} - -func (x *CacheStats) GetL3Chunks() *TierStats { - if x != nil { - return x.L3Chunks - } - return nil -} - -type ClearCacheRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - OriginId *string `protobuf:"bytes,1,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - ClearMetadata bool `protobuf:"varint,2,opt,name=clear_metadata,json=clearMetadata,proto3" json:"clear_metadata,omitempty"` - ClearChunks bool `protobuf:"varint,3,opt,name=clear_chunks,json=clearChunks,proto3" json:"clear_chunks,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ClearCacheRequest) Reset() { - *x = ClearCacheRequest{} - mi := &file_musicfs_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ClearCacheRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ClearCacheRequest) ProtoMessage() {} - -func (x *ClearCacheRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ClearCacheRequest.ProtoReflect.Descriptor instead. -func (*ClearCacheRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{9} -} - -func (x *ClearCacheRequest) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -func (x *ClearCacheRequest) GetClearMetadata() bool { - if x != nil { - return x.ClearMetadata - } - return false -} - -func (x *ClearCacheRequest) GetClearChunks() bool { - if x != nil { - return x.ClearChunks - } - return false -} - -type ClearCacheResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - BytesCleared uint64 `protobuf:"varint,1,opt,name=bytes_cleared,json=bytesCleared,proto3" json:"bytes_cleared,omitempty"` - ChunksCleared uint64 `protobuf:"varint,2,opt,name=chunks_cleared,json=chunksCleared,proto3" json:"chunks_cleared,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ClearCacheResponse) Reset() { - *x = ClearCacheResponse{} - mi := &file_musicfs_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ClearCacheResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ClearCacheResponse) ProtoMessage() {} - -func (x *ClearCacheResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ClearCacheResponse.ProtoReflect.Descriptor instead. -func (*ClearCacheResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{10} -} - -func (x *ClearCacheResponse) GetBytesCleared() uint64 { - if x != nil { - return x.BytesCleared - } - return 0 -} - -func (x *ClearCacheResponse) GetChunksCleared() uint64 { - if x != nil { - return x.ChunksCleared - } - return 0 -} - -type PrefetchRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Paths []string `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"` - OriginId *string `protobuf:"bytes,2,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PrefetchRequest) Reset() { - *x = PrefetchRequest{} - mi := &file_musicfs_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PrefetchRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrefetchRequest) ProtoMessage() {} - -func (x *PrefetchRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[11] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrefetchRequest.ProtoReflect.Descriptor instead. -func (*PrefetchRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{11} -} - -func (x *PrefetchRequest) GetPaths() []string { - if x != nil { - return x.Paths - } - return nil -} - -func (x *PrefetchRequest) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -type PrefetchProgress struct { - state protoimpl.MessageState `protogen:"open.v1"` - CurrentPath string `protobuf:"bytes,1,opt,name=current_path,json=currentPath,proto3" json:"current_path,omitempty"` - Completed uint32 `protobuf:"varint,2,opt,name=completed,proto3" json:"completed,omitempty"` - Total uint32 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"` - BytesFetched uint64 `protobuf:"varint,4,opt,name=bytes_fetched,json=bytesFetched,proto3" json:"bytes_fetched,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PrefetchProgress) Reset() { - *x = PrefetchProgress{} - mi := &file_musicfs_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PrefetchProgress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrefetchProgress) ProtoMessage() {} - -func (x *PrefetchProgress) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[12] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrefetchProgress.ProtoReflect.Descriptor instead. -func (*PrefetchProgress) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{12} -} - -func (x *PrefetchProgress) GetCurrentPath() string { - if x != nil { - return x.CurrentPath - } - return "" -} - -func (x *PrefetchProgress) GetCompleted() uint32 { - if x != nil { - return x.Completed - } - return 0 -} - -func (x *PrefetchProgress) GetTotal() uint32 { - if x != nil { - return x.Total - } - return 0 -} - -func (x *PrefetchProgress) GetBytesFetched() uint64 { - if x != nil { - return x.BytesFetched - } - return 0 -} - -type OriginsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Origins []*OriginInfo `protobuf:"bytes,1,rep,name=origins,proto3" json:"origins,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginsResponse) Reset() { - *x = OriginsResponse{} - mi := &file_musicfs_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginsResponse) ProtoMessage() {} - -func (x *OriginsResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[13] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginsResponse.ProtoReflect.Descriptor instead. -func (*OriginsResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{13} -} - -func (x *OriginsResponse) GetOrigins() []*OriginInfo { - if x != nil { - return x.Origins - } - return nil -} - -type OriginInfo struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - OriginType string `protobuf:"bytes,2,opt,name=origin_type,json=originType,proto3" json:"origin_type,omitempty"` - DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` - RootPath string `protobuf:"bytes,4,opt,name=root_path,json=rootPath,proto3" json:"root_path,omitempty"` - Health HealthStatus `protobuf:"varint,5,opt,name=health,proto3,enum=musicfs.v1.HealthStatus" json:"health,omitempty"` - FilesCount uint64 `protobuf:"varint,6,opt,name=files_count,json=filesCount,proto3" json:"files_count,omitempty"` - TotalSizeBytes uint64 `protobuf:"varint,7,opt,name=total_size_bytes,json=totalSizeBytes,proto3" json:"total_size_bytes,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginInfo) Reset() { - *x = OriginInfo{} - mi := &file_musicfs_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginInfo) ProtoMessage() {} - -func (x *OriginInfo) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[14] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginInfo.ProtoReflect.Descriptor instead. -func (*OriginInfo) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{14} -} - -func (x *OriginInfo) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *OriginInfo) GetOriginType() string { - if x != nil { - return x.OriginType - } - return "" -} - -func (x *OriginInfo) GetDisplayName() string { - if x != nil { - return x.DisplayName - } - return "" -} - -func (x *OriginInfo) GetRootPath() string { - if x != nil { - return x.RootPath - } - return "" -} - -func (x *OriginInfo) GetHealth() HealthStatus { - if x != nil { - return x.Health - } - return HealthStatus_HEALTH_UNKNOWN -} - -func (x *OriginInfo) GetFilesCount() uint64 { - if x != nil { - return x.FilesCount - } - return 0 -} - -func (x *OriginInfo) GetTotalSizeBytes() uint64 { - if x != nil { - return x.TotalSizeBytes - } - return 0 -} - -type OriginRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - OriginId string `protobuf:"bytes,1,opt,name=origin_id,json=originId,proto3" json:"origin_id,omitempty"` - // Optional subdirectory to scope the scan (relative to origin root). - // If empty, scans the entire origin. - // Example: "Metallica - Master of Puppets (1986) [FLAC]" - Subdir *string `protobuf:"bytes,2,opt,name=subdir,proto3,oneof" json:"subdir,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginRequest) Reset() { - *x = OriginRequest{} - mi := &file_musicfs_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginRequest) ProtoMessage() {} - -func (x *OriginRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[15] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginRequest.ProtoReflect.Descriptor instead. -func (*OriginRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{15} -} - -func (x *OriginRequest) GetOriginId() string { - if x != nil { - return x.OriginId - } - return "" -} - -func (x *OriginRequest) GetSubdir() string { - if x != nil && x.Subdir != nil { - return *x.Subdir - } - return "" -} - -type OriginHealthResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - OriginId string `protobuf:"bytes,1,opt,name=origin_id,json=originId,proto3" json:"origin_id,omitempty"` - Status HealthStatus `protobuf:"varint,2,opt,name=status,proto3,enum=musicfs.v1.HealthStatus" json:"status,omitempty"` - Message *string `protobuf:"bytes,3,opt,name=message,proto3,oneof" json:"message,omitempty"` - LastCheckSecs uint64 `protobuf:"varint,4,opt,name=last_check_secs,json=lastCheckSecs,proto3" json:"last_check_secs,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginHealthResponse) Reset() { - *x = OriginHealthResponse{} - mi := &file_musicfs_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginHealthResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginHealthResponse) ProtoMessage() {} - -func (x *OriginHealthResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[16] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginHealthResponse.ProtoReflect.Descriptor instead. -func (*OriginHealthResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{16} -} - -func (x *OriginHealthResponse) GetOriginId() string { - if x != nil { - return x.OriginId - } - return "" -} - -func (x *OriginHealthResponse) GetStatus() HealthStatus { - if x != nil { - return x.Status - } - return HealthStatus_HEALTH_UNKNOWN -} - -func (x *OriginHealthResponse) GetMessage() string { - if x != nil && x.Message != nil { - return *x.Message - } - return "" -} - -func (x *OriginHealthResponse) GetLastCheckSecs() uint64 { - if x != nil { - return x.LastCheckSecs - } - return 0 -} - -type SyncProgress struct { - state protoimpl.MessageState `protogen:"open.v1"` - Phase string `protobuf:"bytes,1,opt,name=phase,proto3" json:"phase,omitempty"` - Current uint32 `protobuf:"varint,2,opt,name=current,proto3" json:"current,omitempty"` - Total uint32 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"` - CurrentPath string `protobuf:"bytes,4,opt,name=current_path,json=currentPath,proto3" json:"current_path,omitempty"` - BytesSynced uint64 `protobuf:"varint,5,opt,name=bytes_synced,json=bytesSynced,proto3" json:"bytes_synced,omitempty"` - NewFiles []*SyncedFile `protobuf:"bytes,6,rep,name=new_files,json=newFiles,proto3" json:"new_files,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SyncProgress) Reset() { - *x = SyncProgress{} - mi := &file_musicfs_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SyncProgress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncProgress) ProtoMessage() {} - -func (x *SyncProgress) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[17] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SyncProgress.ProtoReflect.Descriptor instead. -func (*SyncProgress) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{17} -} - -func (x *SyncProgress) GetPhase() string { - if x != nil { - return x.Phase - } - return "" -} - -func (x *SyncProgress) GetCurrent() uint32 { - if x != nil { - return x.Current - } - return 0 -} - -func (x *SyncProgress) GetTotal() uint32 { - if x != nil { - return x.Total - } - return 0 -} - -func (x *SyncProgress) GetCurrentPath() string { - if x != nil { - return x.CurrentPath - } - return "" -} - -func (x *SyncProgress) GetBytesSynced() uint64 { - if x != nil { - return x.BytesSynced - } - return 0 -} - -func (x *SyncProgress) GetNewFiles() []*SyncedFile { - if x != nil { - return x.NewFiles - } - return nil -} - -type SyncedFile struct { - state protoimpl.MessageState `protogen:"open.v1"` - Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - FileId int64 `protobuf:"varint,2,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - VirtualPath string `protobuf:"bytes,3,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SyncedFile) Reset() { - *x = SyncedFile{} - mi := &file_musicfs_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SyncedFile) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncedFile) ProtoMessage() {} - -func (x *SyncedFile) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[18] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SyncedFile.ProtoReflect.Descriptor instead. -func (*SyncedFile) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{18} -} - -func (x *SyncedFile) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *SyncedFile) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *SyncedFile) GetVirtualPath() string { - if x != nil { - return x.VirtualPath - } - return "" -} - -type EventFilter struct { - state protoimpl.MessageState `protogen:"open.v1"` - EventTypes []string `protobuf:"bytes,1,rep,name=event_types,json=eventTypes,proto3" json:"event_types,omitempty"` - OriginId *string `protobuf:"bytes,2,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *EventFilter) Reset() { - *x = EventFilter{} - mi := &file_musicfs_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *EventFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EventFilter) ProtoMessage() {} - -func (x *EventFilter) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[19] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EventFilter.ProtoReflect.Descriptor instead. -func (*EventFilter) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{19} -} - -func (x *EventFilter) GetEventTypes() []string { - if x != nil { - return x.EventTypes - } - return nil -} - -func (x *EventFilter) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -type Event struct { - state protoimpl.MessageState `protogen:"open.v1"` - EventType string `protobuf:"bytes,1,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` - TimestampMs int64 `protobuf:"varint,2,opt,name=timestamp_ms,json=timestampMs,proto3" json:"timestamp_ms,omitempty"` - OriginId *string `protobuf:"bytes,3,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - Path *string `protobuf:"bytes,4,opt,name=path,proto3,oneof" json:"path,omitempty"` - FileId *int64 `protobuf:"varint,5,opt,name=file_id,json=fileId,proto3,oneof" json:"file_id,omitempty"` - Metadata map[string]string `protobuf:"bytes,6,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Event) Reset() { - *x = Event{} - mi := &file_musicfs_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Event) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Event) ProtoMessage() {} - -func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[20] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Event.ProtoReflect.Descriptor instead. -func (*Event) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{20} -} - -func (x *Event) GetEventType() string { - if x != nil { - return x.EventType - } - return "" -} - -func (x *Event) GetTimestampMs() int64 { - if x != nil { - return x.TimestampMs - } - return 0 -} - -func (x *Event) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -func (x *Event) GetPath() string { - if x != nil && x.Path != nil { - return *x.Path - } - return "" -} - -func (x *Event) GetFileId() int64 { - if x != nil && x.FileId != nil { - return *x.FileId - } - return 0 -} - -func (x *Event) GetMetadata() map[string]string { - if x != nil { - return x.Metadata - } - return nil -} - -type GetMetadataRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - VirtualPath string `protobuf:"bytes,1,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetMetadataRequest) Reset() { - *x = GetMetadataRequest{} - mi := &file_musicfs_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetMetadataRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetMetadataRequest) ProtoMessage() {} - -func (x *GetMetadataRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[21] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetMetadataRequest.ProtoReflect.Descriptor instead. -func (*GetMetadataRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{21} -} - -func (x *GetMetadataRequest) GetVirtualPath() string { - if x != nil { - return x.VirtualPath - } - return "" -} - -type MetadataResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Title *string `protobuf:"bytes,2,opt,name=title,proto3,oneof" json:"title,omitempty"` - Artist *string `protobuf:"bytes,3,opt,name=artist,proto3,oneof" json:"artist,omitempty"` - Album *string `protobuf:"bytes,4,opt,name=album,proto3,oneof" json:"album,omitempty"` - AlbumArtist *string `protobuf:"bytes,5,opt,name=album_artist,json=albumArtist,proto3,oneof" json:"album_artist,omitempty"` - Year *uint32 `protobuf:"varint,6,opt,name=year,proto3,oneof" json:"year,omitempty"` - Track *uint32 `protobuf:"varint,7,opt,name=track,proto3,oneof" json:"track,omitempty"` - Disc *uint32 `protobuf:"varint,8,opt,name=disc,proto3,oneof" json:"disc,omitempty"` - Genre *string `protobuf:"bytes,9,opt,name=genre,proto3,oneof" json:"genre,omitempty"` - Format *string `protobuf:"bytes,10,opt,name=format,proto3,oneof" json:"format,omitempty"` - DurationMs *uint64 `protobuf:"varint,11,opt,name=duration_ms,json=durationMs,proto3,oneof" json:"duration_ms,omitempty"` - Bitrate *uint64 `protobuf:"varint,12,opt,name=bitrate,proto3,oneof" json:"bitrate,omitempty"` - TrackTotal *uint32 `protobuf:"varint,13,opt,name=track_total,json=trackTotal,proto3,oneof" json:"track_total,omitempty"` - DiscTotal *uint32 `protobuf:"varint,14,opt,name=disc_total,json=discTotal,proto3,oneof" json:"disc_total,omitempty"` - Date *string `protobuf:"bytes,15,opt,name=date,proto3,oneof" json:"date,omitempty"` - Composer *string `protobuf:"bytes,16,opt,name=composer,proto3,oneof" json:"composer,omitempty"` - Comment *string `protobuf:"bytes,17,opt,name=comment,proto3,oneof" json:"comment,omitempty"` - Lyrics *string `protobuf:"bytes,18,opt,name=lyrics,proto3,oneof" json:"lyrics,omitempty"` - Copyright *string `protobuf:"bytes,19,opt,name=copyright,proto3,oneof" json:"copyright,omitempty"` - Compilation *bool `protobuf:"varint,20,opt,name=compilation,proto3,oneof" json:"compilation,omitempty"` - ArtistSort *string `protobuf:"bytes,21,opt,name=artist_sort,json=artistSort,proto3,oneof" json:"artist_sort,omitempty"` - AlbumArtistSort *string `protobuf:"bytes,22,opt,name=album_artist_sort,json=albumArtistSort,proto3,oneof" json:"album_artist_sort,omitempty"` - AlbumSort *string `protobuf:"bytes,23,opt,name=album_sort,json=albumSort,proto3,oneof" json:"album_sort,omitempty"` - TitleSort *string `protobuf:"bytes,24,opt,name=title_sort,json=titleSort,proto3,oneof" json:"title_sort,omitempty"` - MbRecordingId *string `protobuf:"bytes,25,opt,name=mb_recording_id,json=mbRecordingId,proto3,oneof" json:"mb_recording_id,omitempty"` - MbAlbumId *string `protobuf:"bytes,26,opt,name=mb_album_id,json=mbAlbumId,proto3,oneof" json:"mb_album_id,omitempty"` - MbArtistId *string `protobuf:"bytes,27,opt,name=mb_artist_id,json=mbArtistId,proto3,oneof" json:"mb_artist_id,omitempty"` - MbAlbumArtistId *string `protobuf:"bytes,28,opt,name=mb_album_artist_id,json=mbAlbumArtistId,proto3,oneof" json:"mb_album_artist_id,omitempty"` - MbReleaseGroupId *string `protobuf:"bytes,29,opt,name=mb_release_group_id,json=mbReleaseGroupId,proto3,oneof" json:"mb_release_group_id,omitempty"` - ReplaygainTrackGain *float32 `protobuf:"fixed32,30,opt,name=replaygain_track_gain,json=replaygainTrackGain,proto3,oneof" json:"replaygain_track_gain,omitempty"` - ReplaygainTrackPeak *float32 `protobuf:"fixed32,31,opt,name=replaygain_track_peak,json=replaygainTrackPeak,proto3,oneof" json:"replaygain_track_peak,omitempty"` - ReplaygainAlbumGain *float32 `protobuf:"fixed32,32,opt,name=replaygain_album_gain,json=replaygainAlbumGain,proto3,oneof" json:"replaygain_album_gain,omitempty"` - ReplaygainAlbumPeak *float32 `protobuf:"fixed32,33,opt,name=replaygain_album_peak,json=replaygainAlbumPeak,proto3,oneof" json:"replaygain_album_peak,omitempty"` - Channels *uint32 `protobuf:"varint,34,opt,name=channels,proto3,oneof" json:"channels,omitempty"` - BitsPerSample *uint32 `protobuf:"varint,35,opt,name=bits_per_sample,json=bitsPerSample,proto3,oneof" json:"bits_per_sample,omitempty"` - Encoder *string `protobuf:"bytes,36,opt,name=encoder,proto3,oneof" json:"encoder,omitempty"` - Label *string `protobuf:"bytes,40,opt,name=label,proto3,oneof" json:"label,omitempty"` - AlbumType *string `protobuf:"bytes,41,opt,name=album_type,json=albumType,proto3,oneof" json:"album_type,omitempty"` - CoverUrl *string `protobuf:"bytes,42,opt,name=cover_url,json=coverUrl,proto3,oneof" json:"cover_url,omitempty"` - CustomTags map[string]string `protobuf:"bytes,50,rep,name=custom_tags,json=customTags,proto3" json:"custom_tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MetadataResponse) Reset() { - *x = MetadataResponse{} - mi := &file_musicfs_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MetadataResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MetadataResponse) ProtoMessage() {} - -func (x *MetadataResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[22] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MetadataResponse.ProtoReflect.Descriptor instead. -func (*MetadataResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{22} -} - -func (x *MetadataResponse) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *MetadataResponse) GetTitle() string { - if x != nil && x.Title != nil { - return *x.Title - } - return "" -} - -func (x *MetadataResponse) GetArtist() string { - if x != nil && x.Artist != nil { - return *x.Artist - } - return "" -} - -func (x *MetadataResponse) GetAlbum() string { - if x != nil && x.Album != nil { - return *x.Album - } - return "" -} - -func (x *MetadataResponse) GetAlbumArtist() string { - if x != nil && x.AlbumArtist != nil { - return *x.AlbumArtist - } - return "" -} - -func (x *MetadataResponse) GetYear() uint32 { - if x != nil && x.Year != nil { - return *x.Year - } - return 0 -} - -func (x *MetadataResponse) GetTrack() uint32 { - if x != nil && x.Track != nil { - return *x.Track - } - return 0 -} - -func (x *MetadataResponse) GetDisc() uint32 { - if x != nil && x.Disc != nil { - return *x.Disc - } - return 0 -} - -func (x *MetadataResponse) GetGenre() string { - if x != nil && x.Genre != nil { - return *x.Genre - } - return "" -} - -func (x *MetadataResponse) GetFormat() string { - if x != nil && x.Format != nil { - return *x.Format - } - return "" -} - -func (x *MetadataResponse) GetDurationMs() uint64 { - if x != nil && x.DurationMs != nil { - return *x.DurationMs - } - return 0 -} - -func (x *MetadataResponse) GetBitrate() uint64 { - if x != nil && x.Bitrate != nil { - return *x.Bitrate - } - return 0 -} - -func (x *MetadataResponse) GetTrackTotal() uint32 { - if x != nil && x.TrackTotal != nil { - return *x.TrackTotal - } - return 0 -} - -func (x *MetadataResponse) GetDiscTotal() uint32 { - if x != nil && x.DiscTotal != nil { - return *x.DiscTotal - } - return 0 -} - -func (x *MetadataResponse) GetDate() string { - if x != nil && x.Date != nil { - return *x.Date - } - return "" -} - -func (x *MetadataResponse) GetComposer() string { - if x != nil && x.Composer != nil { - return *x.Composer - } - return "" -} - -func (x *MetadataResponse) GetComment() string { - if x != nil && x.Comment != nil { - return *x.Comment - } - return "" -} - -func (x *MetadataResponse) GetLyrics() string { - if x != nil && x.Lyrics != nil { - return *x.Lyrics - } - return "" -} - -func (x *MetadataResponse) GetCopyright() string { - if x != nil && x.Copyright != nil { - return *x.Copyright - } - return "" -} - -func (x *MetadataResponse) GetCompilation() bool { - if x != nil && x.Compilation != nil { - return *x.Compilation - } - return false -} - -func (x *MetadataResponse) GetArtistSort() string { - if x != nil && x.ArtistSort != nil { - return *x.ArtistSort - } - return "" -} - -func (x *MetadataResponse) GetAlbumArtistSort() string { - if x != nil && x.AlbumArtistSort != nil { - return *x.AlbumArtistSort - } - return "" -} - -func (x *MetadataResponse) GetAlbumSort() string { - if x != nil && x.AlbumSort != nil { - return *x.AlbumSort - } - return "" -} - -func (x *MetadataResponse) GetTitleSort() string { - if x != nil && x.TitleSort != nil { - return *x.TitleSort - } - return "" -} - -func (x *MetadataResponse) GetMbRecordingId() string { - if x != nil && x.MbRecordingId != nil { - return *x.MbRecordingId - } - return "" -} - -func (x *MetadataResponse) GetMbAlbumId() string { - if x != nil && x.MbAlbumId != nil { - return *x.MbAlbumId - } - return "" -} - -func (x *MetadataResponse) GetMbArtistId() string { - if x != nil && x.MbArtistId != nil { - return *x.MbArtistId - } - return "" -} - -func (x *MetadataResponse) GetMbAlbumArtistId() string { - if x != nil && x.MbAlbumArtistId != nil { - return *x.MbAlbumArtistId - } - return "" -} - -func (x *MetadataResponse) GetMbReleaseGroupId() string { - if x != nil && x.MbReleaseGroupId != nil { - return *x.MbReleaseGroupId - } - return "" -} - -func (x *MetadataResponse) GetReplaygainTrackGain() float32 { - if x != nil && x.ReplaygainTrackGain != nil { - return *x.ReplaygainTrackGain - } - return 0 -} - -func (x *MetadataResponse) GetReplaygainTrackPeak() float32 { - if x != nil && x.ReplaygainTrackPeak != nil { - return *x.ReplaygainTrackPeak - } - return 0 -} - -func (x *MetadataResponse) GetReplaygainAlbumGain() float32 { - if x != nil && x.ReplaygainAlbumGain != nil { - return *x.ReplaygainAlbumGain - } - return 0 -} - -func (x *MetadataResponse) GetReplaygainAlbumPeak() float32 { - if x != nil && x.ReplaygainAlbumPeak != nil { - return *x.ReplaygainAlbumPeak - } - return 0 -} - -func (x *MetadataResponse) GetChannels() uint32 { - if x != nil && x.Channels != nil { - return *x.Channels - } - return 0 -} - -func (x *MetadataResponse) GetBitsPerSample() uint32 { - if x != nil && x.BitsPerSample != nil { - return *x.BitsPerSample - } - return 0 -} - -func (x *MetadataResponse) GetEncoder() string { - if x != nil && x.Encoder != nil { - return *x.Encoder - } - return "" -} - -func (x *MetadataResponse) GetLabel() string { - if x != nil && x.Label != nil { - return *x.Label - } - return "" -} - -func (x *MetadataResponse) GetAlbumType() string { - if x != nil && x.AlbumType != nil { - return *x.AlbumType - } - return "" -} - -func (x *MetadataResponse) GetCoverUrl() string { - if x != nil && x.CoverUrl != nil { - return *x.CoverUrl - } - return "" -} - -func (x *MetadataResponse) GetCustomTags() map[string]string { - if x != nil { - return x.CustomTags - } - return nil -} - -type UpdateMetadataRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Title *string `protobuf:"bytes,2,opt,name=title,proto3,oneof" json:"title,omitempty"` - Artist *string `protobuf:"bytes,3,opt,name=artist,proto3,oneof" json:"artist,omitempty"` - Album *string `protobuf:"bytes,4,opt,name=album,proto3,oneof" json:"album,omitempty"` - AlbumArtist *string `protobuf:"bytes,5,opt,name=album_artist,json=albumArtist,proto3,oneof" json:"album_artist,omitempty"` - TrackNumber *uint32 `protobuf:"varint,6,opt,name=track_number,json=trackNumber,proto3,oneof" json:"track_number,omitempty"` - DiscNumber *uint32 `protobuf:"varint,7,opt,name=disc_number,json=discNumber,proto3,oneof" json:"disc_number,omitempty"` - Date *string `protobuf:"bytes,8,opt,name=date,proto3,oneof" json:"date,omitempty"` - Genre *string `protobuf:"bytes,9,opt,name=genre,proto3,oneof" json:"genre,omitempty"` - Composer *string `protobuf:"bytes,10,opt,name=composer,proto3,oneof" json:"composer,omitempty"` - Comment *string `protobuf:"bytes,11,opt,name=comment,proto3,oneof" json:"comment,omitempty"` - Lyrics *string `protobuf:"bytes,12,opt,name=lyrics,proto3,oneof" json:"lyrics,omitempty"` - Copyright *string `protobuf:"bytes,13,opt,name=copyright,proto3,oneof" json:"copyright,omitempty"` - Compilation *bool `protobuf:"varint,14,opt,name=compilation,proto3,oneof" json:"compilation,omitempty"` - ArtistSort *string `protobuf:"bytes,15,opt,name=artist_sort,json=artistSort,proto3,oneof" json:"artist_sort,omitempty"` - AlbumArtistSort *string `protobuf:"bytes,16,opt,name=album_artist_sort,json=albumArtistSort,proto3,oneof" json:"album_artist_sort,omitempty"` - AlbumSort *string `protobuf:"bytes,17,opt,name=album_sort,json=albumSort,proto3,oneof" json:"album_sort,omitempty"` - TitleSort *string `protobuf:"bytes,18,opt,name=title_sort,json=titleSort,proto3,oneof" json:"title_sort,omitempty"` - MbRecordingId *string `protobuf:"bytes,20,opt,name=mb_recording_id,json=mbRecordingId,proto3,oneof" json:"mb_recording_id,omitempty"` - MbAlbumId *string `protobuf:"bytes,21,opt,name=mb_album_id,json=mbAlbumId,proto3,oneof" json:"mb_album_id,omitempty"` - MbArtistId *string `protobuf:"bytes,22,opt,name=mb_artist_id,json=mbArtistId,proto3,oneof" json:"mb_artist_id,omitempty"` - ReplaygainTrackGain *float32 `protobuf:"fixed32,30,opt,name=replaygain_track_gain,json=replaygainTrackGain,proto3,oneof" json:"replaygain_track_gain,omitempty"` - ReplaygainTrackPeak *float32 `protobuf:"fixed32,31,opt,name=replaygain_track_peak,json=replaygainTrackPeak,proto3,oneof" json:"replaygain_track_peak,omitempty"` - ReplaygainAlbumGain *float32 `protobuf:"fixed32,32,opt,name=replaygain_album_gain,json=replaygainAlbumGain,proto3,oneof" json:"replaygain_album_gain,omitempty"` - ReplaygainAlbumPeak *float32 `protobuf:"fixed32,33,opt,name=replaygain_album_peak,json=replaygainAlbumPeak,proto3,oneof" json:"replaygain_album_peak,omitempty"` - Label *string `protobuf:"bytes,40,opt,name=label,proto3,oneof" json:"label,omitempty"` - AlbumType *string `protobuf:"bytes,41,opt,name=album_type,json=albumType,proto3,oneof" json:"album_type,omitempty"` - CoverUrl *string `protobuf:"bytes,42,opt,name=cover_url,json=coverUrl,proto3,oneof" json:"cover_url,omitempty"` - CustomTags map[string]string `protobuf:"bytes,50,rep,name=custom_tags,json=customTags,proto3" json:"custom_tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *UpdateMetadataRequest) Reset() { - *x = UpdateMetadataRequest{} - mi := &file_musicfs_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *UpdateMetadataRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateMetadataRequest) ProtoMessage() {} - -func (x *UpdateMetadataRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[23] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateMetadataRequest.ProtoReflect.Descriptor instead. -func (*UpdateMetadataRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{23} -} - -func (x *UpdateMetadataRequest) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *UpdateMetadataRequest) GetTitle() string { - if x != nil && x.Title != nil { - return *x.Title - } - return "" -} - -func (x *UpdateMetadataRequest) GetArtist() string { - if x != nil && x.Artist != nil { - return *x.Artist - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbum() string { - if x != nil && x.Album != nil { - return *x.Album - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbumArtist() string { - if x != nil && x.AlbumArtist != nil { - return *x.AlbumArtist - } - return "" -} - -func (x *UpdateMetadataRequest) GetTrackNumber() uint32 { - if x != nil && x.TrackNumber != nil { - return *x.TrackNumber - } - return 0 -} - -func (x *UpdateMetadataRequest) GetDiscNumber() uint32 { - if x != nil && x.DiscNumber != nil { - return *x.DiscNumber - } - return 0 -} - -func (x *UpdateMetadataRequest) GetDate() string { - if x != nil && x.Date != nil { - return *x.Date - } - return "" -} - -func (x *UpdateMetadataRequest) GetGenre() string { - if x != nil && x.Genre != nil { - return *x.Genre - } - return "" -} - -func (x *UpdateMetadataRequest) GetComposer() string { - if x != nil && x.Composer != nil { - return *x.Composer - } - return "" -} - -func (x *UpdateMetadataRequest) GetComment() string { - if x != nil && x.Comment != nil { - return *x.Comment - } - return "" -} - -func (x *UpdateMetadataRequest) GetLyrics() string { - if x != nil && x.Lyrics != nil { - return *x.Lyrics - } - return "" -} - -func (x *UpdateMetadataRequest) GetCopyright() string { - if x != nil && x.Copyright != nil { - return *x.Copyright - } - return "" -} - -func (x *UpdateMetadataRequest) GetCompilation() bool { - if x != nil && x.Compilation != nil { - return *x.Compilation - } - return false -} - -func (x *UpdateMetadataRequest) GetArtistSort() string { - if x != nil && x.ArtistSort != nil { - return *x.ArtistSort - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbumArtistSort() string { - if x != nil && x.AlbumArtistSort != nil { - return *x.AlbumArtistSort - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbumSort() string { - if x != nil && x.AlbumSort != nil { - return *x.AlbumSort - } - return "" -} - -func (x *UpdateMetadataRequest) GetTitleSort() string { - if x != nil && x.TitleSort != nil { - return *x.TitleSort - } - return "" -} - -func (x *UpdateMetadataRequest) GetMbRecordingId() string { - if x != nil && x.MbRecordingId != nil { - return *x.MbRecordingId - } - return "" -} - -func (x *UpdateMetadataRequest) GetMbAlbumId() string { - if x != nil && x.MbAlbumId != nil { - return *x.MbAlbumId - } - return "" -} - -func (x *UpdateMetadataRequest) GetMbArtistId() string { - if x != nil && x.MbArtistId != nil { - return *x.MbArtistId - } - return "" -} - -func (x *UpdateMetadataRequest) GetReplaygainTrackGain() float32 { - if x != nil && x.ReplaygainTrackGain != nil { - return *x.ReplaygainTrackGain - } - return 0 -} - -func (x *UpdateMetadataRequest) GetReplaygainTrackPeak() float32 { - if x != nil && x.ReplaygainTrackPeak != nil { - return *x.ReplaygainTrackPeak - } - return 0 -} - -func (x *UpdateMetadataRequest) GetReplaygainAlbumGain() float32 { - if x != nil && x.ReplaygainAlbumGain != nil { - return *x.ReplaygainAlbumGain - } - return 0 -} - -func (x *UpdateMetadataRequest) GetReplaygainAlbumPeak() float32 { - if x != nil && x.ReplaygainAlbumPeak != nil { - return *x.ReplaygainAlbumPeak - } - return 0 -} - -func (x *UpdateMetadataRequest) GetLabel() string { - if x != nil && x.Label != nil { - return *x.Label - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbumType() string { - if x != nil && x.AlbumType != nil { - return *x.AlbumType - } - return "" -} - -func (x *UpdateMetadataRequest) GetCoverUrl() string { - if x != nil && x.CoverUrl != nil { - return *x.CoverUrl - } - return "" -} - -func (x *UpdateMetadataRequest) GetCustomTags() map[string]string { - if x != nil { - return x.CustomTags - } - return nil -} - -type UpdateMetadataResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` - ErrorMessage *string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *UpdateMetadataResponse) Reset() { - *x = UpdateMetadataResponse{} - mi := &file_musicfs_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *UpdateMetadataResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateMetadataResponse) ProtoMessage() {} - -func (x *UpdateMetadataResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[24] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateMetadataResponse.ProtoReflect.Descriptor instead. -func (*UpdateMetadataResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{24} -} - -func (x *UpdateMetadataResponse) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *UpdateMetadataResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *UpdateMetadataResponse) GetErrorMessage() string { - if x != nil && x.ErrorMessage != nil { - return *x.ErrorMessage - } - return "" -} - -type ClearOverlayRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ClearOverlayRequest) Reset() { - *x = ClearOverlayRequest{} - mi := &file_musicfs_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ClearOverlayRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ClearOverlayRequest) ProtoMessage() {} - -func (x *ClearOverlayRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[25] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ClearOverlayRequest.ProtoReflect.Descriptor instead. -func (*ClearOverlayRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{25} -} - -func (x *ClearOverlayRequest) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -type ClearOverlayResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` - ErrorMessage *string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ClearOverlayResponse) Reset() { - *x = ClearOverlayResponse{} - mi := &file_musicfs_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ClearOverlayResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ClearOverlayResponse) ProtoMessage() {} - -func (x *ClearOverlayResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[26] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ClearOverlayResponse.ProtoReflect.Descriptor instead. -func (*ClearOverlayResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{26} -} - -func (x *ClearOverlayResponse) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *ClearOverlayResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *ClearOverlayResponse) GetErrorMessage() string { - if x != nil && x.ErrorMessage != nil { - return *x.ErrorMessage - } - return "" -} - -type BatchUpdateRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Items []*BatchUpdateItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BatchUpdateRequest) Reset() { - *x = BatchUpdateRequest{} - mi := &file_musicfs_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BatchUpdateRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BatchUpdateRequest) ProtoMessage() {} - -func (x *BatchUpdateRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[27] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BatchUpdateRequest.ProtoReflect.Descriptor instead. -func (*BatchUpdateRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{27} -} - -func (x *BatchUpdateRequest) GetItems() []*BatchUpdateItem { - if x != nil { - return x.Items - } - return nil -} - -type BatchUpdateItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Metadata *UpdateMetadataRequest `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BatchUpdateItem) Reset() { - *x = BatchUpdateItem{} - mi := &file_musicfs_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BatchUpdateItem) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BatchUpdateItem) ProtoMessage() {} - -func (x *BatchUpdateItem) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[28] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BatchUpdateItem.ProtoReflect.Descriptor instead. -func (*BatchUpdateItem) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{28} -} - -func (x *BatchUpdateItem) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *BatchUpdateItem) GetMetadata() *UpdateMetadataRequest { - if x != nil { - return x.Metadata - } - return nil -} - -type BatchUpdateProgress struct { - state protoimpl.MessageState `protogen:"open.v1"` - Completed uint32 `protobuf:"varint,1,opt,name=completed,proto3" json:"completed,omitempty"` - Total uint32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - CurrentFileId *int64 `protobuf:"varint,3,opt,name=current_file_id,json=currentFileId,proto3,oneof" json:"current_file_id,omitempty"` - ErrorMessage *string `protobuf:"bytes,4,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BatchUpdateProgress) Reset() { - *x = BatchUpdateProgress{} - mi := &file_musicfs_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BatchUpdateProgress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BatchUpdateProgress) ProtoMessage() {} - -func (x *BatchUpdateProgress) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[29] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BatchUpdateProgress.ProtoReflect.Descriptor instead. -func (*BatchUpdateProgress) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{29} -} - -func (x *BatchUpdateProgress) GetCompleted() uint32 { - if x != nil { - return x.Completed - } - return 0 -} - -func (x *BatchUpdateProgress) GetTotal() uint32 { - if x != nil { - return x.Total - } - return 0 -} - -func (x *BatchUpdateProgress) GetCurrentFileId() int64 { - if x != nil && x.CurrentFileId != nil { - return *x.CurrentFileId - } - return 0 -} - -func (x *BatchUpdateProgress) GetErrorMessage() string { - if x != nil && x.ErrorMessage != nil { - return *x.ErrorMessage - } - return "" -} - -type ImportMetadataRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - SourcePath string `protobuf:"bytes,1,opt,name=source_path,json=sourcePath,proto3" json:"source_path,omitempty"` - Format *string `protobuf:"bytes,2,opt,name=format,proto3,oneof" json:"format,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ImportMetadataRequest) Reset() { - *x = ImportMetadataRequest{} - mi := &file_musicfs_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ImportMetadataRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ImportMetadataRequest) ProtoMessage() {} - -func (x *ImportMetadataRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[30] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ImportMetadataRequest.ProtoReflect.Descriptor instead. -func (*ImportMetadataRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{30} -} - -func (x *ImportMetadataRequest) GetSourcePath() string { - if x != nil { - return x.SourcePath - } - return "" -} - -func (x *ImportMetadataRequest) GetFormat() string { - if x != nil && x.Format != nil { - return *x.Format - } - return "" -} - -type ImportProgress struct { - state protoimpl.MessageState `protogen:"open.v1"` - Imported uint32 `protobuf:"varint,1,opt,name=imported,proto3" json:"imported,omitempty"` - Total uint32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - CurrentFile *string `protobuf:"bytes,3,opt,name=current_file,json=currentFile,proto3,oneof" json:"current_file,omitempty"` - ErrorMessage *string `protobuf:"bytes,4,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ImportProgress) Reset() { - *x = ImportProgress{} - mi := &file_musicfs_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ImportProgress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ImportProgress) ProtoMessage() {} - -func (x *ImportProgress) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[31] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ImportProgress.ProtoReflect.Descriptor instead. -func (*ImportProgress) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{31} -} - -func (x *ImportProgress) GetImported() uint32 { - if x != nil { - return x.Imported - } - return 0 -} - -func (x *ImportProgress) GetTotal() uint32 { - if x != nil { - return x.Total - } - return 0 -} - -func (x *ImportProgress) GetCurrentFile() string { - if x != nil && x.CurrentFile != nil { - return *x.CurrentFile - } - return "" -} - -func (x *ImportProgress) GetErrorMessage() string { - if x != nil && x.ErrorMessage != nil { - return *x.ErrorMessage - } - return "" -} - -var File_musicfs_proto protoreflect.FileDescriptor - -const file_musicfs_proto_rawDesc = "" + - "\n" + - "\rmusicfs.proto\x12\n" + - "musicfs.v1\"\a\n" + - "\x05Empty\"\xa2\x01\n" + - "\rSearchRequest\x12\x14\n" + - "\x05query\x18\x01 \x01(\tR\x05query\x12\x19\n" + - "\x05limit\x18\x02 \x01(\rH\x00R\x05limit\x88\x01\x01\x12\x1b\n" + - "\x06offset\x18\x03 \x01(\rH\x01R\x06offset\x88\x01\x01\x12 \n" + - "\torigin_id\x18\x04 \x01(\tH\x02R\boriginId\x88\x01\x01B\b\n" + - "\x06_limitB\t\n" + - "\a_offsetB\f\n" + - "\n" + - "_origin_id\"\x8d\x01\n" + - "\x0eSearchResponse\x122\n" + - "\aresults\x18\x01 \x03(\v2\x18.musicfs.v1.SearchResultR\aresults\x12#\n" + - "\rtotal_matches\x18\x02 \x01(\x04R\ftotalMatches\x12\"\n" + - "\rquery_time_ms\x18\x03 \x01(\rR\vqueryTimeMs\"\xdb\x02\n" + - "\fSearchResult\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12!\n" + - "\fvirtual_path\x18\x02 \x01(\tR\vvirtualPath\x12\x1b\n" + - "\x06artist\x18\x03 \x01(\tH\x00R\x06artist\x88\x01\x01\x12\x19\n" + - "\x05album\x18\x04 \x01(\tH\x01R\x05album\x88\x01\x01\x12\x19\n" + - "\x05title\x18\x05 \x01(\tH\x02R\x05title\x88\x01\x01\x12\x14\n" + - "\x05score\x18\x06 \x01(\x02R\x05score\x12H\n" + - "\n" + - "highlights\x18\a \x03(\v2(.musicfs.v1.SearchResult.HighlightsEntryR\n" + - "highlights\x1a=\n" + - "\x0fHighlightsEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\t\n" + - "\a_artistB\b\n" + - "\x06_albumB\b\n" + - "\x06_title\"\xef\x02\n" + - "\x0eStatusResponse\x12\x18\n" + - "\aversion\x18\x01 \x01(\tR\aversion\x12\x1f\n" + - "\vuptime_secs\x18\x02 \x01(\x04R\n" + - "uptimeSecs\x12\x1f\n" + - "\vmount_point\x18\x03 \x01(\tR\n" + - "mountPoint\x12,\n" + - "\x05state\x18\x04 \x01(\x0e2\x16.musicfs.v1.MountStateR\x05state\x12*\n" + - "\x11open_file_handles\x18\x05 \x01(\rR\x0fopenFileHandles\x12$\n" + - "\x0efuse_ops_total\x18\x06 \x01(\x04R\ffuseOpsTotal\x12#\n" + - "\rfiles_indexed\x18\a \x01(\x04R\ffilesIndexed\x12(\n" + - "\x10cache_size_bytes\x18\b \x01(\x04R\x0ecacheSizeBytes\x122\n" + - "\aorigins\x18\t \x03(\v2\x18.musicfs.v1.OriginStatusR\aorigins\"\x92\x01\n" + - "\fOriginStatus\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + - "\vorigin_type\x18\x02 \x01(\tR\n" + - "originType\x120\n" + - "\x06health\x18\x03 \x01(\x0e2\x18.musicfs.v1.HealthStatusR\x06health\x12\x1f\n" + - "\vfiles_count\x18\x04 \x01(\x04R\n" + - "filesCount\"P\n" + - "\x0fShutdownRequest\x12\x1a\n" + - "\bgraceful\x18\x01 \x01(\bR\bgraceful\x12!\n" + - "\ftimeout_secs\x18\x02 \x01(\rR\vtimeoutSecs\"p\n" + - "\tTierStats\x12\x18\n" + - "\aentries\x18\x01 \x01(\x04R\aentries\x12\x1d\n" + - "\n" + - "size_bytes\x18\x02 \x01(\x04R\tsizeBytes\x12\x12\n" + - "\x04hits\x18\x03 \x01(\x04R\x04hits\x12\x16\n" + - "\x06misses\x18\x04 \x01(\x04R\x06misses\"\xbc\x04\n" + - "\n" + - "CacheStats\x12(\n" + - "\x10total_size_bytes\x18\x01 \x01(\x04R\x0etotalSizeBytes\x12&\n" + - "\x0fused_size_bytes\x18\x02 \x01(\x04R\rusedSizeBytes\x12(\n" + - "\x10size_limit_bytes\x18\x03 \x01(\x04R\x0esizeLimitBytes\x12\x1f\n" + - "\vchunk_count\x18\x04 \x01(\x04R\n" + - "chunkCount\x12#\n" + - "\rchunks_unique\x18\x05 \x01(\x04R\fchunksUnique\x12\x1f\n" + - "\vdedup_ratio\x18\x06 \x01(\x01R\n" + - "dedupRatio\x12\x1b\n" + - "\thit_count\x18\a \x01(\x04R\bhitCount\x12\x1d\n" + - "\n" + - "miss_count\x18\b \x01(\x04R\tmissCount\x12\x1b\n" + - "\thit_ratio\x18\t \x01(\x01R\bhitRatio\x12)\n" + - "\x10metadata_entries\x18\n" + - " \x01(\x04R\x0fmetadataEntries\x12%\n" + - "\x0emetadata_bytes\x18\v \x01(\x04R\rmetadataBytes\x126\n" + - "\vl1_metadata\x18\f \x01(\v2\x15.musicfs.v1.TierStatsR\n" + - "l1Metadata\x124\n" + - "\n" + - "l2_headers\x18\r \x01(\v2\x15.musicfs.v1.TierStatsR\tl2Headers\x122\n" + - "\tl3_chunks\x18\x0e \x01(\v2\x15.musicfs.v1.TierStatsR\bl3Chunks\"\x8d\x01\n" + - "\x11ClearCacheRequest\x12 \n" + - "\torigin_id\x18\x01 \x01(\tH\x00R\boriginId\x88\x01\x01\x12%\n" + - "\x0eclear_metadata\x18\x02 \x01(\bR\rclearMetadata\x12!\n" + - "\fclear_chunks\x18\x03 \x01(\bR\vclearChunksB\f\n" + - "\n" + - "_origin_id\"`\n" + - "\x12ClearCacheResponse\x12#\n" + - "\rbytes_cleared\x18\x01 \x01(\x04R\fbytesCleared\x12%\n" + - "\x0echunks_cleared\x18\x02 \x01(\x04R\rchunksCleared\"W\n" + - "\x0fPrefetchRequest\x12\x14\n" + - "\x05paths\x18\x01 \x03(\tR\x05paths\x12 \n" + - "\torigin_id\x18\x02 \x01(\tH\x00R\boriginId\x88\x01\x01B\f\n" + - "\n" + - "_origin_id\"\x8e\x01\n" + - "\x10PrefetchProgress\x12!\n" + - "\fcurrent_path\x18\x01 \x01(\tR\vcurrentPath\x12\x1c\n" + - "\tcompleted\x18\x02 \x01(\rR\tcompleted\x12\x14\n" + - "\x05total\x18\x03 \x01(\rR\x05total\x12#\n" + - "\rbytes_fetched\x18\x04 \x01(\x04R\fbytesFetched\"C\n" + - "\x0fOriginsResponse\x120\n" + - "\aorigins\x18\x01 \x03(\v2\x16.musicfs.v1.OriginInfoR\aorigins\"\xfa\x01\n" + - "\n" + - "OriginInfo\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + - "\vorigin_type\x18\x02 \x01(\tR\n" + - "originType\x12!\n" + - "\fdisplay_name\x18\x03 \x01(\tR\vdisplayName\x12\x1b\n" + - "\troot_path\x18\x04 \x01(\tR\brootPath\x120\n" + - "\x06health\x18\x05 \x01(\x0e2\x18.musicfs.v1.HealthStatusR\x06health\x12\x1f\n" + - "\vfiles_count\x18\x06 \x01(\x04R\n" + - "filesCount\x12(\n" + - "\x10total_size_bytes\x18\a \x01(\x04R\x0etotalSizeBytes\"T\n" + - "\rOriginRequest\x12\x1b\n" + - "\torigin_id\x18\x01 \x01(\tR\boriginId\x12\x1b\n" + - "\x06subdir\x18\x02 \x01(\tH\x00R\x06subdir\x88\x01\x01B\t\n" + - "\a_subdir\"\xb8\x01\n" + - "\x14OriginHealthResponse\x12\x1b\n" + - "\torigin_id\x18\x01 \x01(\tR\boriginId\x120\n" + - "\x06status\x18\x02 \x01(\x0e2\x18.musicfs.v1.HealthStatusR\x06status\x12\x1d\n" + - "\amessage\x18\x03 \x01(\tH\x00R\amessage\x88\x01\x01\x12&\n" + - "\x0flast_check_secs\x18\x04 \x01(\x04R\rlastCheckSecsB\n" + - "\n" + - "\b_message\"\xcf\x01\n" + - "\fSyncProgress\x12\x14\n" + - "\x05phase\x18\x01 \x01(\tR\x05phase\x12\x18\n" + - "\acurrent\x18\x02 \x01(\rR\acurrent\x12\x14\n" + - "\x05total\x18\x03 \x01(\rR\x05total\x12!\n" + - "\fcurrent_path\x18\x04 \x01(\tR\vcurrentPath\x12!\n" + - "\fbytes_synced\x18\x05 \x01(\x04R\vbytesSynced\x123\n" + - "\tnew_files\x18\x06 \x03(\v2\x16.musicfs.v1.SyncedFileR\bnewFiles\"\\\n" + - "\n" + - "SyncedFile\x12\x12\n" + - "\x04path\x18\x01 \x01(\tR\x04path\x12\x17\n" + - "\afile_id\x18\x02 \x01(\x03R\x06fileId\x12!\n" + - "\fvirtual_path\x18\x03 \x01(\tR\vvirtualPath\"^\n" + - "\vEventFilter\x12\x1f\n" + - "\vevent_types\x18\x01 \x03(\tR\n" + - "eventTypes\x12 \n" + - "\torigin_id\x18\x02 \x01(\tH\x00R\boriginId\x88\x01\x01B\f\n" + - "\n" + - "_origin_id\"\xbf\x02\n" + - "\x05Event\x12\x1d\n" + - "\n" + - "event_type\x18\x01 \x01(\tR\teventType\x12!\n" + - "\ftimestamp_ms\x18\x02 \x01(\x03R\vtimestampMs\x12 \n" + - "\torigin_id\x18\x03 \x01(\tH\x00R\boriginId\x88\x01\x01\x12\x17\n" + - "\x04path\x18\x04 \x01(\tH\x01R\x04path\x88\x01\x01\x12\x1c\n" + - "\afile_id\x18\x05 \x01(\x03H\x02R\x06fileId\x88\x01\x01\x12;\n" + - "\bmetadata\x18\x06 \x03(\v2\x1f.musicfs.v1.Event.MetadataEntryR\bmetadata\x1a;\n" + - "\rMetadataEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\f\n" + - "\n" + - "_origin_idB\a\n" + - "\x05_pathB\n" + - "\n" + - "\b_file_id\"7\n" + - "\x12GetMetadataRequest\x12!\n" + - "\fvirtual_path\x18\x01 \x01(\tR\vvirtualPath\"\x83\x11\n" + - "\x10MetadataResponse\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x19\n" + - "\x05title\x18\x02 \x01(\tH\x00R\x05title\x88\x01\x01\x12\x1b\n" + - "\x06artist\x18\x03 \x01(\tH\x01R\x06artist\x88\x01\x01\x12\x19\n" + - "\x05album\x18\x04 \x01(\tH\x02R\x05album\x88\x01\x01\x12&\n" + - "\falbum_artist\x18\x05 \x01(\tH\x03R\valbumArtist\x88\x01\x01\x12\x17\n" + - "\x04year\x18\x06 \x01(\rH\x04R\x04year\x88\x01\x01\x12\x19\n" + - "\x05track\x18\a \x01(\rH\x05R\x05track\x88\x01\x01\x12\x17\n" + - "\x04disc\x18\b \x01(\rH\x06R\x04disc\x88\x01\x01\x12\x19\n" + - "\x05genre\x18\t \x01(\tH\aR\x05genre\x88\x01\x01\x12\x1b\n" + - "\x06format\x18\n" + - " \x01(\tH\bR\x06format\x88\x01\x01\x12$\n" + - "\vduration_ms\x18\v \x01(\x04H\tR\n" + - "durationMs\x88\x01\x01\x12\x1d\n" + - "\abitrate\x18\f \x01(\x04H\n" + - "R\abitrate\x88\x01\x01\x12$\n" + - "\vtrack_total\x18\r \x01(\rH\vR\n" + - "trackTotal\x88\x01\x01\x12\"\n" + - "\n" + - "disc_total\x18\x0e \x01(\rH\fR\tdiscTotal\x88\x01\x01\x12\x17\n" + - "\x04date\x18\x0f \x01(\tH\rR\x04date\x88\x01\x01\x12\x1f\n" + - "\bcomposer\x18\x10 \x01(\tH\x0eR\bcomposer\x88\x01\x01\x12\x1d\n" + - "\acomment\x18\x11 \x01(\tH\x0fR\acomment\x88\x01\x01\x12\x1b\n" + - "\x06lyrics\x18\x12 \x01(\tH\x10R\x06lyrics\x88\x01\x01\x12!\n" + - "\tcopyright\x18\x13 \x01(\tH\x11R\tcopyright\x88\x01\x01\x12%\n" + - "\vcompilation\x18\x14 \x01(\bH\x12R\vcompilation\x88\x01\x01\x12$\n" + - "\vartist_sort\x18\x15 \x01(\tH\x13R\n" + - "artistSort\x88\x01\x01\x12/\n" + - "\x11album_artist_sort\x18\x16 \x01(\tH\x14R\x0falbumArtistSort\x88\x01\x01\x12\"\n" + - "\n" + - "album_sort\x18\x17 \x01(\tH\x15R\talbumSort\x88\x01\x01\x12\"\n" + - "\n" + - "title_sort\x18\x18 \x01(\tH\x16R\ttitleSort\x88\x01\x01\x12+\n" + - "\x0fmb_recording_id\x18\x19 \x01(\tH\x17R\rmbRecordingId\x88\x01\x01\x12#\n" + - "\vmb_album_id\x18\x1a \x01(\tH\x18R\tmbAlbumId\x88\x01\x01\x12%\n" + - "\fmb_artist_id\x18\x1b \x01(\tH\x19R\n" + - "mbArtistId\x88\x01\x01\x120\n" + - "\x12mb_album_artist_id\x18\x1c \x01(\tH\x1aR\x0fmbAlbumArtistId\x88\x01\x01\x122\n" + - "\x13mb_release_group_id\x18\x1d \x01(\tH\x1bR\x10mbReleaseGroupId\x88\x01\x01\x127\n" + - "\x15replaygain_track_gain\x18\x1e \x01(\x02H\x1cR\x13replaygainTrackGain\x88\x01\x01\x127\n" + - "\x15replaygain_track_peak\x18\x1f \x01(\x02H\x1dR\x13replaygainTrackPeak\x88\x01\x01\x127\n" + - "\x15replaygain_album_gain\x18 \x01(\x02H\x1eR\x13replaygainAlbumGain\x88\x01\x01\x127\n" + - "\x15replaygain_album_peak\x18! \x01(\x02H\x1fR\x13replaygainAlbumPeak\x88\x01\x01\x12\x1f\n" + - "\bchannels\x18\" \x01(\rH R\bchannels\x88\x01\x01\x12+\n" + - "\x0fbits_per_sample\x18# \x01(\rH!R\rbitsPerSample\x88\x01\x01\x12\x1d\n" + - "\aencoder\x18$ \x01(\tH\"R\aencoder\x88\x01\x01\x12\x19\n" + - "\x05label\x18( \x01(\tH#R\x05label\x88\x01\x01\x12\"\n" + - "\n" + - "album_type\x18) \x01(\tH$R\talbumType\x88\x01\x01\x12 \n" + - "\tcover_url\x18* \x01(\tH%R\bcoverUrl\x88\x01\x01\x12M\n" + - "\vcustom_tags\x182 \x03(\v2,.musicfs.v1.MetadataResponse.CustomTagsEntryR\n" + - "customTags\x1a=\n" + - "\x0fCustomTagsEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\b\n" + - "\x06_titleB\t\n" + - "\a_artistB\b\n" + - "\x06_albumB\x0f\n" + - "\r_album_artistB\a\n" + - "\x05_yearB\b\n" + - "\x06_trackB\a\n" + - "\x05_discB\b\n" + - "\x06_genreB\t\n" + - "\a_formatB\x0e\n" + - "\f_duration_msB\n" + - "\n" + - "\b_bitrateB\x0e\n" + - "\f_track_totalB\r\n" + - "\v_disc_totalB\a\n" + - "\x05_dateB\v\n" + - "\t_composerB\n" + - "\n" + - "\b_commentB\t\n" + - "\a_lyricsB\f\n" + - "\n" + - "_copyrightB\x0e\n" + - "\f_compilationB\x0e\n" + - "\f_artist_sortB\x14\n" + - "\x12_album_artist_sortB\r\n" + - "\v_album_sortB\r\n" + - "\v_title_sortB\x12\n" + - "\x10_mb_recording_idB\x0e\n" + - "\f_mb_album_idB\x0f\n" + - "\r_mb_artist_idB\x15\n" + - "\x13_mb_album_artist_idB\x16\n" + - "\x14_mb_release_group_idB\x18\n" + - "\x16_replaygain_track_gainB\x18\n" + - "\x16_replaygain_track_peakB\x18\n" + - "\x16_replaygain_album_gainB\x18\n" + - "\x16_replaygain_album_peakB\v\n" + - "\t_channelsB\x12\n" + - "\x10_bits_per_sampleB\n" + - "\n" + - "\b_encoderB\b\n" + - "\x06_labelB\r\n" + - "\v_album_typeB\f\n" + - "\n" + - "_cover_url\"\xf2\f\n" + - "\x15UpdateMetadataRequest\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x19\n" + - "\x05title\x18\x02 \x01(\tH\x00R\x05title\x88\x01\x01\x12\x1b\n" + - "\x06artist\x18\x03 \x01(\tH\x01R\x06artist\x88\x01\x01\x12\x19\n" + - "\x05album\x18\x04 \x01(\tH\x02R\x05album\x88\x01\x01\x12&\n" + - "\falbum_artist\x18\x05 \x01(\tH\x03R\valbumArtist\x88\x01\x01\x12&\n" + - "\ftrack_number\x18\x06 \x01(\rH\x04R\vtrackNumber\x88\x01\x01\x12$\n" + - "\vdisc_number\x18\a \x01(\rH\x05R\n" + - "discNumber\x88\x01\x01\x12\x17\n" + - "\x04date\x18\b \x01(\tH\x06R\x04date\x88\x01\x01\x12\x19\n" + - "\x05genre\x18\t \x01(\tH\aR\x05genre\x88\x01\x01\x12\x1f\n" + - "\bcomposer\x18\n" + - " \x01(\tH\bR\bcomposer\x88\x01\x01\x12\x1d\n" + - "\acomment\x18\v \x01(\tH\tR\acomment\x88\x01\x01\x12\x1b\n" + - "\x06lyrics\x18\f \x01(\tH\n" + - "R\x06lyrics\x88\x01\x01\x12!\n" + - "\tcopyright\x18\r \x01(\tH\vR\tcopyright\x88\x01\x01\x12%\n" + - "\vcompilation\x18\x0e \x01(\bH\fR\vcompilation\x88\x01\x01\x12$\n" + - "\vartist_sort\x18\x0f \x01(\tH\rR\n" + - "artistSort\x88\x01\x01\x12/\n" + - "\x11album_artist_sort\x18\x10 \x01(\tH\x0eR\x0falbumArtistSort\x88\x01\x01\x12\"\n" + - "\n" + - "album_sort\x18\x11 \x01(\tH\x0fR\talbumSort\x88\x01\x01\x12\"\n" + - "\n" + - "title_sort\x18\x12 \x01(\tH\x10R\ttitleSort\x88\x01\x01\x12+\n" + - "\x0fmb_recording_id\x18\x14 \x01(\tH\x11R\rmbRecordingId\x88\x01\x01\x12#\n" + - "\vmb_album_id\x18\x15 \x01(\tH\x12R\tmbAlbumId\x88\x01\x01\x12%\n" + - "\fmb_artist_id\x18\x16 \x01(\tH\x13R\n" + - "mbArtistId\x88\x01\x01\x127\n" + - "\x15replaygain_track_gain\x18\x1e \x01(\x02H\x14R\x13replaygainTrackGain\x88\x01\x01\x127\n" + - "\x15replaygain_track_peak\x18\x1f \x01(\x02H\x15R\x13replaygainTrackPeak\x88\x01\x01\x127\n" + - "\x15replaygain_album_gain\x18 \x01(\x02H\x16R\x13replaygainAlbumGain\x88\x01\x01\x127\n" + - "\x15replaygain_album_peak\x18! \x01(\x02H\x17R\x13replaygainAlbumPeak\x88\x01\x01\x12\x19\n" + - "\x05label\x18( \x01(\tH\x18R\x05label\x88\x01\x01\x12\"\n" + - "\n" + - "album_type\x18) \x01(\tH\x19R\talbumType\x88\x01\x01\x12 \n" + - "\tcover_url\x18* \x01(\tH\x1aR\bcoverUrl\x88\x01\x01\x12R\n" + - "\vcustom_tags\x182 \x03(\v21.musicfs.v1.UpdateMetadataRequest.CustomTagsEntryR\n" + - "customTags\x1a=\n" + - "\x0fCustomTagsEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\b\n" + - "\x06_titleB\t\n" + - "\a_artistB\b\n" + - "\x06_albumB\x0f\n" + - "\r_album_artistB\x0f\n" + - "\r_track_numberB\x0e\n" + - "\f_disc_numberB\a\n" + - "\x05_dateB\b\n" + - "\x06_genreB\v\n" + - "\t_composerB\n" + - "\n" + - "\b_commentB\t\n" + - "\a_lyricsB\f\n" + - "\n" + - "_copyrightB\x0e\n" + - "\f_compilationB\x0e\n" + - "\f_artist_sortB\x14\n" + - "\x12_album_artist_sortB\r\n" + - "\v_album_sortB\r\n" + - "\v_title_sortB\x12\n" + - "\x10_mb_recording_idB\x0e\n" + - "\f_mb_album_idB\x0f\n" + - "\r_mb_artist_idB\x18\n" + - "\x16_replaygain_track_gainB\x18\n" + - "\x16_replaygain_track_peakB\x18\n" + - "\x16_replaygain_album_gainB\x18\n" + - "\x16_replaygain_album_peakB\b\n" + - "\x06_labelB\r\n" + - "\v_album_typeB\f\n" + - "\n" + - "_cover_url\"\x87\x01\n" + - "\x16UpdateMetadataResponse\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x18\n" + - "\asuccess\x18\x02 \x01(\bR\asuccess\x12(\n" + - "\rerror_message\x18\x03 \x01(\tH\x00R\ferrorMessage\x88\x01\x01B\x10\n" + - "\x0e_error_message\".\n" + - "\x13ClearOverlayRequest\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\"\x85\x01\n" + - "\x14ClearOverlayResponse\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x18\n" + - "\asuccess\x18\x02 \x01(\bR\asuccess\x12(\n" + - "\rerror_message\x18\x03 \x01(\tH\x00R\ferrorMessage\x88\x01\x01B\x10\n" + - "\x0e_error_message\"G\n" + - "\x12BatchUpdateRequest\x121\n" + - "\x05items\x18\x01 \x03(\v2\x1b.musicfs.v1.BatchUpdateItemR\x05items\"i\n" + - "\x0fBatchUpdateItem\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12=\n" + - "\bmetadata\x18\x02 \x01(\v2!.musicfs.v1.UpdateMetadataRequestR\bmetadata\"\xc6\x01\n" + - "\x13BatchUpdateProgress\x12\x1c\n" + - "\tcompleted\x18\x01 \x01(\rR\tcompleted\x12\x14\n" + - "\x05total\x18\x02 \x01(\rR\x05total\x12+\n" + - "\x0fcurrent_file_id\x18\x03 \x01(\x03H\x00R\rcurrentFileId\x88\x01\x01\x12(\n" + - "\rerror_message\x18\x04 \x01(\tH\x01R\ferrorMessage\x88\x01\x01B\x12\n" + - "\x10_current_file_idB\x10\n" + - "\x0e_error_message\"`\n" + - "\x15ImportMetadataRequest\x12\x1f\n" + - "\vsource_path\x18\x01 \x01(\tR\n" + - "sourcePath\x12\x1b\n" + - "\x06format\x18\x02 \x01(\tH\x00R\x06format\x88\x01\x01B\t\n" + - "\a_format\"\xb7\x01\n" + - "\x0eImportProgress\x12\x1a\n" + - "\bimported\x18\x01 \x01(\rR\bimported\x12\x14\n" + - "\x05total\x18\x02 \x01(\rR\x05total\x12&\n" + - "\fcurrent_file\x18\x03 \x01(\tH\x00R\vcurrentFile\x88\x01\x01\x12(\n" + - "\rerror_message\x18\x04 \x01(\tH\x01R\ferrorMessage\x88\x01\x01B\x0f\n" + - "\r_current_fileB\x10\n" + - "\x0e_error_message*\x81\x01\n" + - "\n" + - "MountState\x12\x11\n" + - "\rMOUNT_UNKNOWN\x10\x00\x12\x12\n" + - "\x0eMOUNT_MOUNTING\x10\x01\x12\x0f\n" + - "\vMOUNT_READY\x10\x02\x12\x11\n" + - "\rMOUNT_SYNCING\x10\x03\x12\x12\n" + - "\x0eMOUNT_DEGRADED\x10\x04\x12\x14\n" + - "\x10MOUNT_UNMOUNTING\x10\x05*a\n" + - "\fHealthStatus\x12\x12\n" + - "\x0eHEALTH_UNKNOWN\x10\x00\x12\x12\n" + - "\x0eHEALTH_HEALTHY\x10\x01\x12\x13\n" + - "\x0fHEALTH_DEGRADED\x10\x02\x12\x14\n" + - "\x10HEALTH_UNHEALTHY\x10\x032\xf2\x05\n" + - "\aMusicFS\x12?\n" + - "\x06Search\x12\x19.musicfs.v1.SearchRequest\x1a\x1a.musicfs.v1.SearchResponse\x12E\n" + - "\fSearchStream\x12\x19.musicfs.v1.SearchRequest\x1a\x18.musicfs.v1.SearchResult0\x01\x12:\n" + - "\tGetStatus\x12\x11.musicfs.v1.Empty\x1a\x1a.musicfs.v1.StatusResponse\x12:\n" + - "\bShutdown\x12\x1b.musicfs.v1.ShutdownRequest\x1a\x11.musicfs.v1.Empty\x12:\n" + - "\rGetCacheStats\x12\x11.musicfs.v1.Empty\x1a\x16.musicfs.v1.CacheStats\x12K\n" + - "\n" + - "ClearCache\x12\x1d.musicfs.v1.ClearCacheRequest\x1a\x1e.musicfs.v1.ClearCacheResponse\x12G\n" + - "\bPrefetch\x12\x1b.musicfs.v1.PrefetchRequest\x1a\x1c.musicfs.v1.PrefetchProgress0\x01\x12=\n" + - "\vListOrigins\x12\x11.musicfs.v1.Empty\x1a\x1b.musicfs.v1.OriginsResponse\x12N\n" + - "\x0fGetOriginHealth\x12\x19.musicfs.v1.OriginRequest\x1a .musicfs.v1.OriginHealthResponse\x12E\n" + - "\fRescanOrigin\x12\x19.musicfs.v1.OriginRequest\x1a\x18.musicfs.v1.SyncProgress0\x01\x12?\n" + - "\x0fSubscribeEvents\x12\x17.musicfs.v1.EventFilter\x1a\x11.musicfs.v1.Event0\x012\xb7\x03\n" + - "\x0fMetadataService\x12K\n" + - "\vGetMetadata\x12\x1e.musicfs.v1.GetMetadataRequest\x1a\x1c.musicfs.v1.MetadataResponse\x12W\n" + - "\x0eUpdateMetadata\x12!.musicfs.v1.UpdateMetadataRequest\x1a\".musicfs.v1.UpdateMetadataResponse\x12Q\n" + - "\fClearOverlay\x12\x1f.musicfs.v1.ClearOverlayRequest\x1a .musicfs.v1.ClearOverlayResponse\x12X\n" + - "\x13BatchUpdateMetadata\x12\x1e.musicfs.v1.BatchUpdateRequest\x1a\x1f.musicfs.v1.BatchUpdateProgress0\x01\x12Q\n" + - "\x0eImportMetadata\x12!.musicfs.v1.ImportMetadataRequest\x1a\x1a.musicfs.v1.ImportProgress0\x01B6Z4homelab.lan/music-agregator/gen/musicfs/v1;musicfsv1b\x06proto3" - -var ( - file_musicfs_proto_rawDescOnce sync.Once - file_musicfs_proto_rawDescData []byte -) - -func file_musicfs_proto_rawDescGZIP() []byte { - file_musicfs_proto_rawDescOnce.Do(func() { - file_musicfs_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_musicfs_proto_rawDesc), len(file_musicfs_proto_rawDesc))) - }) - return file_musicfs_proto_rawDescData -} - -var file_musicfs_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_musicfs_proto_msgTypes = make([]protoimpl.MessageInfo, 36) -var file_musicfs_proto_goTypes = []any{ - (MountState)(0), // 0: musicfs.v1.MountState - (HealthStatus)(0), // 1: musicfs.v1.HealthStatus - (*Empty)(nil), // 2: musicfs.v1.Empty - (*SearchRequest)(nil), // 3: musicfs.v1.SearchRequest - (*SearchResponse)(nil), // 4: musicfs.v1.SearchResponse - (*SearchResult)(nil), // 5: musicfs.v1.SearchResult - (*StatusResponse)(nil), // 6: musicfs.v1.StatusResponse - (*OriginStatus)(nil), // 7: musicfs.v1.OriginStatus - (*ShutdownRequest)(nil), // 8: musicfs.v1.ShutdownRequest - (*TierStats)(nil), // 9: musicfs.v1.TierStats - (*CacheStats)(nil), // 10: musicfs.v1.CacheStats - (*ClearCacheRequest)(nil), // 11: musicfs.v1.ClearCacheRequest - (*ClearCacheResponse)(nil), // 12: musicfs.v1.ClearCacheResponse - (*PrefetchRequest)(nil), // 13: musicfs.v1.PrefetchRequest - (*PrefetchProgress)(nil), // 14: musicfs.v1.PrefetchProgress - (*OriginsResponse)(nil), // 15: musicfs.v1.OriginsResponse - (*OriginInfo)(nil), // 16: musicfs.v1.OriginInfo - (*OriginRequest)(nil), // 17: musicfs.v1.OriginRequest - (*OriginHealthResponse)(nil), // 18: musicfs.v1.OriginHealthResponse - (*SyncProgress)(nil), // 19: musicfs.v1.SyncProgress - (*SyncedFile)(nil), // 20: musicfs.v1.SyncedFile - (*EventFilter)(nil), // 21: musicfs.v1.EventFilter - (*Event)(nil), // 22: musicfs.v1.Event - (*GetMetadataRequest)(nil), // 23: musicfs.v1.GetMetadataRequest - (*MetadataResponse)(nil), // 24: musicfs.v1.MetadataResponse - (*UpdateMetadataRequest)(nil), // 25: musicfs.v1.UpdateMetadataRequest - (*UpdateMetadataResponse)(nil), // 26: musicfs.v1.UpdateMetadataResponse - (*ClearOverlayRequest)(nil), // 27: musicfs.v1.ClearOverlayRequest - (*ClearOverlayResponse)(nil), // 28: musicfs.v1.ClearOverlayResponse - (*BatchUpdateRequest)(nil), // 29: musicfs.v1.BatchUpdateRequest - (*BatchUpdateItem)(nil), // 30: musicfs.v1.BatchUpdateItem - (*BatchUpdateProgress)(nil), // 31: musicfs.v1.BatchUpdateProgress - (*ImportMetadataRequest)(nil), // 32: musicfs.v1.ImportMetadataRequest - (*ImportProgress)(nil), // 33: musicfs.v1.ImportProgress - nil, // 34: musicfs.v1.SearchResult.HighlightsEntry - nil, // 35: musicfs.v1.Event.MetadataEntry - nil, // 36: musicfs.v1.MetadataResponse.CustomTagsEntry - nil, // 37: musicfs.v1.UpdateMetadataRequest.CustomTagsEntry -} -var file_musicfs_proto_depIdxs = []int32{ - 5, // 0: musicfs.v1.SearchResponse.results:type_name -> musicfs.v1.SearchResult - 34, // 1: musicfs.v1.SearchResult.highlights:type_name -> musicfs.v1.SearchResult.HighlightsEntry - 0, // 2: musicfs.v1.StatusResponse.state:type_name -> musicfs.v1.MountState - 7, // 3: musicfs.v1.StatusResponse.origins:type_name -> musicfs.v1.OriginStatus - 1, // 4: musicfs.v1.OriginStatus.health:type_name -> musicfs.v1.HealthStatus - 9, // 5: musicfs.v1.CacheStats.l1_metadata:type_name -> musicfs.v1.TierStats - 9, // 6: musicfs.v1.CacheStats.l2_headers:type_name -> musicfs.v1.TierStats - 9, // 7: musicfs.v1.CacheStats.l3_chunks:type_name -> musicfs.v1.TierStats - 16, // 8: musicfs.v1.OriginsResponse.origins:type_name -> musicfs.v1.OriginInfo - 1, // 9: musicfs.v1.OriginInfo.health:type_name -> musicfs.v1.HealthStatus - 1, // 10: musicfs.v1.OriginHealthResponse.status:type_name -> musicfs.v1.HealthStatus - 20, // 11: musicfs.v1.SyncProgress.new_files:type_name -> musicfs.v1.SyncedFile - 35, // 12: musicfs.v1.Event.metadata:type_name -> musicfs.v1.Event.MetadataEntry - 36, // 13: musicfs.v1.MetadataResponse.custom_tags:type_name -> musicfs.v1.MetadataResponse.CustomTagsEntry - 37, // 14: musicfs.v1.UpdateMetadataRequest.custom_tags:type_name -> musicfs.v1.UpdateMetadataRequest.CustomTagsEntry - 30, // 15: musicfs.v1.BatchUpdateRequest.items:type_name -> musicfs.v1.BatchUpdateItem - 25, // 16: musicfs.v1.BatchUpdateItem.metadata:type_name -> musicfs.v1.UpdateMetadataRequest - 3, // 17: musicfs.v1.MusicFS.Search:input_type -> musicfs.v1.SearchRequest - 3, // 18: musicfs.v1.MusicFS.SearchStream:input_type -> musicfs.v1.SearchRequest - 2, // 19: musicfs.v1.MusicFS.GetStatus:input_type -> musicfs.v1.Empty - 8, // 20: musicfs.v1.MusicFS.Shutdown:input_type -> musicfs.v1.ShutdownRequest - 2, // 21: musicfs.v1.MusicFS.GetCacheStats:input_type -> musicfs.v1.Empty - 11, // 22: musicfs.v1.MusicFS.ClearCache:input_type -> musicfs.v1.ClearCacheRequest - 13, // 23: musicfs.v1.MusicFS.Prefetch:input_type -> musicfs.v1.PrefetchRequest - 2, // 24: musicfs.v1.MusicFS.ListOrigins:input_type -> musicfs.v1.Empty - 17, // 25: musicfs.v1.MusicFS.GetOriginHealth:input_type -> musicfs.v1.OriginRequest - 17, // 26: musicfs.v1.MusicFS.RescanOrigin:input_type -> musicfs.v1.OriginRequest - 21, // 27: musicfs.v1.MusicFS.SubscribeEvents:input_type -> musicfs.v1.EventFilter - 23, // 28: musicfs.v1.MetadataService.GetMetadata:input_type -> musicfs.v1.GetMetadataRequest - 25, // 29: musicfs.v1.MetadataService.UpdateMetadata:input_type -> musicfs.v1.UpdateMetadataRequest - 27, // 30: musicfs.v1.MetadataService.ClearOverlay:input_type -> musicfs.v1.ClearOverlayRequest - 29, // 31: musicfs.v1.MetadataService.BatchUpdateMetadata:input_type -> musicfs.v1.BatchUpdateRequest - 32, // 32: musicfs.v1.MetadataService.ImportMetadata:input_type -> musicfs.v1.ImportMetadataRequest - 4, // 33: musicfs.v1.MusicFS.Search:output_type -> musicfs.v1.SearchResponse - 5, // 34: musicfs.v1.MusicFS.SearchStream:output_type -> musicfs.v1.SearchResult - 6, // 35: musicfs.v1.MusicFS.GetStatus:output_type -> musicfs.v1.StatusResponse - 2, // 36: musicfs.v1.MusicFS.Shutdown:output_type -> musicfs.v1.Empty - 10, // 37: musicfs.v1.MusicFS.GetCacheStats:output_type -> musicfs.v1.CacheStats - 12, // 38: musicfs.v1.MusicFS.ClearCache:output_type -> musicfs.v1.ClearCacheResponse - 14, // 39: musicfs.v1.MusicFS.Prefetch:output_type -> musicfs.v1.PrefetchProgress - 15, // 40: musicfs.v1.MusicFS.ListOrigins:output_type -> musicfs.v1.OriginsResponse - 18, // 41: musicfs.v1.MusicFS.GetOriginHealth:output_type -> musicfs.v1.OriginHealthResponse - 19, // 42: musicfs.v1.MusicFS.RescanOrigin:output_type -> musicfs.v1.SyncProgress - 22, // 43: musicfs.v1.MusicFS.SubscribeEvents:output_type -> musicfs.v1.Event - 24, // 44: musicfs.v1.MetadataService.GetMetadata:output_type -> musicfs.v1.MetadataResponse - 26, // 45: musicfs.v1.MetadataService.UpdateMetadata:output_type -> musicfs.v1.UpdateMetadataResponse - 28, // 46: musicfs.v1.MetadataService.ClearOverlay:output_type -> musicfs.v1.ClearOverlayResponse - 31, // 47: musicfs.v1.MetadataService.BatchUpdateMetadata:output_type -> musicfs.v1.BatchUpdateProgress - 33, // 48: musicfs.v1.MetadataService.ImportMetadata:output_type -> musicfs.v1.ImportProgress - 33, // [33:49] is the sub-list for method output_type - 17, // [17:33] is the sub-list for method input_type - 17, // [17:17] is the sub-list for extension type_name - 17, // [17:17] is the sub-list for extension extendee - 0, // [0:17] is the sub-list for field type_name -} - -func init() { file_musicfs_proto_init() } -func file_musicfs_proto_init() { - if File_musicfs_proto != nil { - return - } - file_musicfs_proto_msgTypes[1].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[3].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[9].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[11].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[15].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[16].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[19].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[20].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[22].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[23].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[24].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[26].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[29].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[30].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[31].OneofWrappers = []any{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_musicfs_proto_rawDesc), len(file_musicfs_proto_rawDesc)), - NumEnums: 2, - NumMessages: 36, - NumExtensions: 0, - NumServices: 2, - }, - GoTypes: file_musicfs_proto_goTypes, - DependencyIndexes: file_musicfs_proto_depIdxs, - EnumInfos: file_musicfs_proto_enumTypes, - MessageInfos: file_musicfs_proto_msgTypes, - }.Build() - File_musicfs_proto = out.File - file_musicfs_proto_goTypes = nil - file_musicfs_proto_depIdxs = nil -} diff --git a/gen/musicfs/v1/musicfs.pb.go b/gen/musicfs/v1/musicfs.pb.go deleted file mode 100644 index 677a490..0000000 --- a/gen/musicfs/v1/musicfs.pb.go +++ /dev/null @@ -1,3274 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc (unknown) -// source: musicfs.proto - -package musicfsv1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type MountState int32 - -const ( - MountState_MOUNT_UNKNOWN MountState = 0 - MountState_MOUNT_MOUNTING MountState = 1 - MountState_MOUNT_READY MountState = 2 - MountState_MOUNT_SYNCING MountState = 3 - MountState_MOUNT_DEGRADED MountState = 4 - MountState_MOUNT_UNMOUNTING MountState = 5 -) - -// Enum value maps for MountState. -var ( - MountState_name = map[int32]string{ - 0: "MOUNT_UNKNOWN", - 1: "MOUNT_MOUNTING", - 2: "MOUNT_READY", - 3: "MOUNT_SYNCING", - 4: "MOUNT_DEGRADED", - 5: "MOUNT_UNMOUNTING", - } - MountState_value = map[string]int32{ - "MOUNT_UNKNOWN": 0, - "MOUNT_MOUNTING": 1, - "MOUNT_READY": 2, - "MOUNT_SYNCING": 3, - "MOUNT_DEGRADED": 4, - "MOUNT_UNMOUNTING": 5, - } -) - -func (x MountState) Enum() *MountState { - p := new(MountState) - *p = x - return p -} - -func (x MountState) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MountState) Descriptor() protoreflect.EnumDescriptor { - return file_musicfs_proto_enumTypes[0].Descriptor() -} - -func (MountState) Type() protoreflect.EnumType { - return &file_musicfs_proto_enumTypes[0] -} - -func (x MountState) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MountState.Descriptor instead. -func (MountState) EnumDescriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{0} -} - -type HealthStatus int32 - -const ( - HealthStatus_HEALTH_UNKNOWN HealthStatus = 0 - HealthStatus_HEALTH_HEALTHY HealthStatus = 1 - HealthStatus_HEALTH_DEGRADED HealthStatus = 2 - HealthStatus_HEALTH_UNHEALTHY HealthStatus = 3 -) - -// Enum value maps for HealthStatus. -var ( - HealthStatus_name = map[int32]string{ - 0: "HEALTH_UNKNOWN", - 1: "HEALTH_HEALTHY", - 2: "HEALTH_DEGRADED", - 3: "HEALTH_UNHEALTHY", - } - HealthStatus_value = map[string]int32{ - "HEALTH_UNKNOWN": 0, - "HEALTH_HEALTHY": 1, - "HEALTH_DEGRADED": 2, - "HEALTH_UNHEALTHY": 3, - } -) - -func (x HealthStatus) Enum() *HealthStatus { - p := new(HealthStatus) - *p = x - return p -} - -func (x HealthStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HealthStatus) Descriptor() protoreflect.EnumDescriptor { - return file_musicfs_proto_enumTypes[1].Descriptor() -} - -func (HealthStatus) Type() protoreflect.EnumType { - return &file_musicfs_proto_enumTypes[1] -} - -func (x HealthStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HealthStatus.Descriptor instead. -func (HealthStatus) EnumDescriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{1} -} - -type Empty struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Empty) Reset() { - *x = Empty{} - mi := &file_musicfs_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Empty) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Empty) ProtoMessage() {} - -func (x *Empty) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Empty.ProtoReflect.Descriptor instead. -func (*Empty) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{0} -} - -type SearchRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` - Limit *uint32 `protobuf:"varint,2,opt,name=limit,proto3,oneof" json:"limit,omitempty"` - Offset *uint32 `protobuf:"varint,3,opt,name=offset,proto3,oneof" json:"offset,omitempty"` - OriginId *string `protobuf:"bytes,4,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchRequest) Reset() { - *x = SearchRequest{} - mi := &file_musicfs_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchRequest) ProtoMessage() {} - -func (x *SearchRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchRequest.ProtoReflect.Descriptor instead. -func (*SearchRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{1} -} - -func (x *SearchRequest) GetQuery() string { - if x != nil { - return x.Query - } - return "" -} - -func (x *SearchRequest) GetLimit() uint32 { - if x != nil && x.Limit != nil { - return *x.Limit - } - return 0 -} - -func (x *SearchRequest) GetOffset() uint32 { - if x != nil && x.Offset != nil { - return *x.Offset - } - return 0 -} - -func (x *SearchRequest) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -type SearchResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Results []*SearchResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` - TotalMatches uint64 `protobuf:"varint,2,opt,name=total_matches,json=totalMatches,proto3" json:"total_matches,omitempty"` - QueryTimeMs uint32 `protobuf:"varint,3,opt,name=query_time_ms,json=queryTimeMs,proto3" json:"query_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchResponse) Reset() { - *x = SearchResponse{} - mi := &file_musicfs_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchResponse) ProtoMessage() {} - -func (x *SearchResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchResponse.ProtoReflect.Descriptor instead. -func (*SearchResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{2} -} - -func (x *SearchResponse) GetResults() []*SearchResult { - if x != nil { - return x.Results - } - return nil -} - -func (x *SearchResponse) GetTotalMatches() uint64 { - if x != nil { - return x.TotalMatches - } - return 0 -} - -func (x *SearchResponse) GetQueryTimeMs() uint32 { - if x != nil { - return x.QueryTimeMs - } - return 0 -} - -type SearchResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - VirtualPath string `protobuf:"bytes,2,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"` - Artist *string `protobuf:"bytes,3,opt,name=artist,proto3,oneof" json:"artist,omitempty"` - Album *string `protobuf:"bytes,4,opt,name=album,proto3,oneof" json:"album,omitempty"` - Title *string `protobuf:"bytes,5,opt,name=title,proto3,oneof" json:"title,omitempty"` - Score float32 `protobuf:"fixed32,6,opt,name=score,proto3" json:"score,omitempty"` - Highlights map[string]string `protobuf:"bytes,7,rep,name=highlights,proto3" json:"highlights,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchResult) Reset() { - *x = SearchResult{} - mi := &file_musicfs_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchResult) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchResult) ProtoMessage() {} - -func (x *SearchResult) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SearchResult.ProtoReflect.Descriptor instead. -func (*SearchResult) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{3} -} - -func (x *SearchResult) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *SearchResult) GetVirtualPath() string { - if x != nil { - return x.VirtualPath - } - return "" -} - -func (x *SearchResult) GetArtist() string { - if x != nil && x.Artist != nil { - return *x.Artist - } - return "" -} - -func (x *SearchResult) GetAlbum() string { - if x != nil && x.Album != nil { - return *x.Album - } - return "" -} - -func (x *SearchResult) GetTitle() string { - if x != nil && x.Title != nil { - return *x.Title - } - return "" -} - -func (x *SearchResult) GetScore() float32 { - if x != nil { - return x.Score - } - return 0 -} - -func (x *SearchResult) GetHighlights() map[string]string { - if x != nil { - return x.Highlights - } - return nil -} - -type StatusResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` - UptimeSecs uint64 `protobuf:"varint,2,opt,name=uptime_secs,json=uptimeSecs,proto3" json:"uptime_secs,omitempty"` - MountPoint string `protobuf:"bytes,3,opt,name=mount_point,json=mountPoint,proto3" json:"mount_point,omitempty"` - State MountState `protobuf:"varint,4,opt,name=state,proto3,enum=musicfs.v1.MountState" json:"state,omitempty"` - OpenFileHandles uint32 `protobuf:"varint,5,opt,name=open_file_handles,json=openFileHandles,proto3" json:"open_file_handles,omitempty"` - FuseOpsTotal uint64 `protobuf:"varint,6,opt,name=fuse_ops_total,json=fuseOpsTotal,proto3" json:"fuse_ops_total,omitempty"` - FilesIndexed uint64 `protobuf:"varint,7,opt,name=files_indexed,json=filesIndexed,proto3" json:"files_indexed,omitempty"` - CacheSizeBytes uint64 `protobuf:"varint,8,opt,name=cache_size_bytes,json=cacheSizeBytes,proto3" json:"cache_size_bytes,omitempty"` - Origins []*OriginStatus `protobuf:"bytes,9,rep,name=origins,proto3" json:"origins,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *StatusResponse) Reset() { - *x = StatusResponse{} - mi := &file_musicfs_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *StatusResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StatusResponse) ProtoMessage() {} - -func (x *StatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead. -func (*StatusResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{4} -} - -func (x *StatusResponse) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -func (x *StatusResponse) GetUptimeSecs() uint64 { - if x != nil { - return x.UptimeSecs - } - return 0 -} - -func (x *StatusResponse) GetMountPoint() string { - if x != nil { - return x.MountPoint - } - return "" -} - -func (x *StatusResponse) GetState() MountState { - if x != nil { - return x.State - } - return MountState_MOUNT_UNKNOWN -} - -func (x *StatusResponse) GetOpenFileHandles() uint32 { - if x != nil { - return x.OpenFileHandles - } - return 0 -} - -func (x *StatusResponse) GetFuseOpsTotal() uint64 { - if x != nil { - return x.FuseOpsTotal - } - return 0 -} - -func (x *StatusResponse) GetFilesIndexed() uint64 { - if x != nil { - return x.FilesIndexed - } - return 0 -} - -func (x *StatusResponse) GetCacheSizeBytes() uint64 { - if x != nil { - return x.CacheSizeBytes - } - return 0 -} - -func (x *StatusResponse) GetOrigins() []*OriginStatus { - if x != nil { - return x.Origins - } - return nil -} - -type OriginStatus struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - OriginType string `protobuf:"bytes,2,opt,name=origin_type,json=originType,proto3" json:"origin_type,omitempty"` - Health HealthStatus `protobuf:"varint,3,opt,name=health,proto3,enum=musicfs.v1.HealthStatus" json:"health,omitempty"` - FilesCount uint64 `protobuf:"varint,4,opt,name=files_count,json=filesCount,proto3" json:"files_count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginStatus) Reset() { - *x = OriginStatus{} - mi := &file_musicfs_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginStatus) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginStatus) ProtoMessage() {} - -func (x *OriginStatus) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginStatus.ProtoReflect.Descriptor instead. -func (*OriginStatus) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{5} -} - -func (x *OriginStatus) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *OriginStatus) GetOriginType() string { - if x != nil { - return x.OriginType - } - return "" -} - -func (x *OriginStatus) GetHealth() HealthStatus { - if x != nil { - return x.Health - } - return HealthStatus_HEALTH_UNKNOWN -} - -func (x *OriginStatus) GetFilesCount() uint64 { - if x != nil { - return x.FilesCount - } - return 0 -} - -type ShutdownRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Graceful bool `protobuf:"varint,1,opt,name=graceful,proto3" json:"graceful,omitempty"` - TimeoutSecs uint32 `protobuf:"varint,2,opt,name=timeout_secs,json=timeoutSecs,proto3" json:"timeout_secs,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ShutdownRequest) Reset() { - *x = ShutdownRequest{} - mi := &file_musicfs_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ShutdownRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ShutdownRequest) ProtoMessage() {} - -func (x *ShutdownRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ShutdownRequest.ProtoReflect.Descriptor instead. -func (*ShutdownRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{6} -} - -func (x *ShutdownRequest) GetGraceful() bool { - if x != nil { - return x.Graceful - } - return false -} - -func (x *ShutdownRequest) GetTimeoutSecs() uint32 { - if x != nil { - return x.TimeoutSecs - } - return 0 -} - -type TierStats struct { - state protoimpl.MessageState `protogen:"open.v1"` - Entries uint64 `protobuf:"varint,1,opt,name=entries,proto3" json:"entries,omitempty"` - SizeBytes uint64 `protobuf:"varint,2,opt,name=size_bytes,json=sizeBytes,proto3" json:"size_bytes,omitempty"` - Hits uint64 `protobuf:"varint,3,opt,name=hits,proto3" json:"hits,omitempty"` - Misses uint64 `protobuf:"varint,4,opt,name=misses,proto3" json:"misses,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TierStats) Reset() { - *x = TierStats{} - mi := &file_musicfs_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TierStats) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TierStats) ProtoMessage() {} - -func (x *TierStats) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TierStats.ProtoReflect.Descriptor instead. -func (*TierStats) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{7} -} - -func (x *TierStats) GetEntries() uint64 { - if x != nil { - return x.Entries - } - return 0 -} - -func (x *TierStats) GetSizeBytes() uint64 { - if x != nil { - return x.SizeBytes - } - return 0 -} - -func (x *TierStats) GetHits() uint64 { - if x != nil { - return x.Hits - } - return 0 -} - -func (x *TierStats) GetMisses() uint64 { - if x != nil { - return x.Misses - } - return 0 -} - -type CacheStats struct { - state protoimpl.MessageState `protogen:"open.v1"` - TotalSizeBytes uint64 `protobuf:"varint,1,opt,name=total_size_bytes,json=totalSizeBytes,proto3" json:"total_size_bytes,omitempty"` - UsedSizeBytes uint64 `protobuf:"varint,2,opt,name=used_size_bytes,json=usedSizeBytes,proto3" json:"used_size_bytes,omitempty"` - SizeLimitBytes uint64 `protobuf:"varint,3,opt,name=size_limit_bytes,json=sizeLimitBytes,proto3" json:"size_limit_bytes,omitempty"` - ChunkCount uint64 `protobuf:"varint,4,opt,name=chunk_count,json=chunkCount,proto3" json:"chunk_count,omitempty"` - ChunksUnique uint64 `protobuf:"varint,5,opt,name=chunks_unique,json=chunksUnique,proto3" json:"chunks_unique,omitempty"` - DedupRatio float64 `protobuf:"fixed64,6,opt,name=dedup_ratio,json=dedupRatio,proto3" json:"dedup_ratio,omitempty"` - HitCount uint64 `protobuf:"varint,7,opt,name=hit_count,json=hitCount,proto3" json:"hit_count,omitempty"` - MissCount uint64 `protobuf:"varint,8,opt,name=miss_count,json=missCount,proto3" json:"miss_count,omitempty"` - HitRatio float64 `protobuf:"fixed64,9,opt,name=hit_ratio,json=hitRatio,proto3" json:"hit_ratio,omitempty"` - MetadataEntries uint64 `protobuf:"varint,10,opt,name=metadata_entries,json=metadataEntries,proto3" json:"metadata_entries,omitempty"` - MetadataBytes uint64 `protobuf:"varint,11,opt,name=metadata_bytes,json=metadataBytes,proto3" json:"metadata_bytes,omitempty"` - L1Metadata *TierStats `protobuf:"bytes,12,opt,name=l1_metadata,json=l1Metadata,proto3" json:"l1_metadata,omitempty"` - L2Headers *TierStats `protobuf:"bytes,13,opt,name=l2_headers,json=l2Headers,proto3" json:"l2_headers,omitempty"` - L3Chunks *TierStats `protobuf:"bytes,14,opt,name=l3_chunks,json=l3Chunks,proto3" json:"l3_chunks,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CacheStats) Reset() { - *x = CacheStats{} - mi := &file_musicfs_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CacheStats) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CacheStats) ProtoMessage() {} - -func (x *CacheStats) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CacheStats.ProtoReflect.Descriptor instead. -func (*CacheStats) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{8} -} - -func (x *CacheStats) GetTotalSizeBytes() uint64 { - if x != nil { - return x.TotalSizeBytes - } - return 0 -} - -func (x *CacheStats) GetUsedSizeBytes() uint64 { - if x != nil { - return x.UsedSizeBytes - } - return 0 -} - -func (x *CacheStats) GetSizeLimitBytes() uint64 { - if x != nil { - return x.SizeLimitBytes - } - return 0 -} - -func (x *CacheStats) GetChunkCount() uint64 { - if x != nil { - return x.ChunkCount - } - return 0 -} - -func (x *CacheStats) GetChunksUnique() uint64 { - if x != nil { - return x.ChunksUnique - } - return 0 -} - -func (x *CacheStats) GetDedupRatio() float64 { - if x != nil { - return x.DedupRatio - } - return 0 -} - -func (x *CacheStats) GetHitCount() uint64 { - if x != nil { - return x.HitCount - } - return 0 -} - -func (x *CacheStats) GetMissCount() uint64 { - if x != nil { - return x.MissCount - } - return 0 -} - -func (x *CacheStats) GetHitRatio() float64 { - if x != nil { - return x.HitRatio - } - return 0 -} - -func (x *CacheStats) GetMetadataEntries() uint64 { - if x != nil { - return x.MetadataEntries - } - return 0 -} - -func (x *CacheStats) GetMetadataBytes() uint64 { - if x != nil { - return x.MetadataBytes - } - return 0 -} - -func (x *CacheStats) GetL1Metadata() *TierStats { - if x != nil { - return x.L1Metadata - } - return nil -} - -func (x *CacheStats) GetL2Headers() *TierStats { - if x != nil { - return x.L2Headers - } - return nil -} - -func (x *CacheStats) GetL3Chunks() *TierStats { - if x != nil { - return x.L3Chunks - } - return nil -} - -type ClearCacheRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - OriginId *string `protobuf:"bytes,1,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - ClearMetadata bool `protobuf:"varint,2,opt,name=clear_metadata,json=clearMetadata,proto3" json:"clear_metadata,omitempty"` - ClearChunks bool `protobuf:"varint,3,opt,name=clear_chunks,json=clearChunks,proto3" json:"clear_chunks,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ClearCacheRequest) Reset() { - *x = ClearCacheRequest{} - mi := &file_musicfs_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ClearCacheRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ClearCacheRequest) ProtoMessage() {} - -func (x *ClearCacheRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ClearCacheRequest.ProtoReflect.Descriptor instead. -func (*ClearCacheRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{9} -} - -func (x *ClearCacheRequest) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -func (x *ClearCacheRequest) GetClearMetadata() bool { - if x != nil { - return x.ClearMetadata - } - return false -} - -func (x *ClearCacheRequest) GetClearChunks() bool { - if x != nil { - return x.ClearChunks - } - return false -} - -type ClearCacheResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - BytesCleared uint64 `protobuf:"varint,1,opt,name=bytes_cleared,json=bytesCleared,proto3" json:"bytes_cleared,omitempty"` - ChunksCleared uint64 `protobuf:"varint,2,opt,name=chunks_cleared,json=chunksCleared,proto3" json:"chunks_cleared,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ClearCacheResponse) Reset() { - *x = ClearCacheResponse{} - mi := &file_musicfs_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ClearCacheResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ClearCacheResponse) ProtoMessage() {} - -func (x *ClearCacheResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ClearCacheResponse.ProtoReflect.Descriptor instead. -func (*ClearCacheResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{10} -} - -func (x *ClearCacheResponse) GetBytesCleared() uint64 { - if x != nil { - return x.BytesCleared - } - return 0 -} - -func (x *ClearCacheResponse) GetChunksCleared() uint64 { - if x != nil { - return x.ChunksCleared - } - return 0 -} - -type PrefetchRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Paths []string `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"` - OriginId *string `protobuf:"bytes,2,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PrefetchRequest) Reset() { - *x = PrefetchRequest{} - mi := &file_musicfs_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PrefetchRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrefetchRequest) ProtoMessage() {} - -func (x *PrefetchRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[11] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrefetchRequest.ProtoReflect.Descriptor instead. -func (*PrefetchRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{11} -} - -func (x *PrefetchRequest) GetPaths() []string { - if x != nil { - return x.Paths - } - return nil -} - -func (x *PrefetchRequest) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -type PrefetchProgress struct { - state protoimpl.MessageState `protogen:"open.v1"` - CurrentPath string `protobuf:"bytes,1,opt,name=current_path,json=currentPath,proto3" json:"current_path,omitempty"` - Completed uint32 `protobuf:"varint,2,opt,name=completed,proto3" json:"completed,omitempty"` - Total uint32 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"` - BytesFetched uint64 `protobuf:"varint,4,opt,name=bytes_fetched,json=bytesFetched,proto3" json:"bytes_fetched,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PrefetchProgress) Reset() { - *x = PrefetchProgress{} - mi := &file_musicfs_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PrefetchProgress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrefetchProgress) ProtoMessage() {} - -func (x *PrefetchProgress) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[12] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrefetchProgress.ProtoReflect.Descriptor instead. -func (*PrefetchProgress) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{12} -} - -func (x *PrefetchProgress) GetCurrentPath() string { - if x != nil { - return x.CurrentPath - } - return "" -} - -func (x *PrefetchProgress) GetCompleted() uint32 { - if x != nil { - return x.Completed - } - return 0 -} - -func (x *PrefetchProgress) GetTotal() uint32 { - if x != nil { - return x.Total - } - return 0 -} - -func (x *PrefetchProgress) GetBytesFetched() uint64 { - if x != nil { - return x.BytesFetched - } - return 0 -} - -type OriginsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Origins []*OriginInfo `protobuf:"bytes,1,rep,name=origins,proto3" json:"origins,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginsResponse) Reset() { - *x = OriginsResponse{} - mi := &file_musicfs_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginsResponse) ProtoMessage() {} - -func (x *OriginsResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[13] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginsResponse.ProtoReflect.Descriptor instead. -func (*OriginsResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{13} -} - -func (x *OriginsResponse) GetOrigins() []*OriginInfo { - if x != nil { - return x.Origins - } - return nil -} - -type OriginInfo struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - OriginType string `protobuf:"bytes,2,opt,name=origin_type,json=originType,proto3" json:"origin_type,omitempty"` - DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` - RootPath string `protobuf:"bytes,4,opt,name=root_path,json=rootPath,proto3" json:"root_path,omitempty"` - Health HealthStatus `protobuf:"varint,5,opt,name=health,proto3,enum=musicfs.v1.HealthStatus" json:"health,omitempty"` - FilesCount uint64 `protobuf:"varint,6,opt,name=files_count,json=filesCount,proto3" json:"files_count,omitempty"` - TotalSizeBytes uint64 `protobuf:"varint,7,opt,name=total_size_bytes,json=totalSizeBytes,proto3" json:"total_size_bytes,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginInfo) Reset() { - *x = OriginInfo{} - mi := &file_musicfs_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginInfo) ProtoMessage() {} - -func (x *OriginInfo) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[14] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginInfo.ProtoReflect.Descriptor instead. -func (*OriginInfo) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{14} -} - -func (x *OriginInfo) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *OriginInfo) GetOriginType() string { - if x != nil { - return x.OriginType - } - return "" -} - -func (x *OriginInfo) GetDisplayName() string { - if x != nil { - return x.DisplayName - } - return "" -} - -func (x *OriginInfo) GetRootPath() string { - if x != nil { - return x.RootPath - } - return "" -} - -func (x *OriginInfo) GetHealth() HealthStatus { - if x != nil { - return x.Health - } - return HealthStatus_HEALTH_UNKNOWN -} - -func (x *OriginInfo) GetFilesCount() uint64 { - if x != nil { - return x.FilesCount - } - return 0 -} - -func (x *OriginInfo) GetTotalSizeBytes() uint64 { - if x != nil { - return x.TotalSizeBytes - } - return 0 -} - -type OriginRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - OriginId string `protobuf:"bytes,1,opt,name=origin_id,json=originId,proto3" json:"origin_id,omitempty"` - // Optional subdirectory to scope the scan (relative to origin root). - // If empty, scans the entire origin. - // Example: "Metallica - Master of Puppets (1986) [FLAC]" - Subdir *string `protobuf:"bytes,2,opt,name=subdir,proto3,oneof" json:"subdir,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginRequest) Reset() { - *x = OriginRequest{} - mi := &file_musicfs_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginRequest) ProtoMessage() {} - -func (x *OriginRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[15] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginRequest.ProtoReflect.Descriptor instead. -func (*OriginRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{15} -} - -func (x *OriginRequest) GetOriginId() string { - if x != nil { - return x.OriginId - } - return "" -} - -func (x *OriginRequest) GetSubdir() string { - if x != nil && x.Subdir != nil { - return *x.Subdir - } - return "" -} - -type OriginHealthResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - OriginId string `protobuf:"bytes,1,opt,name=origin_id,json=originId,proto3" json:"origin_id,omitempty"` - Status HealthStatus `protobuf:"varint,2,opt,name=status,proto3,enum=musicfs.v1.HealthStatus" json:"status,omitempty"` - Message *string `protobuf:"bytes,3,opt,name=message,proto3,oneof" json:"message,omitempty"` - LastCheckSecs uint64 `protobuf:"varint,4,opt,name=last_check_secs,json=lastCheckSecs,proto3" json:"last_check_secs,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OriginHealthResponse) Reset() { - *x = OriginHealthResponse{} - mi := &file_musicfs_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OriginHealthResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OriginHealthResponse) ProtoMessage() {} - -func (x *OriginHealthResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[16] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OriginHealthResponse.ProtoReflect.Descriptor instead. -func (*OriginHealthResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{16} -} - -func (x *OriginHealthResponse) GetOriginId() string { - if x != nil { - return x.OriginId - } - return "" -} - -func (x *OriginHealthResponse) GetStatus() HealthStatus { - if x != nil { - return x.Status - } - return HealthStatus_HEALTH_UNKNOWN -} - -func (x *OriginHealthResponse) GetMessage() string { - if x != nil && x.Message != nil { - return *x.Message - } - return "" -} - -func (x *OriginHealthResponse) GetLastCheckSecs() uint64 { - if x != nil { - return x.LastCheckSecs - } - return 0 -} - -type SyncProgress struct { - state protoimpl.MessageState `protogen:"open.v1"` - Phase string `protobuf:"bytes,1,opt,name=phase,proto3" json:"phase,omitempty"` - Current uint32 `protobuf:"varint,2,opt,name=current,proto3" json:"current,omitempty"` - Total uint32 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"` - CurrentPath string `protobuf:"bytes,4,opt,name=current_path,json=currentPath,proto3" json:"current_path,omitempty"` - BytesSynced uint64 `protobuf:"varint,5,opt,name=bytes_synced,json=bytesSynced,proto3" json:"bytes_synced,omitempty"` - NewFiles []*SyncedFile `protobuf:"bytes,6,rep,name=new_files,json=newFiles,proto3" json:"new_files,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SyncProgress) Reset() { - *x = SyncProgress{} - mi := &file_musicfs_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SyncProgress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncProgress) ProtoMessage() {} - -func (x *SyncProgress) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[17] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SyncProgress.ProtoReflect.Descriptor instead. -func (*SyncProgress) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{17} -} - -func (x *SyncProgress) GetPhase() string { - if x != nil { - return x.Phase - } - return "" -} - -func (x *SyncProgress) GetCurrent() uint32 { - if x != nil { - return x.Current - } - return 0 -} - -func (x *SyncProgress) GetTotal() uint32 { - if x != nil { - return x.Total - } - return 0 -} - -func (x *SyncProgress) GetCurrentPath() string { - if x != nil { - return x.CurrentPath - } - return "" -} - -func (x *SyncProgress) GetBytesSynced() uint64 { - if x != nil { - return x.BytesSynced - } - return 0 -} - -func (x *SyncProgress) GetNewFiles() []*SyncedFile { - if x != nil { - return x.NewFiles - } - return nil -} - -type SyncedFile struct { - state protoimpl.MessageState `protogen:"open.v1"` - Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - FileId int64 `protobuf:"varint,2,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - VirtualPath string `protobuf:"bytes,3,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SyncedFile) Reset() { - *x = SyncedFile{} - mi := &file_musicfs_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SyncedFile) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncedFile) ProtoMessage() {} - -func (x *SyncedFile) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[18] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SyncedFile.ProtoReflect.Descriptor instead. -func (*SyncedFile) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{18} -} - -func (x *SyncedFile) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *SyncedFile) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *SyncedFile) GetVirtualPath() string { - if x != nil { - return x.VirtualPath - } - return "" -} - -type EventFilter struct { - state protoimpl.MessageState `protogen:"open.v1"` - EventTypes []string `protobuf:"bytes,1,rep,name=event_types,json=eventTypes,proto3" json:"event_types,omitempty"` - OriginId *string `protobuf:"bytes,2,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *EventFilter) Reset() { - *x = EventFilter{} - mi := &file_musicfs_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *EventFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EventFilter) ProtoMessage() {} - -func (x *EventFilter) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[19] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EventFilter.ProtoReflect.Descriptor instead. -func (*EventFilter) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{19} -} - -func (x *EventFilter) GetEventTypes() []string { - if x != nil { - return x.EventTypes - } - return nil -} - -func (x *EventFilter) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -type Event struct { - state protoimpl.MessageState `protogen:"open.v1"` - EventType string `protobuf:"bytes,1,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` - TimestampMs int64 `protobuf:"varint,2,opt,name=timestamp_ms,json=timestampMs,proto3" json:"timestamp_ms,omitempty"` - OriginId *string `protobuf:"bytes,3,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` - Path *string `protobuf:"bytes,4,opt,name=path,proto3,oneof" json:"path,omitempty"` - FileId *int64 `protobuf:"varint,5,opt,name=file_id,json=fileId,proto3,oneof" json:"file_id,omitempty"` - Metadata map[string]string `protobuf:"bytes,6,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Event) Reset() { - *x = Event{} - mi := &file_musicfs_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Event) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Event) ProtoMessage() {} - -func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[20] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Event.ProtoReflect.Descriptor instead. -func (*Event) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{20} -} - -func (x *Event) GetEventType() string { - if x != nil { - return x.EventType - } - return "" -} - -func (x *Event) GetTimestampMs() int64 { - if x != nil { - return x.TimestampMs - } - return 0 -} - -func (x *Event) GetOriginId() string { - if x != nil && x.OriginId != nil { - return *x.OriginId - } - return "" -} - -func (x *Event) GetPath() string { - if x != nil && x.Path != nil { - return *x.Path - } - return "" -} - -func (x *Event) GetFileId() int64 { - if x != nil && x.FileId != nil { - return *x.FileId - } - return 0 -} - -func (x *Event) GetMetadata() map[string]string { - if x != nil { - return x.Metadata - } - return nil -} - -type GetMetadataRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - VirtualPath string `protobuf:"bytes,1,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetMetadataRequest) Reset() { - *x = GetMetadataRequest{} - mi := &file_musicfs_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetMetadataRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetMetadataRequest) ProtoMessage() {} - -func (x *GetMetadataRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[21] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetMetadataRequest.ProtoReflect.Descriptor instead. -func (*GetMetadataRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{21} -} - -func (x *GetMetadataRequest) GetVirtualPath() string { - if x != nil { - return x.VirtualPath - } - return "" -} - -type MetadataResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Title *string `protobuf:"bytes,2,opt,name=title,proto3,oneof" json:"title,omitempty"` - Artist *string `protobuf:"bytes,3,opt,name=artist,proto3,oneof" json:"artist,omitempty"` - Album *string `protobuf:"bytes,4,opt,name=album,proto3,oneof" json:"album,omitempty"` - AlbumArtist *string `protobuf:"bytes,5,opt,name=album_artist,json=albumArtist,proto3,oneof" json:"album_artist,omitempty"` - Year *uint32 `protobuf:"varint,6,opt,name=year,proto3,oneof" json:"year,omitempty"` - Track *uint32 `protobuf:"varint,7,opt,name=track,proto3,oneof" json:"track,omitempty"` - Disc *uint32 `protobuf:"varint,8,opt,name=disc,proto3,oneof" json:"disc,omitempty"` - Genre *string `protobuf:"bytes,9,opt,name=genre,proto3,oneof" json:"genre,omitempty"` - Format *string `protobuf:"bytes,10,opt,name=format,proto3,oneof" json:"format,omitempty"` - DurationMs *uint64 `protobuf:"varint,11,opt,name=duration_ms,json=durationMs,proto3,oneof" json:"duration_ms,omitempty"` - Bitrate *uint64 `protobuf:"varint,12,opt,name=bitrate,proto3,oneof" json:"bitrate,omitempty"` - TrackTotal *uint32 `protobuf:"varint,13,opt,name=track_total,json=trackTotal,proto3,oneof" json:"track_total,omitempty"` - DiscTotal *uint32 `protobuf:"varint,14,opt,name=disc_total,json=discTotal,proto3,oneof" json:"disc_total,omitempty"` - Date *string `protobuf:"bytes,15,opt,name=date,proto3,oneof" json:"date,omitempty"` - Composer *string `protobuf:"bytes,16,opt,name=composer,proto3,oneof" json:"composer,omitempty"` - Comment *string `protobuf:"bytes,17,opt,name=comment,proto3,oneof" json:"comment,omitempty"` - Lyrics *string `protobuf:"bytes,18,opt,name=lyrics,proto3,oneof" json:"lyrics,omitempty"` - Copyright *string `protobuf:"bytes,19,opt,name=copyright,proto3,oneof" json:"copyright,omitempty"` - Compilation *bool `protobuf:"varint,20,opt,name=compilation,proto3,oneof" json:"compilation,omitempty"` - ArtistSort *string `protobuf:"bytes,21,opt,name=artist_sort,json=artistSort,proto3,oneof" json:"artist_sort,omitempty"` - AlbumArtistSort *string `protobuf:"bytes,22,opt,name=album_artist_sort,json=albumArtistSort,proto3,oneof" json:"album_artist_sort,omitempty"` - AlbumSort *string `protobuf:"bytes,23,opt,name=album_sort,json=albumSort,proto3,oneof" json:"album_sort,omitempty"` - TitleSort *string `protobuf:"bytes,24,opt,name=title_sort,json=titleSort,proto3,oneof" json:"title_sort,omitempty"` - MbRecordingId *string `protobuf:"bytes,25,opt,name=mb_recording_id,json=mbRecordingId,proto3,oneof" json:"mb_recording_id,omitempty"` - MbAlbumId *string `protobuf:"bytes,26,opt,name=mb_album_id,json=mbAlbumId,proto3,oneof" json:"mb_album_id,omitempty"` - MbArtistId *string `protobuf:"bytes,27,opt,name=mb_artist_id,json=mbArtistId,proto3,oneof" json:"mb_artist_id,omitempty"` - MbAlbumArtistId *string `protobuf:"bytes,28,opt,name=mb_album_artist_id,json=mbAlbumArtistId,proto3,oneof" json:"mb_album_artist_id,omitempty"` - MbReleaseGroupId *string `protobuf:"bytes,29,opt,name=mb_release_group_id,json=mbReleaseGroupId,proto3,oneof" json:"mb_release_group_id,omitempty"` - ReplaygainTrackGain *float32 `protobuf:"fixed32,30,opt,name=replaygain_track_gain,json=replaygainTrackGain,proto3,oneof" json:"replaygain_track_gain,omitempty"` - ReplaygainTrackPeak *float32 `protobuf:"fixed32,31,opt,name=replaygain_track_peak,json=replaygainTrackPeak,proto3,oneof" json:"replaygain_track_peak,omitempty"` - ReplaygainAlbumGain *float32 `protobuf:"fixed32,32,opt,name=replaygain_album_gain,json=replaygainAlbumGain,proto3,oneof" json:"replaygain_album_gain,omitempty"` - ReplaygainAlbumPeak *float32 `protobuf:"fixed32,33,opt,name=replaygain_album_peak,json=replaygainAlbumPeak,proto3,oneof" json:"replaygain_album_peak,omitempty"` - Channels *uint32 `protobuf:"varint,34,opt,name=channels,proto3,oneof" json:"channels,omitempty"` - BitsPerSample *uint32 `protobuf:"varint,35,opt,name=bits_per_sample,json=bitsPerSample,proto3,oneof" json:"bits_per_sample,omitempty"` - Encoder *string `protobuf:"bytes,36,opt,name=encoder,proto3,oneof" json:"encoder,omitempty"` - Label *string `protobuf:"bytes,40,opt,name=label,proto3,oneof" json:"label,omitempty"` - AlbumType *string `protobuf:"bytes,41,opt,name=album_type,json=albumType,proto3,oneof" json:"album_type,omitempty"` - CoverUrl *string `protobuf:"bytes,42,opt,name=cover_url,json=coverUrl,proto3,oneof" json:"cover_url,omitempty"` - CustomTags map[string]string `protobuf:"bytes,50,rep,name=custom_tags,json=customTags,proto3" json:"custom_tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MetadataResponse) Reset() { - *x = MetadataResponse{} - mi := &file_musicfs_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MetadataResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MetadataResponse) ProtoMessage() {} - -func (x *MetadataResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[22] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MetadataResponse.ProtoReflect.Descriptor instead. -func (*MetadataResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{22} -} - -func (x *MetadataResponse) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *MetadataResponse) GetTitle() string { - if x != nil && x.Title != nil { - return *x.Title - } - return "" -} - -func (x *MetadataResponse) GetArtist() string { - if x != nil && x.Artist != nil { - return *x.Artist - } - return "" -} - -func (x *MetadataResponse) GetAlbum() string { - if x != nil && x.Album != nil { - return *x.Album - } - return "" -} - -func (x *MetadataResponse) GetAlbumArtist() string { - if x != nil && x.AlbumArtist != nil { - return *x.AlbumArtist - } - return "" -} - -func (x *MetadataResponse) GetYear() uint32 { - if x != nil && x.Year != nil { - return *x.Year - } - return 0 -} - -func (x *MetadataResponse) GetTrack() uint32 { - if x != nil && x.Track != nil { - return *x.Track - } - return 0 -} - -func (x *MetadataResponse) GetDisc() uint32 { - if x != nil && x.Disc != nil { - return *x.Disc - } - return 0 -} - -func (x *MetadataResponse) GetGenre() string { - if x != nil && x.Genre != nil { - return *x.Genre - } - return "" -} - -func (x *MetadataResponse) GetFormat() string { - if x != nil && x.Format != nil { - return *x.Format - } - return "" -} - -func (x *MetadataResponse) GetDurationMs() uint64 { - if x != nil && x.DurationMs != nil { - return *x.DurationMs - } - return 0 -} - -func (x *MetadataResponse) GetBitrate() uint64 { - if x != nil && x.Bitrate != nil { - return *x.Bitrate - } - return 0 -} - -func (x *MetadataResponse) GetTrackTotal() uint32 { - if x != nil && x.TrackTotal != nil { - return *x.TrackTotal - } - return 0 -} - -func (x *MetadataResponse) GetDiscTotal() uint32 { - if x != nil && x.DiscTotal != nil { - return *x.DiscTotal - } - return 0 -} - -func (x *MetadataResponse) GetDate() string { - if x != nil && x.Date != nil { - return *x.Date - } - return "" -} - -func (x *MetadataResponse) GetComposer() string { - if x != nil && x.Composer != nil { - return *x.Composer - } - return "" -} - -func (x *MetadataResponse) GetComment() string { - if x != nil && x.Comment != nil { - return *x.Comment - } - return "" -} - -func (x *MetadataResponse) GetLyrics() string { - if x != nil && x.Lyrics != nil { - return *x.Lyrics - } - return "" -} - -func (x *MetadataResponse) GetCopyright() string { - if x != nil && x.Copyright != nil { - return *x.Copyright - } - return "" -} - -func (x *MetadataResponse) GetCompilation() bool { - if x != nil && x.Compilation != nil { - return *x.Compilation - } - return false -} - -func (x *MetadataResponse) GetArtistSort() string { - if x != nil && x.ArtistSort != nil { - return *x.ArtistSort - } - return "" -} - -func (x *MetadataResponse) GetAlbumArtistSort() string { - if x != nil && x.AlbumArtistSort != nil { - return *x.AlbumArtistSort - } - return "" -} - -func (x *MetadataResponse) GetAlbumSort() string { - if x != nil && x.AlbumSort != nil { - return *x.AlbumSort - } - return "" -} - -func (x *MetadataResponse) GetTitleSort() string { - if x != nil && x.TitleSort != nil { - return *x.TitleSort - } - return "" -} - -func (x *MetadataResponse) GetMbRecordingId() string { - if x != nil && x.MbRecordingId != nil { - return *x.MbRecordingId - } - return "" -} - -func (x *MetadataResponse) GetMbAlbumId() string { - if x != nil && x.MbAlbumId != nil { - return *x.MbAlbumId - } - return "" -} - -func (x *MetadataResponse) GetMbArtistId() string { - if x != nil && x.MbArtistId != nil { - return *x.MbArtistId - } - return "" -} - -func (x *MetadataResponse) GetMbAlbumArtistId() string { - if x != nil && x.MbAlbumArtistId != nil { - return *x.MbAlbumArtistId - } - return "" -} - -func (x *MetadataResponse) GetMbReleaseGroupId() string { - if x != nil && x.MbReleaseGroupId != nil { - return *x.MbReleaseGroupId - } - return "" -} - -func (x *MetadataResponse) GetReplaygainTrackGain() float32 { - if x != nil && x.ReplaygainTrackGain != nil { - return *x.ReplaygainTrackGain - } - return 0 -} - -func (x *MetadataResponse) GetReplaygainTrackPeak() float32 { - if x != nil && x.ReplaygainTrackPeak != nil { - return *x.ReplaygainTrackPeak - } - return 0 -} - -func (x *MetadataResponse) GetReplaygainAlbumGain() float32 { - if x != nil && x.ReplaygainAlbumGain != nil { - return *x.ReplaygainAlbumGain - } - return 0 -} - -func (x *MetadataResponse) GetReplaygainAlbumPeak() float32 { - if x != nil && x.ReplaygainAlbumPeak != nil { - return *x.ReplaygainAlbumPeak - } - return 0 -} - -func (x *MetadataResponse) GetChannels() uint32 { - if x != nil && x.Channels != nil { - return *x.Channels - } - return 0 -} - -func (x *MetadataResponse) GetBitsPerSample() uint32 { - if x != nil && x.BitsPerSample != nil { - return *x.BitsPerSample - } - return 0 -} - -func (x *MetadataResponse) GetEncoder() string { - if x != nil && x.Encoder != nil { - return *x.Encoder - } - return "" -} - -func (x *MetadataResponse) GetLabel() string { - if x != nil && x.Label != nil { - return *x.Label - } - return "" -} - -func (x *MetadataResponse) GetAlbumType() string { - if x != nil && x.AlbumType != nil { - return *x.AlbumType - } - return "" -} - -func (x *MetadataResponse) GetCoverUrl() string { - if x != nil && x.CoverUrl != nil { - return *x.CoverUrl - } - return "" -} - -func (x *MetadataResponse) GetCustomTags() map[string]string { - if x != nil { - return x.CustomTags - } - return nil -} - -type UpdateMetadataRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Title *string `protobuf:"bytes,2,opt,name=title,proto3,oneof" json:"title,omitempty"` - Artist *string `protobuf:"bytes,3,opt,name=artist,proto3,oneof" json:"artist,omitempty"` - Album *string `protobuf:"bytes,4,opt,name=album,proto3,oneof" json:"album,omitempty"` - AlbumArtist *string `protobuf:"bytes,5,opt,name=album_artist,json=albumArtist,proto3,oneof" json:"album_artist,omitempty"` - TrackNumber *uint32 `protobuf:"varint,6,opt,name=track_number,json=trackNumber,proto3,oneof" json:"track_number,omitempty"` - DiscNumber *uint32 `protobuf:"varint,7,opt,name=disc_number,json=discNumber,proto3,oneof" json:"disc_number,omitempty"` - Date *string `protobuf:"bytes,8,opt,name=date,proto3,oneof" json:"date,omitempty"` - Genre *string `protobuf:"bytes,9,opt,name=genre,proto3,oneof" json:"genre,omitempty"` - Composer *string `protobuf:"bytes,10,opt,name=composer,proto3,oneof" json:"composer,omitempty"` - Comment *string `protobuf:"bytes,11,opt,name=comment,proto3,oneof" json:"comment,omitempty"` - Lyrics *string `protobuf:"bytes,12,opt,name=lyrics,proto3,oneof" json:"lyrics,omitempty"` - Copyright *string `protobuf:"bytes,13,opt,name=copyright,proto3,oneof" json:"copyright,omitempty"` - Compilation *bool `protobuf:"varint,14,opt,name=compilation,proto3,oneof" json:"compilation,omitempty"` - ArtistSort *string `protobuf:"bytes,15,opt,name=artist_sort,json=artistSort,proto3,oneof" json:"artist_sort,omitempty"` - AlbumArtistSort *string `protobuf:"bytes,16,opt,name=album_artist_sort,json=albumArtistSort,proto3,oneof" json:"album_artist_sort,omitempty"` - AlbumSort *string `protobuf:"bytes,17,opt,name=album_sort,json=albumSort,proto3,oneof" json:"album_sort,omitempty"` - TitleSort *string `protobuf:"bytes,18,opt,name=title_sort,json=titleSort,proto3,oneof" json:"title_sort,omitempty"` - MbRecordingId *string `protobuf:"bytes,20,opt,name=mb_recording_id,json=mbRecordingId,proto3,oneof" json:"mb_recording_id,omitempty"` - MbAlbumId *string `protobuf:"bytes,21,opt,name=mb_album_id,json=mbAlbumId,proto3,oneof" json:"mb_album_id,omitempty"` - MbArtistId *string `protobuf:"bytes,22,opt,name=mb_artist_id,json=mbArtistId,proto3,oneof" json:"mb_artist_id,omitempty"` - ReplaygainTrackGain *float32 `protobuf:"fixed32,30,opt,name=replaygain_track_gain,json=replaygainTrackGain,proto3,oneof" json:"replaygain_track_gain,omitempty"` - ReplaygainTrackPeak *float32 `protobuf:"fixed32,31,opt,name=replaygain_track_peak,json=replaygainTrackPeak,proto3,oneof" json:"replaygain_track_peak,omitempty"` - ReplaygainAlbumGain *float32 `protobuf:"fixed32,32,opt,name=replaygain_album_gain,json=replaygainAlbumGain,proto3,oneof" json:"replaygain_album_gain,omitempty"` - ReplaygainAlbumPeak *float32 `protobuf:"fixed32,33,opt,name=replaygain_album_peak,json=replaygainAlbumPeak,proto3,oneof" json:"replaygain_album_peak,omitempty"` - Label *string `protobuf:"bytes,40,opt,name=label,proto3,oneof" json:"label,omitempty"` - AlbumType *string `protobuf:"bytes,41,opt,name=album_type,json=albumType,proto3,oneof" json:"album_type,omitempty"` - CoverUrl *string `protobuf:"bytes,42,opt,name=cover_url,json=coverUrl,proto3,oneof" json:"cover_url,omitempty"` - CustomTags map[string]string `protobuf:"bytes,50,rep,name=custom_tags,json=customTags,proto3" json:"custom_tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *UpdateMetadataRequest) Reset() { - *x = UpdateMetadataRequest{} - mi := &file_musicfs_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *UpdateMetadataRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateMetadataRequest) ProtoMessage() {} - -func (x *UpdateMetadataRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[23] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateMetadataRequest.ProtoReflect.Descriptor instead. -func (*UpdateMetadataRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{23} -} - -func (x *UpdateMetadataRequest) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *UpdateMetadataRequest) GetTitle() string { - if x != nil && x.Title != nil { - return *x.Title - } - return "" -} - -func (x *UpdateMetadataRequest) GetArtist() string { - if x != nil && x.Artist != nil { - return *x.Artist - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbum() string { - if x != nil && x.Album != nil { - return *x.Album - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbumArtist() string { - if x != nil && x.AlbumArtist != nil { - return *x.AlbumArtist - } - return "" -} - -func (x *UpdateMetadataRequest) GetTrackNumber() uint32 { - if x != nil && x.TrackNumber != nil { - return *x.TrackNumber - } - return 0 -} - -func (x *UpdateMetadataRequest) GetDiscNumber() uint32 { - if x != nil && x.DiscNumber != nil { - return *x.DiscNumber - } - return 0 -} - -func (x *UpdateMetadataRequest) GetDate() string { - if x != nil && x.Date != nil { - return *x.Date - } - return "" -} - -func (x *UpdateMetadataRequest) GetGenre() string { - if x != nil && x.Genre != nil { - return *x.Genre - } - return "" -} - -func (x *UpdateMetadataRequest) GetComposer() string { - if x != nil && x.Composer != nil { - return *x.Composer - } - return "" -} - -func (x *UpdateMetadataRequest) GetComment() string { - if x != nil && x.Comment != nil { - return *x.Comment - } - return "" -} - -func (x *UpdateMetadataRequest) GetLyrics() string { - if x != nil && x.Lyrics != nil { - return *x.Lyrics - } - return "" -} - -func (x *UpdateMetadataRequest) GetCopyright() string { - if x != nil && x.Copyright != nil { - return *x.Copyright - } - return "" -} - -func (x *UpdateMetadataRequest) GetCompilation() bool { - if x != nil && x.Compilation != nil { - return *x.Compilation - } - return false -} - -func (x *UpdateMetadataRequest) GetArtistSort() string { - if x != nil && x.ArtistSort != nil { - return *x.ArtistSort - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbumArtistSort() string { - if x != nil && x.AlbumArtistSort != nil { - return *x.AlbumArtistSort - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbumSort() string { - if x != nil && x.AlbumSort != nil { - return *x.AlbumSort - } - return "" -} - -func (x *UpdateMetadataRequest) GetTitleSort() string { - if x != nil && x.TitleSort != nil { - return *x.TitleSort - } - return "" -} - -func (x *UpdateMetadataRequest) GetMbRecordingId() string { - if x != nil && x.MbRecordingId != nil { - return *x.MbRecordingId - } - return "" -} - -func (x *UpdateMetadataRequest) GetMbAlbumId() string { - if x != nil && x.MbAlbumId != nil { - return *x.MbAlbumId - } - return "" -} - -func (x *UpdateMetadataRequest) GetMbArtistId() string { - if x != nil && x.MbArtistId != nil { - return *x.MbArtistId - } - return "" -} - -func (x *UpdateMetadataRequest) GetReplaygainTrackGain() float32 { - if x != nil && x.ReplaygainTrackGain != nil { - return *x.ReplaygainTrackGain - } - return 0 -} - -func (x *UpdateMetadataRequest) GetReplaygainTrackPeak() float32 { - if x != nil && x.ReplaygainTrackPeak != nil { - return *x.ReplaygainTrackPeak - } - return 0 -} - -func (x *UpdateMetadataRequest) GetReplaygainAlbumGain() float32 { - if x != nil && x.ReplaygainAlbumGain != nil { - return *x.ReplaygainAlbumGain - } - return 0 -} - -func (x *UpdateMetadataRequest) GetReplaygainAlbumPeak() float32 { - if x != nil && x.ReplaygainAlbumPeak != nil { - return *x.ReplaygainAlbumPeak - } - return 0 -} - -func (x *UpdateMetadataRequest) GetLabel() string { - if x != nil && x.Label != nil { - return *x.Label - } - return "" -} - -func (x *UpdateMetadataRequest) GetAlbumType() string { - if x != nil && x.AlbumType != nil { - return *x.AlbumType - } - return "" -} - -func (x *UpdateMetadataRequest) GetCoverUrl() string { - if x != nil && x.CoverUrl != nil { - return *x.CoverUrl - } - return "" -} - -func (x *UpdateMetadataRequest) GetCustomTags() map[string]string { - if x != nil { - return x.CustomTags - } - return nil -} - -type UpdateMetadataResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` - ErrorMessage *string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *UpdateMetadataResponse) Reset() { - *x = UpdateMetadataResponse{} - mi := &file_musicfs_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *UpdateMetadataResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateMetadataResponse) ProtoMessage() {} - -func (x *UpdateMetadataResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[24] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateMetadataResponse.ProtoReflect.Descriptor instead. -func (*UpdateMetadataResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{24} -} - -func (x *UpdateMetadataResponse) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *UpdateMetadataResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *UpdateMetadataResponse) GetErrorMessage() string { - if x != nil && x.ErrorMessage != nil { - return *x.ErrorMessage - } - return "" -} - -type ClearOverlayRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ClearOverlayRequest) Reset() { - *x = ClearOverlayRequest{} - mi := &file_musicfs_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ClearOverlayRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ClearOverlayRequest) ProtoMessage() {} - -func (x *ClearOverlayRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[25] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ClearOverlayRequest.ProtoReflect.Descriptor instead. -func (*ClearOverlayRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{25} -} - -func (x *ClearOverlayRequest) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -type ClearOverlayResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` - ErrorMessage *string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ClearOverlayResponse) Reset() { - *x = ClearOverlayResponse{} - mi := &file_musicfs_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ClearOverlayResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ClearOverlayResponse) ProtoMessage() {} - -func (x *ClearOverlayResponse) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[26] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ClearOverlayResponse.ProtoReflect.Descriptor instead. -func (*ClearOverlayResponse) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{26} -} - -func (x *ClearOverlayResponse) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *ClearOverlayResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *ClearOverlayResponse) GetErrorMessage() string { - if x != nil && x.ErrorMessage != nil { - return *x.ErrorMessage - } - return "" -} - -type BatchUpdateRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Items []*BatchUpdateItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BatchUpdateRequest) Reset() { - *x = BatchUpdateRequest{} - mi := &file_musicfs_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BatchUpdateRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BatchUpdateRequest) ProtoMessage() {} - -func (x *BatchUpdateRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[27] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BatchUpdateRequest.ProtoReflect.Descriptor instead. -func (*BatchUpdateRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{27} -} - -func (x *BatchUpdateRequest) GetItems() []*BatchUpdateItem { - if x != nil { - return x.Items - } - return nil -} - -type BatchUpdateItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` - Metadata *UpdateMetadataRequest `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BatchUpdateItem) Reset() { - *x = BatchUpdateItem{} - mi := &file_musicfs_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BatchUpdateItem) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BatchUpdateItem) ProtoMessage() {} - -func (x *BatchUpdateItem) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[28] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BatchUpdateItem.ProtoReflect.Descriptor instead. -func (*BatchUpdateItem) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{28} -} - -func (x *BatchUpdateItem) GetFileId() int64 { - if x != nil { - return x.FileId - } - return 0 -} - -func (x *BatchUpdateItem) GetMetadata() *UpdateMetadataRequest { - if x != nil { - return x.Metadata - } - return nil -} - -type BatchUpdateProgress struct { - state protoimpl.MessageState `protogen:"open.v1"` - Completed uint32 `protobuf:"varint,1,opt,name=completed,proto3" json:"completed,omitempty"` - Total uint32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - CurrentFileId *int64 `protobuf:"varint,3,opt,name=current_file_id,json=currentFileId,proto3,oneof" json:"current_file_id,omitempty"` - ErrorMessage *string `protobuf:"bytes,4,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BatchUpdateProgress) Reset() { - *x = BatchUpdateProgress{} - mi := &file_musicfs_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BatchUpdateProgress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BatchUpdateProgress) ProtoMessage() {} - -func (x *BatchUpdateProgress) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[29] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BatchUpdateProgress.ProtoReflect.Descriptor instead. -func (*BatchUpdateProgress) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{29} -} - -func (x *BatchUpdateProgress) GetCompleted() uint32 { - if x != nil { - return x.Completed - } - return 0 -} - -func (x *BatchUpdateProgress) GetTotal() uint32 { - if x != nil { - return x.Total - } - return 0 -} - -func (x *BatchUpdateProgress) GetCurrentFileId() int64 { - if x != nil && x.CurrentFileId != nil { - return *x.CurrentFileId - } - return 0 -} - -func (x *BatchUpdateProgress) GetErrorMessage() string { - if x != nil && x.ErrorMessage != nil { - return *x.ErrorMessage - } - return "" -} - -type ImportMetadataRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - SourcePath string `protobuf:"bytes,1,opt,name=source_path,json=sourcePath,proto3" json:"source_path,omitempty"` - Format *string `protobuf:"bytes,2,opt,name=format,proto3,oneof" json:"format,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ImportMetadataRequest) Reset() { - *x = ImportMetadataRequest{} - mi := &file_musicfs_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ImportMetadataRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ImportMetadataRequest) ProtoMessage() {} - -func (x *ImportMetadataRequest) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[30] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ImportMetadataRequest.ProtoReflect.Descriptor instead. -func (*ImportMetadataRequest) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{30} -} - -func (x *ImportMetadataRequest) GetSourcePath() string { - if x != nil { - return x.SourcePath - } - return "" -} - -func (x *ImportMetadataRequest) GetFormat() string { - if x != nil && x.Format != nil { - return *x.Format - } - return "" -} - -type ImportProgress struct { - state protoimpl.MessageState `protogen:"open.v1"` - Imported uint32 `protobuf:"varint,1,opt,name=imported,proto3" json:"imported,omitempty"` - Total uint32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - CurrentFile *string `protobuf:"bytes,3,opt,name=current_file,json=currentFile,proto3,oneof" json:"current_file,omitempty"` - ErrorMessage *string `protobuf:"bytes,4,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ImportProgress) Reset() { - *x = ImportProgress{} - mi := &file_musicfs_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ImportProgress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ImportProgress) ProtoMessage() {} - -func (x *ImportProgress) ProtoReflect() protoreflect.Message { - mi := &file_musicfs_proto_msgTypes[31] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ImportProgress.ProtoReflect.Descriptor instead. -func (*ImportProgress) Descriptor() ([]byte, []int) { - return file_musicfs_proto_rawDescGZIP(), []int{31} -} - -func (x *ImportProgress) GetImported() uint32 { - if x != nil { - return x.Imported - } - return 0 -} - -func (x *ImportProgress) GetTotal() uint32 { - if x != nil { - return x.Total - } - return 0 -} - -func (x *ImportProgress) GetCurrentFile() string { - if x != nil && x.CurrentFile != nil { - return *x.CurrentFile - } - return "" -} - -func (x *ImportProgress) GetErrorMessage() string { - if x != nil && x.ErrorMessage != nil { - return *x.ErrorMessage - } - return "" -} - -var File_musicfs_proto protoreflect.FileDescriptor - -const file_musicfs_proto_rawDesc = "" + - "\n" + - "\rmusicfs.proto\x12\n" + - "musicfs.v1\"\a\n" + - "\x05Empty\"\xa2\x01\n" + - "\rSearchRequest\x12\x14\n" + - "\x05query\x18\x01 \x01(\tR\x05query\x12\x19\n" + - "\x05limit\x18\x02 \x01(\rH\x00R\x05limit\x88\x01\x01\x12\x1b\n" + - "\x06offset\x18\x03 \x01(\rH\x01R\x06offset\x88\x01\x01\x12 \n" + - "\torigin_id\x18\x04 \x01(\tH\x02R\boriginId\x88\x01\x01B\b\n" + - "\x06_limitB\t\n" + - "\a_offsetB\f\n" + - "\n" + - "_origin_id\"\x8d\x01\n" + - "\x0eSearchResponse\x122\n" + - "\aresults\x18\x01 \x03(\v2\x18.musicfs.v1.SearchResultR\aresults\x12#\n" + - "\rtotal_matches\x18\x02 \x01(\x04R\ftotalMatches\x12\"\n" + - "\rquery_time_ms\x18\x03 \x01(\rR\vqueryTimeMs\"\xdb\x02\n" + - "\fSearchResult\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12!\n" + - "\fvirtual_path\x18\x02 \x01(\tR\vvirtualPath\x12\x1b\n" + - "\x06artist\x18\x03 \x01(\tH\x00R\x06artist\x88\x01\x01\x12\x19\n" + - "\x05album\x18\x04 \x01(\tH\x01R\x05album\x88\x01\x01\x12\x19\n" + - "\x05title\x18\x05 \x01(\tH\x02R\x05title\x88\x01\x01\x12\x14\n" + - "\x05score\x18\x06 \x01(\x02R\x05score\x12H\n" + - "\n" + - "highlights\x18\a \x03(\v2(.musicfs.v1.SearchResult.HighlightsEntryR\n" + - "highlights\x1a=\n" + - "\x0fHighlightsEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\t\n" + - "\a_artistB\b\n" + - "\x06_albumB\b\n" + - "\x06_title\"\xef\x02\n" + - "\x0eStatusResponse\x12\x18\n" + - "\aversion\x18\x01 \x01(\tR\aversion\x12\x1f\n" + - "\vuptime_secs\x18\x02 \x01(\x04R\n" + - "uptimeSecs\x12\x1f\n" + - "\vmount_point\x18\x03 \x01(\tR\n" + - "mountPoint\x12,\n" + - "\x05state\x18\x04 \x01(\x0e2\x16.musicfs.v1.MountStateR\x05state\x12*\n" + - "\x11open_file_handles\x18\x05 \x01(\rR\x0fopenFileHandles\x12$\n" + - "\x0efuse_ops_total\x18\x06 \x01(\x04R\ffuseOpsTotal\x12#\n" + - "\rfiles_indexed\x18\a \x01(\x04R\ffilesIndexed\x12(\n" + - "\x10cache_size_bytes\x18\b \x01(\x04R\x0ecacheSizeBytes\x122\n" + - "\aorigins\x18\t \x03(\v2\x18.musicfs.v1.OriginStatusR\aorigins\"\x92\x01\n" + - "\fOriginStatus\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + - "\vorigin_type\x18\x02 \x01(\tR\n" + - "originType\x120\n" + - "\x06health\x18\x03 \x01(\x0e2\x18.musicfs.v1.HealthStatusR\x06health\x12\x1f\n" + - "\vfiles_count\x18\x04 \x01(\x04R\n" + - "filesCount\"P\n" + - "\x0fShutdownRequest\x12\x1a\n" + - "\bgraceful\x18\x01 \x01(\bR\bgraceful\x12!\n" + - "\ftimeout_secs\x18\x02 \x01(\rR\vtimeoutSecs\"p\n" + - "\tTierStats\x12\x18\n" + - "\aentries\x18\x01 \x01(\x04R\aentries\x12\x1d\n" + - "\n" + - "size_bytes\x18\x02 \x01(\x04R\tsizeBytes\x12\x12\n" + - "\x04hits\x18\x03 \x01(\x04R\x04hits\x12\x16\n" + - "\x06misses\x18\x04 \x01(\x04R\x06misses\"\xbc\x04\n" + - "\n" + - "CacheStats\x12(\n" + - "\x10total_size_bytes\x18\x01 \x01(\x04R\x0etotalSizeBytes\x12&\n" + - "\x0fused_size_bytes\x18\x02 \x01(\x04R\rusedSizeBytes\x12(\n" + - "\x10size_limit_bytes\x18\x03 \x01(\x04R\x0esizeLimitBytes\x12\x1f\n" + - "\vchunk_count\x18\x04 \x01(\x04R\n" + - "chunkCount\x12#\n" + - "\rchunks_unique\x18\x05 \x01(\x04R\fchunksUnique\x12\x1f\n" + - "\vdedup_ratio\x18\x06 \x01(\x01R\n" + - "dedupRatio\x12\x1b\n" + - "\thit_count\x18\a \x01(\x04R\bhitCount\x12\x1d\n" + - "\n" + - "miss_count\x18\b \x01(\x04R\tmissCount\x12\x1b\n" + - "\thit_ratio\x18\t \x01(\x01R\bhitRatio\x12)\n" + - "\x10metadata_entries\x18\n" + - " \x01(\x04R\x0fmetadataEntries\x12%\n" + - "\x0emetadata_bytes\x18\v \x01(\x04R\rmetadataBytes\x126\n" + - "\vl1_metadata\x18\f \x01(\v2\x15.musicfs.v1.TierStatsR\n" + - "l1Metadata\x124\n" + - "\n" + - "l2_headers\x18\r \x01(\v2\x15.musicfs.v1.TierStatsR\tl2Headers\x122\n" + - "\tl3_chunks\x18\x0e \x01(\v2\x15.musicfs.v1.TierStatsR\bl3Chunks\"\x8d\x01\n" + - "\x11ClearCacheRequest\x12 \n" + - "\torigin_id\x18\x01 \x01(\tH\x00R\boriginId\x88\x01\x01\x12%\n" + - "\x0eclear_metadata\x18\x02 \x01(\bR\rclearMetadata\x12!\n" + - "\fclear_chunks\x18\x03 \x01(\bR\vclearChunksB\f\n" + - "\n" + - "_origin_id\"`\n" + - "\x12ClearCacheResponse\x12#\n" + - "\rbytes_cleared\x18\x01 \x01(\x04R\fbytesCleared\x12%\n" + - "\x0echunks_cleared\x18\x02 \x01(\x04R\rchunksCleared\"W\n" + - "\x0fPrefetchRequest\x12\x14\n" + - "\x05paths\x18\x01 \x03(\tR\x05paths\x12 \n" + - "\torigin_id\x18\x02 \x01(\tH\x00R\boriginId\x88\x01\x01B\f\n" + - "\n" + - "_origin_id\"\x8e\x01\n" + - "\x10PrefetchProgress\x12!\n" + - "\fcurrent_path\x18\x01 \x01(\tR\vcurrentPath\x12\x1c\n" + - "\tcompleted\x18\x02 \x01(\rR\tcompleted\x12\x14\n" + - "\x05total\x18\x03 \x01(\rR\x05total\x12#\n" + - "\rbytes_fetched\x18\x04 \x01(\x04R\fbytesFetched\"C\n" + - "\x0fOriginsResponse\x120\n" + - "\aorigins\x18\x01 \x03(\v2\x16.musicfs.v1.OriginInfoR\aorigins\"\xfa\x01\n" + - "\n" + - "OriginInfo\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + - "\vorigin_type\x18\x02 \x01(\tR\n" + - "originType\x12!\n" + - "\fdisplay_name\x18\x03 \x01(\tR\vdisplayName\x12\x1b\n" + - "\troot_path\x18\x04 \x01(\tR\brootPath\x120\n" + - "\x06health\x18\x05 \x01(\x0e2\x18.musicfs.v1.HealthStatusR\x06health\x12\x1f\n" + - "\vfiles_count\x18\x06 \x01(\x04R\n" + - "filesCount\x12(\n" + - "\x10total_size_bytes\x18\a \x01(\x04R\x0etotalSizeBytes\"T\n" + - "\rOriginRequest\x12\x1b\n" + - "\torigin_id\x18\x01 \x01(\tR\boriginId\x12\x1b\n" + - "\x06subdir\x18\x02 \x01(\tH\x00R\x06subdir\x88\x01\x01B\t\n" + - "\a_subdir\"\xb8\x01\n" + - "\x14OriginHealthResponse\x12\x1b\n" + - "\torigin_id\x18\x01 \x01(\tR\boriginId\x120\n" + - "\x06status\x18\x02 \x01(\x0e2\x18.musicfs.v1.HealthStatusR\x06status\x12\x1d\n" + - "\amessage\x18\x03 \x01(\tH\x00R\amessage\x88\x01\x01\x12&\n" + - "\x0flast_check_secs\x18\x04 \x01(\x04R\rlastCheckSecsB\n" + - "\n" + - "\b_message\"\xcf\x01\n" + - "\fSyncProgress\x12\x14\n" + - "\x05phase\x18\x01 \x01(\tR\x05phase\x12\x18\n" + - "\acurrent\x18\x02 \x01(\rR\acurrent\x12\x14\n" + - "\x05total\x18\x03 \x01(\rR\x05total\x12!\n" + - "\fcurrent_path\x18\x04 \x01(\tR\vcurrentPath\x12!\n" + - "\fbytes_synced\x18\x05 \x01(\x04R\vbytesSynced\x123\n" + - "\tnew_files\x18\x06 \x03(\v2\x16.musicfs.v1.SyncedFileR\bnewFiles\"\\\n" + - "\n" + - "SyncedFile\x12\x12\n" + - "\x04path\x18\x01 \x01(\tR\x04path\x12\x17\n" + - "\afile_id\x18\x02 \x01(\x03R\x06fileId\x12!\n" + - "\fvirtual_path\x18\x03 \x01(\tR\vvirtualPath\"^\n" + - "\vEventFilter\x12\x1f\n" + - "\vevent_types\x18\x01 \x03(\tR\n" + - "eventTypes\x12 \n" + - "\torigin_id\x18\x02 \x01(\tH\x00R\boriginId\x88\x01\x01B\f\n" + - "\n" + - "_origin_id\"\xbf\x02\n" + - "\x05Event\x12\x1d\n" + - "\n" + - "event_type\x18\x01 \x01(\tR\teventType\x12!\n" + - "\ftimestamp_ms\x18\x02 \x01(\x03R\vtimestampMs\x12 \n" + - "\torigin_id\x18\x03 \x01(\tH\x00R\boriginId\x88\x01\x01\x12\x17\n" + - "\x04path\x18\x04 \x01(\tH\x01R\x04path\x88\x01\x01\x12\x1c\n" + - "\afile_id\x18\x05 \x01(\x03H\x02R\x06fileId\x88\x01\x01\x12;\n" + - "\bmetadata\x18\x06 \x03(\v2\x1f.musicfs.v1.Event.MetadataEntryR\bmetadata\x1a;\n" + - "\rMetadataEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\f\n" + - "\n" + - "_origin_idB\a\n" + - "\x05_pathB\n" + - "\n" + - "\b_file_id\"7\n" + - "\x12GetMetadataRequest\x12!\n" + - "\fvirtual_path\x18\x01 \x01(\tR\vvirtualPath\"\x83\x11\n" + - "\x10MetadataResponse\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x19\n" + - "\x05title\x18\x02 \x01(\tH\x00R\x05title\x88\x01\x01\x12\x1b\n" + - "\x06artist\x18\x03 \x01(\tH\x01R\x06artist\x88\x01\x01\x12\x19\n" + - "\x05album\x18\x04 \x01(\tH\x02R\x05album\x88\x01\x01\x12&\n" + - "\falbum_artist\x18\x05 \x01(\tH\x03R\valbumArtist\x88\x01\x01\x12\x17\n" + - "\x04year\x18\x06 \x01(\rH\x04R\x04year\x88\x01\x01\x12\x19\n" + - "\x05track\x18\a \x01(\rH\x05R\x05track\x88\x01\x01\x12\x17\n" + - "\x04disc\x18\b \x01(\rH\x06R\x04disc\x88\x01\x01\x12\x19\n" + - "\x05genre\x18\t \x01(\tH\aR\x05genre\x88\x01\x01\x12\x1b\n" + - "\x06format\x18\n" + - " \x01(\tH\bR\x06format\x88\x01\x01\x12$\n" + - "\vduration_ms\x18\v \x01(\x04H\tR\n" + - "durationMs\x88\x01\x01\x12\x1d\n" + - "\abitrate\x18\f \x01(\x04H\n" + - "R\abitrate\x88\x01\x01\x12$\n" + - "\vtrack_total\x18\r \x01(\rH\vR\n" + - "trackTotal\x88\x01\x01\x12\"\n" + - "\n" + - "disc_total\x18\x0e \x01(\rH\fR\tdiscTotal\x88\x01\x01\x12\x17\n" + - "\x04date\x18\x0f \x01(\tH\rR\x04date\x88\x01\x01\x12\x1f\n" + - "\bcomposer\x18\x10 \x01(\tH\x0eR\bcomposer\x88\x01\x01\x12\x1d\n" + - "\acomment\x18\x11 \x01(\tH\x0fR\acomment\x88\x01\x01\x12\x1b\n" + - "\x06lyrics\x18\x12 \x01(\tH\x10R\x06lyrics\x88\x01\x01\x12!\n" + - "\tcopyright\x18\x13 \x01(\tH\x11R\tcopyright\x88\x01\x01\x12%\n" + - "\vcompilation\x18\x14 \x01(\bH\x12R\vcompilation\x88\x01\x01\x12$\n" + - "\vartist_sort\x18\x15 \x01(\tH\x13R\n" + - "artistSort\x88\x01\x01\x12/\n" + - "\x11album_artist_sort\x18\x16 \x01(\tH\x14R\x0falbumArtistSort\x88\x01\x01\x12\"\n" + - "\n" + - "album_sort\x18\x17 \x01(\tH\x15R\talbumSort\x88\x01\x01\x12\"\n" + - "\n" + - "title_sort\x18\x18 \x01(\tH\x16R\ttitleSort\x88\x01\x01\x12+\n" + - "\x0fmb_recording_id\x18\x19 \x01(\tH\x17R\rmbRecordingId\x88\x01\x01\x12#\n" + - "\vmb_album_id\x18\x1a \x01(\tH\x18R\tmbAlbumId\x88\x01\x01\x12%\n" + - "\fmb_artist_id\x18\x1b \x01(\tH\x19R\n" + - "mbArtistId\x88\x01\x01\x120\n" + - "\x12mb_album_artist_id\x18\x1c \x01(\tH\x1aR\x0fmbAlbumArtistId\x88\x01\x01\x122\n" + - "\x13mb_release_group_id\x18\x1d \x01(\tH\x1bR\x10mbReleaseGroupId\x88\x01\x01\x127\n" + - "\x15replaygain_track_gain\x18\x1e \x01(\x02H\x1cR\x13replaygainTrackGain\x88\x01\x01\x127\n" + - "\x15replaygain_track_peak\x18\x1f \x01(\x02H\x1dR\x13replaygainTrackPeak\x88\x01\x01\x127\n" + - "\x15replaygain_album_gain\x18 \x01(\x02H\x1eR\x13replaygainAlbumGain\x88\x01\x01\x127\n" + - "\x15replaygain_album_peak\x18! \x01(\x02H\x1fR\x13replaygainAlbumPeak\x88\x01\x01\x12\x1f\n" + - "\bchannels\x18\" \x01(\rH R\bchannels\x88\x01\x01\x12+\n" + - "\x0fbits_per_sample\x18# \x01(\rH!R\rbitsPerSample\x88\x01\x01\x12\x1d\n" + - "\aencoder\x18$ \x01(\tH\"R\aencoder\x88\x01\x01\x12\x19\n" + - "\x05label\x18( \x01(\tH#R\x05label\x88\x01\x01\x12\"\n" + - "\n" + - "album_type\x18) \x01(\tH$R\talbumType\x88\x01\x01\x12 \n" + - "\tcover_url\x18* \x01(\tH%R\bcoverUrl\x88\x01\x01\x12M\n" + - "\vcustom_tags\x182 \x03(\v2,.musicfs.v1.MetadataResponse.CustomTagsEntryR\n" + - "customTags\x1a=\n" + - "\x0fCustomTagsEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\b\n" + - "\x06_titleB\t\n" + - "\a_artistB\b\n" + - "\x06_albumB\x0f\n" + - "\r_album_artistB\a\n" + - "\x05_yearB\b\n" + - "\x06_trackB\a\n" + - "\x05_discB\b\n" + - "\x06_genreB\t\n" + - "\a_formatB\x0e\n" + - "\f_duration_msB\n" + - "\n" + - "\b_bitrateB\x0e\n" + - "\f_track_totalB\r\n" + - "\v_disc_totalB\a\n" + - "\x05_dateB\v\n" + - "\t_composerB\n" + - "\n" + - "\b_commentB\t\n" + - "\a_lyricsB\f\n" + - "\n" + - "_copyrightB\x0e\n" + - "\f_compilationB\x0e\n" + - "\f_artist_sortB\x14\n" + - "\x12_album_artist_sortB\r\n" + - "\v_album_sortB\r\n" + - "\v_title_sortB\x12\n" + - "\x10_mb_recording_idB\x0e\n" + - "\f_mb_album_idB\x0f\n" + - "\r_mb_artist_idB\x15\n" + - "\x13_mb_album_artist_idB\x16\n" + - "\x14_mb_release_group_idB\x18\n" + - "\x16_replaygain_track_gainB\x18\n" + - "\x16_replaygain_track_peakB\x18\n" + - "\x16_replaygain_album_gainB\x18\n" + - "\x16_replaygain_album_peakB\v\n" + - "\t_channelsB\x12\n" + - "\x10_bits_per_sampleB\n" + - "\n" + - "\b_encoderB\b\n" + - "\x06_labelB\r\n" + - "\v_album_typeB\f\n" + - "\n" + - "_cover_url\"\xf2\f\n" + - "\x15UpdateMetadataRequest\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x19\n" + - "\x05title\x18\x02 \x01(\tH\x00R\x05title\x88\x01\x01\x12\x1b\n" + - "\x06artist\x18\x03 \x01(\tH\x01R\x06artist\x88\x01\x01\x12\x19\n" + - "\x05album\x18\x04 \x01(\tH\x02R\x05album\x88\x01\x01\x12&\n" + - "\falbum_artist\x18\x05 \x01(\tH\x03R\valbumArtist\x88\x01\x01\x12&\n" + - "\ftrack_number\x18\x06 \x01(\rH\x04R\vtrackNumber\x88\x01\x01\x12$\n" + - "\vdisc_number\x18\a \x01(\rH\x05R\n" + - "discNumber\x88\x01\x01\x12\x17\n" + - "\x04date\x18\b \x01(\tH\x06R\x04date\x88\x01\x01\x12\x19\n" + - "\x05genre\x18\t \x01(\tH\aR\x05genre\x88\x01\x01\x12\x1f\n" + - "\bcomposer\x18\n" + - " \x01(\tH\bR\bcomposer\x88\x01\x01\x12\x1d\n" + - "\acomment\x18\v \x01(\tH\tR\acomment\x88\x01\x01\x12\x1b\n" + - "\x06lyrics\x18\f \x01(\tH\n" + - "R\x06lyrics\x88\x01\x01\x12!\n" + - "\tcopyright\x18\r \x01(\tH\vR\tcopyright\x88\x01\x01\x12%\n" + - "\vcompilation\x18\x0e \x01(\bH\fR\vcompilation\x88\x01\x01\x12$\n" + - "\vartist_sort\x18\x0f \x01(\tH\rR\n" + - "artistSort\x88\x01\x01\x12/\n" + - "\x11album_artist_sort\x18\x10 \x01(\tH\x0eR\x0falbumArtistSort\x88\x01\x01\x12\"\n" + - "\n" + - "album_sort\x18\x11 \x01(\tH\x0fR\talbumSort\x88\x01\x01\x12\"\n" + - "\n" + - "title_sort\x18\x12 \x01(\tH\x10R\ttitleSort\x88\x01\x01\x12+\n" + - "\x0fmb_recording_id\x18\x14 \x01(\tH\x11R\rmbRecordingId\x88\x01\x01\x12#\n" + - "\vmb_album_id\x18\x15 \x01(\tH\x12R\tmbAlbumId\x88\x01\x01\x12%\n" + - "\fmb_artist_id\x18\x16 \x01(\tH\x13R\n" + - "mbArtistId\x88\x01\x01\x127\n" + - "\x15replaygain_track_gain\x18\x1e \x01(\x02H\x14R\x13replaygainTrackGain\x88\x01\x01\x127\n" + - "\x15replaygain_track_peak\x18\x1f \x01(\x02H\x15R\x13replaygainTrackPeak\x88\x01\x01\x127\n" + - "\x15replaygain_album_gain\x18 \x01(\x02H\x16R\x13replaygainAlbumGain\x88\x01\x01\x127\n" + - "\x15replaygain_album_peak\x18! \x01(\x02H\x17R\x13replaygainAlbumPeak\x88\x01\x01\x12\x19\n" + - "\x05label\x18( \x01(\tH\x18R\x05label\x88\x01\x01\x12\"\n" + - "\n" + - "album_type\x18) \x01(\tH\x19R\talbumType\x88\x01\x01\x12 \n" + - "\tcover_url\x18* \x01(\tH\x1aR\bcoverUrl\x88\x01\x01\x12R\n" + - "\vcustom_tags\x182 \x03(\v21.musicfs.v1.UpdateMetadataRequest.CustomTagsEntryR\n" + - "customTags\x1a=\n" + - "\x0fCustomTagsEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\b\n" + - "\x06_titleB\t\n" + - "\a_artistB\b\n" + - "\x06_albumB\x0f\n" + - "\r_album_artistB\x0f\n" + - "\r_track_numberB\x0e\n" + - "\f_disc_numberB\a\n" + - "\x05_dateB\b\n" + - "\x06_genreB\v\n" + - "\t_composerB\n" + - "\n" + - "\b_commentB\t\n" + - "\a_lyricsB\f\n" + - "\n" + - "_copyrightB\x0e\n" + - "\f_compilationB\x0e\n" + - "\f_artist_sortB\x14\n" + - "\x12_album_artist_sortB\r\n" + - "\v_album_sortB\r\n" + - "\v_title_sortB\x12\n" + - "\x10_mb_recording_idB\x0e\n" + - "\f_mb_album_idB\x0f\n" + - "\r_mb_artist_idB\x18\n" + - "\x16_replaygain_track_gainB\x18\n" + - "\x16_replaygain_track_peakB\x18\n" + - "\x16_replaygain_album_gainB\x18\n" + - "\x16_replaygain_album_peakB\b\n" + - "\x06_labelB\r\n" + - "\v_album_typeB\f\n" + - "\n" + - "_cover_url\"\x87\x01\n" + - "\x16UpdateMetadataResponse\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x18\n" + - "\asuccess\x18\x02 \x01(\bR\asuccess\x12(\n" + - "\rerror_message\x18\x03 \x01(\tH\x00R\ferrorMessage\x88\x01\x01B\x10\n" + - "\x0e_error_message\".\n" + - "\x13ClearOverlayRequest\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\"\x85\x01\n" + - "\x14ClearOverlayResponse\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x18\n" + - "\asuccess\x18\x02 \x01(\bR\asuccess\x12(\n" + - "\rerror_message\x18\x03 \x01(\tH\x00R\ferrorMessage\x88\x01\x01B\x10\n" + - "\x0e_error_message\"G\n" + - "\x12BatchUpdateRequest\x121\n" + - "\x05items\x18\x01 \x03(\v2\x1b.musicfs.v1.BatchUpdateItemR\x05items\"i\n" + - "\x0fBatchUpdateItem\x12\x17\n" + - "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12=\n" + - "\bmetadata\x18\x02 \x01(\v2!.musicfs.v1.UpdateMetadataRequestR\bmetadata\"\xc6\x01\n" + - "\x13BatchUpdateProgress\x12\x1c\n" + - "\tcompleted\x18\x01 \x01(\rR\tcompleted\x12\x14\n" + - "\x05total\x18\x02 \x01(\rR\x05total\x12+\n" + - "\x0fcurrent_file_id\x18\x03 \x01(\x03H\x00R\rcurrentFileId\x88\x01\x01\x12(\n" + - "\rerror_message\x18\x04 \x01(\tH\x01R\ferrorMessage\x88\x01\x01B\x12\n" + - "\x10_current_file_idB\x10\n" + - "\x0e_error_message\"`\n" + - "\x15ImportMetadataRequest\x12\x1f\n" + - "\vsource_path\x18\x01 \x01(\tR\n" + - "sourcePath\x12\x1b\n" + - "\x06format\x18\x02 \x01(\tH\x00R\x06format\x88\x01\x01B\t\n" + - "\a_format\"\xb7\x01\n" + - "\x0eImportProgress\x12\x1a\n" + - "\bimported\x18\x01 \x01(\rR\bimported\x12\x14\n" + - "\x05total\x18\x02 \x01(\rR\x05total\x12&\n" + - "\fcurrent_file\x18\x03 \x01(\tH\x00R\vcurrentFile\x88\x01\x01\x12(\n" + - "\rerror_message\x18\x04 \x01(\tH\x01R\ferrorMessage\x88\x01\x01B\x0f\n" + - "\r_current_fileB\x10\n" + - "\x0e_error_message*\x81\x01\n" + - "\n" + - "MountState\x12\x11\n" + - "\rMOUNT_UNKNOWN\x10\x00\x12\x12\n" + - "\x0eMOUNT_MOUNTING\x10\x01\x12\x0f\n" + - "\vMOUNT_READY\x10\x02\x12\x11\n" + - "\rMOUNT_SYNCING\x10\x03\x12\x12\n" + - "\x0eMOUNT_DEGRADED\x10\x04\x12\x14\n" + - "\x10MOUNT_UNMOUNTING\x10\x05*a\n" + - "\fHealthStatus\x12\x12\n" + - "\x0eHEALTH_UNKNOWN\x10\x00\x12\x12\n" + - "\x0eHEALTH_HEALTHY\x10\x01\x12\x13\n" + - "\x0fHEALTH_DEGRADED\x10\x02\x12\x14\n" + - "\x10HEALTH_UNHEALTHY\x10\x032\xf2\x05\n" + - "\aMusicFS\x12?\n" + - "\x06Search\x12\x19.musicfs.v1.SearchRequest\x1a\x1a.musicfs.v1.SearchResponse\x12E\n" + - "\fSearchStream\x12\x19.musicfs.v1.SearchRequest\x1a\x18.musicfs.v1.SearchResult0\x01\x12:\n" + - "\tGetStatus\x12\x11.musicfs.v1.Empty\x1a\x1a.musicfs.v1.StatusResponse\x12:\n" + - "\bShutdown\x12\x1b.musicfs.v1.ShutdownRequest\x1a\x11.musicfs.v1.Empty\x12:\n" + - "\rGetCacheStats\x12\x11.musicfs.v1.Empty\x1a\x16.musicfs.v1.CacheStats\x12K\n" + - "\n" + - "ClearCache\x12\x1d.musicfs.v1.ClearCacheRequest\x1a\x1e.musicfs.v1.ClearCacheResponse\x12G\n" + - "\bPrefetch\x12\x1b.musicfs.v1.PrefetchRequest\x1a\x1c.musicfs.v1.PrefetchProgress0\x01\x12=\n" + - "\vListOrigins\x12\x11.musicfs.v1.Empty\x1a\x1b.musicfs.v1.OriginsResponse\x12N\n" + - "\x0fGetOriginHealth\x12\x19.musicfs.v1.OriginRequest\x1a .musicfs.v1.OriginHealthResponse\x12E\n" + - "\fRescanOrigin\x12\x19.musicfs.v1.OriginRequest\x1a\x18.musicfs.v1.SyncProgress0\x01\x12?\n" + - "\x0fSubscribeEvents\x12\x17.musicfs.v1.EventFilter\x1a\x11.musicfs.v1.Event0\x012\xb7\x03\n" + - "\x0fMetadataService\x12K\n" + - "\vGetMetadata\x12\x1e.musicfs.v1.GetMetadataRequest\x1a\x1c.musicfs.v1.MetadataResponse\x12W\n" + - "\x0eUpdateMetadata\x12!.musicfs.v1.UpdateMetadataRequest\x1a\".musicfs.v1.UpdateMetadataResponse\x12Q\n" + - "\fClearOverlay\x12\x1f.musicfs.v1.ClearOverlayRequest\x1a .musicfs.v1.ClearOverlayResponse\x12X\n" + - "\x13BatchUpdateMetadata\x12\x1e.musicfs.v1.BatchUpdateRequest\x1a\x1f.musicfs.v1.BatchUpdateProgress0\x01\x12Q\n" + - "\x0eImportMetadata\x12!.musicfs.v1.ImportMetadataRequest\x1a\x1a.musicfs.v1.ImportProgress0\x01B6Z4homelab.lan/music-agregator/gen/musicfs/v1;musicfsv1b\x06proto3" - -var ( - file_musicfs_proto_rawDescOnce sync.Once - file_musicfs_proto_rawDescData []byte -) - -func file_musicfs_proto_rawDescGZIP() []byte { - file_musicfs_proto_rawDescOnce.Do(func() { - file_musicfs_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_musicfs_proto_rawDesc), len(file_musicfs_proto_rawDesc))) - }) - return file_musicfs_proto_rawDescData -} - -var file_musicfs_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_musicfs_proto_msgTypes = make([]protoimpl.MessageInfo, 36) -var file_musicfs_proto_goTypes = []any{ - (MountState)(0), // 0: musicfs.v1.MountState - (HealthStatus)(0), // 1: musicfs.v1.HealthStatus - (*Empty)(nil), // 2: musicfs.v1.Empty - (*SearchRequest)(nil), // 3: musicfs.v1.SearchRequest - (*SearchResponse)(nil), // 4: musicfs.v1.SearchResponse - (*SearchResult)(nil), // 5: musicfs.v1.SearchResult - (*StatusResponse)(nil), // 6: musicfs.v1.StatusResponse - (*OriginStatus)(nil), // 7: musicfs.v1.OriginStatus - (*ShutdownRequest)(nil), // 8: musicfs.v1.ShutdownRequest - (*TierStats)(nil), // 9: musicfs.v1.TierStats - (*CacheStats)(nil), // 10: musicfs.v1.CacheStats - (*ClearCacheRequest)(nil), // 11: musicfs.v1.ClearCacheRequest - (*ClearCacheResponse)(nil), // 12: musicfs.v1.ClearCacheResponse - (*PrefetchRequest)(nil), // 13: musicfs.v1.PrefetchRequest - (*PrefetchProgress)(nil), // 14: musicfs.v1.PrefetchProgress - (*OriginsResponse)(nil), // 15: musicfs.v1.OriginsResponse - (*OriginInfo)(nil), // 16: musicfs.v1.OriginInfo - (*OriginRequest)(nil), // 17: musicfs.v1.OriginRequest - (*OriginHealthResponse)(nil), // 18: musicfs.v1.OriginHealthResponse - (*SyncProgress)(nil), // 19: musicfs.v1.SyncProgress - (*SyncedFile)(nil), // 20: musicfs.v1.SyncedFile - (*EventFilter)(nil), // 21: musicfs.v1.EventFilter - (*Event)(nil), // 22: musicfs.v1.Event - (*GetMetadataRequest)(nil), // 23: musicfs.v1.GetMetadataRequest - (*MetadataResponse)(nil), // 24: musicfs.v1.MetadataResponse - (*UpdateMetadataRequest)(nil), // 25: musicfs.v1.UpdateMetadataRequest - (*UpdateMetadataResponse)(nil), // 26: musicfs.v1.UpdateMetadataResponse - (*ClearOverlayRequest)(nil), // 27: musicfs.v1.ClearOverlayRequest - (*ClearOverlayResponse)(nil), // 28: musicfs.v1.ClearOverlayResponse - (*BatchUpdateRequest)(nil), // 29: musicfs.v1.BatchUpdateRequest - (*BatchUpdateItem)(nil), // 30: musicfs.v1.BatchUpdateItem - (*BatchUpdateProgress)(nil), // 31: musicfs.v1.BatchUpdateProgress - (*ImportMetadataRequest)(nil), // 32: musicfs.v1.ImportMetadataRequest - (*ImportProgress)(nil), // 33: musicfs.v1.ImportProgress - nil, // 34: musicfs.v1.SearchResult.HighlightsEntry - nil, // 35: musicfs.v1.Event.MetadataEntry - nil, // 36: musicfs.v1.MetadataResponse.CustomTagsEntry - nil, // 37: musicfs.v1.UpdateMetadataRequest.CustomTagsEntry -} -var file_musicfs_proto_depIdxs = []int32{ - 5, // 0: musicfs.v1.SearchResponse.results:type_name -> musicfs.v1.SearchResult - 34, // 1: musicfs.v1.SearchResult.highlights:type_name -> musicfs.v1.SearchResult.HighlightsEntry - 0, // 2: musicfs.v1.StatusResponse.state:type_name -> musicfs.v1.MountState - 7, // 3: musicfs.v1.StatusResponse.origins:type_name -> musicfs.v1.OriginStatus - 1, // 4: musicfs.v1.OriginStatus.health:type_name -> musicfs.v1.HealthStatus - 9, // 5: musicfs.v1.CacheStats.l1_metadata:type_name -> musicfs.v1.TierStats - 9, // 6: musicfs.v1.CacheStats.l2_headers:type_name -> musicfs.v1.TierStats - 9, // 7: musicfs.v1.CacheStats.l3_chunks:type_name -> musicfs.v1.TierStats - 16, // 8: musicfs.v1.OriginsResponse.origins:type_name -> musicfs.v1.OriginInfo - 1, // 9: musicfs.v1.OriginInfo.health:type_name -> musicfs.v1.HealthStatus - 1, // 10: musicfs.v1.OriginHealthResponse.status:type_name -> musicfs.v1.HealthStatus - 20, // 11: musicfs.v1.SyncProgress.new_files:type_name -> musicfs.v1.SyncedFile - 35, // 12: musicfs.v1.Event.metadata:type_name -> musicfs.v1.Event.MetadataEntry - 36, // 13: musicfs.v1.MetadataResponse.custom_tags:type_name -> musicfs.v1.MetadataResponse.CustomTagsEntry - 37, // 14: musicfs.v1.UpdateMetadataRequest.custom_tags:type_name -> musicfs.v1.UpdateMetadataRequest.CustomTagsEntry - 30, // 15: musicfs.v1.BatchUpdateRequest.items:type_name -> musicfs.v1.BatchUpdateItem - 25, // 16: musicfs.v1.BatchUpdateItem.metadata:type_name -> musicfs.v1.UpdateMetadataRequest - 3, // 17: musicfs.v1.MusicFS.Search:input_type -> musicfs.v1.SearchRequest - 3, // 18: musicfs.v1.MusicFS.SearchStream:input_type -> musicfs.v1.SearchRequest - 2, // 19: musicfs.v1.MusicFS.GetStatus:input_type -> musicfs.v1.Empty - 8, // 20: musicfs.v1.MusicFS.Shutdown:input_type -> musicfs.v1.ShutdownRequest - 2, // 21: musicfs.v1.MusicFS.GetCacheStats:input_type -> musicfs.v1.Empty - 11, // 22: musicfs.v1.MusicFS.ClearCache:input_type -> musicfs.v1.ClearCacheRequest - 13, // 23: musicfs.v1.MusicFS.Prefetch:input_type -> musicfs.v1.PrefetchRequest - 2, // 24: musicfs.v1.MusicFS.ListOrigins:input_type -> musicfs.v1.Empty - 17, // 25: musicfs.v1.MusicFS.GetOriginHealth:input_type -> musicfs.v1.OriginRequest - 17, // 26: musicfs.v1.MusicFS.RescanOrigin:input_type -> musicfs.v1.OriginRequest - 21, // 27: musicfs.v1.MusicFS.SubscribeEvents:input_type -> musicfs.v1.EventFilter - 23, // 28: musicfs.v1.MetadataService.GetMetadata:input_type -> musicfs.v1.GetMetadataRequest - 25, // 29: musicfs.v1.MetadataService.UpdateMetadata:input_type -> musicfs.v1.UpdateMetadataRequest - 27, // 30: musicfs.v1.MetadataService.ClearOverlay:input_type -> musicfs.v1.ClearOverlayRequest - 29, // 31: musicfs.v1.MetadataService.BatchUpdateMetadata:input_type -> musicfs.v1.BatchUpdateRequest - 32, // 32: musicfs.v1.MetadataService.ImportMetadata:input_type -> musicfs.v1.ImportMetadataRequest - 4, // 33: musicfs.v1.MusicFS.Search:output_type -> musicfs.v1.SearchResponse - 5, // 34: musicfs.v1.MusicFS.SearchStream:output_type -> musicfs.v1.SearchResult - 6, // 35: musicfs.v1.MusicFS.GetStatus:output_type -> musicfs.v1.StatusResponse - 2, // 36: musicfs.v1.MusicFS.Shutdown:output_type -> musicfs.v1.Empty - 10, // 37: musicfs.v1.MusicFS.GetCacheStats:output_type -> musicfs.v1.CacheStats - 12, // 38: musicfs.v1.MusicFS.ClearCache:output_type -> musicfs.v1.ClearCacheResponse - 14, // 39: musicfs.v1.MusicFS.Prefetch:output_type -> musicfs.v1.PrefetchProgress - 15, // 40: musicfs.v1.MusicFS.ListOrigins:output_type -> musicfs.v1.OriginsResponse - 18, // 41: musicfs.v1.MusicFS.GetOriginHealth:output_type -> musicfs.v1.OriginHealthResponse - 19, // 42: musicfs.v1.MusicFS.RescanOrigin:output_type -> musicfs.v1.SyncProgress - 22, // 43: musicfs.v1.MusicFS.SubscribeEvents:output_type -> musicfs.v1.Event - 24, // 44: musicfs.v1.MetadataService.GetMetadata:output_type -> musicfs.v1.MetadataResponse - 26, // 45: musicfs.v1.MetadataService.UpdateMetadata:output_type -> musicfs.v1.UpdateMetadataResponse - 28, // 46: musicfs.v1.MetadataService.ClearOverlay:output_type -> musicfs.v1.ClearOverlayResponse - 31, // 47: musicfs.v1.MetadataService.BatchUpdateMetadata:output_type -> musicfs.v1.BatchUpdateProgress - 33, // 48: musicfs.v1.MetadataService.ImportMetadata:output_type -> musicfs.v1.ImportProgress - 33, // [33:49] is the sub-list for method output_type - 17, // [17:33] is the sub-list for method input_type - 17, // [17:17] is the sub-list for extension type_name - 17, // [17:17] is the sub-list for extension extendee - 0, // [0:17] is the sub-list for field type_name -} - -func init() { file_musicfs_proto_init() } -func file_musicfs_proto_init() { - if File_musicfs_proto != nil { - return - } - file_musicfs_proto_msgTypes[1].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[3].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[9].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[11].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[15].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[16].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[19].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[20].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[22].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[23].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[24].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[26].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[29].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[30].OneofWrappers = []any{} - file_musicfs_proto_msgTypes[31].OneofWrappers = []any{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_musicfs_proto_rawDesc), len(file_musicfs_proto_rawDesc)), - NumEnums: 2, - NumMessages: 36, - NumExtensions: 0, - NumServices: 2, - }, - GoTypes: file_musicfs_proto_goTypes, - DependencyIndexes: file_musicfs_proto_depIdxs, - EnumInfos: file_musicfs_proto_enumTypes, - MessageInfos: file_musicfs_proto_msgTypes, - }.Build() - File_musicfs_proto = out.File - file_musicfs_proto_goTypes = nil - file_musicfs_proto_depIdxs = nil -} diff --git a/gen/musicfs/v1/musicfs_grpc.pb.go b/gen/musicfs/v1/musicfs_grpc.pb.go deleted file mode 100644 index afaeb8d..0000000 --- a/gen/musicfs/v1/musicfs_grpc.pb.go +++ /dev/null @@ -1,775 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.1 -// - protoc (unknown) -// source: musicfs.proto - -package musicfsv1 - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - MusicFS_Search_FullMethodName = "/musicfs.v1.MusicFS/Search" - MusicFS_SearchStream_FullMethodName = "/musicfs.v1.MusicFS/SearchStream" - MusicFS_GetStatus_FullMethodName = "/musicfs.v1.MusicFS/GetStatus" - MusicFS_Shutdown_FullMethodName = "/musicfs.v1.MusicFS/Shutdown" - MusicFS_GetCacheStats_FullMethodName = "/musicfs.v1.MusicFS/GetCacheStats" - MusicFS_ClearCache_FullMethodName = "/musicfs.v1.MusicFS/ClearCache" - MusicFS_Prefetch_FullMethodName = "/musicfs.v1.MusicFS/Prefetch" - MusicFS_ListOrigins_FullMethodName = "/musicfs.v1.MusicFS/ListOrigins" - MusicFS_GetOriginHealth_FullMethodName = "/musicfs.v1.MusicFS/GetOriginHealth" - MusicFS_RescanOrigin_FullMethodName = "/musicfs.v1.MusicFS/RescanOrigin" - MusicFS_SubscribeEvents_FullMethodName = "/musicfs.v1.MusicFS/SubscribeEvents" -) - -// MusicFSClient is the client API for MusicFS service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type MusicFSClient interface { - Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) - SearchStream(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SearchResult], error) - GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StatusResponse, error) - Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Empty, error) - GetCacheStats(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CacheStats, error) - ClearCache(ctx context.Context, in *ClearCacheRequest, opts ...grpc.CallOption) (*ClearCacheResponse, error) - Prefetch(ctx context.Context, in *PrefetchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrefetchProgress], error) - ListOrigins(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*OriginsResponse, error) - GetOriginHealth(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (*OriginHealthResponse, error) - RescanOrigin(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SyncProgress], error) - SubscribeEvents(ctx context.Context, in *EventFilter, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Event], error) -} - -type musicFSClient struct { - cc grpc.ClientConnInterface -} - -func NewMusicFSClient(cc grpc.ClientConnInterface) MusicFSClient { - return &musicFSClient{cc} -} - -func (c *musicFSClient) Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SearchResponse) - err := c.cc.Invoke(ctx, MusicFS_Search_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) SearchStream(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SearchResult], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[0], MusicFS_SearchStream_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[SearchRequest, SearchResult]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_SearchStreamClient = grpc.ServerStreamingClient[SearchResult] - -func (c *musicFSClient) GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StatusResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(StatusResponse) - err := c.cc.Invoke(ctx, MusicFS_GetStatus_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Empty, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(Empty) - err := c.cc.Invoke(ctx, MusicFS_Shutdown_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) GetCacheStats(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CacheStats, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(CacheStats) - err := c.cc.Invoke(ctx, MusicFS_GetCacheStats_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) ClearCache(ctx context.Context, in *ClearCacheRequest, opts ...grpc.CallOption) (*ClearCacheResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ClearCacheResponse) - err := c.cc.Invoke(ctx, MusicFS_ClearCache_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) Prefetch(ctx context.Context, in *PrefetchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrefetchProgress], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[1], MusicFS_Prefetch_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[PrefetchRequest, PrefetchProgress]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_PrefetchClient = grpc.ServerStreamingClient[PrefetchProgress] - -func (c *musicFSClient) ListOrigins(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*OriginsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(OriginsResponse) - err := c.cc.Invoke(ctx, MusicFS_ListOrigins_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) GetOriginHealth(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (*OriginHealthResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(OriginHealthResponse) - err := c.cc.Invoke(ctx, MusicFS_GetOriginHealth_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) RescanOrigin(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SyncProgress], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[2], MusicFS_RescanOrigin_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[OriginRequest, SyncProgress]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_RescanOriginClient = grpc.ServerStreamingClient[SyncProgress] - -func (c *musicFSClient) SubscribeEvents(ctx context.Context, in *EventFilter, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Event], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[3], MusicFS_SubscribeEvents_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[EventFilter, Event]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_SubscribeEventsClient = grpc.ServerStreamingClient[Event] - -// MusicFSServer is the server API for MusicFS service. -// All implementations must embed UnimplementedMusicFSServer -// for forward compatibility. -type MusicFSServer interface { - Search(context.Context, *SearchRequest) (*SearchResponse, error) - SearchStream(*SearchRequest, grpc.ServerStreamingServer[SearchResult]) error - GetStatus(context.Context, *Empty) (*StatusResponse, error) - Shutdown(context.Context, *ShutdownRequest) (*Empty, error) - GetCacheStats(context.Context, *Empty) (*CacheStats, error) - ClearCache(context.Context, *ClearCacheRequest) (*ClearCacheResponse, error) - Prefetch(*PrefetchRequest, grpc.ServerStreamingServer[PrefetchProgress]) error - ListOrigins(context.Context, *Empty) (*OriginsResponse, error) - GetOriginHealth(context.Context, *OriginRequest) (*OriginHealthResponse, error) - RescanOrigin(*OriginRequest, grpc.ServerStreamingServer[SyncProgress]) error - SubscribeEvents(*EventFilter, grpc.ServerStreamingServer[Event]) error - mustEmbedUnimplementedMusicFSServer() -} - -// UnimplementedMusicFSServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedMusicFSServer struct{} - -func (UnimplementedMusicFSServer) Search(context.Context, *SearchRequest) (*SearchResponse, error) { - return nil, status.Error(codes.Unimplemented, "method Search not implemented") -} -func (UnimplementedMusicFSServer) SearchStream(*SearchRequest, grpc.ServerStreamingServer[SearchResult]) error { - return status.Error(codes.Unimplemented, "method SearchStream not implemented") -} -func (UnimplementedMusicFSServer) GetStatus(context.Context, *Empty) (*StatusResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetStatus not implemented") -} -func (UnimplementedMusicFSServer) Shutdown(context.Context, *ShutdownRequest) (*Empty, error) { - return nil, status.Error(codes.Unimplemented, "method Shutdown not implemented") -} -func (UnimplementedMusicFSServer) GetCacheStats(context.Context, *Empty) (*CacheStats, error) { - return nil, status.Error(codes.Unimplemented, "method GetCacheStats not implemented") -} -func (UnimplementedMusicFSServer) ClearCache(context.Context, *ClearCacheRequest) (*ClearCacheResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ClearCache not implemented") -} -func (UnimplementedMusicFSServer) Prefetch(*PrefetchRequest, grpc.ServerStreamingServer[PrefetchProgress]) error { - return status.Error(codes.Unimplemented, "method Prefetch not implemented") -} -func (UnimplementedMusicFSServer) ListOrigins(context.Context, *Empty) (*OriginsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListOrigins not implemented") -} -func (UnimplementedMusicFSServer) GetOriginHealth(context.Context, *OriginRequest) (*OriginHealthResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetOriginHealth not implemented") -} -func (UnimplementedMusicFSServer) RescanOrigin(*OriginRequest, grpc.ServerStreamingServer[SyncProgress]) error { - return status.Error(codes.Unimplemented, "method RescanOrigin not implemented") -} -func (UnimplementedMusicFSServer) SubscribeEvents(*EventFilter, grpc.ServerStreamingServer[Event]) error { - return status.Error(codes.Unimplemented, "method SubscribeEvents not implemented") -} -func (UnimplementedMusicFSServer) mustEmbedUnimplementedMusicFSServer() {} -func (UnimplementedMusicFSServer) testEmbeddedByValue() {} - -// UnsafeMusicFSServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to MusicFSServer will -// result in compilation errors. -type UnsafeMusicFSServer interface { - mustEmbedUnimplementedMusicFSServer() -} - -func RegisterMusicFSServer(s grpc.ServiceRegistrar, srv MusicFSServer) { - // If the following call panics, it indicates UnimplementedMusicFSServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&MusicFS_ServiceDesc, srv) -} - -func _MusicFS_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SearchRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).Search(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_Search_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).Search(ctx, req.(*SearchRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_SearchStream_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SearchRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MusicFSServer).SearchStream(m, &grpc.GenericServerStream[SearchRequest, SearchResult]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_SearchStreamServer = grpc.ServerStreamingServer[SearchResult] - -func _MusicFS_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).GetStatus(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_GetStatus_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).GetStatus(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ShutdownRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).Shutdown(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_Shutdown_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).Shutdown(ctx, req.(*ShutdownRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_GetCacheStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).GetCacheStats(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_GetCacheStats_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).GetCacheStats(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_ClearCache_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ClearCacheRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).ClearCache(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_ClearCache_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).ClearCache(ctx, req.(*ClearCacheRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_Prefetch_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(PrefetchRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MusicFSServer).Prefetch(m, &grpc.GenericServerStream[PrefetchRequest, PrefetchProgress]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_PrefetchServer = grpc.ServerStreamingServer[PrefetchProgress] - -func _MusicFS_ListOrigins_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).ListOrigins(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_ListOrigins_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).ListOrigins(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_GetOriginHealth_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(OriginRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).GetOriginHealth(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_GetOriginHealth_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).GetOriginHealth(ctx, req.(*OriginRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_RescanOrigin_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(OriginRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MusicFSServer).RescanOrigin(m, &grpc.GenericServerStream[OriginRequest, SyncProgress]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_RescanOriginServer = grpc.ServerStreamingServer[SyncProgress] - -func _MusicFS_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(EventFilter) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MusicFSServer).SubscribeEvents(m, &grpc.GenericServerStream[EventFilter, Event]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_SubscribeEventsServer = grpc.ServerStreamingServer[Event] - -// MusicFS_ServiceDesc is the grpc.ServiceDesc for MusicFS service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var MusicFS_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "musicfs.v1.MusicFS", - HandlerType: (*MusicFSServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Search", - Handler: _MusicFS_Search_Handler, - }, - { - MethodName: "GetStatus", - Handler: _MusicFS_GetStatus_Handler, - }, - { - MethodName: "Shutdown", - Handler: _MusicFS_Shutdown_Handler, - }, - { - MethodName: "GetCacheStats", - Handler: _MusicFS_GetCacheStats_Handler, - }, - { - MethodName: "ClearCache", - Handler: _MusicFS_ClearCache_Handler, - }, - { - MethodName: "ListOrigins", - Handler: _MusicFS_ListOrigins_Handler, - }, - { - MethodName: "GetOriginHealth", - Handler: _MusicFS_GetOriginHealth_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "SearchStream", - Handler: _MusicFS_SearchStream_Handler, - ServerStreams: true, - }, - { - StreamName: "Prefetch", - Handler: _MusicFS_Prefetch_Handler, - ServerStreams: true, - }, - { - StreamName: "RescanOrigin", - Handler: _MusicFS_RescanOrigin_Handler, - ServerStreams: true, - }, - { - StreamName: "SubscribeEvents", - Handler: _MusicFS_SubscribeEvents_Handler, - ServerStreams: true, - }, - }, - Metadata: "musicfs.proto", -} - -const ( - MetadataService_GetMetadata_FullMethodName = "/musicfs.v1.MetadataService/GetMetadata" - MetadataService_UpdateMetadata_FullMethodName = "/musicfs.v1.MetadataService/UpdateMetadata" - MetadataService_ClearOverlay_FullMethodName = "/musicfs.v1.MetadataService/ClearOverlay" - MetadataService_BatchUpdateMetadata_FullMethodName = "/musicfs.v1.MetadataService/BatchUpdateMetadata" - MetadataService_ImportMetadata_FullMethodName = "/musicfs.v1.MetadataService/ImportMetadata" -) - -// MetadataServiceClient is the client API for MetadataService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type MetadataServiceClient interface { - GetMetadata(ctx context.Context, in *GetMetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error) - UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error) - ClearOverlay(ctx context.Context, in *ClearOverlayRequest, opts ...grpc.CallOption) (*ClearOverlayResponse, error) - BatchUpdateMetadata(ctx context.Context, in *BatchUpdateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BatchUpdateProgress], error) - ImportMetadata(ctx context.Context, in *ImportMetadataRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ImportProgress], error) -} - -type metadataServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewMetadataServiceClient(cc grpc.ClientConnInterface) MetadataServiceClient { - return &metadataServiceClient{cc} -} - -func (c *metadataServiceClient) GetMetadata(ctx context.Context, in *GetMetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(MetadataResponse) - err := c.cc.Invoke(ctx, MetadataService_GetMetadata_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(UpdateMetadataResponse) - err := c.cc.Invoke(ctx, MetadataService_UpdateMetadata_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) ClearOverlay(ctx context.Context, in *ClearOverlayRequest, opts ...grpc.CallOption) (*ClearOverlayResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ClearOverlayResponse) - err := c.cc.Invoke(ctx, MetadataService_ClearOverlay_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) BatchUpdateMetadata(ctx context.Context, in *BatchUpdateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BatchUpdateProgress], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MetadataService_ServiceDesc.Streams[0], MetadataService_BatchUpdateMetadata_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[BatchUpdateRequest, BatchUpdateProgress]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MetadataService_BatchUpdateMetadataClient = grpc.ServerStreamingClient[BatchUpdateProgress] - -func (c *metadataServiceClient) ImportMetadata(ctx context.Context, in *ImportMetadataRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ImportProgress], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MetadataService_ServiceDesc.Streams[1], MetadataService_ImportMetadata_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[ImportMetadataRequest, ImportProgress]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MetadataService_ImportMetadataClient = grpc.ServerStreamingClient[ImportProgress] - -// MetadataServiceServer is the server API for MetadataService service. -// All implementations must embed UnimplementedMetadataServiceServer -// for forward compatibility. -type MetadataServiceServer interface { - GetMetadata(context.Context, *GetMetadataRequest) (*MetadataResponse, error) - UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error) - ClearOverlay(context.Context, *ClearOverlayRequest) (*ClearOverlayResponse, error) - BatchUpdateMetadata(*BatchUpdateRequest, grpc.ServerStreamingServer[BatchUpdateProgress]) error - ImportMetadata(*ImportMetadataRequest, grpc.ServerStreamingServer[ImportProgress]) error - mustEmbedUnimplementedMetadataServiceServer() -} - -// UnimplementedMetadataServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedMetadataServiceServer struct{} - -func (UnimplementedMetadataServiceServer) GetMetadata(context.Context, *GetMetadataRequest) (*MetadataResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetMetadata not implemented") -} -func (UnimplementedMetadataServiceServer) UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpdateMetadata not implemented") -} -func (UnimplementedMetadataServiceServer) ClearOverlay(context.Context, *ClearOverlayRequest) (*ClearOverlayResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ClearOverlay not implemented") -} -func (UnimplementedMetadataServiceServer) BatchUpdateMetadata(*BatchUpdateRequest, grpc.ServerStreamingServer[BatchUpdateProgress]) error { - return status.Error(codes.Unimplemented, "method BatchUpdateMetadata not implemented") -} -func (UnimplementedMetadataServiceServer) ImportMetadata(*ImportMetadataRequest, grpc.ServerStreamingServer[ImportProgress]) error { - return status.Error(codes.Unimplemented, "method ImportMetadata not implemented") -} -func (UnimplementedMetadataServiceServer) mustEmbedUnimplementedMetadataServiceServer() {} -func (UnimplementedMetadataServiceServer) testEmbeddedByValue() {} - -// UnsafeMetadataServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to MetadataServiceServer will -// result in compilation errors. -type UnsafeMetadataServiceServer interface { - mustEmbedUnimplementedMetadataServiceServer() -} - -func RegisterMetadataServiceServer(s grpc.ServiceRegistrar, srv MetadataServiceServer) { - // If the following call panics, it indicates UnimplementedMetadataServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&MetadataService_ServiceDesc, srv) -} - -func _MetadataService_GetMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetMetadataRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).GetMetadata(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_GetMetadata_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).GetMetadata(ctx, req.(*GetMetadataRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_UpdateMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UpdateMetadataRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).UpdateMetadata(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_UpdateMetadata_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).UpdateMetadata(ctx, req.(*UpdateMetadataRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_ClearOverlay_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ClearOverlayRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).ClearOverlay(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_ClearOverlay_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).ClearOverlay(ctx, req.(*ClearOverlayRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_BatchUpdateMetadata_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(BatchUpdateRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MetadataServiceServer).BatchUpdateMetadata(m, &grpc.GenericServerStream[BatchUpdateRequest, BatchUpdateProgress]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MetadataService_BatchUpdateMetadataServer = grpc.ServerStreamingServer[BatchUpdateProgress] - -func _MetadataService_ImportMetadata_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(ImportMetadataRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MetadataServiceServer).ImportMetadata(m, &grpc.GenericServerStream[ImportMetadataRequest, ImportProgress]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MetadataService_ImportMetadataServer = grpc.ServerStreamingServer[ImportProgress] - -// MetadataService_ServiceDesc is the grpc.ServiceDesc for MetadataService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var MetadataService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "musicfs.v1.MetadataService", - HandlerType: (*MetadataServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetMetadata", - Handler: _MetadataService_GetMetadata_Handler, - }, - { - MethodName: "UpdateMetadata", - Handler: _MetadataService_UpdateMetadata_Handler, - }, - { - MethodName: "ClearOverlay", - Handler: _MetadataService_ClearOverlay_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "BatchUpdateMetadata", - Handler: _MetadataService_BatchUpdateMetadata_Handler, - ServerStreams: true, - }, - { - StreamName: "ImportMetadata", - Handler: _MetadataService_ImportMetadata_Handler, - ServerStreams: true, - }, - }, - Metadata: "musicfs.proto", -} diff --git a/gen/musicfs_grpc.pb.go b/gen/musicfs_grpc.pb.go deleted file mode 100644 index afaeb8d..0000000 --- a/gen/musicfs_grpc.pb.go +++ /dev/null @@ -1,775 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.1 -// - protoc (unknown) -// source: musicfs.proto - -package musicfsv1 - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - MusicFS_Search_FullMethodName = "/musicfs.v1.MusicFS/Search" - MusicFS_SearchStream_FullMethodName = "/musicfs.v1.MusicFS/SearchStream" - MusicFS_GetStatus_FullMethodName = "/musicfs.v1.MusicFS/GetStatus" - MusicFS_Shutdown_FullMethodName = "/musicfs.v1.MusicFS/Shutdown" - MusicFS_GetCacheStats_FullMethodName = "/musicfs.v1.MusicFS/GetCacheStats" - MusicFS_ClearCache_FullMethodName = "/musicfs.v1.MusicFS/ClearCache" - MusicFS_Prefetch_FullMethodName = "/musicfs.v1.MusicFS/Prefetch" - MusicFS_ListOrigins_FullMethodName = "/musicfs.v1.MusicFS/ListOrigins" - MusicFS_GetOriginHealth_FullMethodName = "/musicfs.v1.MusicFS/GetOriginHealth" - MusicFS_RescanOrigin_FullMethodName = "/musicfs.v1.MusicFS/RescanOrigin" - MusicFS_SubscribeEvents_FullMethodName = "/musicfs.v1.MusicFS/SubscribeEvents" -) - -// MusicFSClient is the client API for MusicFS service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type MusicFSClient interface { - Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) - SearchStream(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SearchResult], error) - GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StatusResponse, error) - Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Empty, error) - GetCacheStats(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CacheStats, error) - ClearCache(ctx context.Context, in *ClearCacheRequest, opts ...grpc.CallOption) (*ClearCacheResponse, error) - Prefetch(ctx context.Context, in *PrefetchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrefetchProgress], error) - ListOrigins(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*OriginsResponse, error) - GetOriginHealth(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (*OriginHealthResponse, error) - RescanOrigin(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SyncProgress], error) - SubscribeEvents(ctx context.Context, in *EventFilter, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Event], error) -} - -type musicFSClient struct { - cc grpc.ClientConnInterface -} - -func NewMusicFSClient(cc grpc.ClientConnInterface) MusicFSClient { - return &musicFSClient{cc} -} - -func (c *musicFSClient) Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SearchResponse) - err := c.cc.Invoke(ctx, MusicFS_Search_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) SearchStream(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SearchResult], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[0], MusicFS_SearchStream_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[SearchRequest, SearchResult]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_SearchStreamClient = grpc.ServerStreamingClient[SearchResult] - -func (c *musicFSClient) GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StatusResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(StatusResponse) - err := c.cc.Invoke(ctx, MusicFS_GetStatus_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Empty, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(Empty) - err := c.cc.Invoke(ctx, MusicFS_Shutdown_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) GetCacheStats(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CacheStats, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(CacheStats) - err := c.cc.Invoke(ctx, MusicFS_GetCacheStats_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) ClearCache(ctx context.Context, in *ClearCacheRequest, opts ...grpc.CallOption) (*ClearCacheResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ClearCacheResponse) - err := c.cc.Invoke(ctx, MusicFS_ClearCache_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) Prefetch(ctx context.Context, in *PrefetchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrefetchProgress], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[1], MusicFS_Prefetch_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[PrefetchRequest, PrefetchProgress]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_PrefetchClient = grpc.ServerStreamingClient[PrefetchProgress] - -func (c *musicFSClient) ListOrigins(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*OriginsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(OriginsResponse) - err := c.cc.Invoke(ctx, MusicFS_ListOrigins_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) GetOriginHealth(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (*OriginHealthResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(OriginHealthResponse) - err := c.cc.Invoke(ctx, MusicFS_GetOriginHealth_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *musicFSClient) RescanOrigin(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SyncProgress], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[2], MusicFS_RescanOrigin_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[OriginRequest, SyncProgress]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_RescanOriginClient = grpc.ServerStreamingClient[SyncProgress] - -func (c *musicFSClient) SubscribeEvents(ctx context.Context, in *EventFilter, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Event], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[3], MusicFS_SubscribeEvents_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[EventFilter, Event]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_SubscribeEventsClient = grpc.ServerStreamingClient[Event] - -// MusicFSServer is the server API for MusicFS service. -// All implementations must embed UnimplementedMusicFSServer -// for forward compatibility. -type MusicFSServer interface { - Search(context.Context, *SearchRequest) (*SearchResponse, error) - SearchStream(*SearchRequest, grpc.ServerStreamingServer[SearchResult]) error - GetStatus(context.Context, *Empty) (*StatusResponse, error) - Shutdown(context.Context, *ShutdownRequest) (*Empty, error) - GetCacheStats(context.Context, *Empty) (*CacheStats, error) - ClearCache(context.Context, *ClearCacheRequest) (*ClearCacheResponse, error) - Prefetch(*PrefetchRequest, grpc.ServerStreamingServer[PrefetchProgress]) error - ListOrigins(context.Context, *Empty) (*OriginsResponse, error) - GetOriginHealth(context.Context, *OriginRequest) (*OriginHealthResponse, error) - RescanOrigin(*OriginRequest, grpc.ServerStreamingServer[SyncProgress]) error - SubscribeEvents(*EventFilter, grpc.ServerStreamingServer[Event]) error - mustEmbedUnimplementedMusicFSServer() -} - -// UnimplementedMusicFSServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedMusicFSServer struct{} - -func (UnimplementedMusicFSServer) Search(context.Context, *SearchRequest) (*SearchResponse, error) { - return nil, status.Error(codes.Unimplemented, "method Search not implemented") -} -func (UnimplementedMusicFSServer) SearchStream(*SearchRequest, grpc.ServerStreamingServer[SearchResult]) error { - return status.Error(codes.Unimplemented, "method SearchStream not implemented") -} -func (UnimplementedMusicFSServer) GetStatus(context.Context, *Empty) (*StatusResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetStatus not implemented") -} -func (UnimplementedMusicFSServer) Shutdown(context.Context, *ShutdownRequest) (*Empty, error) { - return nil, status.Error(codes.Unimplemented, "method Shutdown not implemented") -} -func (UnimplementedMusicFSServer) GetCacheStats(context.Context, *Empty) (*CacheStats, error) { - return nil, status.Error(codes.Unimplemented, "method GetCacheStats not implemented") -} -func (UnimplementedMusicFSServer) ClearCache(context.Context, *ClearCacheRequest) (*ClearCacheResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ClearCache not implemented") -} -func (UnimplementedMusicFSServer) Prefetch(*PrefetchRequest, grpc.ServerStreamingServer[PrefetchProgress]) error { - return status.Error(codes.Unimplemented, "method Prefetch not implemented") -} -func (UnimplementedMusicFSServer) ListOrigins(context.Context, *Empty) (*OriginsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListOrigins not implemented") -} -func (UnimplementedMusicFSServer) GetOriginHealth(context.Context, *OriginRequest) (*OriginHealthResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetOriginHealth not implemented") -} -func (UnimplementedMusicFSServer) RescanOrigin(*OriginRequest, grpc.ServerStreamingServer[SyncProgress]) error { - return status.Error(codes.Unimplemented, "method RescanOrigin not implemented") -} -func (UnimplementedMusicFSServer) SubscribeEvents(*EventFilter, grpc.ServerStreamingServer[Event]) error { - return status.Error(codes.Unimplemented, "method SubscribeEvents not implemented") -} -func (UnimplementedMusicFSServer) mustEmbedUnimplementedMusicFSServer() {} -func (UnimplementedMusicFSServer) testEmbeddedByValue() {} - -// UnsafeMusicFSServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to MusicFSServer will -// result in compilation errors. -type UnsafeMusicFSServer interface { - mustEmbedUnimplementedMusicFSServer() -} - -func RegisterMusicFSServer(s grpc.ServiceRegistrar, srv MusicFSServer) { - // If the following call panics, it indicates UnimplementedMusicFSServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&MusicFS_ServiceDesc, srv) -} - -func _MusicFS_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SearchRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).Search(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_Search_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).Search(ctx, req.(*SearchRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_SearchStream_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SearchRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MusicFSServer).SearchStream(m, &grpc.GenericServerStream[SearchRequest, SearchResult]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_SearchStreamServer = grpc.ServerStreamingServer[SearchResult] - -func _MusicFS_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).GetStatus(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_GetStatus_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).GetStatus(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ShutdownRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).Shutdown(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_Shutdown_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).Shutdown(ctx, req.(*ShutdownRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_GetCacheStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).GetCacheStats(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_GetCacheStats_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).GetCacheStats(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_ClearCache_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ClearCacheRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).ClearCache(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_ClearCache_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).ClearCache(ctx, req.(*ClearCacheRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_Prefetch_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(PrefetchRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MusicFSServer).Prefetch(m, &grpc.GenericServerStream[PrefetchRequest, PrefetchProgress]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_PrefetchServer = grpc.ServerStreamingServer[PrefetchProgress] - -func _MusicFS_ListOrigins_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).ListOrigins(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_ListOrigins_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).ListOrigins(ctx, req.(*Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_GetOriginHealth_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(OriginRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MusicFSServer).GetOriginHealth(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MusicFS_GetOriginHealth_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MusicFSServer).GetOriginHealth(ctx, req.(*OriginRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MusicFS_RescanOrigin_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(OriginRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MusicFSServer).RescanOrigin(m, &grpc.GenericServerStream[OriginRequest, SyncProgress]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_RescanOriginServer = grpc.ServerStreamingServer[SyncProgress] - -func _MusicFS_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(EventFilter) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MusicFSServer).SubscribeEvents(m, &grpc.GenericServerStream[EventFilter, Event]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MusicFS_SubscribeEventsServer = grpc.ServerStreamingServer[Event] - -// MusicFS_ServiceDesc is the grpc.ServiceDesc for MusicFS service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var MusicFS_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "musicfs.v1.MusicFS", - HandlerType: (*MusicFSServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Search", - Handler: _MusicFS_Search_Handler, - }, - { - MethodName: "GetStatus", - Handler: _MusicFS_GetStatus_Handler, - }, - { - MethodName: "Shutdown", - Handler: _MusicFS_Shutdown_Handler, - }, - { - MethodName: "GetCacheStats", - Handler: _MusicFS_GetCacheStats_Handler, - }, - { - MethodName: "ClearCache", - Handler: _MusicFS_ClearCache_Handler, - }, - { - MethodName: "ListOrigins", - Handler: _MusicFS_ListOrigins_Handler, - }, - { - MethodName: "GetOriginHealth", - Handler: _MusicFS_GetOriginHealth_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "SearchStream", - Handler: _MusicFS_SearchStream_Handler, - ServerStreams: true, - }, - { - StreamName: "Prefetch", - Handler: _MusicFS_Prefetch_Handler, - ServerStreams: true, - }, - { - StreamName: "RescanOrigin", - Handler: _MusicFS_RescanOrigin_Handler, - ServerStreams: true, - }, - { - StreamName: "SubscribeEvents", - Handler: _MusicFS_SubscribeEvents_Handler, - ServerStreams: true, - }, - }, - Metadata: "musicfs.proto", -} - -const ( - MetadataService_GetMetadata_FullMethodName = "/musicfs.v1.MetadataService/GetMetadata" - MetadataService_UpdateMetadata_FullMethodName = "/musicfs.v1.MetadataService/UpdateMetadata" - MetadataService_ClearOverlay_FullMethodName = "/musicfs.v1.MetadataService/ClearOverlay" - MetadataService_BatchUpdateMetadata_FullMethodName = "/musicfs.v1.MetadataService/BatchUpdateMetadata" - MetadataService_ImportMetadata_FullMethodName = "/musicfs.v1.MetadataService/ImportMetadata" -) - -// MetadataServiceClient is the client API for MetadataService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type MetadataServiceClient interface { - GetMetadata(ctx context.Context, in *GetMetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error) - UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error) - ClearOverlay(ctx context.Context, in *ClearOverlayRequest, opts ...grpc.CallOption) (*ClearOverlayResponse, error) - BatchUpdateMetadata(ctx context.Context, in *BatchUpdateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BatchUpdateProgress], error) - ImportMetadata(ctx context.Context, in *ImportMetadataRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ImportProgress], error) -} - -type metadataServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewMetadataServiceClient(cc grpc.ClientConnInterface) MetadataServiceClient { - return &metadataServiceClient{cc} -} - -func (c *metadataServiceClient) GetMetadata(ctx context.Context, in *GetMetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(MetadataResponse) - err := c.cc.Invoke(ctx, MetadataService_GetMetadata_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(UpdateMetadataResponse) - err := c.cc.Invoke(ctx, MetadataService_UpdateMetadata_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) ClearOverlay(ctx context.Context, in *ClearOverlayRequest, opts ...grpc.CallOption) (*ClearOverlayResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ClearOverlayResponse) - err := c.cc.Invoke(ctx, MetadataService_ClearOverlay_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *metadataServiceClient) BatchUpdateMetadata(ctx context.Context, in *BatchUpdateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BatchUpdateProgress], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MetadataService_ServiceDesc.Streams[0], MetadataService_BatchUpdateMetadata_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[BatchUpdateRequest, BatchUpdateProgress]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MetadataService_BatchUpdateMetadataClient = grpc.ServerStreamingClient[BatchUpdateProgress] - -func (c *metadataServiceClient) ImportMetadata(ctx context.Context, in *ImportMetadataRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ImportProgress], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &MetadataService_ServiceDesc.Streams[1], MetadataService_ImportMetadata_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[ImportMetadataRequest, ImportProgress]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MetadataService_ImportMetadataClient = grpc.ServerStreamingClient[ImportProgress] - -// MetadataServiceServer is the server API for MetadataService service. -// All implementations must embed UnimplementedMetadataServiceServer -// for forward compatibility. -type MetadataServiceServer interface { - GetMetadata(context.Context, *GetMetadataRequest) (*MetadataResponse, error) - UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error) - ClearOverlay(context.Context, *ClearOverlayRequest) (*ClearOverlayResponse, error) - BatchUpdateMetadata(*BatchUpdateRequest, grpc.ServerStreamingServer[BatchUpdateProgress]) error - ImportMetadata(*ImportMetadataRequest, grpc.ServerStreamingServer[ImportProgress]) error - mustEmbedUnimplementedMetadataServiceServer() -} - -// UnimplementedMetadataServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedMetadataServiceServer struct{} - -func (UnimplementedMetadataServiceServer) GetMetadata(context.Context, *GetMetadataRequest) (*MetadataResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetMetadata not implemented") -} -func (UnimplementedMetadataServiceServer) UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpdateMetadata not implemented") -} -func (UnimplementedMetadataServiceServer) ClearOverlay(context.Context, *ClearOverlayRequest) (*ClearOverlayResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ClearOverlay not implemented") -} -func (UnimplementedMetadataServiceServer) BatchUpdateMetadata(*BatchUpdateRequest, grpc.ServerStreamingServer[BatchUpdateProgress]) error { - return status.Error(codes.Unimplemented, "method BatchUpdateMetadata not implemented") -} -func (UnimplementedMetadataServiceServer) ImportMetadata(*ImportMetadataRequest, grpc.ServerStreamingServer[ImportProgress]) error { - return status.Error(codes.Unimplemented, "method ImportMetadata not implemented") -} -func (UnimplementedMetadataServiceServer) mustEmbedUnimplementedMetadataServiceServer() {} -func (UnimplementedMetadataServiceServer) testEmbeddedByValue() {} - -// UnsafeMetadataServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to MetadataServiceServer will -// result in compilation errors. -type UnsafeMetadataServiceServer interface { - mustEmbedUnimplementedMetadataServiceServer() -} - -func RegisterMetadataServiceServer(s grpc.ServiceRegistrar, srv MetadataServiceServer) { - // If the following call panics, it indicates UnimplementedMetadataServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&MetadataService_ServiceDesc, srv) -} - -func _MetadataService_GetMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetMetadataRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).GetMetadata(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_GetMetadata_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).GetMetadata(ctx, req.(*GetMetadataRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_UpdateMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UpdateMetadataRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).UpdateMetadata(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_UpdateMetadata_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).UpdateMetadata(ctx, req.(*UpdateMetadataRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_ClearOverlay_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ClearOverlayRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MetadataServiceServer).ClearOverlay(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: MetadataService_ClearOverlay_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MetadataServiceServer).ClearOverlay(ctx, req.(*ClearOverlayRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _MetadataService_BatchUpdateMetadata_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(BatchUpdateRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MetadataServiceServer).BatchUpdateMetadata(m, &grpc.GenericServerStream[BatchUpdateRequest, BatchUpdateProgress]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MetadataService_BatchUpdateMetadataServer = grpc.ServerStreamingServer[BatchUpdateProgress] - -func _MetadataService_ImportMetadata_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(ImportMetadataRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MetadataServiceServer).ImportMetadata(m, &grpc.GenericServerStream[ImportMetadataRequest, ImportProgress]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type MetadataService_ImportMetadataServer = grpc.ServerStreamingServer[ImportProgress] - -// MetadataService_ServiceDesc is the grpc.ServiceDesc for MetadataService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var MetadataService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "musicfs.v1.MetadataService", - HandlerType: (*MetadataServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetMetadata", - Handler: _MetadataService_GetMetadata_Handler, - }, - { - MethodName: "UpdateMetadata", - Handler: _MetadataService_UpdateMetadata_Handler, - }, - { - MethodName: "ClearOverlay", - Handler: _MetadataService_ClearOverlay_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "BatchUpdateMetadata", - Handler: _MetadataService_BatchUpdateMetadata_Handler, - ServerStreams: true, - }, - { - StreamName: "ImportMetadata", - Handler: _MetadataService_ImportMetadata_Handler, - ServerStreams: true, - }, - }, - Metadata: "musicfs.proto", -} diff --git a/go.mod b/go.mod deleted file mode 100644 index e210878..0000000 --- a/go.mod +++ /dev/null @@ -1,174 +0,0 @@ -module homelab.lan/music-agregator - -go 1.26.2 - -require ( - github.com/anacrolix/torrent v1.61.0 - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 - github.com/jackc/pgx/v5 v5.9.2 - github.com/mewkiz/flac v1.0.13 - github.com/prometheus/client_golang v1.23.2 - github.com/riverqueue/river v0.35.1 - github.com/riverqueue/river/riverdriver/riverpgxv5 v0.35.1 - github.com/rs/zerolog v1.35.1 - github.com/stretchr/testify v1.11.1 - github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300 - github.com/testcontainers/testcontainers-go v0.42.0 - github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0 -) - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/RoaringBitmap/roaring v1.2.3 // indirect - github.com/alecthomas/atomic v0.1.0-alpha2 // indirect - github.com/anacrolix/btree v0.0.0-20251201064447-d86c3fa41bd8 // indirect - github.com/anacrolix/chansync v0.7.0 // indirect - github.com/anacrolix/dht/v2 v2.23.0 // indirect - github.com/anacrolix/envpprof v1.4.0 // indirect - github.com/anacrolix/generics v0.1.1-0.20251125230353-15d98d46693b // indirect - github.com/anacrolix/go-libutp v1.3.2 // indirect - github.com/anacrolix/log v0.17.1-0.20251118025802-918f1157b7bb // indirect - github.com/anacrolix/missinggo v1.3.0 // indirect - github.com/anacrolix/missinggo/perf v1.0.0 // indirect - github.com/anacrolix/missinggo/v2 v2.10.0 // indirect - github.com/anacrolix/mmsg v1.0.1 // indirect - github.com/anacrolix/multiless v0.4.0 // indirect - github.com/anacrolix/stm v0.5.0 // indirect - github.com/anacrolix/sync v0.5.5-0.20251119100342-d78dd1f686f1 // indirect - github.com/anacrolix/upnp v0.1.4 // indirect - github.com/anacrolix/utp v0.1.0 // indirect - github.com/bahlo/generic-list-go v0.2.0 // indirect - github.com/benbjohnson/immutable v0.4.1-0.20221220213129-8932b999621d // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.2.2 // indirect - github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/containerd/errdefs v1.0.0 // indirect - github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/containerd/log v0.1.0 // indirect - github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v28.3.2+incompatible // indirect - github.com/docker/go-connections v0.6.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/ebitengine/purego v0.10.0 // indirect - github.com/edsrzf/mmap-go v1.1.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-llsqlite/adapter v0.0.0-20230927005056-7f5ce7f0c916 // indirect - github.com/go-llsqlite/crawshaw v0.5.6-0.20250312230104-194977a03421 // indirect - github.com/go-logr/logr v1.4.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/btree v1.1.2 // indirect - github.com/google/go-cmp v0.7.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/huandu/xstrings v1.3.2 // indirect - github.com/icza/bitio v1.1.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/puddle/v2 v2.2.2 // indirect - github.com/klauspost/compress v1.18.5 // indirect - github.com/klauspost/cpuid/v2 v2.2.3 // indirect - github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 // indirect - github.com/magiconair/properties v1.8.10 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mewkiz/pkg v0.0.0-20250417130911-3f050ff8c56d // indirect - github.com/mewpkg/term v0.0.0-20241026122259-37a80af23985 // indirect - github.com/minio/sha256-simd v1.0.0 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/go-archive v0.2.0 // indirect - github.com/moby/moby/api v1.54.1 // indirect - github.com/moby/moby/client v0.4.0 // indirect - github.com/moby/patternmatcher v0.6.1 // indirect - github.com/moby/sys/sequential v0.6.0 // indirect - github.com/moby/sys/user v0.4.0 // indirect - github.com/moby/sys/userns v0.1.0 // indirect - github.com/moby/term v0.5.2 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/mschoch/smat v0.2.0 // indirect - github.com/multiformats/go-multihash v0.2.3 // indirect - github.com/multiformats/go-varint v0.0.6 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/pion/datachannel v1.5.9 // indirect - github.com/pion/dtls/v3 v3.0.3 // indirect - github.com/pion/ice/v4 v4.0.2 // indirect - github.com/pion/interceptor v0.1.40 // indirect - github.com/pion/logging v0.2.3 // indirect - github.com/pion/mdns/v2 v2.0.7 // indirect - github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.15 // indirect - github.com/pion/rtp v1.8.18 // indirect - github.com/pion/sctp v1.8.33 // indirect - github.com/pion/sdp/v3 v3.0.9 // indirect - github.com/pion/srtp/v3 v3.0.4 // indirect - github.com/pion/stun/v3 v3.0.0 // indirect - github.com/pion/transport/v3 v3.0.7 // indirect - github.com/pion/turn/v4 v4.0.0 // indirect - github.com/pion/webrtc/v4 v4.0.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.66.1 // indirect - github.com/prometheus/procfs v0.16.1 // indirect - github.com/protolambda/ctxlock v0.1.0 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/riverqueue/river/riverdriver v0.35.1 // indirect - github.com/riverqueue/river/rivershared v0.35.1 // indirect - github.com/riverqueue/river/rivertype v0.35.1 // indirect - github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 // indirect - github.com/shirou/gopsutil/v4 v4.26.3 // indirect - github.com/sirupsen/logrus v1.9.4 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/tidwall/btree v1.8.1 // indirect - github.com/tidwall/gjson v1.18.0 // indirect - github.com/tidwall/match v1.2.0 // indirect - github.com/tidwall/pretty v1.2.1 // indirect - github.com/tidwall/sjson v1.2.5 // indirect - github.com/tklauser/go-sysconf v0.3.16 // indirect - github.com/tklauser/numcpus v0.11.0 // indirect - github.com/wlynxg/anet v0.0.3 // indirect - github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.etcd.io/bbolt v1.3.6 // indirect - go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect - go.opentelemetry.io/otel v1.43.0 // indirect - go.opentelemetry.io/otel/metric v1.43.0 // indirect - go.opentelemetry.io/otel/trace v1.43.0 // indirect - go.uber.org/goleak v1.3.0 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect - golang.org/x/crypto v0.48.0 // indirect - golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/time v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/blake3 v1.1.6 // indirect - modernc.org/libc v1.22.3 // indirect - modernc.org/mathutil v1.5.0 // indirect - modernc.org/memory v1.5.0 // indirect - modernc.org/sqlite v1.21.1 // indirect - zombiezen.com/go/sqlite v0.13.1 // indirect -) - -require ( - github.com/mattn/go-isatty v0.0.20 // indirect - golang.org/x/net v0.51.0 // indirect - golang.org/x/sys v0.42.0 // indirect - golang.org/x/text v0.36.0 // indirect - google.golang.org/grpc v1.81.0 - google.golang.org/protobuf v1.36.11 - gopkg.in/yaml.v2 v2.4.0 -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 5f73c2d..0000000 --- a/go.sum +++ /dev/null @@ -1,710 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -crawshaw.io/iox v0.0.0-20181124134642-c51c3df30797/go.mod h1:sXBiorCo8c46JlQV3oXPKINnZ8mcqnye1EkVkqsectk= -crawshaw.io/sqlite v0.3.2/go.mod h1:igAO5JulrQ1DbdZdtVq48mnZUBAPOeFzer7VhDWNtW4= -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w= -github.com/RoaringBitmap/roaring v0.4.17/go.mod h1:D3qVegWTmfCaX4Bl5CrBE9hfrSrrXIr8KVNvRsDi1NI= -github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= -github.com/RoaringBitmap/roaring v1.2.3 h1:yqreLINqIrX22ErkKI0vY47/ivtJr6n+kMhVOVmhWBY= -github.com/RoaringBitmap/roaring v1.2.3/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/alecthomas/assert/v2 v2.0.0-alpha3 h1:pcHeMvQ3OMstAWgaeaXIAL8uzB9xMm2zlxt+/4ml8lk= -github.com/alecthomas/assert/v2 v2.0.0-alpha3/go.mod h1:+zD0lmDXTeQj7TgDgCt0ePWxb0hMC1G+PGTsTCv1B9o= -github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= -github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= -github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142 h1:8Uy0oSf5co/NZXje7U1z8Mpep++QJOldL2hs/sBQf48= -github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/anacrolix/btree v0.0.0-20251201064447-d86c3fa41bd8 h1:c02PsmoaChabVqAFm7pqPI1UIkDdDAjUaWa6ZmfxybQ= -github.com/anacrolix/btree v0.0.0-20251201064447-d86c3fa41bd8/go.mod h1:7stWJ39LeusmMI8mjJuhFNRqep//vx0AsaySRoK9or0= -github.com/anacrolix/chansync v0.7.0 h1:wgwxbsJRmOqNjil4INpxHrDp4rlqQhECxR8/WBP4Et0= -github.com/anacrolix/chansync v0.7.0/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k= -github.com/anacrolix/dht/v2 v2.23.0 h1:EuD17ykTTEkAMPLjBsS5QjGOwuBgLTdQhds6zPAjeVY= -github.com/anacrolix/dht/v2 v2.23.0/go.mod h1:seXRz6HLw8zEnxlysf9ye2eQbrKUmch6PyOHpe/Nb/U= -github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c= -github.com/anacrolix/envpprof v1.0.0/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c= -github.com/anacrolix/envpprof v1.1.0/go.mod h1:My7T5oSqVfEn4MD4Meczkw/f5lSIndGAKu/0SM/rkf4= -github.com/anacrolix/envpprof v1.4.0 h1:QHeIcrgHcRChhnxR8l6rlaLlRQx9zd7Q2NII6Zbt83w= -github.com/anacrolix/envpprof v1.4.0/go.mod h1:7QIG4CaX1uexQ3tqd5+BRa/9e2D02Wcertl6Yh0jCB0= -github.com/anacrolix/generics v0.0.0-20230113004304-d6428d516633/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8= -github.com/anacrolix/generics v0.1.1-0.20251125230353-15d98d46693b h1:Kuvx/A/TTJuT9x8mn7DeGx2KW9tWn1LI8bira67xdT0= -github.com/anacrolix/generics v0.1.1-0.20251125230353-15d98d46693b/go.mod h1:NGehhfeXJPBujPx0s6cstSj8B+TERsTY32Xckfx5ftc= -github.com/anacrolix/go-libutp v1.3.2 h1:WswiaxTIogchbkzNgGHuHRfbrYLpv4o290mlvcx+++M= -github.com/anacrolix/go-libutp v1.3.2/go.mod h1:fCUiEnXJSe3jsPG554A200Qv+45ZzIIyGEvE56SHmyA= -github.com/anacrolix/log v0.3.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU= -github.com/anacrolix/log v0.6.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU= -github.com/anacrolix/log v0.13.1/go.mod h1:D4+CvN8SnruK6zIFS/xPoRJmtvtnxs+CSfDQ+BFxZ68= -github.com/anacrolix/log v0.14.2/go.mod h1:1OmJESOtxQGNMlUO5rcv96Vpp9mfMqXXbe2RdinFLdY= -github.com/anacrolix/log v0.17.1-0.20251118025802-918f1157b7bb h1:nGNLCQbxFQZz7/9PXLGQ9GmavI/W+eX66pSwVeUwugU= -github.com/anacrolix/log v0.17.1-0.20251118025802-918f1157b7bb/go.mod h1:YjBZbwe2v3RsU7WdoBlVSPVpfKuOAno9SRQ/8tIl+hk= -github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62/go.mod h1:66cFKPCO7Sl4vbFnAaSq7e4OXtdMhRSBagJGWgmpJbM= -github.com/anacrolix/lsan v0.1.0 h1:TbgB8fdVXgBwrNsJGHtht9+9FepNFu5H7dU8ek6XYAY= -github.com/anacrolix/lsan v0.1.0/go.mod h1:66cFKPCO7Sl4vbFnAaSq7e4OXtdMhRSBagJGWgmpJbM= -github.com/anacrolix/missinggo v0.0.0-20180725070939-60ef2fbf63df/go.mod h1:kwGiTUTZ0+p4vAz3VbAI5a30t2YbvemcmspjKwrAz5s= -github.com/anacrolix/missinggo v1.1.0/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo= -github.com/anacrolix/missinggo v1.1.2-0.20190815015349-b888af804467/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo= -github.com/anacrolix/missinggo v1.2.1/go.mod h1:J5cMhif8jPmFoC3+Uvob3OXXNIhOUikzMt+uUjeM21Y= -github.com/anacrolix/missinggo v1.3.0 h1:06HlMsudotL7BAELRZs0yDZ4yVXsHXGi323QBjAVASw= -github.com/anacrolix/missinggo v1.3.0/go.mod h1:bqHm8cE8xr+15uVfMG3BFui/TxyB6//H5fwlq/TeqMc= -github.com/anacrolix/missinggo/perf v1.0.0 h1:7ZOGYziGEBytW49+KmYGTaNfnwUqP1HBsy6BqESAJVw= -github.com/anacrolix/missinggo/perf v1.0.0/go.mod h1:ljAFWkBuzkO12MQclXzZrosP5urunoLS0Cbvb4V0uMQ= -github.com/anacrolix/missinggo/v2 v2.2.0/go.mod h1:o0jgJoYOyaoYQ4E2ZMISVa9c88BbUBVQQW4QeRkNCGY= -github.com/anacrolix/missinggo/v2 v2.5.1/go.mod h1:WEjqh2rmKECd0t1VhQkLGTdIWXO6f6NLjp5GlMZ+6FA= -github.com/anacrolix/missinggo/v2 v2.10.0 h1:pg0iO4Z/UhP2MAnmGcaMtp5ZP9kyWsusENWN9aolrkY= -github.com/anacrolix/missinggo/v2 v2.10.0/go.mod h1:nCRMW6bRCMOVcw5z9BnSYKF+kDbtenx+hQuphf4bK8Y= -github.com/anacrolix/mmsg v1.0.1 h1:TxfpV7kX70m3f/O7ielL/2I3OFkMPjrRCPo7+4X5AWw= -github.com/anacrolix/mmsg v1.0.1/go.mod h1:x8kRaJY/dCrY9Al0PEcj1mb/uFHwP6GCJ9fLl4thEPc= -github.com/anacrolix/multiless v0.4.0 h1:lqSszHkliMsZd2hsyrDvHOw4AbYWa+ijQ66LzbjqWjM= -github.com/anacrolix/multiless v0.4.0/go.mod h1:zJv1JF9AqdZiHwxqPgjuOZDGWER6nyE48WBCi/OOrMM= -github.com/anacrolix/stm v0.2.0/go.mod h1:zoVQRvSiGjGoTmbM0vSLIiaKjWtNPeTvXUSdJQA4hsg= -github.com/anacrolix/stm v0.5.0 h1:9df1KBpttF0TzLgDq51Z+TEabZKMythqgx89f1FQJt8= -github.com/anacrolix/stm v0.5.0/go.mod h1:MOwrSy+jCm8Y7HYfMAwPj7qWVu7XoVvjOiYwJmpeB/M= -github.com/anacrolix/sync v0.0.0-20180808010631-44578de4e778/go.mod h1:s735Etp3joe/voe2sdaXLcqDdJSay1O0OPnM0ystjqk= -github.com/anacrolix/sync v0.3.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DCOj/I0g= -github.com/anacrolix/sync v0.5.5-0.20251119100342-d78dd1f686f1 h1:oLCfNgEOR3/Z98mSwmwTM1pcqCDb/1zIjxCNn7dzVaE= -github.com/anacrolix/sync v0.5.5-0.20251119100342-d78dd1f686f1/go.mod h1:21cUWerw9eiu/3T3kyoChu37AVO+YFue1/H15qqubS0= -github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw= -github.com/anacrolix/tagflag v1.0.0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw= -github.com/anacrolix/tagflag v1.1.0/go.mod h1:Scxs9CV10NQatSmbyjqmqmeQNwGzlNe0CMUMIxqHIG8= -github.com/anacrolix/torrent v1.61.0 h1:vxo+B4SwnoP5AQWbhvnTYIaTgPSX+llYUVuQVsN4Jg8= -github.com/anacrolix/torrent v1.61.0/go.mod h1:yKUKuZSSDdyOsCbuH+rDOpswl/g546gICapdrU7aUmQ= -github.com/anacrolix/upnp v0.1.4 h1:+2t2KA6QOhm/49zeNyeVwDu1ZYS9dB9wfxyVvh/wk7U= -github.com/anacrolix/upnp v0.1.4/go.mod h1:Qyhbqo69gwNWvEk1xNTXsS5j7hMHef9hdr984+9fIic= -github.com/anacrolix/utp v0.1.0 h1:FOpQOmIwYsnENnz7tAGohA+r6iXpRjrq8ssKSre2Cp4= -github.com/anacrolix/utp v0.1.0/go.mod h1:MDwc+vsGEq7RMw6lr2GKOEqjWny5hO5OZXRVNaBJ2Dk= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= -github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= -github.com/benbjohnson/immutable v0.2.0/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI= -github.com/benbjohnson/immutable v0.4.1-0.20221220213129-8932b999621d h1:2qVb9bsAMtmAfnxXltm+6eBzrrS7SZ52c3SedsulaMI= -github.com/benbjohnson/immutable v0.4.1-0.20221220213129-8932b999621d/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bits-and-blooms/bitset v1.2.2 h1:J5gbX05GpMdBjCvQ9MteIg2KKDExr7DrgK+Yc15FvIk= -github.com/bits-and-blooms/bitset v1.2.2/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo= -github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo= -github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaqKnf+7Qs6GbEPfd4iMOitWzXJx8= -github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8/go.mod h1:spo1JLcs67NmW1aVLEgtA8Yy1elc+X8y5SRW1sFW4Og= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= -github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= -github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= -github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= -github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= -github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= -github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA= -github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= -github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= -github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= -github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= -github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= -github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= -github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-llsqlite/adapter v0.0.0-20230927005056-7f5ce7f0c916 h1:OyQmpAN302wAopDgwVjgs2HkFawP9ahIEqkUYz7V7CA= -github.com/go-llsqlite/adapter v0.0.0-20230927005056-7f5ce7f0c916/go.mod h1:DADrR88ONKPPeSGjFp5iEN55Arx3fi2qXZeKCYDpbmU= -github.com/go-llsqlite/crawshaw v0.5.6-0.20250312230104-194977a03421 h1:GClwZI0at7xwV0TpgUMTYr/DoTE7TJZ/tc29LcPcs7o= -github.com/go-llsqlite/crawshaw v0.5.6-0.20250312230104-194977a03421/go.mod h1:/YJdV7uBQaYDE0fwe4z3wwJIZBJxdYzd38ICggWqtaE= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= -github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20190309154008-847fc94819f9/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= -github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= -github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= -github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/icza/bitio v1.1.0 h1:ysX4vtldjdi3Ygai5m1cWy4oLkhWTAi+SyO6HC8L9T0= -github.com/icza/bitio v1.1.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A= -github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k= -github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= -github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0= -github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= -github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw= -github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= -github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= -github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= -github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= -github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 h1:PwQumkgq4/acIiZhtifTV5OUqqiP82UAl0h87xj/l9k= -github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= -github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= -github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI= -github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o= -github.com/mewkiz/flac v1.0.13 h1:6wF8rRQKBFW159Daqx6Ro7K5ZnlVhHUKfS5aTsC4oXs= -github.com/mewkiz/flac v1.0.13/go.mod h1:HfPYDA+oxjyuqMu2V+cyKcxF51KM6incpw5eZXmfA6k= -github.com/mewkiz/pkg v0.0.0-20250417130911-3f050ff8c56d h1:IL2tii4jXLdhCeQN69HNzYYW1kl0meSG0wt5+sLwszU= -github.com/mewkiz/pkg v0.0.0-20250417130911-3f050ff8c56d/go.mod h1:SIpumAnUWSy0q9RzKD3pyH3g1t5vdawUAPcW5tQrUtI= -github.com/mewpkg/term v0.0.0-20241026122259-37a80af23985 h1:h8O1byDZ1uk6RUXMhj1QJU3VXFKXHDZxr4TXRPGeBa8= -github.com/mewpkg/term v0.0.0-20241026122259-37a80af23985/go.mod h1:uiPmbdUbdt1NkGApKl7htQjZ8S7XaGUAVulJUJ9v6q4= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8= -github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU= -github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= -github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= -github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= -github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= -github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U= -github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= -github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= -github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= -github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= -github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= -github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= -github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= -github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= -github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= -github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= -github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= -github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= -github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= -github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= -github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pion/datachannel v1.5.9 h1:LpIWAOYPyDrXtU+BW7X0Yt/vGtYxtXQ8ql7dFfYUVZA= -github.com/pion/datachannel v1.5.9/go.mod h1:kDUuk4CU4Uxp82NH4LQZbISULkX/HtzKa4P7ldf9izE= -github.com/pion/dtls/v3 v3.0.3 h1:j5ajZbQwff7Z8k3pE3S+rQ4STvKvXUdKsi/07ka+OWM= -github.com/pion/dtls/v3 v3.0.3/go.mod h1:weOTUyIV4z0bQaVzKe8kpaP17+us3yAuiQsEAG1STMU= -github.com/pion/ice/v4 v4.0.2 h1:1JhBRX8iQLi0+TfcavTjPjI6GO41MFn4CeTBX+Y9h5s= -github.com/pion/ice/v4 v4.0.2/go.mod h1:DCdqyzgtsDNYN6/3U8044j3U7qsJ9KFJC92VnOWHvXg= -github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= -github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= -github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI= -github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= -github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= -github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= -github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= -github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= -github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= -github.com/pion/rtp v1.8.18 h1:yEAb4+4a8nkPCecWzQB6V/uEU18X1lQCGAQCjP+pyvU= -github.com/pion/rtp v1.8.18/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= -github.com/pion/sctp v1.8.33 h1:dSE4wX6uTJBcNm8+YlMg7lw1wqyKHggsP5uKbdj+NZw= -github.com/pion/sctp v1.8.33/go.mod h1:beTnqSzewI53KWoG3nqB282oDMGrhNxBdb+JZnkCwRM= -github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= -github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= -github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M= -github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ= -github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= -github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= -github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= -github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM= -github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA= -github.com/pion/webrtc/v4 v4.0.0 h1:x8ec7uJQPP3D1iI8ojPAiTOylPI7Fa7QgqZrhpLyqZ8= -github.com/pion/webrtc/v4 v4.0.0/go.mod h1:SfNn8CcFxR6OUVjLXVslAQ3a3994JhyE3Hw1jAuqEto= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= -github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= -github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= -github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= -github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= -github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= -github.com/protolambda/ctxlock v0.1.0 h1:rCUY3+vRdcdZXqT07iXgyr744J2DU2LCBIXowYAjBCE= -github.com/protolambda/ctxlock v0.1.0/go.mod h1:vefhX6rIZH8rsg5ZpOJfEDYQOppZi19SfPiGOFrNnwM= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/riverqueue/river v0.35.1 h1:TK1LLGRdTWL7ARPbIUB+TqMnTYJ0GiCoy5Q/yEf5yBE= -github.com/riverqueue/river v0.35.1/go.mod h1:jDt0LimObI+5e6FVy7LyuIWfHftmV0wARmiK7W+9D64= -github.com/riverqueue/river/riverdriver v0.35.1 h1:zJx8SaQdMP7zVEfd8SDoe8KjVHCXoXoFfzt6v+SJtQg= -github.com/riverqueue/river/riverdriver v0.35.1/go.mod h1:Y+rQzz0uvh+pQI+mzJh3qgAGGNxestOWgjKa7mob87w= -github.com/riverqueue/river/riverdriver/riverpgxv5 v0.35.1 h1:GL+ztwpXgIqBin/3wNzq8h1/H8befxl61/DlLvVCAAY= -github.com/riverqueue/river/riverdriver/riverpgxv5 v0.35.1/go.mod h1:5Llh5ONCFsW67dLm5+OelSWTKhliQ989JLbVMwyuN2U= -github.com/riverqueue/river/rivershared v0.35.1 h1:XEHf7yj35p5Os5r6K08q9BVaAKsvWhP9hfxEr+MwXqg= -github.com/riverqueue/river/rivershared v0.35.1/go.mod h1:YqVk7bZoojLsx58kyQ6ZU2FHP91HP4whVj6MTCtih/c= -github.com/riverqueue/river/rivertype v0.35.1 h1:7SfjZ3Hkr7gRjItMHAUzJBAHIqx41yS/4yjVPQVtNfM= -github.com/riverqueue/river/rivertype v0.35.1/go.mod h1:D1Ad+EaZiaXbQbJcJcfeicXJMBKno0n6UcfKI5Q7DIQ= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= -github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 h1:Lt9DzQALzHoDwMBGJ6v8ObDPR0dzr2a6sXTB1Fq7IHs= -github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA= -github.com/rs/zerolog v1.35.1 h1:m7xQeoiLIiV0BCEY4Hs+j2NG4Gp2o2KPKmhnnLiazKI= -github.com/rs/zerolog v1.35.1/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw= -github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8= -github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8= -github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc= -github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= -github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= -github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff/go.mod h1:KSQcGKpxUMHk3nbYzs/tIBAM2iDooCn0BmttHOJEbLs= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= -github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= -github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300 h1:XQdibLKagjdevRB6vAjVY4qbSr8rQ610YzTkWcxzxSI= -github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300/go.mod h1:FNa/dfN95vAYCNFrIKRrlRo+MBLbwmR9Asa5f2ljmBI= -github.com/testcontainers/testcontainers-go v0.42.0 h1:He3IhTzTZOygSXLJPMX7n44XtK+qhjat1nI9cneBbUY= -github.com/testcontainers/testcontainers-go v0.42.0/go.mod h1:vZjdY1YmUA1qEForxOIOazfsrdyORJAbhi0bp8plN30= -github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0 h1:GCbb1ndrF7OTDiIvxXyItaDab4qkzTFJ48LKFdM7EIo= -github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0/go.mod h1:IRPBaI8jXdrNfD0e4Zm7Fbcgaz5shKxOQv4axiL09xs= -github.com/tidwall/btree v1.8.1 h1:27ehoXvm5AG/g+1VxLS1SD3vRhp/H7LuEfwNvddEdmA= -github.com/tidwall/btree v1.8.1/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A= -github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= -github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM= -github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= -github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= -github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= -github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= -github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= -github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= -github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/wlynxg/anet v0.0.3 h1:PvR53psxFXstc12jelG6f1Lv4MWqE0tI76/hHGjh9rg= -github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= -github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= -go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= -go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= -go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= -go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= -go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= -go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= -go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= -golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 h1:zfMcR1Cs4KNuomFFgGefv5N0czO2XZpUbxGUy8i8ug0= -golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= -golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= -golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= -gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= -google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= -gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c= -lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= -modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY= -modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw= -modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= -modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU= -modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI= -pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= -pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= -zombiezen.com/go/sqlite v0.13.1 h1:qDzxyWWmMtSSEH5qxamqBFmqA2BLSSbtODi3ojaE02o= -zombiezen.com/go/sqlite v0.13.1/go.mod h1:Ht/5Rg3Ae2hoyh1I7gbWtWAl89CNocfqeb/aAMTkJr4= diff --git a/internal/analysis/analyzer.go b/internal/analysis/analyzer.go deleted file mode 100644 index 5507b3f..0000000 --- a/internal/analysis/analyzer.go +++ /dev/null @@ -1,285 +0,0 @@ -package analysis - -import ( - "context" - "crypto/sha256" - "encoding/hex" - "fmt" - "io" - "os" - "path/filepath" - "regexp" - "strings" - "time" - - "github.com/rs/zerolog/log" - - "homelab.lan/music-agregator/internal/audio" - "homelab.lan/music-agregator/internal/database" -) - -var audioExtensions = map[string]bool{ - ".flac": true, ".mp3": true, ".aac": true, ".m4a": true, - ".ape": true, ".wv": true, ".ogg": true, ".wav": true, ".alac": true, -} - -var trackNumberRegex = regexp.MustCompile(`^(\d+)[\s\-._]+`) - -type ReleaseAnalyzer struct { - downloads *database.DownloadRepository - downloadFiles *database.DownloadFileRepository - albumReleases *database.AlbumReleaseRepository - trackReleases *database.TrackReleaseRepository -} - -func NewReleaseAnalyzer(db *database.DB) *ReleaseAnalyzer { - return &ReleaseAnalyzer{ - downloads: database.NewDownloadRepository(db.Pool), - downloadFiles: database.NewDownloadFileRepository(db.Pool), - albumReleases: database.NewAlbumReleaseRepository(db.Pool), - trackReleases: database.NewTrackReleaseRepository(db.Pool), - } -} - -func (a *ReleaseAnalyzer) Analyze(ctx context.Context, downloadID string, contentPath string) (*database.AlbumRelease, []*database.TrackRelease, error) { - download, err := a.downloads.GetByID(ctx, downloadID) - if err != nil { - return nil, nil, fmt.Errorf("getting download: %w", err) - } - - files, err := a.downloadFiles.GetByDownloadID(ctx, downloadID) - if err != nil || len(files) == 0 { - log.Info().Str("download_id", downloadID).Msg("no download files in DB, scanning filesystem") - scanned, scanErr := ScanAndHashFiles(contentPath) - if scanErr != nil { - return nil, nil, fmt.Errorf("scanning files: %w", scanErr) - } - for _, f := range scanned { - f.DownloadID = downloadID - } - if err := a.downloadFiles.CreateBatch(ctx, scanned); err != nil { - return nil, nil, fmt.Errorf("persisting scanned files: %w", err) - } - files = scanned - } - - var audioFiles []*database.DownloadFile - var hasCoverArt, hasCueSheet, hasRipLog bool - for _, f := range files { - if audioExtensions["."+f.FileType] { - audioFiles = append(audioFiles, f) - } - switch f.FileType { - case "jpg", "jpeg", "png", "gif", "webp": - hasCoverArt = true - case "cue": - hasCueSheet = true - case "log": - hasRipLog = true - } - } - - if len(audioFiles) == 0 { - return nil, nil, fmt.Errorf("no audio files found for download %s", downloadID) - } - - var trackReleases []*database.TrackRelease - var totalSize int64 - var totalDuration int - formatCounts := make(map[string]int) - var firstBitDepth, firstSampleRate, firstChannels int - var firstIsLossless bool - - for i, f := range audioFiles { - fullPath := filepath.Join(contentPath, f.FilePath) - info, err := audio.Analyze(fullPath) - if err != nil { - log.Warn().Err(err).Str("path", f.FilePath).Msg("failed to analyze audio file") - info = &audio.TrackInfo{ - Format: strings.ToUpper(f.FileType), - } - } - - if i == 0 { - firstBitDepth = info.BitDepth - firstSampleRate = info.SampleRate - firstChannels = info.Channels - firstIsLossless = info.IsLossless - } - - formatCounts[info.Format]++ - totalSize += f.FileSize - totalDuration += info.DurationMs - - trackNum := extractTrackNumber(f.FilePath) - title := extractTitle(f.FilePath) - - tr := &database.TrackRelease{ - Title: title, - TrackNumber: trackNum, - DiscNumber: 1, - Format: info.Format, - Channels: info.Channels, - FileSize: f.FileSize, - FilePath: f.FilePath, - } - if info.DurationMs > 0 { - dur := info.DurationMs - tr.DurationMs = &dur - } - if info.BitDepth > 0 { - bd := info.BitDepth - tr.BitDepth = &bd - } - if info.SampleRate > 0 { - sr := info.SampleRate - tr.SampleRate = &sr - } - if info.BitrateKbps > 0 { - br := info.BitrateKbps - tr.BitrateKbps = &br - } - trackReleases = append(trackReleases, tr) - } - - dominantFormat := "" - maxCount := 0 - for format, count := range formatCounts { - if count > maxCount { - dominantFormat = format - maxCount = count - } - } - - var source *string - if hasRipLog { - s := "CD" - source = &s - } - - release := &database.AlbumRelease{ - AlbumID: download.AlbumID, - DownloadID: downloadID, - Format: dominantFormat, - Channels: firstChannels, - IsLossless: firstIsLossless, - Source: source, - TotalSize: totalSize, - TotalDurationMs: totalDuration, - TrackCount: len(audioFiles), - HasCoverArt: hasCoverArt, - HasCueSheet: hasCueSheet, - HasRipLog: hasRipLog, - Path: contentPath, - } - if firstBitDepth > 0 { - release.BitDepth = &firstBitDepth - } - if firstSampleRate > 0 { - release.SampleRate = &firstSampleRate - } - - return release, trackReleases, nil -} - -func (a *ReleaseAnalyzer) AnalyzeAndPersist(ctx context.Context, downloadID string, contentPath string) (*database.AlbumRelease, []*database.TrackRelease, error) { - release, trackReleases, err := a.Analyze(ctx, downloadID, contentPath) - if err != nil { - return nil, nil, err - } - - if err := a.albumReleases.DeleteByDownloadID(ctx, downloadID); err != nil { - log.Warn().Err(err).Str("download_id", downloadID).Msg("failed to delete existing album release") - } - - if err := a.albumReleases.Create(ctx, release); err != nil { - return nil, nil, fmt.Errorf("creating album release: %w", err) - } - - for _, tr := range trackReleases { - tr.AlbumReleaseID = release.ID - } - if err := a.trackReleases.CreateBatch(ctx, trackReleases); err != nil { - return nil, nil, fmt.Errorf("creating track releases: %w", err) - } - - return release, trackReleases, nil -} - -func extractTrackNumber(filePath string) int { - base := filepath.Base(filePath) - matches := trackNumberRegex.FindStringSubmatch(base) - if len(matches) >= 2 { - var num int - fmt.Sscanf(matches[1], "%d", &num) - return num - } - return 0 -} - -func extractTitle(filePath string) string { - base := filepath.Base(filePath) - ext := filepath.Ext(base) - name := strings.TrimSuffix(base, ext) - name = trackNumberRegex.ReplaceAllString(name, "") - return strings.TrimSpace(name) -} - -func IsAudioExtension(ext string) bool { - return audioExtensions[ext] -} - -func ScanAndHashFiles(rootPath string) ([]*database.DownloadFile, error) { - var files []*database.DownloadFile - - err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error { - if err != nil || info.IsDir() { - return err - } - - ext := strings.ToLower(filepath.Ext(path)) - relPath, _ := filepath.Rel(rootPath, path) - - fileType := strings.TrimPrefix(ext, ".") - if fileType == "" { - return nil - } - - df := &database.DownloadFile{ - FilePath: relPath, - FileSize: info.Size(), - FileType: fileType, - } - - if IsAudioExtension(ext) || ext == ".cue" || ext == ".log" { - hash, err := hashFile(path) - if err != nil { - log.Warn().Err(err).Str("path", path).Msg("failed to hash file") - } else { - df.SHA256Hash = hash - now := time.Now() - df.VerifiedAt = &now - } - } - - files = append(files, df) - return nil - }) - - return files, err -} - -func hashFile(path string) (string, error) { - f, err := os.Open(path) - if err != nil { - return "", fmt.Errorf("opening file: %w", err) - } - defer f.Close() - - h := sha256.New() - if _, err := io.Copy(h, f); err != nil { - return "", fmt.Errorf("hashing file: %w", err) - } - - return hex.EncodeToString(h.Sum(nil)), nil -} diff --git a/internal/audio/analyzer.go b/internal/audio/analyzer.go deleted file mode 100644 index 02a9258..0000000 --- a/internal/audio/analyzer.go +++ /dev/null @@ -1,35 +0,0 @@ -package audio - -import ( - "fmt" - "path/filepath" - "strings" -) - -type TrackInfo struct { - Format string - BitDepth int - SampleRate int - Channels int - DurationMs int - BitrateKbps int - IsLossless bool -} - -func Analyze(filePath string) (*TrackInfo, error) { - ext := strings.ToLower(filepath.Ext(filePath)) - - switch ext { - case ".flac": - return analyzeFLAC(filePath) - case ".mp3": - return analyzeMP3(filePath) - case ".aac", ".m4a", ".ogg", ".wav", ".ape", ".wv", ".alac": - return &TrackInfo{ - Format: strings.ToUpper(strings.TrimPrefix(ext, ".")), - IsLossless: ext == ".wav" || ext == ".ape" || ext == ".wv" || ext == ".alac", - }, nil - default: - return nil, fmt.Errorf("unsupported audio format: %s", ext) - } -} diff --git a/internal/audio/flac.go b/internal/audio/flac.go deleted file mode 100644 index cb5dab2..0000000 --- a/internal/audio/flac.go +++ /dev/null @@ -1,27 +0,0 @@ -package audio - -import ( - "fmt" - - "github.com/mewkiz/flac" -) - -func analyzeFLAC(filePath string) (*TrackInfo, error) { - stream, err := flac.ParseFile(filePath) - if err != nil { - return nil, fmt.Errorf("parsing FLAC: %w", err) - } - defer stream.Close() - - info := stream.Info - durationMs := int(info.NSamples * 1000 / uint64(info.SampleRate)) - - return &TrackInfo{ - Format: "FLAC", - BitDepth: int(info.BitsPerSample), - SampleRate: int(info.SampleRate), - Channels: int(info.NChannels), - DurationMs: durationMs, - IsLossless: true, - }, nil -} diff --git a/internal/audio/mp3.go b/internal/audio/mp3.go deleted file mode 100644 index dad0287..0000000 --- a/internal/audio/mp3.go +++ /dev/null @@ -1,54 +0,0 @@ -package audio - -import ( - "fmt" - "os" - "time" - - "github.com/tcolgate/mp3" -) - -func analyzeMP3(filePath string) (*TrackInfo, error) { - f, err := os.Open(filePath) - if err != nil { - return nil, fmt.Errorf("opening MP3: %w", err) - } - defer f.Close() - - decoder := mp3.NewDecoder(f) - var frame mp3.Frame - var skipped int - var totalDuration time.Duration - var sampleRate, channels, bitrate int - var frameCount int - - for { - err := decoder.Decode(&frame, &skipped) - if err != nil { - break - } - if frameCount == 0 { - sampleRate = int(frame.Header().SampleRate()) - channels = channelCount(frame.Header().ChannelMode()) - bitrate = int(frame.Header().BitRate()) / 1000 - } - totalDuration += frame.Duration() - frameCount++ - } - - return &TrackInfo{ - Format: "MP3", - SampleRate: sampleRate, - Channels: channels, - DurationMs: int(totalDuration.Milliseconds()), - BitrateKbps: bitrate, - IsLossless: false, - }, nil -} - -func channelCount(mode mp3.FrameChannelMode) int { - if mode == mp3.SingleChannel { - return 1 - } - return 2 -} diff --git a/internal/config/config.go b/internal/config/config.go deleted file mode 100644 index 942ed7f..0000000 --- a/internal/config/config.go +++ /dev/null @@ -1,85 +0,0 @@ -package config - -import ( - "fmt" - "time" -) - -const ( - IndexerTypeJackett IndexerType = "jackett" -) - -const ( - TorrentClientQbittorrent TorrentClientType = "qbittorrent" -) - -type IndexerType string -type TorrentClientType string - -type Config struct { - App struct { - Host string `yaml:"host"` - Port string `yaml:"port"` - } `yaml:"app"` - - Database struct { - URL string `yaml:"url"` - } `yaml:"database"` - - Indexer struct { - Url string `yaml:"url"` - Port string `yaml:"port"` - Type IndexerType `yaml:"type"` - ApiKey string `yaml:"api_key"` - Cache CacheConfig `yaml:"cache"` - } `yaml:"indexer"` - - Torrent struct { - ClientType TorrentClientType `yaml:"client_type"` - Url string `yaml:"url"` - Username string `yaml:"username"` - Password string `yaml:"password"` - ContainerName string `yaml:"container_name"` - } `yaml:"torrent"` - - Metadata struct { - Endpoint string `yaml:"endpoint"` - } `yaml:"metadata"` - - MusicFS struct { - Enabled bool `yaml:"enabled"` - Endpoint string `yaml:"endpoint"` - OriginID string `yaml:"origin_id"` - OriginRoot string `yaml:"origin_root"` - TimeoutSeconds int `yaml:"timeout_seconds"` - } `yaml:"musicfs"` -} - -type CacheConfig struct { - Enabled bool `yaml:"enabled"` - RefreshInterval time.Duration `yaml:"refresh_interval"` - TTL time.Duration `yaml:"ttl"` -} - -func (t *IndexerType) UnmarshalYAML(unmarshal func(any) error) error { - var value string - if err := unmarshal(&value); err != nil { - return err - } - - switch IndexerType(value) { - case IndexerTypeJackett: - *t = IndexerType(value) - return nil - default: - return fmt.Errorf("unknown indexer type: %s", value) - } -} - -func NewConfig() *Config { - config := Config{} - config.App.Host = "localhost" - config.App.Port = "8080" - - return &config -} diff --git a/internal/database/album_event_repository.go b/internal/database/album_event_repository.go deleted file mode 100644 index 1322807..0000000 --- a/internal/database/album_event_repository.go +++ /dev/null @@ -1,116 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5/pgxpool" -) - -type AlbumEvent struct { - ID string - Seq int64 - WorkflowRunID string - AlbumID string - EventType string - Step string - Message string - DataJSON []byte - CreatedAt time.Time -} - -type AlbumEventRepository struct { - pool *pgxpool.Pool -} - -func NewAlbumEventRepository(pool *pgxpool.Pool) *AlbumEventRepository { - return &AlbumEventRepository{pool: pool} -} - -func (r *AlbumEventRepository) Create(ctx context.Context, event *AlbumEvent) error { - err := r.pool.QueryRow(ctx, - `INSERT INTO album_events (workflow_run_id, album_id, event_type, step, message, data_json) - VALUES ($1, $2, $3, $4, $5, $6) - RETURNING id, seq, created_at`, - event.WorkflowRunID, event.AlbumID, event.EventType, event.Step, event.Message, event.DataJSON, - ).Scan(&event.ID, &event.Seq, &event.CreatedAt) - if err != nil { - return fmt.Errorf("creating album event: %w", err) - } - return nil -} - -func (r *AlbumEventRepository) GetByWorkflowRun(ctx context.Context, workflowRunID string) ([]*AlbumEvent, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, seq, workflow_run_id, album_id, event_type, step, message, data_json, created_at - FROM album_events WHERE workflow_run_id = $1 ORDER BY seq`, workflowRunID, - ) - if err != nil { - return nil, fmt.Errorf("listing album events by workflow run: %w", err) - } - defer rows.Close() - - var events []*AlbumEvent - for rows.Next() { - event := &AlbumEvent{} - if err := rows.Scan(&event.ID, &event.Seq, &event.WorkflowRunID, &event.AlbumID, &event.EventType, &event.Step, &event.Message, &event.DataJSON, &event.CreatedAt); err != nil { - return nil, fmt.Errorf("scanning album event: %w", err) - } - events = append(events, event) - } - return events, nil -} - -func (r *AlbumEventRepository) GetByAlbum(ctx context.Context, albumID string, afterSeq int64, limit int) ([]*AlbumEvent, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, seq, workflow_run_id, album_id, event_type, step, message, data_json, created_at - FROM album_events WHERE album_id = $1 AND seq > $2 ORDER BY seq LIMIT $3`, albumID, afterSeq, limit, - ) - if err != nil { - return nil, fmt.Errorf("listing album events by album: %w", err) - } - defer rows.Close() - - var events []*AlbumEvent - for rows.Next() { - event := &AlbumEvent{} - if err := rows.Scan(&event.ID, &event.Seq, &event.WorkflowRunID, &event.AlbumID, &event.EventType, &event.Step, &event.Message, &event.DataJSON, &event.CreatedAt); err != nil { - return nil, fmt.Errorf("scanning album event: %w", err) - } - events = append(events, event) - } - return events, nil -} - -func (r *AlbumEventRepository) GetLatestSeq(ctx context.Context) (int64, error) { - var seq int64 - err := r.pool.QueryRow(ctx, - `SELECT COALESCE(MAX(seq), 0) FROM album_events`, - ).Scan(&seq) - if err != nil { - return 0, fmt.Errorf("getting latest album event seq: %w", err) - } - return seq, nil -} - -func (r *AlbumEventRepository) GetAfterSeq(ctx context.Context, afterSeq int64) ([]*AlbumEvent, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, seq, workflow_run_id, album_id, event_type, step, message, data_json, created_at - FROM album_events WHERE seq > $1 ORDER BY seq LIMIT 1000`, afterSeq, - ) - if err != nil { - return nil, fmt.Errorf("listing album events after seq: %w", err) - } - defer rows.Close() - - var events []*AlbumEvent - for rows.Next() { - event := &AlbumEvent{} - if err := rows.Scan(&event.ID, &event.Seq, &event.WorkflowRunID, &event.AlbumID, &event.EventType, &event.Step, &event.Message, &event.DataJSON, &event.CreatedAt); err != nil { - return nil, fmt.Errorf("scanning album event: %w", err) - } - events = append(events, event) - } - return events, nil -} diff --git a/internal/database/album_release_repository.go b/internal/database/album_release_repository.go deleted file mode 100644 index 641c745..0000000 --- a/internal/database/album_release_repository.go +++ /dev/null @@ -1,91 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5/pgxpool" -) - -type AlbumRelease struct { - ID string - AlbumID string - DownloadID string - Format string - BitDepth *int - SampleRate *int - Channels int - IsLossless bool - Source *string - TotalSize int64 - TotalDurationMs int - TrackCount int - HasCoverArt bool - HasCueSheet bool - HasRipLog bool - Path string - CreatedAt time.Time -} - -type AlbumReleaseRepository struct { - pool *pgxpool.Pool -} - -func NewAlbumReleaseRepository(pool *pgxpool.Pool) *AlbumReleaseRepository { - return &AlbumReleaseRepository{pool: pool} -} - -func (r *AlbumReleaseRepository) Create(ctx context.Context, ar *AlbumRelease) error { - err := r.pool.QueryRow(ctx, - `INSERT INTO album_releases (album_id, download_id, format, bit_depth, sample_rate, channels, is_lossless, source, total_size, total_duration_ms, track_count, has_cover_art, has_cue_sheet, has_rip_log, path) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) - RETURNING id, created_at`, - ar.AlbumID, ar.DownloadID, ar.Format, ar.BitDepth, ar.SampleRate, ar.Channels, ar.IsLossless, ar.Source, ar.TotalSize, ar.TotalDurationMs, ar.TrackCount, ar.HasCoverArt, ar.HasCueSheet, ar.HasRipLog, ar.Path, - ).Scan(&ar.ID, &ar.CreatedAt) - if err != nil { - return fmt.Errorf("creating album release: %w", err) - } - return nil -} - -func (r *AlbumReleaseRepository) GetByAlbumID(ctx context.Context, albumID string) ([]*AlbumRelease, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, album_id, download_id, format, bit_depth, sample_rate, channels, is_lossless, source, total_size, total_duration_ms, track_count, has_cover_art, has_cue_sheet, has_rip_log, path, created_at - FROM album_releases WHERE album_id = $1 ORDER BY created_at DESC`, albumID, - ) - if err != nil { - return nil, fmt.Errorf("listing album releases: %w", err) - } - defer rows.Close() - - var releases []*AlbumRelease - for rows.Next() { - ar := &AlbumRelease{} - if err := rows.Scan(&ar.ID, &ar.AlbumID, &ar.DownloadID, &ar.Format, &ar.BitDepth, &ar.SampleRate, &ar.Channels, &ar.IsLossless, &ar.Source, &ar.TotalSize, &ar.TotalDurationMs, &ar.TrackCount, &ar.HasCoverArt, &ar.HasCueSheet, &ar.HasRipLog, &ar.Path, &ar.CreatedAt); err != nil { - return nil, fmt.Errorf("scanning album release: %w", err) - } - releases = append(releases, ar) - } - return releases, nil -} - -func (r *AlbumReleaseRepository) GetByDownloadID(ctx context.Context, downloadID string) (*AlbumRelease, error) { - ar := &AlbumRelease{} - err := r.pool.QueryRow(ctx, - `SELECT id, album_id, download_id, format, bit_depth, sample_rate, channels, is_lossless, source, total_size, total_duration_ms, track_count, has_cover_art, has_cue_sheet, has_rip_log, path, created_at - FROM album_releases WHERE download_id = $1`, downloadID, - ).Scan(&ar.ID, &ar.AlbumID, &ar.DownloadID, &ar.Format, &ar.BitDepth, &ar.SampleRate, &ar.Channels, &ar.IsLossless, &ar.Source, &ar.TotalSize, &ar.TotalDurationMs, &ar.TrackCount, &ar.HasCoverArt, &ar.HasCueSheet, &ar.HasRipLog, &ar.Path, &ar.CreatedAt) - if err != nil { - return nil, fmt.Errorf("getting album release by download: %w", err) - } - return ar, nil -} - -func (r *AlbumReleaseRepository) DeleteByDownloadID(ctx context.Context, downloadID string) error { - _, err := r.pool.Exec(ctx, `DELETE FROM album_releases WHERE download_id = $1`, downloadID) - if err != nil { - return fmt.Errorf("deleting album release by download: %w", err) - } - return nil -} diff --git a/internal/database/album_repository.go b/internal/database/album_repository.go deleted file mode 100644 index 78f18ae..0000000 --- a/internal/database/album_repository.go +++ /dev/null @@ -1,178 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5" - "github.com/jackc/pgx/v5/pgxpool" -) - -type Album struct { - ID string - ExternalID string - ArtistID string - Title string - AlbumType string - ReleaseDate *time.Time - TotalTracks int - TotalDiscs int - Label string - Genres []string - CoverURL string - MonitorState MonitorState - CreatedAt time.Time - UpdatedAt time.Time -} - -type AlbumRepository struct { - pool *pgxpool.Pool -} - -func NewAlbumRepository(pool *pgxpool.Pool) *AlbumRepository { - return &AlbumRepository{pool: pool} -} - -func (r *AlbumRepository) Create(ctx context.Context, a *Album) error { - _, err := r.pool.Exec(ctx, - `INSERT INTO albums (external_id, artist_id, title, album_type, release_date, total_tracks, total_discs, label, genres, cover_url, monitor_state) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) - ON CONFLICT (external_id) DO UPDATE SET - title = EXCLUDED.title, - album_type = EXCLUDED.album_type, - release_date = EXCLUDED.release_date, - total_tracks = EXCLUDED.total_tracks, - total_discs = EXCLUDED.total_discs, - label = EXCLUDED.label, - genres = EXCLUDED.genres, - cover_url = EXCLUDED.cover_url, - monitor_state = CASE - WHEN albums.monitor_state = 'excluded' THEN albums.monitor_state - WHEN albums.monitor_state = 'monitored' THEN albums.monitor_state - ELSE EXCLUDED.monitor_state - END, - updated_at = NOW()`, - a.ExternalID, a.ArtistID, a.Title, a.AlbumType, a.ReleaseDate, a.TotalTracks, a.TotalDiscs, a.Label, a.Genres, a.CoverURL, a.MonitorState, - ) - if err != nil { - return fmt.Errorf("creating album: %w", err) - } - return nil -} - -func (r *AlbumRepository) CreateBatch(ctx context.Context, albums []*Album) error { - if len(albums) == 0 { - return nil - } - - batch := &pgx.Batch{} - for _, a := range albums { - batch.Queue( - `INSERT INTO albums (external_id, artist_id, title, album_type, release_date, total_tracks, total_discs, label, genres, cover_url, monitor_state) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) - ON CONFLICT (external_id) DO UPDATE SET - title = EXCLUDED.title, - album_type = EXCLUDED.album_type, - release_date = EXCLUDED.release_date, - total_tracks = EXCLUDED.total_tracks, - total_discs = EXCLUDED.total_discs, - label = EXCLUDED.label, - genres = EXCLUDED.genres, - cover_url = EXCLUDED.cover_url, - monitor_state = CASE - WHEN albums.monitor_state = 'excluded' THEN albums.monitor_state - WHEN albums.monitor_state = 'monitored' THEN albums.monitor_state - ELSE EXCLUDED.monitor_state - END, - updated_at = NOW()`, - a.ExternalID, a.ArtistID, a.Title, a.AlbumType, a.ReleaseDate, a.TotalTracks, a.TotalDiscs, a.Label, a.Genres, a.CoverURL, a.MonitorState, - ) - } - - results := r.pool.SendBatch(ctx, batch) - defer results.Close() - - for range albums { - if _, err := results.Exec(); err != nil { - return fmt.Errorf("batch creating album: %w", err) - } - } - return nil -} - -func (r *AlbumRepository) GetByExternalID(ctx context.Context, externalID string) (*Album, error) { - a := &Album{} - err := r.pool.QueryRow(ctx, - `SELECT id, external_id, artist_id, title, album_type, release_date, total_tracks, total_discs, label, genres, cover_url, monitor_state, created_at, updated_at - FROM albums WHERE external_id = $1`, externalID, - ).Scan(&a.ID, &a.ExternalID, &a.ArtistID, &a.Title, &a.AlbumType, &a.ReleaseDate, &a.TotalTracks, &a.TotalDiscs, &a.Label, &a.Genres, &a.CoverURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting album: %w", err) - } - return a, nil -} - -func (r *AlbumRepository) GetByID(ctx context.Context, id string) (*Album, error) { - a := &Album{} - err := r.pool.QueryRow(ctx, - `SELECT id, external_id, artist_id, title, album_type, release_date, total_tracks, total_discs, label, genres, cover_url, monitor_state, created_at, updated_at - FROM albums WHERE id = $1`, id, - ).Scan(&a.ID, &a.ExternalID, &a.ArtistID, &a.Title, &a.AlbumType, &a.ReleaseDate, &a.TotalTracks, &a.TotalDiscs, &a.Label, &a.Genres, &a.CoverURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting album: %w", err) - } - return a, nil -} - -func (r *AlbumRepository) GetByArtistID(ctx context.Context, artistID string) ([]*Album, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, external_id, artist_id, title, album_type, release_date, total_tracks, total_discs, label, genres, cover_url, monitor_state, created_at, updated_at - FROM albums WHERE artist_id = $1 ORDER BY release_date DESC`, artistID, - ) - if err != nil { - return nil, fmt.Errorf("listing albums: %w", err) - } - defer rows.Close() - - var albums []*Album - for rows.Next() { - a := &Album{} - if err := rows.Scan(&a.ID, &a.ExternalID, &a.ArtistID, &a.Title, &a.AlbumType, &a.ReleaseDate, &a.TotalTracks, &a.TotalDiscs, &a.Label, &a.Genres, &a.CoverURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt); err != nil { - return nil, fmt.Errorf("scanning album: %w", err) - } - albums = append(albums, a) - } - return albums, nil -} - -func (r *AlbumRepository) GetMonitored(ctx context.Context) ([]*Album, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, external_id, artist_id, title, album_type, release_date, total_tracks, total_discs, label, genres, cover_url, monitor_state, created_at, updated_at - FROM albums WHERE monitor_state = 'monitored' ORDER BY release_date DESC`, - ) - if err != nil { - return nil, fmt.Errorf("listing monitored albums: %w", err) - } - defer rows.Close() - - var albums []*Album - for rows.Next() { - a := &Album{} - if err := rows.Scan(&a.ID, &a.ExternalID, &a.ArtistID, &a.Title, &a.AlbumType, &a.ReleaseDate, &a.TotalTracks, &a.TotalDiscs, &a.Label, &a.Genres, &a.CoverURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt); err != nil { - return nil, fmt.Errorf("scanning album: %w", err) - } - albums = append(albums, a) - } - return albums, nil -} - -func (r *AlbumRepository) SetMonitorState(ctx context.Context, id string, state MonitorState) error { - _, err := r.pool.Exec(ctx, - `UPDATE albums SET monitor_state = $1, updated_at = NOW() WHERE id = $2`, state, id, - ) - if err != nil { - return fmt.Errorf("updating monitor state: %w", err) - } - return nil -} diff --git a/internal/database/artist_repository.go b/internal/database/artist_repository.go deleted file mode 100644 index c0ea3b4..0000000 --- a/internal/database/artist_repository.go +++ /dev/null @@ -1,100 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5/pgxpool" -) - -type Artist struct { - ID string - ExternalID string - Name string - ArtistType string - Country string - Genres []string - ImageURL string - MonitorState MonitorState - CreatedAt time.Time - UpdatedAt time.Time -} - -type ArtistRepository struct { - pool *pgxpool.Pool -} - -func NewArtistRepository(pool *pgxpool.Pool) *ArtistRepository { - return &ArtistRepository{pool: pool} -} - -func (r *ArtistRepository) Create(ctx context.Context, a *Artist) error { - _, err := r.pool.Exec(ctx, - `INSERT INTO artists (external_id, name, artist_type, country, genres, image_url, monitor_state) - VALUES ($1, $2, $3, $4, $5, $6, $7) - ON CONFLICT (external_id) DO UPDATE SET - name = EXCLUDED.name, - artist_type = EXCLUDED.artist_type, - country = EXCLUDED.country, - genres = EXCLUDED.genres, - image_url = EXCLUDED.image_url, - monitor_state = CASE - WHEN artists.monitor_state = 'excluded' THEN artists.monitor_state - WHEN artists.monitor_state = 'monitored' THEN artists.monitor_state - ELSE EXCLUDED.monitor_state - END, - updated_at = NOW() - RETURNING id, created_at, updated_at`, - a.ExternalID, a.Name, a.ArtistType, a.Country, a.Genres, a.ImageURL, a.MonitorState, - ) - if err != nil { - return fmt.Errorf("creating artist: %w", err) - } - return nil -} - -func (r *ArtistRepository) GetByExternalID(ctx context.Context, externalID string) (*Artist, error) { - a := &Artist{} - err := r.pool.QueryRow(ctx, - `SELECT id, external_id, name, artist_type, country, genres, image_url, monitor_state, created_at, updated_at - FROM artists WHERE external_id = $1`, externalID, - ).Scan(&a.ID, &a.ExternalID, &a.Name, &a.ArtistType, &a.Country, &a.Genres, &a.ImageURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting artist: %w", err) - } - return a, nil -} - -func (r *ArtistRepository) GetAll(ctx context.Context) ([]*Artist, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, external_id, name, artist_type, country, genres, image_url, monitor_state, created_at, updated_at - FROM artists ORDER BY name ASC`, - ) - if err != nil { - return nil, fmt.Errorf("listing artists: %w", err) - } - defer rows.Close() - - var artists []*Artist - for rows.Next() { - a := &Artist{} - if err := rows.Scan(&a.ID, &a.ExternalID, &a.Name, &a.ArtistType, &a.Country, &a.Genres, &a.ImageURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt); err != nil { - return nil, fmt.Errorf("scanning artist: %w", err) - } - artists = append(artists, a) - } - return artists, nil -} - -func (r *ArtistRepository) GetByID(ctx context.Context, id string) (*Artist, error) { - a := &Artist{} - err := r.pool.QueryRow(ctx, - `SELECT id, external_id, name, artist_type, country, genres, image_url, monitor_state, created_at, updated_at - FROM artists WHERE id = $1`, id, - ).Scan(&a.ID, &a.ExternalID, &a.Name, &a.ArtistType, &a.Country, &a.Genres, &a.ImageURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting artist: %w", err) - } - return a, nil -} diff --git a/internal/database/db.go b/internal/database/db.go deleted file mode 100644 index 4cd7e9a..0000000 --- a/internal/database/db.go +++ /dev/null @@ -1,40 +0,0 @@ -package database - -import ( - "context" - "fmt" - - "github.com/jackc/pgx/v5/pgxpool" - "github.com/rs/zerolog/log" -) - -type MonitorState string - -const ( - Monitored MonitorState = "monitored" - Unmonitored MonitorState = "unmonitored" - Excluded MonitorState = "excluded" -) - -type DB struct { - Pool *pgxpool.Pool -} - -func New(ctx context.Context, databaseURL string) (*DB, error) { - pool, err := pgxpool.New(ctx, databaseURL) - if err != nil { - return nil, fmt.Errorf("connecting to database: %w", err) - } - - if err := pool.Ping(ctx); err != nil { - return nil, fmt.Errorf("pinging database: %w", err) - } - - log.Info().Str("url", databaseURL).Msg("database connected") - - return &DB{Pool: pool}, nil -} - -func (db *DB) Close() { - db.Pool.Close() -} diff --git a/internal/database/download_file_repository.go b/internal/database/download_file_repository.go deleted file mode 100644 index b7f4ac8..0000000 --- a/internal/database/download_file_repository.go +++ /dev/null @@ -1,104 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5/pgxpool" -) - -type DownloadFile struct { - ID string - DownloadID string - TrackID *string - FilePath string - FileSize int64 - FileType string - SHA256Hash string - VerifiedAt *time.Time - CreatedAt time.Time -} - -type DownloadFileRepository struct { - pool *pgxpool.Pool -} - -func NewDownloadFileRepository(pool *pgxpool.Pool) *DownloadFileRepository { - return &DownloadFileRepository{pool: pool} -} - -func (r *DownloadFileRepository) Create(ctx context.Context, f *DownloadFile) error { - err := r.pool.QueryRow(ctx, - `INSERT INTO download_files (download_id, track_id, file_path, file_size, file_type, sha256_hash) - VALUES ($1, $2, $3, $4, $5, $6) - RETURNING id, created_at`, - f.DownloadID, f.TrackID, f.FilePath, f.FileSize, f.FileType, f.SHA256Hash, - ).Scan(&f.ID, &f.CreatedAt) - if err != nil { - return fmt.Errorf("creating download file: %w", err) - } - return nil -} - -func (r *DownloadFileRepository) CreateBatch(ctx context.Context, files []*DownloadFile) error { - for _, f := range files { - if err := r.Create(ctx, f); err != nil { - return err - } - } - return nil -} - -func (r *DownloadFileRepository) GetByDownloadID(ctx context.Context, downloadID string) ([]*DownloadFile, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, download_id, track_id, file_path, file_size, file_type, sha256_hash, verified_at, created_at - FROM download_files WHERE download_id = $1 ORDER BY file_path`, downloadID, - ) - if err != nil { - return nil, fmt.Errorf("listing download files: %w", err) - } - defer rows.Close() - - var files []*DownloadFile - for rows.Next() { - f := &DownloadFile{} - if err := rows.Scan(&f.ID, &f.DownloadID, &f.TrackID, &f.FilePath, &f.FileSize, &f.FileType, &f.SHA256Hash, &f.VerifiedAt, &f.CreatedAt); err != nil { - return nil, fmt.Errorf("scanning download file: %w", err) - } - files = append(files, f) - } - return files, nil -} - -func (r *DownloadFileRepository) SetHash(ctx context.Context, id string, hash string) error { - _, err := r.pool.Exec(ctx, - `UPDATE download_files SET sha256_hash = $1, verified_at = NOW() WHERE id = $2`, hash, id, - ) - if err != nil { - return fmt.Errorf("setting file hash: %w", err) - } - return nil -} - -func (r *DownloadFileRepository) GetUnverified(ctx context.Context) ([]*DownloadFile, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, download_id, track_id, file_path, file_size, file_type, sha256_hash, verified_at, created_at - FROM download_files WHERE sha256_hash IS NULL OR verified_at < NOW() - INTERVAL '30 days' - ORDER BY created_at`, - ) - if err != nil { - return nil, fmt.Errorf("listing unverified files: %w", err) - } - defer rows.Close() - - var files []*DownloadFile - for rows.Next() { - f := &DownloadFile{} - if err := rows.Scan(&f.ID, &f.DownloadID, &f.TrackID, &f.FilePath, &f.FileSize, &f.FileType, &f.SHA256Hash, &f.VerifiedAt, &f.CreatedAt); err != nil { - return nil, fmt.Errorf("scanning download file: %w", err) - } - files = append(files, f) - } - return files, nil -} diff --git a/internal/database/download_repository.go b/internal/database/download_repository.go deleted file mode 100644 index e439e2b..0000000 --- a/internal/database/download_repository.go +++ /dev/null @@ -1,227 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5/pgxpool" -) - -type Download struct { - ID string - TorrentID string - AlbumID string - Format string - Quality string - State string - QbitHash string - SavePath *string - ErrorMessage *string - QueuedAt time.Time - StartedAt *time.Time - CompletedAt *time.Time - CreatedAt time.Time - UpdatedAt time.Time -} - -type DownloadRepository struct { - pool *pgxpool.Pool -} - -func NewDownloadRepository(pool *pgxpool.Pool) *DownloadRepository { - return &DownloadRepository{pool: pool} -} - -func (r *DownloadRepository) Create(ctx context.Context, d *Download) error { - err := r.pool.QueryRow(ctx, - `INSERT INTO downloads (torrent_id, album_id, format, quality, state, qbit_hash, save_path) - VALUES ($1, $2, $3, $4, $5, $6, $7) - RETURNING id, queued_at, created_at, updated_at`, - d.TorrentID, d.AlbumID, d.Format, d.Quality, d.State, d.QbitHash, d.SavePath, - ).Scan(&d.ID, &d.QueuedAt, &d.CreatedAt, &d.UpdatedAt) - if err != nil { - return fmt.Errorf("creating download: %w", err) - } - return nil -} - -func (r *DownloadRepository) UpdateState(ctx context.Context, id string, state string) error { - _, err := r.pool.Exec(ctx, - `UPDATE downloads SET state = $1, updated_at = NOW() WHERE id = $2`, state, id, - ) - if err != nil { - return fmt.Errorf("updating download state: %w", err) - } - return nil -} - -func (r *DownloadRepository) SetStarted(ctx context.Context, id string) error { - _, err := r.pool.Exec(ctx, - `UPDATE downloads SET state = 'downloading', started_at = NOW(), updated_at = NOW() WHERE id = $1`, id, - ) - if err != nil { - return fmt.Errorf("setting download started: %w", err) - } - return nil -} - -func (r *DownloadRepository) SetCompleted(ctx context.Context, id string, savePath string) error { - _, err := r.pool.Exec(ctx, - `UPDATE downloads SET state = 'completed', save_path = $1, completed_at = NOW(), updated_at = NOW() WHERE id = $2`, savePath, id, - ) - if err != nil { - return fmt.Errorf("setting download completed: %w", err) - } - return nil -} - -func (r *DownloadRepository) SetFailed(ctx context.Context, id string, errorMsg string) error { - _, err := r.pool.Exec(ctx, - `UPDATE downloads SET state = 'failed', error_message = $1, updated_at = NOW() WHERE id = $2`, errorMsg, id, - ) - if err != nil { - return fmt.Errorf("setting download failed: %w", err) - } - return nil -} - -func (r *DownloadRepository) SetCancelled(ctx context.Context, id string) error { - _, err := r.pool.Exec(ctx, - `UPDATE downloads SET state = 'cancelled', updated_at = NOW() WHERE id = $1`, id, - ) - if err != nil { - return fmt.Errorf("setting download cancelled: %w", err) - } - return nil -} - -func (r *DownloadRepository) SetCancelledByQbitHash(ctx context.Context, hash string) error { - _, err := r.pool.Exec(ctx, - `UPDATE downloads SET state = 'cancelled', updated_at = NOW() WHERE qbit_hash = $1 AND state NOT IN ('completed', 'failed', 'cancelled')`, hash, - ) - if err != nil { - return fmt.Errorf("setting download cancelled by hash: %w", err) - } - return nil -} - -func (r *DownloadRepository) GetByAlbumID(ctx context.Context, albumID string) ([]*Download, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, torrent_id, album_id, format, quality, state, qbit_hash, save_path, error_message, queued_at, started_at, completed_at, created_at, updated_at - FROM downloads WHERE album_id = $1 ORDER BY created_at DESC`, albumID, - ) - if err != nil { - return nil, fmt.Errorf("listing downloads: %w", err) - } - defer rows.Close() - - var downloads []*Download - for rows.Next() { - d := &Download{} - if err := rows.Scan(&d.ID, &d.TorrentID, &d.AlbumID, &d.Format, &d.Quality, &d.State, &d.QbitHash, &d.SavePath, &d.ErrorMessage, &d.QueuedAt, &d.StartedAt, &d.CompletedAt, &d.CreatedAt, &d.UpdatedAt); err != nil { - return nil, fmt.Errorf("scanning download: %w", err) - } - downloads = append(downloads, d) - } - return downloads, nil -} - -func (r *DownloadRepository) GetActiveByTorrentID(ctx context.Context, torrentID string) (*Download, error) { - d := &Download{} - err := r.pool.QueryRow(ctx, - `SELECT id, torrent_id, album_id, format, quality, state, qbit_hash, save_path, error_message, queued_at, started_at, completed_at, created_at, updated_at - FROM downloads WHERE torrent_id = $1 AND state NOT IN ('failed') - ORDER BY created_at DESC LIMIT 1`, torrentID, - ).Scan(&d.ID, &d.TorrentID, &d.AlbumID, &d.Format, &d.Quality, &d.State, &d.QbitHash, &d.SavePath, &d.ErrorMessage, &d.QueuedAt, &d.StartedAt, &d.CompletedAt, &d.CreatedAt, &d.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting active download by torrent: %w", err) - } - return d, nil -} - -func (r *DownloadRepository) GetActive(ctx context.Context) ([]*Download, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, torrent_id, album_id, format, quality, state, qbit_hash, save_path, error_message, queued_at, started_at, completed_at, created_at, updated_at - FROM downloads WHERE state IN ('pending', 'downloading') ORDER BY created_at`, - ) - if err != nil { - return nil, fmt.Errorf("listing active downloads: %w", err) - } - defer rows.Close() - - var downloads []*Download - for rows.Next() { - d := &Download{} - if err := rows.Scan(&d.ID, &d.TorrentID, &d.AlbumID, &d.Format, &d.Quality, &d.State, &d.QbitHash, &d.SavePath, &d.ErrorMessage, &d.QueuedAt, &d.StartedAt, &d.CompletedAt, &d.CreatedAt, &d.UpdatedAt); err != nil { - return nil, fmt.Errorf("scanning download: %w", err) - } - downloads = append(downloads, d) - } - return downloads, nil -} - -func (r *DownloadRepository) GetByID(ctx context.Context, id string) (*Download, error) { - d := &Download{} - err := r.pool.QueryRow(ctx, - `SELECT id, torrent_id, album_id, format, quality, state, qbit_hash, save_path, error_message, queued_at, started_at, completed_at, created_at, updated_at - FROM downloads WHERE id = $1`, id, - ).Scan(&d.ID, &d.TorrentID, &d.AlbumID, &d.Format, &d.Quality, &d.State, &d.QbitHash, &d.SavePath, &d.ErrorMessage, &d.QueuedAt, &d.StartedAt, &d.CompletedAt, &d.CreatedAt, &d.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting download by id: %w", err) - } - return d, nil -} - -func (r *DownloadRepository) GetLatestCompleted(ctx context.Context, albumID string) (*Download, error) { - d := &Download{} - err := r.pool.QueryRow(ctx, - `SELECT id, torrent_id, album_id, format, quality, state, qbit_hash, save_path, error_message, queued_at, started_at, completed_at, created_at, updated_at - FROM downloads WHERE album_id = $1 AND state = 'completed' - ORDER BY completed_at DESC LIMIT 1`, albumID, - ).Scan(&d.ID, &d.TorrentID, &d.AlbumID, &d.Format, &d.Quality, &d.State, &d.QbitHash, &d.SavePath, &d.ErrorMessage, &d.QueuedAt, &d.StartedAt, &d.CompletedAt, &d.CreatedAt, &d.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting latest completed download: %w", err) - } - return d, nil -} - -func (r *DownloadRepository) GetByAlbumIDs(ctx context.Context, albumIDs []string) (map[string][]*Download, error) { - if len(albumIDs) == 0 { - return nil, nil - } - - rows, err := r.pool.Query(ctx, - `SELECT id, torrent_id, album_id, format, quality, state, qbit_hash, save_path, error_message, queued_at, started_at, completed_at, created_at, updated_at - FROM downloads WHERE album_id = ANY($1) AND state NOT IN ('failed', 'cancelled') - ORDER BY album_id, created_at DESC`, albumIDs, - ) - if err != nil { - return nil, fmt.Errorf("batch listing downloads: %w", err) - } - defer rows.Close() - - result := make(map[string][]*Download, len(albumIDs)) - for rows.Next() { - d := &Download{} - if err := rows.Scan(&d.ID, &d.TorrentID, &d.AlbumID, &d.Format, &d.Quality, &d.State, &d.QbitHash, &d.SavePath, &d.ErrorMessage, &d.QueuedAt, &d.StartedAt, &d.CompletedAt, &d.CreatedAt, &d.UpdatedAt); err != nil { - return nil, fmt.Errorf("scanning download: %w", err) - } - result[d.AlbumID] = append(result[d.AlbumID], d) - } - return result, nil -} - -func (r *DownloadRepository) HasAlbumInQuality(ctx context.Context, albumID string, format string, quality string) (bool, error) { - var exists bool - err := r.pool.QueryRow(ctx, - `SELECT EXISTS( - SELECT 1 FROM downloads - WHERE album_id = $1 AND format = $2 AND quality = $3 AND state IN ('completed', 'seeding') - )`, albumID, format, quality, - ).Scan(&exists) - if err != nil { - return false, fmt.Errorf("checking album quality: %w", err) - } - return exists, nil -} diff --git a/internal/database/torrent_repository.go b/internal/database/torrent_repository.go deleted file mode 100644 index cf56bcd..0000000 --- a/internal/database/torrent_repository.go +++ /dev/null @@ -1,104 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5/pgxpool" -) - -type Torrent struct { - ID string - AlbumID string - InfoHash string - Tracker string - Title string - Format string - Quality string - Source string - BitDepth int - SampleRate int - Seeders int - Peers int - Size int64 - TrackCount int - HasCoverArt bool - HasCueSheet bool - HasRipLog bool - DownloadLink string - TorrentFile []byte - CreatedAt time.Time - UpdatedAt time.Time -} - -type TorrentRepository struct { - pool *pgxpool.Pool -} - -func NewTorrentRepository(pool *pgxpool.Pool) *TorrentRepository { - return &TorrentRepository{pool: pool} -} - -func (r *TorrentRepository) Create(ctx context.Context, t *Torrent) error { - _, err := r.pool.Exec(ctx, - `INSERT INTO torrents (album_id, info_hash, tracker, title, format, quality, source, bit_depth, sample_rate, seeders, peers, size, track_count, has_cover_art, has_cue_sheet, has_rip_log, download_link, torrent_file) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18) - ON CONFLICT (info_hash) DO UPDATE SET - seeders = EXCLUDED.seeders, - peers = EXCLUDED.peers, - updated_at = NOW()`, - t.AlbumID, t.InfoHash, t.Tracker, t.Title, t.Format, t.Quality, t.Source, t.BitDepth, t.SampleRate, t.Seeders, t.Peers, t.Size, t.TrackCount, t.HasCoverArt, t.HasCueSheet, t.HasRipLog, t.DownloadLink, t.TorrentFile, - ) - if err != nil { - return fmt.Errorf("creating torrent: %w", err) - } - return nil -} - -func (r *TorrentRepository) GetByInfoHash(ctx context.Context, infoHash string) (*Torrent, error) { - t := &Torrent{} - err := r.pool.QueryRow(ctx, - `SELECT id, album_id, info_hash, tracker, title, format, quality, source, bit_depth, sample_rate, seeders, peers, size, track_count, has_cover_art, has_cue_sheet, has_rip_log, download_link, torrent_file, created_at, updated_at - FROM torrents WHERE info_hash = $1`, infoHash, - ).Scan(&t.ID, &t.AlbumID, &t.InfoHash, &t.Tracker, &t.Title, &t.Format, &t.Quality, &t.Source, &t.BitDepth, &t.SampleRate, &t.Seeders, &t.Peers, &t.Size, &t.TrackCount, &t.HasCoverArt, &t.HasCueSheet, &t.HasRipLog, &t.DownloadLink, &t.TorrentFile, &t.CreatedAt, &t.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting torrent: %w", err) - } - return t, nil -} - -func (r *TorrentRepository) GetByAlbumID(ctx context.Context, albumID string) ([]*Torrent, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, album_id, info_hash, tracker, title, format, quality, source, bit_depth, sample_rate, seeders, peers, size, track_count, has_cover_art, has_cue_sheet, has_rip_log, download_link, torrent_file, created_at, updated_at - FROM torrents WHERE album_id = $1 ORDER BY seeders DESC`, albumID, - ) - if err != nil { - return nil, fmt.Errorf("listing torrents: %w", err) - } - defer rows.Close() - - var torrents []*Torrent - for rows.Next() { - t := &Torrent{} - if err := rows.Scan(&t.ID, &t.AlbumID, &t.InfoHash, &t.Tracker, &t.Title, &t.Format, &t.Quality, &t.Source, &t.BitDepth, &t.SampleRate, &t.Seeders, &t.Peers, &t.Size, &t.TrackCount, &t.HasCoverArt, &t.HasCueSheet, &t.HasRipLog, &t.DownloadLink, &t.TorrentFile, &t.CreatedAt, &t.UpdatedAt); err != nil { - return nil, fmt.Errorf("scanning torrent: %w", err) - } - torrents = append(torrents, t) - } - return torrents, nil -} - -func (r *TorrentRepository) HasAlbumInFormat(ctx context.Context, albumID string, format string) (bool, error) { - var exists bool - err := r.pool.QueryRow(ctx, - `SELECT EXISTS( - SELECT 1 FROM downloads - WHERE album_id = $1 AND format = $2 AND state IN ('completed', 'seeding') - )`, albumID, format, - ).Scan(&exists) - if err != nil { - return false, fmt.Errorf("checking album format: %w", err) - } - return exists, nil -} diff --git a/internal/database/track_release_repository.go b/internal/database/track_release_repository.go deleted file mode 100644 index 4c03420..0000000 --- a/internal/database/track_release_repository.go +++ /dev/null @@ -1,79 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5/pgxpool" -) - -type TrackRelease struct { - ID string - AlbumReleaseID string - TrackID *string - DownloadFileID *string - Title string - TrackNumber int - DiscNumber int - DurationMs *int - Format string - BitDepth *int - SampleRate *int - Channels int - BitrateKbps *int - FileSize int64 - FilePath string - CreatedAt time.Time -} - -type TrackReleaseRepository struct { - pool *pgxpool.Pool -} - -func NewTrackReleaseRepository(pool *pgxpool.Pool) *TrackReleaseRepository { - return &TrackReleaseRepository{pool: pool} -} - -func (r *TrackReleaseRepository) Create(ctx context.Context, tr *TrackRelease) error { - err := r.pool.QueryRow(ctx, - `INSERT INTO track_releases (album_release_id, track_id, download_file_id, title, track_number, disc_number, duration_ms, format, bit_depth, sample_rate, channels, bitrate_kbps, file_size, file_path) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) - RETURNING id, created_at`, - tr.AlbumReleaseID, tr.TrackID, tr.DownloadFileID, tr.Title, tr.TrackNumber, tr.DiscNumber, tr.DurationMs, tr.Format, tr.BitDepth, tr.SampleRate, tr.Channels, tr.BitrateKbps, tr.FileSize, tr.FilePath, - ).Scan(&tr.ID, &tr.CreatedAt) - if err != nil { - return fmt.Errorf("creating track release: %w", err) - } - return nil -} - -func (r *TrackReleaseRepository) CreateBatch(ctx context.Context, tracks []*TrackRelease) error { - for _, tr := range tracks { - if err := r.Create(ctx, tr); err != nil { - return err - } - } - return nil -} - -func (r *TrackReleaseRepository) GetByAlbumReleaseID(ctx context.Context, albumReleaseID string) ([]*TrackRelease, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, album_release_id, track_id, download_file_id, title, track_number, disc_number, duration_ms, format, bit_depth, sample_rate, channels, bitrate_kbps, file_size, file_path, created_at - FROM track_releases WHERE album_release_id = $1 ORDER BY disc_number, track_number`, albumReleaseID, - ) - if err != nil { - return nil, fmt.Errorf("listing track releases: %w", err) - } - defer rows.Close() - - var tracks []*TrackRelease - for rows.Next() { - tr := &TrackRelease{} - if err := rows.Scan(&tr.ID, &tr.AlbumReleaseID, &tr.TrackID, &tr.DownloadFileID, &tr.Title, &tr.TrackNumber, &tr.DiscNumber, &tr.DurationMs, &tr.Format, &tr.BitDepth, &tr.SampleRate, &tr.Channels, &tr.BitrateKbps, &tr.FileSize, &tr.FilePath, &tr.CreatedAt); err != nil { - return nil, fmt.Errorf("scanning track release: %w", err) - } - tracks = append(tracks, tr) - } - return tracks, nil -} diff --git a/internal/database/track_repository.go b/internal/database/track_repository.go deleted file mode 100644 index 6956b0c..0000000 --- a/internal/database/track_repository.go +++ /dev/null @@ -1,68 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5/pgxpool" -) - -type Track struct { - ID string - ExternalID string - AlbumID string - Title string - DurationMS int - ISRC string - DiscNumber int - TrackNumber int - CreatedAt time.Time -} - -type TrackRepository struct { - pool *pgxpool.Pool -} - -func NewTrackRepository(pool *pgxpool.Pool) *TrackRepository { - return &TrackRepository{pool: pool} -} - -func (r *TrackRepository) Create(ctx context.Context, t *Track) error { - _, err := r.pool.Exec(ctx, - `INSERT INTO tracks (external_id, album_id, title, duration_ms, isrc, disc_number, track_number) - VALUES ($1, $2, $3, $4, $5, $6, $7) - ON CONFLICT (external_id) DO UPDATE SET - title = EXCLUDED.title, - duration_ms = EXCLUDED.duration_ms, - isrc = EXCLUDED.isrc, - disc_number = EXCLUDED.disc_number, - track_number = EXCLUDED.track_number`, - t.ExternalID, t.AlbumID, t.Title, t.DurationMS, t.ISRC, t.DiscNumber, t.TrackNumber, - ) - if err != nil { - return fmt.Errorf("creating track: %w", err) - } - return nil -} - -func (r *TrackRepository) GetByAlbumID(ctx context.Context, albumID string) ([]*Track, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, external_id, album_id, title, duration_ms, isrc, disc_number, track_number, created_at - FROM tracks WHERE album_id = $1 ORDER BY disc_number, track_number`, albumID, - ) - if err != nil { - return nil, fmt.Errorf("listing tracks: %w", err) - } - defer rows.Close() - - var tracks []*Track - for rows.Next() { - t := &Track{} - if err := rows.Scan(&t.ID, &t.ExternalID, &t.AlbumID, &t.Title, &t.DurationMS, &t.ISRC, &t.DiscNumber, &t.TrackNumber, &t.CreatedAt); err != nil { - return nil, fmt.Errorf("scanning track: %w", err) - } - tracks = append(tracks, t) - } - return tracks, nil -} diff --git a/internal/database/workflow_run_repository.go b/internal/database/workflow_run_repository.go deleted file mode 100644 index 286b619..0000000 --- a/internal/database/workflow_run_repository.go +++ /dev/null @@ -1,123 +0,0 @@ -package database - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5" - "github.com/jackc/pgx/v5/pgxpool" -) - -var ErrWorkflowAlreadyRunning = fmt.Errorf("workflow already running for this album and quality") - -type WorkflowRun struct { - ID string - AlbumID string - Quality string - Status string - ErrorMessage *string - StartedAt time.Time - CompletedAt *time.Time - CreatedAt time.Time - UpdatedAt time.Time -} - -type WorkflowRunRepository struct { - pool *pgxpool.Pool -} - -func NewWorkflowRunRepository(pool *pgxpool.Pool) *WorkflowRunRepository { - return &WorkflowRunRepository{pool: pool} -} - -func (r *WorkflowRunRepository) Create(ctx context.Context, run *WorkflowRun) error { - err := r.pool.QueryRow(ctx, - `INSERT INTO workflow_runs (album_id, quality, status) VALUES ($1, $2, 'running') - ON CONFLICT ON CONSTRAINT idx_workflow_runs_active DO NOTHING - RETURNING id, started_at, created_at, updated_at`, - run.AlbumID, run.Quality, - ).Scan(&run.ID, &run.StartedAt, &run.CreatedAt, &run.UpdatedAt) - if err != nil { - if err == pgx.ErrNoRows { - return ErrWorkflowAlreadyRunning - } - return fmt.Errorf("creating workflow run: %w", err) - } - return nil -} - -func (r *WorkflowRunRepository) SetCompleted(ctx context.Context, id string) error { - _, err := r.pool.Exec(ctx, - `UPDATE workflow_runs SET status = 'completed', completed_at = NOW(), updated_at = NOW() WHERE id = $1`, id, - ) - if err != nil { - return fmt.Errorf("setting workflow run completed: %w", err) - } - return nil -} - -func (r *WorkflowRunRepository) SetFailed(ctx context.Context, id string, errorMsg string) error { - _, err := r.pool.Exec(ctx, - `UPDATE workflow_runs SET status = 'failed', error_message = $1, completed_at = NOW(), updated_at = NOW() WHERE id = $2`, errorMsg, id, - ) - if err != nil { - return fmt.Errorf("setting workflow run failed: %w", err) - } - return nil -} - -func (r *WorkflowRunRepository) SetCancelled(ctx context.Context, id string) error { - _, err := r.pool.Exec(ctx, - `UPDATE workflow_runs SET status = 'cancelled', completed_at = NOW(), updated_at = NOW() WHERE id = $1`, id, - ) - if err != nil { - return fmt.Errorf("setting workflow run cancelled: %w", err) - } - return nil -} - -func (r *WorkflowRunRepository) GetByAlbumAndQuality(ctx context.Context, albumID string, quality string) (*WorkflowRun, error) { - run := &WorkflowRun{} - err := r.pool.QueryRow(ctx, - `SELECT id, album_id, quality, status, error_message, started_at, completed_at, created_at, updated_at - FROM workflow_runs WHERE album_id = $1 AND quality = $2 AND status = 'running' LIMIT 1`, albumID, quality, - ).Scan(&run.ID, &run.AlbumID, &run.Quality, &run.Status, &run.ErrorMessage, &run.StartedAt, &run.CompletedAt, &run.CreatedAt, &run.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting workflow run by album and quality: %w", err) - } - return run, nil -} - -func (r *WorkflowRunRepository) GetRunning(ctx context.Context) ([]*WorkflowRun, error) { - rows, err := r.pool.Query(ctx, - `SELECT id, album_id, quality, status, error_message, started_at, completed_at, created_at, updated_at - FROM workflow_runs WHERE status = 'running' ORDER BY started_at`, - ) - if err != nil { - return nil, fmt.Errorf("listing running workflow runs: %w", err) - } - defer rows.Close() - - var runs []*WorkflowRun - for rows.Next() { - run := &WorkflowRun{} - if err := rows.Scan(&run.ID, &run.AlbumID, &run.Quality, &run.Status, &run.ErrorMessage, &run.StartedAt, &run.CompletedAt, &run.CreatedAt, &run.UpdatedAt); err != nil { - return nil, fmt.Errorf("scanning workflow run: %w", err) - } - runs = append(runs, run) - } - return runs, nil -} - -func (r *WorkflowRunRepository) GetByID(ctx context.Context, id string) (*WorkflowRun, error) { - run := &WorkflowRun{} - err := r.pool.QueryRow(ctx, - `SELECT id, album_id, quality, status, error_message, started_at, completed_at, created_at, updated_at - FROM workflow_runs WHERE id = $1`, id, - ).Scan(&run.ID, &run.AlbumID, &run.Quality, &run.Status, &run.ErrorMessage, &run.StartedAt, &run.CompletedAt, &run.CreatedAt, &run.UpdatedAt) - if err != nil { - return nil, fmt.Errorf("getting workflow run by id: %w", err) - } - return run, nil -} diff --git a/internal/event_publisher.go b/internal/event_publisher.go deleted file mode 100644 index 1299f03..0000000 --- a/internal/event_publisher.go +++ /dev/null @@ -1,260 +0,0 @@ -package internal - -import ( - "context" - "encoding/json" - "sync" - - "github.com/rs/zerolog/log" - - pb "homelab.lan/music-agregator/gen/music_agregator/v1" - "homelab.lan/music-agregator/internal/database" - "homelab.lan/music-agregator/internal/eventbus" -) - -type EventPublisher interface { - PublishStatus(ctx context.Context, step pb.MonitorStep, msg string, data interface{}) error - PublishError(ctx context.Context, step pb.MonitorStep, err error, recoverable bool) error - PublishResult(ctx context.Context, result *pb.MonitorAlbumResponse) error - SetAlbumID(albumID string) - SetWorkflowRunID(id string) -} - -type dbEventPublisher struct { - mu sync.Mutex - workflowRunID string - albumID string - quality string - events *database.AlbumEventRepository - bus *eventbus.EventBus - topic string -} - -func newDBEventPublisher(albumID, quality string, events *database.AlbumEventRepository, bus *eventbus.EventBus, topic string) *dbEventPublisher { - return &dbEventPublisher{ - albumID: albumID, - quality: quality, - events: events, - bus: bus, - topic: topic, - } -} - -func (p *dbEventPublisher) SetAlbumID(albumID string) { - p.mu.Lock() - defer p.mu.Unlock() - p.albumID = albumID -} - -func (p *dbEventPublisher) getAlbumID() string { - p.mu.Lock() - defer p.mu.Unlock() - return p.albumID -} - -func (p *dbEventPublisher) SetWorkflowRunID(id string) { - p.mu.Lock() - defer p.mu.Unlock() - p.workflowRunID = id -} - -func (p *dbEventPublisher) getWorkflowRunID() string { - p.mu.Lock() - defer p.mu.Unlock() - return p.workflowRunID -} - -func (p *dbEventPublisher) PublishStatus(ctx context.Context, step pb.MonitorStep, msg string, data interface{}) error { - var dataJSON []byte - if data != nil { - var err error - dataJSON, err = json.Marshal(data) - if err != nil { - log.Warn().Err(err).Msg("failed to marshal status data to JSON") - dataJSON = nil - } - } - - albumID := p.getAlbumID() - workflowRunID := p.getWorkflowRunID() - - var seq int64 - if albumID != "" { - event := &database.AlbumEvent{ - WorkflowRunID: workflowRunID, - AlbumID: albumID, - EventType: "status", - Step: step.String(), - Message: msg, - DataJSON: dataJSON, - } - - if err := p.events.Create(ctx, event); err != nil { - log.Error().Err(err).Msg("failed to persist status event") - } else { - seq = event.Seq - } - } - - p.bus.Publish(p.topic, &eventbus.Event{ - Seq: seq, - WorkflowRunID: workflowRunID, - AlbumID: albumID, - Quality: p.quality, - EventType: "status", - Step: step.String(), - Message: msg, - Data: data, - }) - - return nil -} - -func (p *dbEventPublisher) PublishError(ctx context.Context, step pb.MonitorStep, err error, recoverable bool) error { - albumID := p.getAlbumID() - workflowRunID := p.getWorkflowRunID() - - var seq int64 - if albumID != "" { - event := &database.AlbumEvent{ - WorkflowRunID: workflowRunID, - AlbumID: albumID, - EventType: "error", - Step: step.String(), - Message: err.Error(), - } - - if dbErr := p.events.Create(ctx, event); dbErr != nil { - log.Error().Err(dbErr).Msg("failed to persist error event") - } else { - seq = event.Seq - } - } - - p.bus.Publish(p.topic, &eventbus.Event{ - Seq: seq, - WorkflowRunID: workflowRunID, - AlbumID: albumID, - Quality: p.quality, - EventType: "error", - Step: step.String(), - Message: err.Error(), - Data: map[string]bool{"recoverable": recoverable}, - }) - - return nil -} - -func (p *dbEventPublisher) PublishResult(ctx context.Context, result *pb.MonitorAlbumResponse) error { - var dataJSON []byte - if result != nil { - var err error - dataJSON, err = json.Marshal(result) - if err != nil { - log.Warn().Err(err).Msg("failed to marshal result to JSON") - dataJSON = nil - } - } - - albumID := p.getAlbumID() - workflowRunID := p.getWorkflowRunID() - - var seq int64 - if albumID != "" { - event := &database.AlbumEvent{ - WorkflowRunID: workflowRunID, - AlbumID: albumID, - EventType: "result", - Step: pb.MonitorStep_MONITOR_STEP_COMPLETE.String(), - Message: "workflow completed", - DataJSON: dataJSON, - } - - if err := p.events.Create(ctx, event); err != nil { - log.Error().Err(err).Msg("failed to persist result event") - } else { - seq = event.Seq - } - } - - p.bus.Publish(p.topic, &eventbus.Event{ - Seq: seq, - WorkflowRunID: workflowRunID, - AlbumID: albumID, - Quality: p.quality, - EventType: "result", - Step: pb.MonitorStep_MONITOR_STEP_COMPLETE.String(), - Message: "workflow completed", - Data: result, - }) - - return nil -} - -type streamEventPublisher struct { - *dbEventPublisher - stream pb.MusicAgregatorService_MonitorAlbumStreamServer -} - -func newStreamEventPublisher(db *dbEventPublisher, stream pb.MusicAgregatorService_MonitorAlbumStreamServer) *streamEventPublisher { - return &streamEventPublisher{ - dbEventPublisher: db, - stream: stream, - } -} - -func (p *streamEventPublisher) PublishStatus(ctx context.Context, step pb.MonitorStep, msg string, data interface{}) error { - if err := p.dbEventPublisher.PublishStatus(ctx, step, msg, data); err != nil { - return err - } - - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - status := &pb.StatusUpdate{ - Step: step, - Message: msg, - } - - switch v := data.(type) { - case *pb.StreamAlbumInfo: - status.Data = &pb.StatusUpdate_AlbumInfo{AlbumInfo: v} - case *pb.TorrentList: - status.Data = &pb.StatusUpdate_Torrents{Torrents: v} - case *pb.ReleaseInfo: - status.Data = &pb.StatusUpdate_ReleaseInfo{ReleaseInfo: v} - } - - return p.stream.Send(&pb.MonitorAlbumStreamResponse{ - Message: &pb.MonitorAlbumStreamResponse_Status{Status: status}, - }) -} - -func (p *streamEventPublisher) PublishError(ctx context.Context, step pb.MonitorStep, err error, recoverable bool) error { - if dbErr := p.dbEventPublisher.PublishError(ctx, step, err, recoverable); dbErr != nil { - return dbErr - } - - return p.stream.Send(&pb.MonitorAlbumStreamResponse{ - Message: &pb.MonitorAlbumStreamResponse_Error{ - Error: &pb.ErrorUpdate{ - FailedStep: step, - Message: err.Error(), - Recoverable: recoverable, - }, - }, - }) -} - -func (p *streamEventPublisher) PublishResult(ctx context.Context, result *pb.MonitorAlbumResponse) error { - if err := p.dbEventPublisher.PublishResult(ctx, result); err != nil { - return err - } - - return p.stream.Send(&pb.MonitorAlbumStreamResponse{ - Message: &pb.MonitorAlbumStreamResponse_Result{Result: result}, - }) -} diff --git a/internal/eventbus/bus.go b/internal/eventbus/bus.go deleted file mode 100644 index 7b3bfaf..0000000 --- a/internal/eventbus/bus.go +++ /dev/null @@ -1,116 +0,0 @@ -package eventbus - -import "sync" - -type Event struct { - Seq int64 - WorkflowRunID string - AlbumID string - Quality string - EventType string - Step string - Message string - Data interface{} -} - -type Subscription struct { - Ring *RingBuffer[*Event] - C chan struct{} - done chan struct{} - once sync.Once -} - -type EventBus struct { - mu sync.RWMutex - topics map[string]map[*Subscription]struct{} - global map[*Subscription]struct{} -} - -func New() *EventBus { - return &EventBus{ - topics: make(map[string]map[*Subscription]struct{}), - global: make(map[*Subscription]struct{}), - } -} - -func (b *EventBus) Publish(topic string, event *Event) { - b.mu.RLock() - defer b.mu.RUnlock() - - if subs, ok := b.topics[topic]; ok { - for sub := range subs { - sub.Ring.Push(event) - select { - case sub.C <- struct{}{}: - default: - } - } - } - - for sub := range b.global { - sub.Ring.Push(event) - select { - case sub.C <- struct{}{}: - default: - } - } -} - -func (b *EventBus) Subscribe(topic string) (*Subscription, func()) { - sub := &Subscription{ - Ring: NewRingBuffer[*Event](256), - C: make(chan struct{}, 1), - done: make(chan struct{}), - } - - b.mu.Lock() - if b.topics[topic] == nil { - b.topics[topic] = make(map[*Subscription]struct{}) - } - b.topics[topic][sub] = struct{}{} - b.mu.Unlock() - - cleanup := func() { - sub.once.Do(func() { - b.mu.Lock() - delete(b.topics[topic], sub) - if len(b.topics[topic]) == 0 { - delete(b.topics, topic) - } - b.mu.Unlock() - close(sub.done) - }) - } - - return sub, cleanup -} - -func (b *EventBus) SubscribeGlobal() (*Subscription, func()) { - sub := &Subscription{ - Ring: NewRingBuffer[*Event](256), - C: make(chan struct{}, 1), - done: make(chan struct{}), - } - - b.mu.Lock() - b.global[sub] = struct{}{} - b.mu.Unlock() - - cleanup := func() { - sub.once.Do(func() { - b.mu.Lock() - delete(b.global, sub) - b.mu.Unlock() - close(sub.done) - }) - } - - return sub, cleanup -} - -func (b *EventBus) HasTopic(topic string) bool { - b.mu.RLock() - defer b.mu.RUnlock() - _, ok := b.topics[topic] - return ok -} diff --git a/internal/eventbus/bus_test.go b/internal/eventbus/bus_test.go deleted file mode 100644 index fd71a67..0000000 --- a/internal/eventbus/bus_test.go +++ /dev/null @@ -1,168 +0,0 @@ -package eventbus - -import ( - "sync" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestEventBus_PublishSubscribe(t *testing.T) { - bus := New() - sub, cleanup := bus.Subscribe("test-topic") - defer cleanup() - - event := &Event{Seq: 1, EventType: "status", Message: "hello"} - bus.Publish("test-topic", event) - - got, ok := sub.Ring.Pop() - require.True(t, ok) - assert.Equal(t, event, got) -} - -func TestEventBus_MultipleSubscribers(t *testing.T) { - bus := New() - sub1, cleanup1 := bus.Subscribe("topic") - defer cleanup1() - sub2, cleanup2 := bus.Subscribe("topic") - defer cleanup2() - sub3, cleanup3 := bus.Subscribe("topic") - defer cleanup3() - - event := &Event{Seq: 1, EventType: "status"} - bus.Publish("topic", event) - - got1, ok := sub1.Ring.Pop() - require.True(t, ok) - assert.Equal(t, event, got1) - - got2, ok := sub2.Ring.Pop() - require.True(t, ok) - assert.Equal(t, event, got2) - - got3, ok := sub3.Ring.Pop() - require.True(t, ok) - assert.Equal(t, event, got3) -} - -func TestEventBus_GlobalSubscriber(t *testing.T) { - bus := New() - sub, cleanup := bus.SubscribeGlobal() - defer cleanup() - - bus.Publish("topic-a", &Event{Seq: 1}) - bus.Publish("topic-b", &Event{Seq: 2}) - bus.Publish("topic-c", &Event{Seq: 3}) - - got, ok := sub.Ring.Pop() - require.True(t, ok) - assert.Equal(t, int64(1), got.Seq) - - got, ok = sub.Ring.Pop() - require.True(t, ok) - assert.Equal(t, int64(2), got.Seq) - - got, ok = sub.Ring.Pop() - require.True(t, ok) - assert.Equal(t, int64(3), got.Seq) -} - -func TestEventBus_TopicIsolation(t *testing.T) { - bus := New() - subA, cleanupA := bus.Subscribe("topic-a") - defer cleanupA() - - bus.Publish("topic-b", &Event{Seq: 1}) - - _, ok := subA.Ring.Pop() - assert.False(t, ok) -} - -func TestEventBus_Notification(t *testing.T) { - bus := New() - sub, cleanup := bus.Subscribe("topic") - defer cleanup() - - bus.Publish("topic", &Event{Seq: 1}) - - select { - case <-sub.C: - case <-time.After(100 * time.Millisecond): - t.Fatal("expected notification on channel") - } -} - -func TestEventBus_Unsubscribe(t *testing.T) { - bus := New() - sub, cleanup := bus.Subscribe("topic") - - bus.Publish("topic", &Event{Seq: 1}) - _, ok := sub.Ring.Pop() - require.True(t, ok) - - cleanup() - - bus.Publish("topic", &Event{Seq: 2}) - _, ok = sub.Ring.Pop() - assert.False(t, ok) -} - -func TestEventBus_SlowSubscriber(t *testing.T) { - bus := New() - sub, cleanup := bus.Subscribe("topic") - defer cleanup() - - for i := 0; i < 500; i++ { - bus.Publish("topic", &Event{Seq: int64(i)}) - } - - assert.Equal(t, 256, sub.Ring.Len()) - - first, ok := sub.Ring.Pop() - require.True(t, ok) - assert.Equal(t, int64(244), first.Seq) -} - -func TestEventBus_HasTopic(t *testing.T) { - bus := New() - - assert.False(t, bus.HasTopic("topic")) - - sub, cleanup := bus.Subscribe("topic") - _ = sub - assert.True(t, bus.HasTopic("topic")) - - cleanup() - assert.False(t, bus.HasTopic("topic")) -} - -func TestEventBus_ConcurrentPublishSubscribe(t *testing.T) { - bus := New() - var wg sync.WaitGroup - - for i := 0; i < 5; i++ { - wg.Add(1) - go func(id int) { - defer wg.Done() - sub, cleanup := bus.Subscribe("topic") - defer cleanup() - for j := 0; j < 100; j++ { - sub.Ring.Pop() - } - }(i) - } - - for i := 0; i < 5; i++ { - wg.Add(1) - go func(id int) { - defer wg.Done() - for j := 0; j < 100; j++ { - bus.Publish("topic", &Event{Seq: int64(id*100 + j)}) - } - }(i) - } - - wg.Wait() -} diff --git a/internal/eventbus/ring.go b/internal/eventbus/ring.go deleted file mode 100644 index 688a125..0000000 --- a/internal/eventbus/ring.go +++ /dev/null @@ -1,56 +0,0 @@ -package eventbus - -import "sync" - -type RingBuffer[T any] struct { - mu sync.Mutex - buf []T - head int - tail int - count int - cap int -} - -func NewRingBuffer[T any](capacity int) *RingBuffer[T] { - return &RingBuffer[T]{ - buf: make([]T, capacity), - cap: capacity, - } -} - -func (r *RingBuffer[T]) Push(item T) { - r.mu.Lock() - defer r.mu.Unlock() - - r.buf[r.head] = item - r.head = (r.head + 1) % r.cap - - if r.count == r.cap { - r.tail = (r.tail + 1) % r.cap - } else { - r.count++ - } -} - -func (r *RingBuffer[T]) Pop() (T, bool) { - r.mu.Lock() - defer r.mu.Unlock() - - var zero T - if r.count == 0 { - return zero, false - } - - item := r.buf[r.tail] - r.buf[r.tail] = zero - r.tail = (r.tail + 1) % r.cap - r.count-- - - return item, true -} - -func (r *RingBuffer[T]) Len() int { - r.mu.Lock() - defer r.mu.Unlock() - return r.count -} diff --git a/internal/eventbus/ring_test.go b/internal/eventbus/ring_test.go deleted file mode 100644 index 5801afb..0000000 --- a/internal/eventbus/ring_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package eventbus - -import ( - "sync" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestRingBuffer_PushPop(t *testing.T) { - ring := NewRingBuffer[int](5) - - ring.Push(1) - ring.Push(2) - ring.Push(3) - - v, ok := ring.Pop() - require.True(t, ok) - assert.Equal(t, 1, v) - - v, ok = ring.Pop() - require.True(t, ok) - assert.Equal(t, 2, v) - - v, ok = ring.Pop() - require.True(t, ok) - assert.Equal(t, 3, v) -} - -func TestRingBuffer_Empty(t *testing.T) { - ring := NewRingBuffer[int](5) - - v, ok := ring.Pop() - assert.False(t, ok) - assert.Equal(t, 0, v) -} - -func TestRingBuffer_OverwriteOldest(t *testing.T) { - ring := NewRingBuffer[int](4) - - ring.Push(1) - ring.Push(2) - ring.Push(3) - ring.Push(4) - ring.Push(5) - ring.Push(6) - - var values []int - for { - v, ok := ring.Pop() - if !ok { - break - } - values = append(values, v) - } - - assert.Equal(t, []int{3, 4, 5, 6}, values) -} - -func TestRingBuffer_Len(t *testing.T) { - ring := NewRingBuffer[int](5) - - assert.Equal(t, 0, ring.Len()) - - ring.Push(1) - assert.Equal(t, 1, ring.Len()) - - ring.Push(2) - ring.Push(3) - assert.Equal(t, 3, ring.Len()) - - ring.Pop() - assert.Equal(t, 2, ring.Len()) - - ring.Push(4) - ring.Push(5) - ring.Push(6) - ring.Push(7) - assert.Equal(t, 5, ring.Len()) - - ring.Push(8) - assert.Equal(t, 5, ring.Len()) -} - -func TestRingBuffer_Concurrent(t *testing.T) { - ring := NewRingBuffer[int](100) - var wg sync.WaitGroup - - for i := 0; i < 10; i++ { - wg.Add(1) - go func(id int) { - defer wg.Done() - for j := 0; j < 100; j++ { - ring.Push(id*100 + j) - } - }(i) - } - - wg.Add(1) - go func() { - defer wg.Done() - for i := 0; i < 500; i++ { - ring.Pop() - } - }() - - wg.Wait() -} diff --git a/internal/hello/server.go b/internal/hello/server.go deleted file mode 100644 index 1ab00ff..0000000 --- a/internal/hello/server.go +++ /dev/null @@ -1,32 +0,0 @@ -package hello - -import ( - "context" - - "google.golang.org/grpc" - pb "homelab.lan/music-agregator/gen/music_agregator/hello/v1" -) - -type HelloServer struct { - pb.UnimplementedHelloServiceServer -} - -func NewHelloServer() *HelloServer { - return &HelloServer{} -} - -func (server *HelloServer) Ping(ctx context.Context, req *pb.PingRequest) (*pb.PongResponse, error) { - return &pb.PongResponse{}, nil -} - -func (server *HelloServer) Echo(ctx context.Context, req *pb.EchoRequest) (*pb.EchoResponse, error) { - response := &pb.EchoResponse{ - Response: req.GetMsg(), - } - - return response, nil -} - -func (s *HelloServer) Register(server *grpc.Server) { - pb.RegisterHelloServiceServer(server, s) -} diff --git a/internal/indexer/cache.go b/internal/indexer/cache.go deleted file mode 100644 index 4088b8c..0000000 --- a/internal/indexer/cache.go +++ /dev/null @@ -1,79 +0,0 @@ -package indexer - -import ( - "sync" - "time" - - "github.com/rs/zerolog/log" -) - -type CacheEntry struct { - Key string - URL string - Result SearchResult - CreatedAt time.Time - TTL time.Duration - RefreshInterval time.Duration -} - -func (e *CacheEntry) IsExpired() bool { - return time.Now().After(e.CreatedAt.Add(e.TTL)) -} - -type IndexerCache struct { - entries map[string]*CacheEntry - mu sync.RWMutex -} - -func NewIndexerCache() *IndexerCache { - return &IndexerCache{ - entries: make(map[string]*CacheEntry), - } -} - -func (c *IndexerCache) Get(key string) (*CacheEntry, bool) { - c.mu.RLock() - defer c.mu.RUnlock() - - entry, ok := c.entries[key] - if !ok { - log.Trace().Str("key", key).Msg("cache miss") - return nil, false - } - - if entry.IsExpired() { - log.Trace().Str("key", key).Msg("cache expired") - return nil, false - } - - log.Trace().Str("key", key).Int("items", len(entry.Result.Items)).Msg("cache hit") - return entry, true -} - -func (c *IndexerCache) Add(entry CacheEntry) { - c.mu.Lock() - defer c.mu.Unlock() - - c.entries[entry.Key] = &entry - log.Debug().Str("key", entry.Key).Int("items", len(entry.Result.Items)).Dur("ttl", entry.TTL).Dur("refresh", entry.RefreshInterval).Msg("cache entry added") -} - -func (c *IndexerCache) Update(key string, result SearchResult) { - c.mu.Lock() - defer c.mu.Unlock() - - if entry, ok := c.entries[key]; ok { - entry.Result = result - log.Debug().Str("key", key).Int("items", len(result.Items)).Msg("cache entry updated") - } else { - log.Warn().Str("key", key).Msg("cache update for missing entry") - } -} - -func (c *IndexerCache) Remove(key string) { - c.mu.Lock() - defer c.mu.Unlock() - - delete(c.entries, key) - log.Debug().Str("key", key).Msg("cache entry removed") -} diff --git a/internal/indexer/cache_worker.go b/internal/indexer/cache_worker.go deleted file mode 100644 index fa4ce9f..0000000 --- a/internal/indexer/cache_worker.go +++ /dev/null @@ -1,71 +0,0 @@ -package indexer - -import ( - "context" - "time" - - "github.com/jackc/pgx/v5" - "github.com/riverqueue/river" - "github.com/rs/zerolog/log" -) - -type CacheRefreshArgs struct { - Key string `json:"key"` - URL string `json:"url"` - TTLExpires time.Time `json:"ttl_expires"` - RefreshInterval time.Duration `json:"refresh_interval"` -} - -func (CacheRefreshArgs) Kind() string { return "indexer_cache_refresh" } - -type CacheRefreshWorker struct { - river.WorkerDefaults[CacheRefreshArgs] - Cache *IndexerCache - Indexer Indexer - RiverClient *river.Client[pgx.Tx] -} - -func (w *CacheRefreshWorker) Work(ctx context.Context, job *river.Job[CacheRefreshArgs]) error { - args := job.Args - - if w.Cache == nil || w.Indexer == nil { - log.Trace().Str("key", args.Key).Msg("cache disabled, discarding refresh job") - return nil - } - - log.Trace().Str("key", args.Key).Int64("job_id", job.ID).Time("ttl_expires", args.TTLExpires).Msg("cache refresh worker started") - - if time.Now().After(args.TTLExpires) { - w.Cache.Remove(args.Key) - log.Debug().Str("key", args.Key).Msg("cache entry TTL expired, removed") - return nil - } - - log.Trace().Str("key", args.Key).Str("url", args.URL).Msg("fetching fresh data from indexer") - start := time.Now() - result, err := w.Indexer.FetchURL(args.URL) - if err != nil { - retryAt := time.Now().Add(5 * time.Minute) - log.Error().Err(err).Str("key", args.Key).Time("retry_at", retryAt).Msg("cache refresh failed, scheduling retry") - w.RiverClient.Insert(ctx, args, &river.InsertOpts{ - ScheduledAt: retryAt, - }) - return nil - } - log.Trace().Str("key", args.Key).Int("items", len(result.Items)).Dur("duration", time.Since(start)).Msg("fresh data fetched") - - w.Cache.Update(args.Key, result) - - nextRefresh := time.Now().Add(args.RefreshInterval) - _, err = w.RiverClient.Insert(ctx, args, &river.InsertOpts{ - ScheduledAt: nextRefresh, - }) - if err != nil { - log.Error().Err(err).Str("key", args.Key).Msg("failed to schedule next cache refresh") - } else { - log.Trace().Str("key", args.Key).Time("next_refresh", nextRefresh).Msg("next refresh scheduled") - } - - log.Debug().Str("key", args.Key).Int("items", len(result.Items)).Msg("cache refreshed") - return nil -} diff --git a/internal/indexer/cached_indexer.go b/internal/indexer/cached_indexer.go deleted file mode 100644 index 2e1b457..0000000 --- a/internal/indexer/cached_indexer.go +++ /dev/null @@ -1,90 +0,0 @@ -package indexer - -import ( - "context" - "time" - - "github.com/jackc/pgx/v5" - "github.com/riverqueue/river" - "github.com/rs/zerolog/log" - - "homelab.lan/music-agregator/internal/config" -) - -type CachedIndexer struct { - inner Indexer - cache *IndexerCache - riverClient *river.Client[pgx.Tx] - cfg config.CacheConfig -} - -func NewCachedIndexer(inner Indexer, cache *IndexerCache, riverClient *river.Client[pgx.Tx], cfg config.CacheConfig) *CachedIndexer { - return &CachedIndexer{ - inner: inner, - cache: cache, - riverClient: riverClient, - cfg: cfg, - } -} - -func (c *CachedIndexer) Search(query string, limit int32, tracker string) (SearchResult, error) { - key := query + "|" + tracker - log.Trace().Str("key", key).Str("query", query).Str("tracker", tracker).Msg("cached indexer search") - - if entry, ok := c.cache.Get(key); ok { - log.Debug().Str("key", key).Int("items", len(entry.Result.Items)).Msg("returning cached result") - return entry.Result, nil - } - - log.Trace().Str("key", key).Msg("cache miss, fetching from indexer") - result, err := c.inner.Search(query, limit, tracker) - if err != nil { - log.Error().Err(err).Str("key", key).Msg("cached indexer fetch failed") - return SearchResult{}, err - } - - url := c.inner.BuildSearchURL(query, limit, tracker) - log.Trace().Str("key", key).Str("url", url).Int("items", len(result.Items)).Msg("caching result") - - c.cache.Add(CacheEntry{ - Key: key, - URL: url, - Result: result, - CreatedAt: time.Now(), - TTL: c.cfg.TTL, - RefreshInterval: c.cfg.RefreshInterval, - }) - - scheduleAt := time.Now().Add(c.cfg.RefreshInterval) - _, err = c.riverClient.Insert(context.Background(), CacheRefreshArgs{ - Key: key, - URL: url, - TTLExpires: time.Now().Add(c.cfg.TTL), - RefreshInterval: c.cfg.RefreshInterval, - }, &river.InsertOpts{ - ScheduledAt: scheduleAt, - }) - if err != nil { - log.Error().Err(err).Str("key", key).Msg("failed to schedule cache refresh job") - } else { - log.Debug().Str("key", key).Time("scheduled_at", scheduleAt).Msg("cache refresh job scheduled") - } - - log.Debug().Str("key", key).Dur("ttl", c.cfg.TTL).Dur("refresh", c.cfg.RefreshInterval).Int("items", len(result.Items)).Msg("cached indexer search complete") - - return result, nil -} - -func (c *CachedIndexer) FetchURL(url string) (SearchResult, error) { - log.Trace().Str("url", url).Msg("cached indexer fetch URL passthrough") - return c.inner.FetchURL(url) -} - -func (c *CachedIndexer) BuildSearchURL(query string, limit int32, tracker string) string { - return c.inner.BuildSearchURL(query, limit, tracker) -} - -func (c *CachedIndexer) Capabilities(indexerName string) (IndexerCapabilities, error) { - log.Trace().Str("indexer", indexerName).Msg("cached indexer capabilities passthrough") - return c.inner.Capabilities(indexerName) -} diff --git a/internal/indexer/filter.go b/internal/indexer/filter.go deleted file mode 100644 index ff2ee56..0000000 --- a/internal/indexer/filter.go +++ /dev/null @@ -1,5 +0,0 @@ -package indexer - -type Filter interface { - IsKnownCategory(categories []string) bool -} diff --git a/internal/indexer/indexer.go b/internal/indexer/indexer.go deleted file mode 100644 index aab9591..0000000 --- a/internal/indexer/indexer.go +++ /dev/null @@ -1,8 +0,0 @@ -package indexer - -type Indexer interface { - Search(query string, limit int32, indexer string) (SearchResult, error) - FetchURL(url string) (SearchResult, error) - BuildSearchURL(query string, limit int32, tracker string) string - Capabilities(indexerName string) (IndexerCapabilities, error) -} diff --git a/internal/indexer/indexer_capabilities.go b/internal/indexer/indexer_capabilities.go deleted file mode 100644 index d0970fc..0000000 --- a/internal/indexer/indexer_capabilities.go +++ /dev/null @@ -1,103 +0,0 @@ -package indexer - -import ( - "encoding/xml" - "strings" - - pb "homelab.lan/music-agregator/gen/music_agregator/indexer/v1" -) - -type IndexerCapabilities struct { - XMLName xml.Name `xml:"caps"` - Server Server `xml:"server"` - Limits Limits `xml:"limits"` - Searching Searching `xml:"searching"` - Categories []Category `xml:"categories>category"` -} - -type Server struct { - Title string `xml:"title,attr"` -} - -type Limits struct { - Default int `xml:"default,attr"` - Max int `xml:"max,attr"` -} - -type Searching struct { - Search SearchCapability `xml:"search"` - TvSearch SearchCapability `xml:"tv-search"` - MovieSearch SearchCapability `xml:"movie-search"` - MusicSearch SearchCapability `xml:"music-search"` - AudioSearch SearchCapability `xml:"audio-search"` - BookSearch SearchCapability `xml:"book-search"` -} - -type SearchCapability struct { - Available string `xml:"available,attr"` - SupportedParams string `xml:"supportedParams,attr"` - SearchEngine string `xml:"searchEngine,attr"` -} - -type Category struct { - ID int `xml:"id,attr"` - Name string `xml:"name,attr"` - Subcats []Subcat `xml:"subcat"` -} - -type Subcat struct { - ID int `xml:"id,attr"` - Name string `xml:"name,attr"` -} - -func (c *IndexerCapabilities) ToProto() *pb.CapabilitiesResponse { - return &pb.CapabilitiesResponse{ - Server: &pb.Server{ - Title: c.Server.Title, - }, - Limits: &pb.Limits{ - Default: int32(c.Limits.Default), - Max: int32(c.Limits.Max), - }, - Searching: &pb.Searching{ - Search: c.Searching.Search.toProto(), - TvSearch: c.Searching.TvSearch.toProto(), - MovieSearch: c.Searching.MovieSearch.toProto(), - MusicSearch: c.Searching.MusicSearch.toProto(), - AudioSearch: c.Searching.AudioSearch.toProto(), - BookSearch: c.Searching.BookSearch.toProto(), - }, - Categories: c.categoriesToProto(), - } -} - -func (s *SearchCapability) toProto() *pb.SearchCapability { - var params []string - if s.SupportedParams != "" { - params = strings.Split(s.SupportedParams, ",") - } - return &pb.SearchCapability{ - Available: s.Available == "yes", - SupportedParams: params, - SearchEngine: s.SearchEngine, - } -} - -func (c *IndexerCapabilities) categoriesToProto() []*pb.Category { - categories := make([]*pb.Category, len(c.Categories)) - for i, cat := range c.Categories { - subcats := make([]*pb.Subcat, len(cat.Subcats)) - for j, sub := range cat.Subcats { - subcats[j] = &pb.Subcat{ - Id: int32(sub.ID), - Name: sub.Name, - } - } - categories[i] = &pb.Category{ - Id: int32(cat.ID), - Name: cat.Name, - Subcats: subcats, - } - } - return categories -} diff --git a/internal/indexer/jackett.go b/internal/indexer/jackett.go deleted file mode 100644 index aea4aae..0000000 --- a/internal/indexer/jackett.go +++ /dev/null @@ -1,139 +0,0 @@ -package indexer - -import ( - "encoding/xml" - "fmt" - "io" - "net/http" - "net/url" - "time" - - "github.com/rs/zerolog/log" - "homelab.lan/music-agregator/internal/config" -) - -type JacketIndexer struct { - cfg config.Config - client *http.Client -} - -func NewIndexer(cfg config.Config) Indexer { - return &JacketIndexer{ - cfg: cfg, - client: &http.Client{ - Timeout: 60 * time.Second, - }, - } -} - -func (indexer *JacketIndexer) BuildSearchURL(query string, limit int32, tracker string) string { - searchTracker := "all" - if len(tracker) != 0 { - searchTracker = tracker - } - - uri := fmt.Sprintf("%v/api/v2.0/indexers/%v/results/torznab?apikey=%v&cat=3010,3040&q=%v&t=search", - indexer.cfg.Indexer.Url, searchTracker, indexer.cfg.Indexer.ApiKey, url.QueryEscape(query)) - if limit > 0 { - uri += fmt.Sprintf("&limit=%d", limit) - } - - return uri -} - -func (indexer *JacketIndexer) Search(query string, limit int32, tracker string) (SearchResult, error) { - uri := indexer.BuildSearchURL(query, limit, tracker) - return indexer.FetchURL(uri) -} - -type JackettError struct { - Code string `xml:"code,attr"` - Description string `xml:"description,attr"` -} - -func (e *JackettError) Error() string { - return fmt.Sprintf("jackett error %s: %s", e.Code, e.Description) -} - -func (indexer *JacketIndexer) FetchURL(uri string) (SearchResult, error) { - log.Trace().Str("uri", uri).Msg("jackett request") - - req, err := http.NewRequest("GET", uri, nil) - if err != nil { - log.Error().Err(err).Msg("error creating request") - return SearchResult{}, err - } - - start := time.Now() - resp, err := indexer.client.Do(req) - if err != nil { - log.Error().Err(err).Msg("error making search request") - return SearchResult{}, err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Error().Err(err).Msg("error reading search response body") - return SearchResult{}, err - } - - log.Trace(). - Int("status", resp.StatusCode). - Int("body_bytes", len(body)). - Dur("duration", time.Since(start)). - Msg("jackett response") - - if resp.StatusCode != http.StatusOK { - var jackettErr JackettError - if xmlErr := xml.Unmarshal(body, &jackettErr); xmlErr == nil && jackettErr.Code != "" { - log.Error().Str("code", jackettErr.Code).Str("description", jackettErr.Description).Msg("jackett returned error") - return SearchResult{}, &jackettErr - } - return SearchResult{}, fmt.Errorf("jackett returned HTTP %d", resp.StatusCode) - } - - var searchResult SearchResult - if err := xml.Unmarshal(body, &searchResult); err != nil { - log.Error().Err(err).Msg("error parsing search XML") - return SearchResult{}, err - } - - log.Trace().Int("items", len(searchResult.Items)).Msg("jackett XML parsed") - - return searchResult, nil -} - -func (indexer *JacketIndexer) Capabilities(indexerName string) (IndexerCapabilities, error) { - url := indexer.cfg.Indexer.Url - uri := fmt.Sprintf("%v/api/v2.0/indexers/%v/results/torznab/api?apikey=%v&t=caps", url, indexerName, indexer.cfg.Indexer.ApiKey) - - req, err := http.NewRequest("GET", uri, nil) - if err != nil { - log.Error().Err(err).Msg("Error creating request") - return IndexerCapabilities{}, err - } - - resp, err := indexer.client.Do(req) - if err != nil { - log.Error().Err(err).Msg("Error making capabilities request") - return IndexerCapabilities{}, err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Error().Err(err).Msg("Error reading response body") - return IndexerCapabilities{}, err - } - - var capabilities IndexerCapabilities - if err := xml.Unmarshal(body, &capabilities); err != nil { - log.Error().Err(err).Msg("Error parsing capabilities XML") - return IndexerCapabilities{}, err - } - - log.Debug().Str("server", capabilities.Server.Title).Msg("Parsed capabilities") - - return capabilities, nil -} diff --git a/internal/indexer/search.go b/internal/indexer/search.go deleted file mode 100644 index 1787be2..0000000 --- a/internal/indexer/search.go +++ /dev/null @@ -1,140 +0,0 @@ -package indexer - -import ( - "encoding/xml" - "strconv" - - "github.com/rs/zerolog/log" - - pb "homelab.lan/music-agregator/gen/music_agregator/indexer/v1" - "homelab.lan/music-agregator/internal/release" - "homelab.lan/music-agregator/internal/tracker" -) - -type SearchResult struct { - XMLName xml.Name `xml:"rss"` - Items []Item `xml:"channel>item"` -} - -type JackettIndexer struct { - ID string `xml:"id,attr"` -} - -type Item struct { - Title string `xml:"title"` - Link string `xml:"link"` - Guid string `xml:"guid"` - PubDate string `xml:"pubDate"` - Size int64 `xml:"size"` - Description string `xml:"description"` - Categories []string `xml:"category"` - Enclosure Enclosure `xml:"enclosure"` - TorznabAttrs []TorznabAttr `xml:"attr"` - JackettIndexer JackettIndexer `xml:"jackettindexer"` -} - -type Enclosure struct { - URL string `xml:"url,attr"` - Length int64 `xml:"length,attr"` - Type string `xml:"type,attr"` -} - -type TorznabAttr struct { - Name string `xml:"name,attr"` - Value string `xml:"value,attr"` -} - -type SearchItemResult struct { - Title string - DownloadLink string - TorrentPageUrl string - PubDate string - Size int64 - Description string - Categories []string - Tracker string - Seeders int - Peers int - Attrs map[string]string - Release *release.Release -} - -func (si *SearchItemResult) ToProto() *pb.SearchItem { - var pbAttrs []*pb.TorznabAttr - for k, v := range si.Attrs { - pbAttrs = append(pbAttrs, &pb.TorznabAttr{Name: k, Value: v}) - } - - return &pb.SearchItem{ - Title: si.Title, - DownloadLink: si.DownloadLink, - TorrentPageUrl: si.TorrentPageUrl, - PubDate: si.PubDate, - Size: si.Size, - Description: si.Description, - Categories: si.Categories, - TorznabAttrs: pbAttrs, - Release: si.Release.ToProto(), - } -} - -type SearchResponse struct { - Items []*SearchItemResult -} - -func (sr *SearchResponse) ToProto() *pb.SearchResponse { - pbItems := make([]*pb.SearchItem, len(sr.Items)) - for i, item := range sr.Items { - pbItems[i] = item.ToProto() - } - return &pb.SearchResponse{Result: pbItems} -} - -var genericParser = tracker.NewGenericParser() - -func (sr *SearchResult) ToSearchResponse() *SearchResponse { - var items []*SearchItemResult - - for _, item := range sr.Items { - rel := genericParser.Parse(item.Title) - - log.Trace(). - Str("tracker", item.JackettIndexer.ID). - Str("title", item.Title). - Str("artist", rel.Artist). - Str("album", rel.Album). - Int("year", rel.Year). - Bool("parsed", rel.ParsedSuccessfully). - Msg("parsed item") - - attrs := make(map[string]string, len(item.TorznabAttrs)) - for _, attr := range item.TorznabAttrs { - attrs[attr.Name] = attr.Value - } - - seeders, _ := strconv.Atoi(attrs["seeders"]) - peers, _ := strconv.Atoi(attrs["peers"]) - - items = append(items, &SearchItemResult{ - Title: item.Title, - DownloadLink: item.Link, - TorrentPageUrl: item.Guid, - PubDate: item.PubDate, - Size: item.Size, - Description: item.Description, - Categories: item.Categories, - Tracker: item.JackettIndexer.ID, - Seeders: seeders, - Peers: peers, - Attrs: attrs, - Release: rel, - }) - } - - log.Trace(). - Int("total", len(sr.Items)). - Int("items", len(items)). - Msg("conversion complete") - - return &SearchResponse{Items: items} -} diff --git a/internal/indexer/server.go b/internal/indexer/server.go deleted file mode 100644 index 2291933..0000000 --- a/internal/indexer/server.go +++ /dev/null @@ -1,67 +0,0 @@ -package indexer - -import ( - "context" - - "github.com/jackc/pgx/v5" - "github.com/riverqueue/river" - "github.com/rs/zerolog/log" - "google.golang.org/grpc" - - pb "homelab.lan/music-agregator/gen/music_agregator/indexer/v1" - "homelab.lan/music-agregator/internal/config" -) - -type IndexerServer struct { - service *IndexerService - pb.UnimplementedIndexerServiceServer -} - -func NewIndexerServer(cfg config.Config, riverClient *river.Client[pgx.Tx], cacheWorker *CacheRefreshWorker) (*IndexerServer, error) { - service, err := NewIndexerService(cfg, riverClient, cacheWorker) - if err != nil { - log.Err(err).Msg("failed to initialize IndexerService") - return nil, err - } - - return &IndexerServer{service: service}, nil -} - -func (server *IndexerServer) Search(ctx context.Context, req *pb.SearchRequest) (*pb.SearchResponse, error) { - log.Debug(). - Str("query", req.GetQuery()). - Int32("limit", req.GetLimit()). - Str("tracker", req.GetTracker()). - Msg("search started") - - log.Trace().Str("query", req.GetQuery()).Msg("fetching results from indexer") - - resp, err := server.service.Search(req.GetQuery(), req.GetLimit(), req.GetTracker()) - if err != nil { - log.Error().Err(err).Str("query", req.GetQuery()).Msg("search failed") - return nil, err - } - - log.Debug(). - Str("query", req.GetQuery()). - Int("results", len(resp.Items)). - Msg("search completed") - - return resp.ToProto(), nil -} - -func (server *IndexerServer) Capabilities(ctx context.Context, req *pb.CapabilitiesRequest) (*pb.CapabilitiesResponse, error) { - log.Debug().Str("indexer", req.GetIndexer()).Msg("capabilities requested") - - resp, err := server.service.Capabilities(req) - if err != nil { - log.Error().Err(err).Str("indexer", req.GetIndexer()).Msg("capabilities failed") - return nil, err - } - - return resp, nil -} - -func (s *IndexerServer) Register(server *grpc.Server) { - pb.RegisterIndexerServiceServer(server, s) -} diff --git a/internal/indexer/service.go b/internal/indexer/service.go deleted file mode 100644 index ec548bf..0000000 --- a/internal/indexer/service.go +++ /dev/null @@ -1,66 +0,0 @@ -package indexer - -import ( - "fmt" - - "github.com/jackc/pgx/v5" - "github.com/riverqueue/river" - "github.com/rs/zerolog/log" - - pb "homelab.lan/music-agregator/gen/music_agregator/indexer/v1" - "homelab.lan/music-agregator/internal/config" -) - -type Searcher interface { - Search(query string, limit int32, indexer string) (*SearchResponse, error) -} - -type IndexerService struct { - indexer Indexer -} - -func NewIndexerService(cfg config.Config, riverClient *river.Client[pgx.Tx], cacheWorker *CacheRefreshWorker) (*IndexerService, error) { - var idx Indexer - - switch cfg.Indexer.Type { - case config.IndexerTypeJackett: - idx = NewIndexer(cfg) - default: - return nil, fmt.Errorf("unable to create the indexer for type: %v", cfg.Indexer.Type) - } - - if cfg.Indexer.Cache.Enabled && riverClient != nil { - cache := NewIndexerCache() - idx = NewCachedIndexer(idx, cache, riverClient, cfg.Indexer.Cache) - - if cacheWorker != nil { - cacheWorker.Cache = cache - cacheWorker.Indexer = idx - } - - log.Info().Dur("ttl", cfg.Indexer.Cache.TTL).Dur("refresh", cfg.Indexer.Cache.RefreshInterval).Msg("indexer cache enabled") - } - - return &IndexerService{indexer: idx}, nil -} - -func (service *IndexerService) Search(query string, limit int32, indexer string) (*SearchResponse, error) { - searchResult, err := service.indexer.Search(query, limit, indexer) - if err != nil { - log.Error().Err(err).Msg("failed to search in indexer") - return nil, err - } - - log.Trace().Int("raw_items", len(searchResult.Items)).Msg("indexer returned results") - - return searchResult.ToSearchResponse(), nil -} - -func (service *IndexerService) Capabilities(req *pb.CapabilitiesRequest) (*pb.CapabilitiesResponse, error) { - capabilities, err := service.indexer.Capabilities(req.GetIndexer()) - if err != nil { - log.Error().Err(err).Msg("Failed to get capabilities from indexer") - return nil, err - } - return capabilities.ToProto(), nil -} diff --git a/internal/matcher/album.go b/internal/matcher/album.go deleted file mode 100644 index 6210ff7..0000000 --- a/internal/matcher/album.go +++ /dev/null @@ -1,135 +0,0 @@ -package matcher - -import ( - "regexp" - "strings" -) - -const MatchThreshold = 0.7 - -var ( - punctuationRe = regexp.MustCompile(`[^\w\s]`) - yearRe = regexp.MustCompile(`\b(19|20)\d{2}\b`) - whitespaceRe = regexp.MustCompile(`\s+`) - noiseWords = map[string]struct{}{ - "remastered": {}, "remaster": {}, "deluxe": {}, "edition": {}, - "expanded": {}, "anniversary": {}, "special": {}, "limited": {}, - "collectors": {}, "collector": {}, "bonus": {}, "tracks": {}, - "standard": {}, "super": {}, - "flac": {}, "mp3": {}, "aac": {}, "ogg": {}, "wav": {}, - "24bit": {}, "16bit": {}, "48khz": {}, "44khz": {}, "96khz": {}, "192khz": {}, - "cd": {}, "vinyl": {}, "lp": {}, "web": {}, "sacd": {}, - "box": {}, "set": {}, "japan": {}, "shm": {}, - "singles": {}, "single": {}, - "pmedia": {}, - } -) - -func normalize(s string) string { - s = strings.ToLower(s) - s = punctuationRe.ReplaceAllString(s, " ") - s = yearRe.ReplaceAllString(s, " ") - s = whitespaceRe.ReplaceAllString(s, " ") - return strings.TrimSpace(s) -} - -func tokenize(s string) []string { - var tokens []string - for _, word := range strings.Fields(s) { - if _, noise := noiseWords[word]; !noise && len(word) > 1 { - tokens = append(tokens, word) - } - } - return tokens -} - -func AlbumMatchScore(albumTitle, torrentTitle, artistName string) float64 { - normAlbum := normalize(albumTitle) - normTorrent := normalize(torrentTitle) - - if artistName != "" { - normArtist := normalize(artistName) - normTorrent = strings.Replace(normTorrent, normArtist, "", 1) - normTorrent = strings.TrimSpace(whitespaceRe.ReplaceAllString(normTorrent, " ")) - } - - if normAlbum == "" { - return 0 - } - - if strings.Contains(normTorrent, normAlbum) { - return 1.0 - } - - albumTokens := tokenize(normAlbum) - if len(albumTokens) == 0 { - return 0 - } - - torrentTokens := make(map[string]struct{}, len(albumTokens)) - for _, t := range tokenize(normTorrent) { - torrentTokens[t] = struct{}{} - } - - var matches int - for _, token := range albumTokens { - if _, found := torrentTokens[token]; found { - matches++ - continue - } - for tt := range torrentTokens { - if levenshteinClose(token, tt) { - matches++ - break - } - } - } - - return float64(matches) / float64(len(albumTokens)) -} - -func levenshteinClose(a, b string) bool { - if len(a) < 3 || len(b) < 3 { - return false - } - maxDist := 1 - if len(a) > 6 { - maxDist = 2 - } - return levenshtein(a, b) <= maxDist -} - -func levenshtein(a, b string) int { - la, lb := len(a), len(b) - if la == 0 { - return lb - } - if lb == 0 { - return la - } - - prev := make([]int, lb+1) - curr := make([]int, lb+1) - - for j := 0; j <= lb; j++ { - prev[j] = j - } - - for i := 1; i <= la; i++ { - curr[0] = i - for j := 1; j <= lb; j++ { - cost := 1 - if a[i-1] == b[j-1] { - cost = 0 - } - curr[j] = min(curr[j-1]+1, min(prev[j]+1, prev[j-1]+cost)) - } - prev, curr = curr, prev - } - - return prev[lb] -} - -func IsAlbumMatch(albumTitle, torrentTitle, artistName string) bool { - return AlbumMatchScore(albumTitle, torrentTitle, artistName) >= MatchThreshold -} diff --git a/internal/matcher/album_test.go b/internal/matcher/album_test.go deleted file mode 100644 index 3dbd0b2..0000000 --- a/internal/matcher/album_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package matcher - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestAlbumMatchScore(t *testing.T) { - tests := []struct { - album string - torrent string - artist string - wantMin float64 - wantMax float64 - match bool - }{ - { - album: "Ain't My Bitch", - torrent: "Metallica - Ain't My Bitch (2025) [FLAC]", - artist: "Metallica", - wantMin: 0.9, wantMax: 1.0, match: true, - }, - { - album: "Ain't My Bitch", - torrent: "Metallica - Aint My Bitch Remastered 2025 FLAC", - artist: "Metallica", - wantMin: 0.9, wantMax: 1.0, match: true, - }, - { - album: "72 Seasons", - torrent: "Metallica - 72 Seasons (2023) [24Bit-48kHz] FLAC [PMEDIA] ⭐️", - artist: "Metallica", - wantMin: 0.9, wantMax: 1.0, match: true, - }, - { - album: "Kill 'Em All", - torrent: "Metallica - Kill Em All [1983] FLAC", - artist: "Metallica", - wantMin: 0.9, wantMax: 1.0, match: true, - }, - { - album: "...And Justice for All", - torrent: "Metallica - And Justice For All (Remastered) FLAC", - artist: "Metallica", - wantMin: 0.7, wantMax: 1.0, match: true, - }, - { - album: "Master of Puppets", - torrent: "Metallica - Master of Puppets (Remastered Deluxe Box Set) FLAC", - artist: "Metallica", - wantMin: 0.9, wantMax: 1.0, match: true, - }, - { - album: "Ain't My Bitch", - torrent: "Metallica - Load 1996 (Japan SHM-CD)", - artist: "Metallica", - wantMin: 0.0, wantMax: 0.3, match: false, - }, - { - album: "Ain't My Bitch", - torrent: "Metallica - The Memory Remains (Singles, 2026 remastered)", - artist: "Metallica", - wantMin: 0.0, wantMax: 0.3, match: false, - }, - { - album: "Ain't My Bitch", - torrent: "Metallica - 72 Seasons (2023) [24Bit-48kHz] FLAC", - artist: "Metallica", - wantMin: 0.0, wantMax: 0.3, match: false, - }, - { - album: "Hardwired...to Self-Destruct", - torrent: "Metallica - Hardwired To Self-Destruct (Deluxe 2016) [FLAC]", - artist: "Metallica", - wantMin: 0.7, wantMax: 1.0, match: true, - }, - { - album: "S&M", - torrent: "Metallica - S&M (1999) [FLAC]", - artist: "Metallica", - wantMin: 0.9, wantMax: 1.0, match: true, - }, - } - - for _, tt := range tests { - t.Run(tt.album+" vs "+tt.torrent, func(t *testing.T) { - score := AlbumMatchScore(tt.album, tt.torrent, tt.artist) - assert.GreaterOrEqual(t, score, tt.wantMin, "score too low: %.2f", score) - assert.LessOrEqual(t, score, tt.wantMax, "score too high: %.2f", score) - assert.Equal(t, tt.match, IsAlbumMatch(tt.album, tt.torrent, tt.artist), - "match mismatch for score %.2f", score) - }) - } -} diff --git a/internal/metadata/client.go b/internal/metadata/client.go deleted file mode 100644 index 930f900..0000000 --- a/internal/metadata/client.go +++ /dev/null @@ -1,24 +0,0 @@ -package metadata - -import ( - "fmt" - - "github.com/rs/zerolog/log" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - pb "homelab.lan/music-agregator/gen/metadata/v1" -) - -func NewMetadataClient(endpoint string) (pb.MetadataServiceClient, *grpc.ClientConn, error) { - log.Trace().Str("endpoint", endpoint).Msg("connecting to metadata service") - - conn, err := grpc.NewClient(endpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return nil, nil, fmt.Errorf("connecting to metadata service: %w", err) - } - - log.Info().Str("endpoint", endpoint).Msg("metadata service connected") - - return pb.NewMetadataServiceClient(conn), conn, nil -} diff --git a/internal/metadata/server.go b/internal/metadata/server.go deleted file mode 100644 index 3f8ba0b..0000000 --- a/internal/metadata/server.go +++ /dev/null @@ -1,77 +0,0 @@ -package metadata - -import ( - "context" - - "github.com/rs/zerolog/log" - "google.golang.org/grpc" - - pb "homelab.lan/music-agregator/gen/metadata/v1" - "homelab.lan/music-agregator/internal/config" -) - -type MetadataServer struct { - client pb.MetadataServiceClient - conn *grpc.ClientConn - pb.UnimplementedMetadataServiceServer -} - -func NewMetadataServer(cfg config.Config) (*MetadataServer, error) { - client, conn, err := NewMetadataClient(cfg.Metadata.Endpoint) - if err != nil { - log.Err(err).Msg("failed to initialize MetadataServer") - return nil, err - } - - return &MetadataServer{client: client, conn: conn}, nil -} - -func (s *MetadataServer) Close() { - if s.conn != nil { - s.conn.Close() - } -} - -func (s *MetadataServer) Register(server *grpc.Server) { - pb.RegisterMetadataServiceServer(server, s) -} - -func (s *MetadataServer) GetArtist(ctx context.Context, req *pb.GetArtistRequest) (*pb.GetArtistResponse, error) { - log.Debug().Msg("metadata GetArtist") - return s.client.GetArtist(ctx, req) -} - -func (s *MetadataServer) SearchArtists(ctx context.Context, req *pb.SearchArtistsRequest) (*pb.SearchArtistsResponse, error) { - log.Debug().Str("query", req.GetQuery()).Int32("limit", req.GetLimit()).Msg("metadata SearchArtists") - return s.client.SearchArtists(ctx, req) -} - -func (s *MetadataServer) GetAlbum(ctx context.Context, req *pb.GetAlbumRequest) (*pb.GetAlbumResponse, error) { - log.Debug().Msg("metadata GetAlbum") - return s.client.GetAlbum(ctx, req) -} - -func (s *MetadataServer) GetArtistAlbums(ctx context.Context, req *pb.GetArtistAlbumsRequest) (*pb.GetArtistAlbumsResponse, error) { - log.Debug().Str("artist_id", req.GetArtistId()).Msg("metadata GetArtistAlbums") - return s.client.GetArtistAlbums(ctx, req) -} - -func (s *MetadataServer) GetTrack(ctx context.Context, req *pb.GetTrackRequest) (*pb.GetTrackResponse, error) { - log.Debug().Msg("metadata GetTrack") - return s.client.GetTrack(ctx, req) -} - -func (s *MetadataServer) GetAlbumTracks(ctx context.Context, req *pb.GetAlbumTracksRequest) (*pb.GetAlbumTracksResponse, error) { - log.Debug().Str("album_id", req.GetAlbumId()).Msg("metadata GetAlbumTracks") - return s.client.GetAlbumTracks(ctx, req) -} - -func (s *MetadataServer) SearchAlbums(ctx context.Context, req *pb.SearchAlbumsRequest) (*pb.SearchAlbumsResponse, error) { - log.Debug().Str("query", req.GetQuery()).Str("artist", req.GetArtist()).Msg("metadata SearchAlbums") - return s.client.SearchAlbums(ctx, req) -} - -func (s *MetadataServer) SyncArtist(ctx context.Context, req *pb.SyncArtistRequest) (*pb.SyncArtistResponse, error) { - log.Debug().Msg("metadata SyncArtist") - return s.client.SyncArtist(ctx, req) -} diff --git a/internal/metadata/service.go b/internal/metadata/service.go deleted file mode 100644 index f805d91..0000000 --- a/internal/metadata/service.go +++ /dev/null @@ -1,235 +0,0 @@ -package metadata - -import ( - "context" - "fmt" - - "github.com/rs/zerolog/log" - - metadataPb "homelab.lan/music-agregator/gen/metadata/v1" - "homelab.lan/music-agregator/internal/database" -) - -type MetadataService struct { - client metadataPb.MetadataServiceClient - artists *database.ArtistRepository - albums *database.AlbumRepository - tracks *database.TrackRepository -} - -func NewMetadataService(client metadataPb.MetadataServiceClient, db *database.DB) *MetadataService { - return &MetadataService{ - client: client, - artists: database.NewArtistRepository(db.Pool), - albums: database.NewAlbumRepository(db.Pool), - tracks: database.NewTrackRepository(db.Pool), - } -} - -func (s *MetadataService) GetAlbum(ctx context.Context, albumID string) (*metadataPb.Album, error) { - resp, err := s.client.GetAlbum(ctx, &metadataPb.GetAlbumRequest{ - Identifier: &metadataPb.GetAlbumRequest_Id{Id: albumID}, - }) - if err != nil { - return nil, fmt.Errorf("fetching album: %w", err) - } - - album := resp.GetAlbum() - - if _, err := s.albums.GetByExternalID(ctx, album.GetId()); err != nil { - s.PersistArtist(ctx, album, database.Monitored) - s.PersistAlbum(ctx, album, database.Monitored) - } - - return album, nil -} - -func (s *MetadataService) GetArtistAlbums(ctx context.Context, artistExternalID string) ([]*metadataPb.Album, error) { - resp, err := s.client.GetArtistAlbums(ctx, &metadataPb.GetArtistAlbumsRequest{ - ArtistId: artistExternalID, - }) - if err != nil { - return nil, fmt.Errorf("fetching artist albums: %w", err) - } - return resp.GetAlbums(), nil -} - -func (s *MetadataService) SearchArtists(ctx context.Context, query string, limit, offset int32) (*metadataPb.SearchArtistsResponse, error) { - resp, err := s.client.SearchArtists(ctx, &metadataPb.SearchArtistsRequest{ - Query: query, - Limit: limit, - Offset: offset, - }) - if err != nil { - return nil, fmt.Errorf("searching artists: %w", err) - } - return resp, nil -} - -func (s *MetadataService) GetArtistAlbumsWithPagination(ctx context.Context, artistID string, limit, offset int32) (*metadataPb.GetArtistAlbumsResponse, error) { - resp, err := s.client.GetArtistAlbums(ctx, &metadataPb.GetArtistAlbumsRequest{ - ArtistId: artistID, - Limit: limit, - Offset: offset, - }) - if err != nil { - return nil, fmt.Errorf("fetching artist albums: %w", err) - } - return resp, nil -} - -func (s *MetadataService) GetAlbumTracks(ctx context.Context, albumExternalID string) ([]*metadataPb.Track, error) { - resp, err := s.client.GetAlbumTracks(ctx, &metadataPb.GetAlbumTracksRequest{ - AlbumId: albumExternalID, - }) - if err != nil { - return nil, fmt.Errorf("fetching album tracks: %w", err) - } - return resp.GetTracks(), nil -} - -func (s *MetadataService) GetArtistByExternalID(ctx context.Context, externalID string) (*database.Artist, error) { - return s.artists.GetByExternalID(ctx, externalID) -} - -func (s *MetadataService) GetAlbumByID(ctx context.Context, id string) (*database.Album, error) { - return s.albums.GetByID(ctx, id) -} - -func (s *MetadataService) GetAlbumByExternalID(ctx context.Context, externalID string) (*database.Album, error) { - return s.albums.GetByExternalID(ctx, externalID) -} - -func (s *MetadataService) GetAlbumsByArtistID(ctx context.Context, artistID string) ([]*database.Album, error) { - return s.albums.GetByArtistID(ctx, artistID) -} - -func (s *MetadataService) GetTracksByAlbumID(ctx context.Context, albumID string) ([]*database.Track, error) { - return s.tracks.GetByAlbumID(ctx, albumID) -} - -func (s *MetadataService) SetAlbumMonitorState(ctx context.Context, id string, state database.MonitorState) error { - return s.albums.SetMonitorState(ctx, id, state) -} - -func (s *MetadataService) PersistArtist(ctx context.Context, album *metadataPb.Album, state database.MonitorState) { - if len(album.GetArtists()) == 0 { - return - } - - artist := album.GetArtists()[0].GetArtist() - var genres []string - for _, g := range artist.GetGenres() { - genres = append(genres, g.GetName()) - } - - err := s.artists.Create(ctx, &database.Artist{ - ExternalID: artist.GetId(), - Name: artist.GetName(), - ArtistType: artist.GetArtistType(), - Country: artist.GetCountry(), - Genres: genres, - ImageURL: artist.GetImageUrl(), - MonitorState: state, - }) - if err != nil { - log.Warn().Err(err).Str("name", artist.GetName()).Msg("failed to persist artist") - } -} - -func (s *MetadataService) PersistAlbum(ctx context.Context, album *metadataPb.Album, state database.MonitorState) { - s.PersistAlbumForArtist(ctx, album, "", state) -} - -func (s *MetadataService) PersistAlbumsForArtist(ctx context.Context, metadataAlbums []*metadataPb.Album, artistDBID string, state database.MonitorState) { - if len(metadataAlbums) == 0 || artistDBID == "" { - return - } - - dbAlbums := make([]*database.Album, 0, len(metadataAlbums)) - for _, album := range metadataAlbums { - var genres []string - for _, g := range album.GetGenres() { - genres = append(genres, g.GetName()) - } - labelName := "" - if album.GetLabel() != nil { - labelName = album.GetLabel().GetName() - } - dbAlbums = append(dbAlbums, &database.Album{ - ExternalID: album.GetId(), - ArtistID: artistDBID, - Title: album.GetTitle(), - AlbumType: album.GetAlbumType(), - TotalTracks: int(album.GetTotalTracks()), - TotalDiscs: int(album.GetTotalDiscs()), - Label: labelName, - Genres: genres, - CoverURL: album.GetCoverUrl(), - MonitorState: state, - }) - } - - if err := s.albums.CreateBatch(ctx, dbAlbums); err != nil { - log.Warn().Err(err).Int("count", len(dbAlbums)).Msg("failed to batch persist albums") - } -} - -func (s *MetadataService) PersistAlbumForArtist(ctx context.Context, album *metadataPb.Album, artistDBID string, state database.MonitorState) { - if artistDBID == "" { - if len(album.GetArtists()) > 0 { - a, err := s.artists.GetByExternalID(ctx, album.GetArtists()[0].GetArtist().GetId()) - if err == nil { - artistDBID = a.ID - } - } - } - - if artistDBID == "" { - log.Trace().Str("album", album.GetTitle()).Msg("skipping album persist, no artist in DB") - return - } - - var genres []string - for _, g := range album.GetGenres() { - genres = append(genres, g.GetName()) - } - - labelName := "" - if album.GetLabel() != nil { - labelName = album.GetLabel().GetName() - } - - err := s.albums.Create(ctx, &database.Album{ - ExternalID: album.GetId(), - ArtistID: artistDBID, - Title: album.GetTitle(), - AlbumType: album.GetAlbumType(), - TotalTracks: int(album.GetTotalTracks()), - TotalDiscs: int(album.GetTotalDiscs()), - Label: labelName, - Genres: genres, - CoverURL: album.GetCoverUrl(), - MonitorState: state, - }) - if err != nil { - log.Warn().Err(err).Str("title", album.GetTitle()).Msg("failed to persist album") - } -} - -func (s *MetadataService) PersistTracks(ctx context.Context, albumDBID string, tracks []*metadataPb.Track) { - for _, t := range tracks { - err := s.tracks.Create(ctx, &database.Track{ - ExternalID: t.GetId(), - AlbumID: albumDBID, - Title: t.GetTitle(), - DurationMS: int(t.GetDurationMs()), - ISRC: t.GetIsrc(), - DiscNumber: int(t.GetDiscNumber()), - TrackNumber: int(t.GetTrackNumber()), - }) - if err != nil { - log.Warn().Err(err).Str("title", t.GetTitle()).Msg("failed to persist track") - } - } -} diff --git a/internal/monitor_workflow.go b/internal/monitor_workflow.go deleted file mode 100644 index 3b648a7..0000000 --- a/internal/monitor_workflow.go +++ /dev/null @@ -1,456 +0,0 @@ -package internal - -import ( - "context" - "fmt" - "sync" - "time" - - "github.com/rs/zerolog/log" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - pb "homelab.lan/music-agregator/gen/music_agregator/v1" - "homelab.lan/music-agregator/internal/database" -) - -var MaxPromptTimeout = 300 * time.Second - -type monitorWorkflow struct { - mode pb.InteractionMode - req *pb.StartMonitorRequest - service *MusicAgregatorService - publisher EventPublisher - - stream pb.MusicAgregatorService_MonitorAlbumStreamServer - decisions chan *pb.UserDecision - cancel context.CancelFunc - - addedHash string - workflowRunID string - - mu sync.Mutex - promptID int -} - -func (w *monitorWorkflow) nextPromptID() string { - w.mu.Lock() - defer w.mu.Unlock() - w.promptID++ - return fmt.Sprintf("prompt-%d", w.promptID) -} - -func (w *monitorWorkflow) promptAndWait(ctx context.Context, prompt *pb.PromptForDecision) (*pb.UserDecision, error) { - if w.mode == pb.InteractionMode_INTERACTION_MODE_AUTOMATIC { - return w.defaultDecision(prompt), nil - } - - if w.stream == nil { - return w.defaultDecision(prompt), nil - } - - if err := w.stream.Send(&pb.MonitorAlbumStreamResponse{ - Message: &pb.MonitorAlbumStreamResponse_Prompt{Prompt: prompt}, - }); err != nil { - return nil, err - } - - timeout := time.Duration(prompt.TimeoutSeconds) * time.Second - if timeout == 0 || timeout > MaxPromptTimeout { - timeout = MaxPromptTimeout - } - - timeoutCtx, cancel := context.WithTimeout(ctx, timeout) - defer cancel() - - select { - case decision := <-w.decisions: - if decision.PromptId != prompt.PromptId { - return nil, status.Error(codes.InvalidArgument, "prompt_id mismatch") - } - return decision, nil - case <-timeoutCtx.Done(): - return w.defaultDecision(prompt), nil - } -} - -func (w *monitorWorkflow) defaultDecision(prompt *pb.PromptForDecision) *pb.UserDecision { - decision := &pb.UserDecision{PromptId: prompt.PromptId} - - switch prompt.Type { - case pb.PromptType_PROMPT_TYPE_CONFIRM: - decision.Decision = &pb.UserDecision_Confirm{ - Confirm: prompt.GetConfirm().GetDefaultValue(), - } - case pb.PromptType_PROMPT_TYPE_SELECT_ONE: - decision.Decision = &pb.UserDecision_SelectedId{ - SelectedId: prompt.GetSelectOne().GetDefaultId(), - } - case pb.PromptType_PROMPT_TYPE_SELECT_MANY: - decision.Decision = &pb.UserDecision_SelectedIds{ - SelectedIds: &pb.SelectedIds{Ids: prompt.GetSelectMany().GetDefaultIds()}, - } - } - - return decision -} - -func (w *monitorWorkflow) receiveDecisions(ctx context.Context) { - if w.stream == nil { - return - } - - for { - select { - case <-ctx.Done(): - return - default: - } - - msg, err := w.stream.Recv() - if err != nil { - return - } - - if msg.GetCancel() != nil { - if w.cancel != nil { - w.cancel() - } - return - } - - if decision := msg.GetDecision(); decision != nil { - select { - case w.decisions <- decision: - default: - } - } - } -} - -func (w *monitorWorkflow) run(ctx context.Context) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_FETCHING_METADATA, "Fetching album metadata...", nil) - - album, err := w.service.metadata.GetAlbum(ctx, w.req.AlbumId) - if err != nil { - if ctx.Err() != nil { - return ctx.Err() - } - log.Error().Err(err).Str("album_id", w.req.AlbumId).Msg("failed to get album") - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_FETCHING_METADATA, err, false) - return err - } - - artistName := "" - if len(album.GetArtists()) > 0 { - artistName = album.GetArtists()[0].GetArtist().GetName() - } - - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_FETCHING_METADATA, - fmt.Sprintf("Got metadata: %s - %s", artistName, album.GetTitle()), - &pb.StreamAlbumInfo{ - Artist: artistName, - Title: album.GetTitle(), - ReleaseDate: album.GetReleaseDate(), - }) - - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_CHECKING_OWNED, "Checking if already owned...", nil) - - dbAlbum, _ := w.service.metadata.GetAlbumByExternalID(ctx, album.GetId()) - if dbAlbum != nil { - w.publisher.SetAlbumID(dbAlbum.ID) - w.service.metadata.SetAlbumMonitorState(ctx, dbAlbum.ID, database.Monitored) - dbAlbum.MonitorState = database.Monitored - - if w.workflowRunID == "" { - run := &database.WorkflowRun{AlbumID: dbAlbum.ID, Quality: w.req.Quality.String()} - if err := w.service.workflowRuns.Create(ctx, run); err != nil && err != database.ErrWorkflowAlreadyRunning { - log.Warn().Err(err).Msg("failed to create workflow run") - } else if err == nil { - w.workflowRunID = run.ID - w.publisher.SetWorkflowRunID(run.ID) - } - } - - qualityStr := normalizeQuality(w.req.Quality, 0, 0) - owned, err := w.service.downloads.HasAlbumInQuality(ctx, dbAlbum.ID, w.req.Quality.String(), qualityStr) - if err == nil && owned { - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_CHECKING_OWNED, - fmt.Sprintf("Already owned in %s quality", qualityStr), nil) - - if w.mode == pb.InteractionMode_INTERACTION_MODE_MANUAL { - decision, err := w.promptAndWait(ctx, &pb.PromptForDecision{ - PromptId: w.nextPromptID(), - Type: pb.PromptType_PROMPT_TYPE_CONFIRM, - Message: "Album already owned. Download anyway?", - - Options: &pb.PromptForDecision_Confirm{ - Confirm: &pb.ConfirmPrompt{ - ConfirmLabel: "Download anyway", - CancelLabel: "Skip", - DefaultValue: false, - }, - }, - }) - if err != nil { - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_CHECKING_OWNED, err, false) - return err - } - if !decision.GetConfirm() { - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_COMPLETE, "Skipped - already owned", nil) - return w.publisher.PublishResult(ctx, w.service.buildMonitorAlbumResponse(ctx, album, dbAlbum, nil)) - } - } else { - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_COMPLETE, "Already owned", nil) - return w.publisher.PublishResult(ctx, w.service.buildMonitorAlbumResponse(ctx, album, dbAlbum, nil)) - } - } - } - - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_SEARCHING_INDEXER, - fmt.Sprintf("Searching indexers for %s - %s...", artistName, album.GetTitle()), nil) - - searchResult, err := w.service.searchIndexer(album, w.req.IndexerOptions.GetTracker()) - if err != nil { - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_SEARCHING_INDEXER, err, true) - return err - } - - parsed := w.service.parseSearchResults(ctx, searchResult, album, func(phase string, current, total int) { - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_PARSING_RESULTS, - fmt.Sprintf("%s: %d/%d", phase, current, total), nil) - }) - - if len(parsed) > 0 { - summaries := make([]*pb.TorrentSummary, len(parsed)) - for i, p := range parsed { - summaries[i] = &pb.TorrentSummary{ - Id: fmt.Sprintf("torrent-%d", i), - Title: p.item.Title, - Tracker: p.item.Tracker, - Seeders: int32(p.item.Seeders), - Format: p.rel.Format.String(), - Lossless: p.rel.Format.IsLossless(), - } - } - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_PARSING_RESULTS, - fmt.Sprintf("Parsed %d from %d torrents", len(parsed), len(searchResult.Items)), - &pb.TorrentList{Torrents: summaries}) - } else { - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_PARSING_RESULTS, - fmt.Sprintf("Found %d torrents, none parseable", len(searchResult.Items)), nil) - } - - if len(parsed) == 0 { - err := fmt.Errorf("no torrents found for %s", album.GetTitle()) - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_PARSING_RESULTS, err, false) - return err - } - - parsed = filterByAlbumMatch(parsed, album.GetTitle(), artistName) - if len(parsed) == 0 { - err := fmt.Errorf("no torrents match album title %q", album.GetTitle()) - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_PARSING_RESULTS, err, false) - return err - } - - if w.mode == pb.InteractionMode_INTERACTION_MODE_MANUAL && len(parsed) > 1 { - options := make([]*pb.SelectOption, len(parsed)) - defaultIDs := make([]string, len(parsed)) - for i, p := range parsed { - id := fmt.Sprintf("torrent-%d", i) - options[i] = &pb.SelectOption{ - Id: id, - Label: p.item.Title, - Description: fmt.Sprintf("%s - %d seeders", p.item.Tracker, p.item.Seeders), - } - defaultIDs[i] = id - } - - decision, err := w.promptAndWait(ctx, &pb.PromptForDecision{ - PromptId: w.nextPromptID(), - Type: pb.PromptType_PROMPT_TYPE_SELECT_MANY, - Message: "Select torrents to consider", - - Options: &pb.PromptForDecision_SelectMany{ - SelectMany: &pb.SelectManyPrompt{ - Options: options, - DefaultIds: defaultIDs, - MinSelections: 1, - MaxSelections: int32(len(parsed)), - }, - }, - }) - if err != nil { - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_PARSING_RESULTS, err, false) - return err - } - - selectedIDs := make(map[string]bool) - if ids := decision.GetSelectedIds(); ids != nil { - for _, id := range ids.GetIds() { - selectedIDs[id] = true - } - } - - var selected []parsedItem - for i, p := range parsed { - id := fmt.Sprintf("torrent-%d", i) - if selectedIDs[id] { - selected = append(selected, p) - } - } - if len(selected) > 0 { - parsed = selected - } - } - - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_FILTERING_QUALITY, - fmt.Sprintf("Filtering %d results by quality...", len(parsed)), nil) - - filtered := filterByQuality(parsed, w.req.Quality) - if len(filtered) == 0 { - err := fmt.Errorf("no releases match quality filter for %s", album.GetTitle()) - log.Warn().Str("album", album.GetTitle()).Str("quality", w.req.Quality.String()).Msg("no releases match quality filter") - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_FILTERING_QUALITY, err, false) - return err - } - - filtered = filterByActiveSeeders(filtered) - if len(filtered) == 0 { - err := fmt.Errorf("no releases with active seeders for %s", album.GetTitle()) - log.Warn().Str("album", album.GetTitle()).Msg("no releases with active seeders") - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_FILTERING_QUALITY, err, false) - return err - } - - var best parsedItem - if w.mode == pb.InteractionMode_INTERACTION_MODE_MANUAL && len(filtered) > 1 { - options := make([]*pb.SelectOption, len(filtered)) - for i, p := range filtered { - options[i] = &pb.SelectOption{ - Id: fmt.Sprintf("release-%d", i), - Label: p.item.Title, - Description: fmt.Sprintf("%s - %d seeders - %s", p.item.Tracker, p.item.Seeders, p.rel.Format.String()), - } - } - - bestIdx := 0 - for i, p := range filtered { - if p.item.Seeders > filtered[bestIdx].item.Seeders { - bestIdx = i - } - } - - decision, err := w.promptAndWait(ctx, &pb.PromptForDecision{ - PromptId: w.nextPromptID(), - Type: pb.PromptType_PROMPT_TYPE_SELECT_ONE, - Message: "Select release", - - Options: &pb.PromptForDecision_SelectOne{ - SelectOne: &pb.SelectOnePrompt{ - Options: options, - DefaultId: fmt.Sprintf("release-%d", bestIdx), - }, - }, - }) - if err != nil { - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_SELECTING_RELEASE, err, false) - return err - } - - selectedIdx := 0 - if id := decision.GetSelectedId(); id != "" { - for i := range filtered { - if fmt.Sprintf("release-%d", i) == id { - selectedIdx = i - break - } - } - } - best = filtered[selectedIdx] - } else { - best = selectBestRelease(filtered, album.GetTitle()) - } - - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_SELECTING_RELEASE, - fmt.Sprintf("Selected: %s (%d seeders)", best.item.Title, best.item.Seeders), - &pb.ReleaseInfo{ - InfoHash: best.rel.InfoHash, - Format: best.rel.Format.String(), - BitDepth: int32(best.rel.BitDepth), - SampleRate: int32(best.rel.SampleRate), - Seeders: int32(best.item.Seeders), - Tracker: best.item.Tracker, - }) - - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_ADDING_TORRENT, - fmt.Sprintf("Adding torrent: %s...", best.item.Title), nil) - - if w.mode == pb.InteractionMode_INTERACTION_MODE_MANUAL { - decision, err := w.promptAndWait(ctx, &pb.PromptForDecision{ - PromptId: w.nextPromptID(), - Type: pb.PromptType_PROMPT_TYPE_CONFIRM, - Message: fmt.Sprintf("Add torrent '%s' to client?", best.item.Title), - - Options: &pb.PromptForDecision_Confirm{ - Confirm: &pb.ConfirmPrompt{ - ConfirmLabel: "Add", - CancelLabel: "Skip", - DefaultValue: true, - }, - }, - }) - if err != nil { - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_ADDING_TORRENT, err, false) - return err - } - if !decision.GetConfirm() { - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_COMPLETE, "Skipped by user", nil) - return w.publisher.PublishResult(ctx, w.service.buildMonitorAlbumResponse(ctx, album, dbAlbum, nil)) - } - } - - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_SAVING, "Saving to database...", nil) - - dbAlbum, _ = w.service.metadata.GetAlbumByExternalID(ctx, album.GetId()) - if dbAlbum == nil { - w.service.metadata.PersistArtist(ctx, album, database.Monitored) - w.service.metadata.PersistAlbum(ctx, album, database.Monitored) - dbAlbum, _ = w.service.metadata.GetAlbumByExternalID(ctx, album.GetId()) - } - if dbAlbum != nil { - w.publisher.SetAlbumID(dbAlbum.ID) - w.service.saveTorrentAndDownload(ctx, dbAlbum.ID, w.workflowRunID, best) - } else { - log.Warn().Str("album_id", w.req.AlbumId).Msg("album not in DB after persist attempt, skipping torrent/download persistence") - } - - w.addedHash = best.rel.InfoHash - - if err := w.service.addToTorrentClient(best); err != nil { - w.publisher.PublishError(ctx, pb.MonitorStep_MONITOR_STEP_ADDING_TORRENT, err, true) - return err - } - - w.publisher.PublishStatus(ctx, pb.MonitorStep_MONITOR_STEP_COMPLETE, "Done!", nil) - - return w.publisher.PublishResult(ctx, w.service.buildMonitorAlbumResponse(ctx, album, dbAlbum, &best)) -} - -func (w *monitorWorkflow) cleanup(ctx context.Context) { - if w.addedHash != "" { - if err := w.service.torrentClient.DeleteTorrent(w.addedHash); err != nil { - log.Warn().Err(err).Str("hash", w.addedHash).Msg("failed to delete torrent during cancel cleanup") - } - if err := w.service.downloads.SetCancelledByQbitHash(ctx, w.addedHash); err != nil { - log.Warn().Err(err).Str("hash", w.addedHash).Msg("failed to cancel download during cleanup") - } - } -} diff --git a/internal/musicfs/client.go b/internal/musicfs/client.go deleted file mode 100644 index 6c650f0..0000000 --- a/internal/musicfs/client.go +++ /dev/null @@ -1,32 +0,0 @@ -package musicfs - -import ( - "fmt" - - "github.com/rs/zerolog/log" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - pb "homelab.lan/music-agregator/gen/musicfs/v1" -) - -type Client struct { - MusicFS pb.MusicFSClient - Metadata pb.MetadataServiceClient -} - -func NewClient(endpoint string) (*Client, *grpc.ClientConn, error) { - log.Trace().Str("endpoint", endpoint).Msg("connecting to musicfs") - - conn, err := grpc.NewClient(endpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return nil, nil, fmt.Errorf("connecting to musicfs: %w", err) - } - - log.Info().Str("endpoint", endpoint).Msg("musicfs connected") - - return &Client{ - MusicFS: pb.NewMusicFSClient(conn), - Metadata: pb.NewMetadataServiceClient(conn), - }, conn, nil -} diff --git a/internal/musicfs/enricher.go b/internal/musicfs/enricher.go deleted file mode 100644 index d143eaa..0000000 --- a/internal/musicfs/enricher.go +++ /dev/null @@ -1,92 +0,0 @@ -package musicfs - -import ( - "context" - "fmt" - "io" - - "github.com/rs/zerolog/log" - - metadataPb "homelab.lan/music-agregator/gen/metadata/v1" - pb "homelab.lan/music-agregator/gen/musicfs/v1" -) - -func (c *Client) EnrichFiles(ctx context.Context, files []SyncedFile, album *metadataPb.Album) error { - if len(files) == 0 || album == nil { - return nil - } - - genre := firstGenreName(album.GetGenres()) - label := labelName(album.GetLabel()) - albumType := album.GetAlbumType() - coverURL := album.GetCoverUrl() - - var items []*pb.BatchUpdateItem - for _, f := range files { - meta := &pb.UpdateMetadataRequest{ - FileId: f.FileID, - } - if genre != "" { - meta.Genre = &genre - } - if label != "" { - meta.Label = &label - } - if albumType != "" { - meta.AlbumType = &albumType - } - if coverURL != "" { - meta.CoverUrl = &coverURL - } - items = append(items, &pb.BatchUpdateItem{ - FileId: f.FileID, - Metadata: meta, - }) - } - - stream, err := c.Metadata.BatchUpdateMetadata(ctx, &pb.BatchUpdateRequest{Items: items}) - if err != nil { - return fmt.Errorf("batch update: %w", err) - } - - var updated, failed int - for { - progress, err := stream.Recv() - if err == io.EOF { - break - } - if err != nil { - return fmt.Errorf("batch update stream: %w", err) - } - if progress.ErrorMessage != nil { - log.Warn(). - Int64("file_id", progress.GetCurrentFileId()). - Str("error", progress.GetErrorMessage()). - Msg("batch update item failed") - failed++ - } else { - updated++ - } - } - - log.Info(). - Int("updated", updated). - Int("failed", failed). - Msg("enrichment batch complete") - - return nil -} - -func firstGenreName(genres []*metadataPb.Genre) string { - if len(genres) == 0 { - return "" - } - return genres[0].GetName() -} - -func labelName(label *metadataPb.Label) string { - if label == nil { - return "" - } - return label.GetName() -} diff --git a/internal/musicfs/subdir.go b/internal/musicfs/subdir.go deleted file mode 100644 index 65db4df..0000000 --- a/internal/musicfs/subdir.go +++ /dev/null @@ -1,20 +0,0 @@ -package musicfs - -import ( - "path/filepath" - "strings" - - "github.com/rs/zerolog/log" -) - -func DeriveSubdir(originRoot, contentPath string) string { - rel, err := filepath.Rel(originRoot, contentPath) - if err != nil || strings.HasPrefix(rel, "..") { - log.Warn(). - Str("origin_root", originRoot). - Str("content_path", contentPath). - Msg("content path outside origin root, falling back to full rescan") - return "" - } - return rel -} diff --git a/internal/musicfs/subdir_test.go b/internal/musicfs/subdir_test.go deleted file mode 100644 index 0738021..0000000 --- a/internal/musicfs/subdir_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package musicfs - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestDeriveSubdir(t *testing.T) { - tests := []struct { - name string - originRoot string - contentPath string - expected string - }{ - { - name: "normal subdirectory", - originRoot: "/downloads/music", - contentPath: "/downloads/music/Metallica - Master of Puppets (1986) [FLAC]", - expected: "Metallica - Master of Puppets (1986) [FLAC]", - }, - { - name: "nested subdirectory", - originRoot: "/downloads/music", - contentPath: "/downloads/music/Metal/Metallica/Master of Puppets", - expected: "Metal/Metallica/Master of Puppets", - }, - { - name: "same directory", - originRoot: "/downloads/music", - contentPath: "/downloads/music", - expected: ".", - }, - { - name: "outside origin root falls back to empty", - originRoot: "/downloads/music", - contentPath: "/tmp/other/path", - expected: "", - }, - { - name: "parent directory falls back to empty", - originRoot: "/downloads/music/sub", - contentPath: "/downloads/music", - expected: "", - }, - { - name: "trailing slash on root", - originRoot: "/downloads/music/", - contentPath: "/downloads/music/Album", - expected: "Album", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := DeriveSubdir(tt.originRoot, tt.contentPath) - assert.Equal(t, tt.expected, result) - }) - } -} diff --git a/internal/musicfs/sync.go b/internal/musicfs/sync.go deleted file mode 100644 index 1353a3f..0000000 --- a/internal/musicfs/sync.go +++ /dev/null @@ -1,62 +0,0 @@ -package musicfs - -import ( - "context" - "fmt" - "io" - - "github.com/rs/zerolog/log" - - pb "homelab.lan/music-agregator/gen/musicfs/v1" -) - -type SyncedFile struct { - Path string - FileID int64 - VirtualPath string -} - -type RescanResult struct { - NewFiles []SyncedFile - BytesSynced uint64 -} - -func (c *Client) TriggerRescan(ctx context.Context, originID string, subdir string) (*RescanResult, error) { - stream, err := c.MusicFS.RescanOrigin(ctx, &pb.OriginRequest{ - OriginId: originID, - Subdir: &subdir, - }) - if err != nil { - return nil, fmt.Errorf("rescan origin: %w", err) - } - - var result RescanResult - for { - progress, err := stream.Recv() - if err == io.EOF { - break - } - if err != nil { - return nil, fmt.Errorf("rescan stream: %w", err) - } - - log.Trace(). - Str("phase", progress.GetPhase()). - Uint32("current", progress.GetCurrent()). - Uint32("total", progress.GetTotal()). - Msg("rescan progress") - - if progress.GetPhase() == "complete" { - for _, sf := range progress.GetNewFiles() { - result.NewFiles = append(result.NewFiles, SyncedFile{ - Path: sf.GetPath(), - FileID: sf.GetFileId(), - VirtualPath: sf.GetVirtualPath(), - }) - } - result.BytesSynced = progress.GetBytesSynced() - } - } - - return &result, nil -} diff --git a/internal/registrable.go b/internal/registrable.go deleted file mode 100644 index 1fa25c2..0000000 --- a/internal/registrable.go +++ /dev/null @@ -1,7 +0,0 @@ -package internal - -import "google.golang.org/grpc" - -type Registrable interface { - Register(server *grpc.Server) -} diff --git a/internal/release/release.go b/internal/release/release.go deleted file mode 100644 index c0c1aa0..0000000 --- a/internal/release/release.go +++ /dev/null @@ -1,218 +0,0 @@ -package release - -import ( - pb "homelab.lan/music-agregator/gen/music_agregator/indexer/v1" -) - -type Type int - -const ( - TypeUnknown Type = iota - TypeAlbum - TypeEP - TypeSingle - TypeDiscography - TypeCollection - TypeCompilation - TypeSoundtrack - TypeLive - TypeBootleg -) - -func (t Type) String() string { - switch t { - case TypeAlbum: - return "album" - case TypeEP: - return "ep" - case TypeSingle: - return "single" - case TypeDiscography: - return "discography" - case TypeCollection: - return "collection" - case TypeCompilation: - return "compilation" - case TypeSoundtrack: - return "soundtrack" - case TypeLive: - return "live" - case TypeBootleg: - return "bootleg" - default: - return "unknown" - } -} - -func (t Type) Priority() int { - switch t { - case TypeAlbum, TypeEP, TypeSingle: - return 1 - case TypeLive: - return 2 - case TypeSoundtrack: - return 3 - case TypeCollection: - return 4 - case TypeDiscography: - return 5 - case TypeCompilation: - return 6 - case TypeBootleg: - return 7 - default: - return 99 - } -} - -type AudioFormat int - -const ( - FormatUnknown AudioFormat = iota - FormatFLAC - FormatMP3 - FormatAAC - FormatAPE - FormatWavPack - FormatALAC - FormatOGG - FormatWAV -) - -func (f AudioFormat) String() string { - switch f { - case FormatFLAC: - return "FLAC" - case FormatMP3: - return "MP3" - case FormatAAC: - return "AAC" - case FormatAPE: - return "APE" - case FormatWavPack: - return "WavPack" - case FormatALAC: - return "ALAC" - case FormatOGG: - return "OGG" - case FormatWAV: - return "WAV" - default: - return "unknown" - } -} - -func (f AudioFormat) IsLossless() bool { - switch f { - case FormatFLAC, FormatAPE, FormatWavPack, FormatALAC, FormatWAV: - return true - default: - return false - } -} - -type Source int - -const ( - SourceUnknown Source = iota - SourceCD - SourceWEB - SourceVinyl - SourceCassette - SourceDVD - SourceBluRay -) - -func (s Source) String() string { - switch s { - case SourceCD: - return "CD" - case SourceWEB: - return "WEB" - case SourceVinyl: - return "Vinyl" - case SourceCassette: - return "Cassette" - case SourceDVD: - return "DVD" - case SourceBluRay: - return "BluRay" - default: - return "unknown" - } -} - -type Release struct { - RawTitle string - - Artist string - Album string - Year int - YearEnd int - - Type Type - Genres []string - - Format AudioFormat - Source Source - Bitrate string - BitDepth int - SampleRate int - RipType string - - ReleaseCount int - Tags []string - Label string - CatalogNum string - - InfoHash string - TrackCount int - TrackNames []string - AudioFileCount int - TotalAudioSize int64 - HasCoverArt bool - HasCueSheet bool - HasRipLog bool - - ParsedSuccessfully bool - ParseErrors []string -} - -func (r *Release) IsDiscography() bool { - return r.Type == TypeDiscography || r.Type == TypeCollection -} - -func (r *Release) IsSingleRelease() bool { - return r.Type == TypeAlbum || r.Type == TypeEP || r.Type == TypeSingle -} - -func (r *Release) HasYearRange() bool { - return r.YearEnd > 0 && r.YearEnd != r.Year -} - -func (r *Release) ToProto() *pb.Release { - if r == nil { - return nil - } - return &pb.Release{ - RawTitle: r.RawTitle, - Artist: r.Artist, - Album: r.Album, - Year: int32(r.Year), - YearEnd: int32(r.YearEnd), - Type: r.Type.String(), - Genres: r.Genres, - Format: r.Format.String(), - Source: r.Source.String(), - Bitrate: r.Bitrate, - BitDepth: int32(r.BitDepth), - SampleRate: int32(r.SampleRate), - RipType: r.RipType, - ReleaseCount: int32(r.ReleaseCount), - Tags: r.Tags, - Label: r.Label, - CatalogNum: r.CatalogNum, - ParsedSuccessfully: r.ParsedSuccessfully, - ParseErrors: r.ParseErrors, - } -} diff --git a/internal/server.go b/internal/server.go deleted file mode 100644 index a64639b..0000000 --- a/internal/server.go +++ /dev/null @@ -1,330 +0,0 @@ -package internal - -import ( - "context" - "encoding/json" - "time" - - "github.com/jackc/pgx/v5" - "github.com/riverqueue/river" - "github.com/rs/zerolog/log" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - pb "homelab.lan/music-agregator/gen/music_agregator/v1" - "homelab.lan/music-agregator/internal/config" - "homelab.lan/music-agregator/internal/database" - "homelab.lan/music-agregator/internal/eventbus" - "homelab.lan/music-agregator/internal/musicfs" - "homelab.lan/music-agregator/internal/torrent" -) - -type MusicAgregatorServer struct { - service *MusicAgregatorService - bus *eventbus.EventBus - registry *WorkflowRegistry - pb.UnimplementedMusicAgregatorServiceServer -} - -func NewMusicAgregatorServer(cfg config.Config, riverClient *river.Client[pgx.Tx], torrentClient torrent.TorrentClient, pathMapper *torrent.PathMapper, db *database.DB, bus *eventbus.EventBus, musicfsClient *musicfs.Client) (*MusicAgregatorServer, error) { - service, err := NewMusicAgregatorService(cfg, riverClient, torrentClient, pathMapper, db, musicfsClient) - if err != nil { - log.Err(err).Msg("failed to create MusicAgregatorService") - return nil, err - } - return &MusicAgregatorServer{ - service: service, - bus: bus, - registry: NewWorkflowRegistry(bus), - }, nil -} - -func NewMusicAgregatorServerWithService(service *MusicAgregatorService) *MusicAgregatorServer { - bus := eventbus.New() - return &MusicAgregatorServer{ - service: service, - bus: bus, - registry: NewWorkflowRegistry(bus), - } -} - -func NewMusicAgregatorServerWithDeps(service *MusicAgregatorService, bus *eventbus.EventBus, registry *WorkflowRegistry) *MusicAgregatorServer { - return &MusicAgregatorServer{ - service: service, - bus: bus, - registry: registry, - } -} - -func (s *MusicAgregatorServer) GetArtists(ctx context.Context, req *pb.GetArtistsRequest) (*pb.GetArtistsResponse, error) { - return s.service.GetArtists(ctx, req) -} - -func (s *MusicAgregatorServer) GetAlbum(ctx context.Context, req *pb.GetAlbumRequest) (*pb.GetAlbumResponse, error) { - return s.service.GetAlbum(ctx, req) -} - -func (s *MusicAgregatorServer) MonitorAlbum(ctx context.Context, req *pb.MonitorAlbumRequest) (*pb.MonitorAlbumResponse, error) { - return s.service.MonitorAlbum(ctx, req) -} - -func (s *MusicAgregatorServer) MonitorAlbumStream(stream pb.MusicAgregatorService_MonitorAlbumStreamServer) error { - msg, err := stream.Recv() - if err != nil { - return err - } - - startReq := msg.GetStart() - if startReq == nil { - return status.Error(codes.InvalidArgument, "first message must be StartMonitorRequest") - } - - if startReq.Mode == pb.InteractionMode_INTERACTION_MODE_MANUAL { - return s.runManualWorkflow(stream, startReq) - } - return s.runAutomaticWorkflow(stream, startReq) -} - -func (s *MusicAgregatorServer) runManualWorkflow(stream pb.MusicAgregatorService_MonitorAlbumStreamServer, startReq *pb.StartMonitorRequest) error { - ctx, cancel := context.WithCancel(stream.Context()) - defer cancel() - - albumKey := startReq.AlbumId - quality := startReq.Quality.String() - topic := albumKey + ":" + quality - - dbPublisher := newDBEventPublisher("", quality, s.service.albumEvents, s.bus, topic) - publisher := newStreamEventPublisher(dbPublisher, stream) - - workflow := &monitorWorkflow{ - mode: startReq.Mode, - req: startReq, - service: s.service, - publisher: publisher, - stream: stream, - decisions: make(chan *pb.UserDecision, 1), - cancel: cancel, - } - - go workflow.receiveDecisions(ctx) - - err := workflow.run(ctx) - - if ctx.Err() != nil { - cleanupCtx := context.Background() - workflow.cleanup(cleanupCtx) - if workflow.workflowRunID != "" { - s.service.workflowRuns.SetCancelled(cleanupCtx, workflow.workflowRunID) - } - } else if workflow.workflowRunID != "" { - if err != nil { - s.service.workflowRuns.SetFailed(context.Background(), workflow.workflowRunID, err.Error()) - } else { - s.service.workflowRuns.SetCompleted(context.Background(), workflow.workflowRunID) - } - } - - return err -} - -func (s *MusicAgregatorServer) runAutomaticWorkflow(stream pb.MusicAgregatorService_MonitorAlbumStreamServer, startReq *pb.StartMonitorRequest) error { - albumKey := startReq.AlbumId - quality := startReq.Quality.String() - - entry, created := s.registry.GetOrCreate(context.Background(), albumKey, quality) - - sub, cleanup := s.bus.Subscribe(entry.Topic) - defer cleanup() - - if created { - s.registry.WaitGroup().Add(1) - go func() { - defer s.registry.WaitGroup().Done() - defer s.registry.Remove(albumKey, quality) - - publisher := newDBEventPublisher("", quality, s.service.albumEvents, s.bus, entry.Topic) - - workflow := &monitorWorkflow{ - mode: startReq.Mode, - req: startReq, - service: s.service, - publisher: publisher, - } - - err := workflow.run(entry.Ctx) - - if workflow.workflowRunID != "" { - if err != nil { - if entry.Ctx.Err() == context.Canceled { - s.service.workflowRuns.SetCancelled(context.Background(), workflow.workflowRunID) - } else { - s.service.workflowRuns.SetFailed(context.Background(), workflow.workflowRunID, err.Error()) - } - } else { - s.service.workflowRuns.SetCompleted(context.Background(), workflow.workflowRunID) - } - } - }() - } - - for { - select { - case <-sub.C: - for { - event, ok := sub.Ring.Pop() - if !ok { - break - } - if err := s.sendEventToStream(stream, event); err != nil { - return nil - } - if event.EventType == "result" || event.EventType == "error" { - return nil - } - } - case <-stream.Context().Done(): - return nil - } - } -} - -func (s *MusicAgregatorServer) sendEventToStream(stream pb.MusicAgregatorService_MonitorAlbumStreamServer, event *eventbus.Event) error { - resp := &pb.MonitorAlbumStreamResponse{} - - step := pb.MonitorStep(pb.MonitorStep_value[event.Step]) - - switch event.EventType { - case "status": - status := &pb.StatusUpdate{Step: step, Message: event.Message} - - switch v := event.Data.(type) { - case *pb.StreamAlbumInfo: - status.Data = &pb.StatusUpdate_AlbumInfo{AlbumInfo: v} - case *pb.TorrentList: - status.Data = &pb.StatusUpdate_Torrents{Torrents: v} - case *pb.ReleaseInfo: - status.Data = &pb.StatusUpdate_ReleaseInfo{ReleaseInfo: v} - } - - resp.Message = &pb.MonitorAlbumStreamResponse_Status{Status: status} - - case "error": - recoverable := false - if data, ok := event.Data.(map[string]bool); ok { - recoverable = data["recoverable"] - } - resp.Message = &pb.MonitorAlbumStreamResponse_Error{ - Error: &pb.ErrorUpdate{FailedStep: step, Message: event.Message, Recoverable: recoverable}, - } - - case "result": - if result, ok := event.Data.(*pb.MonitorAlbumResponse); ok { - resp.Message = &pb.MonitorAlbumStreamResponse_Result{Result: result} - } else if event.Data != nil { - if jsonBytes, ok := event.Data.(json.RawMessage); ok { - var result pb.MonitorAlbumResponse - if err := json.Unmarshal(jsonBytes, &result); err == nil { - resp.Message = &pb.MonitorAlbumStreamResponse_Result{Result: &result} - } - } - } - } - - return stream.Send(resp) -} - -func (s *MusicAgregatorServer) AnalyzeAlbumRelease(ctx context.Context, req *pb.AnalyzeAlbumReleaseRequest) (*pb.AnalyzeAlbumReleaseResponse, error) { - return s.service.AnalyzeAlbumRelease(ctx, req) -} - -func (s *MusicAgregatorServer) SearchArtists(ctx context.Context, req *pb.SearchArtistsRequest) (*pb.SearchArtistsResponse, error) { - return s.service.SearchArtists(ctx, req) -} - -func (s *MusicAgregatorServer) GetArtistAlbums(ctx context.Context, req *pb.GetArtistAlbumsRequest) (*pb.GetArtistAlbumsResponse, error) { - return s.service.GetArtistAlbums(ctx, req) -} - -func (s *MusicAgregatorServer) ResyncAlbum(ctx context.Context, req *pb.ResyncAlbumRequest) (*pb.ResyncAlbumResponse, error) { - return s.service.ResyncAlbum(ctx, req.GetAlbumId()) -} - -func (s *MusicAgregatorServer) Register(server *grpc.Server) { - pb.RegisterMusicAgregatorServiceServer(server, s) -} - -func (s *MusicAgregatorServer) SubscribeEvents(req *pb.SubscribeEventsRequest, stream pb.MusicAgregatorService_SubscribeEventsServer) error { - ctx := stream.Context() - - sub, cleanup := s.bus.SubscribeGlobal() - defer cleanup() - - if req.SinceSeq > 0 { - events, err := s.service.albumEvents.GetAfterSeq(ctx, req.SinceSeq) - if err == nil { - for _, e := range events { - if err := stream.Send(albumEventToProto(e)); err != nil { - return err - } - } - } - } - - var lastSentSeq int64 - if req.SinceSeq > 0 { - lastSentSeq = req.SinceSeq - } - - for { - select { - case <-sub.C: - for { - event, ok := sub.Ring.Pop() - if !ok { - break - } - if event.Seq > lastSentSeq { - pbEvent := busEventToAlbumEvent(event) - if err := stream.Send(pbEvent); err != nil { - return nil - } - lastSentSeq = event.Seq - } - } - case <-ctx.Done(): - return nil - } - } -} - -func albumEventToProto(e *database.AlbumEvent) *pb.AlbumEvent { - return &pb.AlbumEvent{ - Seq: e.Seq, - WorkflowRunId: e.WorkflowRunID, - AlbumId: e.AlbumID, - EventType: e.EventType, - Step: e.Step, - Message: e.Message, - DataJson: e.DataJSON, - TimestampMs: e.CreatedAt.UnixMilli(), - } -} - -func busEventToAlbumEvent(e *eventbus.Event) *pb.AlbumEvent { - var dataJSON []byte - if e.Data != nil { - dataJSON, _ = json.Marshal(e.Data) - } - return &pb.AlbumEvent{ - Seq: e.Seq, - WorkflowRunId: e.WorkflowRunID, - AlbumId: e.AlbumID, - Quality: e.Quality, - EventType: e.EventType, - Step: e.Step, - Message: e.Message, - DataJson: dataJSON, - TimestampMs: time.Now().UnixMilli(), - } -} diff --git a/internal/service.go b/internal/service.go deleted file mode 100644 index 969c5b4..0000000 --- a/internal/service.go +++ /dev/null @@ -1,1454 +0,0 @@ -package internal - -import ( - "context" - "fmt" - "io" - "net/http" - "regexp" - "sort" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/jackc/pgx/v5" - "github.com/riverqueue/river" - "github.com/rs/zerolog/log" - "golang.org/x/sync/errgroup" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - metadataPb "homelab.lan/music-agregator/gen/metadata/v1" - pb "homelab.lan/music-agregator/gen/music_agregator/v1" - - "homelab.lan/music-agregator/internal/analysis" - "homelab.lan/music-agregator/internal/config" - "homelab.lan/music-agregator/internal/database" - "homelab.lan/music-agregator/internal/indexer" - albumMatcher "homelab.lan/music-agregator/internal/matcher" - "homelab.lan/music-agregator/internal/metadata" - "homelab.lan/music-agregator/internal/musicfs" - "homelab.lan/music-agregator/internal/release" - "homelab.lan/music-agregator/internal/torrent" - torrentParser "homelab.lan/music-agregator/internal/tracker" - "homelab.lan/music-agregator/internal/workers" -) - -type parsedItem struct { - item *indexer.SearchItemResult - rel *release.Release - torrentData []byte - realSeeders int -} - -type MusicAgregatorService struct { - config config.Config - metadata *metadata.MetadataService - indexer indexer.Searcher - torrentClient torrent.TorrentClient - magnetResolver torrentParser.Resolver - riverClient *river.Client[pgx.Tx] - pathMapper *torrent.PathMapper - torrents *database.TorrentRepository - downloads *database.DownloadRepository - artists *database.ArtistRepository - downloadFiles *database.DownloadFileRepository - albumReleases *database.AlbumReleaseRepository - trackReleases *database.TrackReleaseRepository - analyzer *analysis.ReleaseAnalyzer - workflowRuns *database.WorkflowRunRepository - albumEvents *database.AlbumEventRepository - musicfsClient *musicfs.Client - shutdownCtx context.Context - shutdownCancel context.CancelFunc -} - -func NewMusicAgregatorService(cfg config.Config, riverClient *river.Client[pgx.Tx], torrentClient torrent.TorrentClient, pathMapper *torrent.PathMapper, db *database.DB, musicfsClient *musicfs.Client) (*MusicAgregatorService, error) { - idx, err := indexer.NewIndexerService(cfg, riverClient, nil) - if err != nil { - log.Err(err).Msg("failed to create IndexerService") - return nil, err - } - - metadataClient, _, err := metadata.NewMetadataClient(cfg.Metadata.Endpoint) - if err != nil { - log.Err(err).Msg("failed to create metadata client") - return nil, err - } - - magnetResolver, err := torrentParser.NewMagnetResolver(30 * time.Second) - if err != nil { - log.Err(err).Msg("failed to create magnet resolver") - return nil, err - } - - ctx, cancel := context.WithCancel(context.Background()) - - return &MusicAgregatorService{ - config: cfg, - metadata: metadata.NewMetadataService(metadataClient, db), - indexer: idx, - torrentClient: torrentClient, - magnetResolver: magnetResolver, - riverClient: riverClient, - pathMapper: pathMapper, - torrents: database.NewTorrentRepository(db.Pool), - downloads: database.NewDownloadRepository(db.Pool), - artists: database.NewArtistRepository(db.Pool), - downloadFiles: database.NewDownloadFileRepository(db.Pool), - albumReleases: database.NewAlbumReleaseRepository(db.Pool), - trackReleases: database.NewTrackReleaseRepository(db.Pool), - analyzer: analysis.NewReleaseAnalyzer(db), - workflowRuns: database.NewWorkflowRunRepository(db.Pool), - albumEvents: database.NewAlbumEventRepository(db.Pool), - musicfsClient: musicfsClient, - shutdownCtx: ctx, - shutdownCancel: cancel, - }, nil -} - -func NewMusicAgregatorServiceWithDeps( - metadata *metadata.MetadataService, - searcher indexer.Searcher, - torrentClient torrent.TorrentClient, - magnetResolver torrentParser.Resolver, - riverClient *river.Client[pgx.Tx], - pathMapper *torrent.PathMapper, - db *database.DB, -) *MusicAgregatorService { - ctx, cancel := context.WithCancel(context.Background()) - - return &MusicAgregatorService{ - metadata: metadata, - indexer: searcher, - torrentClient: torrentClient, - magnetResolver: magnetResolver, - riverClient: riverClient, - pathMapper: pathMapper, - torrents: database.NewTorrentRepository(db.Pool), - downloads: database.NewDownloadRepository(db.Pool), - artists: database.NewArtistRepository(db.Pool), - downloadFiles: database.NewDownloadFileRepository(db.Pool), - albumReleases: database.NewAlbumReleaseRepository(db.Pool), - trackReleases: database.NewTrackReleaseRepository(db.Pool), - analyzer: analysis.NewReleaseAnalyzer(db), - workflowRuns: database.NewWorkflowRunRepository(db.Pool), - albumEvents: database.NewAlbumEventRepository(db.Pool), - shutdownCtx: ctx, - shutdownCancel: cancel, - } -} - -func (s *MusicAgregatorService) Close() { - if s.shutdownCancel != nil { - s.shutdownCancel() - } - if closer, ok := s.magnetResolver.(interface{ Close() }); ok { - closer.Close() - } -} - -func (s *MusicAgregatorService) RecoverWorkflows(ctx context.Context) { - stale, err := s.workflowRuns.GetRunning(ctx) - if err != nil { - log.Error().Err(err).Msg("failed to query stale workflow runs for recovery") - return - } - - if len(stale) == 0 { - return - } - - for _, run := range stale { - downloads, err := s.downloads.GetByAlbumID(ctx, run.AlbumID) - if err != nil { - log.Error().Err(err).Str("workflow_run_id", run.ID).Msg("failed to query downloads for recovery") - s.workflowRuns.SetFailed(ctx, run.ID, "recovery: failed to query downloads") - continue - } - - hasActive := false - for _, d := range downloads { - if d.State == "downloading" || d.State == "completed" || d.State == "seeding" { - hasActive = true - break - } - } - - if hasActive { - s.workflowRuns.SetCompleted(ctx, run.ID) - log.Info().Str("workflow_run_id", run.ID).Str("album_id", run.AlbumID).Msg("recovered stale workflow as completed") - } else { - s.workflowRuns.SetFailed(ctx, run.ID, "server restarted during workflow") - log.Warn().Str("workflow_run_id", run.ID).Str("album_id", run.AlbumID).Msg("recovered stale workflow as failed") - } - } -} - -func (service *MusicAgregatorService) GetArtists(ctx context.Context, _ *pb.GetArtistsRequest) (*pb.GetArtistsResponse, error) { - dbArtists, err := service.artists.GetAll(ctx) - if err != nil { - log.Error().Err(err).Msg("failed to list artists") - return nil, fmt.Errorf("listing artists: %w", err) - } - - artists := make([]*pb.ArtistSummary, len(dbArtists)) - var mu sync.Mutex - g, gCtx := errgroup.WithContext(ctx) - g.SetLimit(5) - - for i, a := range dbArtists { - i, a := i, a - g.Go(func() error { - albums, err := service.buildAlbumsForArtist(gCtx, a) - if err != nil { - log.Warn().Err(err).Str("artist", a.Name).Msg("failed to build album details, returning artist without albums") - } - - summary := &pb.ArtistSummary{ - Id: a.ID, - ExternalId: a.ExternalID, - Name: a.Name, - ArtistType: a.ArtistType, - Country: a.Country, - Genres: a.Genres, - ImageUrl: a.ImageURL, - MonitorState: toProtoMonitorState(a.MonitorState), - Albums: albums, - } - - mu.Lock() - artists[i] = summary - mu.Unlock() - return nil - }) - } - - _ = g.Wait() - - return &pb.GetArtistsResponse{Artists: artists}, nil -} - -func (service *MusicAgregatorService) buildAlbumsForArtist(ctx context.Context, artist *database.Artist) ([]*pb.AlbumDetail, error) { - var metadataAlbums []*metadataPb.Album - var err error - for attempt := 0; attempt < 3; attempt++ { - metadataAlbums, err = service.metadata.GetArtistAlbums(ctx, artist.ExternalID) - if err == nil { - break - } - log.Warn().Err(err).Int("attempt", attempt+1).Str("artist", artist.Name).Msg("metadata GetArtistAlbums failed, retrying") - time.Sleep(time.Duration(attempt+1) * 200 * time.Millisecond) - } - if err != nil { - return nil, fmt.Errorf("fetching metadata albums: %w", err) - } - - service.metadata.PersistAlbumsForArtist(ctx, metadataAlbums, artist.ID, database.Unmonitored) - - dbAlbums, err := service.metadata.GetAlbumsByArtistID(ctx, artist.ID) - if err != nil { - log.Warn().Err(err).Str("artist_id", artist.ID).Msg("failed to get local albums") - dbAlbums = nil - } - - dbAlbumsByExternalID := make(map[string]*database.Album, len(dbAlbums)) - albumIDs := make([]string, 0, len(dbAlbums)) - for _, a := range dbAlbums { - dbAlbumsByExternalID[a.ExternalID] = a - albumIDs = append(albumIDs, a.ID) - } - - downloadsByAlbumID, _ := service.downloads.GetByAlbumIDs(ctx, albumIDs) - - albums := make([]*pb.AlbumDetail, 0, len(metadataAlbums)) - for _, ma := range metadataAlbums { - detail := &pb.AlbumDetail{ - ExternalId: ma.GetId(), - Title: ma.GetTitle(), - AlbumType: ma.GetAlbumType(), - ReleaseDate: ma.GetReleaseDate(), - TotalTracks: ma.GetTotalTracks(), - TotalDiscs: ma.GetTotalDiscs(), - CoverUrl: ma.GetCoverUrl(), - } - - if ma.GetLabel() != nil { - detail.Label = ma.GetLabel().GetName() - } - for _, g := range ma.GetGenres() { - detail.Genres = append(detail.Genres, g.GetName()) - } - - if dbAlbum, ok := dbAlbumsByExternalID[ma.GetId()]; ok { - detail.Id = dbAlbum.ID - detail.MonitorState = toProtoMonitorState(dbAlbum.MonitorState) - - if downloads, ok := downloadsByAlbumID[dbAlbum.ID]; ok { - for _, d := range downloads { - detail.Downloads = append(detail.Downloads, &pb.DownloadInfo{ - State: d.State, - Format: d.Format, - Quality: d.Quality, - SavePath: derefStr(d.SavePath), - }) - } - } - } else { - detail.MonitorState = pb.MonitorState_MONITOR_STATE_UNMONITORED - } - - albums = append(albums, detail) - } - - return albums, nil -} - -func (service *MusicAgregatorService) GetAlbum(ctx context.Context, req *pb.GetAlbumRequest) (*pb.GetAlbumResponse, error) { - dbAlbum, err := service.metadata.GetAlbumByID(ctx, req.GetAlbumId()) - if err != nil { - return nil, fmt.Errorf("album not found: %w", err) - } - - info, err := service.buildAlbumInfo(ctx, dbAlbum) - if err != nil { - return nil, err - } - - return &pb.GetAlbumResponse{Info: info}, nil -} - -func (service *MusicAgregatorService) buildAlbumInfo(ctx context.Context, dbAlbum *database.Album) (*pb.AlbumInfo, error) { - metadataAlbum, err := service.metadata.GetAlbum(ctx, dbAlbum.ExternalID) - if err != nil { - log.Error().Err(err).Str("album_id", dbAlbum.ExternalID).Msg("failed to get album from metadata") - return nil, fmt.Errorf("fetching album: %w", err) - } - - metadataTracks, err := service.metadata.GetAlbumTracks(ctx, dbAlbum.ExternalID) - if err != nil { - log.Warn().Err(err).Str("album_id", dbAlbum.ExternalID).Msg("failed to get tracks from metadata") - } - - service.metadata.PersistTracks(ctx, dbAlbum.ID, metadataTracks) - - album := &pb.AlbumDetail{ - Id: dbAlbum.ID, - ExternalId: metadataAlbum.GetId(), - Title: metadataAlbum.GetTitle(), - AlbumType: metadataAlbum.GetAlbumType(), - ReleaseDate: metadataAlbum.GetReleaseDate(), - TotalTracks: metadataAlbum.GetTotalTracks(), - TotalDiscs: metadataAlbum.GetTotalDiscs(), - CoverUrl: metadataAlbum.GetCoverUrl(), - MonitorState: toProtoMonitorState(dbAlbum.MonitorState), - } - - if metadataAlbum.GetLabel() != nil { - album.Label = metadataAlbum.GetLabel().GetName() - } - for _, g := range metadataAlbum.GetGenres() { - album.Genres = append(album.Genres, g.GetName()) - } - - downloads, err := service.downloads.GetByAlbumID(ctx, dbAlbum.ID) - if err == nil && len(downloads) > 0 { - for _, d := range downloads { - album.Downloads = append(album.Downloads, &pb.DownloadInfo{ - State: d.State, - Format: d.Format, - Quality: d.Quality, - SavePath: derefStr(d.SavePath), - }) - } - } - - var bestDownload *database.Download - for _, d := range downloads { - if d.State == "completed" || d.State == "seeding" { - bestDownload = d - break - } - } - if bestDownload == nil && len(downloads) > 0 { - bestDownload = downloads[0] - } - - var downloadFilesByTrackID map[string]*database.DownloadFile - if bestDownload != nil { - files, err := service.downloadFiles.GetByDownloadID(ctx, bestDownload.ID) - if err == nil { - downloadFilesByTrackID = make(map[string]*database.DownloadFile, len(files)) - for _, f := range files { - if f.TrackID != nil { - downloadFilesByTrackID[*f.TrackID] = f - } - } - } - } - - dbTracks, _ := service.metadata.GetTracksByAlbumID(ctx, dbAlbum.ID) - dbTracksByExternalID := make(map[string]*database.Track, len(dbTracks)) - for _, t := range dbTracks { - dbTracksByExternalID[t.ExternalID] = t - } - - var trackReleasesByTrackID map[string]*database.TrackRelease - albumReleases, err := service.albumReleases.GetByAlbumID(ctx, dbAlbum.ID) - if err == nil && len(albumReleases) > 0 { - ar := albumReleases[0] - album.Release = &pb.AlbumReleaseDetail{ - Id: ar.ID, - Format: ar.Format, - Channels: int32(ar.Channels), - IsLossless: ar.IsLossless, - TotalSize: ar.TotalSize, - TotalDurationMs: int32(ar.TotalDurationMs), - TrackCount: int32(ar.TrackCount), - HasCoverArt: ar.HasCoverArt, - HasCueSheet: ar.HasCueSheet, - HasRipLog: ar.HasRipLog, - Path: ar.Path, - } - if ar.BitDepth != nil { - album.Release.BitDepth = int32(*ar.BitDepth) - } - if ar.SampleRate != nil { - album.Release.SampleRate = int32(*ar.SampleRate) - } - if ar.Source != nil { - album.Release.Source = *ar.Source - } - - trs, err := service.trackReleases.GetByAlbumReleaseID(ctx, ar.ID) - if err == nil { - trackReleasesByTrackID = make(map[string]*database.TrackRelease, len(trs)) - for _, tr := range trs { - if tr.TrackID != nil { - trackReleasesByTrackID[*tr.TrackID] = tr - } - } - } - } - - tracks := make([]*pb.TrackDetail, 0, len(metadataTracks)) - for _, mt := range metadataTracks { - td := &pb.TrackDetail{ - ExternalId: mt.GetId(), - Title: mt.GetTitle(), - DurationMs: mt.GetDurationMs(), - DiscNumber: mt.GetDiscNumber(), - TrackNumber: mt.GetTrackNumber(), - Isrc: mt.GetIsrc(), - Explicit: mt.GetExplicit(), - } - - for _, ac := range mt.GetArtists() { - td.Artists = append(td.Artists, &pb.ArtistCredit{ - Id: ac.GetArtist().GetId(), - Name: ac.GetArtist().GetName(), - }) - } - - if dbTrack, ok := dbTracksByExternalID[mt.GetId()]; ok { - td.Id = dbTrack.ID - - if tr, ok := trackReleasesByTrackID[dbTrack.ID]; ok { - td.FilePath = tr.FilePath - td.FileSize = tr.FileSize - td.Format = tr.Format - td.Channels = int32(tr.Channels) - if tr.DurationMs != nil { - td.DurationMs = int32(*tr.DurationMs) - } - if tr.BitDepth != nil { - td.BitDepth = int32(*tr.BitDepth) - } - if tr.SampleRate != nil { - td.SampleRate = int32(*tr.SampleRate) - } - if tr.BitrateKbps != nil { - td.BitrateKbps = int32(*tr.BitrateKbps) - } - } else if df, ok := downloadFilesByTrackID[dbTrack.ID]; ok { - td.FilePath = df.FilePath - td.FileSize = df.FileSize - td.Format = df.FileType - } - } - - tracks = append(tracks, td) - } - - return &pb.AlbumInfo{ - Album: album, - Tracks: tracks, - }, nil -} - -func (service *MusicAgregatorService) AnalyzeAlbumRelease(ctx context.Context, req *pb.AnalyzeAlbumReleaseRequest) (*pb.AnalyzeAlbumReleaseResponse, error) { - dbAlbum, err := service.metadata.GetAlbumByID(ctx, req.GetAlbumId()) - if err != nil { - return nil, fmt.Errorf("album not found: %w", err) - } - - downloads, err := service.downloads.GetByAlbumID(ctx, dbAlbum.ID) - if err != nil || len(downloads) == 0 { - return nil, fmt.Errorf("no downloads found for album") - } - - var download *database.Download - for _, d := range downloads { - if d.State == "completed" || d.State == "seeding" { - download = d - break - } - } - if download == nil { - return nil, fmt.Errorf("no completed download found for album") - } - - contentPath := "" - existingRelease, err := service.albumReleases.GetByDownloadID(ctx, download.ID) - if err == nil { - contentPath = existingRelease.Path - } - - if contentPath == "" && download.QbitHash != "" { - torrents, err := service.torrentClient.Find(torrent.FindOptions{Hash: download.QbitHash}) - if err == nil && len(torrents) > 0 { - contentPath = torrents[0].ContentPath - if service.pathMapper != nil { - contentPath = service.pathMapper.ToHost(contentPath) - } - } - } - - if contentPath == "" { - return nil, fmt.Errorf("cannot determine content path for download") - } - - _, _, err = service.analyzer.AnalyzeAndPersist(ctx, download.ID, contentPath) - if err != nil { - return nil, fmt.Errorf("analyzing release: %w", err) - } - - info, err := service.buildAlbumInfo(ctx, dbAlbum) - if err != nil { - return nil, err - } - - return &pb.AnalyzeAlbumReleaseResponse{Info: info}, nil -} - -func (service *MusicAgregatorService) MonitorAlbum(ctx context.Context, req *pb.MonitorAlbumRequest) (*pb.MonitorAlbumResponse, error) { - album, err := service.metadata.GetAlbum(ctx, req.GetAlbumId()) - if err != nil { - log.Error().Err(err).Str("album_id", req.GetAlbumId()).Msg("failed to get album") - return nil, err - } - - dbAlbum, _ := service.metadata.GetAlbumByExternalID(ctx, album.GetId()) - if dbAlbum != nil { - service.metadata.SetAlbumMonitorState(ctx, dbAlbum.ID, database.Monitored) - dbAlbum.MonitorState = database.Monitored - - qualityStr := normalizeQuality(req.GetQuality(), 0, 0) - owned, err := service.downloads.HasAlbumInQuality(ctx, dbAlbum.ID, req.GetQuality().String(), qualityStr) - if err == nil && owned { - log.Info().Str("album", dbAlbum.Title).Str("quality", qualityStr).Msg("album already owned in requested quality") - return service.buildMonitorAlbumResponse(ctx, album, dbAlbum, nil), nil - } - } - - searchResult, err := service.searchIndexer(album, req.GetIndexerOptions().GetTracker()) - if err != nil { - return nil, err - } - - parsed := service.parseSearchResults(ctx, searchResult, album, nil) - - if len(parsed) == 0 { - return nil, status.Errorf(codes.NotFound, "no torrents found for %s", album.GetTitle()) - } - - albumArtist := "" - if len(album.GetArtists()) > 0 { - albumArtist = album.GetArtists()[0].GetArtist().GetName() - } - parsed = filterByAlbumMatch(parsed, album.GetTitle(), albumArtist) - if len(parsed) == 0 { - return nil, status.Errorf(codes.NotFound, "no torrents match album title %q", album.GetTitle()) - } - - filtered := filterByQuality(parsed, req.GetQuality()) - if len(filtered) == 0 { - return nil, status.Errorf(codes.NotFound, "no releases match quality filter for %s", album.GetTitle()) - } - - filtered = filterByActiveSeeders(filtered) - if len(filtered) == 0 { - return nil, status.Errorf(codes.NotFound, "no releases with active seeders for %s", album.GetTitle()) - } - - best := selectBestRelease(filtered, album.GetTitle()) - - if err := service.addToTorrentClient(best); err != nil { - return nil, err - } - - dbAlbum, _ = service.metadata.GetAlbumByExternalID(ctx, album.GetId()) - if dbAlbum == nil { - service.metadata.PersistArtist(ctx, album, database.Monitored) - service.metadata.PersistAlbum(ctx, album, database.Monitored) - dbAlbum, _ = service.metadata.GetAlbumByExternalID(ctx, album.GetId()) - } - if dbAlbum != nil { - service.saveTorrentAndDownload(ctx, dbAlbum.ID, "", best) - } else { - log.Warn().Str("album_id", req.GetAlbumId()).Msg("album not in DB after persist attempt, skipping torrent/download persistence") - } - - return service.buildMonitorAlbumResponse(ctx, album, dbAlbum, &best), nil -} - -func (service *MusicAgregatorService) searchIndexer(album *metadataPb.Album, tracker string) (*indexer.SearchResponse, error) { - artistName := "" - if len(album.GetArtists()) > 0 { - artistName = album.GetArtists()[0].GetArtist().GetName() - } - - if tracker == "" { - tracker = "all" - } - - title := album.GetTitle() - queries := buildSearchQueries(artistName, title) - - for _, query := range queries { - result, err := service.indexer.Search(query, -1, tracker) - if err != nil { - log.Error().Err(err).Str("query", query).Msg("indexer search failed") - return nil, err - } - - log.Debug().Int("results", len(result.Items)).Str("query", query).Msg("indexer search completed") - - if len(result.Items) > 0 { - return result, nil - } - - log.Debug().Str("query", query).Msg("no results, trying broader search") - } - - return &indexer.SearchResponse{}, nil -} - -func buildSearchQueries(artist, title string) []string { - artist = normalizeSearchQuery(artist) - title = normalizeSearchQuery(title) - - clean := cleanAlbumTitle(title) - - var queries []string - seen := make(map[string]bool) - add := func(q string) { - q = strings.TrimSpace(q) - if q != "" && !seen[strings.ToLower(q)] { - seen[strings.ToLower(q)] = true - queries = append(queries, q) - } - } - - withArtist := func(t string) string { - if artist != "" { - return artist + " " + t - } - return t - } - - add(withArtist(clean)) - - noPunct := stripPunctuation(clean) - add(withArtist(noPunct)) - - if artist != "" { - add(artist) - } - - return queries -} - -var unicodeReplacer = strings.NewReplacer( - "\u2019", "'", // right single quote - "\u2018", "'", // left single quote - "\u201C", "\"", // left double quote - "\u201D", "\"", // right double quote - "\u2013", "-", // en dash - "\u2014", "-", // em dash - "\u2026", "...", // ellipsis -) - -func normalizeSearchQuery(s string) string { - s = unicodeReplacer.Replace(s) - for strings.Contains(s, " ") { - s = strings.ReplaceAll(s, " ", " ") - } - return strings.TrimSpace(s) -} - -var editionTagPattern = regexp.MustCompile(`(?i)\b(remaster(?:ed)?|deluxe(?:\s+edition)?|expanded(?:\s+edition)?|anniversary(?:\s+edition)?|special\s+edition|bonus\s+track|limited\s+edition|collector'?s?\s+edition|super\s+deluxe|standard\s+edition)\b`) -var bracketPattern = regexp.MustCompile(`[\(\[\{][^)\]\}]*[\)\]\}]`) - -func cleanAlbumTitle(title string) string { - clean := bracketPattern.ReplaceAllString(title, "") - clean = editionTagPattern.ReplaceAllString(clean, "") - clean = strings.TrimRight(clean, " -–—:") - for strings.Contains(clean, " ") { - clean = strings.ReplaceAll(clean, " ", " ") - } - clean = strings.TrimSpace(clean) - if clean == "" { - return title - } - return clean -} - -func extractEditionTags(title string) []string { - matches := editionTagPattern.FindAllString(title, -1) - tags := make([]string, len(matches)) - for i, m := range matches { - tags[i] = strings.ToLower(strings.TrimSpace(m)) - } - return tags -} - -func stripPunctuation(s string) string { - var b strings.Builder - for _, r := range s { - switch { - case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9', r == ' ': - b.WriteRune(r) - default: - b.WriteRune(' ') - } - } - result := b.String() - for strings.Contains(result, " ") { - result = strings.ReplaceAll(result, " ", " ") - } - return strings.TrimSpace(result) -} - -type resolveProgressFunc func(phase string, current, total int) - -const maxMagnetResolves = 5 - -func (service *MusicAgregatorService) parseSearchResults(ctx context.Context, searchResult *indexer.SearchResponse, album *metadataPb.Album, onProgress resolveProgressFunc) []parsedItem { - var candidates []*indexer.SearchItemResult - for i := range searchResult.Items { - item := searchResult.Items[i] - if item.DownloadLink == "" { - log.Trace().Str("title", item.Title).Msg("skipping item without download link") - continue - } - if item.Seeders == 0 { - log.Warn().Str("title", item.Title).Str("tracker", item.Tracker).Msg("skipping torrent with no seeders") - continue - } - candidates = append(candidates, item) - } - - total := len(candidates) - if total == 0 { - return nil - } - - progress := func(phase string, current, t int) { - if onProgress != nil { - onProgress(phase, current, t) - } - } - - progress("Pre-parsing titles", 0, total) - parser := torrentParser.NewGenericParser() - parsed := make([]parsedItem, total) - for i, item := range candidates { - rel := parser.Parse(item.Title) - parsed[i] = parsedItem{ - item: item, - rel: rel, - realSeeders: -1, - } - } - log.Info().Int("candidates", total).Msg("phase 1: title pre-parse complete") - progress("Pre-parsed titles", total, total) - - progress("Checking cache", 0, total) - var cacheHits int - for i := range parsed { - p := &parsed[i] - infoHash := torrentParser.ExtractInfoHash(p.item.DownloadLink) - if infoHash == "" { - if h, ok := p.item.Attrs["infohash"]; ok { - infoHash = strings.ToLower(h) - } - } - if infoHash == "" { - continue - } - - cached, err := service.torrents.GetByInfoHash(ctx, infoHash) - if err != nil || len(cached.TorrentFile) == 0 { - continue - } - - fullParser := torrentParser.NewGenericParser() - p.rel = fullParser.ParseTorrent(cached.TorrentFile, album) - p.torrentData = cached.TorrentFile - cacheHits++ - - log.Debug(). - Str("title", p.item.Title). - Str("hash", infoHash). - Str("format", p.rel.Format.String()). - Msg("cache hit") - } - log.Info().Int("cache_hits", cacheHits).Int("candidates", total).Msg("phase 2: cache lookup complete") - progress("Cache hits", cacheHits, total) - - var needsResolve []int - for i := range parsed { - if parsed[i].torrentData == nil { - needsResolve = append(needsResolve, i) - } - } - - sort.Slice(needsResolve, func(a, b int) bool { - return parsed[needsResolve[a]].item.Seeders > parsed[needsResolve[b]].item.Seeders - }) - if len(needsResolve) > maxMagnetResolves { - needsResolve = needsResolve[:maxMagnetResolves] - } - - resolveCount := len(needsResolve) - if resolveCount > 0 { - log.Info().Int("to_resolve", resolveCount).Int("skipped", total-cacheHits-resolveCount).Msg("phase 3: resolving top candidates") - progress("Resolving torrents", 0, resolveCount) - - const maxWorkers = 10 - sem := make(chan struct{}, maxWorkers) - var wg sync.WaitGroup - var resolved atomic.Int32 - - for _, idx := range needsResolve { - wg.Add(1) - go func(i int) { - defer wg.Done() - sem <- struct{}{} - defer func() { <-sem }() - - p := &parsed[i] - resolveParser := torrentParser.NewGenericParser() - out := service.resolveRelease(resolveParser, p.item, album) - p.rel = out.rel - p.torrentData = out.torrentData - p.realSeeders = out.realSeeders - - n := int(resolved.Add(1)) - progress("Resolving torrents", n, resolveCount) - - log.Debug(). - Str("title", p.item.Title). - Str("format", out.rel.Format.String()). - Int("real_seeders", out.realSeeders). - Msg("resolved") - }(idx) - } - - wg.Wait() - } - - log.Debug(). - Int("total", total). - Int("cache_hits", cacheHits). - Int("resolved", resolveCount). - Int("title_only", total-cacheHits-resolveCount). - Msg("parsing complete") - - return parsed -} - -type resolveOutput struct { - rel *release.Release - torrentData []byte - realSeeders int -} - -func (service *MusicAgregatorService) resolveRelease(parser *torrentParser.GenericParser, item *indexer.SearchItemResult, album *metadataPb.Album) resolveOutput { - if strings.HasPrefix(item.DownloadLink, "magnet:") { - log.Trace().Str("title", item.Title).Int("reported_seeders", item.Seeders).Msg("resolving magnet") - result, err := service.magnetResolver.Resolve(item.DownloadLink) - if err != nil { - log.Warn().Err(err).Str("title", item.Title).Int("reported_seeders", item.Seeders).Msg("magnet resolve failed, falling back to title parse") - return resolveOutput{rel: parser.Parse(item.Title)} - } - log.Debug(). - Str("title", item.Title). - Int("reported_seeders", item.Seeders). - Int("real_seeders", result.ConnectedSeeders). - Msg("magnet resolved with seeder info") - return resolveOutput{ - rel: parser.ParseTorrent(result.Data, album), - torrentData: result.Data, - realSeeders: result.ConnectedSeeders, - } - } - - torrentData, err := downloadTorrentData(item.DownloadLink) - if err != nil { - log.Warn().Err(err).Str("title", item.Title).Msg("failed to download torrent, falling back to title parse") - return resolveOutput{rel: parser.Parse(item.Title)} - } - return resolveOutput{ - rel: parser.ParseTorrent(torrentData, album), - torrentData: torrentData, - realSeeders: -1, - } -} - -func filterByAlbumMatch(items []parsedItem, albumTitle, artistName string) []parsedItem { - var matched []parsedItem - for _, p := range items { - score := albumMatcher.AlbumMatchScore(albumTitle, p.item.Title, artistName) - if score >= albumMatcher.MatchThreshold { - matched = append(matched, p) - } else { - log.Debug(). - Str("title", p.item.Title). - Float64("score", score). - Str("wanted", albumTitle). - Msg("filtered out by album match") - } - } - if len(matched) == 0 { - log.Warn().Str("album", albumTitle).Int("total", len(items)).Msg("no torrents match album title") - } - return matched -} - -func filterByQuality(items []parsedItem, quality pb.QualityType) []parsedItem { - var filtered []parsedItem - for _, p := range items { - match := quality == pb.QualityType_QUALITY_UNSPECIFIED || - (quality == pb.QualityType_QUALITY_LOSSLESS && p.rel.Format.IsLossless()) || - (quality == pb.QualityType_QUALITY_LOSSY && !p.rel.Format.IsLossless()) - - if !match { - log.Debug().Str("title", p.item.Title).Str("format", p.rel.Format.String()).Str("wanted", quality.String()).Msg("filtered out by quality") - continue - } - filtered = append(filtered, p) - } - return filtered -} - -func filterByActiveSeeders(items []parsedItem) []parsedItem { - var withSeeders []parsedItem - for _, p := range items { - if p.realSeeders > 0 { - withSeeders = append(withSeeders, p) - } else if p.realSeeders == -1 { - withSeeders = append(withSeeders, p) - } else { - log.Debug(). - Str("title", p.item.Title). - Int("reported_seeders", p.item.Seeders). - Int("real_seeders", p.realSeeders). - Msg("filtered out: magnet resolved but no active seeders") - } - } - if len(withSeeders) == 0 { - log.Warn().Int("total", len(items)).Msg("no torrents with active seeders, keeping all as fallback") - return items - } - return withSeeders -} - -func selectBestRelease(items []parsedItem, albumTitle string) parsedItem { - editionTags := extractEditionTags(albumTitle) - - best := items[0] - for _, p := range items[1:] { - if betterRelease(p, best, editionTags) { - best = p - } - } - - log.Info(). - Str("title", best.item.Title). - Str("format", best.rel.Format.String()). - Int("seeders", best.item.Seeders). - Int("real_seeders", best.realSeeders). - Str("tracker", best.item.Tracker). - Str("hash", best.rel.InfoHash). - Strs("edition_tags", editionTags). - Msg("best release selected") - - return best -} - -func betterRelease(candidate, current parsedItem, editionTags []string) bool { - cEdition := editionMatchScore(candidate.item.Title, editionTags) - bEdition := editionMatchScore(current.item.Title, editionTags) - if cEdition != bEdition { - return cEdition > bEdition - } - - cHasReal := candidate.realSeeders > 0 - bHasReal := current.realSeeders > 0 - - if cHasReal && !bHasReal { - return true - } - if !cHasReal && bHasReal { - return false - } - if cHasReal && bHasReal { - return candidate.realSeeders > current.realSeeders - } - return candidate.item.Seeders > current.item.Seeders -} - -func editionMatchScore(torrentTitle string, editionTags []string) int { - if len(editionTags) == 0 { - return 0 - } - lower := strings.ToLower(torrentTitle) - score := 0 - for _, tag := range editionTags { - if strings.Contains(lower, tag) { - score++ - } - } - return score -} - -func (service *MusicAgregatorService) addToTorrentClient(best parsedItem) error { - if best.rel.InfoHash != "" { - existing, err := service.torrentClient.Find(torrent.FindOptions{Hash: best.rel.InfoHash}) - if err == nil && len(existing) > 0 { - log.Info().Str("hash", best.rel.InfoHash).Str("state", existing[0].State).Msg("torrent already exists in client") - return nil - } - } - - savePath := "" - if service.pathMapper != nil { - savePath = service.pathMapper.ContainerDownloadPath() - } - - if strings.HasPrefix(best.item.DownloadLink, "magnet:") { - if err := service.torrentClient.AddMagnet(best.item.DownloadLink, savePath); err != nil { - log.Error().Err(err).Str("title", best.item.Title).Msg("failed to add magnet to client") - return err - } - } else { - if len(best.torrentData) == 0 { - log.Error().Str("title", best.item.Title).Msg("no torrent data available") - return fmt.Errorf("no torrent data available for best release") - } - if err := service.torrentClient.AddTorrent(torrent.TorrentFile{ - Filename: best.rel.Album + ".torrent", - Data: best.torrentData, - }, savePath); err != nil { - log.Error().Err(err).Str("title", best.item.Title).Msg("failed to add torrent to client") - return err - } - } - - log.Info().Str("title", best.item.Title).Str("hash", best.rel.InfoHash).Msg("torrent added to client") - return nil -} - -func (service *MusicAgregatorService) saveTorrentAndDownload(ctx context.Context, dbAlbumID string, workflowRunID string, best parsedItem) { - quality := normalizeQuality(pb.QualityType_QUALITY_UNSPECIFIED, best.rel.BitDepth, best.rel.SampleRate) - - dbTorrent := &database.Torrent{ - AlbumID: dbAlbumID, - InfoHash: best.rel.InfoHash, - Tracker: best.item.Tracker, - Title: best.item.Title, - Format: best.rel.Format.String(), - Quality: quality, - Source: best.rel.Source.String(), - BitDepth: best.rel.BitDepth, - SampleRate: best.rel.SampleRate, - Seeders: best.item.Seeders, - Peers: best.item.Peers, - Size: best.rel.TotalAudioSize, - TrackCount: best.rel.TrackCount, - HasCoverArt: best.rel.HasCoverArt, - HasCueSheet: best.rel.HasCueSheet, - HasRipLog: best.rel.HasRipLog, - DownloadLink: best.item.DownloadLink, - TorrentFile: best.torrentData, - } - if err := service.torrents.Create(ctx, dbTorrent); err != nil { - log.Error().Err(err).Str("hash", best.rel.InfoHash).Msg("failed to save torrent to DB") - return - } - - savedTorrent, err := service.torrents.GetByInfoHash(ctx, best.rel.InfoHash) - if err != nil { - log.Error().Err(err).Msg("failed to retrieve saved torrent") - return - } - - existingDownload, err := service.downloads.GetActiveByTorrentID(ctx, savedTorrent.ID) - if err == nil && existingDownload != nil { - log.Info().Str("hash", best.rel.InfoHash).Str("state", existingDownload.State).Msg("active download already exists, skipping") - return - } - - download := &database.Download{ - TorrentID: savedTorrent.ID, - AlbumID: dbAlbumID, - Format: best.rel.Format.String(), - Quality: quality, - State: "downloading", - QbitHash: best.rel.InfoHash, - } - if err := service.downloads.Create(ctx, download); err != nil { - log.Error().Err(err).Msg("failed to save download to DB") - return - } - - if service.riverClient != nil { - _, err := service.riverClient.Insert(ctx, workers.PollDownloadArgs{ - DownloadID: download.ID, - TorrentHash: best.rel.InfoHash, - CheckInterval: 30 * time.Second, - AlbumID: dbAlbumID, - Quality: quality, - WorkflowRunID: workflowRunID, - }, &river.InsertOpts{ - ScheduledAt: time.Now().Add(30 * time.Second), - }) - if err != nil { - log.Error().Err(err).Msg("failed to schedule download poll job") - } else { - log.Debug().Str("download_id", download.ID).Str("hash", best.rel.InfoHash).Msg("download poll job scheduled") - } - } - - log.Info().Str("hash", best.rel.InfoHash).Str("download_id", download.ID).Msg("torrent and download saved to DB") -} - -func normalizeQuality(quality pb.QualityType, bitDepth int, sampleRate int) string { - if bitDepth > 0 && sampleRate > 0 { - return fmt.Sprintf("%d-%d", bitDepth, sampleRate/1000) - } - switch quality { - case pb.QualityType_QUALITY_LOSSLESS: - return "16-44" - case pb.QualityType_QUALITY_LOSSY: - return "320" - default: - return "" - } -} - -func buildMonitoredRelease(p parsedItem) *pb.MonitoredRelease { - return &pb.MonitoredRelease{ - InfoHash: p.rel.InfoHash, - Artist: p.rel.Artist, - Album: p.rel.Album, - Year: int32(p.rel.Year), - Format: p.rel.Format.String(), - Lossless: p.rel.Format.IsLossless(), - BitDepth: int32(p.rel.BitDepth), - SampleRate: int32(p.rel.SampleRate), - Source: p.rel.Source.String(), - TrackCount: int32(p.rel.TrackCount), - TrackNames: p.rel.TrackNames, - HasCoverArt: p.rel.HasCoverArt, - HasCueSheet: p.rel.HasCueSheet, - HasRipLog: p.rel.HasRipLog, - TotalAudioSize: p.rel.TotalAudioSize, - DownloadLink: p.item.DownloadLink, - Seeders: int32(p.item.Seeders), - Tracker: p.item.Tracker, - } -} - -func (service *MusicAgregatorService) buildMonitorAlbumResponse(ctx context.Context, metadataAlbum *metadataPb.Album, dbAlbum *database.Album, best *parsedItem) *pb.MonitorAlbumResponse { - resp := &pb.MonitorAlbumResponse{} - - if best != nil { - resp.Release = buildMonitoredRelease(*best) - } - - if dbAlbum != nil { - resp.Album = service.buildAlbumDetail(ctx, dbAlbum) - } - - if len(metadataAlbum.GetArtists()) > 0 { - dbArtist, err := service.metadata.GetArtistByExternalID(ctx, metadataAlbum.GetArtists()[0].GetArtist().GetId()) - if err == nil { - resp.Artist = &pb.ArtistSummary{ - Id: dbArtist.ID, - ExternalId: dbArtist.ExternalID, - Name: dbArtist.Name, - ArtistType: dbArtist.ArtistType, - Country: dbArtist.Country, - Genres: dbArtist.Genres, - ImageUrl: dbArtist.ImageURL, - MonitorState: toProtoMonitorState(dbArtist.MonitorState), - } - } - } - - return resp -} - -func (service *MusicAgregatorService) buildAlbumDetail(ctx context.Context, dbAlbum *database.Album) *pb.AlbumDetail { - detail := &pb.AlbumDetail{ - Id: dbAlbum.ID, - ExternalId: dbAlbum.ExternalID, - Title: dbAlbum.Title, - AlbumType: dbAlbum.AlbumType, - TotalTracks: int32(dbAlbum.TotalTracks), - TotalDiscs: int32(dbAlbum.TotalDiscs), - Label: dbAlbum.Label, - Genres: dbAlbum.Genres, - CoverUrl: dbAlbum.CoverURL, - MonitorState: toProtoMonitorState(dbAlbum.MonitorState), - } - - if dbAlbum.ReleaseDate != nil { - detail.ReleaseDate = dbAlbum.ReleaseDate.Format("2006-01-02") - } - - downloads, err := service.downloads.GetByAlbumID(ctx, dbAlbum.ID) - if err == nil { - for _, d := range downloads { - detail.Downloads = append(detail.Downloads, &pb.DownloadInfo{ - State: d.State, - Format: d.Format, - Quality: d.Quality, - SavePath: derefStr(d.SavePath), - }) - } - } - - return detail -} - -func toProtoMonitorState(state database.MonitorState) pb.MonitorState { - switch state { - case database.Monitored: - return pb.MonitorState_MONITOR_STATE_MONITORED - case database.Unmonitored: - return pb.MonitorState_MONITOR_STATE_UNMONITORED - case database.Excluded: - return pb.MonitorState_MONITOR_STATE_EXCLUDED - default: - return pb.MonitorState_MONITOR_STATE_UNSPECIFIED - } -} - -func derefStr(s *string) string { - if s == nil { - return "" - } - return *s -} - -func downloadTorrentData(url string) ([]byte, error) { - client := &http.Client{Timeout: 30 * time.Second} - resp, err := client.Get(url) - if err != nil { - return nil, fmt.Errorf("downloading torrent: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("torrent download returned HTTP %d", resp.StatusCode) - } - - data, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("reading torrent data: %w", err) - } - - return data, nil -} - -func (service *MusicAgregatorService) ResyncAlbum(ctx context.Context, albumID string) (*pb.ResyncAlbumResponse, error) { - if service.musicfsClient == nil { - return nil, status.Error(codes.FailedPrecondition, "musicfs not configured") - } - - download, err := service.downloads.GetLatestCompleted(ctx, albumID) - if err != nil { - return nil, status.Errorf(codes.NotFound, "no completed download for album %s: %v", albumID, err) - } - - subdir := "" - if download.QbitHash != "" { - results, err := service.torrentClient.Find(torrent.FindOptions{Hash: download.QbitHash}) - if err == nil && len(results) > 0 { - contentPath := results[0].ContentPath - if service.pathMapper != nil { - contentPath = service.pathMapper.ToHost(contentPath) - } - subdir = musicfs.DeriveSubdir(service.config.MusicFS.OriginRoot, contentPath) - } - } - - log.Info(). - Str("album_id", albumID). - Str("subdir", subdir). - Msg("resyncing album with musicfs") - - result, err := service.musicfsClient.TriggerRescan(ctx, service.config.MusicFS.OriginID, subdir) - if err != nil { - return nil, status.Errorf(codes.Internal, "musicfs rescan failed: %v", err) - } - - log.Info(). - Int("new_files", len(result.NewFiles)). - Uint64("bytes_synced", result.BytesSynced). - Msg("musicfs rescan complete") - - var filesEnriched int - if len(result.NewFiles) > 0 { - dbAlbum, err := service.metadata.GetAlbumByID(ctx, albumID) - if err != nil { - log.Warn().Err(err).Str("album_id", albumID).Msg("failed to get album for enrichment") - } else { - albumMeta, err := service.metadata.GetAlbum(ctx, dbAlbum.ExternalID) - if err != nil { - log.Warn().Err(err).Str("external_id", dbAlbum.ExternalID).Msg("failed to get album metadata for enrichment") - } else { - err = service.musicfsClient.EnrichFiles(ctx, result.NewFiles, albumMeta) - if err != nil { - log.Warn().Err(err).Msg("musicfs enrichment failed") - } else { - filesEnriched = len(result.NewFiles) - } - } - } - } - - return &pb.ResyncAlbumResponse{ - FilesSynced: int32(len(result.NewFiles)), - FilesEnriched: int32(filesEnriched), - BytesSynced: result.BytesSynced, - }, nil -} - -func (service *MusicAgregatorService) SearchArtists(ctx context.Context, req *pb.SearchArtistsRequest) (*pb.SearchArtistsResponse, error) { - resp, err := service.metadata.SearchArtists(ctx, req.GetQuery(), req.GetLimit(), req.GetOffset()) - if err != nil { - return nil, err - } - - artists := make([]*pb.SearchArtistResult, len(resp.GetArtists())) - for i, a := range resp.GetArtists() { - genres := make([]string, len(a.GetGenres())) - for j, g := range a.GetGenres() { - genres[j] = g.GetName() - } - - extIDs := make([]*pb.ExternalId, len(a.GetExternalIds())) - for j, e := range a.GetExternalIds() { - extIDs[j] = &pb.ExternalId{ - Provider: e.GetSource(), - Id: e.GetSourceId(), - } - } - - artists[i] = &pb.SearchArtistResult{ - Id: a.GetId(), - Name: a.GetName(), - SortName: a.GetSortName(), - ArtistType: a.GetArtistType(), - Country: a.GetCountry(), - FormedDate: a.GetFormedDate(), - DisbandedDate: a.GetDisbandedDate(), - Description: a.GetDescription(), - ImageUrl: a.GetImageUrl(), - Genres: genres, - ExternalIds: extIDs, - } - } - - return &pb.SearchArtistsResponse{ - Artists: artists, - Total: resp.GetTotal(), - }, nil -} - -func (service *MusicAgregatorService) GetArtistAlbums(ctx context.Context, req *pb.GetArtistAlbumsRequest) (*pb.GetArtistAlbumsResponse, error) { - resp, err := service.metadata.GetArtistAlbumsWithPagination(ctx, req.GetArtistId(), req.GetLimit(), req.GetOffset()) - if err != nil { - return nil, err - } - - albums := make([]*pb.AlbumResult, len(resp.GetAlbums())) - for i, a := range resp.GetAlbums() { - genres := make([]string, len(a.GetGenres())) - for j, g := range a.GetGenres() { - genres[j] = g.GetName() - } - - extIDs := make([]*pb.ExternalId, len(a.GetExternalIds())) - for j, e := range a.GetExternalIds() { - extIDs[j] = &pb.ExternalId{ - Provider: e.GetSource(), - Id: e.GetSourceId(), - } - } - - artists := make([]*pb.AlbumArtistCredit, len(a.GetArtists())) - for j, ac := range a.GetArtists() { - artists[j] = &pb.AlbumArtistCredit{ - Id: ac.GetArtist().GetId(), - Name: ac.GetArtist().GetName(), - Role: ac.GetRole(), - } - } - - var label *pb.AlbumLabel - if a.GetLabel() != nil { - label = &pb.AlbumLabel{ - Id: a.GetLabel().GetId(), - Name: a.GetLabel().GetName(), - Country: a.GetLabel().GetCountry(), - } - } - - albums[i] = &pb.AlbumResult{ - Id: a.GetId(), - Title: a.GetTitle(), - AlbumType: a.GetAlbumType(), - ReleaseDate: a.GetReleaseDate(), - Upc: a.GetUpc(), - TotalTracks: a.GetTotalTracks(), - TotalDiscs: a.GetTotalDiscs(), - CoverUrl: a.GetCoverUrl(), - Artists: artists, - Label: label, - Genres: genres, - ExternalIds: extIDs, - } - } - - return &pb.GetArtistAlbumsResponse{ - Albums: albums, - Total: resp.GetTotal(), - }, nil -} diff --git a/internal/torrent/client.go b/internal/torrent/client.go deleted file mode 100644 index 010bb73..0000000 --- a/internal/torrent/client.go +++ /dev/null @@ -1,50 +0,0 @@ -package torrent - -type TorrentInfo struct { - Hash string - Name string - Size int64 - Progress float64 - DlSpeed int64 - UpSpeed int64 - NumSeeds int32 - NumLeechs int32 - State string - ETA int64 - Ratio float64 - Category string - Tags string - AddedOn int64 - CompletionOn int64 - SavePath string - ContentPath string - Downloaded int64 - Uploaded int64 - Tracker string - SeedingTime int64 - AmountLeft int64 - Availability float64 -} - -type TorrentFile struct { - Filename string - Data []byte -} - -type FindOptions struct { - Hash string - Name string - Category string - Tag string - State string -} - -type TorrentClient interface { - Login(username string, password string) (string, error) - List() ([]TorrentInfo, error) - Find(opts FindOptions) ([]TorrentInfo, error) - AddTorrent(file TorrentFile, savePath string) error - AddMagnet(magnetURI string, savePath string) error - DeleteTorrent(hash string) error - DefaultSavePath() (string, error) -} diff --git a/internal/torrent/factory.go b/internal/torrent/factory.go deleted file mode 100644 index d1603f7..0000000 --- a/internal/torrent/factory.go +++ /dev/null @@ -1,36 +0,0 @@ -package torrent - -import ( - "fmt" - - "github.com/rs/zerolog/log" - - "homelab.lan/music-agregator/internal/config" -) - -func MustNewTorrentClient(cfg config.Config) TorrentClient { - client, err := NewTorrentClient(cfg) - if err != nil { - panic(fmt.Sprintf("failed to create torrent client: %v", err)) - } - return client -} - -func NewTorrentClient(cfg config.Config) (TorrentClient, error) { - var client TorrentClient - - switch cfg.Torrent.ClientType { - case config.TorrentClientQbittorrent: - client = NewQbittorrentClient(cfg.Torrent.Url) - default: - return nil, fmt.Errorf("unknown torrent client type: %s", cfg.Torrent.ClientType) - } - - if _, err := client.Login(cfg.Torrent.Username, cfg.Torrent.Password); err != nil { - return nil, fmt.Errorf("torrent client login failed: %w", err) - } - - log.Info().Str("client", string(cfg.Torrent.ClientType)).Str("url", cfg.Torrent.Url).Msg("torrent client connected") - - return client, nil -} diff --git a/internal/torrent/path_mapper.go b/internal/torrent/path_mapper.go deleted file mode 100644 index 54a9c54..0000000 --- a/internal/torrent/path_mapper.go +++ /dev/null @@ -1,88 +0,0 @@ -package torrent - -import ( - "context" - "fmt" - "strings" - "time" - - dockerclient "github.com/docker/docker/client" - "github.com/rs/zerolog/log" -) - -type PathMapper struct { - containerPath string - hostPath string -} - -func NewPathMapper(containerName string, torrentClient TorrentClient) (*PathMapper, error) { - if containerName == "" { - savePath, err := torrentClient.DefaultSavePath() - if err != nil { - return nil, fmt.Errorf("getting default save path: %w", err) - } - log.Info().Str("path", savePath).Msg("no container configured, using direct path") - return &PathMapper{containerPath: savePath, hostPath: savePath}, nil - } - - savePath, err := torrentClient.DefaultSavePath() - if err != nil { - return nil, fmt.Errorf("getting default save path: %w", err) - } - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - cli, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation()) - if err != nil { - return nil, fmt.Errorf("creating docker client: %w", err) - } - defer cli.Close() - - inspect, err := cli.ContainerInspect(ctx, containerName) - if err != nil { - return nil, fmt.Errorf("inspecting container %s: %w", containerName, err) - } - - hostPath := "" - for _, mount := range inspect.Mounts { - if mount.Destination == savePath { - hostPath = mount.Source - break - } - } - - if hostPath == "" { - return nil, fmt.Errorf("no mount found for %s in container %s", savePath, containerName) - } - - log.Info(). - Str("container", containerName). - Str("container_path", savePath). - Str("host_path", hostPath). - Msg("resolved download path mapping") - - return &PathMapper{containerPath: savePath, hostPath: hostPath}, nil -} - -func (m *PathMapper) ToHost(containerPath string) string { - if m.containerPath == m.hostPath { - return containerPath - } - return strings.Replace(containerPath, m.containerPath, m.hostPath, 1) -} - -func (m *PathMapper) ToContainer(hostPath string) string { - if m.containerPath == m.hostPath { - return hostPath - } - return strings.Replace(hostPath, m.hostPath, m.containerPath, 1) -} - -func (m *PathMapper) HostDownloadPath() string { - return m.hostPath -} - -func (m *PathMapper) ContainerDownloadPath() string { - return m.containerPath -} diff --git a/internal/torrent/qbittorrent_client.go b/internal/torrent/qbittorrent_client.go deleted file mode 100644 index a70f9b9..0000000 --- a/internal/torrent/qbittorrent_client.go +++ /dev/null @@ -1,373 +0,0 @@ -package torrent - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "mime/multipart" - "net/http" - "net/url" - "strings" - "time" - - "github.com/rs/zerolog/log" -) - -type QbittorrentClient struct { - baseURL string - client *http.Client - sid string -} - -func NewQbittorrentClient(baseURL string) *QbittorrentClient { - return &QbittorrentClient{ - baseURL: strings.TrimRight(baseURL, "/"), - client: &http.Client{ - Timeout: 10 * time.Second, - }, - } -} - -func (c *QbittorrentClient) Login(username string, password string) (string, error) { - log.Trace().Str("url", c.baseURL).Str("username", username).Msg("qbittorrent login attempt") - - data := url.Values{ - "username": {username}, - "password": {password}, - } - - start := time.Now() - resp, err := c.client.PostForm(c.baseURL+"/api/v2/auth/login", data) - if err != nil { - log.Error().Err(err).Str("url", c.baseURL).Msg("qbittorrent login request failed") - return "", fmt.Errorf("login request failed: %w", err) - } - defer resp.Body.Close() - - log.Trace().Int("status", resp.StatusCode).Dur("duration", time.Since(start)).Msg("qbittorrent login response") - - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Error().Err(err).Msg("qbittorrent reading login response failed") - return "", fmt.Errorf("reading login response: %w", err) - } - - if resp.StatusCode == http.StatusForbidden { - log.Warn().Msg("qbittorrent login forbidden: too many failed attempts") - return "", fmt.Errorf("login forbidden: too many failed attempts") - } - - if string(body) != "Ok." { - log.Warn().Str("response", string(body)).Msg("qbittorrent login rejected") - return "", fmt.Errorf("login failed: %s", string(body)) - } - - for _, cookie := range resp.Cookies() { - if cookie.Name == "SID" { - c.sid = cookie.Value - log.Info().Str("url", c.baseURL).Msg("qbittorrent login successful") - log.Trace().Str("sid", c.sid).Msg("qbittorrent session ID acquired") - return c.sid, nil - } - } - - log.Error().Msg("qbittorrent login succeeded but no SID cookie returned") - return "", fmt.Errorf("login succeeded but no SID cookie returned") -} - -func (c *QbittorrentClient) List() ([]TorrentInfo, error) { - return c.Find(FindOptions{}) -} - -func (c *QbittorrentClient) Find(opts FindOptions) ([]TorrentInfo, error) { - log.Trace(). - Str("hash", opts.Hash). - Str("name", opts.Name). - Str("category", opts.Category). - Str("tag", opts.Tag). - Str("state", opts.State). - Msg("qbittorrent finding torrents") - - params := url.Values{} - if opts.Hash != "" { - params.Set("hashes", opts.Hash) - } - if opts.Category != "" { - params.Set("category", opts.Category) - } - if opts.Tag != "" { - params.Set("tag", opts.Tag) - } - if opts.State != "" { - params.Set("filter", opts.State) - } - - reqURL := c.baseURL + "/api/v2/torrents/info" - if len(params) > 0 { - reqURL += "?" + params.Encode() - } - - req, err := http.NewRequest("GET", reqURL, nil) - if err != nil { - log.Error().Err(err).Msg("qbittorrent creating find request failed") - return nil, fmt.Errorf("creating find request: %w", err) - } - req.AddCookie(&http.Cookie{Name: "SID", Value: c.sid}) - - start := time.Now() - resp, err := c.client.Do(req) - if err != nil { - log.Error().Err(err).Msg("qbittorrent find request failed") - return nil, fmt.Errorf("find request failed: %w", err) - } - defer resp.Body.Close() - - log.Trace().Int("status", resp.StatusCode).Dur("duration", time.Since(start)).Msg("qbittorrent find response") - - if resp.StatusCode != http.StatusOK { - log.Error().Int("status", resp.StatusCode).Msg("qbittorrent find returned non-OK status") - return nil, fmt.Errorf("find request returned status %d", resp.StatusCode) - } - - var items []QbittorrentListItem - if err := json.NewDecoder(resp.Body).Decode(&items); err != nil { - log.Error().Err(err).Msg("qbittorrent decoding find response failed") - return nil, fmt.Errorf("decoding find response: %w", err) - } - - torrents := make([]TorrentInfo, len(items)) - for i, item := range items { - torrents[i] = item.toTorrentInfo() - } - - torrents = filterLocally(torrents, opts) - - log.Debug().Int("count", len(torrents)).Msg("qbittorrent find results") - - return torrents, nil -} - -func filterLocally(torrents []TorrentInfo, opts FindOptions) []TorrentInfo { - var result []TorrentInfo - - for _, t := range torrents { - if opts.Name != "" && !strings.Contains(strings.ToLower(t.Name), strings.ToLower(opts.Name)) { - continue - } - if opts.Hash != "" && !strings.EqualFold(t.Hash, opts.Hash) { - continue - } - if opts.Category != "" && !strings.EqualFold(t.Category, opts.Category) { - continue - } - if opts.Tag != "" && !strings.Contains(strings.ToLower(t.Tags), strings.ToLower(opts.Tag)) { - continue - } - if opts.State != "" && !strings.EqualFold(t.State, opts.State) { - continue - } - result = append(result, t) - } - - return result -} - -func (c *QbittorrentClient) AddTorrent(file TorrentFile, savePath string) error { - log.Trace().Str("filename", file.Filename).Int("size", len(file.Data)).Str("save_path", savePath).Msg("qbittorrent adding torrent file") - - var buf bytes.Buffer - writer := multipart.NewWriter(&buf) - - part, err := writer.CreateFormFile("torrents", file.Filename) - if err != nil { - log.Error().Err(err).Msg("qbittorrent creating multipart form failed") - return fmt.Errorf("creating multipart form: %w", err) - } - - if _, err := part.Write(file.Data); err != nil { - log.Error().Err(err).Msg("qbittorrent writing torrent data failed") - return fmt.Errorf("writing torrent data: %w", err) - } - - if savePath != "" { - if err := writer.WriteField("savepath", savePath); err != nil { - return fmt.Errorf("writing savepath field: %w", err) - } - } - - if err := writer.Close(); err != nil { - return fmt.Errorf("closing multipart writer: %w", err) - } - - req, err := http.NewRequest("POST", c.baseURL+"/api/v2/torrents/add", &buf) - if err != nil { - log.Error().Err(err).Msg("qbittorrent creating add request failed") - return fmt.Errorf("creating add request: %w", err) - } - req.Header.Set("Content-Type", writer.FormDataContentType()) - req.AddCookie(&http.Cookie{Name: "SID", Value: c.sid}) - - return c.doAdd(req, file.Filename) -} - -func (c *QbittorrentClient) AddMagnet(magnetURI string, savePath string) error { - truncated := magnetURI - if len(truncated) > 80 { - truncated = truncated[:80] + "..." - } - log.Trace().Str("magnet", truncated).Str("save_path", savePath).Msg("qbittorrent adding magnet") - - data := url.Values{"urls": {magnetURI}} - if savePath != "" { - data.Set("savepath", savePath) - } - req, err := http.NewRequest("POST", c.baseURL+"/api/v2/torrents/add", strings.NewReader(data.Encode())) - if err != nil { - log.Error().Err(err).Msg("qbittorrent creating magnet add request failed") - return fmt.Errorf("creating magnet add request: %w", err) - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.AddCookie(&http.Cookie{Name: "SID", Value: c.sid}) - - return c.doAdd(req, truncated) -} - -func (c *QbittorrentClient) doAdd(req *http.Request, label string) error { - start := time.Now() - resp, err := c.client.Do(req) - if err != nil { - log.Error().Err(err).Msg("qbittorrent add request failed") - return fmt.Errorf("add request failed: %w", err) - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Error().Err(err).Msg("qbittorrent reading add response failed") - return fmt.Errorf("reading add response: %w", err) - } - - log.Trace().Int("status", resp.StatusCode).Dur("duration", time.Since(start)).Msg("qbittorrent add response") - - if resp.StatusCode != http.StatusOK || string(body) != "Ok." { - log.Error().Int("status", resp.StatusCode).Str("body", string(body)).Msg("qbittorrent add failed") - return fmt.Errorf("add failed: status %d, body: %s", resp.StatusCode, string(body)) - } - - log.Info().Str("label", label).Msg("qbittorrent torrent added") - return nil -} - -type QbittorrentListItem struct { - Hash string `json:"hash"` - Name string `json:"name"` - Size int64 `json:"size"` - Progress float64 `json:"progress"` - DlSpeed int64 `json:"dlspeed"` - UpSpeed int64 `json:"upspeed"` - NumSeeds int32 `json:"num_seeds"` - NumLeechs int32 `json:"num_leechs"` - State string `json:"state"` - ETA int64 `json:"eta"` - Ratio float64 `json:"ratio"` - Category string `json:"category"` - Tags string `json:"tags"` - AddedOn int64 `json:"added_on"` - CompletionOn int64 `json:"completion_on"` - SavePath string `json:"save_path"` - ContentPath string `json:"content_path"` - Downloaded int64 `json:"downloaded"` - Uploaded int64 `json:"uploaded"` - Tracker string `json:"tracker"` - SeedingTime int64 `json:"seeding_time"` - AmountLeft int64 `json:"amount_left"` - Availability float64 `json:"availability"` -} - -func (t *QbittorrentListItem) toTorrentInfo() TorrentInfo { - return TorrentInfo{ - Hash: t.Hash, - Name: t.Name, - Size: t.Size, - Progress: t.Progress, - DlSpeed: t.DlSpeed, - UpSpeed: t.UpSpeed, - NumSeeds: t.NumSeeds, - NumLeechs: t.NumLeechs, - State: t.State, - ETA: t.ETA, - Ratio: t.Ratio, - Category: t.Category, - Tags: t.Tags, - AddedOn: t.AddedOn, - CompletionOn: t.CompletionOn, - SavePath: t.SavePath, - ContentPath: t.ContentPath, - Downloaded: t.Downloaded, - Uploaded: t.Uploaded, - Tracker: t.Tracker, - SeedingTime: t.SeedingTime, - AmountLeft: t.AmountLeft, - Availability: t.Availability, - } -} - -func (c *QbittorrentClient) DeleteTorrent(hash string) error { - log.Trace().Str("hash", hash).Msg("qbittorrent deleting torrent") - - data := url.Values{} - data.Set("hashes", hash) - data.Set("deleteFiles", "true") - - req, err := http.NewRequest("POST", c.baseURL+"/api/v2/torrents/delete", strings.NewReader(data.Encode())) - if err != nil { - log.Error().Err(err).Msg("qbittorrent creating delete request failed") - return fmt.Errorf("creating delete request: %w", err) - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.AddCookie(&http.Cookie{Name: "SID", Value: c.sid}) - - start := time.Now() - resp, err := c.client.Do(req) - if err != nil { - log.Error().Err(err).Msg("qbittorrent delete request failed") - return fmt.Errorf("delete request failed: %w", err) - } - defer resp.Body.Close() - - log.Trace().Int("status", resp.StatusCode).Dur("duration", time.Since(start)).Msg("qbittorrent delete response") - - if resp.StatusCode != http.StatusOK { - log.Error().Int("status", resp.StatusCode).Msg("qbittorrent delete returned non-OK status") - return fmt.Errorf("delete torrent returned status %d", resp.StatusCode) - } - - log.Info().Str("hash", hash).Msg("qbittorrent torrent deleted") - return nil -} - -func (c *QbittorrentClient) DefaultSavePath() (string, error) { - req, err := http.NewRequest("GET", c.baseURL+"/api/v2/app/defaultSavePath", nil) - if err != nil { - return "", fmt.Errorf("creating request: %w", err) - } - req.AddCookie(&http.Cookie{Name: "SID", Value: c.sid}) - - resp, err := c.client.Do(req) - if err != nil { - return "", fmt.Errorf("requesting default save path: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("default save path returned status %d", resp.StatusCode) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("reading response: %w", err) - } - - return strings.TrimSpace(string(body)), nil -} diff --git a/internal/torrent/server.go b/internal/torrent/server.go deleted file mode 100644 index 0170b6c..0000000 --- a/internal/torrent/server.go +++ /dev/null @@ -1,39 +0,0 @@ -package torrent - -import ( - "context" - - "github.com/rs/zerolog/log" - "google.golang.org/grpc" - - pb "homelab.lan/music-agregator/gen/music_agregator/torrent/v1" -) - -type TorrentServer struct { - service *TorrentService - pb.UnimplementedTorrentServiceServer -} - -func NewTorrentServer(client TorrentClient) *TorrentServer { - return &TorrentServer{service: NewTorrentService(client)} -} - -func (server *TorrentServer) List(ctx context.Context, req *pb.ListRequest) (*pb.ListResponse, error) { - return server.service.List(req) -} - -func (server *TorrentServer) Add(ctx context.Context, req *pb.AddRequest) (*pb.AddResponse, error) { - log.Debug().Str("download_url", req.GetDownloadUrl()).Str("filename", req.GetFilename()).Msg("add torrent requested") - - resp, err := server.service.Add(req) - if err != nil { - log.Error().Err(err).Msg("add torrent failed") - return nil, err - } - - return resp, nil -} - -func (s *TorrentServer) Register(server *grpc.Server) { - pb.RegisterTorrentServiceServer(server, s) -} diff --git a/internal/torrent/service.go b/internal/torrent/service.go deleted file mode 100644 index f4b60b0..0000000 --- a/internal/torrent/service.go +++ /dev/null @@ -1,199 +0,0 @@ -package torrent - -import ( - "fmt" - "io" - "net/http" - "path" - "strings" - "time" - - "github.com/rs/zerolog/log" - - pb "homelab.lan/music-agregator/gen/music_agregator/torrent/v1" -) - -type TorrentService struct { - client TorrentClient - token string -} - -func NewTorrentService(client TorrentClient) *TorrentService { - return &TorrentService{ - client: client, - } -} - -func (service *TorrentService) List(req *pb.ListRequest) (*pb.ListResponse, error) { - torrents, err := service.client.List() - if err != nil { - return nil, err - } - - return &pb.ListResponse{Items: toProtoItems(torrents)}, nil -} - -func (service *TorrentService) Add(req *pb.AddRequest) (*pb.AddResponse, error) { - var file TorrentFile - - if len(req.GetTorrentData()) > 0 { - file = TorrentFile{ - Filename: req.GetFilename(), - Data: req.GetTorrentData(), - } - } else if req.GetDownloadUrl() != "" { - downloaded, err := downloadTorrentFile(req.GetDownloadUrl()) - if err != nil { - return nil, err - } - file = *downloaded - } else { - return nil, fmt.Errorf("either torrent_data or download_url must be provided") - } - - if err := service.client.AddTorrent(file, ""); err != nil { - return nil, err - } - - time.Sleep(500 * time.Millisecond) - - searchName := strings.TrimSuffix(file.Filename, ".torrent") - torrents, err := service.client.Find(FindOptions{Name: searchName}) - if err != nil { - log.Warn().Err(err).Msg("torrent added but failed to find it afterwards") - return &pb.AddResponse{}, nil - } - - if len(torrents) == 0 { - log.Warn().Str("filename", file.Filename).Msg("torrent added but not found in client") - return &pb.AddResponse{}, nil - } - - return &pb.AddResponse{Item: toProtoItem(torrents[0])}, nil -} - -func toProtoItems(torrents []TorrentInfo) []*pb.ListItem { - items := make([]*pb.ListItem, len(torrents)) - for i, t := range torrents { - items[i] = toProtoItem(t) - } - return items -} - -func toProtoItem(t TorrentInfo) *pb.ListItem { - return &pb.ListItem{ - Hash: t.Hash, - Name: t.Name, - Size: t.Size, - Progress: t.Progress, - Dlspeed: t.DlSpeed, - Upspeed: t.UpSpeed, - NumSeeds: t.NumSeeds, - NumLeechs: t.NumLeechs, - State: t.State, - Eta: t.ETA, - Ratio: t.Ratio, - Category: t.Category, - Tags: t.Tags, - AddedOn: t.AddedOn, - CompletionOn: t.CompletionOn, - SavePath: t.SavePath, - ContentPath: t.ContentPath, - Downloaded: t.Downloaded, - Uploaded: t.Uploaded, - Tracker: t.Tracker, - SeedingTime: t.SeedingTime, - AmountLeft: t.AmountLeft, - Availability: t.Availability, - - SizeFormatted: formatBytes(t.Size), - ProgressFormatted: fmt.Sprintf("%.1f%%", t.Progress*100), - DlspeedFormatted: formatSpeed(t.DlSpeed), - UpspeedFormatted: formatSpeed(t.UpSpeed), - AddedOnFormatted: formatTimestamp(t.AddedOn), - CompletionOnFormatted: formatTimestamp(t.CompletionOn), - DownloadedFormatted: formatBytes(t.Downloaded), - UploadedFormatted: formatBytes(t.Uploaded), - AmountLeftFormatted: formatBytes(t.AmountLeft), - AvailabilityFormatted: fmt.Sprintf("%.2f", t.Availability), - EtaFormatted: formatETA(t.ETA), - } -} - -func formatBytes(b int64) string { - switch { - case b >= 1<<30: - return fmt.Sprintf("%.2f GB", float64(b)/float64(1<<30)) - case b >= 1<<20: - return fmt.Sprintf("%.1f MB", float64(b)/float64(1<<20)) - case b >= 1<<10: - return fmt.Sprintf("%.0f KB", float64(b)/float64(1<<10)) - default: - return fmt.Sprintf("%d B", b) - } -} - -func formatSpeed(bytesPerSec int64) string { - if bytesPerSec == 0 { - return "0 B/s" - } - return formatBytes(bytesPerSec) + "/s" -} - -func formatTimestamp(ts int64) string { - if ts <= 0 { - return "" - } - return time.Unix(ts, 0).Format("2006-01-02 15:04:05") -} - -func formatETA(seconds int64) string { - if seconds <= 0 || seconds >= 8640000 { - return "∞" - } - d := time.Duration(seconds) * time.Second - h := int(d.Hours()) - m := int(d.Minutes()) % 60 - s := int(d.Seconds()) % 60 - if h > 0 { - return fmt.Sprintf("%dh %dm %ds", h, m, s) - } - if m > 0 { - return fmt.Sprintf("%dm %ds", m, s) - } - return fmt.Sprintf("%ds", s) -} - -func downloadTorrentFile(url string) (*TorrentFile, error) { - log.Trace().Str("url", url).Msg("downloading torrent file") - - client := &http.Client{Timeout: 30 * time.Second} - resp, err := client.Get(url) - if err != nil { - log.Error().Err(err).Str("url", url).Msg("downloading torrent file failed") - return nil, fmt.Errorf("downloading torrent file: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - log.Error().Int("status", resp.StatusCode).Str("url", url).Msg("torrent download returned non-OK status") - return nil, fmt.Errorf("torrent download returned status %d", resp.StatusCode) - } - - data, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("reading torrent file: %w", err) - } - - filename := path.Base(resp.Request.URL.Path) - if !strings.HasSuffix(strings.ToLower(filename), ".torrent") { - filename += ".torrent" - } - - log.Debug().Str("filename", filename).Int("size", len(data)).Msg("torrent file downloaded") - - return &TorrentFile{ - Filename: filename, - Data: data, - }, nil -} diff --git a/internal/tracker/generic_parser.go b/internal/tracker/generic_parser.go deleted file mode 100644 index 324a1cd..0000000 --- a/internal/tracker/generic_parser.go +++ /dev/null @@ -1,351 +0,0 @@ -package tracker - -import ( - "path/filepath" - "regexp" - "strconv" - "strings" - - "github.com/anacrolix/torrent/metainfo" - "github.com/rs/zerolog/log" - - metadataPb "homelab.lan/music-agregator/gen/metadata/v1" - "homelab.lan/music-agregator/internal/release" -) - -var ( - bitratePattern = regexp.MustCompile(`(?i)(\d{2,3})\s*kbps`) - hiResPatterns = []*regexp.Regexp{ - regexp.MustCompile(`(?i)(\d{1,2})\s*[Bb]it\s*[-/]?\s*(\d{2,3}(?:\.\d)?)\s*[kK][Hh][Zz]`), - regexp.MustCompile(`(?i)\[?\s*(?:FLAC|Flac)\s+(\d{1,2})\s*[-/]\s*(\d{2,3}(?:\.\d)?)\s*\]?`), - regexp.MustCompile(`(?i)\[?\s*(\d{1,2})\s*[Bb]it\s*\]?`), - } - sourcePattern = regexp.MustCompile(`(?i)\[(CD|WEB|Vinyl|LP|Cassette|MC|DVD|Blu-?Ray|SACD|DAT)\]`) - ripTypePattern = regexp.MustCompile(`(?i)(vinyl\s*rip|SACD[- ]?R|HDCD|DSD\d*|tape\s*rip)`) -) - -var audioExtensions = map[string]release.AudioFormat{ - ".flac": release.FormatFLAC, - ".mp3": release.FormatMP3, - ".aac": release.FormatAAC, - ".m4a": release.FormatAAC, - ".ape": release.FormatAPE, - ".wv": release.FormatWavPack, - ".alac": release.FormatALAC, - ".ogg": release.FormatOGG, - ".wav": release.FormatWAV, -} - -type GenericParser struct{} - -func NewGenericParser() *GenericParser { - return &GenericParser{} -} - -func (p *GenericParser) ParseTorrent(torrentData []byte, album *metadataPb.Album) *release.Release { - r := &release.Release{} - - p.fillFromMetadata(r, album) - p.fillFromTorrent(r, torrentData) - - r.ParsedSuccessfully = r.Artist != "" && r.Album != "" - if !r.ParsedSuccessfully { - r.ParseErrors = append(r.ParseErrors, "missing artist or album") - } - - return r -} - -func (p *GenericParser) Parse(title string) *release.Release { - r := &release.Release{RawTitle: title} - - p.fillFromTitle(r, title) - - r.ParsedSuccessfully = r.Artist != "" && r.Album != "" - if !r.ParsedSuccessfully { - r.ParseErrors = append(r.ParseErrors, "missing artist or album") - } - - return r -} - -func (p *GenericParser) fillFromMetadata(r *release.Release, album *metadataPb.Album) { - if album == nil { - return - } - - r.Album = album.GetTitle() - - if len(album.GetArtists()) > 0 { - r.Artist = album.GetArtists()[0].GetArtist().GetName() - } - - if album.GetReleaseDate() != "" { - if year, err := strconv.Atoi(album.GetReleaseDate()[:4]); err == nil { - r.Year = year - } - } - - switch strings.ToLower(album.GetAlbumType()) { - case "album": - r.Type = release.TypeAlbum - case "ep": - r.Type = release.TypeEP - case "single": - r.Type = release.TypeSingle - case "compilation": - r.Type = release.TypeCompilation - case "soundtrack": - r.Type = release.TypeSoundtrack - case "live": - r.Type = release.TypeLive - } - - for _, g := range album.GetGenres() { - r.Genres = append(r.Genres, g.GetName()) - } - - if album.GetLabel() != nil { - r.Label = album.GetLabel().GetName() - } - - r.TrackCount = int(album.GetTotalTracks()) - r.ReleaseCount = int(album.GetTotalDiscs()) - - log.Trace(). - Str("artist", r.Artist). - Str("album", r.Album). - Int("year", r.Year). - Str("type", r.Type.String()). - Msg("filled from metadata") -} - -func (p *GenericParser) fillFromTorrent(r *release.Release, torrentData []byte) { - if len(torrentData) == 0 { - return - } - - mi, err := metainfo.Load(strings.NewReader(string(torrentData))) - if err != nil { - log.Error().Err(err).Msg("failed to parse torrent data") - r.ParseErrors = append(r.ParseErrors, "failed to parse torrent: "+err.Error()) - return - } - - info, err := mi.UnmarshalInfo() - if err != nil { - log.Error().Err(err).Msg("failed to unmarshal torrent info") - r.ParseErrors = append(r.ParseErrors, "failed to unmarshal torrent info: "+err.Error()) - return - } - - r.RawTitle = info.Name - r.InfoHash = mi.HashInfoBytes().HexString() - - formatCounts := make(map[release.AudioFormat]int) - formatSizes := make(map[release.AudioFormat]int64) - - if len(info.Files) == 0 { - ext := strings.ToLower(filepath.Ext(info.Name)) - if fmt, ok := audioExtensions[ext]; ok { - r.Format = fmt - r.AudioFileCount = 1 - r.TotalAudioSize = info.Length - } - } else { - for _, f := range info.Files { - path := filepath.Join(f.Path...) - ext := strings.ToLower(filepath.Ext(path)) - name := strings.TrimSuffix(filepath.Base(path), ext) - - if fmt, ok := audioExtensions[ext]; ok { - formatCounts[fmt]++ - formatSizes[fmt] += f.Length - r.TrackNames = append(r.TrackNames, cleanTrackName(name)) - } - - switch ext { - case ".jpg", ".jpeg", ".png": - r.HasCoverArt = true - case ".cue": - r.HasCueSheet = true - case ".log": - r.HasRipLog = true - } - } - - var dominantFormat release.AudioFormat - var maxCount int - for fmt, count := range formatCounts { - if count > maxCount { - maxCount = count - dominantFormat = fmt - } - } - r.Format = dominantFormat - r.AudioFileCount = maxCount - r.TotalAudioSize = formatSizes[dominantFormat] - } - - if r.HasRipLog { - r.Source = release.SourceCD - } - - if r.TrackCount == 0 { - r.TrackCount = r.AudioFileCount - } - - p.fillFromTitle(r, info.Name) - p.deduceFromFileSize(r) - - log.Trace(). - Str("hash", r.InfoHash). - Str("format", r.Format.String()). - Int("audio_files", r.AudioFileCount). - Int64("audio_size", r.TotalAudioSize). - Bool("cover", r.HasCoverArt). - Bool("cue", r.HasCueSheet). - Bool("log", r.HasRipLog). - Int("bit_depth", r.BitDepth). - Int("sample_rate", r.SampleRate). - Str("bitrate", r.Bitrate). - Msg("filled from torrent") -} - -func (p *GenericParser) fillFromTitle(r *release.Release, title string) { - if title == "" { - return - } - - if m := bitratePattern.FindStringSubmatch(title); len(m) > 1 { - r.Bitrate = m[1] + " kbps" - } - - for _, pattern := range hiResPatterns { - m := pattern.FindStringSubmatch(title) - if len(m) < 2 { - continue - } - if r.BitDepth == 0 { - if bd, err := strconv.Atoi(m[1]); err == nil { - r.BitDepth = bd - } - } - if len(m) > 2 && r.SampleRate == 0 { - if sr, err := strconv.ParseFloat(m[2], 64); err == nil { - r.SampleRate = int(sr * 1000) - } - } - if r.BitDepth > 0 { - break - } - } - - if m := sourcePattern.FindStringSubmatch(title); len(m) > 1 && r.Source == release.SourceUnknown { - switch strings.ToUpper(m[1]) { - case "CD": - r.Source = release.SourceCD - case "WEB": - r.Source = release.SourceWEB - case "VINYL", "LP": - r.Source = release.SourceVinyl - case "CASSETTE", "MC": - r.Source = release.SourceCassette - case "DVD": - r.Source = release.SourceDVD - case "BLU-RAY", "BLURAY": - r.Source = release.SourceBluRay - } - } - - if m := ripTypePattern.FindStringSubmatch(title); len(m) > 1 { - r.RipType = m[1] - } - - log.Trace(). - Str("bitrate", r.Bitrate). - Int("bit_depth", r.BitDepth). - Int("sample_rate", r.SampleRate). - Str("source", r.Source.String()). - Str("rip_type", r.RipType). - Msg("filled from title") -} - -func (p *GenericParser) deduceFromFileSize(r *release.Release) { - if r.AudioFileCount == 0 || r.TotalAudioSize == 0 { - return - } - - avgFileSize := r.TotalAudioSize / int64(r.AudioFileCount) - avgFileSizeMB := float64(avgFileSize) / (1024 * 1024) - - switch { - case r.Format.IsLossless(): - if r.BitDepth > 0 && r.SampleRate > 0 { - return - } - - // Average FLAC file size per ~4 min track: - // 16/44.1 ≈ 25-35 MB 24/48 ≈ 40-60 MB - // 24/96 ≈ 80-120 MB 24/192 ≈ 160-240 MB - switch { - case avgFileSizeMB >= 130: - p.setIfMissing(r, 24, 192000) - case avgFileSizeMB >= 65: - p.setIfMissing(r, 24, 96000) - case avgFileSizeMB >= 38: - p.setIfMissing(r, 24, 48000) - default: - p.setIfMissing(r, 16, 44100) - } - - log.Trace(). - Float64("avg_file_mb", avgFileSizeMB). - Int("deduced_bit_depth", r.BitDepth). - Int("deduced_sample_rate", r.SampleRate). - Msg("deduced lossless quality from file size") - - case r.Format == release.FormatMP3: - if r.Bitrate != "" { - return - } - - // Average MP3 file size per ~4 min track: - // 128 kbps ≈ 3.5-4 MB 192 kbps ≈ 5-6 MB - // 256 kbps ≈ 7-8 MB 320 kbps ≈ 9-10 MB - switch { - case avgFileSizeMB >= 8.5: - r.Bitrate = "320 kbps" - case avgFileSizeMB >= 6.5: - r.Bitrate = "256 kbps" - case avgFileSizeMB >= 4.5: - r.Bitrate = "192 kbps" - default: - r.Bitrate = "128 kbps" - } - - log.Trace(). - Float64("avg_file_mb", avgFileSizeMB). - Str("deduced_bitrate", r.Bitrate). - Msg("deduced mp3 bitrate from file size") - } -} - -func (p *GenericParser) setIfMissing(r *release.Release, bitDepth int, sampleRate int) { - if r.BitDepth == 0 { - r.BitDepth = bitDepth - } - if r.SampleRate == 0 { - r.SampleRate = sampleRate - } -} - -var trackNumberPrefix = regexp.MustCompile(`^\d{1,3}[\s.\-]+`) - -func cleanTrackName(name string) string { - cleaned := trackNumberPrefix.ReplaceAllString(name, "") - if cleaned == "" { - return name - } - return strings.TrimSpace(cleaned) -} diff --git a/internal/tracker/generic_parser_test.go b/internal/tracker/generic_parser_test.go deleted file mode 100644 index 3ea7a56..0000000 --- a/internal/tracker/generic_parser_test.go +++ /dev/null @@ -1,572 +0,0 @@ -package tracker - -import ( - "bytes" - "fmt" - "testing" - - metadataPb "homelab.lan/music-agregator/gen/metadata/v1" - "homelab.lan/music-agregator/internal/release" -) - -type testFile struct { - path string - size int64 -} - -func buildTorrentData(name string, files []testFile) []byte { - var buf bytes.Buffer - buf.WriteString("d8:announce35:http://tracker.example.com/announce4:infod") - - if len(files) == 0 { - buf.WriteString(fmt.Sprintf("6:lengthi0e4:name%d:%s12:piece lengthi16384e6:pieces20:01234567890123456789", len(name), name)) - } else if len(files) == 1 { - buf.WriteString(fmt.Sprintf("6:lengthi%de4:name%d:%s12:piece lengthi16384e6:pieces20:01234567890123456789", files[0].size, len(files[0].path), files[0].path)) - } else { - buf.WriteString("5:filesl") - for _, f := range files { - buf.WriteString(fmt.Sprintf("d6:lengthi%de4:pathl%d:%see", f.size, len(f.path), f.path)) - } - buf.WriteString(fmt.Sprintf("e4:name%d:%s12:piece lengthi16384e6:pieces20:01234567890123456789", len(name), name)) - } - - buf.WriteString("ee") - return buf.Bytes() -} - -func TestGenericParser_Parse(t *testing.T) { - p := NewGenericParser() - - tests := []struct { - name string - title string - wantBitrate string - wantBitDepth int - wantSampleRate int - wantSource release.Source - wantRipType string - }{ - { - name: "discography no hires", - title: "System Of A Down - Discography [FLAC Songs] [PMEDIA]", - }, - { - name: "hiphop hires 24-44", - title: "Snoop Dogg - 10 Til' Midnight (2026 Hip Hop Rap) [Flac 24-44]", - wantBitDepth: 24, - wantSampleRate: 44000, - }, - { - name: "pop hires 24bit", - title: "Sabrina Carpenter - Short n' Sweet [Deluxe] [2025] [Hi-Res FLAC 24bit]-Sc4r3cr0w", - wantBitDepth: 24, - }, - { - name: "rock hires 24bit", - title: "Linkin Park - From Zero [Deluxe Edition] [2025] [Hi-Res] [FLAC-24bit]-Sc4r3cr0w", - }, - { - name: "rock hires 24-48", - title: "Linkin Park - From Zero (2024) [24Bit-48kHz] FLAC [PMEDIA]", - wantBitDepth: 24, - wantSampleRate: 48000, - }, - { - name: "hiphop hires 24-96", - title: "J. Cole - The Fall-Off (2026 Hip Hop Rap) [Flac 24-96]", - wantBitDepth: 24, - wantSampleRate: 96000, - }, - { - name: "minimal format", - title: "Bjork-Bastards.2012.FLAC-NewAlbumReleases", - }, - { - name: "vinyl hires", - title: "Gorillaz - Demon Days [Live From The Apollo Theater] [2025] [Vinyl Hi-Res] [FLAC-24bit]-Sc4r3cr0w", - }, - { - name: "cd with log", - title: "Linkin Park - Meteora (Tracks, Log, Cue, Scans) (2003) [FLAC] 88", - }, - { - name: "rock 16-44", - title: "Heart - Jupiters Darling (2004 Rock) [Flac 16-44]", - wantBitDepth: 16, - wantSampleRate: 44000, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - r := p.Parse(tt.title) - - if tt.wantBitrate != "" && r.Bitrate != tt.wantBitrate { - t.Errorf("Bitrate = %q, want %q", r.Bitrate, tt.wantBitrate) - } - if tt.wantBitDepth != 0 && r.BitDepth != tt.wantBitDepth { - t.Errorf("BitDepth = %d, want %d", r.BitDepth, tt.wantBitDepth) - } - if tt.wantSampleRate != 0 && r.SampleRate != tt.wantSampleRate { - t.Errorf("SampleRate = %d, want %d", r.SampleRate, tt.wantSampleRate) - } - if tt.wantSource != release.SourceUnknown && r.Source != tt.wantSource { - t.Errorf("Source = %v, want %v", r.Source, tt.wantSource) - } - if tt.wantRipType != "" && r.RipType != tt.wantRipType { - t.Errorf("RipType = %q, want %q", r.RipType, tt.wantRipType) - } - }) - } -} - -func TestGenericParser_ParseTorrent(t *testing.T) { - p := NewGenericParser() - - makeFlacFiles := func(count int, sizeMB float64) []testFile { - files := make([]testFile, count) - for i := range files { - files[i] = testFile{ - path: fmt.Sprintf("%02d - Track %d.flac", i+1, i+1), - size: int64(sizeMB * 1024 * 1024), - } - } - return files - } - - makeMp3Files := func(count int, sizeMB float64) []testFile { - files := make([]testFile, count) - for i := range files { - files[i] = testFile{ - path: fmt.Sprintf("%02d - Track %d.mp3", i+1, i+1), - size: int64(sizeMB * 1024 * 1024), - } - } - return files - } - - tests := []struct { - name string - torrentName string - files []testFile - album *metadataPb.Album - wantFormat release.AudioFormat - wantAudioFileCount int - wantHasCoverArt bool - wantHasCueSheet bool - wantHasRipLog bool - wantSource release.Source - wantInfoHashEmpty bool - wantBitDepth int - wantSampleRate int - wantTrackNames []string - wantArtist string - wantAlbum string - wantYear int - wantType release.Type - wantGenres []string - wantLabel string - wantParseErrors bool - }{ - { - name: "flac album with cover cue log", - torrentName: "Test Artist - Test Album (2024) [FLAC]", - files: append(append(makeFlacFiles(12, 30), - testFile{path: "cover.jpg", size: 500000}, - testFile{path: "album.cue", size: 2000}), - testFile{path: "rip.log", size: 5000}), - album: &metadataPb.Album{ - Title: "Test Album", - AlbumType: "Album", - ReleaseDate: "2024-01-15", - TotalTracks: 12, - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Test Artist"}}}, - Genres: []*metadataPb.Genre{{Name: "Rock"}}, - Label: &metadataPb.Label{Name: "Test Label"}, - }, - wantFormat: release.FormatFLAC, - wantAudioFileCount: 12, - wantHasCoverArt: true, - wantHasCueSheet: true, - wantHasRipLog: true, - wantSource: release.SourceCD, - wantArtist: "Test Artist", - wantAlbum: "Test Album", - wantYear: 2024, - wantType: release.TypeAlbum, - wantGenres: []string{"Rock"}, - wantLabel: "Test Label", - }, - { - name: "mp3 album with cover", - torrentName: "Artist - MP3 Album (2023)", - files: append(makeMp3Files(10, 10), - testFile{path: "cover.jpg", size: 300000}), - album: &metadataPb.Album{ - Title: "MP3 Album", - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Artist"}}}, - ReleaseDate: "2023-05-20", - }, - wantFormat: release.FormatMP3, - wantAudioFileCount: 10, - wantHasCoverArt: true, - wantHasCueSheet: false, - wantHasRipLog: false, - wantArtist: "Artist", - wantAlbum: "MP3 Album", - wantYear: 2023, - }, - { - name: "mixed format dominant wins", - torrentName: "Mixed Format Album", - files: append(makeFlacFiles(10, 30), - testFile{path: "bonus1.mp3", size: 10485760}, - testFile{path: "bonus2.mp3", size: 10485760}), - album: &metadataPb.Album{ - Title: "Mixed Format Album", - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Artist"}}}, - }, - wantFormat: release.FormatFLAC, - wantAudioFileCount: 10, - }, - { - name: "single file torrent flac", - torrentName: "Single Track.flac", - files: []testFile{{path: "Single Track.flac", size: 50 * 1024 * 1024}}, - album: &metadataPb.Album{ - Title: "Single Track", - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Artist"}}}, - }, - wantFormat: release.FormatFLAC, - wantAudioFileCount: 1, - }, - { - name: "single file torrent mp3", - torrentName: "Single.mp3", - files: []testFile{{path: "Single.mp3", size: 10 * 1024 * 1024}}, - album: &metadataPb.Album{ - Title: "Single", - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Artist"}}}, - }, - wantFormat: release.FormatMP3, - wantAudioFileCount: 1, - }, - { - name: "no audio files", - torrentName: "Not Music", - files: []testFile{ - {path: "readme.txt", size: 1000}, - {path: "image.jpg", size: 500000}, - }, - album: &metadataPb.Album{ - Title: "Not Music", - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Someone"}}}, - }, - wantFormat: release.FormatUnknown, - wantAudioFileCount: 0, - wantHasCoverArt: true, - }, - { - name: "hires in title", - torrentName: "Artist - Album (2024) [24Bit-96kHz] FLAC", - files: makeFlacFiles(12, 100), - album: &metadataPb.Album{ - Title: "Album", - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Artist"}}}, - }, - wantFormat: release.FormatFLAC, - wantAudioFileCount: 12, - wantBitDepth: 24, - wantSampleRate: 96000, - }, - { - name: "source from title", - torrentName: "Artist - Album [WEB] FLAC", - files: makeFlacFiles(10, 30), - album: &metadataPb.Album{ - Title: "Album", - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Artist"}}}, - }, - wantFormat: release.FormatFLAC, - wantAudioFileCount: 10, - wantSource: release.SourceWEB, - }, - { - name: "track names cleaned", - torrentName: "Artist - Album", - files: []testFile{ - {path: "01 - First Track.flac", size: 30 * 1024 * 1024}, - {path: "02 - Second Track.flac", size: 30 * 1024 * 1024}, - }, - album: &metadataPb.Album{ - Title: "Album", - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Artist"}}}, - }, - wantFormat: release.FormatFLAC, - wantAudioFileCount: 2, - wantTrackNames: []string{"First Track", "Second Track"}, - }, - { - name: "metadata fills release fields", - torrentName: "Test Torrent", - files: makeFlacFiles(8, 30), - album: &metadataPb.Album{ - Title: "Metadata Album", - AlbumType: "EP", - ReleaseDate: "2020-06-15", - TotalTracks: 8, - TotalDiscs: 1, - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Metadata Artist"}}}, - Genres: []*metadataPb.Genre{{Name: "Electronic"}, {Name: "Ambient"}}, - Label: &metadataPb.Label{Name: "Metadata Label"}, - }, - wantFormat: release.FormatFLAC, - wantAudioFileCount: 8, - wantArtist: "Metadata Artist", - wantAlbum: "Metadata Album", - wantYear: 2020, - wantType: release.TypeEP, - wantGenres: []string{"Electronic", "Ambient"}, - wantLabel: "Metadata Label", - }, - { - name: "empty torrent data", - torrentName: "", - files: nil, - album: &metadataPb.Album{ - Title: "Album Only", - ReleaseDate: "2022-01-01", - Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Artist Only"}}}, - }, - wantFormat: release.FormatUnknown, - wantAudioFileCount: 0, - wantInfoHashEmpty: true, - wantArtist: "Artist Only", - wantAlbum: "Album Only", - wantYear: 2022, - }, - { - name: "invalid torrent data", - torrentName: "invalid", - files: nil, - album: &metadataPb.Album{Title: "Album", Artists: []*metadataPb.ArtistCredit{{Artist: &metadataPb.Artist{Name: "Artist"}}}}, - wantArtist: "Artist", - wantAlbum: "Album", - wantParseErrors: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var torrentData []byte - if tt.name == "empty torrent data" { - torrentData = nil - } else if tt.name == "invalid torrent data" { - torrentData = []byte("garbage data that is not valid bencode") - } else { - torrentData = buildTorrentData(tt.torrentName, tt.files) - } - - r := p.ParseTorrent(torrentData, tt.album) - - if r.Format != tt.wantFormat { - t.Errorf("Format = %v, want %v", r.Format, tt.wantFormat) - } - if r.AudioFileCount != tt.wantAudioFileCount { - t.Errorf("AudioFileCount = %d, want %d", r.AudioFileCount, tt.wantAudioFileCount) - } - if r.HasCoverArt != tt.wantHasCoverArt { - t.Errorf("HasCoverArt = %v, want %v", r.HasCoverArt, tt.wantHasCoverArt) - } - if r.HasCueSheet != tt.wantHasCueSheet { - t.Errorf("HasCueSheet = %v, want %v", r.HasCueSheet, tt.wantHasCueSheet) - } - if r.HasRipLog != tt.wantHasRipLog { - t.Errorf("HasRipLog = %v, want %v", r.HasRipLog, tt.wantHasRipLog) - } - if tt.wantSource != release.SourceUnknown && r.Source != tt.wantSource { - t.Errorf("Source = %v, want %v", r.Source, tt.wantSource) - } - if tt.wantInfoHashEmpty && r.InfoHash != "" { - t.Errorf("InfoHash = %q, want empty", r.InfoHash) - } - if !tt.wantInfoHashEmpty && tt.name != "invalid torrent data" && r.InfoHash == "" { - t.Error("InfoHash should not be empty") - } - if tt.wantBitDepth != 0 && r.BitDepth != tt.wantBitDepth { - t.Errorf("BitDepth = %d, want %d", r.BitDepth, tt.wantBitDepth) - } - if tt.wantSampleRate != 0 && r.SampleRate != tt.wantSampleRate { - t.Errorf("SampleRate = %d, want %d", r.SampleRate, tt.wantSampleRate) - } - if len(tt.wantTrackNames) > 0 { - if len(r.TrackNames) != len(tt.wantTrackNames) { - t.Errorf("TrackNames length = %d, want %d", len(r.TrackNames), len(tt.wantTrackNames)) - } else { - for i, name := range tt.wantTrackNames { - if r.TrackNames[i] != name { - t.Errorf("TrackNames[%d] = %q, want %q", i, r.TrackNames[i], name) - } - } - } - } - if tt.wantArtist != "" && r.Artist != tt.wantArtist { - t.Errorf("Artist = %q, want %q", r.Artist, tt.wantArtist) - } - if tt.wantAlbum != "" && r.Album != tt.wantAlbum { - t.Errorf("Album = %q, want %q", r.Album, tt.wantAlbum) - } - if tt.wantYear != 0 && r.Year != tt.wantYear { - t.Errorf("Year = %d, want %d", r.Year, tt.wantYear) - } - if tt.wantType != release.TypeUnknown && r.Type != tt.wantType { - t.Errorf("Type = %v, want %v", r.Type, tt.wantType) - } - if len(tt.wantGenres) > 0 { - if len(r.Genres) != len(tt.wantGenres) { - t.Errorf("Genres length = %d, want %d", len(r.Genres), len(tt.wantGenres)) - } else { - for i, g := range tt.wantGenres { - if r.Genres[i] != g { - t.Errorf("Genres[%d] = %q, want %q", i, r.Genres[i], g) - } - } - } - } - if tt.wantLabel != "" && r.Label != tt.wantLabel { - t.Errorf("Label = %q, want %q", r.Label, tt.wantLabel) - } - if tt.wantParseErrors && len(r.ParseErrors) == 0 { - t.Error("expected ParseErrors but got none") - } - }) - } -} - -func TestGenericParser_DeduceFromFileSize(t *testing.T) { - p := NewGenericParser() - - makeFlacRelease := func(count int, avgSizeMB float64) *release.Release { - return &release.Release{ - Format: release.FormatFLAC, - AudioFileCount: count, - TotalAudioSize: int64(float64(count) * avgSizeMB * 1024 * 1024), - } - } - - makeMp3Release := func(count int, avgSizeMB float64) *release.Release { - return &release.Release{ - Format: release.FormatMP3, - AudioFileCount: count, - TotalAudioSize: int64(float64(count) * avgSizeMB * 1024 * 1024), - } - } - - tests := []struct { - name string - release *release.Release - wantBitDepth int - wantSampleRate int - wantBitrate string - }{ - { - name: "flac 16/44.1 from small files", - release: makeFlacRelease(12, 30), - wantBitDepth: 16, - wantSampleRate: 44100, - }, - { - name: "flac 24/48 from medium files", - release: makeFlacRelease(12, 50), - wantBitDepth: 24, - wantSampleRate: 48000, - }, - { - name: "flac 24/96 from large files", - release: makeFlacRelease(12, 100), - wantBitDepth: 24, - wantSampleRate: 96000, - }, - { - name: "flac 24/192 from very large files", - release: makeFlacRelease(12, 200), - wantBitDepth: 24, - wantSampleRate: 192000, - }, - { - name: "title overrides heuristic", - release: &release.Release{ - Format: release.FormatFLAC, - AudioFileCount: 12, - TotalAudioSize: int64(12 * 30 * 1024 * 1024), - BitDepth: 24, - SampleRate: 48000, - }, - wantBitDepth: 24, - wantSampleRate: 48000, - }, - { - name: "mp3 320kbps from large files", - release: makeMp3Release(12, 10), - wantBitrate: "320 kbps", - }, - { - name: "mp3 128kbps from small files", - release: makeMp3Release(12, 3.5), - wantBitrate: "128 kbps", - }, - { - name: "mp3 title overrides", - release: &release.Release{ - Format: release.FormatMP3, - AudioFileCount: 12, - TotalAudioSize: int64(12 * 3.5 * 1024 * 1024), - Bitrate: "320 kbps", - }, - wantBitrate: "320 kbps", - }, - { - name: "no audio files skips deduction", - release: &release.Release{ - Format: release.FormatFLAC, - AudioFileCount: 0, - TotalAudioSize: 0, - }, - wantBitDepth: 0, - wantSampleRate: 0, - }, - { - name: "aac files no deduction", - release: &release.Release{ - Format: release.FormatAAC, - AudioFileCount: 12, - TotalAudioSize: int64(12 * 50 * 1024 * 1024), - }, - wantBitDepth: 0, - wantSampleRate: 0, - wantBitrate: "", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - p.deduceFromFileSize(tt.release) - - if tt.wantBitDepth != 0 && tt.release.BitDepth != tt.wantBitDepth { - t.Errorf("BitDepth = %d, want %d", tt.release.BitDepth, tt.wantBitDepth) - } - if tt.wantSampleRate != 0 && tt.release.SampleRate != tt.wantSampleRate { - t.Errorf("SampleRate = %d, want %d", tt.release.SampleRate, tt.wantSampleRate) - } - if tt.wantBitrate != "" && tt.release.Bitrate != tt.wantBitrate { - t.Errorf("Bitrate = %q, want %q", tt.release.Bitrate, tt.wantBitrate) - } - if tt.name == "no audio files skips deduction" || tt.name == "aac files no deduction" { - if tt.release.BitDepth != 0 || tt.release.SampleRate != 0 || tt.release.Bitrate != "" { - t.Errorf("expected no deduction, got BitDepth=%d, SampleRate=%d, Bitrate=%q", - tt.release.BitDepth, tt.release.SampleRate, tt.release.Bitrate) - } - } - }) - } -} diff --git a/internal/tracker/magnet.go b/internal/tracker/magnet.go deleted file mode 100644 index 8c4708a..0000000 --- a/internal/tracker/magnet.go +++ /dev/null @@ -1,154 +0,0 @@ -package tracker - -import ( - "context" - "fmt" - "net/url" - "strings" - "time" - - "github.com/anacrolix/torrent" - "github.com/anacrolix/torrent/bencode" - "github.com/anacrolix/torrent/metainfo" - "github.com/rs/zerolog/log" -) - -func ExtractInfoHash(magnetURI string) string { - u, err := url.Parse(magnetURI) - if err != nil { - return "" - } - xt := u.Query().Get("xt") - if strings.HasPrefix(xt, "urn:btih:") { - return strings.ToLower(xt[len("urn:btih:"):]) - } - return "" -} - -type ResolveResult struct { - Data []byte - ConnectedSeeders int -} - -type Resolver interface { - Resolve(magnetURI string) (*ResolveResult, error) -} - -type MagnetResolver struct { - client *torrent.Client - timeout time.Duration -} - -func NewMagnetResolver(timeout time.Duration) (*MagnetResolver, error) { - cfg := torrent.NewDefaultClientConfig() - cfg.DataDir = "" - cfg.NoDHT = false - cfg.NoUpload = true - cfg.Seed = false - cfg.ListenPort = 0 - - client, err := torrent.NewClient(cfg) - if err != nil { - return nil, fmt.Errorf("creating torrent client: %w", err) - } - - log.Info().Dur("timeout", timeout).Msg("magnet resolver initialized") - - return &MagnetResolver{ - client: client, - timeout: timeout, - }, nil -} - -func (r *MagnetResolver) Resolve(magnetURI string) (*ResolveResult, error) { - truncated := magnetURI - if len(truncated) > 80 { - truncated = truncated[:80] + "..." - } - log.Trace().Str("magnet", truncated).Msg("resolving magnet") - - t, err := r.client.AddMagnet(magnetURI) - if err != nil { - return nil, fmt.Errorf("adding magnet: %w", err) - } - defer t.Drop() - - ctx, cancel := context.WithTimeout(context.Background(), r.timeout) - defer cancel() - - ticker := time.NewTicker(5 * time.Second) - defer ticker.Stop() - - noActiveSince := time.Now() - - for { - select { - case <-t.GotInfo(): - ticker.Stop() - goto resolved - case <-ctx.Done(): - stats := t.Stats() - log.Warn(). - Str("hash", t.InfoHash().HexString()). - Int("total_peers", stats.TotalPeers). - Int("active_peers", stats.ActivePeers). - Int("pending_peers", stats.PendingPeers). - Int("half_open_peers", stats.HalfOpenPeers). - Int("connected_seeders", stats.ConnectedSeeders). - Msg("magnet resolve timed out") - return nil, fmt.Errorf("timeout resolving magnet after %s: peers=%d active=%d seeders=%d", - r.timeout, stats.TotalPeers, stats.ActivePeers, stats.ConnectedSeeders) - case <-ticker.C: - stats := t.Stats() - log.Trace(). - Str("hash", t.InfoHash().HexString()). - Int("total_peers", stats.TotalPeers). - Int("active_peers", stats.ActivePeers). - Int("connected_seeders", stats.ConnectedSeeders). - Msg("magnet resolve waiting") - - if stats.ActivePeers > 0 { - noActiveSince = time.Now() - } - - if stats.TotalPeers > 0 && time.Since(noActiveSince) > 15*time.Second { - log.Warn(). - Str("hash", t.InfoHash().HexString()). - Int("total_peers", stats.TotalPeers). - Int("active_peers", stats.ActivePeers). - Msg("magnet has peers but none active for 15s, giving up early") - return nil, fmt.Errorf("no active peers after 15s: total=%d active=%d", stats.TotalPeers, stats.ActivePeers) - } - } - } -resolved: - - stats := t.Stats() - info := t.Info() - log.Debug(). - Str("name", info.Name). - Int("files", len(info.Files)). - Int64("size", info.TotalLength()). - Int("connected_seeders", stats.ConnectedSeeders). - Int("active_peers", stats.ActivePeers). - Msg("magnet resolved") - - mi := t.Metainfo() - data, err := bencode.Marshal(metainfo.MetaInfo{ - InfoBytes: mi.InfoBytes, - Announce: mi.Announce, - AnnounceList: mi.AnnounceList, - }) - if err != nil { - return nil, fmt.Errorf("marshaling torrent data: %w", err) - } - - return &ResolveResult{ - Data: data, - ConnectedSeeders: stats.ConnectedSeeders, - }, nil -} - -func (r *MagnetResolver) Close() { - r.client.Close() -} diff --git a/internal/workers/poll_download.go b/internal/workers/poll_download.go deleted file mode 100644 index efc5d45..0000000 --- a/internal/workers/poll_download.go +++ /dev/null @@ -1,282 +0,0 @@ -package workers - -import ( - "context" - "fmt" - "time" - - "github.com/jackc/pgx/v5" - "github.com/riverqueue/river" - "github.com/rs/zerolog/log" - - "homelab.lan/music-agregator/internal/analysis" - "homelab.lan/music-agregator/internal/database" - "homelab.lan/music-agregator/internal/eventbus" - "homelab.lan/music-agregator/internal/metadata" - "homelab.lan/music-agregator/internal/musicfs" - "homelab.lan/music-agregator/internal/torrent" -) - -type PollDownloadArgs struct { - DownloadID string `json:"download_id"` - TorrentHash string `json:"torrent_hash"` - CheckInterval time.Duration `json:"check_interval"` - AlbumID string `json:"album_id"` - Quality string `json:"quality"` - WorkflowRunID string `json:"workflow_run_id"` -} - -func (PollDownloadArgs) Kind() string { return "poll_download" } - -type PollDownloadWorker struct { - river.WorkerDefaults[PollDownloadArgs] - TorrentClient torrent.TorrentClient - Downloads *database.DownloadRepository - DownloadFiles *database.DownloadFileRepository - AlbumReleases *database.AlbumReleaseRepository - TrackReleases *database.TrackReleaseRepository - RiverClient *river.Client[pgx.Tx] - PathMapper *torrent.PathMapper - Analyzer *analysis.ReleaseAnalyzer - MusicFSClient *musicfs.Client - MusicFSOriginID string - MusicFSOriginRoot string - MetadataService *metadata.MetadataService - EventBus *eventbus.EventBus - AlbumEvents *database.AlbumEventRepository -} - -func (w *PollDownloadWorker) Work(ctx context.Context, job *river.Job[PollDownloadArgs]) error { - args := job.Args - - log.Trace().Str("download_id", args.DownloadID).Str("hash", args.TorrentHash).Msg("polling download status") - - results, err := w.TorrentClient.Find(torrent.FindOptions{Hash: args.TorrentHash}) - if err != nil { - log.Error().Err(err).Str("hash", args.TorrentHash).Msg("failed to query torrent client") - return w.reschedule(ctx, args) - } - - if len(results) == 0 { - log.Warn().Str("hash", args.TorrentHash).Msg("torrent not found in client, marking failed") - w.Downloads.SetFailed(ctx, args.DownloadID, "torrent not found in client") - w.publishEvent(ctx, args, "error", "", "torrent not found in client") - return nil - } - - t := results[0] - - switch { - case t.Progress >= 1.0: - return w.onCompleted(ctx, args, t) - - case t.State == "error": - log.Warn().Str("hash", args.TorrentHash).Str("state", t.State).Msg("torrent in error state") - w.Downloads.SetFailed(ctx, args.DownloadID, "torrent error state") - w.publishEvent(ctx, args, "error", "", "torrent error state") - return nil - - default: - log.Trace(). - Str("hash", args.TorrentHash). - Str("state", t.State). - Float64("progress", t.Progress*100). - Int64("dlspeed", t.DlSpeed). - Msg("download in progress") - w.publishEvent(ctx, args, "status", "", - fmt.Sprintf("Downloading: %.1f%% ↓%s", t.Progress*100, formatSpeed(t.DlSpeed))) - return w.reschedule(ctx, args) - } -} - -func (w *PollDownloadWorker) onCompleted(ctx context.Context, args PollDownloadArgs, t torrent.TorrentInfo) error { - log.Info().Str("hash", args.TorrentHash).Str("path", t.ContentPath).Msg("download completed") - - contentPath := t.ContentPath - if w.PathMapper != nil { - contentPath = w.PathMapper.ToHost(contentPath) - } - - savePath := t.SavePath - if w.PathMapper != nil { - savePath = w.PathMapper.ToHost(savePath) - } - - if err := w.Downloads.SetCompleted(ctx, args.DownloadID, savePath); err != nil { - log.Error().Err(err).Msg("failed to update download as completed") - return err - } - - files, err := analysis.ScanAndHashFiles(contentPath) - if err != nil { - log.Error().Err(err).Str("path", contentPath).Msg("failed to scan downloaded files") - return nil - } - - for _, f := range files { - f.DownloadID = args.DownloadID - } - - if err := w.DownloadFiles.CreateBatch(ctx, files); err != nil { - log.Error().Err(err).Msg("failed to save download files") - return nil - } - - log.Info(). - Str("download_id", args.DownloadID). - Int("files", len(files)). - Msg("download files scanned and hashed") - - if w.Analyzer != nil { - _, _, err := w.Analyzer.AnalyzeAndPersist(ctx, args.DownloadID, contentPath) - if err != nil { - log.Error().Err(err).Msg("failed to analyze release") - } - } - - if w.MusicFSClient != nil { - w.syncAndEnrichMusicFS(ctx, args, contentPath) - } - - w.publishEvent(ctx, args, "result", "MONITOR_STEP_COMPLETE", "Download completed") - - return nil -} - -func (w *PollDownloadWorker) syncAndEnrichMusicFS(ctx context.Context, args PollDownloadArgs, contentPath string) { - subdir := musicfs.DeriveSubdir(w.MusicFSOriginRoot, contentPath) - - result, err := w.MusicFSClient.TriggerRescan(ctx, w.MusicFSOriginID, subdir) - if err != nil { - log.Warn().Err(err).Msg("musicfs rescan failed") - return - } - - log.Info(). - Int("new_files", len(result.NewFiles)). - Uint64("bytes_synced", result.BytesSynced). - Msg("musicfs rescan complete") - - if len(result.NewFiles) == 0 { - return - } - - download, err := w.Downloads.GetByID(ctx, args.DownloadID) - if err != nil { - log.Warn().Err(err).Msg("failed to get download for enrichment") - return - } - - if w.MetadataService == nil { - log.Warn().Msg("no metadata service configured, skipping enrichment") - return - } - - album, err := w.MetadataService.GetAlbumByID(ctx, download.AlbumID) - if err != nil { - log.Warn().Err(err).Str("album_id", download.AlbumID).Msg("failed to get album for enrichment") - return - } - - albumMeta, err := w.MetadataService.GetAlbum(ctx, album.ExternalID) - if err != nil { - log.Warn().Err(err).Str("external_id", album.ExternalID).Msg("failed to get album metadata for enrichment") - return - } - - err = w.MusicFSClient.EnrichFiles(ctx, result.NewFiles, albumMeta) - if err != nil { - log.Warn().Err(err).Msg("musicfs enrichment failed") - } -} - -func (w *PollDownloadWorker) reschedule(ctx context.Context, args PollDownloadArgs) error { - if w.RiverClient == nil { - log.Warn().Str("download_id", args.DownloadID).Msg("no river client, cannot reschedule poll_download") - return nil - } - _, err := w.RiverClient.Insert(ctx, args, &river.InsertOpts{ - ScheduledAt: time.Now().Add(args.CheckInterval), - }) - if err != nil { - log.Error().Err(err).Msg("failed to reschedule poll_download") - } - return nil -} - -func (w *PollDownloadWorker) RecoverOrphanedDownloads(ctx context.Context) { - active, err := w.Downloads.GetActive(ctx) - if err != nil { - log.Error().Err(err).Msg("failed to query active downloads for recovery") - return - } - - if len(active) == 0 { - return - } - - for _, d := range active { - _, err := w.RiverClient.Insert(ctx, PollDownloadArgs{ - DownloadID: d.ID, - TorrentHash: d.QbitHash, - CheckInterval: 30 * time.Second, - AlbumID: d.AlbumID, - Quality: d.Quality, - }, &river.InsertOpts{ - ScheduledAt: time.Now().Add(5 * time.Second), - UniqueOpts: river.UniqueOpts{ - ByArgs: true, - }, - }) - if err != nil { - log.Error().Err(err).Str("download_id", d.ID).Msg("failed to reschedule orphaned download") - } else { - log.Info().Str("download_id", d.ID).Str("hash", d.QbitHash).Msg("recovered orphaned download poll job") - } - } -} - -func (w *PollDownloadWorker) publishEvent(ctx context.Context, args PollDownloadArgs, eventType, step, message string) { - if w.EventBus == nil { - return - } - - topic := args.AlbumID + ":" + args.Quality - - var seq int64 - if w.AlbumEvents != nil && args.AlbumID != "" { - event := &database.AlbumEvent{ - WorkflowRunID: args.WorkflowRunID, - AlbumID: args.AlbumID, - EventType: eventType, - Step: step, - Message: message, - } - if err := w.AlbumEvents.Create(ctx, event); err != nil { - log.Error().Err(err).Msg("failed to persist download event") - } else { - seq = event.Seq - } - } - - w.EventBus.Publish(topic, &eventbus.Event{ - Seq: seq, - WorkflowRunID: args.WorkflowRunID, - AlbumID: args.AlbumID, - Quality: args.Quality, - EventType: eventType, - Step: step, - Message: message, - }) -} - -func formatSpeed(bytesPerSec int64) string { - switch { - case bytesPerSec >= 1<<20: - return fmt.Sprintf("%.1f MB/s", float64(bytesPerSec)/float64(1<<20)) - case bytesPerSec >= 1<<10: - return fmt.Sprintf("%.0f KB/s", float64(bytesPerSec)/float64(1<<10)) - default: - return fmt.Sprintf("%d B/s", bytesPerSec) - } -} diff --git a/internal/workflow_registry.go b/internal/workflow_registry.go deleted file mode 100644 index 3b5c67c..0000000 --- a/internal/workflow_registry.go +++ /dev/null @@ -1,100 +0,0 @@ -package internal - -import ( - "context" - "fmt" - "sync" - "time" - - "homelab.lan/music-agregator/internal/eventbus" -) - -type WorkflowEntry struct { - ID string - AlbumID string - Quality string - Ctx context.Context - Cancel context.CancelFunc - Topic string - Ready chan struct{} -} - -type WorkflowRegistry struct { - mu sync.Mutex - workflows map[string]*WorkflowEntry - bus *eventbus.EventBus - wg sync.WaitGroup -} - -func NewWorkflowRegistry(bus *eventbus.EventBus) *WorkflowRegistry { - return &WorkflowRegistry{ - workflows: make(map[string]*WorkflowEntry), - bus: bus, - } -} - -func workflowKey(albumID, quality string) string { - return fmt.Sprintf("%s:%s", albumID, quality) -} - -func (r *WorkflowRegistry) GetOrCreate(ctx context.Context, albumID, quality string) (*WorkflowEntry, bool) { - r.mu.Lock() - defer r.mu.Unlock() - - key := workflowKey(albumID, quality) - if entry, ok := r.workflows[key]; ok { - return entry, false - } - - wfCtx, cancel := context.WithCancel(ctx) - entry := &WorkflowEntry{ - AlbumID: albumID, - Quality: quality, - Ctx: wfCtx, - Cancel: cancel, - Topic: key, - Ready: make(chan struct{}), - } - r.workflows[key] = entry - return entry, true -} - -func (r *WorkflowRegistry) Remove(albumID, quality string) { - r.mu.Lock() - defer r.mu.Unlock() - - key := workflowKey(albumID, quality) - delete(r.workflows, key) -} - -func (r *WorkflowRegistry) Get(albumID, quality string) (*WorkflowEntry, bool) { - r.mu.Lock() - defer r.mu.Unlock() - - key := workflowKey(albumID, quality) - entry, ok := r.workflows[key] - return entry, ok -} - -func (r *WorkflowRegistry) WaitGroup() *sync.WaitGroup { - return &r.wg -} - -func (r *WorkflowRegistry) Shutdown(timeout time.Duration) { - r.mu.Lock() - for _, entry := range r.workflows { - entry.Cancel() - } - r.mu.Unlock() - - done := make(chan struct{}) - go func() { - r.wg.Wait() - close(done) - }() - - select { - case <-done: - case <-time.After(timeout): - } -} diff --git a/internal/workflow_registry_test.go b/internal/workflow_registry_test.go deleted file mode 100644 index fcebf07..0000000 --- a/internal/workflow_registry_test.go +++ /dev/null @@ -1,144 +0,0 @@ -package internal - -import ( - "context" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "homelab.lan/music-agregator/internal/eventbus" -) - -func TestRegistry_GetOrCreate_New(t *testing.T) { - bus := eventbus.New() - reg := NewWorkflowRegistry(bus) - - entry, created := reg.GetOrCreate(context.Background(), "album-1", "LOSSLESS") - assert.True(t, created) - require.NotNil(t, entry) - assert.Equal(t, "album-1", entry.AlbumID) - assert.Equal(t, "LOSSLESS", entry.Quality) - assert.Equal(t, "album-1:LOSSLESS", entry.Topic) - assert.NotNil(t, entry.Ctx) - assert.NotNil(t, entry.Cancel) - assert.NotNil(t, entry.Ready) -} - -func TestRegistry_GetOrCreate_ExistingReturned(t *testing.T) { - bus := eventbus.New() - reg := NewWorkflowRegistry(bus) - - entry1, created1 := reg.GetOrCreate(context.Background(), "album-1", "LOSSLESS") - assert.True(t, created1) - - entry2, created2 := reg.GetOrCreate(context.Background(), "album-1", "LOSSLESS") - assert.False(t, created2) - assert.Same(t, entry1, entry2) -} - -func TestRegistry_GetOrCreate_DifferentQuality(t *testing.T) { - bus := eventbus.New() - reg := NewWorkflowRegistry(bus) - - entry1, created1 := reg.GetOrCreate(context.Background(), "album-1", "LOSSLESS") - assert.True(t, created1) - - entry2, created2 := reg.GetOrCreate(context.Background(), "album-1", "LOSSY") - assert.True(t, created2) - assert.NotSame(t, entry1, entry2) -} - -func TestRegistry_Remove(t *testing.T) { - bus := eventbus.New() - reg := NewWorkflowRegistry(bus) - - reg.GetOrCreate(context.Background(), "album-1", "LOSSLESS") - reg.Remove("album-1", "LOSSLESS") - - _, ok := reg.Get("album-1", "LOSSLESS") - assert.False(t, ok) - - entry, created := reg.GetOrCreate(context.Background(), "album-1", "LOSSLESS") - assert.True(t, created) - assert.NotNil(t, entry) -} - -func TestRegistry_Get(t *testing.T) { - bus := eventbus.New() - reg := NewWorkflowRegistry(bus) - - _, ok := reg.Get("album-1", "LOSSLESS") - assert.False(t, ok) - - reg.GetOrCreate(context.Background(), "album-1", "LOSSLESS") - entry, ok := reg.Get("album-1", "LOSSLESS") - assert.True(t, ok) - assert.Equal(t, "album-1", entry.AlbumID) -} - -func TestRegistry_ConcurrentGetOrCreate(t *testing.T) { - bus := eventbus.New() - reg := NewWorkflowRegistry(bus) - - var wg sync.WaitGroup - results := make(chan bool, 20) - - for i := 0; i < 20; i++ { - wg.Add(1) - go func() { - defer wg.Done() - _, created := reg.GetOrCreate(context.Background(), "album-1", "LOSSLESS") - results <- created - }() - } - - wg.Wait() - close(results) - - createdCount := 0 - for created := range results { - if created { - createdCount++ - } - } - assert.Equal(t, 1, createdCount) -} - -func TestRegistry_Shutdown(t *testing.T) { - bus := eventbus.New() - reg := NewWorkflowRegistry(bus) - - entry, _ := reg.GetOrCreate(context.Background(), "album-1", "LOSSLESS") - - reg.WaitGroup().Add(1) - go func() { - defer reg.WaitGroup().Done() - <-entry.Ctx.Done() - }() - - start := time.Now() - reg.Shutdown(5 * time.Second) - elapsed := time.Since(start) - - assert.Less(t, elapsed, 2*time.Second) - assert.Error(t, entry.Ctx.Err()) -} - -func TestRegistry_ShutdownTimeout(t *testing.T) { - bus := eventbus.New() - reg := NewWorkflowRegistry(bus) - - reg.WaitGroup().Add(1) - - start := time.Now() - reg.Shutdown(100 * time.Millisecond) - elapsed := time.Since(start) - - assert.GreaterOrEqual(t, elapsed, 100*time.Millisecond) - assert.Less(t, elapsed, 500*time.Millisecond) - - reg.WaitGroup().Done() -} diff --git a/justfile b/justfile index 372da8b..ff48e22 100644 --- a/justfile +++ b/justfile @@ -1,13 +1,8 @@ -target := "cmd/music-agregator/main.go" - proto: buf generate build: proto - go build {{target}} - -tidy: - go mod tidy + cargo build run *FLAGS: proto - go run {{target}} {{FLAGS}} + cargo run -- {{FLAGS}} diff --git a/nix/default.nix b/nix/default.nix deleted file mode 100644 index 44817d4..0000000 --- a/nix/default.nix +++ /dev/null @@ -1,68 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -let - cfg = config.services.agregators; -in -{ - imports = [ - ./postgres.nix - ./vpn.nix - ./qbittorrent.nix - ./jackett.nix - ./metadata-agregator.nix - ./musicfs.nix - ./music-agregator.nix - ]; - - options.services.agregators = { - enable = lib.mkEnableOption "agregators music automation pipeline"; - - mediaDir = lib.mkOption { - type = lib.types.path; - default = "/data/music"; - description = '' - Root directory for music files. - qBittorrent downloads here, musicfs reads from here. - ''; - }; - - stateDir = lib.mkOption { - type = lib.types.path; - default = "/var/lib/agregators"; - description = "Root state directory. Per-service subdirectories are created automatically."; - }; - - user = lib.mkOption { - type = lib.types.str; - default = "agregators"; - description = "Shared system user for all agregators services."; - }; - - group = lib.mkOption { - type = lib.types.str; - default = "agregators"; - description = "Shared system group for all agregators services."; - }; - }; - - config = lib.mkIf cfg.enable { - users.users.${cfg.user} = lib.mkIf (cfg.user == "agregators") { - isSystemUser = true; - group = cfg.group; - home = cfg.stateDir; - }; - - users.groups.${cfg.group} = lib.mkIf (cfg.group == "agregators") { }; - - systemd.tmpfiles.rules = [ - "d '${cfg.mediaDir}' 0775 ${cfg.user} ${cfg.group} - -" - "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" - "d '${cfg.stateDir}/postgres' 0770 ${cfg.user} ${cfg.group} - -" - ]; - }; -} diff --git a/nix/jackett.nix b/nix/jackett.nix deleted file mode 100644 index 9afb03c..0000000 --- a/nix/jackett.nix +++ /dev/null @@ -1,75 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -let - cfg = config.services.agregators; - jackettCfg = cfg.jackett; -in -{ - options.services.agregators.jackett = { - enable = lib.mkEnableOption "Jackett torrent indexer aggregator"; - - port = lib.mkOption { - type = lib.types.port; - default = 9117; - description = "Jackett HTTP port."; - }; - - stateDir = lib.mkOption { - type = lib.types.path; - default = "${cfg.stateDir}/jackett"; - defaultText = lib.literalExpression ''"''${cfg.stateDir}/jackett"''; - description = "Jackett data directory."; - }; - - apiKeyFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - description = '' - File containing the Jackett API key. - If null, music-agregator must be configured with the API key manually. - ''; - }; - - package = lib.mkPackageOption pkgs "jackett" { }; - - openFirewall = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Open the Jackett port in the firewall."; - }; - }; - - config = lib.mkIf (cfg.enable && jackettCfg.enable) { - systemd.tmpfiles.rules = [ - "d '${jackettCfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" - ]; - - systemd.services.jackett = { - description = "Jackett torrent indexer aggregator"; - after = [ "network-online.target" ]; - wants = [ "network-online.target" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - Type = "simple"; - User = cfg.user; - Group = cfg.group; - ExecStart = lib.concatStringsSep " " [ - "${lib.getExe jackettCfg.package}" - "--DataFolder=${jackettCfg.stateDir}" - "--Port=${toString jackettCfg.port}" - "--NoUpdates" - ]; - Restart = "on-failure"; - RestartSec = 5; - }; - }; - - networking.firewall.allowedTCPPorts = lib.mkIf jackettCfg.openFirewall [ jackettCfg.port ]; - }; -} diff --git a/nix/metadata-agregator.nix b/nix/metadata-agregator.nix deleted file mode 100644 index de38476..0000000 --- a/nix/metadata-agregator.nix +++ /dev/null @@ -1,142 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -let - cfg = config.services.agregators; - metaCfg = cfg.metadata-agregator; - pgCfg = cfg.postgres; - db = pgCfg.metadataDatabase; - yaml = pkgs.formats.yaml { }; - - dbPasswordPlaceholder = "@META_DB_PASSWORD@"; - - configFile = yaml.generate "metadata-agregator.yaml" { - server.port = metaCfg.port; - database = { - host = if pgCfg.host == "/run/postgresql" then "localhost" else pgCfg.host; - port = pgCfg.port; - name = db.name; - user = db.user; - password = dbPasswordPlaceholder; - sslmode = "disable"; - }; - logging = { - level = metaCfg.logging.level; - format = metaCfg.logging.format; - }; - metrics = { - enabled = metaCfg.metrics.enable; - port = metaCfg.metrics.port; - }; - }; -in -{ - options.services.agregators.metadata-agregator = { - enable = lib.mkEnableOption "metadata-agregator music metadata gRPC service"; - - package = lib.mkOption { - type = lib.types.package; - description = "The metadata-agregator package."; - }; - - port = lib.mkOption { - type = lib.types.port; - default = 50051; - description = "gRPC listen port."; - }; - - logging = { - level = lib.mkOption { - type = lib.types.str; - default = "info"; - description = "Log level."; - }; - - format = lib.mkOption { - type = lib.types.enum [ - "json" - "console" - ]; - default = "json"; - description = "Log output format."; - }; - }; - - metrics = { - enable = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Enable Prometheus metrics endpoint."; - }; - - port = lib.mkOption { - type = lib.types.port; - default = 9091; - description = "Prometheus metrics HTTP port."; - }; - }; - - openFirewall = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Open the gRPC port in the firewall."; - }; - }; - - config = lib.mkIf (cfg.enable && metaCfg.enable) { - systemd.services.metadata-agregator = { - description = "metadata-agregator - Music metadata gRPC service"; - after = [ - "network.target" - "agregators-schema-metadata.service" - ]; - requires = [ "agregators-schema-metadata.service" ]; - wantedBy = [ "multi-user.target" ]; - - preStart = '' - cp --no-preserve=mode ${configFile} /run/metadata-agregator/config.yaml - - ${ - if db.passwordFile != null then - '' - ${pkgs.replace-secret}/bin/replace-secret \ - '${dbPasswordPlaceholder}' \ - '${db.passwordFile}' \ - /run/metadata-agregator/config.yaml - '' - else - '' - ${pkgs.gnused}/bin/sed -i "s/${dbPasswordPlaceholder}//" /run/metadata-agregator/config.yaml - '' - } - ''; - - serviceConfig = { - Type = "simple"; - ExecStart = "${lib.getExe metaCfg.package} -config /run/metadata-agregator/config.yaml"; - User = cfg.user; - Group = cfg.group; - RuntimeDirectory = "metadata-agregator"; - RuntimeDirectoryMode = "0750"; - Restart = "on-failure"; - RestartSec = 5; - - ProtectSystem = "strict"; - PrivateTmp = true; - NoNewPrivileges = true; - ProtectHome = true; - ProtectKernelTunables = true; - ProtectKernelModules = true; - ProtectControlGroups = true; - }; - }; - - networking.firewall.allowedTCPPorts = lib.mkIf metaCfg.openFirewall ( - [ metaCfg.port ] ++ lib.optional metaCfg.metrics.enable metaCfg.metrics.port - ); - }; -} diff --git a/nix/music-agregator.nix b/nix/music-agregator.nix deleted file mode 100644 index 42565b1..0000000 --- a/nix/music-agregator.nix +++ /dev/null @@ -1,275 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -let - cfg = config.services.agregators; - maCfg = cfg.music-agregator; - pgCfg = cfg.postgres; - qbtCfg = cfg.qbittorrent; - jackettCfg = cfg.jackett; - metaCfg = cfg.metadata-agregator; - mfsCfg = cfg.musicfs; - vpnCfg = cfg.vpn; - yaml = pkgs.formats.yaml { }; - - vpnEnabled = vpnCfg.enable && qbtCfg.vpn.enable or false; - namespaceAddr = "192.168.15.1"; - musicfsEnabled = mfsCfg.enable; - - dbPasswordPlaceholder = "@MUSIC_DB_PASSWORD@"; - qbtPasswordPlaceholder = "@QBT_PASSWORD@"; - - # Auto-wire qBittorrent address based on VPN - qbtAddr = - if maCfg.qbittorrentUrl != null then - maCfg.qbittorrentUrl - else if vpnEnabled then - "http://${namespaceAddr}:${toString qbtCfg.webuiPort}" - else - "http://127.0.0.1:${toString qbtCfg.webuiPort}"; - - dbHost = if pgCfg.host == "/run/postgresql" then "localhost" else pgCfg.host; - - configFile = yaml.generate "music-agregator.yaml" { - app = { - host = maCfg.host; - port = toString maCfg.port; - }; - database = { - url = "postgresql://${pgCfg.musicDatabase.user}:${dbPasswordPlaceholder}@${dbHost}:${toString pgCfg.port}/${pgCfg.musicDatabase.name}?sslmode=disable"; - }; - indexer = { - url = maCfg.jackettUrl; - type = "jackett"; - api_key = "@JACKETT_API_KEY@"; - } - // lib.optionalAttrs (maCfg.indexerCache.enable) { - cache = { - enabled = true; - refresh_interval = maCfg.indexerCache.refreshInterval; - ttl = maCfg.indexerCache.ttl; - }; - }; - torrent = { - client_type = "qbittorrent"; - url = qbtAddr; - username = qbtCfg.username; - password = qbtPasswordPlaceholder; - # No container_name — native paths, no Docker - }; - metadata = { - endpoint = maCfg.metadataEndpoint; - }; - musicfs = { - enabled = musicfsEnabled; - endpoint = maCfg.musicfsEndpoint; - origin_id = lib.optionalString musicfsEnabled mfsCfg.originId; - origin_root = lib.optionalString musicfsEnabled (toString mfsCfg.originPath); - timeout_seconds = maCfg.musicfsTimeoutSeconds; - }; - }; -in -{ - options.services.agregators.music-agregator = { - enable = lib.mkEnableOption "music-agregator orchestrator service"; - - package = lib.mkOption { - type = lib.types.package; - description = "The music-agregator package."; - }; - - host = lib.mkOption { - type = lib.types.str; - default = "0.0.0.0"; - description = "gRPC server bind address."; - }; - - port = lib.mkOption { - type = lib.types.port; - default = 3000; - description = "gRPC server port."; - }; - - # --- Auto-wired endpoints (override for external services) --- - - metadataEndpoint = lib.mkOption { - type = lib.types.str; - default = "localhost:${toString metaCfg.port}"; - defaultText = lib.literalExpression ''"localhost:''${toString cfg.metadata-agregator.port}"''; - description = "metadata-agregator gRPC endpoint."; - }; - - musicfsEndpoint = lib.mkOption { - type = lib.types.str; - default = "localhost:${toString mfsCfg.port}"; - defaultText = lib.literalExpression ''"localhost:''${toString cfg.musicfs.port}"''; - description = "musicfs gRPC endpoint."; - }; - - musicfsTimeoutSeconds = lib.mkOption { - type = lib.types.int; - default = 300; - description = "Timeout in seconds for musicfs operations."; - }; - - jackettUrl = lib.mkOption { - type = lib.types.str; - default = "http://127.0.0.1:${toString jackettCfg.port}"; - defaultText = lib.literalExpression ''"http://127.0.0.1:''${toString cfg.jackett.port}"''; - description = "Jackett HTTP URL."; - }; - - jackettApiKeyFile = lib.mkOption { - type = lib.types.path; - description = "File containing the Jackett API key."; - }; - - qbittorrentUrl = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - description = '' - qBittorrent WebUI URL override. - If null, auto-detected from VPN and port config. - ''; - }; - - qbittorrentPasswordFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = qbtCfg.passwordFile; - defaultText = lib.literalExpression "cfg.qbittorrent.passwordFile"; - description = "File containing qBittorrent WebUI password."; - }; - - indexerCache = { - enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Enable Jackett indexer cache with background refresh."; - }; - - refreshInterval = lib.mkOption { - type = lib.types.str; - default = "30m"; - description = "Background refresh interval."; - }; - - ttl = lib.mkOption { - type = lib.types.str; - default = "1h"; - description = "Cache entry time-to-live."; - }; - }; - - openFirewall = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Open the gRPC port in the firewall."; - }; - }; - - config = lib.mkIf (cfg.enable && maCfg.enable) { - assertions = [ - { - assertion = metaCfg.enable; - message = "services.agregators.music-agregator requires services.agregators.metadata-agregator.enable"; - } - { - assertion = jackettCfg.enable || maCfg.jackettUrl != "http://127.0.0.1:${toString jackettCfg.port}"; - message = "services.agregators.music-agregator requires either jackett enabled or a custom jackettUrl"; - } - { - assertion = qbtCfg.enable || maCfg.qbittorrentUrl != null; - message = "services.agregators.music-agregator requires either qbittorrent enabled or a custom qbittorrentUrl"; - } - ]; - - systemd.services.music-agregator = { - description = "music-agregator - Music automation orchestrator"; - after = [ - "network.target" - "agregators-schema-music.service" - "metadata-agregator.service" - ] - ++ lib.optional jackettCfg.enable "jackett.service" - ++ lib.optional qbtCfg.enable "qbittorrent.service" - ++ lib.optional musicfsEnabled "musicfs.service"; - - requires = [ - "agregators-schema-music.service" - "metadata-agregator.service" - ]; - - wants = - lib.optional jackettCfg.enable "jackett.service" - ++ lib.optional qbtCfg.enable "qbittorrent.service" - ++ lib.optional musicfsEnabled "musicfs.service"; - - wantedBy = [ "multi-user.target" ]; - - preStart = '' - cp --no-preserve=mode ${configFile} /run/music-agregator/config.yaml - - # Inject database password - ${ - if pgCfg.musicDatabase.passwordFile != null then - '' - ${pkgs.replace-secret}/bin/replace-secret \ - '${dbPasswordPlaceholder}' \ - '${pgCfg.musicDatabase.passwordFile}' \ - /run/music-agregator/config.yaml - '' - else - '' - ${pkgs.gnused}/bin/sed -i "s/${dbPasswordPlaceholder}//" /run/music-agregator/config.yaml - '' - } - - # Inject Jackett API key - ${pkgs.replace-secret}/bin/replace-secret \ - '@JACKETT_API_KEY@' \ - '${maCfg.jackettApiKeyFile}' \ - /run/music-agregator/config.yaml - - # Inject qBittorrent password - ${ - if maCfg.qbittorrentPasswordFile != null then - '' - ${pkgs.replace-secret}/bin/replace-secret \ - '${qbtPasswordPlaceholder}' \ - '${maCfg.qbittorrentPasswordFile}' \ - /run/music-agregator/config.yaml - '' - else - '' - ${pkgs.gnused}/bin/sed -i "s/${qbtPasswordPlaceholder}//" /run/music-agregator/config.yaml - '' - } - ''; - - serviceConfig = { - Type = "simple"; - ExecStart = "${lib.getExe maCfg.package} -config /run/music-agregator/config.yaml"; - User = cfg.user; - Group = cfg.group; - RuntimeDirectory = "music-agregator"; - RuntimeDirectoryMode = "0750"; - Restart = "on-failure"; - RestartSec = 5; - - ProtectSystem = "strict"; - PrivateTmp = true; - NoNewPrivileges = true; - ProtectHome = true; - ProtectKernelTunables = true; - ProtectKernelModules = true; - ProtectControlGroups = true; - }; - }; - - networking.firewall.allowedTCPPorts = lib.mkIf maCfg.openFirewall [ maCfg.port ]; - }; -} diff --git a/nix/musicfs.nix b/nix/musicfs.nix deleted file mode 100644 index 95b070e..0000000 --- a/nix/musicfs.nix +++ /dev/null @@ -1,142 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -let - cfg = config.services.agregators; - mfsCfg = cfg.musicfs; - toml = pkgs.formats.toml { }; - - configFile = toml.generate "musicfs.toml" ( - { - mount_point = mfsCfg.mountPoint; - cache_dir = mfsCfg.cacheDir; - - origins = [ - { - id = mfsCfg.originId; - origin_type = "local"; - priority = 1; - enabled = true; - path = mfsCfg.originPath; - } - ]; - } - // lib.optionalAttrs (mfsCfg.cache != { }) { cache = mfsCfg.cache; } - // lib.optionalAttrs (mfsCfg.logging != { }) { logging = mfsCfg.logging; } - // mfsCfg.extraConfig - ); -in -{ - options.services.agregators.musicfs = { - enable = lib.mkEnableOption "musicfs virtual FUSE filesystem"; - - package = lib.mkOption { - type = lib.types.package; - description = "The musicfs package."; - }; - - port = lib.mkOption { - type = lib.types.port; - default = 50052; - description = "gRPC control API port."; - }; - - mountPoint = lib.mkOption { - type = lib.types.path; - default = "/mnt/music"; - description = "Where to mount the virtual filesystem."; - }; - - cacheDir = lib.mkOption { - type = lib.types.path; - default = "${cfg.stateDir}/musicfs/cache"; - defaultText = lib.literalExpression ''"''${cfg.stateDir}/musicfs/cache"''; - description = "Directory for cache data (CAS chunks, metadata, search index)."; - }; - - originPath = lib.mkOption { - type = lib.types.path; - default = "${cfg.mediaDir}/downloads"; - defaultText = lib.literalExpression ''"''${cfg.mediaDir}/downloads"''; - description = "Source directory for music files (typically qBittorrent download dir)."; - }; - - originId = lib.mkOption { - type = lib.types.str; - default = "local-storage"; - description = "Origin identifier used by musicfs and music-agregator."; - }; - - cache = lib.mkOption { - type = lib.types.attrsOf toml.type; - default = { }; - description = "Cache settings passed to [cache] in config."; - }; - - logging = lib.mkOption { - type = lib.types.attrsOf toml.type; - default = { }; - description = "Logging settings passed to [logging] in config."; - }; - - extraConfig = lib.mkOption { - type = lib.types.attrsOf toml.type; - default = { }; - description = "Additional top-level config keys."; - }; - - openFirewall = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Open the gRPC port in the firewall."; - }; - }; - - config = lib.mkIf (cfg.enable && mfsCfg.enable) { - programs.fuse.userAllowOther = true; - - systemd.tmpfiles.rules = [ - "d '${mfsCfg.mountPoint}' 0755 ${cfg.user} ${cfg.group} - -" - "d '${mfsCfg.cacheDir}' 0750 ${cfg.user} ${cfg.group} - -" - ]; - - systemd.services.musicfs = { - description = "MusicFS - Virtual FUSE Filesystem for Music"; - after = [ - "network.target" - "local-fs.target" - ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - Type = "notify"; - ExecStart = "${lib.getExe mfsCfg.package} mount --config ${configFile} --grpc-port ${toString mfsCfg.port}"; - ExecStopPost = "${pkgs.fuse3}/bin/fusermount3 -u ${mfsCfg.mountPoint}"; - User = cfg.user; - Group = cfg.group; - Restart = "on-failure"; - RestartSec = 5; - - ProtectSystem = "strict"; - ReadWritePaths = [ - mfsCfg.mountPoint - mfsCfg.cacheDir - mfsCfg.originPath - ]; - PrivateTmp = true; - NoNewPrivileges = true; - ProtectHome = "read-only"; - ProtectKernelTunables = true; - ProtectKernelModules = true; - ProtectControlGroups = true; - DeviceAllow = [ "/dev/fuse rw" ]; - }; - }; - - networking.firewall.allowedTCPPorts = lib.mkIf mfsCfg.openFirewall [ mfsCfg.port ]; - }; -} diff --git a/nix/postgres.nix b/nix/postgres.nix deleted file mode 100644 index 4d0b8ae..0000000 --- a/nix/postgres.nix +++ /dev/null @@ -1,237 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -let - cfg = config.services.agregators; - pgCfg = cfg.postgres; - - # For local: run as the db user via peer auth (service runs as that user) - # For remote: run as anyone, use password auth via PGPASSWORD - mkPsql = - db: - lib.concatStringsSep " " ( - [ - "${pkgs.postgresql}/bin/psql" - ] - ++ lib.optionals (!isLocal) [ - "-h ${lib.escapeShellArg pgCfg.host}" - "-p ${toString pgCfg.port}" - "-U ${lib.escapeShellArg db.user}" - ] - ++ [ - "-d ${lib.escapeShellArg db.name}" - ] - ); - - mkPasswordExport = - db: - if db.passwordFile != null then - ''export PGPASSWORD="$(cat ${lib.escapeShellArg db.passwordFile})"'' - else - ""; - - isLocal = pgCfg.host == "/run/postgresql" || pgCfg.host == "localhost" || pgCfg.host == "127.0.0.1"; -in -{ - options.services.agregators.postgres = { - host = lib.mkOption { - type = lib.types.str; - default = "/run/postgresql"; - description = '' - PostgreSQL host. Use a path for unix socket (e.g. /run/postgresql) - or a hostname for TCP. - ''; - }; - - port = lib.mkOption { - type = lib.types.port; - default = 5432; - description = "PostgreSQL port (ignored for unix socket connections)."; - }; - - musicDatabase = { - name = lib.mkOption { - type = lib.types.str; - default = "music_agregator"; - description = "Database name for music-agregator."; - }; - - user = lib.mkOption { - type = lib.types.str; - default = "music_agregator"; - description = "Database user for music-agregator."; - }; - - passwordFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - description = "Password file for music-agregator database. Null for peer auth."; - }; - }; - - metadataDatabase = { - name = lib.mkOption { - type = lib.types.str; - default = "metadata_agregator"; - description = "Database name for metadata-agregator."; - }; - - user = lib.mkOption { - type = lib.types.str; - default = "metadata_agregator"; - description = "Database user for metadata-agregator."; - }; - - passwordFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - description = "Password file for metadata-agregator database. Null for peer auth."; - }; - }; - - settings = lib.mkOption { - type = lib.types.attrsOf lib.types.str; - default = { }; - description = "Extra PostgreSQL settings merged into services.postgresql.settings."; - example = { - shared_buffers = "256MB"; - effective_cache_size = "768MB"; - }; - }; - }; - - config = lib.mkIf cfg.enable { - # Create system users for peer auth (local postgres only) - users.users = lib.mkIf isLocal { - ${pgCfg.musicDatabase.user} = { - isSystemUser = true; - group = cfg.group; - }; - ${pgCfg.metadataDatabase.user} = { - isSystemUser = true; - group = cfg.group; - }; - }; - - # Enable and configure local PostgreSQL - services.postgresql = lib.mkIf isLocal { - enable = lib.mkDefault true; - settings = { - shared_preload_libraries = "pg_prewarm"; - } - // pgCfg.settings; - - ensureDatabases = [ - pgCfg.musicDatabase.name - pgCfg.metadataDatabase.name - ]; - - ensureUsers = [ - { - name = pgCfg.musicDatabase.user; - ensureDBOwnership = true; - } - { - name = pgCfg.metadataDatabase.user; - ensureDBOwnership = true; - } - ]; - }; - - # Schema init for metadata_agregator - systemd.services.agregators-schema-metadata = { - description = "Initialize metadata_agregator database schema"; - after = [ "network.target" ] ++ lib.optionals isLocal [ "postgresql.service" ]; - requires = lib.optionals isLocal [ "postgresql.service" ]; - before = [ "metadata-agregator.service" ]; - requiredBy = [ "metadata-agregator.service" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - # Run as the db user for peer auth on local postgres - User = if isLocal then pgCfg.metadataDatabase.user else cfg.user; - }; - - script = - let - psql = mkPsql pgCfg.metadataDatabase; - passwordExport = mkPasswordExport pgCfg.metadataDatabase; - in - '' - ${passwordExport} - MARKER="${cfg.stateDir}/postgres/.schema-metadata-initialized" - - # Wait for database - for i in $(seq 1 30); do - if ${psql} -c "SELECT 1" >/dev/null 2>&1; then break; fi - echo "Waiting for metadata database... ($i/30)" - sleep 1 - done - - if [ -f "$MARKER" ]; then - echo "metadata_agregator schema already initialized" - exit 0 - fi - - echo "Applying metadata_agregator schema..." - ${psql} -f ${./sql/metadata/001_schema.sql} - - touch "$MARKER" - echo "metadata_agregator schema initialized" - ''; - }; - - # Schema init for music_agregator - systemd.services.agregators-schema-music = { - description = "Initialize music_agregator database schema"; - after = [ "network.target" ] ++ lib.optionals isLocal [ "postgresql.service" ]; - requires = lib.optionals isLocal [ "postgresql.service" ]; - before = [ "music-agregator.service" ]; - requiredBy = [ "music-agregator.service" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - # Run as the db user for peer auth on local postgres - User = if isLocal then pgCfg.musicDatabase.user else cfg.user; - }; - - script = - let - psql = mkPsql pgCfg.musicDatabase; - passwordExport = mkPasswordExport pgCfg.musicDatabase; - in - '' - ${passwordExport} - MARKER="${cfg.stateDir}/postgres/.schema-music-initialized" - - # Wait for database - for i in $(seq 1 30); do - if ${psql} -c "SELECT 1" >/dev/null 2>&1; then break; fi - echo "Waiting for music database... ($i/30)" - sleep 1 - done - - if [ -f "$MARKER" ]; then - echo "music_agregator schema already initialized" - exit 0 - fi - - echo "Applying music_agregator schema..." - ${psql} -f ${./sql/music/001_river.sql} - ${psql} -f ${./sql/music/002_schema.sql} - ${psql} -f ${./sql/music/003_event_bus.sql} - - touch "$MARKER" - echo "music_agregator schema initialized" - ''; - }; - }; -} diff --git a/nix/qbittorrent.nix b/nix/qbittorrent.nix deleted file mode 100644 index 912d73c..0000000 --- a/nix/qbittorrent.nix +++ /dev/null @@ -1,136 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -let - cfg = config.services.agregators; - qbtCfg = cfg.qbittorrent; - vpnCfg = cfg.vpn; - vpnEnabled = vpnCfg.enable && qbtCfg.vpn.enable; - - # Inside VPN namespace, services bind to the namespace address - namespaceAddr = "192.168.15.1"; - listenAddr = if vpnEnabled then namespaceAddr else "0.0.0.0"; -in -{ - options.services.agregators.qbittorrent = { - enable = lib.mkEnableOption "qBittorrent torrent client"; - - vpn = { - enable = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Confine qBittorrent to the VPN network namespace."; - }; - }; - - webuiPort = lib.mkOption { - type = lib.types.port; - default = 8080; - description = "qBittorrent WebUI port."; - }; - - peerPort = lib.mkOption { - type = lib.types.port; - default = 6881; - description = "BitTorrent peer port (opened through VPN)."; - }; - - downloadDir = lib.mkOption { - type = lib.types.path; - default = "${cfg.mediaDir}/downloads"; - defaultText = lib.literalExpression ''"''${cfg.mediaDir}/downloads"''; - description = "Directory where qBittorrent saves completed downloads."; - }; - - username = lib.mkOption { - type = lib.types.str; - default = "admin"; - description = "qBittorrent WebUI username."; - }; - - passwordFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - description = "File containing qBittorrent WebUI password."; - }; - - stateDir = lib.mkOption { - type = lib.types.path; - default = "${cfg.stateDir}/qbittorrent"; - defaultText = lib.literalExpression ''"''${cfg.stateDir}/qbittorrent"''; - description = "qBittorrent state/config directory."; - }; - - package = lib.mkPackageOption pkgs "qbittorrent-nox" { }; - - openFirewall = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Open the WebUI port in the firewall."; - }; - }; - - config = lib.mkIf (cfg.enable && qbtCfg.enable) { - assertions = [ - { - assertion = qbtCfg.vpn.enable -> vpnCfg.enable; - message = "services.agregators.qbittorrent.vpn.enable requires services.agregators.vpn.enable"; - } - ]; - - systemd.tmpfiles.rules = [ - "d '${qbtCfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" - "d '${qbtCfg.stateDir}/qBittorrent' 0750 ${cfg.user} ${cfg.group} - -" - "d '${qbtCfg.stateDir}/qBittorrent/config' 0750 ${cfg.user} ${cfg.group} - -" - "d '${qbtCfg.downloadDir}' 0775 ${cfg.user} ${cfg.group} - -" - "d '${qbtCfg.downloadDir}/.incomplete' 0775 ${cfg.user} ${cfg.group} - -" - ]; - - systemd.services.qbittorrent = { - description = "qBittorrent-nox BitTorrent client"; - after = [ "network-online.target" ]; - wants = [ "network-online.target" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - Type = "simple"; - User = cfg.user; - Group = cfg.group; - ExecStart = lib.concatStringsSep " " [ - "${lib.getExe qbtCfg.package}" - "--webui-port=${toString qbtCfg.webuiPort}" - "--profile=${qbtCfg.stateDir}" - ]; - Restart = "on-failure"; - RestartSec = 5; - }; - }; - - # VPN confinement - systemd.services.qbittorrent.vpnConfinement = lib.mkIf vpnEnabled { - enable = true; - vpnNamespace = vpnCfg.namespace; - }; - - vpnNamespaces.${vpnCfg.namespace} = lib.mkIf vpnEnabled { - portMappings = [ - { - from = qbtCfg.webuiPort; - to = qbtCfg.webuiPort; - } - ]; - openVPNPorts = [ - { - port = qbtCfg.peerPort; - protocol = "both"; - } - ]; - }; - - networking.firewall.allowedTCPPorts = lib.mkIf qbtCfg.openFirewall [ qbtCfg.webuiPort ]; - }; -} diff --git a/nix/sql/metadata/001_schema.sql b/nix/sql/metadata/001_schema.sql deleted file mode 100644 index 3cf729c..0000000 --- a/nix/sql/metadata/001_schema.sql +++ /dev/null @@ -1,194 +0,0 @@ -CREATE EXTENSION IF NOT EXISTS pg_prewarm; -CREATE EXTENSION IF NOT EXISTS pg_trgm; - -CREATE TABLE artists ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - name TEXT NOT NULL, - sort_name TEXT, - artist_type TEXT, - country TEXT, - formed_date DATE, - disbanded_date DATE, - description TEXT, - image_url TEXT, - source TEXT NOT NULL, - source_id TEXT, - created_at TIMESTAMPTZ DEFAULT now(), - updated_at TIMESTAMPTZ DEFAULT now() -); - -CREATE TABLE works ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - title TEXT NOT NULL, - work_type TEXT, - language TEXT, - source TEXT NOT NULL, - source_id TEXT, - created_at TIMESTAMPTZ DEFAULT now(), - updated_at TIMESTAMPTZ DEFAULT now() -); - -CREATE TABLE tracks ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - work_id UUID REFERENCES works(id), - title TEXT NOT NULL, - duration_ms INT, - isrc TEXT, - explicit BOOLEAN DEFAULT false, - source TEXT NOT NULL, - source_id TEXT, - created_at TIMESTAMPTZ DEFAULT now(), - updated_at TIMESTAMPTZ DEFAULT now() -); - -CREATE TABLE labels ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - name TEXT NOT NULL, - country TEXT, - founded_date DATE, - source TEXT NOT NULL, - source_id TEXT, - created_at TIMESTAMPTZ DEFAULT now(), - updated_at TIMESTAMPTZ DEFAULT now() -); - -CREATE TABLE albums ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - label_id UUID REFERENCES labels(id), - title TEXT NOT NULL, - album_type TEXT, - secondary_types TEXT[] DEFAULT '{}', - release_date DATE, - upc TEXT, - total_tracks INT, - total_discs INT DEFAULT 1, - cover_url TEXT, - source TEXT NOT NULL, - source_id TEXT, - created_at TIMESTAMPTZ DEFAULT now(), - updated_at TIMESTAMPTZ DEFAULT now() -); - -CREATE TABLE genres ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - name TEXT NOT NULL UNIQUE, - parent_id UUID REFERENCES genres(id) -); - -CREATE TABLE track_artists ( - track_id UUID REFERENCES tracks(id) ON DELETE CASCADE, - artist_id UUID REFERENCES artists(id) ON DELETE CASCADE, - role TEXT DEFAULT 'primary', - position INT DEFAULT 0, - PRIMARY KEY (track_id, artist_id, role) -); - -CREATE TABLE album_artists ( - album_id UUID REFERENCES albums(id) ON DELETE CASCADE, - artist_id UUID REFERENCES artists(id) ON DELETE CASCADE, - role TEXT DEFAULT 'primary', - position INT DEFAULT 0, - PRIMARY KEY (album_id, artist_id, role) -); - -CREATE TABLE album_tracks ( - album_id UUID REFERENCES albums(id) ON DELETE CASCADE, - track_id UUID REFERENCES tracks(id) ON DELETE CASCADE, - disc_number INT DEFAULT 1, - track_number INT NOT NULL, - PRIMARY KEY (album_id, track_id) -); - -CREATE TABLE work_artists ( - work_id UUID REFERENCES works(id) ON DELETE CASCADE, - artist_id UUID REFERENCES artists(id) ON DELETE CASCADE, - role TEXT DEFAULT 'writer', - PRIMARY KEY (work_id, artist_id, role) -); - -CREATE TABLE artist_genres ( - artist_id UUID REFERENCES artists(id) ON DELETE CASCADE, - genre_id UUID REFERENCES genres(id) ON DELETE CASCADE, - PRIMARY KEY (artist_id, genre_id) -); - -CREATE TABLE album_genres ( - album_id UUID REFERENCES albums(id) ON DELETE CASCADE, - genre_id UUID REFERENCES genres(id) ON DELETE CASCADE, - PRIMARY KEY (album_id, genre_id) -); - -CREATE TABLE similar_artists ( - artist_id UUID REFERENCES artists(id) ON DELETE CASCADE, - similar_artist_id UUID REFERENCES artists(id) ON DELETE CASCADE, - score REAL DEFAULT 0.5, - PRIMARY KEY (artist_id, similar_artist_id) -); - -CREATE TABLE lyrics ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - track_id UUID REFERENCES tracks(id) ON DELETE CASCADE, - content TEXT, - synced_content JSONB, - language TEXT, - source TEXT NOT NULL, - source_id TEXT, - created_at TIMESTAMPTZ DEFAULT now() -); - -CREATE TABLE playlists ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - name TEXT NOT NULL, - description TEXT, - is_public BOOLEAN DEFAULT true, - cover_url TEXT, - created_at TIMESTAMPTZ DEFAULT now(), - updated_at TIMESTAMPTZ DEFAULT now() -); - -CREATE TABLE playlist_tracks ( - playlist_id UUID REFERENCES playlists(id) ON DELETE CASCADE, - track_id UUID REFERENCES tracks(id) ON DELETE CASCADE, - position INT NOT NULL, - added_at TIMESTAMPTZ DEFAULT now(), - PRIMARY KEY (playlist_id, track_id) -); - -CREATE TABLE artist_external_ids ( - artist_id UUID REFERENCES artists(id) ON DELETE CASCADE, - source TEXT NOT NULL, - source_id TEXT NOT NULL, - url TEXT, - fetched_at TIMESTAMPTZ DEFAULT now(), - PRIMARY KEY (artist_id, source, source_id) -); - -CREATE TABLE album_external_ids ( - album_id UUID REFERENCES albums(id) ON DELETE CASCADE, - source TEXT NOT NULL, - source_id TEXT NOT NULL, - url TEXT, - fetched_at TIMESTAMPTZ DEFAULT now(), - PRIMARY KEY (album_id, source, source_id) -); - -CREATE TABLE track_external_ids ( - track_id UUID REFERENCES tracks(id) ON DELETE CASCADE, - source TEXT NOT NULL, - source_id TEXT NOT NULL, - url TEXT, - fetched_at TIMESTAMPTZ DEFAULT now(), - PRIMARY KEY (track_id, source, source_id) -); - -CREATE INDEX idx_artists_name ON artists(name); -CREATE INDEX idx_artists_name_trgm ON artists USING gin (name gin_trgm_ops); -CREATE INDEX idx_artists_source ON artists(source, source_id); -CREATE INDEX idx_tracks_isrc ON tracks(isrc) WHERE isrc IS NOT NULL; -CREATE INDEX idx_tracks_source ON tracks(source, source_id); -CREATE INDEX idx_albums_upc ON albums(upc) WHERE upc IS NOT NULL; -CREATE INDEX idx_albums_source ON albums(source, source_id); -CREATE INDEX idx_albums_release_date ON albums(release_date); -CREATE INDEX idx_genres_name ON genres(name); -CREATE INDEX idx_lyrics_track_id ON lyrics(track_id); -CREATE INDEX idx_playlist_tracks_position ON playlist_tracks(playlist_id, position); diff --git a/nix/sql/music/001_river.sql b/nix/sql/music/001_river.sql deleted file mode 100644 index 2319355..0000000 --- a/nix/sql/music/001_river.sql +++ /dev/null @@ -1,286 +0,0 @@ --- Version 1 -CREATE TABLE river_migration( - id bigserial PRIMARY KEY, - created_at timestamptz NOT NULL DEFAULT NOW(), - version bigint NOT NULL, - CONSTRAINT version CHECK (version >= 1) -); - -CREATE UNIQUE INDEX ON river_migration USING btree(version); - --- Version 2 -CREATE TYPE river_job_state AS ENUM( - 'available', - 'cancelled', - 'completed', - 'discarded', - 'retryable', - 'running', - 'scheduled' -); - -CREATE TABLE river_job( - -- 8 bytes - id bigserial PRIMARY KEY, - - -- 8 bytes (4 bytes + 2 bytes + 2 bytes) - -- - -- `state` is kept near the top of the table for operator convenience -- when - -- looking at jobs with `SELECT *` it'll appear first after ID. The other two - -- fields aren't as important but are kept adjacent to `state` for alignment - -- to get an 8-byte block. - state river_job_state NOT NULL DEFAULT 'available', - attempt smallint NOT NULL DEFAULT 0, - max_attempts smallint NOT NULL, - - -- 8 bytes each (no alignment needed) - attempted_at timestamptz, - created_at timestamptz NOT NULL DEFAULT NOW(), - finalized_at timestamptz, - scheduled_at timestamptz NOT NULL DEFAULT NOW(), - - -- 2 bytes (some wasted padding probably) - priority smallint NOT NULL DEFAULT 1, - - -- types stored out-of-band - args jsonb, - attempted_by text[], - errors jsonb[], - kind text NOT NULL, - metadata jsonb NOT NULL DEFAULT '{}', - queue text NOT NULL DEFAULT 'default', - tags varchar(255)[], - - CONSTRAINT finalized_or_finalized_at_null CHECK ((state IN ('cancelled', 'completed', 'discarded') AND finalized_at IS NOT NULL) OR finalized_at IS NULL), - CONSTRAINT max_attempts_is_positive CHECK (max_attempts > 0), - CONSTRAINT priority_in_range CHECK (priority >= 1 AND priority <= 4), - CONSTRAINT queue_length CHECK (char_length(queue) > 0 AND char_length(queue) < 128), - CONSTRAINT kind_length CHECK (char_length(kind) > 0 AND char_length(kind) < 128) -); - --- We may want to consider adding another property here after `kind` if it seems --- like it'd be useful for something. -CREATE INDEX river_job_kind ON river_job USING btree(kind); - -CREATE INDEX river_job_state_and_finalized_at_index ON river_job USING btree(state, finalized_at) WHERE finalized_at IS NOT NULL; - -CREATE INDEX river_job_prioritized_fetching_index ON river_job USING btree(state, queue, priority, scheduled_at, id); - -CREATE INDEX river_job_args_index ON river_job USING GIN(args); - -CREATE INDEX river_job_metadata_index ON river_job USING GIN(metadata); - -CREATE OR REPLACE FUNCTION river_job_notify() - RETURNS TRIGGER - AS $$ -DECLARE - payload json; -BEGIN - IF NEW.state = 'available' THEN - -- Notify will coalesce duplicate notifications within a transaction, so - -- keep these payloads generalized: - payload = json_build_object('queue', NEW.queue); - PERFORM - pg_notify('river_insert', payload::text); - END IF; - RETURN NULL; -END; -$$ -LANGUAGE plpgsql; - -CREATE TRIGGER river_notify - AFTER INSERT ON river_job - FOR EACH ROW - EXECUTE PROCEDURE river_job_notify(); - -CREATE UNLOGGED TABLE river_leader( - -- 8 bytes each (no alignment needed) - elected_at timestamptz NOT NULL, - expires_at timestamptz NOT NULL, - - -- types stored out-of-band - leader_id text NOT NULL, - name text PRIMARY KEY, - - CONSTRAINT name_length CHECK (char_length(name) > 0 AND char_length(name) < 128), - CONSTRAINT leader_id_length CHECK (char_length(leader_id) > 0 AND char_length(leader_id) < 128) -); - - --- Version 3 -ALTER TABLE river_job ALTER COLUMN tags SET DEFAULT '{}'; -UPDATE river_job SET tags = '{}' WHERE tags IS NULL; -ALTER TABLE river_job ALTER COLUMN tags SET NOT NULL; - - --- Version 4 --- The args column never had a NOT NULL constraint or default value at the --- database level, though we tried to ensure one at the application level. -ALTER TABLE river_job ALTER COLUMN args SET DEFAULT '{}'; -UPDATE river_job SET args = '{}' WHERE args IS NULL; -ALTER TABLE river_job ALTER COLUMN args SET NOT NULL; -ALTER TABLE river_job ALTER COLUMN args DROP DEFAULT; - --- The metadata column never had a NOT NULL constraint or default value at the --- database level, though we tried to ensure one at the application level. -ALTER TABLE river_job ALTER COLUMN metadata SET DEFAULT '{}'; -UPDATE river_job SET metadata = '{}' WHERE metadata IS NULL; -ALTER TABLE river_job ALTER COLUMN metadata SET NOT NULL; - --- The 'pending' job state will be used for upcoming functionality: -ALTER TYPE river_job_state ADD VALUE IF NOT EXISTS 'pending' AFTER 'discarded'; - -ALTER TABLE river_job DROP CONSTRAINT finalized_or_finalized_at_null; -ALTER TABLE river_job ADD CONSTRAINT finalized_or_finalized_at_null CHECK ( - (finalized_at IS NULL AND state NOT IN ('cancelled', 'completed', 'discarded')) OR - (finalized_at IS NOT NULL AND state IN ('cancelled', 'completed', 'discarded')) -); - -DROP TRIGGER river_notify ON river_job; -DROP FUNCTION river_job_notify; - --- --- Create table `river_queue`. --- - -CREATE TABLE river_queue ( - name text PRIMARY KEY NOT NULL, - created_at timestamptz NOT NULL DEFAULT now(), - metadata jsonb NOT NULL DEFAULT '{}' ::jsonb, - paused_at timestamptz, - updated_at timestamptz NOT NULL -); - --- --- Alter `river_leader` to add a default value of 'default` to `name`. --- - -ALTER TABLE river_leader - ALTER COLUMN name SET DEFAULT 'default', - DROP CONSTRAINT name_length, - ADD CONSTRAINT name_length CHECK (name = 'default'); - --- Version 5 --- --- Rebuild the migration table so it's based on `(line, version)`. --- - -DO -$body$ -BEGIN - -- Tolerate users who may be using their own migration system rather than - -- River's. If they are, they will have skipped version 001 containing - -- `CREATE TABLE river_migration`, so this table won't exist. - IF (SELECT to_regclass('river_migration') IS NOT NULL) THEN - ALTER TABLE river_migration - RENAME TO river_migration_old; - - CREATE TABLE river_migration( - line TEXT NOT NULL, - version bigint NOT NULL, - created_at timestamptz NOT NULL DEFAULT NOW(), - CONSTRAINT line_length CHECK (char_length(line) > 0 AND char_length(line) < 128), - CONSTRAINT version_gte_1 CHECK (version >= 1), - PRIMARY KEY (line, version) - ); - - INSERT INTO river_migration - (created_at, line, version) - SELECT created_at, 'main', version - FROM river_migration_old; - - DROP TABLE river_migration_old; - END IF; -END; -$body$ -LANGUAGE 'plpgsql'; - --- --- Add `river_job.unique_key` and bring up an index on it. --- - --- These statements use `IF NOT EXISTS` to allow users with a `river_job` table --- of non-trivial size to build the index `CONCURRENTLY` out of band of this --- migration, then follow by completing the migration. -ALTER TABLE river_job - ADD COLUMN IF NOT EXISTS unique_key bytea; - -CREATE UNIQUE INDEX IF NOT EXISTS river_job_kind_unique_key_idx ON river_job (kind, unique_key) WHERE unique_key IS NOT NULL; - --- --- Create `river_client` and derivative. --- --- This feature hasn't quite yet been implemented, but we're taking advantage of --- the migration to add the schema early so that we can add it later without an --- additional migration. --- - -CREATE UNLOGGED TABLE river_client ( - id text PRIMARY KEY NOT NULL, - created_at timestamptz NOT NULL DEFAULT now(), - metadata jsonb NOT NULL DEFAULT '{}', - paused_at timestamptz, - updated_at timestamptz NOT NULL, - CONSTRAINT name_length CHECK (char_length(id) > 0 AND char_length(id) < 128) -); - --- Differs from `river_queue` in that it tracks the queue state for a particular --- active client. -CREATE UNLOGGED TABLE river_client_queue ( - river_client_id text NOT NULL REFERENCES river_client (id) ON DELETE CASCADE, - name text NOT NULL, - created_at timestamptz NOT NULL DEFAULT now(), - max_workers bigint NOT NULL DEFAULT 0, - metadata jsonb NOT NULL DEFAULT '{}', - num_jobs_completed bigint NOT NULL DEFAULT 0, - num_jobs_running bigint NOT NULL DEFAULT 0, - updated_at timestamptz NOT NULL, - PRIMARY KEY (river_client_id, name), - CONSTRAINT name_length CHECK (char_length(name) > 0 AND char_length(name) < 128), - CONSTRAINT num_jobs_completed_zero_or_positive CHECK (num_jobs_completed >= 0), - CONSTRAINT num_jobs_running_zero_or_positive CHECK (num_jobs_running >= 0) -); - --- Version 6 -CREATE OR REPLACE FUNCTION river_job_state_in_bitmask(bitmask BIT(8), state river_job_state) -RETURNS boolean -LANGUAGE SQL -IMMUTABLE -AS $$ - SELECT CASE state - WHEN 'available' THEN get_bit(bitmask, 7) - WHEN 'cancelled' THEN get_bit(bitmask, 6) - WHEN 'completed' THEN get_bit(bitmask, 5) - WHEN 'discarded' THEN get_bit(bitmask, 4) - WHEN 'pending' THEN get_bit(bitmask, 3) - WHEN 'retryable' THEN get_bit(bitmask, 2) - WHEN 'running' THEN get_bit(bitmask, 1) - WHEN 'scheduled' THEN get_bit(bitmask, 0) - ELSE 0 - END = 1; -$$; - --- --- Add `river_job.unique_states` and bring up an index on it. --- --- This column may exist already if users manually created the column and index --- as instructed in the changelog so the index could be created `CONCURRENTLY`. --- -ALTER TABLE river_job ADD COLUMN IF NOT EXISTS unique_states BIT(8); - --- This statement uses `IF NOT EXISTS` to allow users with a `river_job` table --- of non-trivial size to build the index `CONCURRENTLY` out of band of this --- migration, then follow by completing the migration. -CREATE UNIQUE INDEX IF NOT EXISTS river_job_unique_idx ON river_job (unique_key) - WHERE unique_key IS NOT NULL - AND unique_states IS NOT NULL - AND river_job_state_in_bitmask(unique_states, state); - --- Remove the old unique index. Users who are actively using the unique jobs --- feature and who wish to avoid deploy downtime may want od drop this in a --- subsequent migration once all jobs using the old unique system have been --- completed (i.e. no more rows with non-null unique_key and null --- unique_states). -DROP INDEX river_job_kind_unique_key_idx; - - diff --git a/nix/sql/music/002_schema.sql b/nix/sql/music/002_schema.sql deleted file mode 100644 index 0e41ea3..0000000 --- a/nix/sql/music/002_schema.sql +++ /dev/null @@ -1,166 +0,0 @@ -CREATE TYPE monitor_state AS ENUM ('monitored', 'unmonitored', 'excluded'); - -CREATE TABLE artists ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - external_id VARCHAR(255) NOT NULL UNIQUE, - name VARCHAR(500) NOT NULL, - artist_type VARCHAR(50), - country VARCHAR(10), - genres TEXT[], - image_url TEXT, - monitor_state monitor_state NOT NULL DEFAULT 'unmonitored', - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE TABLE albums ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - external_id VARCHAR(255) NOT NULL UNIQUE, - artist_id UUID NOT NULL REFERENCES artists(id) ON DELETE CASCADE, - title VARCHAR(500) NOT NULL, - album_type VARCHAR(50), - release_date DATE, - total_tracks INT, - total_discs INT DEFAULT 1, - label VARCHAR(255), - genres TEXT[], - cover_url TEXT, - monitor_state monitor_state NOT NULL DEFAULT 'unmonitored', - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_albums_artist ON albums(artist_id); -CREATE INDEX idx_albums_monitored ON albums(monitor_state) WHERE monitor_state = 'monitored'; - -CREATE TABLE tracks ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - external_id VARCHAR(255) NOT NULL UNIQUE, - album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE, - title VARCHAR(500) NOT NULL, - duration_ms INT, - isrc VARCHAR(20), - disc_number INT DEFAULT 1, - track_number INT NOT NULL, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_tracks_album ON tracks(album_id); - -CREATE TABLE torrents ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE, - info_hash VARCHAR(40) NOT NULL UNIQUE, - tracker VARCHAR(100) NOT NULL, - title TEXT NOT NULL, - format VARCHAR(20) NOT NULL, - quality VARCHAR(20), - source VARCHAR(20), - bit_depth INT, - sample_rate INT, - seeders INT DEFAULT 0, - peers INT DEFAULT 0, - size BIGINT, - track_count INT, - has_cover_art BOOLEAN DEFAULT FALSE, - has_cue_sheet BOOLEAN DEFAULT FALSE, - has_rip_log BOOLEAN DEFAULT FALSE, - download_link TEXT, - torrent_file BYTEA, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_torrents_album ON torrents(album_id); -CREATE INDEX idx_torrents_album_format ON torrents(album_id, format); - -CREATE TYPE download_state AS ENUM ( - 'pending', 'downloading', 'completed', 'failed', 'seeding', 'paused' -); - -CREATE TABLE downloads ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - torrent_id UUID NOT NULL REFERENCES torrents(id) ON DELETE CASCADE, - album_id UUID NOT NULL, - format VARCHAR(20) NOT NULL, - quality VARCHAR(20), - state download_state NOT NULL DEFAULT 'pending', - qbit_hash VARCHAR(64), - save_path TEXT, - error_message TEXT, - queued_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - started_at TIMESTAMPTZ, - completed_at TIMESTAMPTZ, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE UNIQUE INDEX idx_unique_active_torrent - ON downloads(torrent_id) - WHERE state NOT IN ('failed'); - -CREATE UNIQUE INDEX idx_unique_owned_album_quality - ON downloads(album_id, format, quality) - WHERE state IN ('completed', 'seeding'); - -CREATE INDEX idx_downloads_state ON downloads(state); -CREATE INDEX idx_downloads_album ON downloads(album_id); - -CREATE TABLE download_files ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - download_id UUID NOT NULL REFERENCES downloads(id) ON DELETE CASCADE, - track_id UUID REFERENCES tracks(id), - file_path TEXT NOT NULL, - file_size BIGINT NOT NULL, - file_type VARCHAR(20) NOT NULL, - sha256_hash VARCHAR(64), - verified_at TIMESTAMPTZ, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_download_files_download ON download_files(download_id); -CREATE INDEX idx_download_files_hash ON download_files(sha256_hash) WHERE sha256_hash IS NOT NULL; - -CREATE TABLE album_releases ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE, - download_id UUID NOT NULL REFERENCES downloads(id) ON DELETE CASCADE, - format VARCHAR(20) NOT NULL, - bit_depth INT, - sample_rate INT, - channels INT DEFAULT 2, - is_lossless BOOLEAN NOT NULL DEFAULT FALSE, - source VARCHAR(20), - total_size BIGINT NOT NULL DEFAULT 0, - total_duration_ms INT NOT NULL DEFAULT 0, - track_count INT NOT NULL DEFAULT 0, - has_cover_art BOOLEAN DEFAULT FALSE, - has_cue_sheet BOOLEAN DEFAULT FALSE, - has_rip_log BOOLEAN DEFAULT FALSE, - path TEXT NOT NULL, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_album_releases_album ON album_releases(album_id); -CREATE UNIQUE INDEX idx_album_releases_download ON album_releases(download_id); - -CREATE TABLE track_releases ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - album_release_id UUID NOT NULL REFERENCES album_releases(id) ON DELETE CASCADE, - track_id UUID REFERENCES tracks(id), - download_file_id UUID REFERENCES download_files(id), - title VARCHAR(500) NOT NULL, - track_number INT NOT NULL DEFAULT 1, - disc_number INT NOT NULL DEFAULT 1, - duration_ms INT, - format VARCHAR(20) NOT NULL, - bit_depth INT, - sample_rate INT, - channels INT DEFAULT 2, - bitrate_kbps INT, - file_size BIGINT NOT NULL DEFAULT 0, - file_path TEXT NOT NULL, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_track_releases_album_release ON track_releases(album_release_id); diff --git a/nix/sql/music/003_event_bus.sql b/nix/sql/music/003_event_bus.sql deleted file mode 100644 index 6e8ec7c..0000000 --- a/nix/sql/music/003_event_bus.sql +++ /dev/null @@ -1,33 +0,0 @@ -CREATE TABLE workflow_runs ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE, - quality VARCHAR(20) NOT NULL, - status VARCHAR(20) NOT NULL DEFAULT 'running', - error_message TEXT, - started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - completed_at TIMESTAMPTZ, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - running_lock BOOLEAN GENERATED ALWAYS AS (CASE WHEN status = 'running' THEN TRUE ELSE NULL END) STORED, - CONSTRAINT idx_workflow_runs_active UNIQUE (album_id, quality, running_lock) -); - -CREATE INDEX idx_workflow_runs_status ON workflow_runs(status); - -CREATE TABLE album_events ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - seq BIGSERIAL NOT NULL, - workflow_run_id UUID NOT NULL REFERENCES workflow_runs(id) ON DELETE CASCADE, - album_id UUID NOT NULL, - event_type VARCHAR(20) NOT NULL, - step VARCHAR(50) NOT NULL, - message TEXT NOT NULL, - data_json JSONB, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_album_events_workflow ON album_events(workflow_run_id); -CREATE INDEX idx_album_events_album ON album_events(album_id); -CREATE INDEX idx_album_events_seq ON album_events(seq); - -ALTER TYPE download_state ADD VALUE IF NOT EXISTS 'cancelled'; diff --git a/nix/vpn.nix b/nix/vpn.nix deleted file mode 100644 index f9e122d..0000000 --- a/nix/vpn.nix +++ /dev/null @@ -1,48 +0,0 @@ -{ - config, - lib, - ... -}: - -let - cfg = config.services.agregators; - vpnCfg = cfg.vpn; -in -{ - options.services.agregators.vpn = { - enable = lib.mkEnableOption "WireGuard VPN via VPN-Confinement for torrent traffic"; - - wgConfigFile = lib.mkOption { - type = lib.types.path; - description = '' - Path to WireGuard configuration file. - Must not be in the Nix store — use a runtime path. - ''; - example = "/run/secrets/wireguard.conf"; - }; - - accessibleFrom = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ - "192.168.1.0/24" - "192.168.0.0/24" - "127.0.0.1" - ]; - description = "CIDRs allowed to reach services inside the VPN namespace."; - }; - - namespace = lib.mkOption { - type = lib.types.str; - default = "wg"; - description = "Name of the VPN network namespace."; - }; - }; - - config = lib.mkIf (cfg.enable && vpnCfg.enable) { - vpnNamespaces.${vpnCfg.namespace} = { - enable = true; - wireguardConfigFile = vpnCfg.wgConfigFile; - accessibleFrom = vpnCfg.accessibleFrom; - }; - }; -} diff --git a/package.nix b/package.nix deleted file mode 100644 index bcb221e..0000000 --- a/package.nix +++ /dev/null @@ -1,26 +0,0 @@ -{ - lib, - buildGoModule, -}: - -buildGoModule { - pname = "music-agregator"; - version = "0.1.0"; - - src = ./.; - - vendorHash = "sha256-LXzaQul2aDJakWF9fX7ZOz2uf3VxO2D54Xn7uH1hps8="; - proxyVendor = true; - - subPackages = [ "cmd/music-agregator" ]; - - ldflags = [ - "-s" - "-w" - ]; - - meta = { - description = "Music automation orchestrator — monitors albums, manages downloads, drives metadata enrichment"; - mainProgram = "music-agregator"; - }; -} diff --git a/proto/hello.proto b/proto/hello.proto new file mode 100644 index 0000000..2bb7a10 --- /dev/null +++ b/proto/hello.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; +package hello; + +service Greeter { + // Our SayHello rpc accepts HelloRequests and returns HelloReplies + rpc SayHello (HelloRequest) returns (HelloReply); +} +message HelloRequest { + // Request message contains the name to be greeted + string name = 1; +} + +message HelloReply { + // Reply contains the greeting message + string message = 1; +} diff --git a/proto/music_agregator/hello/v1/service.proto b/proto/music_agregator/hello/v1/service.proto deleted file mode 100644 index 78b3eae..0000000 --- a/proto/music_agregator/hello/v1/service.proto +++ /dev/null @@ -1,22 +0,0 @@ -syntax = "proto3"; -package music_agregator.hello.v1; -option go_package = "homelab.lan/music-agregator/gen/music_agregator/v1/hello"; - -service HelloService { - rpc Ping(PingRequest) returns (PongResponse) {} - rpc Echo(EchoRequest) returns (EchoResponse) {} -} - -message PingRequest { - -} -message PongResponse { -} - -message EchoRequest { - string msg = 1; -} - -message EchoResponse { - string response = 1; -} diff --git a/proto/music_agregator/indexer/v1/indexer.proto b/proto/music_agregator/indexer/v1/indexer.proto deleted file mode 100644 index 544f5a3..0000000 --- a/proto/music_agregator/indexer/v1/indexer.proto +++ /dev/null @@ -1,109 +0,0 @@ -syntax = "proto3"; -package music_agregator.indexer.v1; -option go_package = "homelab.lan/music-agregator/gen/music_agregator/v1/indexer"; - -service IndexerService { - rpc Search(SearchRequest) returns (SearchResponse) {} - rpc Capabilities(CapabilitiesRequest) returns (CapabilitiesResponse) {} -} - -message SearchRequest { - string query = 1; - int32 limit = 2; - string tracker = 3; -} -message SearchResponse { - repeated SearchItem result = 1; -} - -message SearchItem { - string title = 1; - string download_link = 2; - string torrent_page_url = 3; - string pub_date = 4; - int64 size = 5; - string description = 6; - repeated string categories = 7; - Enclosure enclosure = 8; - repeated TorznabAttr torznab_attrs = 9; - Release release = 10; -} - -message Release { - string raw_title = 1; - string artist = 2; - string album = 3; - int32 year = 4; - int32 year_end = 5; - string type = 6; - repeated string genres = 7; - string format = 8; - string source = 9; - string bitrate = 10; - int32 bit_depth = 11; - int32 sample_rate = 12; - string rip_type = 13; - int32 release_count = 14; - repeated string tags = 15; - string label = 16; - string catalog_num = 17; - bool parsed_successfully = 18; - repeated string parse_errors = 19; -} - -message Enclosure { - string url = 1; - int64 length = 2; - string type = 3; -} - -message TorznabAttr { - string name = 1; - string value = 2; -} - -message CapabilitiesRequest { - string indexer = 1; -} - -message CapabilitiesResponse { - Server server = 1; - Limits limits = 2; - Searching searching = 3; - repeated Category categories = 4; -} - -message Server { - string title = 1; -} - -message Limits { - int32 default = 1; - int32 max = 2; -} - -message Searching { - SearchCapability search = 1; - SearchCapability tv_search = 2; - SearchCapability movie_search = 3; - SearchCapability music_search = 4; - SearchCapability audio_search = 5; - SearchCapability book_search = 6; -} - -message SearchCapability { - bool available = 1; - repeated string supported_params = 2; - string search_engine = 3; -} - -message Category { - int32 id = 1; - string name = 2; - repeated Subcat subcats = 3; -} - -message Subcat { - int32 id = 1; - string name = 2; -} diff --git a/proto/music_agregator/torrent/v1/torrent.proto b/proto/music_agregator/torrent/v1/torrent.proto deleted file mode 100644 index 7a34b42..0000000 --- a/proto/music_agregator/torrent/v1/torrent.proto +++ /dev/null @@ -1,72 +0,0 @@ -syntax = "proto3"; -package music_agregator.torrent.v1; -option go_package = "homelab.lan/music-agregator/gen/music_agregator/v1/torrent"; - -service TorrentService { - rpc List(ListRequest) returns (ListResponse) {} - rpc Add(AddRequest) returns (AddResponse) {} -} - -message ListRequest { - string client_name = 1; - string filter = 2; - string category = 3; - string tag = 4; - string sort = 5; - bool reverse = 6; - int32 limit = 7; - int32 offset = 8; -} - -message ListResponse { - repeated ListItem items = 1; -} - -message ListItem { - string hash = 1; - string name = 2; - int64 size = 3; - double progress = 4; - int64 dlspeed = 5; - int64 upspeed = 6; - int32 num_seeds = 7; - int32 num_leechs = 8; - string state = 9; - int64 eta = 10; - double ratio = 11; - string category = 12; - string tags = 13; - int64 added_on = 14; - int64 completion_on = 15; - string save_path = 16; - string content_path = 17; - int64 downloaded = 18; - int64 uploaded = 19; - string tracker = 20; - int64 seeding_time = 21; - int64 amount_left = 22; - double availability = 23; - - string size_formatted = 100; - string progress_formatted = 101; - string dlspeed_formatted = 102; - string upspeed_formatted = 103; - string added_on_formatted = 104; - string completion_on_formatted = 105; - string downloaded_formatted = 106; - string uploaded_formatted = 107; - string amount_left_formatted = 108; - string availability_formatted = 109; - string eta_formatted = 110; -} - -message AddRequest { - string download_url = 1; - string filename = 2; - bytes torrent_data = 3; - string save_path = 4; -} - -message AddResponse { - ListItem item = 1; -} diff --git a/proto/music_agregator/v1/music_agregator.proto b/proto/music_agregator/v1/music_agregator.proto deleted file mode 100644 index 598f114..0000000 --- a/proto/music_agregator/v1/music_agregator.proto +++ /dev/null @@ -1,410 +0,0 @@ -syntax = "proto3"; -package music_agregator.v1; -option go_package = "homelab.lan/music-agregator/gen/music_agregator/v1/"; - -service MusicAgregatorService { - rpc MonitorAlbum(MonitorAlbumRequest) returns (MonitorAlbumResponse) { - option deprecated = true; - } - rpc MonitorAlbumStream(stream MonitorAlbumStreamRequest) returns (stream MonitorAlbumStreamResponse) {} - rpc GetArtists(GetArtistsRequest) returns (GetArtistsResponse) {} - rpc GetAlbum(GetAlbumRequest) returns (GetAlbumResponse) {} - rpc AnalyzeAlbumRelease(AnalyzeAlbumReleaseRequest) returns (AnalyzeAlbumReleaseResponse) {} - rpc SearchArtists(SearchArtistsRequest) returns (SearchArtistsResponse) {} - rpc GetArtistAlbums(GetArtistAlbumsRequest) returns (GetArtistAlbumsResponse) {} - rpc SubscribeEvents(SubscribeEventsRequest) returns (stream AlbumEvent) {} - rpc ResyncAlbum(ResyncAlbumRequest) returns (ResyncAlbumResponse) {} -} - -message ResyncAlbumRequest { - string album_id = 1; -} - -message ResyncAlbumResponse { - int32 files_synced = 1; - int32 files_enriched = 2; - uint64 bytes_synced = 3; -} - -message MonitorAlbumRequest { - string album_id = 1; - IndexerOptions indexer_options = 2; - QualityType quality = 3; -} - -message IndexerOptions { - string tracker = 1; -} - -enum QualityType { - QUALITY_UNSPECIFIED = 0; - QUALITY_LOSSLESS = 1; - QUALITY_LOSSY = 2; -} - -message MonitorAlbumResponse { - AlbumDetail album = 1; - ArtistSummary artist = 2; - MonitoredRelease release = 3; -} - -message GetArtistsRequest {} - -message GetArtistsResponse { - repeated ArtistSummary artists = 1; -} - -enum MonitorState { - MONITOR_STATE_UNSPECIFIED = 0; - MONITOR_STATE_MONITORED = 1; - MONITOR_STATE_UNMONITORED = 2; - MONITOR_STATE_EXCLUDED = 3; -} - -message ArtistSummary { - string id = 1; - string external_id = 2; - string name = 3; - string artist_type = 4; - string country = 5; - repeated string genres = 6; - string image_url = 7; - MonitorState monitor_state = 8; - repeated AlbumDetail albums = 9; -} - -message AlbumDetail { - string id = 1; - string external_id = 2; - string title = 3; - string album_type = 4; - string release_date = 5; - int32 total_tracks = 6; - int32 total_discs = 7; - string cover_url = 8; - repeated string genres = 9; - string label = 10; - MonitorState monitor_state = 11; - repeated DownloadInfo downloads = 12; - AlbumReleaseDetail release = 13; -} - -message DownloadInfo { - string state = 1; - string format = 2; - string quality = 3; - string save_path = 4; -} - -message GetAlbumRequest { - string album_id = 1; -} - -message AlbumInfo { - AlbumDetail album = 1; - repeated TrackDetail tracks = 2; -} - -message GetAlbumResponse { - AlbumInfo info = 1; -} - -message AnalyzeAlbumReleaseRequest { - string album_id = 1; -} - -message AnalyzeAlbumReleaseResponse { - AlbumInfo info = 1; -} - -message TrackDetail { - string id = 1; - string external_id = 2; - string title = 3; - int32 duration_ms = 4; - int32 disc_number = 5; - int32 track_number = 6; - string isrc = 7; - bool explicit = 8; - repeated ArtistCredit artists = 9; - string file_path = 10; - int64 file_size = 11; - string format = 12; - int32 bit_depth = 13; - int32 sample_rate = 14; - int32 channels = 15; - int32 bitrate_kbps = 16; -} - -message ArtistCredit { - string id = 1; - string name = 2; -} - -message AlbumReleaseDetail { - string id = 1; - string format = 2; - int32 bit_depth = 3; - int32 sample_rate = 4; - int32 channels = 5; - bool is_lossless = 6; - string source = 7; - int64 total_size = 8; - int32 total_duration_ms = 9; - int32 track_count = 10; - bool has_cover_art = 11; - bool has_cue_sheet = 12; - bool has_rip_log = 13; - string path = 14; -} - -message MonitoredRelease { - string info_hash = 1; - string artist = 2; - string album = 3; - int32 year = 4; - string format = 5; - bool lossless = 6; - int32 bit_depth = 7; - int32 sample_rate = 8; - string source = 9; - int32 track_count = 10; - repeated string track_names = 11; - bool has_cover_art = 12; - bool has_cue_sheet = 13; - bool has_rip_log = 14; - int64 total_audio_size = 15; - string download_link = 16; - int32 seeders = 17; - string tracker = 18; -} - -message SearchArtistsRequest { - string query = 1; - int32 limit = 2; - int32 offset = 3; -} - -message SearchArtistsResponse { - repeated SearchArtistResult artists = 1; - int32 total = 2; -} - -message SearchArtistResult { - string id = 1; - string name = 2; - string sort_name = 3; - string artist_type = 4; - string country = 5; - string formed_date = 6; - string disbanded_date = 7; - string description = 8; - string image_url = 9; - repeated string genres = 10; - repeated ExternalId external_ids = 11; -} - -message ExternalId { - string provider = 1; - string id = 2; -} - -message GetArtistAlbumsRequest { - string artist_id = 1; - int32 limit = 2; - int32 offset = 3; -} - -message GetArtistAlbumsResponse { - repeated AlbumResult albums = 1; - int32 total = 2; -} - -message AlbumResult { - string id = 1; - string title = 2; - string album_type = 3; - string release_date = 4; - string upc = 5; - int32 total_tracks = 6; - int32 total_discs = 7; - string cover_url = 8; - repeated AlbumArtistCredit artists = 9; - AlbumLabel label = 10; - repeated string genres = 11; - repeated ExternalId external_ids = 12; -} - -message AlbumArtistCredit { - string id = 1; - string name = 2; - string role = 3; -} - -message AlbumLabel { - string id = 1; - string name = 2; - string country = 3; -} - -message SubscribeEventsRequest { - int64 since_seq = 1; -} - -message AlbumEvent { - int64 seq = 1; - string workflow_run_id = 2; - string album_id = 3; - string quality = 4; - string event_type = 5; - string step = 6; - string message = 7; - bytes data_json = 8; - int64 timestamp_ms = 9; -} - -enum InteractionMode { - INTERACTION_MODE_AUTOMATIC = 0; - INTERACTION_MODE_MANUAL = 1; -} - -enum MonitorStep { - MONITOR_STEP_UNSPECIFIED = 0; - MONITOR_STEP_FETCHING_METADATA = 1; - MONITOR_STEP_CHECKING_OWNED = 2; - MONITOR_STEP_SEARCHING_INDEXER = 3; - MONITOR_STEP_PARSING_RESULTS = 4; - MONITOR_STEP_FILTERING_QUALITY = 5; - MONITOR_STEP_SELECTING_RELEASE = 6; - MONITOR_STEP_ADDING_TORRENT = 7; - MONITOR_STEP_SAVING = 8; - MONITOR_STEP_COMPLETE = 9; -} - -enum PromptType { - PROMPT_TYPE_UNSPECIFIED = 0; - PROMPT_TYPE_CONFIRM = 1; - PROMPT_TYPE_SELECT_ONE = 2; - PROMPT_TYPE_SELECT_MANY = 3; -} - -message MonitorAlbumStreamRequest { - oneof message { - StartMonitorRequest start = 1; - UserDecision decision = 2; - CancelRequest cancel = 3; - } -} - -message StartMonitorRequest { - string album_id = 1; - IndexerOptions indexer_options = 2; - QualityType quality = 3; - InteractionMode mode = 4; -} - -message UserDecision { - string prompt_id = 1; - oneof decision { - bool confirm = 2; - string selected_id = 3; - SelectedIds selected_ids = 4; - } -} - -message SelectedIds { - repeated string ids = 1; -} - -message CancelRequest {} - -message MonitorAlbumStreamResponse { - oneof message { - StatusUpdate status = 1; - PromptForDecision prompt = 2; - MonitorAlbumResponse result = 3; - ErrorUpdate error = 4; - } -} - -message StatusUpdate { - MonitorStep step = 1; - string message = 2; - oneof data { - StreamAlbumInfo album_info = 10; - TorrentList torrents = 11; - ReleaseInfo release_info = 12; - } -} - -message PromptForDecision { - string prompt_id = 1; - PromptType type = 2; - string message = 3; - int32 timeout_seconds = 4; - oneof options { - ConfirmPrompt confirm = 10; - SelectOnePrompt select_one = 11; - SelectManyPrompt select_many = 12; - } -} - -message ErrorUpdate { - MonitorStep failed_step = 1; - string message = 2; - bool recoverable = 3; -} - -message StreamAlbumInfo { - string artist = 1; - string title = 2; - string release_date = 3; - bool already_owned = 4; - string owned_quality = 5; -} - -message TorrentList { - repeated TorrentSummary torrents = 1; -} - -message TorrentSummary { - string id = 1; - string title = 2; - string tracker = 3; - int32 seeders = 4; - string format = 5; - bool lossless = 6; -} - -message ReleaseInfo { - string info_hash = 1; - string format = 2; - int32 bit_depth = 3; - int32 sample_rate = 4; - int32 seeders = 5; - string tracker = 6; -} - -message ConfirmPrompt { - string confirm_label = 1; - string cancel_label = 2; - bool default_value = 3; -} - -message SelectOnePrompt { - repeated SelectOption options = 1; - string default_id = 2; -} - -message SelectManyPrompt { - repeated SelectOption options = 1; - repeated string default_ids = 2; - int32 min_selections = 3; - int32 max_selections = 4; -} - -message SelectOption { - string id = 1; - string label = 2; - string description = 3; -} diff --git a/src/generated/hello/hello.rs b/src/generated/hello/hello.rs new file mode 100644 index 0000000..2944543 --- /dev/null +++ b/src/generated/hello/hello.rs @@ -0,0 +1,78 @@ +// @generated +// This file is @generated by prost-build. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct HelloRequest { + /// Request message contains the name to be greeted + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, +} +impl ::prost::Name for HelloRequest { + const NAME: &'static str = "HelloRequest"; + const PACKAGE: &'static str = "hello"; + fn full_name() -> ::prost::alloc::string::String { + "hello.HelloRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/hello.HelloRequest".into() + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct HelloReply { + /// Reply contains the greeting message + #[prost(string, tag = "1")] + pub message: ::prost::alloc::string::String, +} +impl ::prost::Name for HelloReply { + const NAME: &'static str = "HelloReply"; + const PACKAGE: &'static str = "hello"; + fn full_name() -> ::prost::alloc::string::String { + "hello.HelloReply".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/hello.HelloReply".into() + } +} +/// Encoded file descriptor set for the `hello` package +pub const FILE_DESCRIPTOR_SET: &[u8] = &[ + 0x0a, 0xd0, 0x04, 0x0a, 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x22, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x48, + 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x32, 0x3d, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x12, 0x32, + 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x13, 0x2e, 0x68, 0x65, 0x6c, + 0x6c, 0x6f, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x11, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x4a, 0xa6, 0x03, 0x0a, 0x06, 0x12, 0x04, 0x00, 0x00, 0x0f, 0x01, 0x0a, 0x08, 0x0a, + 0x01, 0x0c, 0x12, 0x03, 0x00, 0x00, 0x12, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x01, 0x00, + 0x0e, 0x0a, 0x0a, 0x0a, 0x02, 0x06, 0x00, 0x12, 0x04, 0x03, 0x00, 0x06, 0x01, 0x0a, 0x0a, 0x0a, + 0x03, 0x06, 0x00, 0x01, 0x12, 0x03, 0x03, 0x08, 0x0f, 0x0a, 0x4e, 0x0a, 0x04, 0x06, 0x00, 0x02, + 0x00, 0x12, 0x03, 0x05, 0x04, 0x35, 0x1a, 0x41, 0x20, 0x4f, 0x75, 0x72, 0x20, 0x53, 0x61, 0x79, + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x72, 0x70, 0x63, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, + 0x73, 0x20, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x48, 0x65, 0x6c, 0x6c, + 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x05, 0x08, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x02, + 0x12, 0x03, 0x05, 0x12, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x05, 0x29, 0x33, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x07, 0x00, 0x0a, 0x01, 0x0a, + 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x07, 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x09, 0x04, 0x0a, 0x0a, 0x3e, 0x0a, 0x04, 0x04, 0x00, 0x02, + 0x00, 0x12, 0x03, 0x09, 0x04, 0x14, 0x1a, 0x31, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, + 0x20, 0x67, 0x72, 0x65, 0x65, 0x74, 0x65, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x09, 0x0b, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, + 0x12, 0x03, 0x09, 0x12, 0x13, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x0c, 0x00, 0x0f, + 0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x0c, 0x08, 0x12, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x0e, 0x04, 0x0a, 0x0a, 0x32, 0x0a, 0x04, 0x04, + 0x01, 0x02, 0x00, 0x12, 0x03, 0x0e, 0x04, 0x17, 0x1a, 0x25, 0x20, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, + 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0e, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0e, 0x15, 0x16, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +]; +include!("hello.serde.rs"); +include!("hello.tonic.rs"); +// @@protoc_insertion_point(module) diff --git a/src/generated/hello/hello.serde.rs b/src/generated/hello/hello.serde.rs new file mode 100644 index 0000000..cd18fc8 --- /dev/null +++ b/src/generated/hello/hello.serde.rs @@ -0,0 +1,185 @@ +// @generated +impl serde::Serialize for HelloReply { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.message.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("hello.HelloReply", len)?; + if !self.message.is_empty() { + struct_ser.serialize_field("message", &self.message)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for HelloReply { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &["message"]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Message, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting( + &self, + formatter: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "message" => Ok(GeneratedField::Message), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = HelloReply; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct hello.HelloReply") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut message__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Message => { + if message__.is_some() { + return Err(serde::de::Error::duplicate_field("message")); + } + message__ = Some(map_.next_value()?); + } + } + } + Ok(HelloReply { + message: message__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("hello.HelloReply", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for HelloRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.name.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("hello.HelloRequest", len)?; + if !self.name.is_empty() { + struct_ser.serialize_field("name", &self.name)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for HelloRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &["name"]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Name, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting( + &self, + formatter: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "name" => Ok(GeneratedField::Name), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = HelloRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct hello.HelloRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut name__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Name => { + if name__.is_some() { + return Err(serde::de::Error::duplicate_field("name")); + } + name__ = Some(map_.next_value()?); + } + } + } + Ok(HelloRequest { + name: name__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("hello.HelloRequest", FIELDS, GeneratedVisitor) + } +} diff --git a/src/generated/hello/hello.tonic.rs b/src/generated/hello/hello.tonic.rs new file mode 100644 index 0000000..a97d739 --- /dev/null +++ b/src/generated/hello/hello.tonic.rs @@ -0,0 +1,270 @@ +// @generated +/// Generated client implementations. +pub mod greeter_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value + )] + use tonic::codegen::http::Uri; + use tonic::codegen::*; + #[derive(Debug, Clone)] + pub struct GreeterClient { + inner: tonic::client::Grpc, + } + impl GreeterClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl GreeterClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> GreeterClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + >>::Error: + Into + std::marker::Send + std::marker::Sync, + { + GreeterClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn say_hello( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static("/hello.Greeter/SayHello"); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("hello.Greeter", "SayHello")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod greeter_server { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value + )] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with GreeterServer. + #[async_trait] + pub trait Greeter: std::marker::Send + std::marker::Sync + 'static { + async fn say_hello( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + } + #[derive(Debug)] + pub struct GreeterServer { + inner: Arc, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + impl GreeterServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor(inner: T, interceptor: F) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for GreeterServer + where + T: Greeter, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + match req.uri().path() { + "/hello.Greeter/SayHello" => { + #[allow(non_camel_case_types)] + struct SayHelloSvc(pub Arc); + impl tonic::server::UnaryService for SayHelloSvc { + type Response = super::HelloReply; + type Future = BoxFuture, tonic::Status>; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = + async move { ::say_hello(&inner, request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = SayHelloSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => Box::pin(async move { + let mut response = http::Response::new(tonic::body::Body::default()); + let headers = response.headers_mut(); + headers.insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers.insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }), + } + } + } + impl Clone for GreeterServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "hello.Greeter"; + impl tonic::server::NamedService for GreeterServer { + const NAME: &'static str = SERVICE_NAME; + } +} diff --git a/src/generated/metadata/v1/metadata.v1.rs b/src/generated/metadata/v1/metadata.v1.rs new file mode 100644 index 0000000..a82105b --- /dev/null +++ b/src/generated/metadata/v1/metadata.v1.rs @@ -0,0 +1,1282 @@ +// @generated +// This file is @generated by prost-build. +// Requests + +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetArtistRequest { + #[prost(enumeration = "Provider", tag = "3")] + pub provider: i32, + #[prost(oneof = "get_artist_request::Identifier", tags = "1, 2")] + pub identifier: ::core::option::Option, +} +/// Nested message and enum types in `GetArtistRequest`. +pub mod get_artist_request { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Identifier { + #[prost(string, tag = "1")] + Id(::prost::alloc::string::String), + #[prost(message, tag = "2")] + External(super::ExternalId), + } +} +impl ::prost::Name for GetArtistRequest { + const NAME: &'static str = "GetArtistRequest"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetArtistRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetArtistRequest".into() + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SearchArtistsRequest { + #[prost(string, tag = "1")] + pub query: ::prost::alloc::string::String, + #[prost(int32, tag = "2")] + pub limit: i32, + #[prost(int32, tag = "3")] + pub offset: i32, + #[prost(enumeration = "Provider", tag = "4")] + pub provider: i32, +} +impl ::prost::Name for SearchArtistsRequest { + const NAME: &'static str = "SearchArtistsRequest"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.SearchArtistsRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.SearchArtistsRequest".into() + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetAlbumRequest { + #[prost(enumeration = "Provider", tag = "3")] + pub provider: i32, + #[prost(oneof = "get_album_request::Identifier", tags = "1, 2")] + pub identifier: ::core::option::Option, +} +/// Nested message and enum types in `GetAlbumRequest`. +pub mod get_album_request { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Identifier { + #[prost(string, tag = "1")] + Id(::prost::alloc::string::String), + #[prost(message, tag = "2")] + External(super::ExternalId), + } +} +impl ::prost::Name for GetAlbumRequest { + const NAME: &'static str = "GetAlbumRequest"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetAlbumRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetAlbumRequest".into() + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetArtistAlbumsRequest { + #[prost(string, tag = "1")] + pub artist_id: ::prost::alloc::string::String, + #[prost(int32, tag = "2")] + pub limit: i32, + #[prost(int32, tag = "3")] + pub offset: i32, + #[prost(enumeration = "Provider", tag = "4")] + pub provider: i32, + #[prost(string, repeated, tag = "5")] + pub album_types: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +impl ::prost::Name for GetArtistAlbumsRequest { + const NAME: &'static str = "GetArtistAlbumsRequest"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetArtistAlbumsRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetArtistAlbumsRequest".into() + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetTrackRequest { + #[prost(enumeration = "Provider", tag = "4")] + pub provider: i32, + #[prost(oneof = "get_track_request::Identifier", tags = "1, 2, 3")] + pub identifier: ::core::option::Option, +} +/// Nested message and enum types in `GetTrackRequest`. +pub mod get_track_request { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Identifier { + #[prost(string, tag = "1")] + Id(::prost::alloc::string::String), + #[prost(message, tag = "2")] + External(super::ExternalId), + #[prost(string, tag = "3")] + Isrc(::prost::alloc::string::String), + } +} +impl ::prost::Name for GetTrackRequest { + const NAME: &'static str = "GetTrackRequest"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetTrackRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetTrackRequest".into() + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetAlbumTracksRequest { + #[prost(string, tag = "1")] + pub album_id: ::prost::alloc::string::String, + #[prost(enumeration = "Provider", tag = "2")] + pub provider: i32, +} +impl ::prost::Name for GetAlbumTracksRequest { + const NAME: &'static str = "GetAlbumTracksRequest"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetAlbumTracksRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetAlbumTracksRequest".into() + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SearchAlbumsRequest { + #[prost(string, tag = "1")] + pub query: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub artist: ::prost::alloc::string::String, + #[prost(int32, tag = "3")] + pub limit: i32, + #[prost(int32, tag = "4")] + pub offset: i32, + #[prost(enumeration = "Provider", tag = "5")] + pub provider: i32, + #[prost(string, repeated, tag = "6")] + pub album_types: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +impl ::prost::Name for SearchAlbumsRequest { + const NAME: &'static str = "SearchAlbumsRequest"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.SearchAlbumsRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.SearchAlbumsRequest".into() + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SyncArtistRequest { + #[prost(enumeration = "Provider", tag = "3")] + pub provider: i32, + #[prost(oneof = "sync_artist_request::Target", tags = "1, 2")] + pub target: ::core::option::Option, +} +/// Nested message and enum types in `SyncArtistRequest`. +pub mod sync_artist_request { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Target { + #[prost(string, tag = "1")] + Name(::prost::alloc::string::String), + #[prost(message, tag = "2")] + External(super::ExternalId), + } +} +impl ::prost::Name for SyncArtistRequest { + const NAME: &'static str = "SyncArtistRequest"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.SyncArtistRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.SyncArtistRequest".into() + } +} +// Responses + +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetArtistResponse { + #[prost(message, optional, tag = "1")] + pub artist: ::core::option::Option, +} +impl ::prost::Name for GetArtistResponse { + const NAME: &'static str = "GetArtistResponse"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetArtistResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetArtistResponse".into() + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SearchArtistsResponse { + #[prost(message, repeated, tag = "1")] + pub artists: ::prost::alloc::vec::Vec, + #[prost(int32, tag = "2")] + pub total: i32, +} +impl ::prost::Name for SearchArtistsResponse { + const NAME: &'static str = "SearchArtistsResponse"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.SearchArtistsResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.SearchArtistsResponse".into() + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAlbumResponse { + #[prost(message, optional, tag = "1")] + pub album: ::core::option::Option, +} +impl ::prost::Name for GetAlbumResponse { + const NAME: &'static str = "GetAlbumResponse"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetAlbumResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetAlbumResponse".into() + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetArtistAlbumsResponse { + #[prost(message, repeated, tag = "1")] + pub albums: ::prost::alloc::vec::Vec, + #[prost(int32, tag = "2")] + pub total: i32, +} +impl ::prost::Name for GetArtistAlbumsResponse { + const NAME: &'static str = "GetArtistAlbumsResponse"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetArtistAlbumsResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetArtistAlbumsResponse".into() + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTrackResponse { + #[prost(message, optional, tag = "1")] + pub track: ::core::option::Option, +} +impl ::prost::Name for GetTrackResponse { + const NAME: &'static str = "GetTrackResponse"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetTrackResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetTrackResponse".into() + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAlbumTracksResponse { + #[prost(message, repeated, tag = "1")] + pub tracks: ::prost::alloc::vec::Vec, +} +impl ::prost::Name for GetAlbumTracksResponse { + const NAME: &'static str = "GetAlbumTracksResponse"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.GetAlbumTracksResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.GetAlbumTracksResponse".into() + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SearchAlbumsResponse { + #[prost(message, repeated, tag = "1")] + pub albums: ::prost::alloc::vec::Vec, + #[prost(int32, tag = "2")] + pub total: i32, +} +impl ::prost::Name for SearchAlbumsResponse { + const NAME: &'static str = "SearchAlbumsResponse"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.SearchAlbumsResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.SearchAlbumsResponse".into() + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SyncArtistResponse { + #[prost(message, optional, tag = "1")] + pub artist: ::core::option::Option, + #[prost(int32, tag = "2")] + pub albums_synced: i32, + #[prost(int32, tag = "3")] + pub tracks_synced: i32, +} +impl ::prost::Name for SyncArtistResponse { + const NAME: &'static str = "SyncArtistResponse"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.SyncArtistResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.SyncArtistResponse".into() + } +} +// Core Entities + +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Artist { + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub sort_name: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub artist_type: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub country: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub formed_date: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub disbanded_date: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub description: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub image_url: ::prost::alloc::string::String, + #[prost(message, repeated, tag = "10")] + pub genres: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "11")] + pub external_ids: ::prost::alloc::vec::Vec, +} +impl ::prost::Name for Artist { + const NAME: &'static str = "Artist"; + const PACKAGE: &'static str = "metadata.v1"; + fn full_name() -> ::prost::alloc::string::String { + "metadata.v1.Artist".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/metadata.v1.Artist".into() + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Album { + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub title: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub album_type: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub release_date: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub upc: ::prost::alloc::string::String, + #[prost(int32, tag = "6")] + pub total_tracks: i32, + #[prost(int32, tag = "7")] + pub total_discs: i32, + #[prost(string, tag = "8")] + pub cover_url: ::prost::alloc::string::String, + #[prost(message, repeated, tag = "9")] + pub artists: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "10")] + pub label: ::core::option::Option