Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Naesstrom/9dcaeac37d5b99d1a4b5b89442133599 to your computer and use it in GitHub Desktop.
Save Naesstrom/9dcaeac37d5b99d1a4b5b89442133599 to your computer and use it in GitHub Desktop.
Sync Plex playlists to shared users.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Description: Sync Plex playlists to shared users.
# Author: /u/SwiftPanda16
# Requires: plexapi, requests, xmltodict
# Changes by me: Syncs all current playlists to all current users. Everytime you run it it deletes the old playlists on the users account and replaces it with your.
import requests
import xmltodict
from plexapi.server import PlexServer
### EDIT SETTINGS ###
PLEX_URL = 'http://localhost:32400'
PLEX_TOKEN = 'xxxxxxxxxx'
PLAYLISTS = [] # List of playlists to sync
USERS = [] # List of users to sync the playlists to
## CODE BELOW ##
def fetch_plex_api(path='', method='GET', plextv=False, **kwargs):
"""Fetches data from the Plex API"""
url = 'https://plex.tv' if plextv else PLEX_URL.rstrip('/')
headers = {'X-Plex-Token': PLEX_TOKEN,
'Accept': 'application/json'}
params = {}
if kwargs:
params.update(kwargs)
try:
if method.upper() == 'GET':
r = requests.get(url + path,
headers=headers, params=params, verify=False)
elif method.upper() == 'POST':
r = requests.post(url + path,
headers=headers, params=params, verify=False)
elif method.upper() == 'PUT':
r = requests.put(url + path,
headers=headers, params=params, verify=False)
elif method.upper() == 'DELETE':
r = requests.delete(url + path,
headers=headers, params=params, verify=False)
else:
print("Invalid request method provided: {method}".format(method=method))
return
if r and len(r.content):
if 'application/json' in r.headers['Content-Type']:
return r.json()
elif 'application/xml' in r.headers['Content-Type']:
return xmltodict.parse(r.content)
else:
return r.content
else:
return r.content
except Exception as e:
print("Error fetching from Plex API: {err}".format(err=e))
def get_user_tokens(server_id):
api_users = fetch_plex_api('/api/users', plextv=True)
api_shared_servers = fetch_plex_api('/api/servers/{server_id}/shared_servers'.format(server_id=server_id), plextv=True)
user_ids = {user['@id']: user.get('@username', user.get('@title')) for user in api_users['MediaContainer']['User']}
users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']}
return users
def main():
"""Main script"""
plex = PlexServer(PLEX_URL, PLEX_TOKEN)
## Line below to add all users ##
USERS= [x.title for x in plex.myPlexAccount().users()]
plex_users = get_user_tokens(plex.machineIdentifier)
## added line below to select all playlists ##
PLAYLISTS = [x.title for x in plex.playlists()]
plex_playlists = {playlist.title: playlist.items() for playlist in plex.playlists()}
for playlist in PLAYLISTS:
playlist_items = plex_playlists.get(playlist)
if not playlist_items:
print("Playlist '{playlist}' not found on the server. Skipping.".format(playlist=playlist))
continue
print("Cloning the '{title}' playlist...".format(title=playlist))
for user in USERS:
user_token = plex_users.get(user)
if not user_token:
print("...User '{user}' not found in shared users. Skipping.".format(user=user))
continue
user_plex = PlexServer(PLEX_URL, user_token)
# Delete the old playlist
try:
user_playlist = user_plex.playlist(playlist)
user_playlist.delete()
except:
pass
# Create a new playlist
user_plex.createPlaylist(playlist, playlist_items)
print("...Created playlist for '{user}'.".format(user=user))
return
if __name__ == "__main__":
main()
print("Done.")
@seanvree
Copy link

seanvree commented Nov 28, 2017

Hey @Naesstrom

I still can't get past this error. I've tried the username, email and userID from the JSON API.

C:\JBOPS\utility>python sync_playlists_to_all_users.py
C:\Python27\lib\site-packages\urllib3\connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
C:\Python27\lib\site-packages\urllib3\connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
Traceback (most recent call last):
  File "sync_playlists_to_all_users.py", line 113, in <module>
    main()
  File "sync_playlists_to_all_users.py", line 78, in main
    plex_users = get_user_tokens(plex.machineIdentifier)
  File "sync_playlists_to_all_users.py", line 70, in get_user_tokens
    users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']}
  File "sync_playlists_to_all_users.py", line 70, in <dictcomp>
    users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']}
KeyError: u'10033576'

C:\JBOPS\utility>

@barbados-clemens
Copy link

barbados-clemens commented Nov 30, 2017

Got it working, Thanks!.
For anyone else who is really new to all of this. First install requests, xmltodict and plexapi through pip.
pip install [ ]

Next, you need to grab your token. This can be found if you log into the plex web app. Then go to the Developer Tools (f12). From there go into the network tab and look the headers for a field titled X-Plex-Token as shown below.

Plex Token

Now you just need to run the script either by python your-script-name.py or double clicking the file.

Hope this helps the next person who stumbles upon this and has no idea how to use this script like I did.

@dskeggs
Copy link

dskeggs commented Dec 17, 2017

thanks @Naesstrom and huge thanks @barbados-clemens. Got mine working under CentOS 7, handy link: https://packaging.python.org/guides/installing-using-linux-tools/
I'm going to run mine on a cron job so they stay in sync.

@seanvree
Copy link

does this still work with Tautulli?

I still can't get past this error:

