-
Notifications
You must be signed in to change notification settings - Fork 2
/
radarr_collection_sync.py
145 lines (128 loc) · 5.95 KB
/
radarr_collection_sync.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Author: /u/RG9400
# Requires: requests
import requests
import json
import time
##################################### CONFIG BELOW #####################################
RADARR_API_KEY = ""
RADARR_LOCAL_URL = 'http://localhost:7878/radarr/' # Make sure you include the trailing /
TRAKT_FORCE_RESYNC = False #Set to True to delete all movies from Trakt's collection before pushing Radarr's list
CHUNK_SIZE = 1000 #number of movies to send to Trakt in a single API paylod
USE_RADARR_COLLECTED_DATE = True #If False, Trakt will use its existing collected date if available (won't work on resync) or the item's release date
########################################################################################
#We rely on Radarr for Trakt oAuth. This requires you to have a Trakt connection already setup in Radarr and authenticated
#The below Trakt Client ID should not need to be changed, but you can verify if it is still accurate by checking the one found at
#https://github.com/Radarr/Radarr/blob/aphrodite/src/NzbDrone.Core/Notifications/Trakt/TraktProxy.cs#L27
TRAKT_CLIENT_ID = "64508a8bf370cee550dde4806469922fd7cd70afb2d5690e3ee7f75ae784b70e"
#########################################################################################
### CODE BELOW ###
def divide_chunks(l, n):
for i in range(0, len(l), n):
yield l[i:i + n]
radarr_notifications_url = '{}api/v3/notification?apikey={}'.format(RADARR_LOCAL_URL, RADARR_API_KEY)
radarr_notifications = requests.get(radarr_notifications_url).json()
trakt_notification = next(notification for notification in radarr_notifications if notification['implementation'] == "Trakt")
access_token = next(token for token in trakt_notification['fields'] if token['name'] == "accessToken")
TRAKT_BEARER_TOKEN = access_token['value']
trakt_api_url = 'https://api.trakt.tv/sync/collection'
trakt_headers = {"Content-Type": "application/json", "Authorization": "Bearer {}".format(TRAKT_BEARER_TOKEN),
"trakt-api-version": "2", "trakt-api-key": TRAKT_CLIENT_ID, 'User-Agent': 'Radarr Trakt Collection Syncer v0.1'}
if TRAKT_FORCE_RESYNC:
deletion_list = []
print('Removing all movies from your Trakt collection to start fresh')
trakt_movies = requests.get('{}/movies'.format(trakt_api_url), headers=trakt_headers).json()
for movie in trakt_movies:
deletion_list.append(movie['movie'])
chunked_deletion_list = divide_chunks(deletion_list, CHUNK_SIZE)
for deletion_sublist in chunked_deletion_list:
deletion_payload = json.dumps({"movies":deletion_sublist})
trakt_delete_response = requests.post('{}/remove'.format(trakt_api_url), headers=trakt_headers, data=deletion_payload)
print("HTTP Response Code: {}".format(trakt_delete_response.status_code))
message = trakt_delete_response.json()
print("Response: {}".format(json.dumps(message, sort_keys=True, indent=4, separators=(',', ': '))))
time.sleep(1)
radarr_api_url = '{}api/v3/movie?apikey={}'.format(RADARR_LOCAL_URL, RADARR_API_KEY)
radarr_movies = requests.get(radarr_api_url).json()
movie_list = []
print('Pushing all downloaded movies from Radarr into your Trakt collection')
downloaded_movies = (movie for movie in radarr_movies if movie['sizeOnDisk'] > 0)
for movie in downloaded_movies:
title = movie['title']
year = movie.get('year', None)
imdb_id = movie.get('imdbId', None)
tmdb_id = movie['tmdbId']
source = movie['movieFile']['quality']['quality']['source']
source_mapping = {
"webdl":"digital",
"webrip":"digital",
"bluray":"bluray",
"tv":"dvd",
"dvd":"dvd"
}
media_type = source_mapping.get(source, None)
radarr_resolution = movie['movieFile']['quality']['quality']['resolution']
scan_type = movie['movieFile']['mediaInfo']['scanType']
resolution_mapping = {
2160:"uhd_4k",
1080:"hd_1080",
720:"hd_720p",
480:"sd_480",
576:"sd_576"
}
resolution = resolution_mapping.get(radarr_resolution, None)
if resolution in ["hd_1080", "sd_480", "sd_576"]:
if scan_type in ['Interlaced', 'MBAFF', 'PAFF']:
resolution = '{}i'.format(resolution)
else:
resolution = '{}p'.format(resolution)
audio_codec = movie['movieFile']['mediaInfo']['audioCodec']
audio_mapping = {
"AC3":"dolby_digital",
"EAC3":"dolby_digital_plus",
"TrueHD":"dolby_truehd",
"EAC3 Atmos":"dolby_digital_plus_atmos",
"TrueHD Atmos":"dolby_atmos",
"DTS":"dts",
"DTS-ES":"dts",
"DTS-HD MA":"dts_ma",
"DTS-HD HRA":"dts_hr",
"DTS-X":"dts_x",
"MP3":"mp3",
"MP2":"mp2",
"Vorbis":"ogg",
"WMA":"wma",
"AAC":"aac",
"PCM":"lpcm",
"FLAC":"flac",
"Opus":"ogg_opus"
}
audio = audio_mapping.get(audio_codec, None)
audio_channel_count = movie['movieFile']['mediaInfo']['audioChannels']
channel_mapping = str(audio_channel_count)
audio_channels = channel_mapping
media_object = {
"title": title,
"year": year,
"ids": {
"imdb": imdb_id,
"tmdb": tmdb_id
},
"media_type": media_type,
"resolution": resolution,
"audio": audio,
"audio_channels": audio_channels
}
if USE_RADARR_COLLECTED_DATE:
collected_at = movie['movieFile']['dateAdded']
media_object["collected_at"] = collected_at
movie_list.append(media_object)
chunked_movie_list = divide_chunks(movie_list, CHUNK_SIZE)
for movie_sublist in chunked_movie_list:
payload = json.dumps({"movies": movie_sublist})
trakt_response = requests.post(trakt_api_url, headers=trakt_headers, data=payload)
print("HTTP Response Code: {}".format(trakt_response.status_code))
message = trakt_response.json()
print("Response: {}".format(json.dumps(message, sort_keys=True, indent=4, separators=(',', ': '))))
time.sleep(1)