Skip to content

Commit

Permalink
Consent filtering by array (#460)
Browse files Browse the repository at this point in the history
* update sdk version

* disable history sync

* remove setting consent on message send

* add the message expiration stuff

* add creating groups and dms by inboxIds

* add a bunch of tests

* add a last message test

* get the tests passing
  • Loading branch information
nplasterer authored Jan 17, 2025
1 parent 696dc30 commit 52f80ac
Show file tree
Hide file tree
Showing 14 changed files with 456 additions and 184 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ let package = Package(
.package(url: "https://github.com/bufbuild/connect-swift", exact: "1.0.0"),
.package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.4.3"),
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", exact: "1.8.3"),
.package(url: "https://github.com/xmtp/libxmtp-swift.git", exact: "3.0.18")
.package(url: "https://github.com/xmtp/libxmtp-swift.git", exact: "3.0.20")
],
targets: [
.target(
Expand Down
15 changes: 1 addition & 14 deletions Sources/XMTPiOS/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,7 @@ public struct ClientOptions {
self.preAuthenticateToInboxCallback = preAuthenticateToInboxCallback
self.dbEncryptionKey = dbEncryptionKey
self.dbDirectory = dbDirectory
if historySyncUrl == nil {
switch api.env {
case .production:
self.historySyncUrl =
"https://message-history.production.ephemera.network/"
case .local:
self.historySyncUrl = "http://localhost:5558"
default:
self.historySyncUrl =
"https://message-history.dev.ephemera.network/"
}
} else {
self.historySyncUrl = historySyncUrl
}
self.historySyncUrl = historySyncUrl
}
}

Expand Down
166 changes: 141 additions & 25 deletions Sources/XMTPiOS/Conversations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,21 @@ public actor Conversations {
public func sync() async throws {
try await ffiConversations.sync()
}
public func syncAllConversations(consentState: ConsentState? = nil)
public func syncAllConversations(consentStates: [ConsentState]? = nil)
async throws -> UInt32
{
return try await ffiConversations.syncAllConversations(
consentState: consentState?.toFFI)
consentStates: consentStates?.toFFI)
}

public func listGroups(
createdAfter: Date? = nil, createdBefore: Date? = nil,
limit: Int? = nil,
consentState: ConsentState? = nil
consentStates: [ConsentState]? = nil
) throws -> [Group] {
var options = FfiListConversationsOptions(
createdAfterNs: nil, createdBeforeNs: nil, limit: nil,
consentState: consentState?.toFFI, includeDuplicateDms: false)
consentStates: consentStates?.toFFI, includeDuplicateDms: false)
if let createdAfter {
options.createdAfterNs = Int64(createdAfter.millisecondsSinceEpoch)
}
Expand All @@ -111,11 +111,11 @@ public actor Conversations {
public func listDms(
createdAfter: Date? = nil, createdBefore: Date? = nil,
limit: Int? = nil,
consentState: ConsentState? = nil
consentStates: [ConsentState]? = nil
) throws -> [Dm] {
var options = FfiListConversationsOptions(
createdAfterNs: nil, createdBeforeNs: nil, limit: nil,
consentState: consentState?.toFFI, includeDuplicateDms: false)
consentStates: consentStates?.toFFI, includeDuplicateDms: false)
if let createdAfter {
options.createdAfterNs = Int64(createdAfter.millisecondsSinceEpoch)
}
Expand All @@ -137,11 +137,11 @@ public actor Conversations {
public func list(
createdAfter: Date? = nil, createdBefore: Date? = nil,
limit: Int? = nil,
consentState: ConsentState? = nil
consentStates: [ConsentState]? = nil
) async throws -> [Conversation] {
var options = FfiListConversationsOptions(
createdAfterNs: nil, createdBeforeNs: nil, limit: nil,
consentState: consentState?.toFFI, includeDuplicateDms: false)
consentStates: consentStates?.toFFI, includeDuplicateDms: false)
if let createdAfter {
options.createdAfterNs = Int64(createdAfter.millisecondsSinceEpoch)
}
Expand Down Expand Up @@ -227,6 +227,13 @@ public actor Conversations {
}
}

public func newConversation(
with peerAddress: String
) async throws -> Conversation {
let dm = try await findOrCreateDm(with: peerAddress)
return Conversation.dm(dm)
}

public func findOrCreateDm(with peerAddress: String) async throws -> Dm {
if peerAddress.lowercased() == client.address.lowercased() {
throw ConversationError.memberCannotBeSelf
Expand All @@ -249,13 +256,39 @@ public actor Conversations {
return newDm
}

public func newConversationWithInboxId(
with peerInboxId: String
) async throws -> Conversation {
let dm = try await findOrCreateDmWithInboxId(with: peerInboxId)
return Conversation.dm(dm)
}

public func findOrCreateDmWithInboxId(with peerInboxId: String)
async throws -> Dm
{
if peerInboxId.lowercased() == client.inboxID.lowercased() {
throw ConversationError.memberCannotBeSelf
}
if let existingDm = try client.findDmByInboxId(inboxId: peerInboxId) {
return existingDm
}

let newDm =
try await ffiConversations
.createDmWithInboxId(inboxId: peerInboxId)
.dmFromFFI(client: client)
return newDm
}

public func newGroup(
with addresses: [String],
permissions: GroupPermissionPreconfiguration = .allMembers,
name: String = "",
imageUrlSquare: String = "",
description: String = "",
pinnedFrameUrl: String = ""
pinnedFrameUrl: String = "",
messageExpirationFromMs: Int64? = nil,
messageExpirationMs: Int64? = nil
) async throws -> Group {
return try await newGroupInternal(
with: addresses,
Expand All @@ -266,7 +299,9 @@ public actor Conversations {
imageUrlSquare: imageUrlSquare,
description: description,
pinnedFrameUrl: pinnedFrameUrl,
permissionPolicySet: nil
permissionPolicySet: nil,
messageExpirationFromMs: messageExpirationMs,
messageExpirationMs: messageExpirationMs
)
}

Expand All @@ -276,7 +311,9 @@ public actor Conversations {
name: String = "",
imageUrlSquare: String = "",
description: String = "",
pinnedFrameUrl: String = ""
pinnedFrameUrl: String = "",
messageExpirationFromMs: Int64? = nil,
messageExpirationMs: Int64? = nil
) async throws -> Group {
return try await newGroupInternal(
with: addresses,
Expand All @@ -286,18 +323,22 @@ public actor Conversations {
description: description,
pinnedFrameUrl: pinnedFrameUrl,
permissionPolicySet: PermissionPolicySet.toFfiPermissionPolicySet(
permissionPolicySet)
permissionPolicySet),
messageExpirationFromMs: messageExpirationMs,
messageExpirationMs: messageExpirationMs
)
}

private func newGroupInternal(
with addresses: [String],
permissions: FfiGroupPermissionsOptions = .allMembers,
permissions: FfiGroupPermissionsOptions = .default,
name: String = "",
imageUrlSquare: String = "",
description: String = "",
pinnedFrameUrl: String = "",
permissionPolicySet: FfiPermissionPolicySet? = nil
permissionPolicySet: FfiPermissionPolicySet? = nil,
messageExpirationFromMs: Int64? = nil,
messageExpirationMs: Int64? = nil
) async throws -> Group {
if addresses.first(where: {
$0.lowercased() == client.address.lowercased()
Expand All @@ -322,7 +363,90 @@ public actor Conversations {
groupImageUrlSquare: imageUrlSquare,
groupDescription: description,
groupPinnedFrameUrl: pinnedFrameUrl,
customPermissionPolicySet: permissionPolicySet
customPermissionPolicySet: permissionPolicySet,
messageExpirationFromMs: messageExpirationMs,
messageExpirationMs: messageExpirationMs
)
).groupFromFFI(client: client)
return group
}

public func newGroupWithInboxIds(
with inboxIds: [String],
permissions: GroupPermissionPreconfiguration = .allMembers,
name: String = "",
imageUrlSquare: String = "",
description: String = "",
pinnedFrameUrl: String = "",
messageExpirationFromMs: Int64? = nil,
messageExpirationMs: Int64? = nil
) async throws -> Group {
return try await newGroupInternalWithInboxIds(
with: inboxIds,
permissions:
GroupPermissionPreconfiguration.toFfiGroupPermissionOptions(
option: permissions),
name: name,
imageUrlSquare: imageUrlSquare,
description: description,
pinnedFrameUrl: pinnedFrameUrl,
permissionPolicySet: nil,
messageExpirationFromMs: messageExpirationMs,
messageExpirationMs: messageExpirationMs
)
}

public func newGroupCustomPermissionsWithInboxIds(
with inboxIds: [String],
permissionPolicySet: PermissionPolicySet,
name: String = "",
imageUrlSquare: String = "",
description: String = "",
pinnedFrameUrl: String = "",
messageExpirationFromMs: Int64? = nil,
messageExpirationMs: Int64? = nil
) async throws -> Group {
return try await newGroupInternalWithInboxIds(
with: inboxIds,
permissions: FfiGroupPermissionsOptions.customPolicy,
name: name,
imageUrlSquare: imageUrlSquare,
description: description,
pinnedFrameUrl: pinnedFrameUrl,
permissionPolicySet: PermissionPolicySet.toFfiPermissionPolicySet(
permissionPolicySet),
messageExpirationFromMs: messageExpirationMs,
messageExpirationMs: messageExpirationMs
)
}

private func newGroupInternalWithInboxIds(
with inboxIds: [String],
permissions: FfiGroupPermissionsOptions = .default,
name: String = "",
imageUrlSquare: String = "",
description: String = "",
pinnedFrameUrl: String = "",
permissionPolicySet: FfiPermissionPolicySet? = nil,
messageExpirationFromMs: Int64? = nil,
messageExpirationMs: Int64? = nil
) async throws -> Group {
if inboxIds.contains(where: {
$0.lowercased() == client.inboxID.lowercased()
}) {
throw ConversationError.memberCannotBeSelf
}
let group = try await ffiConversations.createGroupWithInboxIds(
inboxIds: inboxIds,
opts: FfiCreateGroupOptions(
permissions: permissions,
groupName: name,
groupImageUrlSquare: imageUrlSquare,
groupDescription: description,
groupPinnedFrameUrl: pinnedFrameUrl,
customPermissionPolicySet: permissionPolicySet,
messageExpirationFromMs: messageExpirationMs,
messageExpirationMs: messageExpirationMs
)
).groupFromFFI(client: client)
return group
Expand All @@ -334,7 +458,7 @@ public actor Conversations {
AsyncThrowingStream { continuation in
let ffiStreamActor = FfiStreamActor()

let messageCallback = MessageCallback() {
let messageCallback = MessageCallback {
message in
guard !Task.isCancelled else {
continuation.finish()
Expand All @@ -343,8 +467,7 @@ public actor Conversations {
}
return
}
if let message = Message.create(ffiMessage: message)
{
if let message = Message.create(ffiMessage: message) {
continuation.yield(message)
}
}
Expand Down Expand Up @@ -386,13 +509,6 @@ public actor Conversations {
return try await conversation.toConversation(client: client)
}

public func newConversation(
with peerAddress: String
) async throws -> Conversation {
let dm = try await findOrCreateDm(with: peerAddress)
return Conversation.dm(dm)
}

public func getHmacKeys() throws
-> Xmtp_KeystoreApi_V1_GetConversationHmacKeysResponse
{
Expand Down
12 changes: 0 additions & 12 deletions Sources/XMTPiOS/Dm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,6 @@ public struct Dm: Identifiable, Equatable, Hashable {
}

public func send(encodedContent: EncodedContent) async throws -> String {
if try consentState() == .unknown {
try await updateConsentState(state: .allowed)
}

let messageId = try await ffiConversation.send(
contentBytes: encodedContent.serializedData())
return messageId.toHex
Expand Down Expand Up @@ -136,10 +132,6 @@ public struct Dm: Identifiable, Equatable, Hashable {
public func prepareMessage(encodedContent: EncodedContent) async throws
-> String
{
if try consentState() == .unknown {
try await updateConsentState(state: .allowed)
}

let messageId = try ffiConversation.sendOptimistic(
contentBytes: encodedContent.serializedData())
return messageId.toHex
Expand All @@ -148,10 +140,6 @@ public struct Dm: Identifiable, Equatable, Hashable {
public func prepareMessage<T>(content: T, options: SendOptions? = nil)
async throws -> String
{
if try consentState() == .unknown {
try await updateConsentState(state: .allowed)
}

let encodeContent = try await encodeContent(
content: content, options: options)
return try ffiConversation.sendOptimistic(
Expand Down
6 changes: 6 additions & 0 deletions Sources/XMTPiOS/Extensions/Ffi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ extension FfiConversationMember {
}
}

extension Array where Element == ConsentState {
var toFFI: [FfiConsentState] {
return self.map { $0.toFFI }
}
}

extension ConsentState {
var toFFI: FfiConsentState {
switch self {
Expand Down
12 changes: 0 additions & 12 deletions Sources/XMTPiOS/Group.swift
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,6 @@ public struct Group: Identifiable, Equatable, Hashable {
}

public func send(encodedContent: EncodedContent) async throws -> String {
if try consentState() == .unknown {
try await updateConsentState(state: .allowed)
}

let messageId = try await ffiGroup.send(
contentBytes: encodedContent.serializedData())
return messageId.toHex
Expand Down Expand Up @@ -332,10 +328,6 @@ public struct Group: Identifiable, Equatable, Hashable {
public func prepareMessage(encodedContent: EncodedContent) async throws
-> String
{
if try consentState() == .unknown {
try await updateConsentState(state: .allowed)
}

let messageId = try ffiGroup.sendOptimistic(
contentBytes: encodedContent.serializedData())
return messageId.toHex
Expand All @@ -344,10 +336,6 @@ public struct Group: Identifiable, Equatable, Hashable {
public func prepareMessage<T>(content: T, options: SendOptions? = nil)
async throws -> String
{
if try consentState() == .unknown {
try await updateConsentState(state: .allowed)
}

let encodeContent = try await encodeContent(
content: content, options: options)
return try ffiGroup.sendOptimistic(
Expand Down
Loading

0 comments on commit 52f80ac

Please sign in to comment.