/
processTV.py
612 lines (465 loc) · 26.5 KB
/
processTV.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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
# Author: Nic Wolfe <nic@wolfeden.ca>
# URL: http://code.google.com/p/sickbeard/
#
# This file is part of Sick Beard.
#
# Sick Beard is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Sick Beard is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
from __future__ import with_statement
import os, subprocess, shlex
import shutil
import sys
import re
import glob
from shutil import Error
from sickbeard import notifiers
from sickbeard import exceptions
from sickbeard import notifiers
from sickbeard import db, classes, helpers, sceneHelpers
from sickbeard import history
from sickbeard import encodingKludge as ek
from sickbeard import logger
from sickbeard.common import *
from sickbeard.notifiers import xbmc
from lib.tvdb_api import tvnamer, tvdb_api, tvdb_exceptions
from lib.tvnamer.utils import FileParser
from lib.tvnamer import tvnamer_exceptions
#from tvdb_api.nfogen import createXBMCInfo
sample_ratio = 0.3
def renameFile(movedFilePath, newName):
filePath = os.path.split(movedFilePath)
oldFile = os.path.splitext(filePath[1])
renamedFilePathname = ek.ek(os.path.join, filePath[0], helpers.sanitizeFileName(newName) + oldFile[1])
logger.log(u"Renaming from " + movedFilePath + " to " + renamedFilePathname)
try:
ek.ek(os.rename, movedFilePath, renamedFilePathname)
except (OSError, IOError), e:
logger.log(u"Failed renaming " + movedFilePath + " to " + os.path.basename(renamedFilePathname) + ": " + str(e), logger.ERROR)
return False
return renamedFilePathname
def copyFile(srcFile, destFile):
shutil.copyfile(srcFile, destFile)
try:
shutil.copymode(srcFile, destFile)
except OSError:
pass
def moveFile(srcFile, destFile):
try:
os.rename(srcFile, destFile)
except OSError:
copyFile(srcFile, destFile)
os.unlink(srcFile)
def deleteAssociatedFiles(file):
if not ek.ek(os.path.isfile, file):
return
baseName = file.rpartition('.')[0]+'.'
for associatedFilePath in ek.ek(glob.glob, baseName+'*'):
# only delete it if the only non-shared part is the extension
if '.' in associatedFilePath[len(baseName):]:
logger.log(u"Not deleting file "+associatedFilePath+" because it looks like it's not related", logger.DEBUG)
continue
logger.log(u"Deleting file "+associatedFilePath+" because it is associated with "+file, logger.DEBUG)
ek.ek(os.remove, associatedFilePath)
def _checkForExistingFile(renamedFilePath, oldFile):
# if the new file exists, return the appropriate code depending on the size
if ek.ek(os.path.isfile, renamedFilePath):
# see if it's bigger than our old file
if ek.ek(os.path.getsize, renamedFilePath) >= ek.ek(os.path.getsize, oldFile):
return 1
else:
return -1
else:
return 0
def findInHistory(nzbName):
names = [nzbName, nzbName.rpartition(".")[0]]
if not nzbName:
return None
myDB = db.DBConnection()
for curName in names:
sqlResults = myDB.select("SELECT * FROM history WHERE resource LIKE ?", [re.sub("[\.\-\ ]", "_", curName)])
if len(sqlResults) == 1:
return (int(sqlResults[0]["showid"]), int(sqlResults[0]["season"]), int(sqlResults[0]["episode"]))
return None
def logHelper (logMessage, logLevel=logger.MESSAGE):
logger.log(logMessage, logLevel)
return logMessage + "\n"
def processDir (dirName, nzbName=None, recurse=False):
returnStr = ''
returnStr += logHelper("Processing folder "+dirName, logger.DEBUG)
# if they passed us a real dir then assume it's the one we want
if ek.ek(os.path.isdir, dirName):
dirName = ek.ek(os.path.realpath, dirName)
# if they've got a download dir configured then use it
elif sickbeard.TV_DOWNLOAD_DIR and os.path.isdir(sickbeard.TV_DOWNLOAD_DIR) \
and os.path.normpath(dirName) != os.path.normpath(sickbeard.TV_DOWNLOAD_DIR):
dirName = ek.ek(os.path.join, sickbeard.TV_DOWNLOAD_DIR, os.path.abspath(dirName).split(os.path.sep)[-1])
returnStr += logHelper("Trying to use folder "+dirName, logger.DEBUG)
# if we didn't find a real dir then quit
if not ek.ek(os.path.isdir, dirName):
returnStr += logHelper("Unable to figure out what folder to process. If your downloader and Sick Beard aren't on the same PC make sure you fill out your TV download dir in the config.", logger.DEBUG)
return returnStr
# TODO: check if it's failed and deal with it if it is
if os.path.basename(dirName).startswith('_FAILED_'):
returnStr += logHelper("The directory name indicates it failed to extract, cancelling", logger.DEBUG)
return returnStr
elif os.path.basename(dirName).startswith('_UNDERSIZED_'):
returnStr += logHelper("The directory name indicates that it was previously rejected for being undersized, cancelling", logger.DEBUG)
return returnStr
elif os.path.basename(dirName).startswith('_UNPACK_'):
returnStr += logHelper("The directory name indicates that this release is in the process of being unpacked, skipping", logger.DEBUG)
return returnStr
# make sure the dir isn't inside a show dir
myDB = db.DBConnection()
sqlResults = myDB.select("SELECT * FROM tv_shows")
for sqlShow in sqlResults:
if dirName.lower().startswith(ek.ek(os.path.realpath, sqlShow["location"]).lower()+os.sep) or dirName.lower() == ek.ek(os.path.realpath, sqlShow["location"]).lower():
returnStr += logHelper("You're trying to post process an episode that's already been moved to its show dir", logger.ERROR)
return returnStr
fileList = ek.ek(os.listdir, dirName)
# split the list into video files and folders
folders = filter(lambda x: ek.ek(os.path.isdir, ek.ek(os.path.join, dirName, x)), fileList)
videoFiles = filter(helpers.isMediaFile, fileList)
# recursively process all the folders
for curFolder in folders:
returnStr += logHelper("Recursively processing a folder: "+curFolder, logger.DEBUG)
returnStr += processDir(ek.ek(os.path.join, dirName, curFolder), recurse=True)
remainingFolders = filter(lambda x: ek.ek(os.path.isdir, ek.ek(os.path.join, dirName, x)), fileList)
# process any files in the dir
for movedFilePath in videoFiles:
movedFilePath = ek.ek(os.path.join, dirName, movedFilePath)
# if there's only one video file in the dir we can use the dirname to process too
if len(videoFiles) == 1:
returnStr += logHelper("Auto processing file: "+movedFilePath+" ("+dirName+")")
result = processFile(movedFilePath, dirName, nzbName)
# as long as the postprocessing was successful delete the old folder unless the config wants us not to
if type(result) == list:
returnStr += result[0]
if not sickbeard.KEEP_PROCESSED_DIR and \
os.path.normpath(dirName) != os.path.normpath(sickbeard.TV_DOWNLOAD_DIR) and \
len(remainingFolders) == 0:
returnStr += logHelper("Deleting folder " + dirName, logger.DEBUG)
try:
shutil.rmtree(dirName)
except (OSError, IOError), e:
returnStr += logHelper("Warning: unable to remove the folder " + dirName + ": " + str(e), logger.ERROR)
returnStr += logHelper("Processing succeeded for "+movedFilePath)
else:
returnStr += result
returnStr += logHelper("Processing failed for "+movedFilePath)
else:
returnStr += logHelper("Auto processing file: "+movedFilePath)
result = processFile(movedFilePath, None, nzbName)
if type(result) == list:
returnStr += result[0]
returnStr += logHelper("Processing succeeded for "+movedFilePath)
else:
returnStr += result
returnStr += logHelper("Processing failed for "+movedFilePath)
return returnStr
def processFile(fileName, downloadDir=None, nzbName=None):
returnStr = ''
folderName = None
if downloadDir != None:
folderName = downloadDir.split(os.path.sep)[-1]
returnStr += logHelper("Processing file "+fileName+" (with folder name "+str(folderName)+" and NZB name "+str(nzbName)+")", logger.DEBUG)
finalNameList = []
for curName in (fileName, folderName, nzbName):
if curName != None:
for curSceneName in sceneHelpers.sceneToNormalShowNames(curName):
if curSceneName not in finalNameList:
finalNameList.append(curSceneName)
showResults = None
result = None
tvdb_id = None
season = None
episodes = []
# first try looking up every name in our history
for curName in finalNameList:
historyResult = findInHistory(curName)
if historyResult:
returnStr += logHelper("Result from history: "+str(historyResult)+" from "+curName, logger.DEBUG)
(tvdb_id, season, episode) = historyResult
episodes = [episode]
showResults = helpers.findCertainShow(sickbeard.showList, tvdb_id)
break
# if that didn't work then try manually parsing and searching them on TVDB
for curName in finalNameList:
# if we already have the info from the history then don't bother with this
if tvdb_id != None and season != None and episodes != []:
break
# set all search stuff to defaults so we don't carry results over from the last iteration
tvdb_id = None
season = None
episodes = []
try:
returnStr += logHelper("Attempting to parse name "+curName, logger.DEBUG)
myParser = FileParser(curName)
result = myParser.parse()
season = result.seasonnumber if result.seasonnumber != None else 1
episodes = result.episodenumbers
returnStr += logHelper("Ended up with season "+str(season)+" and episodes "+str(episodes), logger.DEBUG)
except tvnamer_exceptions.InvalidFilename:
returnStr += logHelper("Unable to parse the filename "+curName+" into a valid episode", logger.DEBUG)
continue
if not result.seriesname:
returnStr += logHelper("Filename "+curName+" has no series name, unable to use this name for processing", logger.DEBUG)
continue
if not episodes:
returnStr += logHelper("Unable to find an episode number in the filename "+curName+", skipping", logger.DEBUG)
continue
# reverse-lookup the scene exceptions
returnStr += logHelper("Checking scene exceptions for "+result.seriesname, logger.DEBUG)
sceneID = None
for exceptionID in sceneExceptions:
for curException in sceneExceptions[exceptionID]:
if result.seriesname == curException:
sceneID = exceptionID
break
if sceneID:
returnStr += logHelper("Scene exception lookup got tvdb id "+str(sceneID)+", using that", logger.DEBUG)
break
showObj = None
try:
t = tvdb_api.Tvdb(custom_ui=classes.ShowListUI, **sickbeard.TVDB_API_PARMS)
# get the tvdb object from either the scene exception ID or the series name
if sceneID:
returnStr += logHelper("Looking up ID "+str(sceneID)+" on TVDB", logger.DEBUG)
showObj = t[sceneID]
else:
returnStr += logHelper("Looking up name "+result.seriesname+" on TVDB", logger.DEBUG)
showObj = t[result.seriesname]
returnStr += logHelper("Got tvdb_id "+str(showObj["id"])+" and series name "+showObj["seriesname"].decode('utf-8')+" from TVDB", logger.DEBUG)
showInfo = (int(showObj["id"]), showObj["seriesname"])
except (tvdb_exceptions.tvdb_exception, IOError), e:
returnStr += logHelper("Unable to look up show on TVDB: "+str(e).decode('utf-8'), logger.DEBUG)
returnStr += logHelper("Looking up show in DB instead", logger.DEBUG)
showInfo = helpers.searchDBForShow(result.seriesname)
if showInfo:
tvdb_id = showInfo[0]
if showInfo and season == None:
myDB = db.DBConnection()
numseasonsSQlResult = myDB.select("SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0", [tvdb_id])
numseasons = numseasonsSQlResult[0][0]
if numseasons == 1 and season == None:
returnStr += logHelper("Don't have a season number, but this show appears to only have 1 season, setting seasonnumber to 1...", logger.DEBUG)
season = 1
# if it is an air-by-date show and we successfully found it on TVDB, convert the date into a season/episode
if season == -1 and showObj:
returnStr += logHelper("Looks like this is an air-by-date show, attempting to parse...", logger.DEBUG)
try:
epObj = showObj.airedOn(episodes[0])[0]
season = int(epObj["seasonnumber"])
episodes = [int(epObj["episodenumber"])]
except tvdb_exceptions.tvdb_episodenotfound, e:
returnStr += logHelper("Unable to find episode with date "+str(episodes[0])+" for show "+showObj["seriesname"]+", skipping", logger.DEBUG)
continue
# if we couldn't get the necessary info from either of the above methods, try the next name
if tvdb_id == None or season == None or episodes == []:
returnStr += logHelper("Unable to get all the necessary info, ended up with tvdb_id "+str(tvdb_id)+", season "+str(season)+", and episodes "+str(episodes)+". Skipping to the next name...", logger.DEBUG)
continue
# find the show in the showlist
try:
showResults = helpers.findCertainShow(sickbeard.showList, showInfo[0])
except exceptions.MultipleShowObjectsException:
raise #TODO: later I'll just log this, for now I want to know about it ASAP
if showResults != None:
returnStr += logHelper("Found the show in our list, continuing", logger.DEBUG)
break
# end for
# if we came out of the loop with not enough info then give up
if tvdb_id == None or season == None or episodes == []:
# if we have a good enough result then fine, use it
returnStr += logHelper("Unable to figure out what this episode is, giving up. Ended up with tvdb_id "+str(tvdb_id)+", season "+str(season)+", and episodes "+str(episodes)+".", logger.DEBUG)
return returnStr
# if we found enough info but it wasn't a show we know about, give up
if showResults == None:
returnStr += logHelper("The episode doesn't match a show in my list - bad naming?", logger.DEBUG)
return returnStr
# if we DO know about the show but its dir is offline, give up
if not os.path.isdir(showResults._location):
returnStr += logHelper("The show dir doesn't exist, canceling postprocessing", logger.DEBUG)
return returnStr
if season == -1:
return returnStr
# search all possible names for our new quality, in case the file or dir doesn't have it
newQuality = Quality.UNKNOWN
for curName in finalNameList:
curNewQuality = Quality.nameQuality(curName)
returnStr += logHelper("Looking up quality for name "+curName+", got "+Quality.qualityStrings[curNewQuality], logger.DEBUG)
# just remember if we find a good quality
if curNewQuality != Quality.UNKNOWN and newQuality == Quality.UNKNOWN:
newQuality = curNewQuality
returnStr += logHelper("saved quality "+Quality.qualityStrings[newQuality], logger.DEBUG)
# if we didn't get a quality from one of the names above, try assuming from each of the names
for curName in finalNameList:
if newQuality != Quality.UNKNOWN:
break
newQuality = Quality.assumeQuality(curName)
returnStr += logHelper("Guessing quality for name "+curName+", got "+Quality.qualityStrings[curNewQuality], logger.DEBUG)
if newQuality != Quality.UNKNOWN:
break
returnStr += logHelper("Unless we're told otherwise, assuming the quality is "+Quality.qualityStrings[newQuality], logger.DEBUG)
rootEp = None
for curEpisode in episodes:
episode = int(curEpisode)
returnStr += logHelper("TVDB thinks the file is tvdb_id = " + str(tvdb_id) + " " + str(season) + "x" + str(episode), logger.DEBUG)
# now that we've figured out which episode this file is just load it manually
try:
curEp = showResults.getEpisode(season, episode)
except exceptions.EpisodeNotFoundException, e:
returnStr += logHelper("Unable to create episode: "+str(e).decode('utf-8'), logger.DEBUG)
return returnStr
if rootEp == None:
rootEp = curEp
rootEp.relatedEps = []
else:
rootEp.relatedEps.append(curEp)
oldStatus = None
# make sure the quality is set right before we continue
if rootEp.status in Quality.SNATCHED + Quality.SNATCHED_PROPER:
oldStatus, newQuality = Quality.splitCompositeStatus(rootEp.status)
returnStr += logHelper("The old status had a quality in it, using that: "+Quality.qualityStrings[newQuality], logger.DEBUG)
else:
for curEp in [rootEp] + rootEp.relatedEps:
curEp.status = Quality.compositeStatus(SNATCHED, newQuality)
# figure out the new filename
biggestFileName = os.path.basename(fileName)
biggestFileExt = os.path.splitext(biggestFileName)[1]
# if we're supposed to put it in a season folder then figure out what folder to use
seasonFolder = ''
if rootEp.show.seasonfolders == True:
# search the show dir for season folders
for curDir in os.listdir(rootEp.show.location):
if not os.path.isdir(os.path.join(rootEp.show.location, curDir)):
continue
# if it's a season folder, check if it's the one we want
match = re.match(".*[Ss]eason\s*(\d+)", curDir)
if match != None:
# if it's the correct season folder then stop looking
if int(match.group(1)) == int(rootEp.season):
seasonFolder = curDir
break
# if we couldn't find the right one then just assume "Season X" format is what we want
if seasonFolder == '':
seasonFolder = 'Season ' + str(rootEp.season)
returnStr += logHelper("Season folders were " + str(rootEp.show.seasonfolders) + " which gave " + seasonFolder, logger.DEBUG)
destDir = os.path.join(rootEp.show.location, seasonFolder)
# movedFilePath is the full path to where we will move the file
movedFilePath = os.path.join(destDir, biggestFileName)
# renamedFilePath is the full path to the renamed file's eventual location
if sickbeard.RENAME_EPISODES:
renamedFilePath = os.path.join(destDir, helpers.sanitizeFileName(rootEp.prettyName())+biggestFileExt)
else:
renamedFilePath = movedFilePath
returnStr += logHelper("The ultimate destination for " + fileName + " is " + renamedFilePath, logger.DEBUG)
existingResult = _checkForExistingFile(renamedFilePath, fileName)
# if there's no file with that exact filename then check for a different episode file (in case we're going to delete it)
if existingResult == 0:
existingResult = _checkForExistingFile(rootEp.location, fileName)
if existingResult == -1:
existingResult = -2
if existingResult == 1:
existingResult = 2
returnStr += logHelper("Existing result: "+str(existingResult), logger.DEBUG)
# see if the existing file is bigger - if it is, bail (unless it's a proper or better quality in which case we're forcing an overwrite)
if existingResult > 0:
if rootEp.status in Quality.SNATCHED_PROPER:
returnStr += logHelper("There is already a file that's bigger at "+renamedFilePath+" but I'm going to overwrite it with a PROPER", logger.DEBUG)
elif oldStatus != None:
returnStr += logHelper("There is already a file that's bigger at "+renamedFilePath+" but I'm going to overwrite it because this one seems to have been downloaded on purpose", logger.DEBUG)
else:
returnStr += logHelper("There is already a file that's bigger at "+renamedFilePath+" - not processing this episode.", logger.DEBUG)
# tag the dir so we know what happened
if downloadDir:
try:
oldDirName = os.path.abspath(downloadDir)
baseDirPath = os.path.dirname(oldDirName)
endDirPath = os.path.basename(oldDirName)
newDirPath = ek.ek(os.path.join, baseDirPath, '_UNDERSIZED_'+endDirPath)
returnStr += logHelper("Renaming the parent folder to indicate that the post process was failed: "+downloadDir+" -> "+newDirPath, logger.DEBUG)
os.rename(oldDirName, newDirPath)
except (OSError, IOError), e:
returnStr += logHelper("Failed renaming " + oldDirName + " to " + newDirPath + ": " + str(e), logger.ERROR)
return returnStr
# if the dir doesn't exist (new season folder) then make it
if not os.path.isdir(destDir):
returnStr += logHelper("Season folder didn't exist, creating it", logger.DEBUG)
os.mkdir(destDir)
if sickbeard.KEEP_PROCESSED_DIR:
returnStr += logHelper("Copying from " + fileName + " to " + destDir, logger.DEBUG)
try:
copyFile(fileName, movedFilePath)
returnStr += logHelper("File was copied successfully", logger.DEBUG)
except (Error, IOError, OSError), e:
returnStr += logHelper("Unable to copy the file: " + str(e), logger.ERROR)
return returnStr
else:
returnStr += logHelper("Moving from " + fileName + " to " + movedFilePath, logger.DEBUG)
try:
moveFile(fileName, movedFilePath)
returnStr += logHelper("File was moved successfully", logger.DEBUG)
except (Error, IOError, OSError), e:
returnStr += logHelper("Unable to move the file: " + str(e), logger.ERROR)
return returnStr
existingFile = None
# if we're deleting a file with a different name then just go ahead
if existingResult in (-2, 2):
existingFile = rootEp.location
if rootEp.status in Quality.SNATCHED_PROPER:
returnStr += logHelper(existingFile + " already exists and is the same size or larger but I'm deleting it to make way for the proper", logger.DEBUG)
else:
returnStr += logHelper(existingFile + " already exists but it's smaller than the new file so I'm replacing it", logger.DEBUG)
elif ek.ek(os.path.isfile, renamedFilePath):
returnStr += logHelper(renamedFilePath + " already exists but it's smaller or the same size as the new file so I'm replacing it", logger.DEBUG)
existingFile = renamedFilePath
if existingFile and ek.ek(os.path.normpath, movedFilePath) != ek.ek(os.path.normpath, existingFile):
deleteAssociatedFiles(existingFile)
# update the statuses before we rename so the quality goes into the name properly
for curEp in [rootEp] + rootEp.relatedEps:
with curEp.lock:
curEp.location = renamedFilePath
curEp.status = Quality.compositeStatus(DOWNLOADED, newQuality)
curEp.saveToDB()
if ek.ek(os.path.normpath, movedFilePath) != ek.ek(os.path.normpath, renamedFilePath):
try:
ek.ek(os.rename, movedFilePath, renamedFilePath)
returnStr += logHelper("Renaming the file " + movedFilePath + " to " + renamedFilePath, logger.DEBUG)
except (OSError, IOError), e:
returnStr += logHelper("Failed renaming " + movedFilePath + " to " + renamedFilePath + ": " + str(e), logger.ERROR)
return returnStr
else:
returnStr += logHelper("Renaming is disabled, leaving file as "+movedFilePath, logger.DEBUG)
# log it to history
history.logDownload(rootEp, fileName)
notifiers.notify(NOTIFY_DOWNLOAD, rootEp.prettyName(True))
# generate nfo/tbn
rootEp.createMetaFiles()
rootEp.saveToDB()
# try updating just show path first
if sickbeard.XBMC_UPDATE_LIBRARY:
for curHost in [x.strip() for x in sickbeard.XBMC_HOST.split(",")]:
if not notifiers.xbmc.updateLibrary(curHost, showName=rootEp.show.name) and sickbeard.XBMC_UPDATE_FULL:
# do a full update if requested
returnStr += logHelper("Update of show directory failed on " + curHost + ", trying full update as requested")
notifiers.xbmc.updateLibrary(curHost)
for curScriptName in sickbeard.EXTRA_SCRIPTS:
script_cmd = shlex.split(curScriptName) + [rootEp.location, biggestFileName, str(tvdb_id), str(season), str(episode), str(rootEp.airdate)]
returnStr += logHelper("Executing command "+str(script_cmd))
try:
p = subprocess.Popen(script_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, err = p.communicate()
returnStr += logHelper("Script result: "+str(out), logger.DEBUG)
except OSError, e:
returnStr += logHelper("Unable to run extra_script: "+str(e).decode('utf-8'))
returnStr += logHelper("Post processing finished successfully", logger.DEBUG)
return [returnStr]