source: trunk/SapphireMovieImporter.m @ 331

Revision 331, 29.2 KB checked in by pmerrill, 6 years ago (diff)
  • Movie Import updated for IMDB's code changes.
Line 
1//
2//  SapphireMovieImporter.m
3//  Sapphire
4//
5//  Created by Patrick Merrill on 9/10/07.
6//  Copyright 2007 www.nanopi.net. All rights reserved.
7//
8
9#import "SapphireMovieImporter.h"
10#import "SapphireMetaData.h"
11#import "NSString-Extensions.h"
12#import "SapphireMovieChooser.h"
13#import "SapphirePosterChooser.h"
14#import "SapphireFrontRowCompat.h"
15#import "SapphireShowChooser.h"
16
17/* Translation Keys */
18#define TRANSLATIONS_KEY                        @"Translations"
19#define IMDB_LINK_KEY                           @"IMDB Link"
20#define IMP_LINK_KEY                            @"IMP Link"
21#define IMP_POSTERS_KEY                         @"IMP Posters"
22#define SELECTED_POSTER_KEY                     @"Selected Poster"
23 /* IMDB XPATHS */
24#define IMDB_SEARCH_XPATH                               @"//td[starts-with(a/@href,'/title')]"
25#define IMDB_UNIQUE_SEARCH_XPATH                @"//a[@class='tn15more inline']/@href"
26#define IMDB_RESULT_LINK_XPATH                  @"a/@href"
27#define IMDB_POSTER_LINK_XPATH                  @"//ul/li/a/@href"
28#define IMDB_RESULT_NAME_XPATH                  @"normalize-space(string())"
29#define IMDB_RESULT_TITLE_YEAR_XPATH    @"//div[@id='tn15title']/h1/replace(string(), '\n', '')"
30#define IMDB_RESULT_INFO_XPATH  @"//div[@class='info']"
31#define IMDB_RESTULT_CAST_NAMES_XPATH   @"//div[@class='info']/table/tr/td/a"
32/* IMP XPATHS */
33#define IMP_POSTER_CANDIDATES_XPATH             @"//img/@src"
34#define IMP_LINK_REDIRECT_XPATH                         @"//head/meta/@content/string()"
35
36
37
38
39/*Delegate class to download cover art*/
40@interface SapphireMovieDataMenuDownloadDelegate : NSObject
41{
42        NSString *destination;
43        NSArray *requestList ;
44        NSMutableArray *delegates ;
45        long downloadsLeft ;
46        id delegate;
47}
48- (id)initWithRequest:(NSArray*)reqList withDestination:(NSString *)dest delegate:(id)aDelegate;
49- (void) downloadDidFinish: (NSURLDownload *) download;
50- (void)downloadMoviePosters ;
51-(void)downloadSingleMoviePoster;
52@end
53
54@interface NSObject (MovieDataDownloadDelegateDelegate)
55- (void)downloadCompleted:(NSURLDownload *)download atIndex:(int)index;
56@end
57
58@implementation SapphireMovieDataMenuDownloadDelegate
59/*!
60* @brief Initialize a cover art downloader
61 *
62 * @param reqList The list of url requests to try
63 * @param dest The path to save the file
64 */
65- (id)initWithRequest:(NSArray*)reqList withDestination:(NSString *)dest delegate:(id)aDelegate;
66{
67        self = [super init];
68        if(!self)
69                return nil;
70        delegates = [NSMutableArray new];
71        destination = [dest retain];
72        requestList = [reqList retain];
73        downloadsLeft=[requestList count];
74        delegate = aDelegate;
75        return self;   
76}
77
78- (void)dealloc
79{
80        [destination release];
81        [requestList release];
82        [delegates release];
83        [super dealloc];
84}
85
86/*!
87 * @brief Fire the delegate to start downloading the posters
88 *
89 */
90-(void)downloadMoviePosters
91{
92        NSEnumerator *reqEnum = [requestList objectEnumerator] ;
93        NSString *req = nil ;
94        while((req = [reqEnum nextObject]) !=nil)
95        {
96                NSURL *posterURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.IMPAwards.com%@",req]];
97                NSString *fullDestination = [NSString stringWithFormat:@"%@/%@", destination, [req lastPathComponent]];
98                NSURLRequest *request = [NSURLRequest requestWithURL:posterURL];
99                NSURLDownload *currentDownload = [[NSURLDownload alloc] initWithRequest:request delegate:self] ;
100                [currentDownload setDestination:fullDestination allowOverwrite:YES];
101                [delegates addObject:currentDownload];
102                [currentDownload release];
103        }
104}
105
106/*!
107 * @brief Fire the delegate to start downloading a single poster
108 *
109 */
110-(void)downloadSingleMoviePoster
111{
112        NSURL *posterURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.IMPAwards.com%@",[requestList objectAtIndex:0]]];
113        NSString *fullDestination = destination;
114        NSURLRequest *request = [NSURLRequest requestWithURL:posterURL];
115        NSURLDownload *currentDownload = [[NSURLDownload alloc] initWithRequest:request delegate:self] ;
116        [currentDownload setDestination:fullDestination allowOverwrite:YES];
117        [delegates addObject:currentDownload];
118        [currentDownload release];
119}
120
121- (void) downloadDidFinish: (NSURLDownload *) download
122{
123        downloadsLeft--;
124        if([delegate respondsToSelector:@selector(downloadCompleted:atIndex:)])
125                [delegate downloadCompleted:download atIndex:[delegates indexOfObject:download]];
126}
127
128@end
129
130@interface SapphireMovieImporter (private)
131- (void)writeSettings;
132@end
133
134@implementation SapphireMovieImporter
135
136- (id) initWithSavedSetting:(NSString *)path
137{
138        self = [super init];
139        if(!self)
140                return nil;
141       
142        /*Get the settings*/
143        settingsPath = [path retain];
144        NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:path];
145        /*Get or create the show translation dict*/
146        movieTranslations = [[settings objectForKey:TRANSLATIONS_KEY] mutableCopy];
147        if(movieTranslations == nil)
148                movieTranslations = [NSMutableDictionary new];
149        /*Cached movie info*/
150        movieInfo = [NSMutableDictionary new];
151       
152        return self;
153}
154
155- (void)dealloc
156{
157        [dataMenu release];
158        [movieTranslations release];
159        [movieInfo release];
160        [settingsPath release];
161        [super dealloc];
162}
163
164/*!
165* @brief Sets the importer's data menu
166 *
167 * @param theDataMenu The importer's menu
168 */
169- (void)setImporterDataMenu:(SapphireImporterDataMenu *)theDataMenu
170{
171        [dataMenu release];
172        dataMenu = [theDataMenu retain];
173}
174
175/*!
176* @brief Gets IMPAwards.com Poster page link
177 *
178 * @param candidateIMDBLink The functions IMDB Posters Path
179 */
180- (NSString *)getPosterPath:(NSString *)candidateIMDBLink
181{
182        NSError *error = nil ;
183        NSURL * url=[NSURL URLWithString:[NSString stringWithFormat:@"http://www.imdb.com%@/posters",candidateIMDBLink]] ;
184        NSXMLDocument *document = [[NSXMLDocument alloc] initWithContentsOfURL:url options:NSXMLDocumentTidyHTML error:&error];
185        NSXMLElement *root = [document rootElement];
186
187        /*Get the results list*/
188        NSArray *results = [root objectsForXQuery:IMDB_POSTER_LINK_XPATH error:&error];
189        if([results count])
190        {
191                /*Get each result*/
192                NSEnumerator *resultEnum = [results objectEnumerator];
193                NSXMLElement *result = nil;
194                while((result = [resultEnum nextObject]) != nil)
195                {
196                        /*Add the result to the list*/                 
197                        NSString *resultURL =[[result stringValue] lowercaseString];
198                        if(resultURL == nil)
199                                continue;
200                        else if([resultURL hasPrefix:@"http://www.impawards.com"])/* See if the link is to IMP */
201                        {
202                                NSString * foundPosterLink =[resultURL stringByReplacingAllOccurancesOf:@"http://www.impawards.com" withString:@""];
203                                return foundPosterLink;
204                        }
205                }               
206        }
207        return nil;
208}
209
210/*!
211* @brief Compile IMPAwards.com Poster link list
212 *
213 * @param posterPageLink The Movie's IMP Poster link extention
214 * @return An array of canidate poster images
215 */
216- (NSArray *)getPosterLinks:(NSString *)posterPageLink
217{
218        NSError *error = nil ;
219        NSURL * url=[NSURL URLWithString:[NSString stringWithFormat:@"http://www.IMPAwards.com%@",posterPageLink]] ;
220        NSXMLDocument *document = [[NSXMLDocument alloc] initWithContentsOfURL:url options:NSXMLDocumentTidyHTML error:&error];
221        NSXMLElement *root = [document rootElement];
222        NSMutableArray * candidatePosterLinks=[NSMutableArray arrayWithObjects:nil] ;
223        NSString * yearPathComponent=[posterPageLink stringByDeletingLastPathComponent];
224       
225        /*Get the results list*/
226        NSArray *results = [root objectsForXQuery:IMP_POSTER_CANDIDATES_XPATH error:&error];
227        if([results count]<1)
228        {
229                /* IMDB had the wrong release year link, see if IMP Tried to redirect*/
230                NSString * newPosterPageLink=[[root objectsForXQuery:IMP_LINK_REDIRECT_XPATH error:&error]objectAtIndex:0] ;
231                NSScanner *trimmer=[NSScanner scannerWithString:newPosterPageLink];
232                [trimmer scanUpToString:@"URL=.." intoString:&yearPathComponent];
233                newPosterPageLink=[newPosterPageLink substringFromIndex:[yearPathComponent length]+6];
234                yearPathComponent=[newPosterPageLink stringByDeletingLastPathComponent];
235                url=[NSURL URLWithString:[NSString stringWithFormat:@"http://www.IMPAwards.com%@",newPosterPageLink]] ;
236                document = [[NSXMLDocument alloc] initWithContentsOfURL:url options:NSXMLDocumentTidyHTML error:&error];
237                root = [document rootElement];
238                results = [root objectsForXQuery:IMP_POSTER_CANDIDATES_XPATH error:&error];
239        }
240
241        if([results count])
242        {
243                /*Get each result*/
244                NSEnumerator *resultEnum = [results objectEnumerator];
245                NSXMLElement *result = nil;
246                while((result = [resultEnum nextObject]) != nil)
247                {
248                        /*Add the result to the list*/                 
249                        NSString *resultURL =[[result stringValue] lowercaseString];
250                        if(resultURL == nil)
251                                continue;
252                        if([resultURL hasPrefix:@"posters/"]) /* get the displayed poster link */
253                        {
254                                NSString * subPath=[resultURL substringFromIndex:7];
255                                subPath=[NSString stringWithFormat:[NSString stringWithFormat:@"%@/posters%@",yearPathComponent,subPath]];
256                                [candidatePosterLinks addObject:subPath];
257                        }
258                        else if([resultURL hasPrefix:@"thumbs/"]) /* get the displayed poster link */
259                        {
260                                NSString * subPath=[resultURL substringFromIndex:11];
261                                subPath=[NSString stringWithFormat:[NSString stringWithFormat:@"%@/posters/%@",yearPathComponent,subPath]];
262                                [candidatePosterLinks addObject:subPath];
263                        }
264                }
265        }
266        if([candidatePosterLinks count])
267        {
268                /* download all posters to the scratch folder */
269                NSString *posterBuffer = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/Poster_Buffer"];
270                [[NSFileManager defaultManager] createDirectoryAtPath:posterBuffer attributes:nil];
271                SapphireMovieDataMenuDownloadDelegate *myDelegate = [[SapphireMovieDataMenuDownloadDelegate alloc] initWithRequest:candidatePosterLinks withDestination:posterBuffer delegate:self];
272                [myDelegate downloadMoviePosters] ;
273                [myDelegate autorelease];
274        }
275        return [[candidatePosterLinks copy] autorelease];
276}
277
278/*!
279 * @brief A download completed
280 *
281 * @param download The download which completed
282 * @param index The index of this poster
283 */
284- (void)downloadCompleted:(NSURLDownload *)download atIndex:(int)index;
285{
286        [posterChooser reloadPoster:index];
287}
288
289/*!
290* @brief Fetch information for a movie
291 *
292 * @param movieTitleLink The IMDB link extention (part of the show's URL)
293 * @param moviePath The movie file's location
294 * @return A cached dictionary of the movie info
295 */
296- (NSMutableDictionary *)getMetaForMovie:(NSString *)movieTitleLink withPath:(NSString*)moviePath
297{
298        NSError *error = nil;
299        NSMutableDictionary *ret = [NSMutableDictionary dictionary];
300       
301        /* Gather IMDB Data */
302        /*Get the movie html*/
303        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.IMDB.com%@",movieTitleLink]];
304        NSXMLDocument *document = [[NSXMLDocument alloc] initWithContentsOfURL:url options:NSXMLDocumentTidyHTML error:&error];
305       
306        /* Get the movie title */
307        NSString *movieTitle= [[document objectsForXQuery:IMDB_RESULT_TITLE_YEAR_XPATH error:&error] objectAtIndex:0];
308        NSScanner *metaTrimmer=[NSScanner scannerWithString:movieTitle];
309        [metaTrimmer scanUpToString:@"(" intoString:&movieTitle];
310        movieTitle=[movieTitle substringToIndex:[movieTitle length]-1];
311       
312        /* Get the User Rating (IMDB) */
313        NSArray *ratingCandidates=[document objectsForXQuery:@"//b/string()" error:&error];
314        NSString *usrRating=[[document objectsForXQuery:@"//b/string()" error:&error] objectAtIndex:[ratingCandidates indexOfObject:@"User Rating:"]+1];
315        metaTrimmer=[NSScanner scannerWithString:usrRating];
316        [metaTrimmer scanUpToString:@"/" intoString:&usrRating];
317       
318        /* Check for IMDB top 250 */
319        NSNumber * top250=nil ;
320        NSArray *top250Candidate=[document objectsForXQuery:@"//div[@class='left']/a/string()" error:&error];
321
322        if([top250Candidate count])
323        {
324                NSString *top250Str=[top250Candidate objectAtIndex:0];
325                if([top250Str hasPrefix:@"Top 250:"])
326                        top250=[NSNumber numberWithInt:[[top250Str substringFromIndex:10] intValue]];
327        }
328               
329        /* Get the release date */
330        NSArray *rawData=[document objectsForXQuery:IMDB_RESULT_INFO_XPATH error:&error];
331        NSDate * releaseDate=nil ;
332        NSString * plot=nil;
333        NSString * mpaaRating=nil;
334        NSNumber * oscarsWon=nil ;
335        NSArray * directors=nil;
336        NSArray * writers=nil;
337        NSArray * genres=nil;
338        if([rawData count])
339        {
340                NSEnumerator *resultEnum = [rawData objectEnumerator];
341                NSXMLElement *result = nil;
342                while((result = [resultEnum nextObject]) != nil)
343                {
344                        NSString *dataCandidate=[result stringValue];
345
346                        if([dataCandidate length])
347                        {
348                                NSString * dataType=nil;
349                                NSScanner * trimmer=[NSScanner scannerWithString:dataCandidate];
350                                [trimmer scanUpToString:@"\n" intoString:&dataType];
351                                if([dataType hasPrefix:@"Release"])
352                                {
353                                        [trimmer scanUpToString:@"(" intoString:&dataCandidate];
354                                        releaseDate=[NSDate dateWithNaturalLanguageString:dataCandidate];
355
356                                }
357                                else if([dataType hasPrefix:@"Writers"])
358                                {
359                                        NSString *writersStr = [[trimmer string] substringFromIndex:[trimmer scanLocation]+1];
360                                        NSMutableArray *mutWrit = [[writersStr componentsSeparatedByString:@"\n"] mutableCopy];
361                                        [mutWrit removeObject:@""];
362                                        writers = [[mutWrit copy] autorelease];
363                                        [mutWrit release];
364                                }
365                                else if([dataType hasPrefix:@"Director"])
366                                {
367                                        NSString *directorsStr = [[trimmer string] substringFromIndex:[trimmer scanLocation]+1];
368                                        NSMutableArray *mutDirs = [[directorsStr componentsSeparatedByString:@"\n"] mutableCopy];
369                                        [mutDirs removeObject:@""];
370                                        directors = [[mutDirs copy] autorelease];
371                                        [mutDirs release];
372                                }
373                                else if([dataType hasPrefix:@"Awards"])
374                                {
375                                        NSString *awardsStr = [[trimmer string] substringFromIndex:[trimmer scanLocation]+1];
376                                        trimmer=[NSScanner scannerWithString:awardsStr];
377                                        [trimmer scanUpToString:@" Oscars." intoString:&awardsStr];
378                                        if([awardsStr length]<[[trimmer string] length])
379                                        {
380                                                awardsStr=[awardsStr substringFromIndex:3];
381                                                oscarsWon=[NSNumber numberWithInt:[awardsStr intValue]];
382                                        }
383                                }
384                                else if([dataType hasPrefix:@"MPAA"])
385                                {
386                                        NSString *mpaaStr = [[trimmer string] substringFromIndex:[trimmer scanLocation]+1];
387                                        if([mpaaStr hasPrefix:@"Rated"])
388                                        {
389                                                trimmer=[NSScanner scannerWithString:[mpaaStr substringFromIndex:6]] ;
390                                                [trimmer scanUpToString:@" " intoString:&mpaaRating];
391                                        }
392                                }
393                                else if([dataType hasPrefix:@"Genre"])
394                                {
395
396                                        NSMutableArray *myGenres=[NSMutableArray array];
397                                        while(![trimmer isAtEnd])
398                                        {
399                                                NSString *aGenre=nil;
400                                                [trimmer scanUpToString:@"/" intoString:&aGenre];
401                                                if(aGenre)
402                                                {
403                                                        if([aGenre isEqualToString:@"/"])
404                                                                continue ;
405                                                        else if([aGenre hasSuffix:@"more\n"])
406                                                                aGenre=[aGenre substringToIndex:[aGenre length]-6];
407                                                        else if([aGenre hasSuffix:@" "])
408                                                                aGenre=[aGenre substringToIndex:[aGenre length]-1];
409                                                        [myGenres addObject:aGenre];
410                                                }
411                                                else
412                                                {
413                                                        [trimmer scanUpToString:@" " intoString:&aGenre];
414                                                }
415                                        }
416                                        genres = [[myGenres copy] autorelease];
417                                }
418                                else if([dataType hasPrefix:@"Plot Outline"])
419                                {
420                                        [trimmer scanUpToString:@"more\n" intoString:&plot];
421                                }
422                                else
423                                        continue ;
424                        }
425                        else
426                                continue ;
427                }
428
429               
430        }
431       
432        /* Get the cast list */
433        NSArray *rawCast=[document objectsForXQuery:IMDB_RESTULT_CAST_NAMES_XPATH error:&error];
434        NSArray *completeCast=nil ;
435        if([rawCast count])
436        {
437                NSMutableArray *results=nil;
438                NSEnumerator *resultEnum = [rawCast objectEnumerator];
439                NSXMLElement *result = nil;
440                while((result = [resultEnum nextObject]) != nil)
441                {
442                        NSString *castName=nil;
443                        castName=[result stringValue];
444                        if([castName length])
445                        {
446                                NSString * castURL=[[[result attributeForName:@"href"]stringValue]lowercaseString];
447                                if([castURL hasPrefix:@"/name/"])
448                                {
449                                        if(!results)
450                                                results=[NSMutableArray arrayWithObject:castName];
451                                        else
452                                                [results addObject:castName];
453                                }
454                                else continue ;
455                        }
456                        else
457                        continue ;
458                }
459                completeCast=[[results copy] autorelease] ;
460        }
461       
462       
463        /* populate metadata to return */
464        [ret setObject:movieTitleLink forKey:META_MOVIE_IDENTIFIER_KEY];
465        if(oscarsWon)
466                [ret setObject:oscarsWon forKey:META_MOVIE_OSCAR_KEY];
467        else
468                [ret setObject:[NSNumber numberWithInt:0] forKey:META_MOVIE_OSCAR_KEY];
469        if(top250)
470                [ret setObject:top250 forKey:META_MOVIE_IMDB_250_KEY];
471        if([usrRating length]>0)
472                [ret setObject:[NSNumber numberWithFloat:[usrRating floatValue]] forKey:META_MOVIE_IMDB_RATING_KEY];
473        if(mpaaRating)
474                [ret setObject:mpaaRating forKey:META_MOVIE_MPAA_RATING_KEY];
475        else
476                [ret setObject:@"NA" forKey:META_MOVIE_MPAA_RATING_KEY];
477        if(directors)
478                [ret setObject:directors forKey:META_MOVIE_DIRECTOR_KEY];
479        if(plot)
480                [ret setObject:plot forKey:META_MOVIE_PLOT_KEY];
481        if(releaseDate)
482                [ret setObject:releaseDate forKey:META_MOVIE_RELEASE_DATE_KEY];
483        if(genres)
484                [ret setObject:genres forKey:META_MOVIE_GENRES_KEY];
485        if(completeCast)
486                [ret setObject:completeCast forKey:META_MOVIE_CAST_KEY];
487        if(movieTitle)
488                [ret setObject:movieTitle forKey:META_MOVIE_TITLE_KEY];
489        return ret;
490}
491
492
493
494/*!
495* @brief Searches for a movie based on the filename
496 *
497 * @param searchStr Part of the filename to use in the show search
498 * @return An array of possible results
499 */
500- (NSArray *)searchResultsForMovie:(NSString *)searchStr
501{
502        /* prep the search string */
503        searchStr = [searchStr stringByDeletingPathExtension];
504        searchStr = [searchStr stringByReplacingAllOccurancesOf:@"_" withString:@" "];
505        searchStr = [searchStr stringByReplacingAllOccurancesOf:@"." withString:@" "];
506        searchStr = [searchStr stringByReplacingAllOccurancesOf:@"-" withString:@" "];
507        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.imdb.com/find?s=all&q=%@", [searchStr URLEncode]]];
508        NSError * error = nil;
509        BOOL uniqueResult=NO ;
510        NSArray * results = nil;
511        NSMutableArray *ret=nil;
512        NSXMLDocument *document = [[NSXMLDocument alloc] initWithContentsOfURL:url options:NSXMLDocumentTidyHTML error:&error];
513        NSXMLElement *root = [document rootElement];   
514        NSString *resultTitle=[[[root objectsForXQuery:@"//title" error:&error]objectAtIndex:0] stringValue];
515       
516        if([resultTitle isEqualToString:@"IMDb Search"])/*Make sure we didn't get back a unique result */
517        {
518                results = [root objectsForXQuery:IMDB_SEARCH_XPATH error:&error];
519                ret = [NSMutableArray arrayWithCapacity:[results count]];
520        }
521        else /* IMDB directly linked to a unique movie title */
522        {
523                uniqueResult=YES ;
524                ret = [NSMutableArray arrayWithCapacity:1];
525                results = [root objectsForXQuery:IMDB_UNIQUE_SEARCH_XPATH error:&error];               
526        }       
527               
528        if([results count])
529        {
530                /*Get each result*/
531                NSEnumerator *resultEnum = [results objectEnumerator];
532                NSXMLElement *result = nil;
533                while((result = [resultEnum nextObject]) != nil)
534                {
535                        if(uniqueResult)/*Check for a unique title link*/
536                        {
537                                NSURL *resultURL = [NSURL URLWithString:[[[result objectsForXQuery:IMDB_UNIQUE_SEARCH_XPATH error:&error] objectAtIndex:0] stringValue]] ;
538                                if(resultURL == nil)
539                                        continue;
540                                NSString *URLSubPath =[resultURL path] ;
541                                if([URLSubPath hasSuffix:@"/releaseinfo"])
542                                {
543                                        URLSubPath=[URLSubPath stringByReplacingAllOccurancesOf:@"/releaseinfo" withString:@"/"];
544                                        URLSubPath=[URLSubPath substringFromIndex:1];
545                                        [ret addObject:[NSDictionary dictionaryWithObjectsAndKeys:
546                                                resultTitle, @"name",
547                                                URLSubPath, IMDB_LINK_KEY,
548                                                nil]];
549                                        return ret ;
550                                }
551                        }
552                        else
553                        {
554                                /*Add the result to the list*/
555                                NSURL *resultURL = [NSURL URLWithString:[[[result objectsForXQuery:IMDB_RESULT_LINK_XPATH error:&error] objectAtIndex:0] stringValue]] ;
556                                NSString * resultTitleValue=[result stringValue];
557                                /* Deal with AKA titles */
558                                if([resultTitleValue hasPrefix:@"\n"])
559                                {
560                                        resultTitleValue=[resultTitleValue substringFromIndex:3];
561                                        resultTitle=[resultTitle stringByReplacingAllOccurancesOf:@"\n" withString:@" "];
562                                //      NSString *enumeratedResultTitle=[resultTitleValue substringFromIndex:3];
563                                //      resultTitleValue=enumeratedResultTitle ;
564                                }
565                                /* Skip image links */
566                                else if(resultURL == nil || [resultTitleValue compare:@" "])
567                                        continue;
568                                /*Skip Video Game titles (VG) */
569                                else if([resultTitleValue hasSuffix:@" (VG) "])
570                                        continue ;
571                                [ret addObject:[NSDictionary dictionaryWithObjectsAndKeys:
572                                        [[result objectsForXQuery:IMDB_RESULT_NAME_XPATH error:&error] objectAtIndex:0], @"name",
573                                        [resultURL path], IMDB_LINK_KEY,
574                                        nil]];
575                        }
576                }
577                if(!uniqueResult)return ret;
578        }
579        return nil ;
580}
581
582
583/*!
584* @brief Write our setings out
585 */
586- (void)writeSettings
587{
588        NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
589                movieTranslations, TRANSLATIONS_KEY,
590                nil];
591        [settings writeToFile:settingsPath atomically:YES];
592}
593
594/*!
595* @brief verify file extention of a file
596 *
597 * @param filePAth The file's path
598 * @return YES if candidate, NO otherwise
599 */
600- (BOOL)isMovieCandidate:(NSString*)fileExt
601{
602        if([[SapphireMetaData videoExtensions] member:fileExt])
603                return YES;
604        else return NO ;
605}
606
607/*!
608* @brief Import a single File
609 *
610 * @param metaData The file to import
611 * @return YES if imported, NO otherwise
612 */
613- (BOOL) importMetaData:(SapphireFileMetaData *)metaData
614{
615        currentData = metaData;
616        /*Check to see if it is already imported*/
617        if([metaData importedTimeFromSource:META_IMDB_IMPORT_KEY])
618                return NO;
619        id controller = [[dataMenu stack] peekController];
620        /* Check to see if we are waiting on the user to select a show title */
621        if([controller isKindOfClass:[SapphireShowChooser class]])
622        {
623                /* Another chooser is on the screen - delay further processing */
624                return NO;
625        }
626        /*Get path*/
627        NSString *path = [metaData path];
628        if(![self isMovieCandidate:[path pathExtension]])
629                return NO;
630        /*Get fineName*/
631        NSString *fileName = [path lastPathComponent];
632        if([metaData fileClass]==FILE_CLASS_TV_SHOW) /* File is a TV Show - skip it */
633                return NO ;
634       
635        /*Get the movie title*/
636        NSString *movieDataLink = nil ;
637        /*Check to see if we know this movie*/
638        NSMutableDictionary *dict=[movieTranslations objectForKey:[fileName lowercaseString]];
639        if(dict == nil)
640        {
641                /*Ask the user what movie this is*/
642                NSArray *movies = [self searchResultsForMovie:fileName];
643                /*Pause for the user's input*/
644                [dataMenu pause];
645                /*Bring up the prompt*/
646                SapphireMovieChooser *chooser = [[SapphireMovieChooser alloc] initWithScene:[dataMenu scene]];
647                [chooser setMovies:movies];
648                [chooser setFileName:fileName];         
649                [chooser setListTitle:BRLocalizedString(@"Select Movie Title", @"Prompt the user for title of movie")];
650                /*And display prompt*/
651                [[dataMenu stack] pushController:chooser];
652                [chooser release];
653                return NO ;
654                //Data will be ready for access on the next call
655        }
656
657        NSString * selectedPoster=nil ;
658        selectedPoster=[dict objectForKey:SELECTED_POSTER_KEY] ;
659        if(!selectedPoster)
660        {
661                /* Posters will be downloaded, let the user choose one */
662                [SapphireFrontRowCompat renderScene:[dataMenu scene]];
663                NSArray *posters=[dict objectForKey:IMP_POSTERS_KEY];
664                if(![posters count])
665                {
666                        NSString *posterPath=nil ;
667                        /* Get the IMP Key with the IMDB Posters page */
668                        posterPath=[self getPosterPath:[dict objectForKey:IMDB_LINK_KEY]] ;
669                        if(posterPath!=nil)
670                        {
671                                [dict setObject:posterPath forKey:IMP_LINK_KEY];
672                                /*We got a posterPath, get the posterLinks */
673                                posters = [self getPosterLinks:posterPath];
674                                if(posters != nil)
675                                {
676                                        /* Add the poster links */
677                                        [dict setObject:posters forKey:IMP_POSTERS_KEY];
678                                        [self writeSettings];
679                                }
680                                /* Add another method via chooser incase IMDB doesn't have an IMP link */
681                        }
682                        else posters=nil ;
683                }
684                if(posters != nil)
685                {
686                        [dataMenu pause];
687                        posterChooser=[[SapphirePosterChooser alloc] initWithScene:[dataMenu scene]];
688                        [posterChooser setPosters:posters] ;
689                        [posterChooser setFileName:fileName];
690                        [posterChooser setListTitle:BRLocalizedString(@"Select Movie Poster", @"Prompt the user for poster selection")];
691                        [[dataMenu stack] pushController:posterChooser];
692                        [posterChooser release];
693                        return NO;
694                }
695        }
696        if(selectedPoster && [dict objectForKey:IMP_POSTERS_KEY])
697        {
698                /* Lets move the selected poster to the corresponding Cover Art Directory */
699                NSFileManager *fileAgent=[NSFileManager defaultManager];
700                NSString * poster=[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/Poster_Buffer"];
701                poster=[poster stringByAppendingPathComponent:[selectedPoster lastPathComponent]];
702                NSString * coverart=[[path stringByDeletingLastPathComponent]stringByAppendingPathComponent:@"Cover Art"];
703                [fileAgent createDirectoryAtPath:coverart attributes:nil];
704                coverart=[coverart stringByAppendingPathComponent:[fileName stringByDeletingPathExtension]];
705                coverart=[coverart stringByAppendingPathExtension:[poster pathExtension]];
706                if([fileAgent fileExistsAtPath:poster])/* See if we need to clean up */
707                {
708                        if([fileAgent fileExistsAtPath:coverart])/* Remove old poster */
709                                [fileAgent removeFileAtPath:coverart handler:self];
710                        [fileAgent movePath:poster toPath:coverart handler:self] ;
711                        /* Lets clean up the Poster_Buffer */
712                        NSArray *oldPosters = [dict objectForKey:IMP_POSTERS_KEY];
713                        if([oldPosters count])
714                        {
715                                NSEnumerator *resultEnum = [oldPosters objectEnumerator];
716                                NSString *result = nil;
717                                while((result = [resultEnum nextObject]) != nil)
718                                {
719                                        BOOL isDir=NO ;
720                                        NSString *removeFile=[NSString stringWithFormat:@"%@/%@",[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/Poster_Buffer"],[result lastPathComponent]];
721                                        [fileAgent fileExistsAtPath:removeFile isDirectory:&isDir];
722                                        if(!isDir)[fileAgent removeFileAtPath:removeFile handler:self] ;
723                                }
724                        }
725                }
726                else if(![fileAgent fileExistsAtPath:coverart])
727                {
728                        /* We have seen this file before, but in a different location */
729                        /* - OR - the coverart has been deleted*/
730                        NSArray * posterList=[NSArray arrayWithObject:selectedPoster];
731                        SapphireMovieDataMenuDownloadDelegate *myDelegate = [[SapphireMovieDataMenuDownloadDelegate alloc] initWithRequest:posterList withDestination:coverart delegate:self];
732                        [myDelegate downloadSingleMoviePoster] ;
733                        [myDelegate autorelease];
734                }
735//              return NO;
736        }
737       
738        /*Import the info*/
739        /*IMDB Data */
740        NSMutableDictionary *infoIMDB = nil;
741        movieDataLink=[dict objectForKey:IMDB_LINK_KEY];
742        infoIMDB = [self getMetaForMovie:movieDataLink withPath:path];
743        if(!infoIMDB)
744                return NO;
745        [infoIMDB removeObjectForKey:IMDB_LINK_KEY];
746        [metaData importInfo:infoIMDB fromSource:META_IMDB_IMPORT_KEY withTime:[[NSDate date] timeIntervalSince1970]];
747        [metaData setFileClass:FILE_CLASS_MOVIE];
748        /*We imported something*/
749        return YES;
750}
751
752
753/*!
754* @brief The completion text to display
755 *
756 * @return The completion text to display
757 */
758- (NSString *)completionText
759{
760        return BRLocalizedString(@"All availble Movie data has been imported", @"The Movie import is complete");
761}
762
763/*!
764* @brief The initial text to display
765 *
766 * @return The initial text to display
767 */
768- (NSString *)initialText
769{
770        return BRLocalizedString(@"Fetch Movie Data", @"Title");
771}
772
773/*!
774* @brief The informative text to display
775 *
776 * @return The informative text to display
777 */
778- (NSString *)informativeText
779{
780        return BRLocalizedString(@"This tool will attempt to fetch information about your Movie files from the Internet (IMDB/IMPAwards).  This procedure may take quite some time and could ask you questions.  You may cancel at any time.", @"Description of the movie import");
781}
782
783/*!
784* @brief The button title
785 *
786 * @return The button title
787 */
788- (NSString *)buttonTitle
789{
790        return BRLocalizedString(@"Start Fetching Data", @"Button");
791}
792
793/*!
794* @brief The data menu was exhumed
795 *
796 * @param controller The Controller which was on top
797 */
798- (void) wasExhumedByPoppingController: (BRLayerController *) controller
799{
800        /*See if it was a movie chooser*/
801        if([controller isKindOfClass:[SapphireMovieChooser class]])
802        {
803                /*Get the user's selection*/
804                SapphireMovieChooser *chooser = (SapphireMovieChooser *)controller;
805                int selection = [chooser selection];
806                if(selection == MOVIE_CHOOSE_CANCEL)
807                {
808                        /*They aborted, skip*/
809                        [dataMenu skipNextItem];
810                }
811                else if(selection == MOVIE_CHOOSE_NOT_MOVIE)
812                {
813                        /*They said it is not a movie, so put in empty data so they are not asked again*/
814                        [currentData importInfo:[NSMutableDictionary dictionary] fromSource:META_IMDB_IMPORT_KEY withTime:[[NSDate date] timeIntervalSince1970]];
815                        if ([currentData fileClass] != FILE_CLASS_TV_SHOW)
816                                [currentData setFileClass:FILE_CLASS_UNKNOWN];
817                }
818                else if(selection==MOVIE_CHOOSE_OTHER)
819                {
820                        [currentData importInfo:[NSMutableDictionary dictionary] fromSource:META_IMDB_IMPORT_KEY withTime:[[NSDate date] timeIntervalSince1970]];
821                        [currentData setFileClass:FILE_CLASS_OTHER] ;
822                }
823                else if(selection==MOVIE_CHOOSE_TV_SHOW)
824                {
825                        [currentData importInfo:[NSMutableDictionary dictionary] fromSource:META_IMDB_IMPORT_KEY withTime:[[NSDate date] timeIntervalSince1970]];
826                        [currentData setFileClass:FILE_CLASS_TV_SHOW] ;
827                }
828                else
829                {
830                        /*They selected a movie title, save the translation and write it*/
831                        NSDictionary *movie = [[chooser movies] objectAtIndex:selection];
832                        NSString *filename = [[chooser fileName] lowercaseString];
833                        NSMutableDictionary * transDict = [movieTranslations objectForKey:filename];
834                        if(transDict == nil)
835                        {
836                                transDict=[NSMutableDictionary new] ;
837                                [movieTranslations setObject:transDict forKey:filename];
838                                [transDict release];
839                        }
840                        /* Add IMDB Key */
841                        [transDict setObject:[movie objectForKey:IMDB_LINK_KEY] forKey:IMDB_LINK_KEY];
842                }
843                [self writeSettings];
844                /*We can resume now*/
845                [dataMenu resume];
846        }
847        else if([controller isKindOfClass:[SapphirePosterChooser class]])
848        {
849                int selectedPoster = [posterChooser selectedPoster];
850                if(selectedPoster == POSTER_CHOOSE_CANCEL)
851                        /*They aborted, skip*/
852                        [dataMenu skipNextItem];
853                else
854                {
855                        NSString *selected = [[posterChooser posters] objectAtIndex:selectedPoster];
856                        NSMutableDictionary * transDict = [movieTranslations objectForKey:[[posterChooser fileName]lowercaseString]];
857                        if(transDict == nil)
858                        {
859                                transDict=[NSMutableDictionary new] ;
860                                [movieTranslations setObject:transDict forKey:[[posterChooser fileName]lowercaseString]];
861                                [transDict release];
862                        }
863                        [transDict setObject:selected forKey:SELECTED_POSTER_KEY];
864                }
865                posterChooser = nil;
866                [self writeSettings];
867                /*We can resume now*/
868                [dataMenu resume];
869        }
870        else
871                return;
872}
873
874@end
Note: See TracBrowser for help on using the repository browser.