Store whisper flag in db and remove unused message 'recipient' value

pull/1049/head
Morgan Pretty 6 months ago
parent ef0f73a38c
commit 222d8b478d

@ -563,6 +563,7 @@
FD2DD58E2C6DBEBF0073D9BE /* SSKMockedExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD22724D2C327BA5004D8A6C /* SSKMockedExtensions.swift */; };
FD2DD5902C6DD13C0073D9BE /* DifferenceKit in Frameworks */ = {isa = PBXBuildFile; productRef = FD2DD58F2C6DD13C0073D9BE /* DifferenceKit */; };
FD3003662A25D5B300B5A5FB /* ConfigMessageReceiveJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3003652A25D5B300B5A5FB /* ConfigMessageReceiveJob.swift */; };
FD3559482CC5BF580088F2A9 /* _020_AddMissingWhisperFlag.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3559472CC5BF550088F2A9 /* _020_AddMissingWhisperFlag.swift */; };
FD368A6829DE8F9C000DBF1E /* _012_AddFTSIfNeeded.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD368A6729DE8F9B000DBF1E /* _012_AddFTSIfNeeded.swift */; };
FD368A6A29DE9E30000DBF1E /* UIContextualAction+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD368A6929DE9E30000DBF1E /* UIContextualAction+Utilities.swift */; };
FD37E9C328A1C6F3003AE748 /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD37E9C228A1C6F3003AE748 /* ThemeManager.swift */; };
@ -1731,6 +1732,7 @@
FD2B4AFE2946C93200AB4848 /* ConfigurationSyncJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationSyncJob.swift; sourceTree = "<group>"; };
FD2B4B032949887A00AB4848 /* QueryInterfaceRequest+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "QueryInterfaceRequest+Utilities.swift"; sourceTree = "<group>"; };
FD3003652A25D5B300B5A5FB /* ConfigMessageReceiveJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigMessageReceiveJob.swift; sourceTree = "<group>"; };
FD3559472CC5BF550088F2A9 /* _020_AddMissingWhisperFlag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _020_AddMissingWhisperFlag.swift; sourceTree = "<group>"; };
FD368A6729DE8F9B000DBF1E /* _012_AddFTSIfNeeded.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _012_AddFTSIfNeeded.swift; sourceTree = "<group>"; };
FD368A6929DE9E30000DBF1E /* UIContextualAction+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIContextualAction+Utilities.swift"; sourceTree = "<group>"; };
FD37E9C228A1C6F3003AE748 /* ThemeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = "<group>"; };
@ -3686,6 +3688,7 @@
FD428B222B4B9969006D0888 /* _017_RebuildFTSIfNeeded_2_4_5.swift */,
7B5233C5290636D700F8F375 /* _018_DisappearingMessagesConfiguration.swift */,
FDDD554D2C1FCB77006CBF03 /* _019_ScheduleAppUpdateCheckJob.swift */,
FD3559472CC5BF550088F2A9 /* _020_AddMissingWhisperFlag.swift */,
);
path = Migrations;
sourceTree = "<group>";
@ -5030,7 +5033,8 @@
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
Base
en,
Base,
);
mainGroup = D221A07E169C9E5E00537ABF;
packageReferences = (
@ -5872,6 +5876,7 @@
FDC13D582A17207D007267C7 /* UnsubscribeResponse.swift in Sources */,
FD09799927FFC1A300936362 /* Attachment.swift in Sources */,
FD245C5F2850662200B966DD /* OWSWindowManager.m in Sources */,
FD3559482CC5BF580088F2A9 /* _020_AddMissingWhisperFlag.swift in Sources */,
FDF40CDE2897A1BC006A0CC4 /* _004_RemoveLegacyYDB.swift in Sources */,
FDF0B74928060D13004C14C5 /* QuotedReplyModel.swift in Sources */,
FD3003662A25D5B300B5A5FB /* ConfigMessageReceiveJob.swift in Sources */,

@ -36,7 +36,8 @@ public enum SNMessagingKit: MigratableTarget { // Just to make the external API
_016_MakeBrokenProfileTimestampsNullable.self,
_017_RebuildFTSIfNeeded_2_4_5.self,
_018_DisappearingMessagesConfiguration.self,
_019_ScheduleAppUpdateCheckJob.self
_019_ScheduleAppUpdateCheckJob.self,
_020_AddMissingWhisperFlag.self
]
]
)