C:\Tautulli\scripts>python sync_playlists_to_all_users.py
C:\Python27\lib\site-packages\urllib3\connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
C:\Python27\lib\site-packages\urllib3\connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
Traceback (most recent call last):
  File "sync_playlists_to_all_users.py", line 113, in <module>
    main()
  File "sync_playlists_to_all_users.py", line 78, in main
    plex_users = get_user_tokens(plex.machineIdentifier)
  File "sync_playlists_to_all_users.py", line 70, in get_user_tokens
    users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']}
  File "sync_playlists_to_all_users.py", line 70, in <dictcomp>
    users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']}
KeyError: u'10914021'

C:\Tautulli\scripts>

@dmnchild
Copy link

Im late to the party, but just wanted to say thanks for this! So much time saved and frustration than having to click each user with webtools!
Worked a charm on latest plex at time of this post.

@Databobio
Copy link

Same sentiment as the last post. Thank you for this! Worked perfectly!

@Mshriver2
Copy link

Got it working, Thanks!.
For anyone else who is really new to all of this. First install requests, xmltodict and plexapi through pip.
pip install [ ]

Next, you need to grab your token. This can be found if you log into the plex web app. Then go to the Developer Tools (f12). From there go into the network tab and look the headers for a field titled X-Plex-Token as shown below.

Plex Token

Now you just need to run the script either by python your-script-name.py or double clicking the file.

Hope this helps the next person who stumbles upon this and has no idea how to use this script like I did.

Was wondering is there way to easily switch between all playlist's and certain playlist's or a way to exclude certain playlist's from the "all" list? Thanks

@jansppenrade2
Copy link

I'm always getting this error:

C:\Users\Username\AppData\Local\Programs\Python\Python37-32\lib\site-packages\urllib3\connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) C:\Users\Username\AppData\Local\Programs\Python\Python37-32\lib\site-packages\urllib3\connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) Traceback (most recent call last): File "c:/Users/Username/Desktop/plex_sync_playlists_to_users.py", line 113, in <module> main() File "c:/Users/Username/Desktop/plex_sync_playlists_to_users.py", line 78, in main plex_users = get_user_tokens(plex.machineIdentifier) File "c:/Users/Username/Desktop/plex_sync_playlists_to_users.py", line 70, in get_user_tokens users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']} File "c:/Users/Username/Desktop/plex_sync_playlists_to_users.py", line 70, in <dictcomp> users = {user_ids[user['@userID']]: user['@accessToken'] for user in api_shared_servers['MediaContainer']['SharedServer']} KeyError: '20329724'

Someone else getting the same error?

@Mecool-KX
Copy link

Mecool-KX commented Apr 11, 2020

Same error than @seanvree. I'm using Ubuntu 16.04 with Python 3.52

Any way to solve it?

@brettwatson77
Copy link

Got it working, Thanks!.
For anyone else who is really new to all of this. First install requests, xmltodict and plexapi through pip.
pip install [ ]

Next, you need to grab your token. This can be found if you log into the plex web app. Then go to the Developer Tools (f12). From there go into the network tab and look the headers for a field titled X-Plex-Token as shown below.

Plex Token

Now you just need to run the script either by python your-script-name.py or double clicking the file.

Hope this helps the next person who stumbles upon this and has no idea how to use this script like I did.

this was so helpful but I need major help I'm still getting no module requests errors and I've followed multiple instructions online though python and terminal. :( can you help me please?

@brettwatson77
Copy link

Got it working, Thanks!.
For anyone else who is really new to all of this. First install requests, xmltodict and plexapi through pip.
pip install [ ]
Next, you need to grab your token. This can be found if you log into the plex web app. Then go to the Developer Tools (f12). From there go into the network tab and look the headers for a field titled X-Plex-Token as shown below.
Plex Token
Now you just need to run the script either by python your-script-name.py or double clicking the file.
Hope this helps the next person who stumbles upon this and has no idea how to use this script like I did.

this was so helpful but I need major help I'm still getting no module requests errors and I've followed multiple instructions online though python and terminal. :( can you help me please?

HOLY SHIT I GOT IT TO WORK! (if anyone on Mac needs help I can now help others)

@brettwatson77
Copy link

Got it working, Thanks!.
For anyone else who is really new to all of this. First install requests, xmltodict and plexapi through pip.
pip install [ ]
Next, you need to grab your token. This can be found if you log into the plex web app. Then go to the Developer Tools (f12). From there go into the network tab and look the headers for a field titled X-Plex-Token as shown below.
Plex Token
Now you just need to run the script either by python your-script-name.py or double clicking the file.
Hope this helps the next person who stumbles upon this and has no idea how to use this script like I did.

this was so helpful but I need major help I'm still getting no module requests errors and I've followed multiple instructions online though python and terminal. :( can you help me please?

HOLY SHIT I GOT IT TO WORK! (if anyone on Mac needs help I can now help others)

OK so I had it working, I migrated my server to a new Mac changed the token and now can't get past this new error!

Warning (from warnings module):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/urllib3/connectionpool.py", line 1013
warnings.warn(
InsecureRequestWarning: Unverified HTTPS request is being made to host 'plex.tv'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings

Warning (from warnings module):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/urllib3/connectionpool.py", line 1013
warnings.warn(
InsecureRequestWarning: Unverified HTTPS request is being made to host 'plex.tv'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Traceback (most recent call last):
File "/Users/brettwatson/Desktop/sync_playlists_to_all_users.py", line 113, in
main()
File "/Users/brettwatson/Desktop/sync_playlists_to_all_users.py", line 80, in main
PLAYLISTS = [x.title for x in plex.playlists()]
File "/Users/brettwatson/Desktop/sync_playlists_to_all_users.py", line 80, in
PLAYLISTS = [x.title for x in plex.playlists()]
AttributeError: 'Tag' object has no attribute 'title'
"

@brettwatson77
Copy link

I worked it out the new plexapi kills the script revert to the older plexapi and it works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment