~not/sonar

d1ace5c6603b9b051137f3e59cb30781ae8e1bd5 — b123400 a month ago db75158
Search API
M Sonar.xcodeproj/project.pbxproj => Sonar.xcodeproj/project.pbxproj +6 -0
@@ 40,6 40,7 @@
		CFD908BD2732B1F800FEFD53 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CFD908BC2732B1F800FEFD53 /* main.m */; };
		CFD908C72732C5E800FEFD53 /* PlayerWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CFD908C52732C5E800FEFD53 /* PlayerWindowController.m */; };
		CFD908CB2732CC2800FEFD53 /* PlayerHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = CFD908CA2732CC2800FEFD53 /* PlayerHeaderView.m */; };
		CFDB4AD22BAB117D00A36AEE /* BRSonicAPIResponseSearchResult.m in Sources */ = {isa = PBXBuildFile; fileRef = CFDB4AD12BAB117D00A36AEE /* BRSonicAPIResponseSearchResult.m */; };
		CFDC05452743BE820065F13D /* BRSonicAPISong.m in Sources */ = {isa = PBXBuildFile; fileRef = CFDC05442743BE820065F13D /* BRSonicAPISong.m */; };
		CFDC05482743BE9A0065F13D /* BRSonicAPIResponseSongs.m in Sources */ = {isa = PBXBuildFile; fileRef = CFDC05472743BE9A0065F13D /* BRSonicAPIResponseSongs.m */; };
		CFDC054B2743C0A50065F13D /* BRSonicAPIResponseAlbums.m in Sources */ = {isa = PBXBuildFile; fileRef = CFDC054A2743C0A50065F13D /* BRSonicAPIResponseAlbums.m */; };


@@ 123,6 124,8 @@
		CFD908C52732C5E800FEFD53 /* PlayerWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PlayerWindowController.m; sourceTree = "<group>"; };
		CFD908C92732CC2800FEFD53 /* PlayerHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlayerHeaderView.h; sourceTree = "<group>"; };
		CFD908CA2732CC2800FEFD53 /* PlayerHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PlayerHeaderView.m; sourceTree = "<group>"; };
		CFDB4AD02BAB117D00A36AEE /* BRSonicAPIResponseSearchResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BRSonicAPIResponseSearchResult.h; sourceTree = "<group>"; };
		CFDB4AD12BAB117D00A36AEE /* BRSonicAPIResponseSearchResult.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BRSonicAPIResponseSearchResult.m; sourceTree = "<group>"; };
		CFDC05432743BE820065F13D /* BRSonicAPISong.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BRSonicAPISong.h; sourceTree = "<group>"; };
		CFDC05442743BE820065F13D /* BRSonicAPISong.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BRSonicAPISong.m; sourceTree = "<group>"; };
		CFDC05462743BE9A0065F13D /* BRSonicAPIResponseSongs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BRSonicAPIResponseSongs.h; sourceTree = "<group>"; };


@@ 314,6 317,8 @@
				CF5849B42A41891A00B494C7 /* BRSonicAPIResponsePlaylist.m */,
				CFE160E4279C386E00287C14 /* BRSonicAPIResponseStarred.h */,
				CFE160E5279C386E00287C14 /* BRSonicAPIResponseStarred.m */,
				CFDB4AD02BAB117D00A36AEE /* BRSonicAPIResponseSearchResult.h */,
				CFDB4AD12BAB117D00A36AEE /* BRSonicAPIResponseSearchResult.m */,
				CFD1C4D6273E958B009ED1CD /* BRSonicAPIArtist.h */,
				CFD1C4D7273E958B009ED1CD /* BRSonicAPIArtist.m */,
				CFDC054C2743C0B90065F13D /* BRSonicAPIAlbum.h */,


@@ 478,6 483,7 @@
				CFDC05512743C3870065F13D /* Album.m in Sources */,
				CF252E93273E634200A0D26C /* Artist.m in Sources */,
				CFC62B2428ACB1F4006E08B6 /* SonarApplication.m in Sources */,
				CFDB4AD22BAB117D00A36AEE /* BRSonicAPIResponseSearchResult.m in Sources */,
				CFDC054B2743C0A50065F13D /* BRSonicAPIResponseAlbums.m in Sources */,
				CFB55EAF2781DBA6004F9C47 /* Playlist.m in Sources */,
				CFDC054E2743C0B90065F13D /* BRSonicAPIAlbum.m in Sources */,

M Sonar/API Client/BRSonicAPIClient.h => Sonar/API Client/BRSonicAPIClient.h +5 -0
@@ 14,6 14,7 @@
#import "BRSonicAPIResponsePlaylist.h"
#import "BRSonicAPIResponsePlaylistSongs.h"
#import "BRSonicAPIResponseStarred.h"
#import "BRSonicAPIResponseSearchResult.h"

