diff --git a/src/MTXClient.h b/src/MTXClient.h index 0208cfc..7689ab6 100644 --- a/src/MTXClient.h +++ b/src/MTXClient.h @@ -61,6 +61,13 @@ typedef void (^mtx_client_room_list_block_t)( typedef void (^mtx_client_room_join_block_t)(OFString *_Nullable roomID, id _Nullable exception); +/** + * @brief A block called when a room was left. + * + * @param exception An exception if leaving the room failed + */ +typedef void (^mtx_client_room_leave_block_t)(id _Nullable exception); + /** * @brief A class that represents a client. */ @@ -143,6 +150,15 @@ typedef void (^mtx_client_room_join_block_t)(OFString *_Nullable roomID, */ - (void)joinRoom: (OFString *)room block: (mtx_client_room_join_block_t)block; + +/** + * @brief Leaves the specified room. + * + * @param roomID The room ID to leave + * @param block A block to call when the room was left + */ +- (void)leaveRoom: (OFString *)roomID + block: (mtx_client_room_leave_block_t)block; @end OF_ASSUME_NONNULL_END diff --git a/src/MTXClient.m b/src/MTXClient.m index 6650444..f8bf619 100644 --- a/src/MTXClient.m +++ b/src/MTXClient.m @@ -25,6 +25,7 @@ #import "MTXFetchRoomListFailedException.h" #import "MTXJoinRoomFailedException.h" +#import "MTXLeaveRoomFailedException.h" #import "MTXLoginFailedException.h" #import "MTXLogoutFailedException.h" @@ -287,4 +288,33 @@ validateHomeserver(OFURL *homeserver) objc_autoreleasePoolPop(pool); } + +- (void)leaveRoom: (OFString *)roomID + block: (mtx_client_room_leave_block_t)block +{ + void *pool = objc_autoreleasePoolPush(); + MTXRequest *request = [self requestWithPath: [OFString + stringWithFormat: @"/_matrix/client/r0/rooms/%@/leave", roomID]]; + request.method = OF_HTTP_REQUEST_METHOD_POST; + [request performWithBlock: ^ (mtx_response_t response, int statusCode, + id exception) { + if (exception != nil) { + block(exception); + return; + } + + if (statusCode != 200) { + block([MTXLeaveRoomFailedException + exceptionWithRoomID: roomID + statusCode: statusCode + response: response + client: self]); + return; + } + + block(nil); + }]; + + objc_autoreleasePoolPop(pool); +} @end diff --git a/src/ObjMatrix.h b/src/ObjMatrix.h index a0b09e4..237c639 100644 --- a/src/ObjMatrix.h +++ b/src/ObjMatrix.h @@ -24,5 +24,7 @@ #import "MTXRequest.h" #import "MTXFetchRoomListFailedException.h" +#import "MTXJoinRoomFailedException.h" +#import "MTXLeaveRoomFailedException.h" #import "MTXLoginFailedException.h" #import "MTXLogoutFailedException.h" diff --git a/src/exceptions/MTXLeaveRoomFailedException.h b/src/exceptions/MTXLeaveRoomFailedException.h new file mode 100644 index 0000000..a19bb0c --- /dev/null +++ b/src/exceptions/MTXLeaveRoomFailedException.h @@ -0,0 +1,48 @@ +/* + * 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 MTXLeaveRoomFailedException: MTXClientException +@property (readonly, nonatomic) OFString *roomID; + ++ (instancetype)exceptionWithStatusCode: (int)statusCode + response: (mtx_response_t)response + client: (MTXClient *)client OF_UNAVAILABLE; ++ (instancetype)exceptionWithRoomID: (OFString *)roomID + statusCode: (int)statusCode + response: (mtx_response_t)response + client: (MTXClient *)client; +- (instancetype)initWithStatusCode: (int)statusCode + response: (mtx_response_t)response + client: (MTXClient *)client OF_UNAVAILABLE; +- (instancetype)initWithRoomID: (OFString *)roomID + statusCode: (int)statusCode + response: (mtx_response_t)response + client: (MTXClient *)client; +@end + +OF_ASSUME_NONNULL_END diff --git a/src/exceptions/MTXLeaveRoomFailedException.m b/src/exceptions/MTXLeaveRoomFailedException.m new file mode 100644 index 0000000..558f486 --- /dev/null +++ b/src/exceptions/MTXLeaveRoomFailedException.m @@ -0,0 +1,71 @@ +/* + * 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 "MTXLeaveRoomFailedException.h" + +#import "MTXClient.h" + +@implementation MTXLeaveRoomFailedException ++ (instancetype)exceptionWithRoomID: (OFString *)roomID + statusCode: (int)statusCode + response: (mtx_response_t)response + client: (MTXClient *)client +{ + return [[[self alloc] initWithRoomID: roomID + statusCode: statusCode + response: response + client: client] autorelease]; +} + +- (instancetype)initWithRoomID: (OFString *)roomID + statusCode: (int)statusCode + response: (mtx_response_t)response + client: (MTXClient *)client +{ + self = [super initWithStatusCode: statusCode + response: response + client: client]; + + @try { + _roomID = [roomID copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_roomID release]; + + [super dealloc]; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"Failed to leave room %@ for %@: %@", + _roomID, self.client.userID, self.response]; +} +@end diff --git a/src/exceptions/Makefile b/src/exceptions/Makefile index 866feec..b8abf61 100644 --- a/src/exceptions/Makefile +++ b/src/exceptions/Makefile @@ -6,6 +6,7 @@ STATIC_LIB_NOINST = ${EXCEPTIONS_A} SRCS = MTXClientException.m \ MTXFetchRoomListFailedException.m \ MTXJoinRoomFailedException.m \ + MTXLeaveRoomFailedException.m \ MTXLoginFailedException.m \ MTXLogoutFailedException.m INCLUDES = ${SRCS:.m=.h} diff --git a/tests/tests.m b/tests/tests.m index 5322820..c33a08d 100644 --- a/tests/tests.m +++ b/tests/tests.m @@ -80,15 +80,31 @@ OF_APPLICATION_DELEGATE(Tests) - (void)joinRoom { - [_client joinRoom: @"#test:nil.im" + OFString *room = @"#test:nil.im"; + [_client joinRoom: room block: ^ (OFString *roomID, id exception) { if (exception != nil) { - of_log(@"Failed to join room: %@", exception); + of_log(@"Failed to join room %@: %@", room, exception); [OFApplication terminateWithStatus: 1]; } of_log(@"Joined room %@", roomID); + [self leaveRoom: roomID]; + }]; +} + +- (void)leaveRoom: (OFString *)roomID +{ + [_client leaveRoom: roomID + block: ^ (id exception) { + if (exception != nil) { + of_log(@"Failed to leave room %@: %@", exception); + [OFApplication terminateWithStatus: 1]; + } + + of_log(@"Left room %@", roomID); + [self logOut]; }]; }