processTV.py 25.2 KB
Newer Older
1
2
3
# Author: Nic Wolfe <[email protected]>
# URL: http://code.google.com/p/sickbeard/
#
echel0n's avatar
echel0n committed
4
# This file is part of SickRage.
5
#
echel0n's avatar
echel0n committed
6
# SickRage is free software: you can redistribute it and/or modify
7
8
9
10
# 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.
#
echel0n's avatar
echel0n committed
11
# SickRage is distributed in the hope that it will be useful,
12
13
14
15
16
# 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
echel0n's avatar
echel0n committed
17
# along with SickRage.  If not, see <http://www.gnu.org/licenses/>.
18
19
20
21
22
23
24
25
26
27
28
29

from __future__ import with_statement

import os
import stat

import sickbeard
from sickbeard import postProcessor
from sickbeard import db, helpers, exceptions
from sickbeard import encodingKludge as ek
from sickbeard.exceptions import ex
from sickbeard import logger
30
from sickbeard.name_parser.parser import NameParser, InvalidNameException, InvalidShowException
31
32
33
34
35
36
37
from sickbeard import common

from sickbeard import failedProcessor

from lib.unrar2 import RarFile, RarInfo
from lib.unrar2.rar_exceptions import *

Alexandre Beloin's avatar
Alexandre Beloin committed
38
39
40
41
42
43
import shutil
import lib.shutil_custom

shutil.copyfile = lib.shutil_custom.copyfile_custom


44
45
class ProcessResult:
    def __init__(self):
46
47
48
49
        self.result = True
        self.output = ''
        self.missedfiles = []
        self.aggresult = True
echel0n's avatar
echel0n committed
50

echel0n's avatar
echel0n committed
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def delete_folder(folder, check_empty=True):

    # check if it's a folder
    if not ek.ek(os.path.isdir, folder):
        return False

    # check if it isn't TV_DOWNLOAD_DIR
    if sickbeard.TV_DOWNLOAD_DIR:
        if helpers.real_path(folder) == helpers.real_path(sickbeard.TV_DOWNLOAD_DIR):
            return False

    # check if it's empty folder when wanted checked
    if check_empty:
        check_files = ek.ek(os.listdir, folder)
        if check_files:
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
            logger.log(u"Not deleting folder " + folder + " found the following files: " + str(check_files), logger.INFO)
            return False
        
        try:
            logger.log(u"Deleting folder (if it's empty): " + folder)
            os.rmdir(folder)
        except (OSError, IOError), e:
            logger.log(u"Warning: unable to delete folder: " + folder + ": " + ex(e), logger.WARNING)
            return False
    else:
        try:
            logger.log(u"Deleting folder: " + folder)
            shutil.rmtree(folder)
        except (OSError, IOError), e:
            logger.log(u"Warning: unable to delete folder: " + folder + ": " + ex(e), logger.WARNING)
echel0n's avatar
echel0n committed
81
82
83
84
            return False

    return True

85
def delete_files(processPath, notwantedFiles, result, force=False):
echel0n's avatar
echel0n committed
86

87
88
89
    if not result.result and force:
        result.output += logHelper(u"Forcing deletion of files, even though last result was not success", logger.DEBUG)
    elif not result.result:
echel0n's avatar
echel0n committed
90
91
92
93
94
95
96
97
98
99
        return

    #Delete all file not needed
    for cur_file in notwantedFiles:

        cur_file_path = ek.ek(os.path.join, processPath, cur_file)

        if not ek.ek(os.path.isfile, cur_file_path):
            continue  #Prevent error when a notwantedfiles is an associated files

100
        result.output += logHelper(u"Deleting file " + cur_file, logger.DEBUG)
echel0n's avatar
echel0n committed
101
102
103
104
105

        #check first the read-only attribute
        file_attribute = ek.ek(os.stat, cur_file_path)[0]
        if (not file_attribute & stat.S_IWRITE):
            # File is read-only, so make it writeable
