emby-cli 0.1.1__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. emby_cli-0.2.2/CHANGELOG.md +22 -0
  2. {emby_cli-0.1.1 → emby_cli-0.2.2}/PKG-INFO +10 -1
  3. {emby_cli-0.1.1 → emby_cli-0.2.2}/README.md +9 -0
  4. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/_version.py +2 -2
  5. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/cli.py +39 -6
  6. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/client.py +345 -73
  7. emby_cli-0.2.2/src/emby_cli/commands/batch.py +158 -0
  8. emby_cli-0.2.2/src/emby_cli/commands/download.py +71 -0
  9. emby_cli-0.2.2/src/emby_cli/commands/info.py +125 -0
  10. emby_cli-0.2.2/src/emby_cli/commands/list.py +50 -0
  11. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/commands/play.py +5 -4
  12. emby_cli-0.2.2/src/emby_cli/commands/search.py +30 -0
  13. emby_cli-0.2.2/src/emby_cli/commands/sync.py +46 -0
  14. emby_cli-0.2.2/src/emby_cli/commands/version.py +35 -0
  15. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/constants.py +5 -0
  16. emby_cli-0.2.2/src/emby_cli/download_ops.py +136 -0
  17. emby_cli-0.2.2/src/emby_cli/output.py +79 -0
  18. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/resolve.py +111 -33
  19. emby_cli-0.2.2/tests/test_client.py +102 -0
  20. emby_cli-0.2.2/tests/test_info.py +105 -0
  21. emby_cli-0.2.2/tests/test_output.py +19 -0
  22. emby_cli-0.2.2/tests/test_parser.py +80 -0
  23. emby_cli-0.2.2/tests/test_resolve_table.py +42 -0
  24. emby_cli-0.2.2/tests/test_version.py +127 -0
  25. emby_cli-0.1.1/CHANGELOG.md +0 -5
  26. emby_cli-0.1.1/src/emby_cli/commands/batch.py +0 -244
  27. emby_cli-0.1.1/src/emby_cli/commands/download.py +0 -77
  28. emby_cli-0.1.1/src/emby_cli/commands/list.py +0 -35
  29. emby_cli-0.1.1/src/emby_cli/commands/search.py +0 -31
  30. emby_cli-0.1.1/src/emby_cli/commands/sync.py +0 -54
  31. emby_cli-0.1.1/src/emby_cli/download_ops.py +0 -47
  32. emby_cli-0.1.1/tests/test_parser.py +0 -32
  33. {emby_cli-0.1.1 → emby_cli-0.2.2}/.env.example +0 -0
  34. {emby_cli-0.1.1 → emby_cli-0.2.2}/.github/workflows/ci.yml +0 -0
  35. {emby_cli-0.1.1 → emby_cli-0.2.2}/.github/workflows/publish.yml +0 -0
  36. {emby_cli-0.1.1 → emby_cli-0.2.2}/.gitignore +0 -0
  37. {emby_cli-0.1.1 → emby_cli-0.2.2}/LICENSE +0 -0
  38. {emby_cli-0.1.1 → emby_cli-0.2.2}/pyproject.toml +0 -0
  39. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/__init__.py +0 -0
  40. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/__main__.py +0 -0
  41. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/commands/__init__.py +0 -0
  42. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/util.py +0 -0
  43. {emby_cli-0.1.1 → emby_cli-0.2.2}/src/emby_cli/version.py +0 -0
  44. {emby_cli-0.1.1 → emby_cli-0.2.2}/tests/test_resolve.py +0 -0
  45. {emby_cli-0.1.1 → emby_cli-0.2.2}/tests/test_util.py +0 -0
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ## 0.2.2
6
+
7
+ - `version`: show emby-cli version; with valid server credentials also show Emby `/System/Info` version.
8
+ - `info`: session summary (user, url, server, version, os, id) plus library names and item counts from `GET /Items/Counts` (replaces draft `whoami`).
9
+ - `--pick-best-item` is a flag (presence enables auto-select); no longer takes `0`/`1`.
10
+ - `info` / `version` probe the server once (no retries); on failure show configured user/URL and mark server name/version as not validated.
11
+ - Note: `/Items/Counts` may count multiple versions of the same title higher than UI “items” views.
12
+ - `probe_session`: fall back to `/System/Info/Public` when full `/System/Info` is forbidden (non-admin users); still proceed with Views/Counts.
13
+ - Avoid broken `/Users/Me` on some Emby servers (HTTP 500 Guid format): use `User` from authenticate or `/Users/{id}`.
14
+ - `list`: library table is ID/Name/Type/Items (no Year/Res); gather all counts before printing; `list -l` keeps media table like `search`.
15
+
16
+ ## 0.2.0
17
+
18
+ - API fixes: `get_item_info` Fields, `/Users/Me`, safer 416 resume, `api_key` on play URLs, client version from package, `/emby` base URL normalize, HLS without invalid `copy` codecs, paginated episodes.
19
+ - Shared resolve for `play`/`batch` (strict by default; `--pick-best-item` flag).
20
+ - Homogeneous CLI messages (`output.py`); shared library/download loops; non-zero exit on errors / batch not-found.
21
+ - `search`: paginate Emby results (was capped at 25); `--count` / `-n` to limit how many to return (default: all).
22
+ - More tests (`test_client`, `test_output`, parser coverage).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: emby-cli
3
- Version: 0.1.1
3
+ Version: 0.2.2
4
4
  Summary: CLI to list, search, play, and download/backup original media from an Emby server via its REST API.
