Archived
1
This repository has been archived on 2022-08-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
ilyrics/iLyrics/Magistrix.m
Kim Wittenburg e4fdd7e306 Release 1.0
iLyrics functionality added
Magistrix Lyrics Hoster added

Release 1.0.1
Added Split View in Main Window
Some little code changes
2012-06-16 16:29:56 +02:00

211 lines
10 KiB
Objective-C

//
// Magistrix.m
// iLyrics
//
// Created by Kim Wittenburg on 14.06.12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
//
//TODO: Use correct Date
#import "Magistrix.h"
typedef enum {
LyricsPage,
ResultsPage,
NoResultsPage,
UnknownPage
} PageType;
@implementation Magistrix {
NSString *query;
int loadedResults;
int resultCount;
}
-(NSString*) name {
return @"Magistrix";
}
-(NSDate *)hosterVersion {
return [NSDate dateWithString:@"2012-06-16 11:00:00 +0100"];
}
-(void) startNewSearchForQuery: (NSString*) q {
[self resetLoadedResults];
query = q;
}
-(BOOL) hasMoreResults {
return loadedResults < resultCount;
}
-(NSArray*) nextResults {
int site = (loadedResults/10) + 1;
NSString *searchPath = [NSString stringWithFormat:@"http://www.magistrix.de/lyrics/search?q=%@&page=%i", [query stringByReplacingOccurrencesOfString:@" " withString:@"+"], site];
NSURL *searchURL = [NSURL URLWithString:searchPath];
NSError *error;
NSString *page = [NSString stringWithContentsOfURL:searchURL encoding:NSUTF8StringEncoding error:&error];
if (error) {
return nil;
}
PageType pType = [self typeOfPage:page];
if (pType == LyricsPage) {
resultCount = 1;
loadedResults = 1;
return [NSArray arrayWithObject:[self searchResultFromLyricsPage:page atURL:searchURL]];
} else if (pType == ResultsPage) {
[self shouldSetResultCountFromPage:page];
return [self searchResultsFromPage:page];
} else if (pType == NoResultsPage) {
return [[NSArray alloc] init];
} else {
NSRunAlertPanel(NSLocalizedString(@"Magistrix.messages.unknownPage.title", @""), NSLocalizedString(@"Magistrix.messages.unknownPage.detail", @""), NSLocalizedString(@"OK", @""), nil, nil);
return [[NSArray alloc] init];
}
}
-(PageType) typeOfPage: (NSString *) page {
if ([page rangeOfString:@"<title>Songtext-Suche</title>"].location != NSNotFound) {
if ([page rangeOfString:@"<div class='empty_collection'>"].location != NSNotFound) {
return NoResultsPage;
} else {
return ResultsPage;
}
}
if ([page rangeOfString:@"<div id='songtext'>"].location != NSNotFound) {
return LyricsPage;
}
return UnknownPage;
}
-(SearchResult*) searchResultFromLyricsPage: (NSString *) page atURL: (NSURL *) url{
int headingStart = NSMaxRange([page rangeOfString:@"<h1>"]);
int headingEnd = [page rangeOfString:@"</h1>"].location;
int artistStart = NSMaxRange([page rangeOfString:@">" options:NSCaseInsensitiveSearch range:NSMakeRange(headingStart, headingEnd-headingStart)]);
NSRange artistEndTag = [page rangeOfString:@"</a>" options:NSCaseInsensitiveSearch range:NSMakeRange(artistStart, headingEnd-artistStart)];
int artistEnd = artistEndTag.location;
int songNameStart = NSMaxRange(artistEndTag);
int songNameEnd = headingEnd;
NSString *artist = [page substringWithRange:NSMakeRange(artistStart, artistEnd-artistStart)];
NSString *songName = [page substringWithRange:NSMakeRange(songNameStart, songNameEnd-songNameStart)];
//Remove the " Lyric" and the " &ndash; " from the Song name
songName = [[songName substringToIndex:[songName length]-[@" Lyric" length]] substringFromIndex:[@" &ndash; " length]];
NSString *preview = [self lyricsFromPage:page];
return [[SearchResult alloc]initWithName:songName fromArtist:artist preview:preview link:url];
}
-(NSArray*) searchResultsFromPage: (NSString *) page {
int resultsTableStart = NSMaxRange([page rangeOfString:@"<table>"]);
int resultsTableEnd = [page rangeOfString:@"</table>"].location;
NSArray *resultTags = [self resultTagsFromTable:[page substringWithRange:NSMakeRange(resultsTableStart, resultsTableEnd-resultsTableStart)]];
NSMutableArray *searchResults = [[NSMutableArray alloc] init];
for (NSString *tag in resultTags) {
[searchResults addObject:[self searchResultFromResultTag:tag]];
}
//Increase loadedResults by 10 which is a full results site
//Even if there are less than 10 results on a page (would not have any effect)
loadedResults += 10;
return searchResults;
}
-(NSArray*) resultTagsFromTable: (NSString *) table {
NSRange restRange = NSMakeRange(0, [table length]);
NSMutableArray *tags = [[NSMutableArray alloc] init];
NSUInteger currentIndex = [table rangeOfString:@"<td>"].location;
while (currentIndex != NSNotFound) {
int startIndex = currentIndex + [@"<td>" length];
int endIndex = [table rangeOfString:@"</td>" options:NSCaseInsensitiveSearch range:restRange].location;
NSRange tagRange = NSMakeRange(startIndex, endIndex-startIndex);
[tags addObject:[table substringWithRange:tagRange]];
restRange = [self restRangeFromString:table subtractingRange:tagRange];
restRange.length -= [@"</td>" length];
restRange.location += [@"</td>" length];
currentIndex = [table rangeOfString:@"<td>" options:NSCaseInsensitiveSearch range:restRange].location;
}
return tags;
}
-(SearchResult*) searchResultFromResultTag: (NSString *) tag {
NSRange artistStartRange = [tag rangeOfString:@">"];
int artistEndIndex = [tag rangeOfString:@"<" options:NSCaseInsensitiveSearch range:[self restRangeFromString:tag subtractingRange:artistStartRange]].location;
int artistStartIndex = NSMaxRange(artistStartRange);
NSString *artist = [tag substringWithRange:NSMakeRange(artistStartIndex, artistEndIndex-artistStartIndex)];
NSRange restRange = [self restRangeFromString:tag subtractingRange:NSMakeRange(artistEndIndex, [@"</a>" length])];
NSRange songNameTagStartRange = [tag rangeOfString:@"<a href=\"" options:NSCaseInsensitiveSearch range:restRange];
int linkStart = NSMaxRange(songNameTagStartRange);
NSRange linkEndRage = [tag rangeOfString:@"\"" options:NSCaseInsensitiveSearch range:[self restRangeFromString:tag subtractingRange:songNameTagStartRange]];
NSURL *link = [self urlFromHref:[tag substringWithRange:NSMakeRange(linkStart, linkEndRage.location-linkStart)]];
int songNameStart = NSMaxRange([tag rangeOfString:@">" options:NSCaseInsensitiveSearch range:[self restRangeFromString:tag subtractingRange:songNameTagStartRange]]);
int songNameEnd = [tag rangeOfString:@"</a>" options:NSCaseInsensitiveSearch range:[self restRangeFromString:tag subtractingRange:songNameTagStartRange]].location;
NSString *songName = [tag substringWithRange:NSMakeRange(songNameStart, songNameEnd-songNameStart)];
int previewStart = songNameEnd + [@"</a>" length] + [@"\n<p>" length];
NSRange previewRestRange = NSMakeRange(previewStart, [tag length]-previewStart);
int previewEnd = [tag rangeOfString:@"</p>" options:NSCaseInsensitiveSearch range:previewRestRange].location;
NSString *preview = [self stringByRemovingHTMLTags:[tag substringWithRange:NSMakeRange(previewStart, previewEnd-previewStart)]];
return [[SearchResult alloc] initWithName:songName fromArtist:artist preview:preview link:link];
}
-(NSURL*) urlFromHref: (NSString *) link {
if ([link hasPrefix:@"/"]) {
return [NSURL URLWithString:[NSString stringWithFormat:@"http://www.Magistrix.de%@", link]];
} else {
return [NSURL URLWithString:link];
}
}
-(NSString*) stringByRemovingHTMLTags: (NSString *)string {
return [[[[[[[[[[string stringByReplacingOccurrencesOfString:@"<strong>" withString:@""] stringByReplacingOccurrencesOfString:@"</strong>" withString:@""] stringByReplacingOccurrencesOfString:@"<b>" withString:@""] stringByReplacingOccurrencesOfString:@"</b>" withString:@""] stringByReplacingOccurrencesOfString:@"<i>" withString:@""] stringByReplacingOccurrencesOfString:@"</i>" withString:@""] stringByReplacingOccurrencesOfString:@"<p>" withString:@""] stringByReplacingOccurrencesOfString:@"</p>" withString:@""] stringByReplacingOccurrencesOfString:@"<br />" withString:@""] stringByReplacingOccurrencesOfString:@"&quot;" withString:@"\""];
}
-(NSRange) restRangeFromString: (NSString *) page subtractingRange: (NSRange) aRange {
int loc = NSMaxRange(aRange);
return NSMakeRange(loc, [page length]-loc);
}
-(void) shouldSetResultCountFromPage: (NSString *) page {
if (resultCount == 0) {
//Nothing loaded before
NSRange resultsLabelStartRange = [page rangeOfString:@"<p>Ergebnisse 1 bis "];
int resultsLabelEnd = [page rangeOfString:@"</p>" options:NSCaseInsensitiveSearch range:[self restRangeFromString:page subtractingRange:resultsLabelStartRange]].location;
NSString *resultsLabel = [page substringWithRange:NSMakeRange(NSMaxRange(resultsLabelStartRange), resultsLabelEnd-resultsLabelStartRange.location)];
if ([resultsLabel rangeOfString:@"ungefähr"].location != NSNotFound){
//Needs not more than 100 which means 10 sites (which is the maximum)
resultCount = 100;
} else {
int resultsStart = NSMaxRange([resultsLabel rangeOfString:@"von "]);
int resultsEnd = [resultsLabel rangeOfString:@"<"].location;
NSString *results = [resultsLabel substringWithRange:NSMakeRange(resultsStart, resultsEnd-resultsStart)];
resultCount = [results intValue];
}
if (resultCount > 100) {
resultCount = 100;
}
}
}
-(void) resetLoadedResults {
loadedResults = 0;
}
-(Lyrics*) lyricsBySearchResult: (SearchResult *) result {
NSError *error = nil;
NSString *page = [NSString stringWithContentsOfURL:[result link] encoding:NSUTF8StringEncoding error:&error];
if (error) {
return nil;
}
NSString *lyrics = [self lyricsFromPage:page];
return [[Lyrics alloc] initWithName:[result name] byArtist:[result artist] withLyrics:lyrics];
}
-(NSString *) lyricsFromPage: (NSString *)page {
int lyricsStart = NSMaxRange([page rangeOfString:@"<div id='songtext'>"]) + [@"\n" length];
NSRange restRange = NSMakeRange(lyricsStart, [page length]-lyricsStart);
int lyricsEnd = [page rangeOfString:@"<div class='clear'></div>" options:NSCaseInsensitiveSearch range:restRange].location;
NSString *lyrics = [self stringByRemovingHTMLTags:[page substringWithRange:NSMakeRange(lyricsStart, lyricsEnd-lyricsStart)]];
return lyrics;
}
@end