From 4a4e3ce8d0d83b6ba22c3468781bdbf6b2bd53fb Mon Sep 17 00:00:00 2001 From: Jack Hogan Date: Mon, 30 Sep 2024 15:22:26 -0400 Subject: [PATCH 1/4] iOS reachability --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 74257d192..1dc147386 100644 --- a/Package.swift +++ b/Package.swift @@ -27,7 +27,7 @@ let package = Package( .target( name: "DiscordKitCore", dependencies: [ - .product(name: "Reachability", package: "Reachability.swift", condition: .when(platforms: [.macOS])), + .product(name: "Reachability", package: "Reachability.swift", condition: .when(platforms: [.macOS, .iOS])), .product(name: "SwiftProtobuf", package: "swift-protobuf"), .product(name: "Logging", package: "swift-log"), .product(name: "OpenCombine", package: "OpenCombine", condition: .when(platforms: [.linux])), From c6c4024bbeedb0bb4f97435144f42f16d0738312 Mon Sep 17 00:00:00 2001 From: Jack Hogan Date: Mon, 30 Sep 2024 15:41:31 -0400 Subject: [PATCH 2/4] Fixed compile errors on cache --- .../DiscordKit/Gateway/GatewayCachedState.swift | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Sources/DiscordKit/Gateway/GatewayCachedState.swift b/Sources/DiscordKit/Gateway/GatewayCachedState.swift index e409aee3a..563d7373d 100644 --- a/Sources/DiscordKit/Gateway/GatewayCachedState.swift +++ b/Sources/DiscordKit/Gateway/GatewayCachedState.swift @@ -32,12 +32,17 @@ public class CachedState: ObservableObject { /// Populates the cache using the provided event. /// - Parameter event: An incoming Gateway "ready" event. func configure(using event: ReadyEvt) { - event.guilds.forEach(appendOrReplace(_:)) - dms = event.private_channels - user = event.user - event.users.forEach(appendOrReplace(_:)) - event.merged_members.enumerated().forEach { (idx, guildMembers) in - members[event.guilds[idx].id] = guildMembers.first(where: { $0.user_id == event.user.id }) + do { + let guilds = try event.guilds.map({ try $0.unwrap() }) + guilds.forEach(appendOrReplace(_:)) + dms = try event.private_channels.map({ try $0.unwrap() }) + user = event.user + event.users.forEach(appendOrReplace(_:)) + event.merged_members.enumerated().forEach { (idx, guildMembers) in + members[guilds[idx].id] = guildMembers.first(where: { $0.user_id == event.user.id }) + } + } catch { + print("Error configuring cache: \(error.localizedDescription)") } print(members) } From 0536521f581d3192a32b5661af3043177972487e Mon Sep 17 00:00:00 2001 From: Jack Hogan Date: Sun, 6 Oct 2024 21:08:35 -0400 Subject: [PATCH 3/4] Allowed for more attachment data sources --- Sources/DiscordKitCore/REST/APIChannel.swift | 4 +- .../REST/APIMultipartFormBody.swift | 40 +++++++++++++++---- Sources/DiscordKitCore/REST/APIRequest.swift | 4 +- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/Sources/DiscordKitCore/REST/APIChannel.swift b/Sources/DiscordKitCore/REST/APIChannel.swift index f4601d6b8..f73d4814c 100644 --- a/Sources/DiscordKitCore/REST/APIChannel.swift +++ b/Sources/DiscordKitCore/REST/APIChannel.swift @@ -43,7 +43,7 @@ public extension DiscordREST { /// > POST: `/channels/{channel.id}/messages` func createChannelMsg( message: NewMessage, - attachments: [URL] = [], + attachments: [some Attachable] = [URL](), id: Snowflake ) async throws -> Message { return try await postReq(path: "channels/\(id)/messages", body: message, attachments: attachments) @@ -66,7 +66,7 @@ public extension DiscordREST { id: Snowflake, msgID: Snowflake ) async throws -> MessageReadAck { - return try await postReq(path: "channels/\(id)/messages/\(msgID)/ack", body: MessageReadAck(token: nil), attachments: []) + return try await postReq(path: "channels/\(id)/messages/\(msgID)/ack", body: MessageReadAck(token: nil), attachments: [URL]()) } /// Typing Start (Undocumented endpoint!) diff --git a/Sources/DiscordKitCore/REST/APIMultipartFormBody.swift b/Sources/DiscordKitCore/REST/APIMultipartFormBody.swift index bd9265a97..2edad2594 100644 --- a/Sources/DiscordKitCore/REST/APIMultipartFormBody.swift +++ b/Sources/DiscordKitCore/REST/APIMultipartFormBody.swift @@ -7,29 +7,55 @@ import Foundation +#if canImport(AppIntents) +import AppIntents + +@available(macOS 13.0, iOS 16.0, *) +extension IntentFile: Attachable { + public func asAttachable() throws -> AttachableData { + AttachableData(data: self.data, name: self.filename, mimeType: self.type?.preferredMIMEType ?? "application/octet-stream") + } +} +#endif + +public protocol Attachable { + func asAttachable() throws -> AttachableData +} + +public struct AttachableData { + public let data: Data + public let name: String + public let mimeType: String +} + +extension URL: Attachable { + public func asAttachable() throws -> AttachableData { + let name = try self.resourceValues(forKeys: [URLResourceKey.nameKey]).name ?? UUID().uuidString + return AttachableData(data: try Data(contentsOf: self), name: name, mimeType: self.mimeType) + } +} + public extension DiscordREST { static func createMultipartBody( with payloadJson: Data?, boundary: String, - attachments: [URL] + attachments: [some Attachable] ) -> Data { var body = Data() for (num, attachment) in attachments.enumerated() { - guard let name = try? attachment.resourceValues(forKeys: [URLResourceKey.nameKey]).name else { - continue - } - guard let attachmentData = try? Data(contentsOf: attachment) else { + guard let attachmentData = try? attachment.asAttachable() else { DiscordREST.log.error("Could not get data of attachment #\(num)") continue } + let name = attachmentData.name body.append("--\(boundary)\r\n".data(using: .utf8)!) body.append( "Content-Disposition: form-data; name=\"files[\(num)]\"; filename=\"\(name)\"\r\n".data(using: .utf8)! ) - body.append("Content-Type: \(attachment.mimeType)\r\n\r\n".data(using: .utf8)!) - body.append(attachmentData) + body.append("Content-Type: \(attachmentData.mimeType)\r\n\r\n".data(using: .utf8)!) + body.append(attachmentData.data) body.append("\r\n".data(using: .utf8)!) } diff --git a/Sources/DiscordKitCore/REST/APIRequest.swift b/Sources/DiscordKitCore/REST/APIRequest.swift index 880725215..c634221b1 100644 --- a/Sources/DiscordKitCore/REST/APIRequest.swift +++ b/Sources/DiscordKitCore/REST/APIRequest.swift @@ -49,7 +49,7 @@ public extension DiscordREST { func makeRequest( path: String, query: [URLQueryItem] = [], - attachments: [URL] = [], + attachments: [some Attachable] = [URL](), body: Data? = nil, method: RequestMethod = .get ) async throws -> Data { @@ -143,7 +143,7 @@ public extension DiscordREST { func postReq( path: String, body: B? = nil, - attachments: [URL] = [] + attachments: [some Attachable] = [URL]() ) async throws -> D { let payload = body != nil ? try DiscordREST.encoder.encode(body) : nil let respData = try await makeRequest( From 72508d205e6846013ce4ba2fed8c198e7be68e9c Mon Sep 17 00:00:00 2001 From: Jack Hogan Date: Wed, 13 Aug 2025 11:16:32 -0700 Subject: [PATCH 4/4] AttachableData fully public --- Sources/DiscordKitCore/REST/APIMultipartFormBody.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sources/DiscordKitCore/REST/APIMultipartFormBody.swift b/Sources/DiscordKitCore/REST/APIMultipartFormBody.swift index 2edad2594..e60e2faed 100644 --- a/Sources/DiscordKitCore/REST/APIMultipartFormBody.swift +++ b/Sources/DiscordKitCore/REST/APIMultipartFormBody.swift @@ -26,6 +26,12 @@ public struct AttachableData { public let data: Data public let name: String public let mimeType: String + + public init(data: Data, name: String, mimeType: String) { + self.data = data + self.name = name + self.mimeType = mimeType + } } extension URL: Attachable {