Skip to content

Instantly share code, notes, and snippets.

@rustymyers
Last active June 7, 2022 08:18
Show Gist options
  • Save rustymyers/a68f405909224e023088c8cac6834c32 to your computer and use it in GitHub Desktop.
Save rustymyers/a68f405909224e023088c8cac6834c32 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
"""
#------------------------------------------------------------------------------------------------
#-- Movie Tag Updater for Radarr
#--------------------------------------------------------------------------------------------------
# Program : Radarr_tagarr
# To Complie : n/a
#
# Purpose : Add tags and profiles to radarr movies. Tags are retreived from Radarr.
# Say Y to add a tag. N to skip a tag. N for all tags will remove all tags.
#
# Called By :
# Calls :
#
# Author : Rusty Myers <[email protected]>
# Based Upon :
#
# Note :
#
# Revisions :
# 2017-05-03 <rusty> Initial Version
# 2017-05-03 <rusty> Updated to dynamically retreive tags and bulk set the ones chosen
# 2018-02-13 <rusty> New method to check for matching tags without concern for order,
# Adding code to combine tags with existing movie tags instead of replace,
# Updating hostname fields to make it easier to support http or https
# 2019-07-26 <rusty> Updating to Python3
# 2020-08-25 <rusty> Adding --dry-run for testing changes
# 2020-09-01 <rusty> Adding name resolution for hostname
#
# Version : 1.5
#------------------------------------------------------------------------------------------------"""
#
from __future__ import print_function
import requests, argparse, socket
# Function to return json of all movies
def get_data(radarrhost):
"""Get data from API"""
response = requests.get(radarrhost)
return response.json()
# function to put updated data
def put_data(radarrhost, moviedata):
"""Put data into API"""
result = requests.put(radarrhost, json=moviedata)
return result
# Variables
# Radarr API Key, get it in Settings->General->Security of Sonarr pages
APIKEY = ""
# Radarr Host Name: Add reverse proxy or direct IP:port, no trailing slash
HOSTNAME = ""
# Set dryrun default to false
dryrun = False
# Get our arguments
parser = argparse.ArgumentParser(description='Check, Print, and Save DHCP & BSDP Information.')
parser.add_argument('-d', '--dry-run', action='store_true', \
dest='dryrun', help='Dry run of tagging, displays expected outcomes.')
parser.add_argument('-k', '-apikey' , action='store', default=APIKEY, \
dest='APIKEY', help='Path to plist for saving results to plist. Default: /Library/Preferences/edu.psu.sdt.plist')
parser.add_argument('-n', '--hostname', action='store', default=HOSTNAME, \
dest='HOSTNAME', help='Test code with stored BSDP response from OS X Server, writing to /tmp/org.network.plist.')
args = parser.parse_args()
if args.dryrun:
print("!!! Dry Run...not making any changes...")
dryrun = True
if args.APIKEY:
APIKEY = args.APIKEY
if args.HOSTNAME:
HOSTNAME = args.HOSTNAME
host_address = ""
HOST = "".join(HOSTNAME.split("/")[2:3])
try:
host_address = socket.gethostbyname(HOST)
except:
print("Unable to resolve hostname! {}".format(HOST))
exit(1)
# Get All Tags
ALLTAGSJSON = get_data(HOSTNAME + "/api/tag?apikey=" + APIKEY)
# Get all Profiles
ALLPROFILESJSON = get_data(HOSTNAME + "/api/profile?apikey=" + APIKEY)
print("Connecting to: {}".format(HOSTNAME + "/api/tag?apikey=" + APIKEY))
# Set a profile
PROFILEINT = ""
PROFILENAMES = {}
# Print Profiles
for profile in ALLPROFILESJSON:
if profile == "error":
print("Could not connect to Radarr!")
exit(0)
print("Which profile should we add to the movie?")
print("ID: {1} Name: {0}".format(profile["name"], profile["id"]))
# Add tag to lookup by it's id
PROFILENAMES[profile["id"]] = profile["name"]
# Ask if we should add it to all movies?
ADDPROFILE = input('Which profile to all movies? [1-{0}] : '.format(len(PROFILENAMES)))
# Add the profiles to our list of tag numbers
PROFILEINT = int(ADDPROFILE)
ADDPROFILE = input('Are you sure you want to set all movies to profile \"{0}\"? [y/n] : '.format(PROFILENAMES[PROFILEINT]))
# If the answer not starts with any case Y
if not ADDPROFILE.lower().startswith("y"):
print("Skipping profile...")
else:
print("Adding profile {0}...".format(PROFILENAMES[PROFILEINT]))
# Make list of tags to add
TAGS = []
# Make a tag lookup for later
TAGNAMES = {}
# For each tag
for tag in ALLTAGSJSON:
# Add tag to lookup by it's id
TAGNAMES[tag['id']] = tag['label']
# Ask if we should add it to all movies?
ADDTAG = input('Add Tag \"{0}\" to all movies? [y/n] : '.format(tag['label']))
# If the answer starts with any case Y
if ADDTAG.lower().startswith("y"):
# Add the tag to our list of tag numbers
TAGS.append(int(tag['id']))
# Ask if we should contiunue?
ADDTAG = input("Add Tag(s) '{0}' to all movies? [y/n] : ".format(", ".join(TAGNAMES[int(p)] for p in TAGS)))
# If the answer starts with any case Y
if ADDTAG.lower().startswith("y"):
# Get All Movies
ALLMOVIESJSON = get_data(HOSTNAME + "/api/movie?apikey=" + APIKEY)
# for each movie
for movie in ALLMOVIESJSON:
# get movie ID for updating data with put_data
movieID = movie['id']
# Set tagMissing to false and check each tag
dataMissing = False
# For each tag we want to add
for tag in TAGS:
# If that tag does not exist currenlty
if tag not in movie['tags']:
# Set boolean to update tags
dataMissing = True
else:
TAGLIST = ", ".join(TAGNAMES[int(p)] for p in movie['tags'])
print("Found existing tags: {}".format(TAGLIST))
if movie['profileId'] != PROFILEINT:
dataMissing = True
if dryrun:
TAGLIST = ", ".join(TAGNAMES[int(p)] for p in movie['tags'])
MOVIETITLE = movie['title'].encode('utf-8')
print("!!! Dry-Run: Movie {0} has existing tags: {1} ".format(MOVIETITLE, TAGLIST))
if not dataMissing:
# Print movies that have the correct tags
TAGLIST = ", ".join(TAGNAMES[int(p)] for p in movie['tags'])
MOVIETITLE = movie['title'].encode('utf-8')
print("Skipping {0} with existing tags: {1} ".format(MOVIETITLE, TAGLIST))
else:
# Print name to statisfy user something is happening
TAGLIST = ", ".join(TAGNAMES[int(p)] for p in TAGS)
MOVIETITLE = movie['title'].encode('utf-8')
PNAMES = PROFILENAMES[PROFILEINT]
print("Adding '{0}' tags and {2} profile to Movie: {1}"\
.format(TAGLIST, MOVIETITLE, PNAMES))
# Combine movie tags and new tags
tag_set = list(set(movie['tags']+TAGS))
# Add unique tags
movie['tags'] = tag_set
movie['profileId'] = PROFILEINT
# Update radarrHost to include movie ID
radarrHost = HOSTNAME + "/api/movie/" + str(movieID) + "?apikey=" + APIKEY
if dryrun:
print("!!! Dry-run, not updating movie: {}!".format(MOVIETITLE))
print("CHANGES: Adding '{0}' tags and '{2}' profile to Movie: {1}".format(TAGLIST, MOVIETITLE, PNAMES))
# print(movie)
else:
# Put movie back to radarr
updateMovie = put_data(radarrHost, movie)
# If the update worked, just tell 'em that
if updateMovie.status_code == 202:
print("Sucessfully updated \"{0}\"".format(movie['title'].encode('utf-8')))
else:
# If the update didn't work, let 'em know
MOVIETITLE = movie['title'].encode('utf-8')
STATUSCODE = updateMovie.status_code
print("Failed: \"{0}\" returned response code: {1}".format(MOVIETITLE, STATUSCODE))
if b"Dragnet" in movie['title'].encode():
exit(0)
@rustymyers
Copy link
Author

@hughesjs Try version 1.5. I added a check to see if it could resolve the hostname when run:

/radarr_tagarr3.py -d -k "KEY" -n "http://1234example.com/radarr"
!!! Dry Run...not making any changes...
Unable to resolve hostname! 1234example.com

See if you get a similar error for your host. Feel free to email me directly your hostname, too, if you want me to see if I can determine the issue.
Thanks

@ak2766
Copy link

ak2766 commented Sep 8, 2020

@ak2766 Try version 1.4. You can now pass variables to the command line, including --dry-run or -d:
./radarr_tagarr3.py --dry-run -k "myAPIkey21384y01h" -n "https://radarr.com/myhost"

I've just downloaded v1.5 - it works beautifully.

Many thanks.

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