Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

playlist_to_collection.py (copy poster from playlist to collection too) #212

Open
AverageDave93 opened this issue May 31, 2024 · 3 comments
Labels
1. Feature request Request for feature to be added to script

Comments

@AverageDave93
Copy link

In what file should the feature be added?
playlist_to_collection.py

What is the feature request?
copying the poster from the playlist to the collection.

@AverageDave93 AverageDave93 added the 1. Feature request Request for feature to be added to script label May 31, 2024
@AverageDave93
Copy link
Author

AverageDave93 commented Jun 12, 2024

I have change the playlist_to_collection.py to include the copying of a playlist poster to the collection. you just need to install plexapi just as you did requests.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
The use case of this script is the following:
    Get the content of a playlist and put it in a collection
Requirements (python3 -m pip install [requirement]):
    requests
    plexapi
Setup:
    Fill the variables below firstly, then run the script with -h to see the arguments that you need to give.
"""

import requests
import plexapi
from plexapi.server import PlexServer
import argparse
import logging
from os import getenv

# Configuration
plex_ip = getenv('plex_ip', '')
plex_port = getenv('plex_port', '')
plex_api_token = getenv('plex_api_token', '')
base_url = f"http://{plex_ip}:{plex_port}"

# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Modify the playlist_to_collection() function to return playlist_name
def playlist_to_collection(ssn, library_name: str, playlist_name: str, remove_playlist: bool=False):
    try:
        # Fetch playlists
        logger.info("Fetching playlists...")
        playlists_response = ssn.get(f'{base_url}/playlists')
        playlists_response.raise_for_status()
        playlists = playlists_response.json()['MediaContainer']

        if 'Metadata' not in playlists:
            return 'Playlist not found', None

        # Find the target playlist
        playlist_entries = []
        for playlist in playlists['Metadata']:
            if playlist['title'] == playlist_name:
                logger.info(f"Found playlist '{playlist_name}' with ID {playlist['ratingKey']}")
                playlist_id = playlist['ratingKey']
                playlist_entries_response = ssn.get(f'{base_url}/playlists/{playlist_id}/items')
                playlist_entries_response.raise_for_status()
                playlist_entries = playlist_entries_response.json()['MediaContainer']
                if 'Metadata' not in playlist_entries:
                    return 'Playlist is empty', None
                playlist_entries = [entry['ratingKey'] for entry in playlist_entries['Metadata']]
                collection_thumb_url = playlist['thumb']
                break
        else:
            return 'Playlist not found', None

        # Fetch library sections
        logger.info("Fetching library sections...")
        sections_response = ssn.get(f'{base_url}/library/sections')
        sections_response.raise_for_status()
        sections = sections_response.json()['MediaContainer']['Directory']

        # Find the target library
        for lib in sections:
            if lib['title'] == library_name:
                lib_id = lib['key']
                lib_type = lib['type']
                break
        else:
            return 'Library not found', None

        # Map library type to Plex type
        lib_type_map = {'movie': '1', 'show': '4', 'artist': '10', 'photo': '13'}
        if lib_type not in lib_type_map:
            return 'Library type not supported', None
        lib_type = lib_type_map[lib_type]

        # Remove existing collection with the same name
        logger.info(f"Checking for existing collections named '{playlist_name}'...")
        collections_response = ssn.get(f'{base_url}/library/sections/{lib_id}/collections')
        collections_response.raise_for_status()
        collections = collections_response.json()['MediaContainer']
        if 'Metadata' in collections:
            for collection in collections['Metadata']:
                if collection['title'] == playlist_name:
                    logger.info(f"Deleting existing collection '{playlist_name}' with ID {collection['ratingKey']}")
                    delete_collection_response = ssn.delete(f'{base_url}/library/collections/{collection["ratingKey"]}')
                    delete_collection_response.raise_for_status()
                    break

        # Create new collection
        logger.info(f"Creating new collection '{playlist_name}'...")
        machine_id_response = ssn.get(f'{base_url}/')
        machine_id_response.raise_for_status()
        machine_id = machine_id_response.json()['MediaContainer']['machineIdentifier']
        ssn.post(f'{base_url}/library/collections', params={
            'type': lib_type,
            'title': playlist_name,
            'smart': '0',
            'sectionId': lib_id,
            'uri': f'server://{machine_id}/com.plexapp.plugins.library/library/metadata/{",".join(playlist_entries)}'
        })

        # Remove playlist if specified
        if remove_playlist:
            logger.info(f"Deleting playlist '{playlist_name}' with ID {playlist_id}")
            delete_playlist_response = ssn.delete(f'{base_url}/playlists/{playlist_id}')
            if delete_playlist_response.status_code == 200:
                logger.info(f"Successfully deleted playlist '{playlist_name}'")
            else:
                logger.error(f"Failed to delete playlist '{playlist_name}'. Status code: {delete_playlist_response.status_code}")

        return 'Operation completed successfully', collection_thumb_url
    except requests.RequestException as e:
        logger.error(f'HTTP Request failed: {e}')
        return 'HTTP Request failed', None
    except Exception as e:
        logger.error(f'An error occurred: {e}')
        return 'An error occurred', None

if __name__ == '__main__':
    # Setup session
    ssn = requests.Session()
    ssn.headers.update({'Accept': 'application/json'})
    ssn.params.update({'X-Plex-Token': plex_api_token})

    # Setup argument parsing
    parser = argparse.ArgumentParser(description='Get the content of a playlist and put it in a collection')
    parser.add_argument('-l', '--LibraryName', type=str, help='Name of target library', required=True)
    parser.add_argument('-p', '--PlaylistName', type=str, help='Name of target playlist', required=True)
    parser.add_argument('-r', '--RemovePlaylist', help='Remove source playlist afterwards', action='store_true')

    args = parser.parse_args()

    # Call function and process result
    response, collection_thumb_url = playlist_to_collection(ssn=ssn, library_name=args.LibraryName, playlist_name=args.PlaylistName, remove_playlist=args.RemovePlaylist)
    if response != 'Operation completed successfully':
        parser.error(response)
    else:
        logger.info(response)

    # Collection information
    COLLECTION_TITLE = args.PlaylistName
    POSTER_URL = f"http://{plex_ip}:{plex_port}{collection_thumb_url}?X-Plex-Token={plex_api_token}"

    # Connect to Plex server
    plex = PlexServer(base_url, plex_api_token)

    # Retrieve the collection
    collection = plex.library.section(args.LibraryName).collection(COLLECTION_TITLE)

    # Set the poster image for the collection
    collection.uploadPoster(POSTER_URL)

    print(f"Poster set successfully for collection: {COLLECTION_TITLE}")

@AverageDave93
Copy link
Author

@AverageDave93
Copy link
Author

AverageDave93 commented Jun 20, 2024

not sure if anone is even using/wanting this lol bu there was an issue with the scrpt where if it didnt have a poster set then it wouldnt copy it across, below is the new script that will work.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
The use case of this script is the following:
    Get the content of a playlist and put it in a collection
Requirements (python3 -m pip install [requirement]):
    requests
    plexapi
Setup:
    Fill the variables below firstly, then run the script with -h to see the arguments that you need to give.
"""

