totaldebug / pyarr

Python client for Servarr API's (Sonarr, Radarr, Readarr, Lidarr)
https://docs.totaldebug.uk/pyarr
MIT License
74 stars 20 forks source link

upd_movie not working #177

Open patsaindon opened 2 months ago

patsaindon commented 2 months ago

Is there an existing issue for this?

Current Behaviour

I do a script that will update the movie path when added to Radarr. The results of the script will show that the path is updated, but not in Radarr.

Steps To Reproduce

  1. On an Unraid 6.12.11, Radarr Version 5.9.1.9070
  2. On Python 3.9.16
  3. radarr = ExtendedRadarrAPI('localhost', 'apikey') radarr.upd_movie(data=movie, move_files=True)

Updated movie path to /movies/2020/Demon Slayer Kimetsu no Yaiba The Movie Mugen Train (2020)

But the movie Path in Radarr did not change.

Expected behaviour

The the movie path in Radarr is changed after it runned the script

Pyarr Version

5.2.0

Python Version

3.9.16

Example Code

import os
import requests
import re
from pyarr import RadarrAPI
import json
from typing import Optional, Dict, Any

# Define JsonObject type
JsonObject = Dict[str, Any]

class RadarrAPI:
    def __init__(self, host: str, api_key: str, ver_uri: str = '/api/v3'):
        self.host = host
        self.api_key = api_key
        self.ver_uri = ver_uri

    def _put(self, endpoint: str, ver_uri: str, data: JsonObject, params: Optional[Dict[str, Any]] = None) -> requests.Response:
        url = f"{self.host}{ver_uri}/{endpoint}"
        headers = {
            'X-Api-Key': self.api_key,
            'Content-Type': 'application/json'
        }
        response = requests.put(url, headers=headers, json=data, params=params)
        response.raise_for_status()  # Raise an exception for HTTP errors
        return response

    def _get(self, endpoint: str) -> requests.Response:
        url = f"{self.host}{self.ver_uri}/{endpoint}"
        headers = {
            'X-Api-Key': self.api_key,
            'Content-Type': 'application/json'
        }
        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise an exception for HTTP errors
        return response

# Extend the RadarrAPI class to include the get_movie_by_id, upd_movie, and get_movie methods
class ExtendedRadarrAPI(RadarrAPI):
    def get_movie_by_id(self, movie_id):
        response = self._get(f'/api/v3/movie/{movie_id}')
        return response.json()

    def upd_movie(self, data=None, move_files=True):
        if data is None:
            raise ValueError("No movie data provided")
        url = 'movie'
        print(f"PUT request URL: {url}")
        print(f"PUT request ver_uri: {self.ver_uri}")
        print(f"PUT request params: {params}")
        print(f"PUT request data: {json.dumps(data, indent=4)}")
        response = self._put(url, self.ver_uri, data=data, params=params)
        print(f"PUT response status code: {response.status_code}")
        print(f"PUT response content: {response.content}")
        return response.json()  # Return the JSON response

    def get_movie(self):
        response = self._get('movie')
        return response.json()  # Return the JSON response

# Initialize the Radarr instance
radarr = ExtendedRadarrAPI('localhost', ''api_key)

# Define the root folder
root = '/movies'

try:
    # Get the last added movie id from the Radarr API
    movies = radarr.get_movie()

    # Get last movie added
    last_added_movie = sorted(movies, key=lambda x: x['added'], reverse=True)

    # If last_added_movies is empty, raise an exception
    if not last_added_movie:
        raise Exception("Failed to get the last added movie")
    # Get the internal Radarr ID from the first movie in the list
    movie_id = last_added_movie[0]['id']
    tmdbId = last_added_movie[0]['tmdbId']
    imdbId = last_added_movie[0]['imdbId']
    movie_title = last_added_movie[0]['title']
    movie_year = last_added_movie[0]['year']
    path = last_added_movie[0]['path']

    # Get the movie title from the movie details
    movie_title = last_added_movie[0]['title']
    if movie_title.startswith('The '):
        movie_title = f"{movie_title[4:]}, The"
    if movie_title.startswith('A '):
        movie_title = f"{movie_title[2:]}, A"
    if movie_title.startswith('An '):
        movie_title = f"{movie_title[3:]}, An"

    # If movie title contains special characters, remove them
    movie_title = re.sub(r'[^A-Za-z0-9 ]+', '', movie_title)

    # Define the compliant path
    compliant_path = str(f'{root}/{movie_year}/{movie_title} ({movie_year})')

    # Define missing variables
    quality_profile = 1  # Example value, replace with actual value
    monitored = True  # Example value, replace with actual value
    minimum_availability = "announced"  # Example value, replace with actual value
    tags = []  # Example value, replace with actual value

    # Define the params variable with the necessary data
    params = {
        'id': movie_id,
        'title': movie_title,
        'path': compliant_path,
        'folderName': compliant_path,
        'tmdbId': tmdbId,
        'imdbId': imdbId,
        'year': movie_year,
        'qualityProfileId': quality_profile,
        'monitored': monitored,
        'minimumAvailability': minimum_availability,
        'tags': tags
    }

    # Get movie details
    movie_details = radarr.get_movie()

    # From all movies, select the movie with movie id
    movie = [m for m in movie_details if m['id'] == movie_id][0]

    # Update the movie path and folderName in movie details
    movie['path'] = compliant_path
    movie['folderName'] = compliant_path

    # Update the movie path in Radarr API with the compliant path if it is not compliant
    radarr.upd_movie(data=movie, move_files=True)

    print(f"Updated movie path to {compliant_path}")

except requests.exceptions.RequestException as e:
    print(f"Request failed: {e}")
except Exception as e:
    print(f"An error occurred: {e}")

Relevant log output

No response

Code of Conduct

fumantsu commented 1 month ago

I created this till official support. Inspired from https://docs.totaldebug.uk/pyarr/_modules/pyarr/radarr.html

class ExtendedSonarrAPI(SonarrAPI):
    def upd_series_with_move(
        self, data: JsonObject, move_files: Optional[bool] = None
    ) -> JsonObject:
        params = {}
        if move_files is not None:
            params["moveFiles"] = move_files
        print(type(data))
        return self._put(
            "series",
            self.ver_uri,
            data=data,
            params=params,
        )
sonarr = ExtendedSonarrAPI(base_url, api_key)
sonarr.upd_series_with_move(series_info, True)