106
            result.output += logHelper(u"Changing ReadOnly Flag for file " + cur_file, logger.DEBUG)
echel0n's avatar
echel0n committed
107
108
109
            try:
                ek.ek(os.chmod, cur_file_path, stat.S_IWRITE)
            except OSError, e:
110
                result.output += logHelper(u"Cannot change permissions of " + cur_file_path + ': ' + str(e.strerror),
echel0n's avatar
echel0n committed
111
112
113
114
                                       logger.DEBUG)
        try:
            ek.ek(os.remove, cur_file_path)
        except OSError, e:
115
            result.output += logHelper(u"Unable to delete file " + cur_file + ': ' + str(e.strerror), logger.DEBUG)
echel0n's avatar
echel0n committed
116

117
def logHelper(logMessage, logLevel=logger.INFO):
118
119
120
    logger.log(logMessage, logLevel)
    return logMessage + u"\n"

echel0n's avatar
echel0n committed
121

122
def processDir(dirName, nzbName=None, process_method=None, force=False, is_priority=None, delete_on=False, failed=False, type="auto"):
123
124
125
    """
    Scans through the files in dirName and processes whatever media files it finds

126
    dirName: The folder name to look in
127
128
129
130
131
132
    nzbName: The NZB name which resulted in this folder being downloaded
    force: True to postprocess already postprocessed files
    failed: Boolean for whether or not the download failed
    type: Type of postprocessing auto or manual
    """

133
    result = ProcessResult()
134

135
    result.output += logHelper(u"Processing folder " + dirName, logger.DEBUG)
136

137
    result.output += logHelper(u"TV_DOWNLOAD_DIR: " + sickbeard.TV_DOWNLOAD_DIR, logger.DEBUG)
138
    postpone = False
139
140
141
142
    # 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)

Nils Vogels's avatar
Nils Vogels committed
143
    # if the client and SickRage are not on the same machine translate the Dir in a network dir
144
145
146
    elif sickbeard.TV_DOWNLOAD_DIR and ek.ek(os.path.isdir, sickbeard.TV_DOWNLOAD_DIR) \
            and ek.ek(os.path.normpath, dirName) != ek.ek(os.path.normpath, sickbeard.TV_DOWNLOAD_DIR):
        dirName = ek.ek(os.path.join, sickbeard.TV_DOWNLOAD_DIR, ek.ek(os.path.abspath, dirName).split(os.path.sep)[-1])
147
        result.output += logHelper(u"Trying to use folder " + dirName, logger.DEBUG)
148
149
150

    # if we didn't find a real dir then quit
    if not ek.ek(os.path.isdir, dirName):
151
        result.output += logHelper(
echel0n's avatar
echel0n committed
152
            u"Unable to figure out what folder to process. If your downloader and SickRage aren't on the same PC make sure you fill out your TV download dir in the config.",
echel0n's avatar
echel0n committed
153
            logger.DEBUG)
154
        return result.output
155
156
157

    path, dirs, files = get_path_dir_files(dirName, nzbName, type)

158
    SyncFiles = filter(helpers.isSyncFile, files)
159

160
161
    # Don't post process if files are still being synced and option is activated
    if SyncFiles and sickbeard.POSTPONE_IF_SYNC_FILES:
162
163
164
        postpone = True
        
    nzbNameOriginal = nzbName
165

166
    if not postpone:
167
        result.output += logHelper(u"PostProcessing Path: " + path, logger.INFO)
168
        result.output += logHelper(u"PostProcessing Dirs: " + str(dirs), logger.DEBUG)
169

170
171
172
173
174
        rarFiles = filter(helpers.isRarFile, files)
        rarContent = unRAR(path, rarFiles, force, result)
        files += rarContent
        videoFiles = filter(helpers.isMediaFile, files)
        videoInRar = filter(helpers.isMediaFile, rarContent)
