66require_relative 'resolver'
77
88module DIDKit
9+
10+ #
11+ # Represents a DID identifier (account on the ATProto network). This class serves as an entry
12+ # point to various lookup helpers. For convenience it can also be accessed as just `DID` without
13+ # the `DIDKit::` prefix.
14+ #
15+ # @example Resolving a handle
16+ # did = DID.resolve_handle('bsky.app')
17+ #
18+
919 class DID
1020 GENERIC_REGEXP = /\A did\: \w +\: .+\z /
1121
1222 include Requests
1323
24+ # Resolve a handle into a DID. Looks up the given ATProto domain handle using the DNS TXT method
25+ # and the HTTP .well-known method and returns a DID if one is assigned using either of the methods.
26+ #
27+ # If a DID string or a {DID} object is passed, it simply returns that DID, so you can use this
28+ # method to pass it an input string from the user which can be a DID or handle, without having to
29+ # check which one it is.
30+ #
31+ # @param handle [String, DID] a domain handle (may start with an `@`) or a DID string
32+ # @return [DID, nil] resolved DID if found, nil otherwise
33+
1434 def self . resolve_handle ( handle )
1535 Resolver . new . resolve_handle ( handle )
1636 end
1737
18- attr_reader :type , :did , :resolved_by
38+ # @return [Symbol] DID type (`:plc` or `:web`)
39+ attr_reader :type
40+
41+ # @return [String] DID identifier string
42+ attr_reader :did
43+
44+ # @return [Symbol, nil] `:dns` or `:http` if the DID was looked up using one of those methods
45+ attr_reader :resolved_by
46+
47+ alias to_s did
48+
49+
50+ # Create a DID object from a DID string.
51+ #
52+ # @param did [String, DID] DID string or another DID object
53+ # @param resolved_by [Symbol, nil] optionally, how the DID was looked up (`:dns` or `:http`)
54+ # @raise [DIDError] when the DID format or type is invalid
1955
2056 def initialize ( did , resolved_by = nil )
2157 if did . is_a? ( DID )
@@ -36,20 +72,39 @@ def initialize(did, resolved_by = nil)
3672 @resolved_by = resolved_by
3773 end
3874
39- alias to_s did
75+ # Returns or looks up the DID document with the DID's identity details from an appropriate source.
76+ # This method caches the document in a local variable if it's called again.
77+ #
78+ # @return [Document] resolved DID document
4079
4180 def document
4281 @document ||= get_document
4382 end
4483
84+ # Looks up the DID document with the DID's identity details from an appropriate source.
85+ # @return [Document] resolved DID document
86+
4587 def get_document
4688 Resolver . new . resolve_did ( self )
4789 end
4890
91+ # Returns the first verified handle assigned to this DID.
92+ #
93+ # Looks up the domain handles assigned to this DID in its DID document, checks if they are
94+ # verified (i.e. assigned correctly to this DID using DNS TXT or .well-known) and returns
95+ # the first handle that validates correctly, or nil if none matches.
96+ #
97+ # @return [String, nil] verified handle domain, if found
98+
4999 def get_verified_handle
50100 Resolver . new . get_verified_handle ( document )
51101 end
52102
103+ # Fetches the PLC audit log (list of all previous operations) for a did:plc DID.
104+ #
105+ # @return [Array<PLCOperation>] list of PLC operations in the audit log
106+ # @raise [DIDError] when the DID is not a did:plc
107+
53108 def get_audit_log
54109 if @type == :plc
55110 PLCImporter . new . fetch_audit_log ( self )
@@ -58,10 +113,23 @@ def get_audit_log
58113 end
59114 end
60115
116+ # Returns the domain portion of a did:web identifier.
117+ #
118+ # @return [String, nil] DID domain if the DID is a did:web, nil for did:plc
119+
61120 def web_domain
62121 did . gsub ( /^did\: web\: / , '' ) if type == :web
63122 end
64123
124+ # Checks the status of the account/repo on its own PDS using the `getRepoStatus` endpoint.
125+ #
126+ # @param request_options [Hash] request options to override
127+ # @option request_options [Integer] :timeout request timeout (default: 15)
128+ # @option request_options [Integer] :max_redirects maximum number of redirects to follow (default: 5)
129+ #
130+ # @return [Symbol, nil] `:active`, or returned inactive status, or `nil` if account is not found
131+ # @raise [APIError] when the response is invalid
132+
65133 def account_status ( request_options = { } )
66134 doc = self . document
67135 return nil if doc . pds_endpoint . nil?
@@ -91,14 +159,31 @@ def account_status(request_options = {})
91159 end
92160 end
93161
162+ # Checks if the account is seen as active on its own PDS, using the `getRepoStatus` endpoint.
163+ # This is a helper which calls the {#account_status} method and checks if the status is `:active`.
164+ #
165+ # @return [Boolean] true if the returned status is active
166+ # @raise [APIError] when the response is invalid
167+
94168 def account_active?
95169 account_status == :active
96170 end
97171
172+ # Checks if the account exists its own PDS, using the `getRepoStatus` endpoint.
173+ # This is a helper which calls the {#account_status} method and checks if the repo is found at all.
174+ #
175+ # @return [Boolean] true if the returned status is valid, false if repo is not found
176+ # @raise [APIError] when the response is invalid
177+
98178 def account_exists?
99179 account_status != nil
100180 end
101181
182+ # Compares the DID to another DID object or string.
183+ #
184+ # @param other [DID, String] other DID to compare with
185+ # @return [Boolean] true if it's the same DID
186+
102187 def ==( other )
103188 if other . is_a? ( String )
104189 self . did == other
0 commit comments