0
# Settings and Server Management
1
2
Server settings access, sync operations, and utility functions. Includes comprehensive configuration management, mobile sync capabilities, real-time notifications, and helper functions for common operations with full server administration and maintenance tools.
3
4
## Capabilities
5
6
### Settings - Server Configuration Management
7
8
Server settings access and modification with comprehensive configuration control.
9
10
```python { .api }
11
class Settings:
12
"""Server settings container."""
13
14
def __init__(self, server, data, initpath):
15
"""
16
Initialize settings container.
17
18
Args:
19
server (PlexServer): Parent server instance
20
data: Settings data
21
initpath (str): API initialization path
22
"""
23
24
def get(self, attr, default=None):
25
"""
26
Get a setting value by attribute name.
27
28
Args:
29
attr (str): Setting attribute name
30
default: Default value if setting not found
31
32
Returns:
33
Setting: Setting object or default value
34
"""
35
36
def all(self):
37
"""
38
Get all settings.
39
40
Returns:
41
List[Setting]: All server settings
42
"""
43
44
def groups(self):
45
"""
46
Get settings organized by group.
47
48
Returns:
49
List[dict]: Settings grouped by category
50
"""
51
52
def save(self):
53
"""Save all modified settings to server."""
54
55
class Setting:
56
"""Individual server setting."""
57
58
@property
59
def id(self):
60
"""Setting ID."""
61
62
@property
63
def label(self):
64
"""Human-readable setting label."""
65
66
@property
67
def summary(self):
68
"""Setting description."""
69
70
@property
71
def type(self):
72
"""Setting type (bool, int, text, etc.)."""
73
74
@property
75
def default(self):
76
"""Default setting value."""
77
78
@property
79
def value(self):
80
"""Current setting value."""
81
82
@property
83
def hidden(self):
84
"""Whether setting is hidden from UI."""
85
86
@property
87
def advanced(self):
88
"""Whether setting is advanced."""
89
90
@property
91
def group(self):
92
"""Setting group/category."""
93
94
@property
95
def enumValues(self):
96
"""Available values for enum settings."""
97
98
def set(self, value):
99
"""
100
Set setting value.
101
102
Args:
103
value: New setting value
104
"""
105
106
def toUrl(self):
107
"""
108
Convert setting to URL parameter format.
109
110
Returns:
111
str: URL parameter string
112
"""
113
```
114
115
### Sync - Mobile Device Synchronization
116
117
Mobile sync functionality for downloading content to devices with comprehensive sync management.
118
119
```python { .api }
120
class SyncItem:
121
"""Item marked for sync to mobile device."""
122
123
@property
124
def id(self):
125
"""Sync item ID."""
126
127
@property
128
def version(self):
129
"""Sync item version."""
130
131
@property
132
def rootTitle(self):
133
"""Root title of synced content."""
134
135
@property
136
def title(self):
137
"""Sync item title."""
138
139
@property
140
def metadataType(self):
141
"""Type of synced metadata."""
142
143
@property
144
def machineIdentifier(self):
145
"""Target device identifier."""
146
147
@property
148
def status(self):
149
"""Sync status."""
150
151
@property
152
def mediaSettings(self):
153
"""Media quality settings for sync."""
154
155
@property
156
def policy(self):
157
"""Sync policy settings."""
158
159
def remove(self):
160
"""Remove this item from sync."""
161
162
class SyncList:
163
"""List of sync items for a device."""
164
165
@property
166
def clientId(self):
167
"""Target client ID."""
168
169
@property
170
def machineIdentifier(self):
171
"""Target device identifier."""
172
173
@property
174
def version(self):
175
"""Sync list version."""
176
177
def items(self):
178
"""
179
Get items in sync list.
180
181
Returns:
182
List[SyncItem]: Sync items
183
"""
184
185
def addItem(self, item, **kwargs):
186
"""
187
Add item to sync list.
188
189
Args:
190
item (MediaObject): Item to sync
191
**kwargs: Sync parameters
192
"""
193
194
class Status:
195
"""Sync status information."""
196
197
@property
198
def itemsCount(self):
199
"""Total number of sync items."""
200
201
@property
202
def itemsCompleteCount(self):
203
"""Number of completed sync items."""
204
205
@property
206
def itemsDownloadedCount(self):
207
"""Number of downloaded items."""
208
209
@property
210
def itemsReadyCount(self):
211
"""Number of items ready for download."""
212
213
@property
214
def itemsSuccessfulCount(self):
215
"""Number of successfully synced items."""
216
217
@property
218
def totalSize(self):
219
"""Total size of sync content."""
220
221
@property
222
def version(self):
223
"""Sync status version."""
224
225
class MediaSettings:
226
"""Media quality settings for sync."""
227
228
@property
229
def audioBoost(self):
230
"""Audio boost setting."""
231
232
@property
233
def maxVideoBitrate(self):
234
"""Maximum video bitrate for sync."""
235
236
@property
237
def musicBitrate(self):
238
"""Music bitrate for sync."""
239
240
@property
241
def photoQuality(self):
242
"""Photo quality setting."""
243
244
@property
245
def photoResolution(self):
246
"""Photo resolution for sync."""
247
248
@property
249
def subtitleSize(self):
250
"""Subtitle size setting."""
251
252
@property
253
def videoQuality(self):
254
"""Video quality setting."""
255
256
@property
257
def videoResolution(self):
258
"""Video resolution for sync."""
259
260
class Policy:
261
"""Sync policy settings."""
262
263
@property
264
def scope(self):
265
"""Sync scope."""
266
267
@property
268
def unwatched(self):
269
"""Whether to sync unwatched content only."""
270
271
@property
272
def value(self):
273
"""Policy value."""
274
```
275
276
### AlertListener - Real-time Notifications
277
278
Real-time server notification monitoring with event-driven callback system.
279
280
```python { .api }
281
class AlertListener(threading.Thread):
282
"""Real-time server notification listener."""
283
284
def __init__(self, server, callback=None, callbackError=None):
285
"""
286
Initialize alert listener.
287
288
Args:
289
server (PlexServer): Server to monitor
290
callback (callable, optional): Callback for notifications
291
callbackError (callable, optional): Callback for errors
292
"""
293
294
def run(self):
295
"""Start listening for notifications (called by start())."""
296
297
def stop(self):
298
"""Stop listening for notifications."""
299
300
def listen(self):
301
"""Listen for a single notification (blocking)."""
302
```
303
304
### Utility Functions
305
306
Helper functions for common PlexAPI operations and data manipulation.
307
308
```python { .api }
309
# Type conversion and casting utilities
310
def cast(func, value):
311
"""
312
Apply type casting function safely.
313
314
Args:
315
func (callable): Casting function
316
value: Value to cast
317
318
Returns:
319
Casted value or None if casting fails
320
"""
321
322
def toDatetime(value, format=None):
323
"""
324
Convert value to datetime object.
325
326
Args:
327
value: Value to convert (string, int, etc.)
328
format (str, optional): Date format string
329
330
Returns:
331
datetime: Converted datetime object
332
"""
333
334
def toList(value, itemcast=None, delim=','):
335
"""
336
Convert value to list.
337
338
Args:
339
value: Value to convert
340
itemcast (callable, optional): Function to cast list items
341
delim (str): Delimiter for string splitting
342
343
Returns:
344
list: Converted list
345
"""
346
347
# Search and type utilities
348
def searchType(libtype):
349
"""
350
Convert library type to search type.
351
352
Args:
353
libtype (str): Library type name
354
355
Returns:
356
str: Corresponding search type
357
"""
358
359
def lowerFirst(s):
360
"""
361
Lowercase first character of string.
362
363
Args:
364
s (str): Input string
365
366
Returns:
367
str: String with lowercased first character
368
"""
369
370
# URL and parameter utilities
371
def joinArgs(args):
372
"""
373
Join dictionary arguments into URL parameter string.
374
375
Args:
376
args (dict): Arguments to join
377
378
Returns:
379
str: URL parameter string
380
"""
381
382
# Threading utilities
383
def threaded(callback, listargs):
384
"""
385
Execute callback function in parallel threads.
386
387
Args:
388
callback (callable): Function to execute
389
listargs (list): List of argument tuples for each thread
390
391
Returns:
392
list: Results from all threads
393
"""
394
395
# Download utilities
396
def download(url, token, filename=None, savepath=None, session=None, chunksize=4024, unpack=False, mocked=False, showstatus=False):
397
"""
398
Download file from Plex server.
399
400
Args:
401
url (str): Download URL
402
token (str): Authentication token
403
filename (str, optional): Target filename
404
savepath (str, optional): Download directory
405
session (requests.Session, optional): HTTP session
406
chunksize (int): Download chunk size
407
unpack (bool): Whether to unpack archives
408
mocked (bool): Whether to mock download
409
showstatus (bool): Whether to show progress
410
411
Returns:
412
str: Downloaded file path
413
"""
414
415
def downloadSessionImages(server, filename=None, height=150, width=150, opacity=100, saturation=100):
416
"""
417
Download session thumbnails/images.
418
419
Args:
420
server (PlexServer): Server instance
421
filename (str, optional): Output filename
422
height (int): Image height
423
width (int): Image width
424
opacity (int): Image opacity (0-100)
425
saturation (int): Image saturation (0-100)
426
427
Returns:
428
str: Downloaded image path
429
"""
430
431
# Tag manipulation utilities
432
def tag_helper(tag, items, locked=True, remove=False):
433
"""
434
Helper for managing media tags.
435
436
Args:
437
tag (str): Tag name
438
items (list): Items to tag
439
locked (bool): Whether tags are locked
440
remove (bool): Whether to remove tags
441
442
Returns:
443
dict: Tag operation parameters
444
"""
445
446
# Agent utilities
447
def getAgentIdentifier(section, agent):
448
"""
449
Get metadata agent identifier for section.
450
451
Args:
452
section (LibrarySection): Library section
453
agent (str): Agent name
454
455
Returns:
456
str: Agent identifier
457
"""
458
459
# Configuration utilities
460
def getMyPlexAccount(opts=None):
461
"""
462
Get MyPlex account from configuration.
463
464
Args:
465
opts (dict, optional): Configuration options
466
467
Returns:
468
MyPlexAccount: MyPlex account instance
469
"""
470
471
# Interactive utilities
472
def choose(msg, items, attr):
473
"""
474
Interactive selection helper for command-line usage.
475
476
Args:
477
msg (str): Selection prompt message
478
items (list): Items to choose from
479
attr (str): Attribute to display for items
480
481
Returns:
482
Selected item
483
"""
484
```
485
486
### GDM - Network Discovery
487
488
Good Day Mate (GDM) protocol for automatic Plex server discovery on local networks.
489
490
```python { .api }
491
class GDM:
492
"""Network discovery for Plex servers using GDM protocol."""
493
494
def __init__(self, timeout=3):
495
"""
496
Initialize GDM discovery client.
497
498
Args:
499
timeout (int): Discovery timeout in seconds
500
"""
501
502
def scan(self, scan_for='server'):
503
"""
504
Scan for Plex servers on network.
505
506
Args:
507
scan_for (str): What to scan for ('server', 'client')
508
"""
509
510
@property
511
def entries(self):
512
"""
513
Get discovered entries.
514
515
Returns:
516
List[dict]: Discovered server information
517
"""
518
519
def find(self, value, key='name'):
520
"""
521
Find specific server by attribute.
522
523
Args:
524
value (str): Value to search for
525
key (str): Attribute to search in
526
527
Returns:
528
dict: Matching server entry
529
"""
530
531
def main():
532
"""Command-line GDM discovery utility."""
533
```
534
535
## Usage Examples
536
537
### Server Settings Management
538
539
```python
540
# Access server settings
541
settings = plex.settings
542
543
# Get all settings
544
all_settings = settings.all()
545
print(f"Total settings: {len(all_settings)}")
546
547
# Get settings by group
548
groups = settings.groups()
549
for group in groups:
550
print(f"Group: {group['group']}")
551
for setting in group['settings']:
552
print(f" {setting.label}: {setting.value}")
553
554
# Get specific setting
555
transcoder_setting = settings.get('TranscoderQuality')
556
if transcoder_setting:
557
print(f"Transcoder Quality: {transcoder_setting.value}")
558
print(f"Default: {transcoder_setting.default}")
559
print(f"Available values: {transcoder_setting.enumValues}")
560
561
# Modify a setting
562
log_level_setting = settings.get('LogLevel')
563
if log_level_setting:
564
print(f"Current log level: {log_level_setting.value}")
565
log_level_setting.set('DEBUG')
566
settings.save() # Save changes to server
567
print("Log level updated to DEBUG")
568
```
569
570
### Mobile Sync Operations
571
572
```python
573
# Note: Sync operations require appropriate Plex Pass features and mobile app setup
574
575
# Get sync lists for devices
576
# sync_lists = plex.syncLists() # Would return SyncList objects
577
#
578
# for sync_list in sync_lists:
579
# print(f"Device: {sync_list.machineIdentifier}")
580
# items = sync_list.items()
581
# print(f"Sync items: {len(items)}")
582
#
583
# for item in items:
584
# print(f" {item.title} - Status: {item.status}")
585
586
# Add item to sync (example structure)
587
# movie = plex.library.section('Movies').get('Sample Movie')
588
# device_id = 'mobile-device-123'
589
#
590
# sync_settings = MediaSettings()
591
# sync_settings.videoQuality = 4 # Medium quality
592
# sync_settings.videoResolution = '720p'
593
#
594
# sync_policy = Policy()
595
# sync_policy.unwatched = True
596
#
597
# # This would add the movie to sync for the specified device
598
# # plex.createSyncItem(movie, device_id, settings=sync_settings, policy=sync_policy)
599
600
print("Sync operations would be performed here (requires Plex Pass)")
601
```
602
603
### Real-time Notifications
604
605
```python
606
import time
607
from plexapi.alert import AlertListener
608
609
def notification_callback(data):
610
"""Handle incoming notifications."""
611
print(f"Notification received: {data}")
612
613
# Parse notification data
614
if 'type' in data:
615
notification_type = data['type']
616
617
if notification_type == 'playing':
618
print(f"Playback started: {data.get('title', 'Unknown')}")
619
elif notification_type == 'paused':
620
print(f"Playback paused: {data.get('title', 'Unknown')}")
621
elif notification_type == 'stopped':
622
print(f"Playback stopped: {data.get('title', 'Unknown')}")
623
elif notification_type == 'library.new':
624
print(f"New content added: {data.get('title', 'Unknown')}")
625
626
def error_callback(error):
627
"""Handle notification errors."""
628
print(f"Notification error: {error}")
629
630
# Start listening for notifications
631
listener = AlertListener(plex, callback=notification_callback, callbackError=error_callback)
632
listener.start()
633
634
try:
635
# Keep listening for 60 seconds
636
time.sleep(60)
637
finally:
638
listener.stop()
639
print("Stopped listening for notifications")
640
```
641
642
### Network Discovery
643
644
```python
645
from plexapi.gdm import GDM
646
647
# Discover Plex servers on local network
648
gdm = GDM()
649
gdm.scan()
650
651
print("Discovered Plex servers:")
652
for server in gdm.entries:
653
print(f"Name: {server['name']}")
654
print(f"Host: {server['host']}")
655
print(f"Port: {server['port']}")
656
print(f"Updated: {server['updated']}")
657
print("-" * 30)
658
659
# Find specific server
660
my_server = gdm.find('My Plex Server', key='name')
661
if my_server:
662
print(f"Found server at {my_server['host']}:{my_server['port']}")
663
664
# Connect to discovered server
665
from plexapi.server import PlexServer
666
discovered_plex = PlexServer(f"http://{my_server['host']}:{my_server['port']}", token='your-token')
667
```
668
669
### Utility Function Examples
670
671
```python
672
from plexapi import utils
673
from datetime import datetime
674
675
# Type conversion utilities
676
date_string = "2023-01-15T10:30:00Z"
677
dt = utils.toDatetime(date_string)
678
print(f"Converted date: {dt}")
679
680
# List conversion
681
genre_string = "Action,Adventure,Sci-Fi"
682
genres = utils.toList(genre_string)
683
print(f"Genres: {genres}")
684
685
# Search type conversion
686
search_type = utils.searchType('movie')
687
print(f"Search type for 'movie': {search_type}")
688
689
# URL parameter joining
690
params = {'title': 'Inception', 'year': 2010, 'genre': 'Sci-Fi'}
691
url_params = utils.joinArgs(params)
692
print(f"URL parameters: {url_params}")
693
694
# Download example
695
movie = plex.library.section('Movies').get('Sample Movie')
696
for media in movie.media:
697
for part in media.parts():
698
# This would download the media file
699
download_url = plex.url(part.key)
700
# downloaded_path = utils.download(download_url, plex._token, savepath='/downloads/')
701
print(f"Would download: {part.file}")
702
```
703
704
### Advanced Server Management
705
706
```python
707
def server_health_check(plex_server):
708
"""Comprehensive server health check."""
709
710
print("=== Plex Server Health Check ===")
711
712
# Basic server info
713
print(f"Server: {plex_server.friendlyName}")
714
print(f"Version: {plex_server.version}")
715
print(f"Platform: {plex_server.platform} {plex_server.platformVersion}")
716
717
# Check active sessions
718
sessions = plex_server.sessions()
719
print(f"Active sessions: {len(sessions)}")
720
721
transcoding_sessions = [s for s in sessions if hasattr(s, 'transcodeSession') and s.transcodeSession]
722
print(f"Transcoding sessions: {len(transcoding_sessions)}")
723
724
# Check library sections
725
library_sections = plex_server.library.sections()
726
print(f"Library sections: {len(library_sections)}")
727
728
for section in library_sections:
729
item_count = len(section.all())
730
print(f" {section.title}: {item_count} items")
731
732
# Check connected clients
733
clients = plex_server.clients()
734
print(f"Connected clients: {len(clients)}")
735
736
for client in clients:
737
print(f" {client.title} ({client.product})")
738
739
# Check server features
740
print(f"MyPlex enabled: {plex_server.myPlex}")
741
print(f"Remote access: {plex_server.myPlexSigninState == 'ok'}")
742
print(f"Transcoding available: {plex_server.transcoderVideo}")
743
744
# Check recent activity
745
try:
746
recent_items = plex_server.library.recentlyAdded()
747
print(f"Recently added items: {len(recent_items)}")
748
except Exception as e:
749
print(f"Could not fetch recent items: {e}")
750
751
# Run health check
752
server_health_check(plex)
753
```
754
755
### Configuration Management
756
757
```python
758
def backup_server_settings(plex_server, backup_file='plex_settings_backup.json'):
759
"""Backup server settings to file."""
760
import json
761
762
settings = plex_server.settings.all()
763
settings_data = {}
764
765
for setting in settings:
766
settings_data[setting.id] = {
767
'label': setting.label,
768
'value': setting.value,
769
'default': setting.default,
770
'type': setting.type,
771
'group': setting.group
772
}
773
774
with open(backup_file, 'w') as f:
775
json.dump(settings_data, f, indent=2, default=str)
776
777
print(f"Settings backed up to {backup_file}")
778
779
def restore_server_settings(plex_server, backup_file='plex_settings_backup.json'):
780
"""Restore server settings from backup file."""
781
import json
782
783
try:
784
with open(backup_file, 'r') as f:
785
settings_data = json.load(f)
786
787
settings = plex_server.settings
788
changes_made = 0
789
790
for setting_id, setting_data in settings_data.items():
791
current_setting = settings.get(setting_id)
792
if current_setting and current_setting.value != setting_data['value']:
793
current_setting.set(setting_data['value'])
794
changes_made += 1
795
796
if changes_made > 0:
797
settings.save()
798
print(f"Restored {changes_made} settings from backup")
799
else:
800
print("No settings needed to be restored")
801
802
except FileNotFoundError:
803
print(f"Backup file {backup_file} not found")
804
except Exception as e:
805
print(f"Error restoring settings: {e}")
806
807
# Backup and restore examples
808
backup_server_settings(plex)
809
# restore_server_settings(plex) # Uncomment to restore
810
```