Index: src/MTXClient.h ================================================================== --- src/MTXClient.h +++ src/MTXClient.h @@ -40,10 +40,19 @@ * * @param exception `nil` on success, otherwise an exception */ typedef void (^mtx_client_logout_block_t)(id _Nullable exception); +/** + * @brief A block called when the room list was fetched. + * + * @param rooms An array of joined rooms, or nil on error + * @param exception An exception if fetching the room list failed + */ +typedef void (^mtx_client_room_list_block_t)( + OFArray *_Nullable rooms, id _Nullable exception); + /** * @brief A class that represents a client. */ @interface MTXClient: OFObject /** @@ -103,11 +112,18 @@ /** * @brief Logs out the device and invalidates the access token. * * @warning The client can no longer be used after this succeeded! * - * @param block The block to call when logging out succeeded or failed + * @param block A block to call when logging out succeeded or failed */ - (void)asyncLogOutWithBlock: (mtx_client_logout_block_t)block; + +/** + * @brief Fetches the list of joined rooms. + * + * @param block A block to call with the list of joined room + */ +- (void)asyncFetchRoomList: (mtx_client_room_list_block_t)block; @end OF_ASSUME_NONNULL_END Index: src/MTXClient.m ================================================================== --- src/MTXClient.m +++ src/MTXClient.m @@ -21,10 +21,11 @@ */ #import "MTXClient.h" #import "MTXRequest.h" +#import "MTXFetchRoomListFailedException.h" #import "MTXLoginFailedException.h" #import "MTXLogoutFailedException.h" static void validateHomeserver(OFURL *homeserver) @@ -199,9 +200,35 @@ return; } block(nil); }]; + + objc_autoreleasePoolPop(pool); +} + +- (void)asyncFetchRoomList: (mtx_client_room_list_block_t)block +{ + void *pool = objc_autoreleasePoolPush(); + MTXRequest *request = + [self requestWithPath: @"/_matrix/client/r0/joined_rooms"]; + [request asyncPerformWithBlock: ^ (mtx_response_t response, + int statusCode, id exception) { + if (exception != nil) { + block(nil, exception); + return; + } + + if (statusCode != 200 || response[@"joined_rooms"] == nil) { + block(nil, [MTXFetchRoomListFailedException + exceptionWithClient: self + statusCode: statusCode + response: response]); + return; + } + + block(response[@"joined_rooms"], nil); + }]; objc_autoreleasePoolPop(pool); } @end Index: src/ObjMatrix.h ================================================================== --- src/ObjMatrix.h +++ src/ObjMatrix.h @@ -21,7 +21,8 @@ */ #import "MTXClient.h" #import "MTXRequest.h" +#import "MTXFetchRoomListFailedException.h" #import "MTXLoginFailedException.h" #import "MTXLogoutFailedException.h" ADDED src/exceptions/MTXClientException.h Index: src/exceptions/MTXClientException.h ================================================================== --- src/exceptions/MTXClientException.h +++ src/exceptions/MTXClientException.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, Jonathan Schleifer + * + * https://fossil.nil.im/objmatrix + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +#import "MTXRequest.h" + +OF_ASSUME_NONNULL_BEGIN + +@class MTXClient; + +@interface MTXClientException: OFException +@property (readonly, nonatomic) MTXClient *client; +@property (readonly, nonatomic) int statusCode; +@property (readonly, nonatomic) mtx_response_t response; + ++ (instancetype)exceptionWithClient: (MTXClient *)client + statusCode: (int)statusCode + response: (mtx_response_t)response; +- (instancetype)initWithClient: (OFString *)user + statusCode: (int)statusCode + response: (mtx_response_t)response; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/MTXClientException.m Index: src/exceptions/MTXClientException.m ================================================================== --- src/exceptions/MTXClientException.m +++ src/exceptions/MTXClientException.m @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020, Jonathan Schleifer + * + * https://fossil.nil.im/objmatrix + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "MTXLogoutFailedException.h" + +#import "MTXClient.h" + +@implementation MTXClientException ++ (instancetype)exceptionWithClient: (MTXClient *)client + statusCode: (int)statusCode + response: (mtx_response_t)response +{ + return [[[self alloc] initWithClient: client + statusCode: statusCode + response: response] autorelease]; +} + +- (instancetype)initWithClient: (MTXClient *)client + statusCode: (int)statusCode + response: (mtx_response_t)response +{ + self = [super init]; + + @try { + _client = [client retain]; + _statusCode = statusCode; + _response = [response copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_client release]; + [_response release]; + + [super dealloc]; +} +@end ADDED src/exceptions/MTXFetchRoomListFailedException.h Index: src/exceptions/MTXFetchRoomListFailedException.h ================================================================== --- src/exceptions/MTXFetchRoomListFailedException.h +++ src/exceptions/MTXFetchRoomListFailedException.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020, Jonathan Schleifer + * + * https://fossil.nil.im/objmatrix + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +#import "MTXClientException.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface MTXFetchRoomListFailedException: MTXClientException +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/MTXFetchRoomListFailedException.m Index: src/exceptions/MTXFetchRoomListFailedException.m ================================================================== --- src/exceptions/MTXFetchRoomListFailedException.m +++ src/exceptions/MTXFetchRoomListFailedException.m @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Jonathan Schleifer + * + * https://fossil.nil.im/objmatrix + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "MTXFetchRoomListFailedException.h" + +#import "MTXClient.h" + +@implementation MTXFetchRoomListFailedException +- (OFString *)description +{ + return [OFString stringWithFormat: + @"Failed to fetch room list for %@: %@", + self.client.userID, self.response]; +} +@end Index: src/exceptions/MTXLogoutFailedException.h ================================================================== --- src/exceptions/MTXLogoutFailedException.h +++ src/exceptions/MTXLogoutFailedException.h @@ -20,25 +20,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ #import -#import "MTXRequest.h" +#import "MTXClientException.h" OF_ASSUME_NONNULL_BEGIN -@class MTXClient; - -@interface MTXLogoutFailedException: OFException -@property (readonly, nonatomic) MTXClient *client; -@property (readonly, nonatomic) int statusCode; -@property (readonly, nonatomic) mtx_response_t response; - -+ (instancetype)exceptionWithClient: (MTXClient *)client - statusCode: (int)statusCode - response: (mtx_response_t)response; -- (instancetype)initWithClient: (OFString *)user - statusCode: (int)statusCode - response: (mtx_response_t)response; +@interface MTXLogoutFailedException: MTXClientException @end OF_ASSUME_NONNULL_END Index: src/exceptions/MTXLogoutFailedException.m ================================================================== --- src/exceptions/MTXLogoutFailedException.m +++ src/exceptions/MTXLogoutFailedException.m @@ -23,46 +23,12 @@ #import "MTXLogoutFailedException.h" #import "MTXClient.h" @implementation MTXLogoutFailedException -+ (instancetype)exceptionWithClient: (MTXClient *)client - statusCode: (int)statusCode - response: (mtx_response_t)response -{ - return [[[self alloc] initWithClient: client - statusCode: statusCode - response: response] autorelease]; -} - -- (instancetype)initWithClient: (MTXClient *)client - statusCode: (int)statusCode - response: (mtx_response_t)response -{ - self = [super init]; - - @try { - _client = [client retain]; - _statusCode = statusCode; - _response = [response copy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_client release]; - [_response release]; - - [super dealloc]; -} - - (OFString *)description { return [OFString stringWithFormat: - @"Failed to log out user %@: %@", _client.userID, _response]; + @"Failed to log out user %@: %@", + self.client.userID, self.response]; } @end Index: src/exceptions/Makefile ================================================================== --- src/exceptions/Makefile +++ src/exceptions/Makefile @@ -1,13 +1,15 @@ include ../../extra.mk STATIC_PIC_LIB_NOINST = ${EXCEPTIONS_LIB_A} STATIC_LIB_NOINST = ${EXCEPTIONS_A} -SRCS = MTXLoginFailedException.m \ +SRCS = MTXClientException.m \ + MTXFetchRoomListFailedException.m \ + MTXLoginFailedException.m \ MTXLogoutFailedException.m INCLUDES = ${SRCS:.m=.h} include ../../buildsys.mk CPPFLAGS += -I. -I.. Index: tests/tests.m ================================================================== --- tests/tests.m +++ tests/tests.m @@ -28,10 +28,14 @@ @end OF_APPLICATION_DELEGATE(Tests) @implementation Tests +{ + MTXClient *_client; +} + - (void)applicationDidFinishLaunching { __auto_type environment = OFApplication.environment; if (environment[@"OBJMATRIX_USER"] == nil || environment[@"OBJMATRIX_PASS"] == nil || @@ -50,20 +54,41 @@ if (exception != nil) { of_log(@"Error logging in: %@", exception); [OFApplication terminateWithStatus: 1]; } - of_log(@"Logged in client: %@", client); - - [client asyncLogOutWithBlock: ^ (id exception) { - if (exception != nil) { - of_log(@"Failed to log out: %@\n", exception); - [OFApplication terminateWithStatus: 1]; - } - - of_log(@"Logged out client"); - - [OFApplication terminate]; - }]; + _client = [client retain]; + of_log(@"Logged in client: %@", _client); + + [self fetchRoomList]; + }]; +} + +- (void)fetchRoomList +{ + [_client asyncFetchRoomList: ^ (OFArray *rooms, + id exception) { + if (exception != nil) { + of_log(@"Failed to fetch room list: %@", exception); + [OFApplication terminateWithStatus: 1]; + } + + of_log(@"Fetched room list: %@", rooms); + + [self logOut]; + }]; +} + +- (void)logOut +{ + [_client asyncLogOutWithBlock: ^ (id exception) { + if (exception != nil) { + of_log(@"Failed to log out: %@\n", exception); + [OFApplication terminateWithStatus: 1]; + } + + of_log(@"Logged out client"); + + [OFApplication terminate]; }]; } @end