import requests
from os import getenv
import argparse
import logging
from plexapi.server import PlexServer

# Configuration
plex_ip = getenv('plex_ip', '')
plex_port = getenv('plex_port', '')
plex_api_token = getenv('plex_api_token', '')
base_url = f"http://{plex_ip}:{plex_port}"

# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Modify the playlist_to_collection() function to return playlist_name
def playlist_to_collection(ssn, library_name: str, playlist_name: str, remove_playlist: bool=False):
    try:
        # Fetch playlists
        logger.info("Fetching playlists...")
        playlists_response = ssn.get(f'{base_url}/playlists')
        playlists_response.raise_for_status()
        playlists = playlists_response.json()['MediaContainer']

        if 'Metadata' not in playlists:
            return 'Playlist not found', None

        # Find the target playlist
        playlist_entries = []
        for playlist in playlists['Metadata']:
            if playlist['title'] == playlist_name:
                logger.info(f"Found playlist '{playlist_name}' with ID {playlist['ratingKey']}")
                playlist_id = playlist['ratingKey']
                playlist_entries_response = ssn.get(f'{base_url}/playlists/{playlist_id}/items')
                playlist_entries_response.raise_for_status()
                playlist_entries = playlist_entries_response.json()['MediaContainer']
                if 'Metadata' not in playlist_entries:
                    return 'Playlist is empty', None
                playlist_entries = [entry['ratingKey'] for entry in playlist_entries['Metadata']]
                collection_thumb_url = playlist.get('thumb', '')  # Safely retrieve thumb attribute
                break
        else:
            return 'Playlist not found', None

        # Fetch library sections
        logger.info("Fetching library sections...")
        sections_response = ssn.get(f'{base_url}/library/sections')
        sections_response.raise_for_status()
        sections = sections_response.json()['MediaContainer']['Directory']

        # Find the target library
        for lib in sections:
            if lib['title'] == library_name:
                lib_id = lib['key']
                lib_type = lib['type']
                break
        else:
            return 'Library not found', None

        # Map library type to Plex type
        lib_type_map = {'movie': '1', 'show': '4', 'artist': '10', 'photo': '13'}
        if lib_type not in lib_type_map:
            return 'Library type not supported', None
        lib_type = lib_type_map[lib_type]

        # Remove existing collection with the same name
        logger.info(f"Checking for existing collections named '{playlist_name}'...")
        collections_response = ssn.get(f'{base_url}/library/sections/{lib_id}/collections')
        collections_response.raise_for_status()
        collections = collections_response.json()['MediaContainer']
        if 'Metadata' in collections:
            for collection in collections['Metadata']:
                if collection['title'] == playlist_name:
                    logger.info(f"Deleting existing collection '{playlist_name}' with ID {collection['ratingKey']}")
                    delete_collection_response = ssn.delete(f'{base_url}/library/collections/{collection["ratingKey"]}')
                    delete_collection_response.raise_for_status()
                    break

        # Create new collection
        logger.info(f"Creating new collection '{playlist_name}'...")
        machine_id_response = ssn.get(f'{base_url}/')
        machine_id_response.raise_for_status()
        machine_id = machine_id_response.json()['MediaContainer']['machineIdentifier']
        ssn.post(f'{base_url}/library/collections', params={
            'type': lib_type,
            'title': playlist_name,
            'smart': '0',
            'sectionId': lib_id,
            'uri': f'server://{machine_id}/com.plexapp.plugins.library/library/metadata/{",".join(playlist_entries)}'
        })

        # Remove playlist if specified
        if remove_playlist:
            logger.info(f"Deleting playlist '{playlist_name}' with ID {playlist_id}")
            delete_playlist_response = ssn.delete(f'{base_url}/playlists/{playlist_id}')
            if delete_playlist_response.status_code == 200:
                logger.info(f"Successfully deleted playlist '{playlist_name}'")
            else:
                logger.error(f"Failed to delete playlist '{playlist_name}'. Status code: {delete_playlist_response.status_code}")

        return 'Operation completed successfully', collection_thumb_url
    except requests.RequestException as e:
        logger.error(f'HTTP Request failed: {e}')
        return 'HTTP Request failed', None
    except Exception as e:
        logger.error(f'An error occurred: {e}')
        return 'An error occurred', None

