source: trunk/SapphireFrappliance/SapphireTVShowImporter.m @ 527

Revision 527, 23.0 KB checked in by gbooker, 7 years ago (diff)

Switched to getting the screenshot url out of the ep list. This is far faster, and actually more reliable now that tvrage is doing the preview movies on the ep page.

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