-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
249 lines (212 loc) · 10.5 KB
/
main.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#--------------------------------------------
# Sometimes Torrent Trackers set shit names in movie files.
# This shit causes "Unable to parse file" error in Radarr Activity, then Radarr can't rewrite file to setted Path.
# This script uses Radarr API to check if exist an activity with this error and force rename
# This project contains posttorrent.sh Bash script integrated with Transmission Daemon to auto-unrar torrent downloads.
# posttorrent.sh Credits to Killemov. Instructions : https://forum.transmissionbt.com/viewtopic.php?t=10364
#
# Rectificarr
# Created By : fe80grau
# Created Date: 2023/02
# version ='1.0'
# Radarr API : https://radarr.video/docs/api/
# Radarr API Endpoint used in this script: https://radarr.video/docs/api/#/Queue/get_api_v3_queue
# isBase64 function from: https://stackoverflow.com/questions/12315398/check-if-a-string-is-encoded-in-base64-using-python
# -------------------------------------------
import requests
import urllib.parse
import shutil
import traceback
import base64
import json
import os
import mimetypes
import glob
import subprocess
mimetypes.init()
#Reading config file
with open('config.json', 'r') as f:
config = json.load(f)
#Utils
def makeUrl(host, port, endpoint, params=False):
baseurl = "http://{}:{}/".format(host, port)
return "{}{}?{}".format(baseurl, endpoint, params) if params else "{}{}".format(baseurl, endpoint)
def rename(title, year, quality, file):
return "{} ({}) {}.{}".format(title, year, quality, file.split('.')[-1])
def isMediaFile(fileName):
mimestart = mimetypes.guess_type(fileName)[0]
if mimestart != None:
mimestart = mimestart.split('/')[0]
if mimestart in ['video']:
return True
return False
#Define Radarr setting and enpoint url constructor
#Queue
params_radarr = urllib.parse.urlencode({
"includeUnknownMovieItems" : "true",
"includeMovie" : "true",
"apikey" : config['radarr']['api_key']
})
#Make url merging chunks with makeUrl util
queue_url_radarr = makeUrl(config['radarr']['host'],
config['radarr']['port'],
'api/v3/queue',
params_radarr)
#Get list of all movies /api/v3/movie amd merging history
movies_history = []
params_radarr = urllib.parse.urlencode({
"apikey" : config['radarr']['api_key']
})
movies_url_radarr = makeUrl(config['radarr']['host'],
config['radarr']['port'],
'api/v3/movie',
params_radarr)
movies = requests.get(movies_url_radarr).json()
for movie in movies:
params_radarr = urllib.parse.urlencode({
"movieid" : movie['id'],
"apikey" : config['radarr']['api_key']
})
#Get history for movie item
history_url_radarr = makeUrl(config['radarr']['host'],
config['radarr']['port'],
'api/v3/history/movie',
params_radarr)
histories = requests.get(history_url_radarr).json()
downloadsIds = []
for history in histories:
if 'downloadId' in history:
downloadsIds.append(history['downloadId'])
data = {
"id" : movie['id'],
"title" : movie['title'],
"year" : movie['year'],
"path" : movie['path'],
"downloadIds" : downloadsIds
}
movies_history.append(data)
#MAIN
if __name__ == "__main__":
#Call url_radarr with GET
data = requests.get(queue_url_radarr).json()
print("Rectificarr is running...")
#Activities in Radarr shows in records key (list)
#An activity is a download/rewrite process. A movie can be download many times with differents torrent tyrs, each download is an activity.
if 'records' in data:
print('Processing data from Radarr')
#Loop Activies
for item in data['records']:
#Check if statusMessages is setted. If not, this code will initilice a fake values to avoid errors and keep minimal code
if len(item['statusMessages']) < 1:
item['statusMessages'] = [{'messages' : [''], 'title':''}]
trackedDownloadStatus = item['trackedDownloadStatus']
trackedDownloadState = item['trackedDownloadState']
try:
statusMessage = item['statusMessages'][0]['messages'][0]
except:
print(item)
queue_url_radarr = ""
if not "wasn't grabbed by Radarr" in statusMessage:
if not 'movieId' in item:
for mh in movies_history:
if item['downloadId'] in mh['downloadIds']:
item['movieId'] = mh['id']
item['movie'] = {
"title" : mh['title'],
"year" : mh['year'],
"path" : mh['path']
}
break
if not 'movieId' in item:
break
#Getting data from Activity
queue_id = item['id']
downloadId = item['downloadId']
movieId = item['movieId']
title = item['movie']['title']
year = str(item['movie']['year'])
path = item['movie']['path']
quality = item['quality']['quality']['name']
source = item['outputPath']
file_source = item['statusMessages'][0]['title']
#If the movie is in a folder
if not os.path.isfile(source):
for f in os.listdir(source):
if os.path.isfile(os.path.join(source, f)) and isMediaFile(os.path.join(source, f)):
file_source = f
#Print movie title to debug
print("||||| {}".format(title))
#Check conditions to ensure that "Unable to parse file" error in statusMessage depends to importPending trackedDownloadState
if trackedDownloadStatus == 'warning' \
and trackedDownloadState == 'importPending' \
and (statusMessage == 'Unable to parse file' or statusMessage == 'Unknown Movie') :
#Print movieId and absolute path to debug
print("|||||||||| Movie warning detectect: {} - {}/{}".format(movieId, title, file_source))
print("- Trying to rename and move to correct folder")
#Trying to make a new_name and rewrite in source. After that, Radarr automaticaly will detect this change and can parse the file.
try:
new_name = rename(title, year, quality, file_source)
print("- Old name: {}".format(file_source))
print("- New name: {}".format(new_name))
#Quick patch to solve https://github.com/fe80Grau/Rectificarr/issues/2
if os.path.isfile(source):
mv_source = source
mv_new = source.replace(source.split('/')[-1], new_name)
else:
mv_source = source + "/" + file_source
mv_new = source + "/" + new_name
#shutil.move(mv_source, mv_new)
#Copy file to Radarr defined movie path
print("|||||Importing movie... ")
if not os.path.isdir(path):
os.mkdir(path)
if not os.path.isfile("{}/{}".format(path, new_name)):
shutil.copy(mv_source, "{}/{}".format(path, new_name))
params_radarr = urllib.parse.urlencode({
"folder" : "{}/{}".format(path, new_name),
"downloadId" : downloadId,
"movieid" : movieId,
"apikey" : config['radarr']['api_key']
})
manual_import_radarr = makeUrl(config['radarr']['host'],
config['radarr']['port'],
'api/v3/manualimport',
params_radarr)
manual_import_result = requests.get(manual_import_radarr).json()
print("import done")
print("|||||Removing from queue...")
params_radarr = urllib.parse.urlencode({
"apikey" : config['radarr']['api_key'],
"removeFromClient" : False,
"blocklist" : False
})
delete_url_radarr = makeUrl(config['radarr']['host'],
config['radarr']['port'],
'api/v3/queue/{}'.format(queue_id),
params_radarr)
delete_result = requests.delete(delete_url_radarr)
if delete_result.status_code == 200:
print("Delete done")
else:
print(delete_result)
print(delete_result.text)
#Rescan movie with /api/command?name=RescanMovie?movieId={movieId}
print("|||||Rescanning movie... ")
params_radarr = urllib.parse.urlencode({
"name" : "RescanMovie",
"movieid" : movieId,
"apikey" : config['radarr']['api_key']
})
command_url_radarr = makeUrl(config['radarr']['host'],
config['radarr']['port'],
'api/v3/command',
params_radarr)
command_result = requests.get(command_url_radarr).json()
print("Rescan done")
except Exception:
traceback.print_exc()
#If endpoints fails...
else:
print('No data found')