source: branches/CoreData/SapphireFrappliance/MetaDataImporting/SapphireTVShowImporter.m @ 558

Revision 558, 22.9 KB checked in by gbooker, 7 years ago (diff)

Background importer is now working. Leopard file system events watcher is also working

Line 
1/*
2 * SapphireTVShowImporter.m
3 * Sapphire
4 *
5 * Created by Graham Booker on Jun. 30, 2007.
6 * Copyright 2007 Sapphire Development Team and/or www.nanopi.net
7 * All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License as published by the Free Software Foundation; either version 3 of the License,
11 * or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
14 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 * Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with this program; if not,
18 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 */
20
21#import "SapphireTVShowImporter.h"
22#import "SapphireFileMetaData.h"
23#import "NSString-Extensions.h"
24#import "NSFileManager-Extensions.h"
25#import "SapphireShowChooser.h"
26#import "SapphireMovieChooser.h"
27#import "SapphireMetaDataSupport.h"
28#import "SapphireTVTranslation.h"
29#import "SapphireEpisode.h"
30
31/* TVRage XPATHS  */
32#define TVRAGE_SHOWNAME_XPATH @".//h3/text()"
33#define TVRAGE_EPLIST_XPATH @"//*[@class='b']"
34#define TVRAGE_EP_INFO @".//*[@class='b2']/*"
35#define TVRAGE_EP_TEXT @".//*[@class='b2']/text()"
36#define TVRAGE_SCREEN_CAP_XPATH @".//img[contains(@src, 'screencap')]"
37#define TVRAGE_SEARCH_XPATH @"//*[@class='b1']/a"
38#define TVRAGE_UNKNOWN_XPATH @"//*[contains(text(), 'Unknown Page')]"
39
40#define TRANSLATIONS_KEY                @"Translations"
41#define LINK_KEY                                @"Link"
42#define IMG_URL                                 @"imgURL"
43
44/*Delegate class to download cover art*/
45@interface SapphireTVShowDataMenuDownloadDelegate : NSObject
46{
47        NSString *destination;
48}
49- (id)initWithDest:(NSString *)dest;
50@end
51
52@implementation SapphireTVShowDataMenuDownloadDelegate
53/*!
54 * @brief Initialize a cover art downloader
55 *
56 * @param dest The path to save the file
57 */
58- (id)initWithDest:(NSString *)dest
59{
60        self = [super init];
61        if(!self)
62                return nil;
63       
64        destination = [dest retain];
65       
66        return self;
67}
68
69- (void)dealloc
70{
71        [destination release];
72        [super dealloc];
73}
74
75/*!
76 * @brief Delegate Method which prompts for location to save file.  Override and set new
77 * destination
78 *
79 * @param download The downloader
80 * @param filename The suggested filename
81 */
82- (void)download:(NSURLDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename
83{
84        [download setDestination:destination allowOverwrite:YES];
85}
86@end
87 
88@interface SapphireTVShowImporter (private)
89- (void)writeSettings;
90@end
91
92@implementation SapphireTVShowImporter
93
94- (id) initWithContext:(NSManagedObjectContext *)context
95{
96        self = [super init];
97        if(!self)
98                return nil;
99       
100        /*Get the settings*/
101        moc = [context retain];
102        /*Cached show info*/
103        showInfo = [NSMutableDictionary new];
104       
105        /*Initialize the regexes*/
106        regcomp(&letterMarking, "[\\. -]?S[0-9]+E[S0-9]+(-E[0-9]+)?", REG_EXTENDED | REG_ICASE);
107        regcomp(&seasonByEpisode, "[\\. -]?[0-9]+x[S0-9]+(-[0-9]+)?", REG_EXTENDED | REG_ICASE);
108        regcomp(&seasonEpisodeTriple, "[\\. -][0-9]{1,3}[S0-9]{2}[\\. -]", REG_EXTENDED | REG_ICASE);   
109        return self;
110}
111
112- (void)dealloc
113{
114        [moc release];
115        [showInfo release];
116        regfree(&letterMarking);
117        regfree(&seasonByEpisode);
118        regfree(&seasonEpisodeTriple);
119        [super dealloc];
120}
121
122- (void)setImporterDataMenu:(SapphireImporterDataMenu *)theDataMenu
123{
124        dataMenu = theDataMenu;
125}
126
127/*!
128 * @brief Add an episode's info into our cache dict
129 *
130 * @param showName The TV Show's name
131 * @param epTitle The episode's title
132 * @param season The episode's season
133 * @param ep The episodes's episode number within the season
134 * @param summary The episodes's summary
135 * @param eplink The episode's info URL
136 * @param epNumber The absolute episode number
137 * @param airDate The episode's air date
138 * @param imgURL The episode's screenshot URL
139 * @param dict The cache dictionary
140 */
141- (void)addEp:(NSString *)showName title:(NSString *)epTitle season:(int)season epNum:(int)ep summary:(NSString *)summary link:(NSString *)epLink absEpNum:(int)epNumber airDate:(NSDate *)airDate showID:(NSString *)showID imgURL:(NSString *)imgURL toDict:(NSMutableDictionary *)dict
142{
143        /*Set the key by which to store this.  Either by season/ep or season/title*/
144        NSNumber *epNum = [NSNumber numberWithInt:ep];
145        id key = epNum;
146        if(ep == 0)
147                key = [epTitle lowercaseString];
148       
149        /*Get the ep dict*/
150        NSNumber *seasonNum = [NSNumber numberWithInt:season];
151        NSMutableDictionary *epDict = [dict objectForKey:key];
152        if(epDict == nil)
153        {
154                epDict = [NSMutableDictionary new];
155                [dict setObject:epDict forKey:key];
156                [epDict release];
157        }
158        /*Add info*/
159        if(showName)
160        {
161                [epDict setObject:showName forKey:META_SHOW_NAME_KEY] ;
162        }
163        if(ep != 0)
164                [epDict setObject:epNum forKey:META_EPISODE_NUMBER_KEY];
165        if(season != 0)
166        {
167                [epDict setObject:seasonNum forKey:META_SEASON_NUMBER_KEY];
168        }
169        if(epTitle != nil)
170                [epDict setObject:epTitle forKey:META_TITLE_KEY];
171        if(epLink != nil)
172                [epDict setObject:epLink forKey:LINK_KEY];
173        if(showID != nil)
174                [epDict setObject:showID forKey:META_SHOW_IDENTIFIER_KEY];
175        if(summary != nil)
176                [epDict setObject:summary forKey:META_DESCRIPTION_KEY];
177        if(epNumber != nil)
178                [epDict setObject:[NSNumber numberWithInt:epNumber] forKey:META_ABSOLUTE_EP_NUMBER_KEY];
179        if(airDate != nil)
180                [epDict setObject:airDate forKey:META_SHOW_AIR_DATE];
181        if(imgURL != nil)
182                [epDict setObject:imgURL forKey:IMG_URL];
183}
184
185/*!
186 * @brief Fetch information about a season of a show
187 *
188 * @param seriesName The tvrage series name (part of the show's URL)
189 * @param season The season to fech
190 * @return A cached dictionary of the season's episodes
191 */
192- (NSMutableDictionary *)getMetaForSeries:(NSString *)seriesName inSeason:(int)season
193{
194        NSMutableDictionary *ret = [NSMutableDictionary dictionary];
195        NSCharacterSet *decimalSet = [NSCharacterSet decimalDigitCharacterSet];
196        /*Get the season's html*/
197        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.tvrage.com%@/episode_guide/%d", seriesName, season]];
198        NSError *error = nil;
199        NSXMLDocument *document = [[NSXMLDocument alloc] initWithContentsOfURL:url options:NSXMLDocumentTidyHTML error:&error];
200        /* Dump XML document to disk (Dev Only) */
201/*      NSString *documentPath =[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/XML"];
202        [[document XMLDataWithOptions:NSXMLNodePrettyPrint] writeToFile:[NSString stringWithFormat:@"/%@%@.xml",documentPath,seriesName] atomically:YES] ;*/
203        /*Get the episode list*/
204        NSString *showName= nil;
205       
206       
207        NSXMLElement *html = [document rootElement];
208       
209        NSArray *titleArray=[html objectsForXQuery:TVRAGE_SHOWNAME_XPATH error:&error];
210        if([titleArray count])
211        {
212                showName=[[titleArray objectAtIndex:0] stringValue];
213                int length = [showName length];
214                if([showName characterAtIndex:length - 1] == '\n')
215                        showName = [showName substringToIndex:length - 1];
216/*              int index = [showName rangeOfString:@"Season" options:0].location;
217                if(index != NSNotFound)
218                        showName = [showName substringToIndex:index - 1];*/
219        }
220
221        NSArray *eps = [html objectsForXQuery:TVRAGE_EPLIST_XPATH error:&error];
222        NSEnumerator *epEnum = [eps objectEnumerator];
223        NSXMLNode *epNode = nil;
224        while((epNode = [epEnum nextObject]) != nil)
225        {
226                /*Parse the episode's info*/
227                NSString *epTitle = nil;
228                NSString *link = nil;
229                int seasonNum = 0;
230                int ep = 0;
231                int epNumber = 0;
232                NSMutableString *summary = nil;
233                NSDate *airDate = nil;
234                NSString *imageURL = nil;
235               
236                /*Get the info pieces*/
237                NSArray *epInfos = [epNode objectsForXQuery:TVRAGE_EP_INFO error:&error];
238                NSEnumerator *epInfoEnum = [epInfos objectEnumerator];
239                NSXMLNode *epInfo = nil;
240                while((epInfo = [epInfoEnum nextObject]) != nil)
241                {
242                        NSString *nodeName = [epInfo name];
243                        NSArray *summaryObjects = [epInfo objectsForXQuery:@".//font" error:&error];
244                        if([summaryObjects count] && ![nodeName isEqualToString:@"font"])
245                        {
246                                /*Sometimes, the summary is inside formatting, strip*/
247                                epInfo = [summaryObjects objectAtIndex:0];
248                                nodeName = [epInfo name];
249                        }
250                        if(link == nil && [nodeName isEqualToString:@"a"])
251                        {
252                                /*Get the URL*/
253                                link = [[(NSXMLElement *)epInfo attributeForName:@"href"] stringValue];
254                                link = [NSString stringWithFormat:@"http://www.tvrage.com%@", link];
255                                /*Parse the name*/
256                                NSString *epInfoStr = [[epInfo childAtIndex:0] stringValue];
257                                if(epInfoStr != nil)
258                                {
259                                        /*Get the season number and ep numbers*/
260                                        NSScanner *scanner = [NSScanner scannerWithString:epInfoStr];
261                                        NSRange range = [epInfoStr rangeOfString:@" - " options:0];
262                                        if(range.location != NSNotFound)
263                                        {
264                                                [scanner scanInt:&epNumber];
265                                                [scanner scanUpToCharactersFromSet:decimalSet intoString:nil];
266                                                [scanner scanInt:&seasonNum];
267                                                [scanner scanUpToCharactersFromSet:decimalSet intoString:nil];
268                                                [scanner scanInt:&ep];
269                                                [scanner setScanLocation:range.length + range.location];
270                                                if(seasonNum == 0)
271                                                        seasonNum = season;
272                                        }
273                                        else
274                                                seasonNum = season;
275                                        epTitle = [epInfoStr substringFromIndex:[scanner scanLocation]];
276                                }
277                        }
278                        else if(summary == nil && [nodeName isEqualToString:@"font"])
279                        {
280                                /*Get the summary*/
281                                NSArray *summaries = [epInfo objectsForXQuery:@"replace(string(), '\n\n', '\n')" error:&error];
282                                summary = [NSMutableString string];
283                                NSEnumerator *sumEnum = [summaries objectEnumerator];
284                                NSXMLNode *sum = nil;
285                                while((sum = [sumEnum nextObject]) != nil)
286                                        [summary appendFormat:@"\n%@", sum];
287                                if([summary length] > 3 && [[summary substringFromIndex:3] isEqualToString:@"No Summary (Add Here)"])
288                                        summary = nil;
289                                if([summary length])
290                                        [summary deleteCharactersInRange:NSMakeRange(0,1)];
291                                else
292                                        summary = nil;
293                        }
294                        else if(imageURL == nil)
295                        {
296                                NSArray *images = [epInfo objectsForXQuery:TVRAGE_SCREEN_CAP_XPATH error:&error];
297                                if([images count])
298                                {
299                                        imageURL = [[(NSXMLElement *)[images objectAtIndex:0] attributeForName:@"src"] stringValue];
300                                }
301                        }
302                }
303                epInfos = [epNode objectsForXQuery:TVRAGE_EP_TEXT error:&error];
304                epInfoEnum = [epInfos objectEnumerator];
305                epInfo = nil;
306                while((epInfo = [epInfoEnum nextObject]) != nil)
307                {
308                        /*Get the air date*/
309                        NSString *nodeName = [epInfo stringValue];
310                        if ([nodeName hasPrefix:@" ("] && [nodeName hasSuffix:@") "])
311                        {
312                                NSString *subStr = [nodeName substringWithRange:NSMakeRange(2, [nodeName length] - 4)];
313                               
314                                airDate = [NSDate dateWithNaturalLanguageString:subStr];
315                                if([airDate timeIntervalSince1970] == 0)
316                                        airDate = nil;
317                                else
318                                        break;
319                        }
320                }
321                /*Add to cache*/
322                [self addEp:showName title:epTitle season:seasonNum epNum:ep summary:summary link:link absEpNum:epNumber airDate:airDate showID:seriesName imgURL:imageURL toDict:ret];
323        }
324        return ret;
325}
326
327/*!
328 * @brief Searches for a show based on the filename
329 *
330 * @param searchStr Part of the filename to use in the show search
331 * @return An array of possible results
332 */
333- (NSArray *)searchResultsForSeries:(NSString *)searchStr
334{
335        /*Load the search info*/
336        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.tvrage.com/search.php?search=%@&sonly=1", [searchStr URLEncode]]];
337        NSError *error = nil;
338        NSXMLDocument *document = [[NSXMLDocument alloc] initWithContentsOfURL:url options:NSXMLDocumentTidyHTML error:&error];
339       
340        /*Get the results list*/
341        NSXMLElement *root = [document rootElement];
342        NSArray *results = [root objectsForXQuery:TVRAGE_SEARCH_XPATH error:&error];
343        NSMutableArray *ret = [NSMutableArray arrayWithCapacity:[results count]];
344        if([results count])
345        {
346                /*Get each result*/
347                NSEnumerator *resultEnum = [results objectEnumerator];
348                NSXMLElement *result = nil;
349                while((result = [resultEnum nextObject]) != nil)
350                {
351                        /*Add the result to the list*/
352                        NSURL *resultURL = [NSURL URLWithString:[[result attributeForName:@"href"] stringValue]];
353                        if(resultURL == nil)
354                                continue;
355                        [ret addObject:[NSDictionary dictionaryWithObjectsAndKeys:
356                                [[result childAtIndex:0] stringValue], @"name",
357                                [resultURL path], LINK_KEY,
358                                nil]];
359                }
360                return ret;
361        }
362        /*No results found*/
363        return nil;
364}
365
366/*!
367 * @brief Fetch cached information about a show's season, and if none, fetch it
368 *
369 * @param show The tvrage series name
370 * @param season The season to fetch
371 * @return A dictionary with info about the season
372 */
373- (NSMutableDictionary *)getInfo:(NSString *)show forSeason:(int)season
374{
375        /*Get the show's info*/
376        NSMutableDictionary *showDict = [showInfo objectForKey:show];
377        NSMutableDictionary *seasonDict = nil;
378        NSNumber *seasonNum = [NSNumber numberWithInt:season];
379        if(!showDict)
380        {
381                showDict = [NSMutableDictionary new];
382                [showInfo setObject:showDict forKey:show];
383                [showDict release];
384        }
385        else
386                /*Get the season's info*/
387                seasonDict = [showDict objectForKey:seasonNum];
388        if(!seasonDict)
389        {
390                /*Not in cache, so fetch it*/
391                seasonDict = [self getMetaForSeries:show inSeason:season];
392                if(seasonDict != nil)
393                        /*Put the result in cache*/
394                        [showDict setObject:seasonDict forKey:seasonNum];
395        }
396        /*Return the info*/
397        return seasonDict;
398}
399
400/*!
401 * @brief Get info about a show's episode
402 *
403 * @param show The tvrage show name
404 * @param season The episode's season
405 * @param ep The episode's episode number
406 * @return The episode's info
407 */
408- (NSMutableDictionary *)getInfo:(NSString *)show forSeason:(int)season episode:(int)ep
409{
410        NSNumber *epNum = [NSNumber numberWithInt:ep];
411        return [NSMutableDictionary dictionaryWithDictionary:[[self getInfo:show forSeason:season] objectForKey:epNum]];
412}
413
414/*!
415 * @brief Get info about a show's episode which doesn't have an episode number (specials)
416 *
417 * @param show The tvrage show name
418 * @param season The episode's season
419 * @param epTitle The episode's title
420 * @return The episode's info
421 */
422- (NSMutableDictionary *)getInfo:(NSString *)show forSeason:(int)season episodeTitle:(NSString *)epTitle
423{
424        return [NSMutableDictionary dictionaryWithDictionary:[[self getInfo:show forSeason:season] objectForKey:[epTitle lowercaseString]]];
425}
426
427/*!
428 * @brief Write our setings out
429 */
430- (void)writeSettings
431{
432        NSError *error = nil;
433        [moc save:&error];
434}
435
436- (void)combine:(NSMutableDictionary *)info with:(NSMutableDictionary *)info2
437{
438        NSMutableDictionary *tdict = [info2 mutableCopy];
439        [tdict addEntriesFromDictionary:info];
440        NSString *secname = [info2 objectForKey:META_TITLE_KEY];
441        NSString *origname = [info objectForKey:META_TITLE_KEY];
442        if(secname != nil && origname != nil)
443                [tdict setObject:[NSString stringWithFormat:@"%@ / %@", origname, secname] forKey:META_TITLE_KEY];
444
445        if([info objectForKey:META_EPISODE_NUMBER_KEY] != nil)
446        {
447                NSNumber *secondEp = [info2 objectForKey:META_EPISODE_NUMBER_KEY];
448                [tdict setObject:secondEp forKey:META_EPISODE_2_NUMBER_KEY];
449        }
450        NSString *secdesc = [info2 objectForKey:META_DESCRIPTION_KEY];
451        NSString *origdesc = [info objectForKey:META_DESCRIPTION_KEY];
452        if(secdesc != nil && origdesc != nil)
453                [tdict setObject:[NSString stringWithFormat:@"%@ / %@", origdesc, secdesc] forKey:META_DESCRIPTION_KEY];
454
455        if([info objectForKey:META_ABSOLUTE_EP_NUMBER_KEY] != nil)
456        {
457                NSNumber *secondEp = [info2 objectForKey:META_ABSOLUTE_EP_NUMBER_KEY];
458                [tdict setObject:secondEp forKey:META_ABSOLUTE_EP_2_NUMBER_KEY];
459        }
460       
461        [info addEntriesFromDictionary:tdict];
462        [tdict release];
463}
464
465- (ImportState) importMetaData:(SapphireFileMetaData *)metaData
466{
467        currentData = metaData;
468        /*Check to see if it is already imported*/
469        if([metaData importTypeValue] & IMPORT_TYPE_TVSHOW_MASK)
470                return IMPORT_STATE_NOT_UPDATED;
471        id controller = [[dataMenu stack] peekController];
472        /* Check to see if we are waiting on the user to select a movie title */
473        if(controller != nil && ![controller isKindOfClass:[SapphireImporterDataMenu class]])
474        {
475                /* Another chooser is on the screen - delay further processing */
476                return IMPORT_STATE_NOT_UPDATED;
477        }
478        /*Get path*/
479        NSString *path = [metaData path];
480//      NSArray *pathComponents = [path pathComponents];
481        NSString *fileName = [path lastPathComponent];
482       
483        /*Check regexes to see if this is a tv show*/
484        int index = NSNotFound;
485        int secondEp = -1;
486        regmatch_t matches[3];
487        NSData *fileNameData = [fileName dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
488        const char *theFileName = [fileNameData bytes];
489        NSString *scanString = nil;
490        if(!regexec(&letterMarking, theFileName, 3, matches, 0))
491        {
492                index = matches[0].rm_so;
493                scanString = [fileName substringFromIndex:index];
494                secondEp = matches[1].rm_so;
495        }
496        else if(!regexec(&seasonByEpisode, theFileName, 3, matches, 0))
497        {
498                index = matches[0].rm_so;
499                scanString = [fileName substringFromIndex:index];
500                secondEp = matches[1].rm_so;
501        }
502        else if(!regexec(&seasonEpisodeTriple, theFileName, 3, matches, 0))
503        {
504                index = matches[0].rm_so;
505                /*Insert an artificial season/ep seperator so things are easier later*/
506                NSMutableString *tempStr = [fileName mutableCopy];
507//              if(index > [tempStr length] || index <= 0 )return NO;
508                [tempStr deleteCharactersInRange:NSMakeRange(0, index+1)];
509                [tempStr insertString:@"x" atIndex:matches[0].rm_eo - index - 4];
510                scanString = [tempStr autorelease];
511        }
512       
513        /*See if we found a match*/
514        if(index == NSNotFound)
515                return IMPORT_STATE_NOT_UPDATED;
516       
517        /*Get the show title*/
518        NSString *searchStr = [fileName substringToIndex:index];
519        /*Check to see if we know this title*/
520        SapphireTVTranslation *tran = [SapphireTVTranslation tvTranslationForName:[searchStr lowercaseString] inContext:moc];
521        if([tran showPath] == nil)
522        {
523                if(dataMenu == nil)
524                        /*There is no data menu, background import. So we can't ask user, skip*/
525                        return IMPORT_STATE_NOT_UPDATED;
526                /*Ask the user what show this is*/
527                NSArray *shows = [self searchResultsForSeries:searchStr];
528                /*Bring up the prompt*/
529                SapphireShowChooser *chooser = [[SapphireShowChooser alloc] initWithScene:[dataMenu scene]];
530                [chooser setShows:shows];
531                [chooser setFileName:fileName];
532                [chooser setListTitle:BRLocalizedString(@"Select Show Title", @"Prompt the user for showname with a file")];
533                [chooser setSearchStr:searchStr];
534                /*And display prompt*/
535                [[dataMenu stack] pushController:chooser];
536                [chooser release];
537                return IMPORT_STATE_NEEDS_SUSPEND;
538        }
539       
540        int season = 0;
541        int ep = 0;
542        /*Get the season*/
543        NSScanner *scanner = [NSScanner scannerWithString:scanString];
544        NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];
545        [scanner scanUpToCharactersFromSet:digits intoString:nil];
546        [scanner scanInt:&season];
547        /*Get the episode number*/
548        NSString *skipped = nil;
549        [scanner scanUpToCharactersFromSet:digits intoString:&skipped];
550        [scanner scanInt:&ep];
551        /*Was there an S before the episode number?*/
552        if([skipped hasSuffix:@"S"])
553                ep = 0;
554       
555        int overriddenSeason = [metaData searchSeasonNumber];
556        if(overriddenSeason != -1)
557                season = overriddenSeason;
558
559        int overriddenEpisode = [metaData searchEpisodeNumber];
560        if(overriddenEpisode != -1)
561                ep = overriddenEpisode;
562
563        /*No season, no info*/
564        if(season == 0)
565                return IMPORT_STATE_NOT_UPDATED;
566       
567        int otherEp = 0;
568        if(secondEp != -1)
569        {
570                [scanner setScanLocation:secondEp - index];
571                [scanner scanUpToCharactersFromSet:digits intoString:nil];
572                [scanner scanInt:&otherEp];
573        }
574       
575        overriddenEpisode = [metaData searchLastEpisodeNumber];
576        if(overriddenEpisode != -1)
577                otherEp = overriddenEpisode;
578
579        /*Get the episode's info*/
580        NSMutableDictionary *info = nil, *info2 = nil;
581        if(ep != 0)
582        {
583                /*Match on s/e*/
584                info = [self getInfo:[tran showPath] forSeason:season episode:ep];
585                if(otherEp != 0)
586                        info2 = [self getInfo:[tran showPath] forSeason:season episode:otherEp];
587        }
588        else
589        {
590                /*Match on show title*/
591                NSString *showTitle = nil;
592                [scanner scanUpToCharactersFromSet:[NSCharacterSet letterCharacterSet] intoString:nil];
593                if([scanner scanUpToString:@"." intoString:&showTitle])
594                        info = [self getInfo:[tran showPath] forSeason:season episodeTitle:showTitle];
595        }
596        /*No info, well, no info*/
597        if(!info)
598                return IMPORT_STATE_NOT_UPDATED;
599               
600        /* Lets process the cover art directory structure */
601        NSString * previewArtPath=[NSString stringWithFormat:@"%@/@TV/%@/%@",
602                                                                        [SapphireMetaDataSupport collectionArtPath],
603                                                                        [info objectForKey:META_SHOW_NAME_KEY],
604                                                                        [NSString stringWithFormat:@"Season %d",[[info objectForKey:META_SEASON_NUMBER_KEY] intValue]]];
605                                               
606        [[NSFileManager defaultManager] constructPath:previewArtPath];
607        /*Check for screen cap locally and on server*/
608        NSString *imgURL = [info objectForKey:IMG_URL];
609        NSString *newPath = nil;
610        if(ep != 0)
611                newPath = [previewArtPath stringByAppendingFormat:@"/Episode %d", ep];
612        else
613                newPath = [previewArtPath stringByAppendingPathComponent:[info objectForKey:META_TITLE_KEY]];
614        NSString *imageDestination = [newPath stringByAppendingPathExtension:@"jpg"];
615        BOOL isDir = NO;
616        BOOL imageExists = [[NSFileManager defaultManager] fileExistsAtPath:imageDestination isDirectory:&isDir] && !isDir;
617        if(imgURL && !imageExists)
618        {
619                /*Download the screen cap*/
620                NSURL *imageURL = [NSURL URLWithString:imgURL];
621                NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
622                SapphireTVShowDataMenuDownloadDelegate *myDelegate = [[SapphireTVShowDataMenuDownloadDelegate alloc] initWithDest:imageDestination];
623                [[NSURLDownload alloc] initWithRequest:request delegate:myDelegate];
624                [myDelegate release];
625        }
626       
627        if(info2 != nil)
628                [self combine:info with:info2];
629        /*Import the info*/
630        [info removeObjectForKey:LINK_KEY];
631        SapphireEpisode *episode = [SapphireEpisode episodeWithDictionary:info inContext:moc];
632        [metaData setTvEpisode:episode];
633        [tran setTvShow:[episode tvShow]];
634       
635        /*We imported something*/
636        return IMPORT_STATE_UPDATED;
637}
638
639- (NSString *)completionText
640{
641        return BRLocalizedString(@"All availble TV Show data has been imported", @"The TV Show import complete");
642}
643
644- (NSString *)initialText
645{
646        return BRLocalizedString(@"Fetch TV Show Data", @"Title");
647}
648
649- (NSString *)informativeText
650{
651        return BRLocalizedString(@"This tool will attempt to fetch information about your TV shows files from the Internet (TVRage).  This procedure may take quite some time and could ask you questions.  You may cancel at any time.", @"Description of the movie import");
652}
653
654- (NSString *)buttonTitle
655{
656        return BRLocalizedString(@"Start Fetching Data", @"Button");
657}
658
659- (void) wasExhumedByPoppingController: (BRLayerController *) controller
660{
661        /*See if it was a show chooser*/
662        if(![controller isKindOfClass:[SapphireShowChooser class]])
663                return;
664       
665        /*Get the user's selection*/
666        SapphireShowChooser *chooser = (SapphireShowChooser *)controller;
667        int selection = [chooser selection];
668        if(selection == SHOW_CHOOSE_CANCEL)
669                /*They aborted, skip*/
670                [dataMenu skipNextItem];
671        else if(selection == SHOW_CHOOSE_NOT_SHOW)
672        {
673                /*They said it is not a show, so put in empty data so they are not asked again*/
674                [currentData importInfo:[NSMutableDictionary dictionary] fromSource:IMPORT_TYPE_TVSHOW_MASK withTime:[[NSDate date] timeIntervalSince1970]];
675                if ([currentData fileClassValue] == FILE_CLASS_TV_SHOW)
676                        [currentData setFileClassValue:FILE_CLASS_UNKNOWN];
677        }
678        else
679        {
680                /*They selected a show, save the translation and write it*/
681                NSDictionary *show = [[chooser shows] objectAtIndex:selection];
682                [SapphireTVTranslation createTVTranslationForName:[[chooser searchStr] lowercaseString] withPath:[show objectForKey:LINK_KEY] inContext:moc];
683                [self writeSettings];
684        }
685        /*We can resume now*/
686        [dataMenu resume];
687}
688
689@end
Note: See TracBrowser for help on using the repository browser.