175

176
177
178
179
        result.output += logHelper(u"PostProcessing Files: " + str(files), logger.DEBUG)
        result.output += logHelper(u"PostProcessing VideoFiles: " + str(videoFiles), logger.DEBUG)
        result.output += logHelper(u"PostProcessing RarContent: " + str(rarContent), logger.DEBUG)
        result.output += logHelper(u"PostProcessing VideoInRar: " + str(videoInRar), logger.DEBUG)
180

181
182
183
        # If nzbName is set and there's more than one videofile in the folder, files will be lost (overwritten).
        if len(videoFiles) >= 2:
            nzbName = None
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
        if not process_method:
            process_method = sickbeard.PROCESS_METHOD
    
        result.result = True
    
        #Don't Link media when the media is extracted from a rar in the same path
        if process_method in ('hardlink', 'symlink') and videoInRar:
            process_media(path, videoInRar, nzbName, 'move', force, is_priority, result)
            delete_files(path, rarContent, result)
            for video in set(videoFiles) - set(videoInRar):
                process_media(path, [video], nzbName, process_method, force, is_priority, result)
        elif sickbeard.DELRARCONTENTS and videoInRar:
            process_media(path, videoInRar, nzbName, process_method, force, is_priority, result)
            delete_files(path, rarContent, result, True)
            for video in set(videoFiles) - set(videoInRar):
                process_media(path, [video], nzbName, process_method, force, is_priority, result)
        else:
            for video in videoFiles:
                process_media(path, [video], nzbName, process_method, force, is_priority, result)
        
    else:
        result.output += logHelper(u"Found temporary sync files, skipping post processing for folder " + str(path), logger.WARNING)
        result.output += logHelper(u"Sync Files: " + str(SyncFiles) + " in path: " + path, logger.WARNING)
        result.missedfiles.append(path + " : Syncfiles found")
        
210
    #Process Video File in all TV Subdir
211
    for dir in [x for x in dirs if validateDir(path, x, nzbNameOriginal, failed, result)]:
212

213
        result.result = True
214
215

        for processPath, processDir, fileList in ek.ek(os.walk, ek.ek(os.path.join, path, dir), topdown=False):
216
217
218
219
            
            if (not validateDir(path, processPath, nzbNameOriginal, failed, result)):
                continue
            
220
221
            postpone = False
            
222
            SyncFiles = filter(helpers.isSyncFile, fileList)
223

224
225
            # Don't post process if files are still being synced and option is activated
            if SyncFiles and sickbeard.POSTPONE_IF_SYNC_FILES:
226
227
228
229
230
231
232
233
234
235
                postpone = True

            if not postpone:
                rarFiles = filter(helpers.isRarFile, fileList)
                rarContent = unRAR(processPath, rarFiles, force, result)
                fileList = set(fileList + rarContent)
                videoFiles = filter(helpers.isMediaFile, fileList)
                videoInRar = filter(helpers.isMediaFile, rarContent)
                notwantedFiles = [x for x in fileList if x not in videoFiles]
                if notwantedFiles:
236
                    result.output += logHelper(u"Found unwanted files: " + str(notwantedFiles), logger.DEBUG)
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    
                #Don't Link media when the media is extracted from a rar in the same path
                if process_method in ('hardlink', 'symlink') and videoInRar:
                    process_media(processPath, videoInRar, nzbName, 'move', force, is_priority, result)
                    process_media(processPath, set(videoFiles) - set(videoInRar), nzbName, process_method, force,
                                  is_priority, result)
                    delete_files(processPath, rarContent, result)
                elif sickbeard.DELRARCONTENTS and videoInRar:
                    process_media(processPath, videoInRar, nzbName, process_method, force, is_priority, result)
                    process_media(processPath, set(videoFiles) - set(videoInRar), nzbName, process_method, force,
                                  is_priority, result)
                    delete_files(processPath, rarContent, result, True)
                else:
                    process_media(processPath, videoFiles, nzbName, process_method, force, is_priority, result)
    
                    #Delete all file not needed
                    if process_method != "move" or not result.result \