NS_ASSUME_NONNULL_BEGIN



@@ 53,6 54,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)getStarredsWithCredential:(BRSonicAPICredential *)credential
                       completion:(void (^) (NSError * _Nullable error, BRSonicAPIResponseStarred *response))callback;

- (void)searchWithKeyword:(NSString *)keyword
               credential:(BRSonicAPICredential *)credential
               completion:(void (^) (NSError * _Nullable error, BRSonicAPIResponseSearchResult *response))callback;

- (void)starWithItem:(id)item
      withCredential:(BRSonicAPICredential *)credential
          completion:(void (^) (NSError * _Nullable error))callback;

M Sonar/API Client/BRSonicAPIClient.m => Sonar/API Client/BRSonicAPIClient.m +40 -0
@@ 373,6 373,46 @@
    }] resume];
}

- (void)searchWithKeyword:(NSString *)keyword
               credential:(BRSonicAPICredential *)credential
               completion:(void (^) (NSError * _Nullable error, BRSonicAPIResponseSearchResult *response))callback {
    NSURLComponents *components = [NSURLComponents componentsWithURL:credential.host resolvingAgainstBaseURL:NO];
    [components setPath:@"/rest/search3"];
    
    [components setQueryItems:
     [[credential baseUrlQueryItems] arrayByAddingObjectsFromArray:@[
        [NSURLQueryItem queryItemWithName:@"query" value:keyword],
        [NSURLQueryItem queryItemWithName:@"artistCount" value:@"500"],
        [NSURLQueryItem queryItemWithName:@"albumCount" value:@"500"],
        [NSURLQueryItem queryItemWithName:@"songCount" value:@"500"]
     ]]];
    
    [[[NSURLSession sharedSession] dataTaskWithURL:components.URL
                                 completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            callback(error, nil);
            return;
        }
        NSError *rError = nil;
        BRSonicAPIResponseSearchResult *xml = [[BRSonicAPIResponseSearchResult alloc] initWithData:data
                                                                                           options:NSXMLNodeOptionsNone
                                                                                             error:&rError];
        if (rError) {
            callback(rError, nil);
            return;
        }
        if (xml.status == BRSonicAPIResponseStatusFailed) {
            callback(xml.error ?: [NSError errorWithDomain:@"net.b123400.sonic"
                                                      code:0
                                                  userInfo:@{
                NSLocalizedDescriptionKey: NSLocalizedString(@"Failed", @"")
            }], nil);
            return;
        }
        callback(nil, xml);
    }] resume];
}

- (void)starWithItem:(id)item
      withCredential:(BRSonicAPICredential *)credential
          completion:(void (^) (NSError * _Nullable error))callback {

A Sonar/API Client/BRSonicAPIResponseSearchResult.h => Sonar/API Client/BRSonicAPIResponseSearchResult.h +18 -0
@@ 0,0 1,18 @@
//
//  BRSonicAPIResponseSearchResult.h
//  Sonar
//
//  Created by b123400 on 2024/03/20.
//

#import "BRSonicAPIResponse.h"

NS_ASSUME_NONNULL_BEGIN

@interface BRSonicAPIResponseSearchResult : BRSonicAPIResponse

- (NSArray*)items;

@end

NS_ASSUME_NONNULL_END

A Sonar/API Client/BRSonicAPIResponseSearchResult.m => Sonar/API Client/BRSonicAPIResponseSearchResult.m +33 -0
@@ 0,0 1,33 @@
//
//  BRSonicAPIResponseSearchResult.m
//  Sonar
//
//  Created by b123400 on 2024/03/20.
//

#import "BRSonicAPIResponseSearchResult.h"
#import "BRSonicAPISong.h"
#import "BRSonicAPIAlbum.h"
#import "BRSonicAPIArtist.h"

@implementation BRSonicAPIResponseSearchResult

- (NSArray *)items {
    NSXMLElement *starredElement = [[self.rootElement elementsForName:@"searchResult3"] firstObject];
    NSMutableArray *items = [NSMutableArray array];
    for (NSXMLElement *childElement in starredElement.children) {
        if ([[childElement name] isEqualTo:@"artist"]) {
            BRSonicAPIArtist *a = [[BRSonicAPIArtist alloc] initWithXMLElement:childElement];
            [items addObject:a];
        } else if ([[childElement name] isEqualTo:@"album"]) {
            BRSonicAPIAlbum *a = [[BRSonicAPIAlbum alloc] initWithXMLElement:childElement];
            [items addObject:a];
        } else if ([[childElement name] isEqualTo:@"song"]) {
            BRSonicAPISong *a = [[BRSonicAPISong alloc] initWithXMLElement:childElement];
            [items addObject:a];
        }
    }
    return items;
}

@end