5
5
  Project-URL: Homepage, https://github.com/soukron/emby-cli
6
6
  Project-URL: Repository, https://github.com/soukron/emby-cli
@@ -70,14 +70,23 @@ See `.env.example`. The app does not load `.env` itself — `source` it or expor
70
70
  ## Usage
71
71
 
72
72
  ```bash
73
+ emby-cli version
74
+ emby-cli info
73
75
  emby-cli list
74
76
  emby-cli search "Title"
77
+ emby-cli search "Title" --count 50
75
78
  emby-cli download -i <itemId> -o ./downloads
76
79
  emby-cli sync -l "Movies"
77
80
  emby-cli batch -F titles.txt -n
81
+ emby-cli batch -F titles.txt --pick-best-item
78
82
  emby-cli play "Movie (2010)"
83
+ emby-cli play "Show S01E01" --pick-best-item
79
84
  ```
80
85
 
86
+ `info` reports libraries and totals from `GET /Items/Counts` (totals may include multiple versions of the same title).
87
+
88
+ Title resolution (`play` / `batch`) is **strict** by default (year mismatch or multiple matches fail that line). Pass `--pick-best-item` to auto-select the best ≤1080p version. In `batch`, a season line like `Show S01` downloads the whole season (with the same pick-best rule per episode version).
89
+
81
90
  Download methods (`-m` / `EMBY_METHOD`):
82
91
 
83
92
  - `download` — `GET /Items/{id}/Download`
@@ -36,14 +36,23 @@ See `.env.example`. The app does not load `.env` itself — `source` it or expor
36
36
  ## Usage
37
37
 
38
38
  ```bash
39
+ emby-cli version
40
+ emby-cli info
39
41
  emby-cli list
40
42
  emby-cli search "Title"
43
+ emby-cli search "Title" --count 50
41
44
  emby-cli download -i <itemId> -o ./downloads
42
45
  emby-cli sync -l "Movies"
43
46
  emby-cli batch -F titles.txt -n
47
+ emby-cli batch -F titles.txt --pick-best-item
44
48
  emby-cli play "Movie (2010)"
49
+ emby-cli play "Show S01E01" --pick-best-item
45
50
  ```
46
51
 
52
+ `info` reports libraries and totals from `GET /Items/Counts` (totals may include multiple versions of the same title).
53
+
54
+ Title resolution (`play` / `batch`) is **strict** by default (year mismatch or multiple matches fail that line). Pass `--pick-best-item` to auto-select the best ≤1080p version. In `batch`, a season line like `Show S01` downloads the whole season (with the same pick-best rule per episode version).
55
+
47
56
  Download methods (`-m` / `EMBY_METHOD`):
48
57
 
49
58
  - `download` — `GET /Items/{id}/Download`
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.1.1'
22
- __version_tuple__ = version_tuple = (0, 1, 1)
21
+ __version__ = version = '0.2.2'
22
+ __version_tuple__ = version_tuple = (0, 2, 2)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -15,13 +15,21 @@ import requests
15
15
  from emby_cli.client import EmbyClient
16
16
  from emby_cli.commands.batch import cmd_batch
17
17
  from emby_cli.commands.download import cmd_download
18
+ from emby_cli.commands.info import cmd_info
18
19
  from emby_cli.commands.list import cmd_list
19
20
  from emby_cli.commands.play import cmd_play
20
21
  from emby_cli.commands.search import cmd_search
21
22
  from emby_cli.commands.sync import cmd_sync
23
+ from emby_cli.commands.version import cmd_version
22
24
  from emby_cli.constants import DEFAULT_OUTPUT
23
25
 
24
26
 
27
+ _FORCE_HELP = (
28
+ "Re-download even if local file matches remote size "
29
+ "(or HLS .mkv + .done marker exists)"
30
+ )
31
+
32
+
25
33
  def build_parser() -> argparse.ArgumentParser:
26
34
  env = os.environ.get
27
35
 
@@ -44,7 +52,7 @@ def build_parser() -> argparse.ArgumentParser:
44
52
  dl.add_argument("--item-id", "-i", default=env("EMBY_ITEM_ID"), help="Specific item ID to download (env: EMBY_ITEM_ID)")
45
53
  dl.add_argument("--output", "-o", default=env("EMBY_OUTPUT", DEFAULT_OUTPUT),
46
54
  help=f"Output directory (env: EMBY_OUTPUT, default: {DEFAULT_OUTPUT})")
