@ -11,7 +11,7 @@ public final class LokiGroupChatAPI : NSObject {
// MARK: P u b l i c C h a t
@objc public static let publicChatServer = " https://chat.lokinet.org "
@objc public static let publicChatMessageType = " network.loki.messenger.publicChat "
@objc public static let publicChatServerID : UInt = 1
@objc public static let publicChatServerID : UInt 64 = 1
// MARK: C o n v e n i e n c e
private static var userDisplayName : String {
@ -28,7 +28,7 @@ public final class LokiGroupChatAPI : NSObject {
// MARK: E r r o r
public enum Error : Swift . Error {
case tokenParsingFailed, tokenDecryptionFailed , messageParsingFailed , deletionParsingFailed , jsonParsing Failed
case parsingFailed, decryption Failed
}
// MARK: D a t a b a s e
@ -87,7 +87,7 @@ public final class LokiGroupChatAPI : NSObject {
return TSNetworkManager . shared ( ) . makePromise ( request : request ) . map { $0 . responseObject } . map { rawResponse in
guard let json = rawResponse as ? JSON , let base64EncodedChallenge = json [ " cipherText64 " ] as ? String , let base64EncodedServerPublicKey = json [ " serverPubKey64 " ] as ? String ,
let challenge = Data ( base64Encoded : base64EncodedChallenge ) , var serverPublicKey = Data ( base64Encoded : base64EncodedServerPublicKey ) else {
throw Error . tokenP arsingFailed
throw Error . p arsingFailed
}
// D i s c a r d t h e " 0 5 " p r e f i x i f n e e d e d
if ( serverPublicKey . count = = 33 ) {
@ -97,7 +97,7 @@ public final class LokiGroupChatAPI : NSObject {
// T h e c h a l l e n g e i s p r e f i x e d b y t h e 1 6 b i t I V
guard let tokenAsData = try ? DiffieHellman . decrypt ( challenge , publicKey : serverPublicKey , privateKey : userKeyPair . privateKey ) ,
let token = String ( bytes : tokenAsData , encoding : . utf8 ) else {
throw Error . tokenD ecryptionFailed
throw Error . d ecryptionFailed
}
return token
}
@ -136,7 +136,7 @@ public final class LokiGroupChatAPI : NSObject {
return TSNetworkManager . shared ( ) . makePromise ( request : request ) . map { $0 . responseObject } . map { rawResponse in
guard let json = rawResponse as ? JSON , let rawMessages = json [ " data " ] as ? [ JSON ] else {
print ( " [Loki] Couldn't parse messages for group chat with ID: \( group ) on server: \( server ) from: \( rawResponse ) . " )
throw Error . messageP arsingFailed
throw Error . p arsingFailed
}
return rawMessages . flatMap { message in
guard let annotations = message [ " annotations " ] as ? [ JSON ] , let annotation = annotations . first , let value = annotation [ " value " ] as ? JSON ,
@ -167,7 +167,7 @@ public final class LokiGroupChatAPI : NSObject {
guard let json = rawResponse as ? JSON , let messageAsJSON = json [ " data " ] as ? JSON , let serverID = messageAsJSON [ " id " ] as ? UInt64 , let body = messageAsJSON [ " text " ] as ? String ,
let dateAsString = messageAsJSON [ " created_at " ] as ? String , let date = dateFormatter . date ( from : dateAsString ) else {
print ( " [Loki] Couldn't parse message for group chat with ID: \( group ) on server: \( server ) from: \( rawResponse ) . " )
throw Error . messageP arsingFailed
throw Error . p arsingFailed
}
let timestamp = UInt64 ( date . timeIntervalSince1970 ) * 1000
return LokiGroupMessage ( serverID : serverID , hexEncodedPublicKey : userHexEncodedPublicKey , displayName : displayName , body : body , type : publicChatMessageType , timestamp : timestamp )
@ -194,7 +194,7 @@ public final class LokiGroupChatAPI : NSObject {
return TSNetworkManager . shared ( ) . makePromise ( request : request ) . map { $0 . responseObject } . map { rawResponse in
guard let json = rawResponse as ? JSON , let deletions = json [ " data " ] as ? [ JSON ] else {
print ( " [Loki] Couldn't parse deleted messages for group chat with ID: \( group ) on server: \( server ) from: \( rawResponse ) . " )
throw Error . deletionP arsingFailed
throw Error . p arsingFailed
}
return deletions . flatMap { deletion in
guard let serverID = deletion [ " id " ] as ? UInt64 , let messageServerID = deletion [ " message_id " ] as ? UInt64 else {
@ -208,43 +208,30 @@ public final class LokiGroupChatAPI : NSObject {
}
}
public static func deleteMessage WithServerID( _ messageServer ID: UInt , for group : UInt64 , on server : String , is OurOwnMessage: Bool = true ) -> Promise < Void > {
public static func deleteMessage ( with message ID: UInt , for group : UInt64 , on server : String , is SentByUser: Bool ) -> Promise < Void > {
return getAuthToken ( for : server ) . then { token -> Promise < Void > in
let modTag = isOurOwnMessage ? " " : " [Mod] "
print ( " [Loki] \( modTag ) Deleting message with server ID: \( messageServerID ) for group chat with ID: \( group ) on server: \( server ) . " )
let endpoint = isOurOwnMessage ? " \( server ) /channels/ \( group ) /messages/ \( messageServerID ) " : " \( server ) /loki/v1/moderation/message/ \( messageServerID ) "
let url = URL ( string : endpoint ) !
let isModerationRequest = ! isSentByUser
print ( " [Loki] Deleting message with ID: \( messageID ) for group chat with ID: \( group ) on server: \( server ) (isModerationRequest = \( isModerationRequest ) ). " )
let urlAsString = isSentByUser ? " \( server ) /channels/ \( group ) /messages/ \( messageID ) " : " \( server ) /loki/v1/moderation/message/ \( messageID ) "
let url = URL ( string : urlAsString ) !
let request = TSRequest ( url : url , method : " DELETE " , parameters : [ : ] )
request . allHTTPHeaderFields = [ " Content-Type " : " application/json " , " Authorization " : " Bearer \( token ) " ]
return TSNetworkManager . shared ( ) . makePromise ( request : request ) . map { result -> Void in
print ( " [Loki] \( modTag ) Deleted message \( messageServerID ) on server \( server ) . " )
} . recover { error in
// I f w e g o t 4 0 4 o r 4 1 0 t h e n m e s s a g e d o e s n ' t e x i s t o n t h e s e r v e r
if let error = error as ? NetworkManagerError , error . statusCode = = 404 || error . statusCode = = 410 {
print ( " [Loki] \( modTag ) Message \( messageServerID ) was already deleted on the server. " )
return
}
print ( " [Loki] \( modTag ) Failed to delete message \( messageServerID ) on server \( server ) . " )
throw error
return TSNetworkManager . shared ( ) . makePromise ( request : request ) . done { result -> Void in
print ( " [Loki] Deleted message with ID: \( messageID ) on server: \( server ) . " )
}
}
}
public static func isCurrentUserMod( on server : String ) -> Promise < Bool > {
public static func userHasModerationPermission ( for group : UInt64 , on server : String ) -> Promise < Bool > {
return getAuthToken ( for : server ) . then { token -> Promise < Bool > in
let url = URL ( string : " \( server ) /loki/v1/user_info " ) !
let request = TSRequest ( url : url )
request . allHTTPHeaderFields = [ " Content-Type " : " application/json " , " Authorization " : " Bearer \( token ) " ]
return TSNetworkManager . shared ( ) . makePromise ( request : request ) . map { $0 . responseObject } . map { rawResponse in
guard let json = rawResponse as ? JSON , let data = json [ " data " ] as ? JSON else {
print ( " [Loki] Couldn't parse json for user info ." )
throw Error . jsonP arsingFailed
print ( " [Loki] Couldn't parse moderation permission for group chat with ID: \( group ) on server: \( server ) from: \( rawResponse ) ." )
throw Error . p arsingFailed
}
// m o d e r a t o r _ s t a t u s i s n o t s e t f o r u s e r s t h a t a r e n o t m o d s
return data [ " moderator_status " ] as ? Bool ? ? false
}
}
@ -261,8 +248,8 @@ public final class LokiGroupChatAPI : NSObject {
return AnyPromise . from ( sendMessage ( message , to : group , on : server ) )
}
@objc ( deleteMessageWith Server ID: forGroup : onServer : is OurOwnMessage : )
public static func objc_deleteMessage WithServerID( _ messageServer ID: UInt , for group : UInt64 , on server : String , ourMessage: Bool = true ) -> AnyPromise {
return AnyPromise . from ( deleteMessage WithServerID( messageServer ID, for : group , on : server , is OurOwnMessage: ourMessage ) )
@objc ( deleteMessageWith ID: forGroup : onServer : is SentByUser : )
public static func objc_deleteMessage ( with message ID: UInt , for group : UInt64 , on server : String , isSentByUser: Bool ) -> AnyPromise {
return AnyPromise . from ( deleteMessage ( with : message ID, for : group , on : server , is SentByUser: isSentByUser ) )
}
}