Skip to content

Commit

Permalink
Merge pull request #60 from andylin2004/main
Browse files Browse the repository at this point in the history
Adding functions related to clients reposting a Bluesky post
  • Loading branch information
MasterJ93 authored Dec 7, 2024
2 parents 4d5cff0 + 04738f1 commit 38ac43a
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 82 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// DeleteActionRecord.swift
// ATProtoKit
//
// Created by Andy Lin on 11/27/24.
//

import Foundation

extension ATProtoBluesky {

/// Deletes a record.
///
/// This can also be used to validate if a record has been deleted.
/// - Parameter record: The record that needs to be deleted.
///
/// This can be either the URI of the record, or the full record object itself.
internal func deleteActionRecord(_ record: RecordIdentifier) async throws {
guard let session else {
throw ATRequestPrepareError.missingActiveSession
}

guard let sessionURL = session.pdsURL else {
throw ATRequestPrepareError.invalidRequestURL
}

var actionRecord: ATProtoTools.RecordQuery? = nil
try await resolveRecordIdentifierToQuery(record, sessionURL, &actionRecord)

let requestBody = actionRecord

guard let repositoryDID = requestBody?.repository,
let actionCollection = requestBody?.collection,
let actionRecordKey = requestBody?.recordKey else {
throw ATRequestPrepareError.invalidRecord
}

try await atProtoKitInstance.deleteRecord(
repositoryDID: repositoryDID,
collection: actionCollection,
recordKey: actionRecordKey,
swapRecord: requestBody?.recordCID
)
}

fileprivate func resolveRecordIdentifierToQuery(_ record: RecordIdentifier, _ sessionURL: String,
_ actionRecord: inout ATProtoTools.RecordQuery?) async throws {
switch record {
case .recordQuery(let recordQuery):
do {
// Perform the fetch and validation based on recordQuery.
let output = try await atProtoKitInstance.getRepositoryRecord(from: recordQuery.repository,
collection: recordQuery.collection,
recordKey: recordQuery.recordKey,
recordCID: recordQuery.recordCID,
pdsURL: sessionURL
)

let recordURI = "at://\(recordQuery.repository)/\(recordQuery.collection)/\(recordQuery.recordKey)"

guard output.recordURI == recordURI else {
throw ATRequestPrepareError.invalidRecord
}
} catch {
throw error
}

case .recordURI(let recordURI):
do {
// Perform the fetch and validation based on the parsed URI.
let parsedURI = try ATProtoTools().parseURI(recordURI)
let output = try await atProtoKitInstance.getRepositoryRecord(from: parsedURI.repository,
collection: parsedURI.collection,
recordKey: parsedURI.recordKey,
recordCID: parsedURI.recordCID,
pdsURL: sessionURL
)

guard recordURI == output.recordURI else {
throw ATRequestPrepareError.invalidRecord
}

actionRecord = parsedURI
} catch {
throw error
}
}
}

/// Identifies the record based on the specific information provided.
///
/// `RecordIdentifier` provides a unified interface for specifying how the record is defined.
/// This allows methods like ``deleteActionRecord(_:)`` to handle the backend of how to grab the
/// details of the record so it can delete it.
public enum RecordIdentifier {
/// The record object itself.
/// - Parameter recordQuery: the record object.
case recordQuery(recordQuery: ATProtoTools.RecordQuery)
/// The URI of the record.
case recordURI(atURI: String)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,87 +16,6 @@ extension ATProtoBluesky {
///
/// This can be either the URI of the record, or the full record object itself.
public func deleteLikeRecord(_ record: RecordIdentifier) async throws {
guard let session else {
throw ATRequestPrepareError.missingActiveSession
}

guard let sessionURL = session.pdsURL else {
throw ATRequestPrepareError.invalidRequestURL
}

var likeRecord: ATProtoTools.RecordQuery? = nil
try await resolveRecordIdentifierToQuery(record, sessionURL, &likeRecord)

let requestBody = likeRecord

guard let repositoryDID = requestBody?.repository,
let likeCollection = requestBody?.collection,
let likeRecordKey = requestBody?.recordKey else {
throw ATRequestPrepareError.invalidRecord
}

try await atProtoKitInstance.deleteRecord(
repositoryDID: repositoryDID,
collection: likeCollection,
recordKey: likeRecordKey,
swapRecord: requestBody?.recordCID
)
}

fileprivate func resolveRecordIdentifierToQuery(_ record: RecordIdentifier, _ sessionURL: String,
_ likeRecord: inout ATProtoTools.RecordQuery?) async throws {
switch record {
case .recordQuery(let recordQuery):
do {
// Perform the fetch and validation based on recordQuery.
let output = try await atProtoKitInstance.getRepositoryRecord(from: recordQuery.repository,
collection: recordQuery.collection,
recordKey: recordQuery.recordKey,
recordCID: recordQuery.recordCID,
pdsURL: sessionURL
)

let recordURI = "at://\(recordQuery.repository)/\(recordQuery.collection)/\(recordQuery.recordKey)"

guard output.recordURI == recordURI else {
throw ATRequestPrepareError.invalidRecord
}
} catch {
throw error
}

case .recordURI(let recordURI):
do {
// Perform the fetch and validation based on the parsed URI.
let parsedURI = try ATProtoTools().parseURI(recordURI)
let output = try await atProtoKitInstance.getRepositoryRecord(from: parsedURI.repository,
collection: parsedURI.collection,
recordKey: parsedURI.recordKey,
recordCID: parsedURI.recordCID,
pdsURL: sessionURL
)

guard recordURI == output.recordURI else {
throw ATRequestPrepareError.invalidRecord
}

likeRecord = parsedURI
} catch {
throw error
}
}
}

/// Identifies the record based on the specific information provided.
///
/// `RecordIdentifier` provides a unified interface for specifying how the record is defined.
/// This allows methods like ``deleteLikeRecord(_:)`` to handle the backend of how to grab the
/// details of the record so it can delete it.
public enum RecordIdentifier {
/// The record object itself.
/// - Parameter recordQuery: the record object.
case recordQuery(recordQuery: ATProtoTools.RecordQuery)
/// The URI of the record.
case recordURI(atURI: String)
return try await deleteActionRecord(record)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,45 @@ import Foundation

extension ATProtoBluesky {

/// Create a repost record to a user's post.
///
/// - Parameters:
/// - strongReference: The URI of the record, which contains the `recordURI` and `cidHash`.
/// - createdAt: The date and time the like record was created. Defaults to `Date.now`.
/// - shouldValidate: Indicates whether the record should be validated. Optional.
/// Defaults to `true`.
/// - Returns: A
/// ``ComAtprotoLexicon/Repository/StrongReference``
/// structure which represents the record that was successfully created.
public func createRepostRecord(
_ strongReference: ComAtprotoLexicon.Repository.StrongReference,
createdAt: Date = Date(),
shouldValidate: Bool? = true
) async throws -> ComAtprotoLexicon.Repository.StrongReference {
guard let session else { throw ATRequestPrepareError.missingActiveSession }

let repostRecord = AppBskyLexicon.Feed.RepostRecord(
subject: strongReference,
createdAt: createdAt
)

return try await atProtoKitInstance.createRecord(
repositoryDID: session.sessionDID,
collection: "app.bsky.feed.repost",
shouldValidate: shouldValidate,
record: UnknownType.record(repostRecord)
)
}

/// The request body for a repost record.
struct RepostRecordRequestBody: Encodable {
/// The repository for the repost record.
let repo: String
/// The Namespaced Identifiers (NSID) of the request body.
///
/// - Warning: The value must not change.
let collection: String = "app.bsky.feed.repost"
/// The like record itself.
let record: AppBskyLexicon.Feed.RepostRecord
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,13 @@ import Foundation

extension ATProtoBluesky {

/// Deletes a repost record.
///
/// This can also be used to validate if a repost record has been deleted.
/// - Parameter record: The record that needs to be deleted.
///
/// This can be either the URI of the record, or the full record object itself.
public func deleteRepostRecord(_ record: RecordIdentifier) async throws {
try await deleteActionRecord(record)
}
}

0 comments on commit 38ac43a

Please sign in to comment.