47
- dl.add_argument("--force", "-f", action="store_true", help="Re-download even if file exists with matching size")
55
+ dl.add_argument("--force", "-f", action="store_true", help=_FORCE_HELP)
48
56
  dl.add_argument("--throttle", "-t", type=float, nargs="?", const=1.0, default=0,
49
57
  help="Limit speed to playback rate. Optional multiplier: 1=realtime, 1.5=50%% faster (default: off)")
50
58
  dl.add_argument("--method", "-m", default=env("EMBY_METHOD", "download"),
@@ -54,6 +62,13 @@ def build_parser() -> argparse.ArgumentParser:
54
62
 
55
63
  sr = sub.add_parser("search", help="Search for items by name")
56
64
  sr.add_argument("query", help="Search query")
65
+ sr.add_argument(
66
+ "--count", "-n",
67
+ type=int,
68
+ default=None,
69
+ metavar="N",
70
+ help="Max results to return (default: all, paginated)",
71
+ )
57
72
 
58
73
  pl = sub.add_parser("play", help="Play an item via DirectStreamUrl in an external player")
59
74
  pl.add_argument("query", nargs="?",
@@ -65,15 +80,15 @@ def build_parser() -> argparse.ArgumentParser:
65
80
  "/Applications/VLC.app/Contents/MacOS/VLC")
66
81
  pl.add_argument("--wait", action="store_true",
67
82
  help="Block until the player process exits (default: detach and return)")
68
- pl.add_argument("--pick-best-item", type=int, choices=[0, 1], default=0,
69
- help="On ambiguous search results: 0=list and require --item-id (default), "
70
- "1=auto-select best ≤1080p like batch")
83
+ pl.add_argument("--pick-best-item", action="store_true",
84
+ help="On ambiguous search results, auto-select best ≤1080p "
85
+ "(default: list matches and fail)")
71
86
 
72
87
  sy = sub.add_parser("sync", help="Sync all libraries (or one with --library)")
73
88
  sy.add_argument("--library", "-l", default=env("EMBY_LIBRARY"), help="Specific library to sync (env: EMBY_LIBRARY)")
74
89
  sy.add_argument("--output", "-o", default=env("EMBY_OUTPUT", DEFAULT_OUTPUT),
75
90
  help=f"Output directory (env: EMBY_OUTPUT, default: {DEFAULT_OUTPUT})")
76
- sy.add_argument("--force", "-f", action="store_true", help="Re-download even if file exists with matching size")
91
+ sy.add_argument("--force", "-f", action="store_true", help=_FORCE_HELP)
77
92
  sy.add_argument("--throttle", "-t", type=float, nargs="?", const=1.0, default=0,
78
93
  help="Limit speed to playback rate. Optional multiplier: 1=realtime, 1.5=50%% faster (default: off)")
79
94
  sy.add_argument("--method", "-m", default=env("EMBY_METHOD", "download"),
@@ -86,13 +101,23 @@ def build_parser() -> argparse.ArgumentParser:
86
101
  ba.add_argument("--dry-run", "-n", action="store_true", help="Search and select only, do not download")
87
102
  ba.add_argument("--output", "-o", default=env("EMBY_OUTPUT", DEFAULT_OUTPUT),
88
103
  help=f"Output directory (env: EMBY_OUTPUT, default: {DEFAULT_OUTPUT})")
89
- ba.add_argument("--force", "-f", action="store_true", help="Re-download even if file exists with matching size")
104
+ ba.add_argument("--force", "-f", action="store_true", help=_FORCE_HELP)
90
105
  ba.add_argument("--throttle", "-t", type=float, nargs="?", const=1.0, default=0,
91
106
  help="Limit speed to playback rate. Optional multiplier: 1=realtime, 1.5=50%% faster (default: off)")
92
107
  ba.add_argument("--method", "-m", default=env("EMBY_METHOD", "download"),
93
108
  choices=["download", "stream", "hls"],
94
109
  help="Download method: 'download' (API Download), 'stream' (browser-like original.*), "
95
110
  "or 'hls' (stream chunks + remux) (env: EMBY_METHOD)")
111
+ ba.add_argument("--pick-best-item", action="store_true",
112
+ help="On ambiguous search results, auto-select best ≤1080p "
113
+ "(also per episode version in a season; default: fail the line)")
114
+
115
+ sub.add_parser("version", help="Show emby-cli version (and Emby server version if credentials work)")
116
+ sub.add_parser(
117
+ "info",
118
+ help="Show session user, server details, libraries, and item counts "
119
+ "(via /Items/Counts; versions may inflate totals)",
120
+ )
96
121
 
97
122
  return p
98
123
 
@@ -101,6 +126,14 @@ def main() -> None:
101
126
  parser = build_parser()
102
127
  args = parser.parse_args()
103
128
 
129
+ if args.command == "version":
130
+ cmd_version(args)
131
+ return
132
+
133
+ if args.command == "info":
134
+ cmd_info(args)
135
+ return
136
+
104
137
  if not args.server:
105
138
  parser.error("Provide --server or set EMBY_SERVER")
106
139