Skip to content

Commit c8b3f9a

Browse files
committed
Update lexicon models and methods
1 parent ab9be63 commit c8b3f9a

11 files changed

+984
-2
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//
2+
// ToolsOzoneSafelinkAddRuleMethod.swift
3+
// ATProtoKit
4+
//
5+
// Created by Christopher Jr Riley on 2025-07-11.
6+
//
7+
8+
import Foundation
9+
#if canImport(FoundationNetworking)
10+
import FoundationNetworking
11+
#endif
12+
13+
extension ATProtoAdmin {
14+
15+
/// Adds a safety rule for a URL.
16+
///
17+
/// - Note: According to the AT Protocol specifications: "Add a new URL safety rule."
18+
///
19+
/// - SeeAlso: This is based on the [`tools.ozone.safelink.addRule`][github] lexicon.
20+
///
21+
/// [github]: https://github.com/bluesky-social/atproto/blob/main/lexicons/tools/ozone/safelink/addRule.json
22+
///
23+
/// - Parameters:
24+
/// - url: The URL or domain the rule applies to.
25+
/// - urlPattern: A string declaring the pattern of the URL.
26+
/// - action: A string declaring the action taken to the URL.
27+
/// - reason: A string declaring the reason for the action against the URL.
28+
/// - comment: A comment attached to the event. Optional.
29+
/// - createdBy: The decentralized identifier (DID) of the user account that created this event.
30+
/// - Returns: The successfully-created URL safety rule.
31+
///
32+
/// - Throws: An ``ATProtoError``-conforming error type, depending on the issue. Go to
33+
/// ``ATAPIError`` and ``ATRequestPrepareError`` for more details.
34+
public func addRule(
35+
url: URL,
36+
urlPattern: ToolsOzoneLexicon.Safelink.PatternTypeDefinition,
37+
action: ToolsOzoneLexicon.Safelink.ActionTypeDefinition,
38+
reason: ToolsOzoneLexicon.Safelink.ReasonTypeDefinition,
39+
comment: String? = nil,
40+
createdBy: String
41+
) async throws -> ToolsOzoneLexicon.Safelink.URLRuleDefinition {
42+
guard let session = try await self.getUserSession(),
43+
let keychain = sessionConfiguration?.keychainProtocol else {
44+
throw ATRequestPrepareError.missingActiveSession
45+
}
46+
47+
let accessToken = try await keychain.retrieveAccessToken()
48+
49+
guard let sessionURL = session.pdsURL,
50+
let requestURL = URL(string: "\(sessionURL)/xrpc/tools.ozone.safelink.addRule") else {
51+
throw ATRequestPrepareError.invalidRequestURL
52+
}
53+
54+
let requestBody = ToolsOzoneLexicon.Safelink.AddRuleRequestBody(
55+
url: url,
56+
urlPattern: urlPattern,
57+
action: action,
58+
reason: reason,
59+
comment: comment,
60+
createdBy: createdBy
61+
)
62+
63+
do {
64+
let request = apiClientService.createRequest(
65+
forRequest: requestURL,
66+
andMethod: .post,
67+
acceptValue: "application/json",
68+
contentTypeValue: "application/json",
69+
authorizationValue: "Bearer \(accessToken)"
70+
)
71+
let response = try await apiClientService.sendRequest(
72+
request,
73+
withEncodingBody: requestBody,
74+
decodeTo: ToolsOzoneLexicon.Safelink.URLRuleDefinition.self
75+
)
76+
77+
return response
78+
} catch {
79+
throw error
80+
}
81+
}
82+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//
2+
// ToolsOzoneSafelinkQueryEventsMethod.swift
3+
// ATProtoKit
4+
//
5+
// Created by Christopher Jr Riley on 2025-07-12.
6+
//
7+
8+
import Foundation
9+
#if canImport(FoundationNetworking)
10+
import FoundationNetworking
11+
#endif
12+
13+
extension ATProtoAdmin {
14+
15+
/// Queries URL safety audit events.
16+
///
17+
/// - Note: According to the AT Protocol specifications: "Query URL safety audit events."
18+
///
19+
/// - SeeAlso: This is based on the [`tools.ozone.safelink.queryEvents`][github] lexicon.
20+
///
21+
/// [github]: https://github.com/bluesky-social/atproto/blob/main/lexicons/tools/ozone/safelink/queryEvents.json
22+
///
23+
/// - Parameters:
24+
/// - cursor: The mark used to indicate the starting point for the next set of results. Optional.
25+
/// - limit: The number of events in the array. Defaults to `50`. Can only choose between
26+
/// `1` and `100`.
27+
/// - urls: An array of URLs listed for auditing. Optional.
28+
/// - patternType: Filter results based on the selected pattern type. Optional.
29+
/// - sortDirection: Sets the sorting direction of the audit array. Optional.
30+
/// Defaults to `.descending`.
31+
public func queryEvents(
32+
cursor: String? = nil,
33+
limit: Int = 50,
34+
urls: [URL]? = nil,
35+
patternType: String? = nil,
36+
sortDirection: ToolsOzoneLexicon.Safelink.QueryEvents.SortDirection? = .descending
37+
) async throws -> ToolsOzoneLexicon.Safelink.QueryEventsOutput {
38+
guard let session = try await self.getUserSession(),
39+
let keychain = sessionConfiguration?.keychainProtocol else {
40+
throw ATRequestPrepareError.missingActiveSession
41+
}
42+
43+
let accessToken = try await keychain.retrieveAccessToken()
44+
45+
guard let sessionURL = session.pdsURL,
46+
let requestURL = URL(string: "\(sessionURL)/xrpc/tools.ozone.safelink.queryEvents") else {
47+
throw ATRequestPrepareError.invalidRequestURL
48+
}
49+
50+
let finalLimit = max(1, min(limit, 100))
51+
52+
let requestBody = ToolsOzoneLexicon.Safelink.QueryEventsRequestBody(
53+
cursor: cursor,
54+
limit: finalLimit,
55+
urls: urls,
56+
patternType: patternType,
57+
sortDirection: sortDirection
58+
)
59+
60+
do {
61+
let request = apiClientService.createRequest(
62+
forRequest: requestURL,
63+
andMethod: .post,
64+
acceptValue: "application/json",
65+
contentTypeValue: "application/json",
66+
authorizationValue: "Bearer \(accessToken)"
67+
)
68+
let response = try await apiClientService.sendRequest(
69+
request,
70+
withEncodingBody: requestBody,
71+
decodeTo: ToolsOzoneLexicon.Safelink.QueryEventsOutput.self
72+
)
73+
74+
return response
75+
} catch {
76+
throw error
77+
}
78+
}
79+
}

Sources/ATProtoKit/APIReference/AppBskyAPI/AppBskyNotificationRegisterPushMethod.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,16 @@ extension ATProtoKit {
2626
/// - token: The token of the service.
2727
/// - platform: The platform of the client.
2828
/// - appID: The identifier of the client.
29+
/// - isAgeRestricted: Determines whether the user account is age restricted. Optional.
2930
///
3031
/// - Throws: An ``ATProtoError``-conforming error type, depending on the issue. Go to
3132
/// ``ATAPIError`` and ``ATRequestPrepareError`` for more details.
3233
public func registerPush(
3334
serviceDID: String,
3435
token: String,
3536
platform: AppBskyLexicon.Notification.RegisterPush.Platform,
36-
appID: String
37+
appID: String,
38+
isAgeRestricted: Bool? = nil
3739
) async throws {
3840
guard let session = try await self.getUserSession(),
3941
let keychain = sessionConfiguration?.keychainProtocol else {
@@ -51,7 +53,8 @@ extension ATProtoKit {
5153
serviceDID: serviceDID,
5254
token: token,
5355
platform: platform,
54-
appID: appID
56+
appID: appID,
57+
isAgeRestricted: isAgeRestricted
5558
)
5659

5760
do {

Sources/ATProtoKit/Models/Lexicons/app.bsky/Notification/AppBskyNotificationRegisterPush.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,18 @@ extension AppBskyLexicon.Notification {
5353
/// The app ID for the push notification.
5454
public let appID: String
5555

56+
/// Determines whether the user account is age restricted.
57+
///
58+
/// - Note: According to the AT Protocol specifications: "Set to true when the actor is
59+
/// age restricted."
60+
public let isAgeRestricted: Bool?
61+
5662
enum CodingKeys: String, CodingKey {
5763
case serviceDID = "serviceDid"
5864
case token
5965
case platform
6066
case appID = "appId"
67+
case isAgeRestricted = "ageRestricted"
6168
}
6269
}
6370
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//
2+
// ToolsOzoneSafelinkAddRule.swift
3+
// ATProtoKit
4+
//
5+
// Created by Christopher Jr Riley on 2025-07-11.
6+
//
7+
8+
import Foundation
9+
#if canImport(FoundationNetworking)
10+
import FoundationNetworking
11+
#endif
12+
13+
extension ToolsOzoneLexicon.Safelink {
14+
15+
/// A request body model for adding a safety rule for a URL.
16+
///
17+
/// - Note: According to the AT Protocol specifications: "Add a new URL safety rule."
18+
///
19+
/// - SeeAlso: This is based on the [`tools.ozone.safelink.addRule`][github] lexicon.
20+
///
21+
/// [github]: https://github.com/bluesky-social/atproto/blob/main/lexicons/tools/ozone/safelink/addRule.json
22+
public struct AddRuleRequestBody: Sendable, Codable {
23+
24+
/// The URL or domain the rule applies to.
25+
///
26+
/// - Note: According to the AT Protocol specifications: "The URL or domain to apply the rule to."
27+
public let url: URL
28+
29+
/// A string declaring the URL pattern.
30+
public let urlPattern: PatternTypeDefinition
31+
32+
/// A string declaring the action taken to the URL.
33+
public let action: ActionTypeDefinition
34+
35+
/// A string declaring the reason for the action against the URL.
36+
public let reason: ReasonTypeDefinition
37+
38+
/// A comment attached to the event. Optional.
39+
///
40+
/// - Note: According to the AT Protocol specifications: "Optional comment about the decision."
41+
public let comment: String?
42+
43+
/// The decentralized identifier (DID) of the user account that created this event.
44+
///
45+
/// - Note: According to the AT Protocol specifications: "Author DID. Only respected when using admin auth."
46+
public let createdBy: String
47+
48+
public init(url: URL, urlPattern: PatternTypeDefinition, action: ActionTypeDefinition,
49+
reason: ReasonTypeDefinition, comment: String?, createdBy: String) {
50+
self.url = url
51+
self.urlPattern = urlPattern
52+
self.action = action
53+
self.reason = reason
54+
self.comment = comment
55+
self.createdBy = createdBy
56+
}
57+
58+
public init(from decoder: any Decoder) throws {
59+
let container = try decoder.container(keyedBy: CodingKeys.self)
60+
61+
self.url = try container.decode(URL.self, forKey: .url)
62+
self.urlPattern = try container.decode(ToolsOzoneLexicon.Safelink.PatternTypeDefinition.self, forKey: .urlPattern)
63+
self.action = try container.decode(ToolsOzoneLexicon.Safelink.ActionTypeDefinition.self, forKey: .action)
64+
self.reason = try container.decode(ToolsOzoneLexicon.Safelink.ReasonTypeDefinition.self, forKey: .reason)
65+
self.comment = try container.decodeIfPresent(String.self, forKey: ToolsOzoneLexicon.Safelink.AddRuleRequestBody.CodingKeys.comment)
66+
self.createdBy = try container.decode(String.self, forKey: ToolsOzoneLexicon.Safelink.AddRuleRequestBody.CodingKeys.createdBy)
67+
}
68+
69+
public func encode(to encoder: any Encoder) throws {
70+
var container = encoder.container(keyedBy: CodingKeys.self)
71+
try container.encode(self.url, forKey: .url)
72+
try container.encode(self.urlPattern, forKey: .urlPattern)
73+
try container.encode(self.action, forKey: .action)
74+
try container.encode(self.reason, forKey: .reason)
75+
try container.encodeIfPresent(self.comment, forKey: .comment)
76+
try container.encode(self.createdBy, forKey: .createdBy)
77+
}
78+
79+
enum CodingKeys: String, CodingKey {
80+
case url
81+
case urlPattern = "pattern"
82+
case action
83+
case reason
84+
case comment
85+
case createdBy
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)