import fetch from 'node-fetch' interface ShortGUID { value: string; shouldFetchRootRecord: boolean; } interface ZoneID { zoneName: string; ownerRecordName: string; zoneType: string; } interface CloudkitType { value: string; type: string; } interface CloudkitTitle { value: string; type: string; } interface Fields { 'cloudkit.type': CloudkitType; 'cloudkit.title': CloudkitTitle; } interface PluginFields { [key: string]: any, } interface Created { timestamp: number; userRecordName: string; deviceID: string; } interface Modified { timestamp: number; userRecordName: string; deviceID: string; } interface ZoneID2 { zoneName: string; ownerRecordName: string; zoneType: string; } interface Share2 { recordName: string; zoneID: ZoneID2; } interface NameComponents { givenName: string; familyName: string; } interface LookupInfo { emailAddress: string; } interface UserIdentity { userRecordName: string; nameComponents: NameComponents; lookupInfo: LookupInfo; } interface Participant { participantId: string; userIdentity: UserIdentity; type: string; acceptanceStatus: string; permission: string; orgUser: boolean; } interface NameComponents2 { givenName: string; familyName: string; } interface LookupInfo2 { emailAddress: string; } interface UserIdentity2 { userRecordName: string; nameComponents: NameComponents2; lookupInfo: LookupInfo2; } interface Owner { participantId: string; userIdentity: UserIdentity2; type: string; acceptanceStatus: string; permission: string; orgUser: boolean; } interface Share { recordName: string; recordType: string; fields: Fields; pluginFields: PluginFields; recordChangeTag: string; created: Created; modified: Modified; share: Share2; publicPermission: string; participants: Participant[]; owner: Owner; displayedHostname: string; shortGUID: string; } interface LastEditorName { value: string; type: string; } interface Extension { value: string; type: string; } interface Basehash { value: string; type: string; } interface Size { value: number; type: string; } interface EncryptedBasename { value: string; type: string; } interface Quarantine { value: string; type: string; } interface Mtime { value: number; type: string; } interface Value { fileChecksum: string; size: number; wrappingKey: string; referenceChecksum: string; downloadURL: string; } interface FileContent { value: Value; type: string; } interface PublicSharingPermission { value: number; type: string; } interface Fields2 { lastEditorName: LastEditorName; extension: Extension; basehash: Basehash; size: Size; encryptedBasename: EncryptedBasename; quarantine: Quarantine; mtime: Mtime; fileContent: FileContent; publicSharingPermission: PublicSharingPermission; } interface PluginFields2 { } interface Created2 { timestamp: number; userRecordName: string; deviceID: string; } interface Modified2 { timestamp: number; userRecordName: string; deviceID: string; } interface ZoneID3 { zoneName: string; ownerRecordName: string; zoneType: string; } interface Share3 { recordName: string; zoneID: ZoneID3; } interface RootRecord { recordName: string; recordType: string; fields: Fields2; pluginFields: PluginFields2; recordChangeTag: string; created: Created2; modified: Modified2; deleted: boolean; share: Share3; displayedHostname: string; shortGUID: string; } interface NameComponents3 { givenName: string; familyName: string; } interface LookupInfo3 { emailAddress: string; } interface OwnerIdentity { userRecordName: string; nameComponents: NameComponents3; lookupInfo: LookupInfo3; } export interface iCloudInfo { shortGUID: ShortGUID; containerIdentifier: string; environment: string; databaseScope: string; zoneID: ZoneID; share: Share; rootRecordName: string; rootRecord: RootRecord; ancestorRecords: any[]; ownerIdentity: OwnerIdentity; potentialMatchList: any[]; } const getGuidFromUrl = (url: string) => { const regex = /icloud\.com\/iclouddrive\/(.{25})/gi const result = regex.exec(url) if (!result || !result[1]) throw new Error(`Cannot get iCloud guid from url '${url}'`) return result[1] } const iCloudDataUrl = 'https://ckdatabasews.icloud.com/database/1/com.apple.cloudkit/production/public/records/resolve' const getiCloudInfo = async (url: string): Promise => fetch(iCloudDataUrl, { method: 'post', body: JSON.stringify({ shortGUIDs: [{ value: getGuidFromUrl(url) }], }) }) .then(r => r.json()) .then(r => (r.results && r.results[0]) || undefined) export default getiCloudInfo