// // GetARecordIntent.swift // shortcut // // Created by Bailey Townsend on 6/30/25. // import ATProtoKit import AppIntents import SwiftData import SwiftUI import UniformTypeIdentifiers struct GetRepoIntent: AppIntent { @Parameter( title: "Repo", description: "The handle or DID of the repo" ) var atIdentifier: String @Parameter( title: "Since", description: "A TID created from a timestamp of since when to get the record") var since: String? static let title: LocalizedStringResource = "Get Repo" static let description: IntentDescription = IntentDescription( stringLiteral: "Get's the users repo as a .CAR file. This can also be used as a backup of your repo, but will not include the account's blobs (pictures, videos, etc)" ) static var parameterSummary: some ParameterSummary { Summary( "Download a CAR export of \(\.$atIdentifier)'s repo" ) { \.$since } } @Dependency private var blobDownloader: BlobDownloader func perform() async throws -> some ReturnsValue { let atProtoManager = AtProtocolManager() let lowerCaseAtIdentifier = self.atIdentifier.lowercased().trim() let info = try await GetRemoteInfo.getRemoteRepoInfo( possibleRepo: lowerCaseAtIdentifier, atProtoManager: atProtoManager) let fileManager = FileManager.default let saveLocation = fileManager.temporaryDirectory let date = Date() let formatter = ISO8601DateFormatter() let utcString = formatter.string(from: date) let fileName = "\(info.handle)-\(utcString).car" do { ///Just to be on the safe side await self.blobDownloader.CancelAll() let response = try await self.blobDownloader.getCar( from: info.repo, since: self.since, fileManager: fileManager, saveLocation: saveLocation, fileName: fileName, pdsURL: info.pdsURL) let record: RepoCarEntity = RepoCarEntity() record.car = IntentFile( fileURL: response ) return .result( value: record) } catch let shortCutError as ShortcutErrors { switch shortCutError { case .NoSession: throw GenericIntentError.message("No session found") case .ErrorCreatingARecord(let errorMessage): throw GenericIntentError.message(errorMessage) case .AuthError(let authError): throw GenericIntentError.message(authError) } } catch let shortCutError as GenericIntentError { throw shortCutError } catch let blobDownloadError as BlobDownloadError { switch blobDownloadError { case .apiError(let error): throw GenericIntentError.message(error.message) default: throw GenericIntentError.general } } catch { throw GenericIntentError.general } } }