pull/63/head
Niels Andriesse 6 years ago
parent a07d50143d
commit fc44b1c191

@ -1272,10 +1272,10 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
if (interationType == OWSInteractionType_IncomingMessage) { if (interationType == OWSInteractionType_IncomingMessage) {
// Only allow deletion on incoming messages if the user has moderation permission // Only allow deletion on incoming messages if the user has moderation permission
return [LKPublicChatAPI isUserModerator:self.userHexEncodedPublicKey forGroup:publicChat.channel onServer:publicChat.server]; return [LKPublicChatAPI isUserModerator:self.userHexEncodedPublicKey forGroup:publicChat.channel onServer:publicChat.server];
} else {
// Only allow deletion on outgoing messages if the user was the sender (i.e. it was not sent from another linked device)
return [self.interaction.actualSenderHexEncodedPublicKey isEqual:self.userHexEncodedPublicKey];
} }
// Only allow deletion on outgoing messages if the user was the sender (i.e. it was not sent from another linked device)
return [self.interaction.actualSenderHexEncodedPublicKey isEqual:self.userHexEncodedPublicKey];
} }
@end @end

@ -35,10 +35,11 @@ public final class LokiStorageAPI : LokiDotNetAPI {
throw Error.parsingFailed throw Error.parsingFailed
} }
return Set(data.flatMap { data -> [DeviceLink] in return Set(data.flatMap { data -> [DeviceLink] in
guard let annotations = data["annotations"] as? [JSON], !annotations.isEmpty, let hexEncodedPublicKey = data["username"] as? String else { return [] } guard let annotations = data["annotations"] as? [JSON], !annotations.isEmpty else { return [] }
guard let annotation = annotations.first(where: { $0["type"] as? String == deviceLinkType }), guard let annotation = annotations.first(where: { $0["type"] as? String == deviceLinkType }),
let value = annotation["value"] as? JSON, let rawDeviceLinks = value["authorisations"] as? [JSON] else { let value = annotation["value"] as? JSON, let rawDeviceLinks = value["authorisations"] as? [JSON],
print("[Loki] Couldn't parse device links for user: \(hexEncodedPublicKey) from: \(rawResponse).") let user = data["user"] as? JSON, let hexEncodedPublicKey = user["username"] as? String else {
print("[Loki] Couldn't parse device links from: \(rawResponse).")
return [] return []
} }
return rawDeviceLinks.compactMap { rawDeviceLink in return rawDeviceLinks.compactMap { rawDeviceLink in

@ -3,6 +3,7 @@ import PromiseKit
@objc(LKPublicChatAPI) @objc(LKPublicChatAPI)
public final class LokiPublicChatAPI : LokiDotNetAPI { public final class LokiPublicChatAPI : LokiDotNetAPI {
private static var moderators: [String:[UInt64:Set<String>]] = [:] // Server URL to (channel ID to set of moderator IDs) private static var moderators: [String:[UInt64:Set<String>]] = [:] // Server URL to (channel ID to set of moderator IDs)
public static var displayNameUpdatees: [String:Set<String>] = [:]
// MARK: Settings // MARK: Settings
private static let fallbackBatchCount = 64 private static let fallbackBatchCount = 64
@ -229,6 +230,33 @@ public final class LokiPublicChatAPI : LokiDotNetAPI {
} }
} }
public static func getDisplayNames(for channel: UInt64, on server: String) -> Promise<Void> {
let publicChatID = "\(server).\(channel)"
guard let hexEncodedPublicKeys = displayNameUpdatees[publicChatID] else { return Promise.value(()) }
displayNameUpdatees[publicChatID] = []
print("[Loki] Getting display names for: \(hexEncodedPublicKeys).")
return getAuthToken(for: server).then(on: DispatchQueue.global()) { token -> Promise<Void> in
let queryParameters = "ids=\(hexEncodedPublicKeys.map { "@\($0)" }.joined(separator: ","))&include_user_annotations=1"
let url = URL(string: "\(server)/users?\(queryParameters)")!
let request = TSRequest(url: url)
return TSNetworkManager.shared().perform(request, withCompletionQueue: DispatchQueue.global()).map { $0.responseObject }.map { rawResponse in
guard let json = rawResponse as? JSON, let data = json["data"] as? [JSON] else {
print("[Loki] Couldn't parse display names for users: \(hexEncodedPublicKeys) from: \(rawResponse).")
throw Error.parsingFailed
}
storage.dbReadWriteConnection.readWrite { transaction in
data.forEach { data in
guard let user = data["user"] as? JSON, let hexEncodedPublicKey = user["username"] as? String, let rawDisplayName = user["name"] as? String else { return }
let endIndex = hexEncodedPublicKey.endIndex
let cutoffIndex = hexEncodedPublicKey.index(endIndex, offsetBy: -8)
let displayName = "\(rawDisplayName) (...\(hexEncodedPublicKey[cutoffIndex..<endIndex]))"
transaction.setObject(displayName, forKey: hexEncodedPublicKey, inCollection: "\(server).\(channel)")
}
}
}
}
}
@objc (isUserModerator:forGroup:onServer:) @objc (isUserModerator:forGroup:onServer:)
public static func isUserModerator(_ hexEncodedPublicString: String, for channel: UInt64, on server: String) -> Bool { public static func isUserModerator(_ hexEncodedPublicString: String, for channel: UInt64, on server: String) -> Bool {
return moderators[server]?[channel]?.contains(hexEncodedPublicString) ?? false return moderators[server]?[channel]?.contains(hexEncodedPublicString) ?? false

@ -1,10 +1,13 @@
// TODO: Move away from polling
@objc(LKPublicChatPoller) @objc(LKPublicChatPoller)
public final class LokiPublicChatPoller : NSObject { public final class LokiPublicChatPoller : NSObject {
private let publicChat: LokiPublicChat private let publicChat: LokiPublicChat
private var pollForNewMessagesTimer: Timer? = nil private var pollForNewMessagesTimer: Timer? = nil
private var pollForDeletedMessagesTimer: Timer? = nil private var pollForDeletedMessagesTimer: Timer? = nil
private var pollForModeratorsTimer: Timer? = nil private var pollForModeratorsTimer: Timer? = nil
private var pollForDisplayNamesTimer: Timer? = nil
private var hasStarted = false private var hasStarted = false
private let userHexEncodedPublicKey = OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey private let userHexEncodedPublicKey = OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey
@ -12,6 +15,7 @@ public final class LokiPublicChatPoller : NSObject {
private let pollForNewMessagesInterval: TimeInterval = 4 private let pollForNewMessagesInterval: TimeInterval = 4
private let pollForDeletedMessagesInterval: TimeInterval = 20 private let pollForDeletedMessagesInterval: TimeInterval = 20
private let pollForModeratorsInterval: TimeInterval = 10 * 60 private let pollForModeratorsInterval: TimeInterval = 10 * 60
private let pollForDisplayNamesInterval: TimeInterval = 60
// MARK: Lifecycle // MARK: Lifecycle
@objc(initForPublicChat:) @objc(initForPublicChat:)
@ -25,10 +29,12 @@ public final class LokiPublicChatPoller : NSObject {
pollForNewMessagesTimer = Timer.scheduledTimer(withTimeInterval: pollForNewMessagesInterval, repeats: true) { [weak self] _ in self?.pollForNewMessages() } pollForNewMessagesTimer = Timer.scheduledTimer(withTimeInterval: pollForNewMessagesInterval, repeats: true) { [weak self] _ in self?.pollForNewMessages() }
pollForDeletedMessagesTimer = Timer.scheduledTimer(withTimeInterval: pollForDeletedMessagesInterval, repeats: true) { [weak self] _ in self?.pollForDeletedMessages() } pollForDeletedMessagesTimer = Timer.scheduledTimer(withTimeInterval: pollForDeletedMessagesInterval, repeats: true) { [weak self] _ in self?.pollForDeletedMessages() }
pollForModeratorsTimer = Timer.scheduledTimer(withTimeInterval: pollForModeratorsInterval, repeats: true) { [weak self] _ in self?.pollForModerators() } pollForModeratorsTimer = Timer.scheduledTimer(withTimeInterval: pollForModeratorsInterval, repeats: true) { [weak self] _ in self?.pollForModerators() }
pollForDisplayNamesTimer = Timer.scheduledTimer(withTimeInterval: pollForDisplayNamesInterval, repeats: true) { [weak self] _ in self?.pollForDisplayNames() }
// Perform initial updates // Perform initial updates
pollForNewMessages() pollForNewMessages()
pollForDeletedMessages() pollForDeletedMessages()
pollForModerators() pollForModerators()
pollForDisplayNames()
hasStarted = true hasStarted = true
} }
@ -36,6 +42,7 @@ public final class LokiPublicChatPoller : NSObject {
pollForNewMessagesTimer?.invalidate() pollForNewMessagesTimer?.invalidate()
pollForDeletedMessagesTimer?.invalidate() pollForDeletedMessagesTimer?.invalidate()
pollForModeratorsTimer?.invalidate() pollForModeratorsTimer?.invalidate()
pollForDisplayNamesTimer?.invalidate()
hasStarted = false hasStarted = false
} }
@ -171,7 +178,17 @@ public final class LokiPublicChatPoller : NSObject {
} }
// Poll // Poll
let _ = LokiPublicChatAPI.getMessages(for: publicChat.channel, on: publicChat.server).done(on: DispatchQueue.global()) { messages in let _ = LokiPublicChatAPI.getMessages(for: publicChat.channel, on: publicChat.server).done(on: DispatchQueue.global()) { messages in
let uniqueHexEncodedPublicKeys = Set(messages.map { $0.hexEncodedPublicKey })
func proceed() { func proceed() {
let storage = OWSPrimaryStorage.shared()
var newDisplayNameUpdatees: Set<String> = []
storage.dbReadConnection.read { transaction in
newDisplayNameUpdatees = Set(uniqueHexEncodedPublicKeys.filter { storage.getMasterHexEncodedPublicKey(for: $0, in: transaction) != $0 }.compactMap { storage.getMasterHexEncodedPublicKey(for: $0, in: transaction) })
}
if !newDisplayNameUpdatees.isEmpty {
let displayNameUpdatees = LokiPublicChatAPI.displayNameUpdatees[publicChat.id] ?? []
LokiPublicChatAPI.displayNameUpdatees[publicChat.id] = displayNameUpdatees.union(newDisplayNameUpdatees)
}
messages.forEach { message in messages.forEach { message in
var wasSentByCurrentUser = false var wasSentByCurrentUser = false
OWSPrimaryStorage.shared().dbReadConnection.read { transaction in OWSPrimaryStorage.shared().dbReadConnection.read { transaction in
@ -184,7 +201,6 @@ public final class LokiPublicChatPoller : NSObject {
} }
} }
} }
let uniqueHexEncodedPublicKeys = Set(messages.map { $0.hexEncodedPublicKey })
let hexEncodedPublicKeysToUpdate = uniqueHexEncodedPublicKeys.filter { hexEncodedPublicKey in let hexEncodedPublicKeysToUpdate = uniqueHexEncodedPublicKeys.filter { hexEncodedPublicKey in
let timeSinceLastUpdate: TimeInterval let timeSinceLastUpdate: TimeInterval
if let lastDeviceLinkUpdate = LokiAPI.lastDeviceLinkUpdate[hexEncodedPublicKey] { if let lastDeviceLinkUpdate = LokiAPI.lastDeviceLinkUpdate[hexEncodedPublicKey] {
@ -234,4 +250,8 @@ public final class LokiPublicChatPoller : NSObject {
private func pollForModerators() { private func pollForModerators() {
let _ = LokiPublicChatAPI.getModerators(for: publicChat.channel, on: publicChat.server) let _ = LokiPublicChatAPI.getModerators(for: publicChat.channel, on: publicChat.server)
} }
private func pollForDisplayNames() {
let _ = LokiPublicChatAPI.getDisplayNames(for: publicChat.channel, on: publicChat.server)
}
} }

@ -1227,6 +1227,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
NSUInteger height = attachment.shouldHaveImageSize ? @(attachment.imageSize.height).unsignedIntegerValue : 0; NSUInteger height = attachment.shouldHaveImageSize ? @(attachment.imageSize.height).unsignedIntegerValue : 0;
[groupMessage addAttachmentWithKind:@"attachment" server:publicChat.server serverID:attachment.serverId contentType:attachment.contentType size:attachment.byteCount fileName:attachment.sourceFilename flags:0 width:width height:height caption:attachment.caption url:attachment.downloadURL linkPreviewURL:nil linkPreviewTitle:nil]; [groupMessage addAttachmentWithKind:@"attachment" server:publicChat.server serverID:attachment.serverId contentType:attachment.contentType size:attachment.byteCount fileName:attachment.sourceFilename flags:0 width:width height:height caption:attachment.caption url:attachment.downloadURL linkPreviewURL:nil linkPreviewTitle:nil];
} }
message.actualSenderHexEncodedPublicKey = userHexEncodedPublicKey;
[[LKPublicChatAPI sendMessage:groupMessage toGroup:publicChat.channel onServer:publicChat.server] [[LKPublicChatAPI sendMessage:groupMessage toGroup:publicChat.channel onServer:publicChat.server]
.thenOn(OWSDispatch.sendingQueue, ^(LKGroupMessage *groupMessage) { .thenOn(OWSDispatch.sendingQueue, ^(LKGroupMessage *groupMessage) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@ -1574,7 +1575,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
} }
}]; }];
BOOL shouldSendTranscript = (AreRecipientUpdatesEnabled() || !message.hasSyncedTranscript) && !isNoteToSelf; BOOL isPublicChatMessage = message.isGroupChatMessage;
BOOL shouldSendTranscript = (AreRecipientUpdatesEnabled() || !message.hasSyncedTranscript) && !isNoteToSelf && !isPublicChatMessage;
if (!shouldSendTranscript) { if (!shouldSendTranscript) {
return success(); return success();
} }

Loading…
Cancel
Save