if __name__ == '__main__':
    # Setup session
    ssn = requests.Session()
    ssn.headers.update({'Accept': 'application/json'})
    ssn.params.update({'X-Plex-Token': plex_api_token})

    # Setup argument parsing
    parser = argparse.ArgumentParser(description='Get the content of a playlist and put it in a collection')
    parser.add_argument('-l', '--LibraryName', type=str, help='Name of target library', required=True)
    parser.add_argument('-p', '--PlaylistName', type=str, help='Name of target playlist', required=True)
    parser.add_argument('-r', '--RemovePlaylist', help='Remove source playlist afterwards', action='store_true')

    args = parser.parse_args()

    # Call function and process result
    response, collection_thumb_url = playlist_to_collection(ssn=ssn, library_name=args.LibraryName, playlist_name=args.PlaylistName, remove_playlist=args.RemovePlaylist)
    if response != 'Operation completed successfully':
        parser.error(response)
    else:
        logger.info(response)

    # Collection information
    COLLECTION_TITLE = args.PlaylistName

    # Check if collection_thumb_url is not empty
    if collection_thumb_url:
        POSTER_URL = f"http://{plex_ip}:{plex_port}{collection_thumb_url}?X-Plex-Token={plex_api_token}"

        # Connect to Plex server
        plex = PlexServer(base_url, plex_api_token)

        # Retrieve the collection
        collection = plex.library.section(args.LibraryName).collection(COLLECTION_TITLE)

        # Set the poster image for the collection
        collection.uploadPoster(POSTER_URL)

        print(f"Poster set successfully for collection: {COLLECTION_TITLE}")
    else:
        print(f"No poster found for collection: {COLLECTION_TITLE}. Poster not set.")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1. Feature request Request for feature to be added to script
Projects
None yet
Development

No branches or pull requests

1 participant