254
                            or (type == "manual" and not delete_on):  #Avoid to delete files if is Manual PostProcessing
255
256
257
258
                        continue
    
                    delete_files(processPath, notwantedFiles, result)
    
259
                    if (not sickbeard.NO_DELETE or type == "manual") and process_method == "move" and \
260
261
262
263
                                    ek.ek(os.path.normpath, processPath) != ek.ek(os.path.normpath,
                                                                                  sickbeard.TV_DOWNLOAD_DIR):
                        if delete_folder(processPath, check_empty=True):
                            result.output += logHelper(u"Deleted folder: " + processPath, logger.DEBUG)
264
            else:
265
266
267
268
269
                result.output += logHelper(u"Found temporary sync files, skipping post processing for folder: " + str(processPath), logger.WARNING)
                result.output += logHelper(u"Sync Files: " + str(SyncFiles) + " in path: " + processPath, logger.WARNING)
                result.missedfiles.append(processPath + " : Syncfiles found")
                                
    if result.aggresult:
270
        result.output += logHelper(u"Processing completed")
271
272
273
274
        if result.missedfiles:
            result.output += logHelper(u"I did encounter some unprocessable items: ")
            for missedfile in result.missedfiles:
                result.output += logHelper(u"[" + missedfile + "]")
275
    else:
276
277
278
        result.output += logHelper(u"Problem(s) during processing, failed the following files/folders:  ", logger.WARNING)
        for missedfile in result.missedfiles:
            result.output += logHelper(u"[" + missedfile + "]", logger.WARNING)
279

280
    return result.output
281
282


283
def validateDir(path, dirName, nzbNameOriginal, failed, result):
284

285
    result.output += logHelper(u"Processing folder " + dirName, logger.DEBUG)
286
287

    if ek.ek(os.path.basename, dirName).startswith('_FAILED_'):
288
        result.output += logHelper(u"The directory name indicates it failed to extract.", logger.DEBUG)
289
290
        failed = True
    elif ek.ek(os.path.basename, dirName).startswith('_UNDERSIZED_'):
291
        result.output += logHelper(u"The directory name indicates that it was previously rejected for being undersized.",
echel0n's avatar
echel0n committed
292
                               logger.DEBUG)
293
        failed = True
294
    elif ek.ek(os.path.basename, dirName).upper().startswith('_UNPACK'):
295
        result.output += logHelper(u"The directory name indicates that this release is in the process of being unpacked.",
echel0n's avatar
echel0n committed
296
                               logger.DEBUG)
297
        result.missedfiles.append(dirName + " : Being unpacked")
298
        return False
299
300

    if failed:
301
        process_failed(os.path.join(path, dirName), nzbNameOriginal, result)
302
        result.missedfiles.append(dirName + " : Failed download")
303
304
        return False

305
    if helpers.is_hidden_folder(os.path.join(path, dirName)):
306
        result.output += logHelper(u"Ignoring hidden folder: " + dirName, logger.DEBUG)
307
        result.missedfiles.append(dirName + " : Hidden folder")
echel0n's avatar
echel0n committed
308
309
        return False

310
    # make sure the dir isn't inside a show dir
311
312
    myDB = db.DBConnection()
    sqlResults = myDB.select("SELECT * FROM tv_shows")
313

314
    for sqlShow in sqlResults:
echel0n's avatar
echel0n committed
315
316
317
        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():
318
            result.output += logHelper(
319
                u"Cannot process an episode that's already been moved to its show dir, skipping " + dirName,
echel0n's avatar
echel0n committed
320
                logger.ERROR)
