plexdo 1.1.18__py3-none-any.whl
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.
- plexdo/__init__.py +26 -0
- plexdo/__main__.py +24 -0
- plexdo/accounts.py +253 -0
- plexdo/airdates.py +136 -0
- plexdo/cache.py +38 -0
- plexdo/cli.py +157 -0
- plexdo/commands/__init__.py +63 -0
- plexdo/commands/auth.py +201 -0
- plexdo/commands/build.py +194 -0
- plexdo/commands/copy.py +169 -0
- plexdo/commands/libraries.py +231 -0
- plexdo/commands/metadata.py +135 -0
- plexdo/commands/missing.py +234 -0
- plexdo/commands/playlists.py +174 -0
- plexdo/commands/rescan.py +95 -0
- plexdo/commands/search.py +114 -0
- plexdo/commands/status.py +245 -0
- plexdo/commands/stream.py +138 -0
- plexdo/commands/users.py +39 -0
- plexdo/commands/watched.py +295 -0
- plexdo/config.py +153 -0
- plexdo/console.py +240 -0
- plexdo/constants.py +111 -0
- plexdo/convert.py +38 -0
- plexdo/data/_plexdo +359 -0
- plexdo/data/plexdo.1 +571 -0
- plexdo/data/plexdo.bash +597 -0
- plexdo/data/plexdo.fish +317 -0
- plexdo/data/plexdo.ps1 +371 -0
- plexdo/formats.py +181 -0
- plexdo/gallery.py +190 -0
- plexdo/identify.py +75 -0
- plexdo/logs.py +21 -0
- plexdo/m3u.py +34 -0
- plexdo/paths.py +105 -0
- plexdo/photos.py +74 -0
- plexdo/playlists.py +174 -0
- plexdo/py.typed +0 -0
- plexdo/records.py +136 -0
- plexdo/sections.py +58 -0
- plexdo/security.py +65 -0
- plexdo/sorting.py +50 -0
- plexdo/throttle.py +59 -0
- plexdo/titles.py +53 -0
- plexdo/tokens.py +88 -0
- plexdo-1.1.18.dist-info/METADATA +601 -0
- plexdo-1.1.18.dist-info/RECORD +51 -0
- plexdo-1.1.18.dist-info/WHEEL +5 -0
- plexdo-1.1.18.dist-info/entry_points.txt +2 -0
- plexdo-1.1.18.dist-info/licenses/LICENSE +232 -0
- plexdo-1.1.18.dist-info/top_level.txt +1 -0
plexdo/data/plexdo.1
ADDED
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
.\" Man page for plexdo (plexdo).
|
|
2
|
+
.\" Regenerate or edit alongside AI.prompt.md; the .TH version must match
|
|
3
|
+
.\" __version__ in src/plexdo/__init__.py.
|
|
4
|
+
.TH PLEXDO 1 "2026-08-14" "plexdo 1.1.18" "User Commands"
|
|
5
|
+
.
|
|
6
|
+
.SH NAME
|
|
7
|
+
plexdo \- command\-line interface for Plex Media Server
|
|
8
|
+
.
|
|
9
|
+
.SH SYNOPSIS
|
|
10
|
+
.B plexdo
|
|
11
|
+
.RI [ global-options ]
|
|
12
|
+
.I command
|
|
13
|
+
.RI [ command-options ]
|
|
14
|
+
.RI [ arguments ...]
|
|
15
|
+
.br
|
|
16
|
+
.B plexdo
|
|
17
|
+
.RI [ global-options ]
|
|
18
|
+
.I command
|
|
19
|
+
.RI [ command-options ]
|
|
20
|
+
.RI [ arguments ...]
|
|
21
|
+
.
|
|
22
|
+
.SH DESCRIPTION
|
|
23
|
+
.B plexdo
|
|
24
|
+
builds and copies playlists, exports libraries to M3U or a static HTML photo
|
|
25
|
+
gallery, synchronises watched state between users, streams media to standard
|
|
26
|
+
output, and reports on server activity.
|
|
27
|
+
.PP
|
|
28
|
+
.B plexdo
|
|
29
|
+
is an alias for the same program; prefer it on Windows, where a dot in a
|
|
30
|
+
command name interacts awkwardly with
|
|
31
|
+
.BR PATHEXT .
|
|
32
|
+
.PP
|
|
33
|
+
Wherever a
|
|
34
|
+
.I user
|
|
35
|
+
is required you may give the numeric user ID or the user\(aqs title, and
|
|
36
|
+
wherever a
|
|
37
|
+
.I library
|
|
38
|
+
is required you may give the numeric library ID or its title. User ID
|
|
39
|
+
.B 0
|
|
40
|
+
always means the admin account. Titles are matched exactly first, then
|
|
41
|
+
case\-insensitively. If a value is both one entry\(aqs ID and another\(aqs title the
|
|
42
|
+
ID wins and a warning names the entry that was skipped; if two entries share a
|
|
43
|
+
title the command aborts and asks for the numeric ID.
|
|
44
|
+
.PP
|
|
45
|
+
Commands that take an existing playlist accept its name or its ratingKey
|
|
46
|
+
interchangeably.
|
|
47
|
+
.
|
|
48
|
+
.SH GLOBAL OPTIONS
|
|
49
|
+
These may be given either before or after the command name.
|
|
50
|
+
.TP
|
|
51
|
+
.BR \-f ", " \-\-format " \fIFORMAT\fR"
|
|
52
|
+
Output format: \fBtable\fR (default), \fBjson\fR, \fByaml\fR, \fBcsv\fR, or
|
|
53
|
+
\fBclixml\fR.
|
|
54
|
+
.TP
|
|
55
|
+
.B \-\-json
|
|
56
|
+
Shorthand for \fB\-\-format json\fR.
|
|
57
|
+
.TP
|
|
58
|
+
.BR \-v ", " \-\-verbose
|
|
59
|
+
Print high\-level progress to standard error.
|
|
60
|
+
.TP
|
|
61
|
+
.B \-\-debug
|
|
62
|
+
Print detailed internal logs to standard error.
|
|
63
|
+
.TP
|
|
64
|
+
.B \-\-dry\-run
|
|
65
|
+
Show what would happen without mutating Plex.
|
|
66
|
+
.TP
|
|
67
|
+
.BR \-W ", " \-\-wide
|
|
68
|
+
Do not shrink table columns to the terminal width. By default the widest
|
|
69
|
+
column is truncated, with an ellipsis, so that a row fits on one line, and the
|
|
70
|
+
columns narrowed are reported at
|
|
71
|
+
.B \-\-verbose
|
|
72
|
+
level. Redirected output is never truncated, so piping to a file or to
|
|
73
|
+
.BR grep (1)
|
|
74
|
+
always carries the whole value.
|
|
75
|
+
.TP
|
|
76
|
+
.BI \-\-throttle " SECONDS"
|
|
77
|
+
Seconds to wait between requests in operations that query once per item, when
|
|
78
|
+
there are more than 50 of them. Defaults to 0.25; pass 0 to disable. Walking
|
|
79
|
+
every season of a large library, or writing watched state item by item, is
|
|
80
|
+
otherwise enough traffic to slow a server down or trip its rate limiting.
|
|
81
|
+
.TP
|
|
82
|
+
.BR \-V ", " \-\-version
|
|
83
|
+
Print the installed version and exit.
|
|
84
|
+
.TP
|
|
85
|
+
.BR \-h ", " \-\-help
|
|
86
|
+
Print help and exit. Every command accepts this.
|
|
87
|
+
.PP
|
|
88
|
+
All logging goes to standard error, so machine\-readable output on standard
|
|
89
|
+
output is always safe to pipe.
|
|
90
|
+
.
|
|
91
|
+
.SH OUTPUT FORMATS
|
|
92
|
+
.TP
|
|
93
|
+
.B table
|
|
94
|
+
Box\-drawn and width\-aligned, accounting for double\-width characters. Falls
|
|
95
|
+
back to ASCII box characters when the console encoding cannot represent the
|
|
96
|
+
Unicode ones.
|
|
97
|
+
.TP
|
|
98
|
+
.B json
|
|
99
|
+
Non\-ASCII is escaped, so it prints on any console.
|
|
100
|
+
.TP
|
|
101
|
+
.B yaml
|
|
102
|
+
Strings are always quoted, so a title such as \fBNO\fR or \fB1.10\fR survives
|
|
103
|
+
as a string rather than being reinterpreted as a boolean or a float.
|
|
104
|
+
.TP
|
|
105
|
+
.B csv
|
|
106
|
+
Header row plus one row per record, with newline line endings.
|
|
107
|
+
.TP
|
|
108
|
+
.B clixml
|
|
109
|
+
PowerShell CLIXML with typed properties, for \fBImport\-Clixml\fR.
|
|
110
|
+
.
|
|
111
|
+
.SH COMMANDS
|
|
112
|
+
.SS Listing and searching
|
|
113
|
+
.TP
|
|
114
|
+
.B list\-libraries
|
|
115
|
+
List every library with its ID, type, and title.
|
|
116
|
+
.TP
|
|
117
|
+
.BI list\-titles " library " [ \-\-album " ALBUM" ]
|
|
118
|
+
.RB ( list\-library
|
|
119
|
+
is an alias.)
|
|
120
|
+
List the titles in a library. Table output shows the rating key, title,
|
|
121
|
+
release date, rating, and studio; a machine\-readable format carries every
|
|
122
|
+
field the server returned for each item, and for a show library nests each
|
|
123
|
+
show\(aqs episodes under a
|
|
124
|
+
.B seasons
|
|
125
|
+
object keyed by season name. Nested objects such as media and their parts are
|
|
126
|
+
expanded, so a file name is at
|
|
127
|
+
.BR media[].parts[].file ,
|
|
128
|
+
and the paths are repeated in a top\-level
|
|
129
|
+
.B files
|
|
130
|
+
list for convenience. Note that
|
|
131
|
+
.B sourceURI
|
|
132
|
+
is not a file name: it is the remote server URI of an item in someone else\(aqs
|
|
133
|
+
playlist, and is null for anything on your own server. \fB\-\-album\fR restricts a photo library to one
|
|
134
|
+
album and is ignored elsewhere.
|
|
135
|
+
.TP
|
|
136
|
+
.BI list\-show " ratingKey " [ \-\-m3u " PATH" ]
|
|
137
|
+
List every episode of a show, skipping specials.
|
|
138
|
+
.TP
|
|
139
|
+
.BI list\-users
|
|
140
|
+
List users with their ID, account type (\fBmanaged\fR, \fBhome\fR,
|
|
141
|
+
\fBfriend\fR, \fBshared\fR), title, username, and email.
|
|
142
|
+
.TP
|
|
143
|
+
.BI list\-playlists " user"
|
|
144
|
+
List a user\(aqs playlists.
|
|
145
|
+
.TP
|
|
146
|
+
.BI list\-playlist " user playlist " [ \-\-m3u " PATH" ]
|
|
147
|
+
List the items in one playlist, named or by ratingKey.
|
|
148
|
+
.TP
|
|
149
|
+
.BI show\-metadata " ratingKey"
|
|
150
|
+
Show full metadata for one item, with fields varying by media type, including
|
|
151
|
+
the server\-side path of every file backing it. A table names a lone file
|
|
152
|
+
.BR file ,
|
|
153
|
+
and numbers them when there are several; a machine\-readable format carries
|
|
154
|
+
them as a
|
|
155
|
+
.B files
|
|
156
|
+
list. Shows and seasons have no media of their own, so they list none: those
|
|
157
|
+
files belong to the episodes.
|
|
158
|
+
.TP
|
|
159
|
+
.BI search " user query " [ \-\-media\-type " TYPE" "] [" \-\-library\-id " LIBRARY" ]
|
|
160
|
+
Search as the given user. \fITYPE\fR is one of \fBmovie\fR, \fBshow\fR,
|
|
161
|
+
\fBepisode\fR, \fBtrack\fR, \fBphoto\fR, \fBalbum\fR, \fBartist\fR. A library
|
|
162
|
+
that cannot be searched is warned about and skipped rather than aborting.
|
|
163
|
+
.
|
|
164
|
+
.SS Building playlists
|
|
165
|
+
Playlists are always constructed fully in memory, validated, previewed, and
|
|
166
|
+
then created in exactly one API call.
|
|
167
|
+
.B \-\-dry\-run
|
|
168
|
+
stops after the preview.
|
|
169
|
+
.TP
|
|
170
|
+
.BI build\-interleaved " name ratingKey ..."
|
|
171
|
+
Round\-robin the episodes of several shows into one playlist.
|
|
172
|
+
.TP
|
|
173
|
+
.BI build\-chronological " name ratingKey ..."
|
|
174
|
+
Order shows and movies by original air date. An episode with no date is
|
|
175
|
+
estimated from the median interval between its neighbours in the same season,
|
|
176
|
+
and you are prompted only when that is impossible.
|
|
177
|
+
.TP
|
|
178
|
+
.BI build\-randomize " user source dest"
|
|
179
|
+
Shuffle a playlist into a new one, using
|
|
180
|
+
.BR secrets (3)
|
|
181
|
+
rather than a predictable generator.
|
|
182
|
+
.PP
|
|
183
|
+
All three accept
|
|
184
|
+
.BR \-o ", " \-\-overwrite ,
|
|
185
|
+
.BI \-\-m3u " PATH",
|
|
186
|
+
and
|
|
187
|
+
.BR \-p ", " \-\-prefix .
|
|
188
|
+
.
|
|
189
|
+
.SS Copying and modifying
|
|
190
|
+
.TP
|
|
191
|
+
.BI copy\-playlist\-all\-users " source_user source_playlist " [ \-o ]
|
|
192
|
+
Copy a playlist to every managed user, skipping the source user. The item list
|
|
193
|
+
is printed once, then each user produces a single line giving its outcome:
|
|
194
|
+
\fBcreated\fR, \fBreplaced\fR, \fBskipped\fR, or \fBfailed\fR. A failure for one
|
|
195
|
+
user does not end the run. In a machine\-readable format the outcomes are
|
|
196
|
+
emitted as one record per user instead.
|
|
197
|
+
.TP
|
|
198
|
+
.BI copy\-playlist\-to\-user " source_user source_playlist user dest " [ \-o ]
|
|
199
|
+
Copy a playlist to one user.
|
|
200
|
+
.TP
|
|
201
|
+
.BI append\-playlist " user playlist ratingKey ..."
|
|
202
|
+
Append items to an existing playlist.
|
|
203
|
+
.TP
|
|
204
|
+
.BI remove\-playlist " user playlist"
|
|
205
|
+
Delete a playlist.
|
|
206
|
+
.PP
|
|
207
|
+
Without
|
|
208
|
+
.BR \-\-overwrite ,
|
|
209
|
+
a copy whose name is taken falls back to appending
|
|
210
|
+
.RB \(dq " admin copy" \(dq;
|
|
211
|
+
if that is taken too the target is skipped with a warning and nothing is
|
|
212
|
+
created or deleted.
|
|
213
|
+
.
|
|
214
|
+
.SS Watched state
|
|
215
|
+
.TP
|
|
216
|
+
.BI copy\-watched " user_a user_b " [ \-1 "] [" \-l " LIBRARY" "] [" \-t " KEY" "] [" \-\-unwatch ]
|
|
217
|
+
Synchronise watched state and resume points between two users.
|
|
218
|
+
.RS
|
|
219
|
+
.PP
|
|
220
|
+
By default the more recent \fBlastViewedAt\fR wins. With
|
|
221
|
+
.B \-\-unwatch
|
|
222
|
+
an item unwatched for either user becomes unwatched for both, and where both
|
|
223
|
+
have progress the earliest \fBlastViewedAt\fR wins instead.
|
|
224
|
+
.TP
|
|
225
|
+
.BR \-1 ", " \-\-one\-way
|
|
226
|
+
Only write to the second user; never modify the first.
|
|
227
|
+
.TP
|
|
228
|
+
.BR \-l ", " \-\-library " \fILIBRARY\fR"
|
|
229
|
+
Restrict to one library.
|
|
230
|
+
.TP
|
|
231
|
+
.BR \-t ", " \-\-title " \fIKEY\fR"
|
|
232
|
+
Restrict to one item, by ratingKey.
|
|
233
|
+
.RE
|
|
234
|
+
.PP
|
|
235
|
+
Preview a full\-library run with
|
|
236
|
+
.B \-\-dry\-run
|
|
237
|
+
first: it compares every item both users can see.
|
|
238
|
+
.
|
|
239
|
+
.SS Exporting
|
|
240
|
+
.TP
|
|
241
|
+
.BI export\-playlist " user playlist path"
|
|
242
|
+
Write a playlist to an M3U file.
|
|
243
|
+
.TP
|
|
244
|
+
.BI export\-titles " library path " [ \-\-sort " ORDER" "] [" \-\-album " ALBUM" ]
|
|
245
|
+
Write a whole library to an M3U file, or to a self\-contained HTML gallery for
|
|
246
|
+
a photo library. \fIORDER\fR is \fBalpha\fR (default), \fBdate\fR, or
|
|
247
|
+
\fBrandom\fR.
|
|
248
|
+
.PP
|
|
249
|
+
M3U files hold the Plex server\(aqs own filesystem paths, not HTTP URLs.
|
|
250
|
+
.BR \-p ", " \-\-prefix
|
|
251
|
+
replaces the server\-side library root with another, for reading the export
|
|
252
|
+
where the media is mounted differently; separators follow the prefix, so a
|
|
253
|
+
Windows prefix produces backslashes. Because the library \fIroot\fR is what is
|
|
254
|
+
replaced, one prefix maps every library to the same place: export libraries
|
|
255
|
+
separately if they are mounted apart.
|
|
256
|
+
.
|
|
257
|
+
.SS Streaming
|
|
258
|
+
.TP
|
|
259
|
+
.BI read " library ratingKey"
|
|
260
|
+
Stream a media file to standard output, for piping into a player or
|
|
261
|
+
redirecting to a file. Quitting the player early is not an error.
|
|
262
|
+
.RS
|
|
263
|
+
.PP
|
|
264
|
+
.EX
|
|
265
|
+
plexdo read 3 12345 | mpv \-
|
|
266
|
+
plexdo read 3 12345 > episode.mkv
|
|
267
|
+
.EE
|
|
268
|
+
.PP
|
|
269
|
+
On Linux with a display attached but no desktop environment,
|
|
270
|
+
.BR mpv (1)
|
|
271
|
+
can draw straight to the console through the kernel modesetting driver, so
|
|
272
|
+
playback needs neither X nor Wayland:
|
|
273
|
+
.PP
|
|
274
|
+
.EX
|
|
275
|
+
plexdo read 3 12345 | mpv \-\-vo=drm \-
|
|
276
|
+
.EE
|
|
277
|
+
.PP
|
|
278
|
+
Run that from a virtual terminal rather than a terminal emulator, and make
|
|
279
|
+
sure your user can reach the DRM device, usually by being in the
|
|
280
|
+
.B video
|
|
281
|
+
group.
|
|
282
|
+
.RE
|
|
283
|
+
.
|
|
284
|
+
.TP
|
|
285
|
+
.BI find\-missing " SHOW " [ \-l " LIBRARY" "] [" \-A "] [" \-s " SEASONS" "] [" \-\-include\-specials ]
|
|
286
|
+
Report the episode numbers missing between the start of a season and its
|
|
287
|
+
highest episode.
|
|
288
|
+
.I SHOW
|
|
289
|
+
is a show title or ratingKey.
|
|
290
|
+
.RS
|
|
291
|
+
.PP
|
|
292
|
+
A season that simply stops early is not reported, since an unaired episode
|
|
293
|
+
cannot be told from a missing one.
|
|
294
|
+
.TP
|
|
295
|
+
.BR \-l ", " \-\-library " \fILIBRARY\fR"
|
|
296
|
+
Look only in this library, by ID or title. Narrows the search for
|
|
297
|
+
.IR SHOW ,
|
|
298
|
+
or the sweep for
|
|
299
|
+
.BR \-A .
|
|
300
|
+
.TP
|
|
301
|
+
.BR \-A ", " \-\-all
|
|
302
|
+
Check every show rather than one named show.
|
|
303
|
+
.I SHOW
|
|
304
|
+
must be omitted.
|
|
305
|
+
.TP
|
|
306
|
+
.BR \-s ", " \-\-season " \fISEASONS\fR"
|
|
307
|
+
One season number, or several separated by commas, as in
|
|
308
|
+
.BR 1,3,5 .
|
|
309
|
+
Applies to a single show. Naming season 0 includes the specials.
|
|
310
|
+
.TP
|
|
311
|
+
.B \-\-include\-specials
|
|
312
|
+
Also check season 0 when no season is named. Specials are numbered
|
|
313
|
+
irregularly, so this is off by default.
|
|
314
|
+
.RE
|
|
315
|
+
.
|
|
316
|
+
.SS Server management
|
|
317
|
+
.TP
|
|
318
|
+
.BI rescan " [library] " [ \-s "] [" \-n ]
|
|
319
|
+
Trigger a library scan for new files.
|
|
320
|
+
.B \-s
|
|
321
|
+
.RB ( \-\-status )
|
|
322
|
+
lists active scan jobs instead and needs no library.
|
|
323
|
+
.B \-n
|
|
324
|
+
.RB ( \-\-now )
|
|
325
|
+
cancels pending scans on every library first.
|
|
326
|
+
.TP
|
|
327
|
+
.BI status " " [ \-\-section " SECTION" ]
|
|
328
|
+
Report server identity, active sessions, shared users, system accounts,
|
|
329
|
+
reachable addresses, scans in progress, other background activity, and
|
|
330
|
+
scheduled tasks. A section that cannot be read is warned about and left empty
|
|
331
|
+
rather than losing the whole report. \fB\-\-format csv\fR and
|
|
332
|
+
\fB\-\-format clixml\fR are flat and require \fB\-\-section\fR.
|
|
333
|
+
.
|
|
334
|
+
.SS Setup
|
|
335
|
+
.TP
|
|
336
|
+
.BI login " " [ \-u " USER" "] [" \-p " PASS" "] [" \-c " CODE" "] [" \-2 ]
|
|
337
|
+
Authenticate against plex.tv and save the token.
|
|
338
|
+
.B \-\-password
|
|
339
|
+
is insecure: it is recorded in shell history and is briefly visible to
|
|
340
|
+
.BR ps (1).
|
|
341
|
+
Prefer the configuration file or the interactive prompt.
|
|
342
|
+
.TP
|
|
343
|
+
.B write\-config\-example
|
|
344
|
+
Write a template configuration file.
|
|
345
|
+
.B \-\-help
|
|
346
|
+
prints the exact template that would be written.
|
|
347
|
+
.
|
|
348
|
+
.SH CONFIGURATION
|
|
349
|
+
Read from
|
|
350
|
+
.IR ~/.local/etc/plexdo.ini .
|
|
351
|
+
.PP
|
|
352
|
+
.EX
|
|
353
|
+
[plex]
|
|
354
|
+
url = http://localhost:32400
|
|
355
|
+
token_path = $XDG_RUNTIME_DIR/.plex.token
|
|
356
|
+
username = you@example.com
|
|
357
|
+
password = your\-plex\-password
|
|
358
|
+
|
|
359
|
+
[99]
|
|
360
|
+
username = bob@example.com
|
|
361
|
+
password = bobs\-plex\-password
|
|
362
|
+
.EE
|
|
363
|
+
.PP
|
|
364
|
+
Values may contain environment variables as
|
|
365
|
+
.B $VAR
|
|
366
|
+
or
|
|
367
|
+
.BR ${VAR} ,
|
|
368
|
+
and
|
|
369
|
+
.B ~
|
|
370
|
+
for your home directory. A name that is not set is left as literal text and
|
|
371
|
+
warned about. Interpolation is disabled, so a password may contain
|
|
372
|
+
.B %
|
|
373
|
+
freely.
|
|
374
|
+
.PP
|
|
375
|
+
.B cache_dir
|
|
376
|
+
in the
|
|
377
|
+
.B [plex]
|
|
378
|
+
section moves the completion cache; it defaults to the platform location shown
|
|
379
|
+
under FILES, and the shell completions honour the same setting.
|
|
380
|
+
.PP
|
|
381
|
+
A section named for a numeric user ID holds that user\(aqs credentials. They are
|
|
382
|
+
used only when the server refuses the admin\-issued token for that user, which
|
|
383
|
+
happens when nothing has been shared with them.
|
|
384
|
+
.PP
|
|
385
|
+
Both this file and the token file are checked at startup and a warning is
|
|
386
|
+
printed if either is readable by group or other. On Windows the check is
|
|
387
|
+
skipped, as access there is governed by ACLs.
|
|
388
|
+
.
|
|
389
|
+
.SH TOKEN STORE
|
|
390
|
+
.I token_path
|
|
391
|
+
holds a JSON object mapping username to token:
|
|
392
|
+
.PP
|
|
393
|
+
.EX
|
|
394
|
+
{
|
|
395
|
+
"@admin": "xxxxxxxxxxxxxxxxxxxx",
|
|
396
|
+
"bob@example.com": "yyyyyyyyyyyyyyyyyyyy"
|
|
397
|
+
}
|
|
398
|
+
.EE
|
|
399
|
+
.PP
|
|
400
|
+
.B @admin
|
|
401
|
+
is the reserved key used when no
|
|
402
|
+
.B [plex] username
|
|
403
|
+
is configured;
|
|
404
|
+
.B @
|
|
405
|
+
cannot occur in a Plex username, so it never collides. The file is written
|
|
406
|
+
atomically with mode 0600. A file from an earlier version holding a single
|
|
407
|
+
bare token is read as the admin token and converted on the next write.
|
|
408
|
+
.PP
|
|
409
|
+
When a command meets a 401 for a user, three sources are tried in turn: the
|
|
410
|
+
server\-scoped token the admin can mint, a token already in the store, and a
|
|
411
|
+
fresh login with that user\(aqs configured credentials. A token obtained by the
|
|
412
|
+
last is saved, so the login happens once rather than on every run.
|
|
413
|
+
.
|
|
414
|
+
.SH SHELL COMPLETION
|
|
415
|
+
Completions are provided for
|
|
416
|
+
.BR bash ,
|
|
417
|
+
.BR zsh ,
|
|
418
|
+
.BR fish ,
|
|
419
|
+
and
|
|
420
|
+
.BR pwsh ,
|
|
421
|
+
covering user and library IDs and titles, rating keys, playlist names and
|
|
422
|
+
keys, and photo album names. Numeric IDs are shown with the title they belong
|
|
423
|
+
to.
|
|
424
|
+
.PP
|
|
425
|
+
Values are read from a 15\-minute cache under
|
|
426
|
+
.IR ~/.cache/plexdo ,
|
|
427
|
+
populated as a side effect of the list commands. A stale cache is refreshed in
|
|
428
|
+
the background, so completion never blocks; the values offered are whatever is
|
|
429
|
+
cached at that moment.
|
|
430
|
+
.PP
|
|
431
|
+
.B make install
|
|
432
|
+
installs all three. See
|
|
433
|
+
.B make help
|
|
434
|
+
for the paths in use.
|
|
435
|
+
.
|
|
436
|
+
.SH EXIT STATUS
|
|
437
|
+
.TP
|
|
438
|
+
.B 0
|
|
439
|
+
Success.
|
|
440
|
+
.TP
|
|
441
|
+
.B 1
|
|
442
|
+
Failure: missing configuration or token, an unknown ID, an inaccessible user,
|
|
443
|
+
a name collision refused without \fB\-\-overwrite\fR, or an invalid argument.
|
|
444
|
+
.
|
|
445
|
+
.SH ENVIRONMENT
|
|
446
|
+
.TP
|
|
447
|
+
.B XDG_RUNTIME_DIR
|
|
448
|
+
Referenced by the default POSIX \fItoken_path\fR. It is a private, user\-only tmpfs
|
|
449
|
+
on most Linux systems, which suits a secret, but it is cleared at logout: you
|
|
450
|
+
will need to run \fBplexdo login\fR again after a reboot. Point
|
|
451
|
+
\fItoken_path\fR somewhere persistent to avoid that.
|
|
452
|
+
.TP
|
|
453
|
+
.B XDG_CACHE_HOME
|
|
454
|
+
Overrides the location of the completion cache on Linux and macOS.
|
|
455
|
+
.TP
|
|
456
|
+
.B LOCALAPPDATA
|
|
457
|
+
On Windows, the parent of the configuration and cache directories.
|
|
458
|
+
.B APPDATA
|
|
459
|
+
is used when it is unset.
|
|
460
|
+
.TP
|
|
461
|
+
.B TEMP
|
|
462
|
+
Referenced by the default Windows \fItoken_path\fR.
|
|
463
|
+
.TP
|
|
464
|
+
.B NO_COLOR
|
|
465
|
+
Not used; output is never coloured.
|
|
466
|
+
.
|
|
467
|
+
.SH FILES
|
|
468
|
+
Paths follow the platform. On Linux and macOS:
|
|
469
|
+
.TP
|
|
470
|
+
.I ~/.local/etc/plexdo.ini
|
|
471
|
+
Configuration.
|
|
472
|
+
.TP
|
|
473
|
+
.I $XDG_RUNTIME_DIR/.plex.token
|
|
474
|
+
Default token store, mode 0600.
|
|
475
|
+
.TP
|
|
476
|
+
.I ~/.cache/plexdo/
|
|
477
|
+
Completion cache.
|
|
478
|
+
.PP
|
|
479
|
+
On Windows:
|
|
480
|
+
.TP
|
|
481
|
+
.I %LOCALAPPDATA%\ePlexDo\eplexdo.ini
|
|
482
|
+
Configuration.
|
|
483
|
+
.TP
|
|
484
|
+
.I %TEMP%\eplexdo.token
|
|
485
|
+
Default token store. Note that this directory is not protected by file
|
|
486
|
+
permissions and Windows may clear it.
|
|
487
|
+
.TP
|
|
488
|
+
.I %LOCALAPPDATA%\ePlexDo\eCache
|
|
489
|
+
Completion cache.
|
|
490
|
+
.
|
|
491
|
+
.SH EXAMPLES
|
|
492
|
+
Create the configuration and authenticate:
|
|
493
|
+
.PP
|
|
494
|
+
.EX
|
|
495
|
+
plexdo write\-config\-example
|
|
496
|
+
plexdo login
|
|
497
|
+
.EE
|
|
498
|
+
.PP
|
|
499
|
+
List libraries, then the titles in one of them by name:
|
|
500
|
+
.PP
|
|
501
|
+
.EX
|
|
502
|
+
plexdo list\-libraries
|
|
503
|
+
plexdo list\-titles "TV Shows"
|
|
504
|
+
.EE
|
|
505
|
+
.PP
|
|
506
|
+
Build a playlist interleaving two shows, replacing any existing one:
|
|
507
|
+
.PP
|
|
508
|
+
.EX
|
|
509
|
+
plexdo build\-interleaved "Mixed Run" 101 202 \-\-overwrite
|
|
510
|
+
.EE
|
|
511
|
+
.PP
|
|
512
|
+
Preview a watched\-state sync before running it for real:
|
|
513
|
+
.PP
|
|
514
|
+
.EX
|
|
515
|
+
plexdo \-\-dry\-run copy\-watched Alice Bob
|
|
516
|
+
plexdo copy\-watched Alice Bob \-\-one\-way
|
|
517
|
+
.EE
|
|
518
|
+
.PP
|
|
519
|
+
Export a library for a client that mounts the media elsewhere:
|
|
520
|
+
.PP
|
|
521
|
+
.EX
|
|
522
|
+
plexdo export\-titles "TV Shows" ~/tv.m3u \-\-prefix \(aq\e\eNAS\emedia\(aq
|
|
523
|
+
.EE
|
|
524
|
+
.PP
|
|
525
|
+
Stream an episode into a player:
|
|
526
|
+
.PP
|
|
527
|
+
.EX
|
|
528
|
+
plexdo read 3 12345 | mpv \-
|
|
529
|
+
.EE
|
|
530
|
+
.PP
|
|
531
|
+
Machine\-readable output:
|
|
532
|
+
.PP
|
|
533
|
+
.EX
|
|
534
|
+
plexdo \-\-json list\-users | jq \(aq.[] | select(.type == "home")\(aq
|
|
535
|
+
plexdo status \-\-section sessions \-f csv
|
|
536
|
+
.EE
|
|
537
|
+
.
|
|
538
|
+
.SH NOTES
|
|
539
|
+
On Windows,
|
|
540
|
+
.B \-\-password
|
|
541
|
+
scrubbing is best effort: the technique that hides the value from
|
|
542
|
+
.BR ps (1)
|
|
543
|
+
has no Windows equivalent, so it stays visible in the process list. Protecting
|
|
544
|
+
the token file is also your responsibility there, as
|
|
545
|
+
.BR chmod (1)
|
|
546
|
+
cannot restrict it.
|
|
547
|
+
.
|
|
548
|
+
.SH SEE ALSO
|
|
549
|
+
.BR jq (1),
|
|
550
|
+
.BR mpv (1),
|
|
551
|
+
.BR ps (1)
|
|
552
|
+
.PP
|
|
553
|
+
Project homepage and source:
|
|
554
|
+
.I https://github.com/sidusnare/plexdo
|
|
555
|
+
.PP
|
|
556
|
+
Further documentation:
|
|
557
|
+
.B README.md
|
|
558
|
+
in the source distribution.
|
|
559
|
+
.
|
|
560
|
+
.SH AUTHORS
|
|
561
|
+
Written by SidusNare. See the project homepage for the full list of
|
|
562
|
+
contributors.
|
|
563
|
+
.
|
|
564
|
+
.SH BUGS
|
|
565
|
+
Report issues at
|
|
566
|
+
.I https://github.com/sidusnare/plexdo/issues
|
|
567
|
+
.
|
|
568
|
+
.SH LICENSE
|
|
569
|
+
GNU General Public License version 3 or later. This is free software: you are
|
|
570
|
+
free to change and redistribute it. There is NO WARRANTY, to the extent
|
|
571
|
+
permitted by law.
|