@ -0,0 +1,28 @@
// Copyright © 2024 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtilitiesKit
enum _020_AddMissingWhisperFlag: Migration {
static let target: TargetMigrations.Identifier = .messagingKit
static let identifier: String = "AddMissingWhisperFlag"
static let needsConfigSync: Bool = false
static let minExpectedRunDuration: TimeInterval = 0.1
static var requirements: [MigrationRequirement] = []
static let fetchedTables: [(TableRecord & FetchableRecord).Type] = []
static let createdOrAlteredTables: [(TableRecord & FetchableRecord).Type] = [Interaction.self]
static let droppedTables: [(TableRecord & FetchableRecord).Type] = []
static func migrate(_ db: Database, using dependencies: Dependencies) throws {
/// We should have had this column from the very beginning but it was missed, so add it in now for when we eventually
/// support whispers in Community conversations
try db.alter(table: Interaction.self) { t in
t.add(.openGroupWhisper, .boolean)
.notNull()
.defaults(to: false)
}
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

@ -64,6 +64,7 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
case openGroupServerMessageId
case openGroupWhisperMods
case openGroupWhisperTo
case openGroupWhisper
}
public enum Variant: Int, Codable, Hashable, DatabaseValueConvertible {
@ -231,6 +232,9 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
/// This value is the id of the user within an Open Group who is the target of this whisper interaction
public let openGroupWhisperTo: String?
/// This flag indicates whether this interaction is a whisper
public let openGroupWhisper: Bool
// MARK: - Relationships
public var thread: QueryInterfaceRequest<SessionThread> {
@ -291,6 +295,7 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
expiresStartedAtMs: Double?,
linkPreviewUrl: String?,
openGroupServerMessageId: Int64?,
openGroupWhisper: Bool,
openGroupWhisperMods: Bool,
openGroupWhisperTo: String?
) {
@ -309,6 +314,7 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
self.expiresStartedAtMs = expiresStartedAtMs
self.linkPreviewUrl = linkPreviewUrl
self.openGroupServerMessageId = openGroupServerMessageId
self.openGroupWhisper = openGroupWhisper
self.openGroupWhisperMods = openGroupWhisperMods
self.openGroupWhisperTo = openGroupWhisperTo
}
@ -328,6 +334,7 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
expiresStartedAtMs: Double? = nil,
linkPreviewUrl: String? = nil,
openGroupServerMessageId: Int64? = nil,
openGroupWhisper: Bool = false,
openGroupWhisperMods: Bool = false,
openGroupWhisperTo: String? = nil
) {
@ -352,6 +359,7 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
self.expiresStartedAtMs = (threadVariant != .community ? expiresStartedAtMs : nil)
self.linkPreviewUrl = linkPreviewUrl
self.openGroupServerMessageId = openGroupServerMessageId
self.openGroupWhisper = openGroupWhisper
self.openGroupWhisperMods = openGroupWhisperMods
self.openGroupWhisperTo = openGroupWhisperTo
}
@ -474,6 +482,7 @@ public extension Interaction {
expiresStartedAtMs: (expiresStartedAtMs ?? self.expiresStartedAtMs),
linkPreviewUrl: self.linkPreviewUrl,
openGroupServerMessageId: (openGroupServerMessageId ?? self.openGroupServerMessageId),
openGroupWhisper: self.openGroupWhisper,
openGroupWhisperMods: self.openGroupWhisperMods,
openGroupWhisperTo: self.openGroupWhisperTo
)
@ -836,8 +845,6 @@ public extension Interaction {
return (expiresInSeconds ?? 0 > 0)
}
var openGroupWhisper: Bool { return (openGroupWhisperMods || (openGroupWhisperTo != nil)) }
var notificationIdentifiers: [String] {
[
notificationIdentifier(shouldGroupMessagesForThread: true),
@ -880,6 +887,7 @@ public extension Interaction {
expiresStartedAtMs: expiresStartedAtMs,
linkPreviewUrl: nil,
openGroupServerMessageId: openGroupServerMessageId,
openGroupWhisper: openGroupWhisper,
openGroupWhisperMods: openGroupWhisperMods,
openGroupWhisperTo: openGroupWhisperTo
)

@ -17,7 +17,10 @@ public extension Message {
openGroupId: String,
sender: String,
timestamp: TimeInterval,
messageServerId: Int64
messageServerId: Int64,
whisper: Bool,
whisperMods: Bool,
whisperTo: String?
)
case openGroupInbox(
timestamp: TimeInterval,

@ -10,9 +10,11 @@ public class Message: Codable {
public var id: String?
public var sentTimestamp: UInt64?
public var receivedTimestamp: UInt64?
public var recipient: String?
public var sender: String?
public var openGroupServerMessageId: UInt64?
public var openGroupWhisper: Bool
public var openGroupWhisperMods: Bool
public var openGroupWhisperTo: String?
public var serverHash: String?
public var ttl: UInt64 { 14 * 24 * 60 * 60 * 1000 }
public var isSelfSendValid: Bool { false }
@ -29,7 +31,7 @@ public class Message: Codable {
public var isValid: Bool {
if let sentTimestamp = sentTimestamp { guard sentTimestamp > 0 else { return false } }
if let receivedTimestamp = receivedTimestamp { guard receivedTimestamp > 0 else { return false } }
return sender != nil && recipient != nil
return sender != nil
}
// MARK: - Initialization
@ -38,9 +40,11 @@ public class Message: Codable {
id: String? = nil,
sentTimestamp: UInt64? = nil,
receivedTimestamp: UInt64? = nil,
recipient: String? = nil,
sender: String? = nil,
openGroupServerMessageId: UInt64? = nil,
openGroupWhisper: Bool = false,
openGroupWhisperMods: Bool = false,
openGroupWhisperTo: String? = nil,
serverHash: String? = nil,
expiresInSeconds: TimeInterval? = nil,
expiresStartedAtMs: Double? = nil
@ -48,9 +52,11 @@ public class Message: Codable {
self.id = id
self.sentTimestamp = sentTimestamp
self.receivedTimestamp = receivedTimestamp
self.recipient = recipient
self.sender = sender
self.openGroupServerMessageId = openGroupServerMessageId
self.openGroupWhisper = openGroupWhisper
self.openGroupWhisperMods = openGroupWhisperMods
self.openGroupWhisperTo = openGroupWhisperTo
self.serverHash = serverHash
self.expiresInSeconds = expiresInSeconds
self.expiresStartedAtMs = expiresStartedAtMs
@ -406,7 +412,10 @@ public extension Message {
openGroupId: openGroupId,
sender: sender,
timestamp: timestamp,
messageServerId: message.id
messageServerId: message.id,
whisper: message.whisper,
whisperMods: message.whisperMods,
whisperTo: message.whisperTo
),
using: dependencies
)

@ -56,7 +56,6 @@ public final class VisibleMessage: Message {
public init(
sender: String? = nil,
sentTimestamp: UInt64? = nil,
recipient: String? = nil,
syncTarget: String? = nil,
text: String?,
attachmentIds: [String] = [],
@ -79,7 +78,6 @@ public final class VisibleMessage: Message {
super.init(
sentTimestamp: sentTimestamp,
recipient: recipient,
sender: sender
)
}
@ -241,7 +239,6 @@ public extension VisibleMessage {
let visibleMessage: VisibleMessage = VisibleMessage(
sender: interaction.authorId,
sentTimestamp: UInt64(interaction.timestampMs),
recipient: (try? interaction.recipientStates.fetchOne(db))?.recipientId,
syncTarget: nil,
text: interaction.body,
attachmentIds: ((try? interaction.attachments.fetchAll(db)) ?? [])

@ -174,15 +174,9 @@ extension MessageReceiver {
linkPreviewUrl: (message.linkPreview?.url ?? message.openGroupInvitation?.url),
// Keep track of the open group server message ID message ID relationship
openGroupServerMessageId: message.openGroupServerMessageId.map { Int64($0) },
openGroupWhisperMods: (message.recipient?.contains(".mods") == true),
openGroupWhisperTo: {
guard
let recipientParts: [String] = message.recipient?.components(separatedBy: "."),
recipientParts.count >= 3 // 'server.roomToken.whisperTo.whisperMods'
else { return nil }
return recipientParts[2]
}()
openGroupWhisper: message.openGroupWhisper,
openGroupWhisperMods: message.openGroupWhisperMods,
openGroupWhisperTo: message.openGroupWhisperTo
).inserted(db)
// stringlint:ignore_stop
}

@ -23,6 +23,9 @@ public enum MessageReceiver {
let sentTimestamp: UInt64
let serverHash: String?
let openGroupServerMessageId: UInt64?
let openGroupWhisper: Bool
let openGroupWhisperMods: Bool
let openGroupWhisperTo: String?
let threadVariant: SessionThread.Variant
let threadIdGenerator: (Message) throws -> String
@ -37,12 +40,15 @@ public enum MessageReceiver {
data: data
)
case (_, .community(let openGroupId, let messageSender, let timestamp, let messageServerId)):
case (_, .community(let openGroupId, let messageSender, let timestamp, let messageServerId, let messageWhisper, let messageWhisperMods, let messageWhisperTo)):
plaintext = data.removePadding() // Remove the padding
sender = messageSender
sentTimestamp = UInt64(floor(timestamp * 1000)) // Convert to ms for database consistency
serverHash = nil
openGroupServerMessageId = UInt64(messageServerId)
openGroupWhisper = messageWhisper
openGroupWhisperMods = messageWhisperMods
openGroupWhisperTo = messageWhisperTo
threadVariant = .community
threadIdGenerator = { message in
// Guard against control messages in open groups
@ -67,6 +73,9 @@ public enum MessageReceiver {
sentTimestamp = UInt64(floor(timestamp * 1000)) // Convert to ms for database consistency
serverHash = nil
openGroupServerMessageId = UInt64(messageServerId)
openGroupWhisper = false
openGroupWhisperMods = false
openGroupWhisperTo = nil
threadVariant = .contact
threadIdGenerator = { _ in sender }
@ -92,6 +101,9 @@ public enum MessageReceiver {
sentTimestamp = envelope.timestamp
serverHash = swarmServerHash
openGroupServerMessageId = nil
openGroupWhisper = false
openGroupWhisperMods = false
openGroupWhisperTo = nil
threadVariant = .contact
threadIdGenerator = { message in
switch message {
@ -156,6 +168,9 @@ public enum MessageReceiver {
}
openGroupServerMessageId = nil
openGroupWhisper = false
openGroupWhisperMods = false
openGroupWhisperTo = nil
threadVariant = .legacyGroup
threadIdGenerator = { _ in publicKey }
@ -176,11 +191,13 @@ public enum MessageReceiver {
.successOrThrow())
let message: Message = try (customMessage ?? Message.createMessageFrom(proto, sender: sender))
message.sender = sender
message.recipient = userSessionId
message.serverHash = serverHash
message.sentTimestamp = sentTimestamp
message.receivedTimestamp = UInt64(SnodeAPI.currentOffsetTimestampMs())
message.openGroupServerMessageId = openGroupServerMessageId
message.openGroupWhisper = openGroupWhisper
message.openGroupWhisperMods = openGroupWhisperMods
message.openGroupWhisperTo = openGroupWhisperTo
// Ignore disappearing message settings in communities (in case of modified clients)
if threadVariant != .community {

@ -190,14 +190,6 @@ public final class MessageSender {
using dependencies: Dependencies
) throws -> PreparedSendData {
message.sender = userPublicKey
message.recipient = {
switch destination {
case .contact(let publicKey): return publicKey
case .syncMessage: return userPublicKey
case .closedGroup(let groupPublicKey): return groupPublicKey
case .openGroup, .openGroupInbox: preconditionFailure()
}
}()
// Validate the message
guard message.isValid, let namespace: SnodeAPI.Namespace = namespace else {
@ -213,9 +205,10 @@ public final class MessageSender {
// Attach the user's profile if needed (no need to do so for 'Note to Self' or sync
// messages as they will be managed by the user config handling
switch (destination, (message.recipient == userPublicKey), message as? MessageWithProfile) {
case (.syncMessage, _, _), (_, true, _), (_, _, .none): break
case (_, _, .some(var messageWithProfile)):
switch (destination, message as? MessageWithProfile) {
case (.syncMessage, _), (_, .none): break
case (.contact(let publicKey), _) where publicKey == userPublicKey: break
case (_, .some(var messageWithProfile)):
let profile: Profile = Profile.fetchOrCreateCurrentUser(db)
if let profileKey: Data = profile.profileEncryptionKey, let profilePictureUrl: String = profile.profilePictureUrl {
@ -330,7 +323,14 @@ public final class MessageSender {
let base64EncodedData = wrappedMessage.base64EncodedString()
let snodeMessage = SnodeMessage(
recipient: message.recipient!,
recipient: {
switch destination {
case .contact(let publicKey): return publicKey
case .syncMessage: return userPublicKey
case .closedGroup(let groupPublicKey): return groupPublicKey
case .openGroup, .openGroupInbox: preconditionFailure()
}
}(),
data: base64EncodedData,
ttl: Message.getSpecifiedTTL(
message: message,
@ -361,16 +361,8 @@ public final class MessageSender {
// stringlint:ignore_start
switch destination {
case .contact, .syncMessage, .closedGroup, .openGroupInbox: preconditionFailure()
case .openGroup(let roomToken, let server, let whisperTo, let whisperMods, _):
case .openGroup(let roomToken, let server, _, _, _):
threadId = OpenGroup.idFor(roomToken: roomToken, server: server)
message.recipient = [
server,
roomToken,
whisperTo,
(whisperMods ? "mods" : nil)
]
.compactMap { $0 }
.joined(separator: ".")
}
// stringlint:ignore_stop
@ -497,7 +489,6 @@ public final class MessageSender {
}
message.sender = userPublicKey
message.recipient = recipientBlindedPublicKey
// Attach the user's profile if needed
if let message: VisibleMessage = message as? VisibleMessage {

@ -149,6 +149,7 @@ class MessageSendJobSpec: QuickSpec {
expiresStartedAtMs: nil,
linkPreviewUrl: nil,
openGroupServerMessageId: nil,
openGroupWhisper: false,
openGroupWhisperMods: false,
openGroupWhisperTo: nil
)

@ -31,6 +31,7 @@ class OpenGroupManagerSpec: QuickSpec {
expiresStartedAtMs: nil,
linkPreviewUrl: nil,
openGroupServerMessageId: nil,
openGroupWhisper: false,
openGroupWhisperMods: false,
openGroupWhisperTo: nil
)

Loading…
Cancel
Save