321
322
323
324
325
326
327
328
329
330
331
            return False

    # Get the videofile list for the next checks
    allFiles = []
    allDirs = []
    for processPath, processDir, fileList in ek.ek(os.walk, ek.ek(os.path.join, path, dirName), topdown=False):
        allDirs += processDir
        allFiles += fileList

    videoFiles = filter(helpers.isMediaFile, allFiles)
    allDirs.append(dirName)
332

333
334
335
    #check if the dir have at least one tv video file
    for video in videoFiles:
        try:
336
            NameParser().parse(video, cache_result=False)
337
            return True
338
        except (InvalidNameException, InvalidShowException):
339
340
341
342
            pass

    for dir in allDirs:
        try:
343
            NameParser().parse(dir, cache_result=False)
344
            return True
345
        except (InvalidNameException, InvalidShowException):
346
347
348
349
350
351
352
353
            pass

    if sickbeard.UNPACK:
        #Search for packed release
        packedFiles = filter(helpers.isRarFile, allFiles)

        for packed in packedFiles:
            try:
354
                NameParser().parse(packed, cache_result=False)
355
                return True
356
            except (InvalidNameException, InvalidShowException):
357
                pass
358
            
359
    result.output += logHelper(dirName + " : No processable items found in folder", logger.DEBUG)
360
361
    return False

362
def unRAR(path, rarFiles, force, result):
363
364
365
366
367

    unpacked_files = []

    if sickbeard.UNPACK and rarFiles:

368
        result.output += logHelper(u"Packed Releases detected: " + str(rarFiles), logger.DEBUG)
369
370
371

        for archive in rarFiles:

372
            result.output += logHelper(u"Unpacking archive: " + archive, logger.DEBUG)
373
374
375
376
377
378
379

            try:
                rar_handle = RarFile(os.path.join(path, archive))

                # Skip extraction if any file in archive has previously been extracted
                skip_file = False
                for file_in_archive in [os.path.basename(x.filename) for x in rar_handle.infolist() if not x.isdir]:
380
381
                    if already_postprocessed(path, file_in_archive, force, result):
                        result.output += logHelper(
echel0n's avatar
echel0n committed
382
383
                            u"Archive file already post-processed, extraction skipped: " + file_in_archive,
                            logger.DEBUG)
384
385
386
387
                        skip_file = True
                        break

                if skip_file:
388
389
                    continue

echel0n's avatar
echel0n committed
390
                rar_handle.extract(path=path, withSubpath=False, overwrite=False)
391
392
393
394
395
                for x in rar_handle.infolist():
                    if not x.isdir:
                        basename = os.path.basename(x.filename)
                        if basename not in unpacked_files:
                            unpacked_files.append(basename)
396
                del rar_handle
Alexandre Beloin's avatar
Alexandre Beloin committed
397
398
399
400

            except FatalRARError:
                result.output += logHelper(u"Failed Unrar archive {0}: Unrar: Fatal Error".format(archive), logger.ERROR)
                result.result = False
401
                result.missedfiles.append(archive + " : Fatal error unpacking archive")
Alexandre Beloin's avatar
Alexandre Beloin committed
402
403
404
405
                continue
            except CRCRARError:
                result.output += logHelper(u"Failed Unrar archive {0}: Unrar: Archive CRC Error".format(archive), logger.ERROR)
                result.result = False
406
                result.missedfiles.append(archive + " : CRC error unpacking archive")
Alexandre Beloin's avatar
Alexandre Beloin committed
407
408
409
410
                continue
            except IncorrectRARPassword:
                result.output += logHelper(u"Failed Unrar archive {0}: Unrar: Invalid Password".format(archive), logger.ERROR)
                result.result = False
411
                result.missedfiles.append(archive + " : Password protected RAR")
Alexandre Beloin's avatar
Alexandre Beloin committed
412
413
                continue
            except NoFileToExtract:
414
                result.output += logHelper(u"Failed Unrar archive {0}: Unrar: No file extracted, check the parent folder and destination file permissions.".format(archive), logger.ERROR)
Alexandre Beloin's avatar
Alexandre Beloin committed
415
                result.result = False
416
                result.missedfiles.append(archive + " : Nothing was unpacked (file permissions?)")
Alexandre Beloin's avatar
Alexandre Beloin committed
417
418
419
420
                continue
            except GenericRARError:
                result.output += logHelper(u"Failed Unrar archive {0}: Unrar: Generic Error".format(archive), logger.ERROR)
                result.result = False
421
                result.missedfiles.append(archive + " : Unpacking Failed with a Generic Error")
Alexandre Beloin's avatar
Alexandre Beloin committed
422
                continue
423
            except Exception, e:
424
425
                result.output += logHelper(u"Failed Unrar archive " + archive + ': ' + ex(e), logger.ERROR)
                result.result = False
426
                result.missedfiles.append(archive + " : Unpacking failed for an unknown reason")
echel0n's avatar
echel0n committed
427
                continue
428

429
        result.output += logHelper(u"UnRar content: " + str(unpacked_files), logger.DEBUG)
430
431
432
433

    return unpacked_files


434
def already_postprocessed(dirName, videofile, force, result):
435
436
437
438
439
440
441
442
443

    if force:
        return False

    #Needed for accessing DB with a unicode DirName
    if not isinstance(dirName, unicode):
        dirName = unicode(dirName, 'utf_8')

    # Avoid processing the same dir again if we use a process method <> move
444
445
446
    myDB = db.DBConnection()
    sqlResult = myDB.select("SELECT * FROM tv_episodes WHERE release_name = ?", [dirName])
    if sqlResult:
447
        result.output += logHelper(u"You're trying to post process a dir that's already been processed, skipping",
448
449
                               logger.DEBUG)
        return True
450

echel0n's avatar
echel0n committed
451
    else:
452
453
454
        # This is needed for video whose name differ from dirName
        if not isinstance(videofile, unicode):
            videofile = unicode(videofile, 'utf_8')
455

456
457
        sqlResult = myDB.select("SELECT * FROM tv_episodes WHERE release_name = ?", [videofile.rpartition('.')[0]])
        if sqlResult:
458
            result.output += logHelper(u"You're trying to post process a video that's already been processed, skipping",
459
460
                                   logger.DEBUG)
            return True
461
        
462
        #Needed if we have downloaded the same episode @ different quality
463
        #But we need to make sure we check the history of the episode we're going to PP, and not others
464
        np = NameParser(dirName, tryIndexers=True, trySceneExceptions=True, convert=True)
465
466
467
468
469
470
471
472
        try: #if it fails to find any info (because we're doing an unparsable folder (like the TV root dir) it will throw an exception, which we want to ignore
            parse_result = np.parse(dirName)
        except: #ignore the exception, because we kind of expected it, but create parse_result anyway so we can perform a check on it.
            parse_result = False
            pass
        
        
        search_sql = "SELECT tv_episodes.indexerid, history.resource FROM tv_episodes INNER JOIN history ON history.showid=tv_episodes.showid" #This part is always the same
473
        search_sql += " WHERE history.season=tv_episodes.season and history.episode=tv_episodes.episode"
474
475
476
477
        #If we find a showid, a season number, and one or more episode numbers then we need to use those in the query
        if parse_result and (parse_result.show.indexerid and parse_result.episode_numbers and parse_result.season_number):
            search_sql += " and tv_episodes.showid = '" + str(parse_result.show.indexerid) + "' and tv_episodes.season = '" + str(parse_result.season_number) + "' and tv_episodes.episode = '" + str(parse_result.episode_numbers[0]) + "'"
        
478
479
480
481
        search_sql += " and tv_episodes.status IN (" + ",".join([str(x) for x in common.Quality.DOWNLOADED]) + ")"
        search_sql += " and history.resource LIKE ?"
        sqlResult = myDB.select(search_sql, [u'%' + videofile])
        if sqlResult:
482
            result.output += logHelper(u"You're trying to post process a video that's already been processed, skipping",
483
484
                                   logger.DEBUG)
            return True
485
486
487
488

    return False


489
def process_media(processPath, videoFiles, nzbName, process_method, force, is_priority, result):
490

echel0n's avatar
echel0n committed
491
    processor = None
492
    for cur_video_file in videoFiles:
493
        cur_video_file_path = ek.ek(os.path.join, processPath, cur_video_file)
494

495
        if already_postprocessed(processPath, cur_video_file, force, result):
496
            result.output += logHelper(u"Already Processed " + cur_video_file_path + " : Skipping", logger.DEBUG)
497
498
499
            continue

        try:
500
            processor = postProcessor.PostProcessor(cur_video_file_path, nzbName, process_method, is_priority)
501
            result.result = processor.process()
502
503
            process_fail_message = ""
        except exceptions.PostProcessingFailed, e:
504
            result.result = False
505
506
            process_fail_message = ex(e)

echel0n's avatar
echel0n committed
507
        if processor:
508
            result.output += processor.log
509

510
511
        if result.result:
            result.output += logHelper(u"Processing succeeded for " + cur_video_file_path)
512
        else:
513
            result.output += logHelper(u"Processing failed for " + cur_video_file_path + ": " + process_fail_message,
echel0n's avatar
echel0n committed
514
                                   logger.WARNING)
515
516
            result.missedfiles.append(cur_video_file_path + " : Processing failed: " + process_fail_message)
            result.aggresult = False
517
518


echel0n's avatar
echel0n committed
519
def get_path_dir_files(dirName, nzbName, type):
520
    path = ""
echel0n's avatar
echel0n committed
521
522
    dirs = []
    files = []
523

echel0n's avatar
echel0n committed
524
    if dirName == sickbeard.TV_DOWNLOAD_DIR and not nzbName or type == "manual":  #Scheduled Post Processing Active
525
526
527
528
        #Get at first all the subdir in the dirName
        for path, dirs, files in ek.ek(os.walk, dirName):
            break
    else:
echel0n's avatar
echel0n committed
529
530
531
        path, dirs = ek.ek(os.path.split, dirName)  #Script Post Processing
        if not nzbName is None and not nzbName.endswith('.nzb') and os.path.isfile(
                os.path.join(dirName, nzbName)):  #For single torrent file without Dir
532
533
534
535
536
537
538
539
            dirs = []
            files = [os.path.join(dirName, nzbName)]
        else:
            dirs = [dirs]
            files = []

    return path, dirs, files

echel0n's avatar
echel0n committed
540

541
def process_failed(dirName, nzbName, result):
542
543
544
    """Process a download that did not complete correctly"""

    if sickbeard.USE_FAILED_DOWNLOADS:
545
546
        processor = None

547
548
        try:
            processor = failedProcessor.FailedProcessor(dirName, nzbName)
549
            result.result = processor.process()
550
551
            process_fail_message = ""
        except exceptions.FailedProcessingFailed, e:
552
            result.result = False
553
554
            process_fail_message = ex(e)

555
        if processor:
556
            result.output += processor.log
557

558
        if sickbeard.DELETE_FAILED and result.result:
echel0n's avatar
echel0n committed
559
            if delete_folder(dirName, check_empty=False):
560
                result.output += logHelper(u"Deleted folder: " + dirName, logger.DEBUG)
561

562
563
        if result.result:
            result.output += logHelper(u"Failed Download Processing succeeded: (" + str(nzbName) + ", " + dirName + ")")
564
        else:
565
            result.output += logHelper(
echel0n's avatar
echel0n committed
566
567
                u"Failed Download Processing failed: (" + str(nzbName) + ", " + dirName + "): " + process_fail_message,
                logger.WARNING)