Skip to content

Commit 64192b4

Browse files
committed
Merge branch 'develop'
2 parents adc84fa + 0300342 commit 64192b4

File tree

41 files changed

+1870
-167
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1870
-167
lines changed

NOTICE.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Notices
2+
3+
ATProtoKit incorporates documentation text sourced from the following repositories:
4+
5+
* LICENSE (Apache License v2.0):
6+
* https://github.com/bluesky-social/atproto/blob/main/LICENSE-MIT.txt
7+
* HOMEPAGE:
8+
* https://github.com/bluesky-social/atproto
9+
10+
[bluesky-social/atproto](https://github.com/bluesky-social/atproto) repository. Please view the [license included the repository](ATProtoLicense/ATPROTO-LICENSE.txt).
11+
12+
-------------------------------------------------------------------------------
13+
14+
ATProtoKit also contains the following repositories:
15+
16+
This product contains swift-docc-plugin from The Swift Programming Language:
17+
18+
* LICENSE (Apache License v2.0):
19+
* https://github.com/swiftlang/swift-docc-plugin/blob/main/LICENSE.txt
20+
* HOMEPAGE:
21+
* https://github.com/swiftlang/swift-docc-plugin
22+
23+
---
24+
25+
* LICENSE (Apache License v2.0):
26+
* https://github.com/apple/swift-log/blob/main/LICENSE.txt
27+
* HOMEPAGE:
28+
* https://github.com/apple/swift-log

README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,4 @@ If you have any questions, you can ask me on Bluesky ([@cjrriley.ca](https://bsk
175175
## License and Acknowledgments
176176
This Swift package is using the MIT License. Please view [LICENSE.md](https://github.com/MasterJ93/ATProtoKit/blob/main/LICENSE.md) for more details.
177177

178-
The documentation text used by Bluesky is licenced under the MIT Licence. Please view [ATPROTO-LICENSE.md](ATProtoLicense/ATPROTO-LICENSE.txt) for more details.
179-
180-
The following Swift packages have been used to help run ATProtoKit:
181-
- [swift-docc-plugin](https://github.com/swiftlang/swift-docc-plugin) from [The Swift Programming Language](https://github.com/swiftlang).
182-
- [swift-log](https://github.com/apple/swift-log) from [Apple](https://github.com/apple).
178+
The documentation text used by Bluesky is licenced under the MIT Licence. Additional Swift packages have also been used to help run ATProtoKit. Please view [NOTICE.md](NOTICE.md) for more details.

Sources/ATProtoKit/APIReference/ATProtoBlueskyAPI/ProfileRecord/CreateProfileRecord.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ extension ATProtoBluesky {
115115
/// - Parameters:
116116
/// - displayName: A display name for the profile. Optional. Defaults to `nil`.
117117
/// - description: A description for the profile. Optional. Defaults to `nil`.
118+
/// - pronouns: The user account's pronoun preferences. Optional. Defaults to `nil`.
119+
/// - websiteURL: The user account's website. Optional. Defaults to `nil`.
118120
/// - avatarImage: An image used for the profile picture. Optional. Defaults to `nil`.
119121
/// - bannerImage: An image used for the banner image. Optional,Defaults to `nil`.
120122
/// - labels: An array of user-defined labels. Optional. Defaults to `nil`.
@@ -130,6 +132,8 @@ extension ATProtoBluesky {
130132
public func createProfileRecord(
131133
with displayName: String? = nil,
132134
description: String? = nil,
135+
pronouns: String? = nil,
136+
websiteURL: URL? = nil,
133137
avatarImage: ATProtoTools.ImageQuery? = nil,
134138
bannerImage: ATProtoTools.ImageQuery? = nil,
135139
labels: [ComAtprotoLexicon.Label.SelfLabelsDefinition]? = nil,
@@ -160,6 +164,18 @@ extension ATProtoBluesky {
160164
descriptionText = description.truncated(toLength: 256)
161165
}
162166

167+
// pronouns
168+
var pronounsText: String? = nil
169+
if let pronouns = pronouns {
170+
pronounsText = pronouns.truncated(toLength: 20)
171+
}
172+
173+
// website
174+
var website: URL? = nil
175+
if let websiteURL = websiteURL {
176+
website = websiteURL
177+
}
178+
163179
// avatarImage
164180
var profileAvatarImage: ComAtprotoLexicon.Repository.UploadBlobOutput? = nil
165181
let accessToken = try await keychain.retrieveAccessToken()
@@ -209,6 +225,8 @@ extension ATProtoBluesky {
209225
let profileRecord = AppBskyLexicon.Actor.ProfileRecord(
210226
displayName: displayNameText,
211227
description: descriptionText,
228+
pronouns: pronounsText,
229+
websiteURL: website,
212230
avatarBlob: profileAvatarImage,
213231
bannerBlob: profileBannerImage,
214232
labels: labelsArray,

Sources/ATProtoKit/APIReference/ATProtoBlueskyAPI/ProfileRecord/UpdateProfileRecord.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ extension ATProtoBluesky {
6969

7070
var newDisplayName: String? = profile.displayName
7171
var newDescription: String? = profile.description
72+
var newPronouns: String? = profile.pronouns
73+
var newWebsiteURL: URL? = profile.websiteURL
7274
var newAvatarImage: ComAtprotoLexicon.Repository.UploadBlobOutput? = profile.avatarBlob
7375
var newBannerImage: ComAtprotoLexicon.Repository.UploadBlobOutput? = profile.bannerBlob
7476
var newLabels: [AppBskyLexicon.Actor.ProfileRecord.LabelsUnion]? = profile.labels
@@ -97,6 +99,22 @@ extension ATProtoBluesky {
9799
}
98100

99101
newDescription = descriptionField?.truncated(toLength: 256)
102+
case .pronouns(let pronounsField):
103+
if pronounsField == nil {
104+
newPronouns = nil
105+
106+
break
107+
}
108+
109+
newPronouns = pronounsField?.truncated(toLength: 20)
110+
case .website(let websiteField):
111+
if websiteField == nil {
112+
newWebsiteURL = nil
113+
114+
break
115+
}
116+
117+
newWebsiteURL = websiteField
100118
case .avatarImage(let avatarImageField):
101119
// Check if the field is nil. If so, set the avatarImage variable to nil and break out of the case early.
102120
if avatarImageField == nil {
@@ -178,6 +196,8 @@ extension ATProtoBluesky {
178196
let profileRecord = AppBskyLexicon.Actor.ProfileRecord(
179197
displayName: newDisplayName,
180198
description: newDescription,
199+
pronouns: newPronouns,
200+
websiteURL: newWebsiteURL,
181201
avatarBlob: newAvatarImage,
182202
bannerBlob: newBannerImage,
183203
labels: newLabels,
@@ -211,6 +231,12 @@ extension ATProtoBluesky {
211231
/// - Parameter with: The object to update the record with. Optional. Defaults to `nil`.
212232
case description(with: String? = nil)
213233

234+
/// The user account's pronoun preferences.
235+
case pronouns(with: String? = nil)
236+
237+
/// The user account's website.
238+
case website(with: URL? = nil)
239+
214240
/// An image used for the profile picture.
215241
///
216242
/// - Parameter with: The object to update the record with. Optional. Defaults to `nil`.
@@ -240,6 +266,8 @@ extension ATProtoBluesky {
240266
switch self {
241267
case .displayName: return "displayName"
242268
case .description: return "description"
269+
case .pronouns: return "pronouns"
270+
case .website: return "website"
243271
case .avatarImage: return "avatarImage"
244272
case .bannerImage: return "bannerImage"
245273
case .labels: return "labels"

Sources/ATProtoKit/APIReference/AdminAndModeratorAPI/QueryModerationEventsAsAdmin.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ extension ATProtoAdmin {
6060
/// the added tags. Optional.
6161
/// - reportTypes: An array of report types. Optional.
6262
/// - policies: Filters events based on the action policies. Optional.
63+
/// - modTool: Filters the results by the modTool name. Optional. Defaults to `nil`.
64+
/// - batchID: Filters the results by the batch ID. Optional. Defaults to `nil`.
65+
/// - ageAssuranceState: Filters the results to events whose age-assurance state matches the
66+
/// specified value. Optional. Defaults to `nil`.
6367
/// - cursor: The mark used to indicate the starting point for the next set
6468
/// of results. Optional.
6569
/// - Returns: An array of all moderation events pertaining a subject, with an optional cursor
@@ -86,6 +90,9 @@ extension ATProtoAdmin {
8690
removedTags: [String]? = nil,
8791
reportTypes: [String]? = nil,
8892
policies: [String]? = nil,
93+
modTool: [String]? = nil,
94+
batchID: String? = nil,
95+
ageAssuranceState: ToolsOzoneLexicon.Moderation.QueryEvents.AgeAssuranceState? = nil,
8996
cursor: String? = nil
9097
) async throws -> ToolsOzoneLexicon.Moderation.QueryEventsOutput {
9198
guard let session = try await self.getUserSession(),
@@ -195,6 +202,18 @@ extension ATProtoAdmin {
195202
queryItems += policies.map { ("policies", $0) }
196203
}
197204

205+
if let modTool {
206+
queryItems += modTool.map { ("modTool", $0) }
207+
}
208+
209+
if let batchID {
210+
queryItems.append(("batchId", batchID))
211+
}
212+
213+
if let ageAssuranceState {
214+
queryItems.append(("ageAssuranceState", "\(ageAssuranceState.rawValue)"))
215+
}
216+
198217
// cursor
199218
if let cursor {
200219
queryItems.append(("cursor", cursor))
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//
2+
// ToolsOzoneModerationGetAccountTimelineMethod.swift
3+
// ATProtoKit
4+
//
5+
// Created by Christopher Jr Riley on 2025-09-26.
6+
//
7+
8+
import Foundation
9+
#if canImport(FoundationNetworking)
10+
import FoundationNetworking
11+
#endif
12+
13+
extension ATProtoAdmin {
14+
15+
/// Retrieves the timeline of all available events for an account, including moderation events, account
16+
/// history, and decentralized identifier (DID) history.
17+
///
18+
/// - Note: According to the AT Protocol specifications: "Get timeline of all available events of
19+
/// an account. This includes moderation events, account history and did history."
20+
///
21+
/// - SeeAlso: This is based on the [`tools.ozone.moderation.getAccountTimeline`][github] lexicon.
22+
///
23+
/// [github]: https://github.com/bluesky-social/atproto/blob/main/lexicons/tools/ozone/moderation/getAccountTimeline.json
24+
///
25+
/// - Parameter did: The decentralized identifier (DID) of the account to retrieve the timeline from.
26+
/// - Returns: An array of items in the account's timeline.
27+
///
28+
/// - Throws: An ``ATProtoError``-conforming error type, depending on the issue. Go to
29+
/// ``ATAPIError`` and ``ATRequestPrepareError`` for more details.
30+
public func getAccountTimeline(for did: String) async throws -> ToolsOzoneLexicon.Moderation.GetAccountTimelineOutput {
31+
guard let session = try await self.getUserSession(),
32+
let keychain = sessionConfiguration?.keychainProtocol else {
33+
throw ATRequestPrepareError.missingActiveSession
34+
}
35+
36+
try await sessionConfiguration?.ensureValidToken()
37+
let accessToken = try await keychain.retrieveAccessToken()
38+
39+
guard let sessionURL = session.pdsURL,
40+
let requestURL = URL(string: "\(sessionURL)/xrpc/tools.ozone.moderation.getAccountTimeline") else {
41+
throw ATRequestPrepareError.invalidRequestURL
42+
}
43+
44+
var queryItems = [(String, String)]()
45+
46+
queryItems.append(("did", did))
47+
48+
let queryURL: URL
49+
50+
do {
51+
queryURL = try apiClientService.setQueryItems(
52+
for: requestURL,
53+
with: queryItems
54+
)
55+
56+
let request = apiClientService.createRequest(
57+
forRequest: queryURL,
58+
andMethod: .get,
59+
acceptValue: "application/json",
60+
contentTypeValue: nil,
61+
authorizationValue: "Bearer \(accessToken)"
62+
)
63+
let response = try await apiClientService.sendRequest(
64+
request,
65+
decodeTo: ToolsOzoneLexicon.Moderation.GetAccountTimelineOutput.self
66+
)
67+
68+
return response
69+
} catch {
70+
throw error
71+
}
72+
}
73+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//
2+
// AppBskyBookmarkCreateBookmarkMethod.swift
3+
// ATProtoKit
4+
//
5+
// Created by Christopher Jr Riley on 2025-09-26.
6+
//
7+
8+
import Foundation
9+
#if canImport(FoundationNetworking)
10+
import FoundationNetworking
11+
#endif
12+
13+
extension ATProtoKit {
14+
15+
/// Creates a private bookmark for the specified record.
16+
///
17+
/// Currently limited to `app.bsky.feed.post` records.
18+
///
19+
/// - Note: According to the AT Protocol specifications: "Creates a private bookmark for the
20+
/// specified record. Currently, only `app.bsky.feed.post` records are supported.
21+
/// Requires authentication."
22+
///
23+
/// - SeeAlso: This is based on the [`app.bsky.bookmark.createBookmark`][github] lexicon.
24+
///
25+
/// [github]: https://github.com/bluesky-social/atproto/blob/main/lexicons/app/bsky/bookmark/createBookmark.json
26+
///
27+
/// - Parameters:
28+
/// - uri: The URI of the bookmark.
29+
/// - cid: The CID of the bookmark.
30+
///
31+
/// - Throws: An ``ATProtoError``-conforming error type, depending on the issue. Go to
32+
/// ``ATAPIError`` and ``ATRequestPrepareError`` for more details.
33+
public func createBookmark(
34+
uri: String,
35+
cid: String
36+
) async throws {
37+
guard let session = try await self.getUserSession(),
38+
let keychain = sessionConfiguration?.keychainProtocol else {
39+
throw ATRequestPrepareError.missingActiveSession
40+
}
41+
42+
try await sessionConfiguration?.ensureValidToken()
43+
let accessToken = try await keychain.retrieveAccessToken()
44+
let sessionURL = session.serviceEndpoint.absoluteString
45+
46+
guard let requestURL = URL(string: "\(sessionURL)/xrpc/app.bsky.bookmark.createBookmark") else {
47+
throw ATRequestPrepareError.invalidRequestURL
48+
}
49+
50+
let requestBody = AppBskyLexicon.Bookmark.CreateBookmarkRequestBody(
51+
uri: uri,
52+
cid: cid
53+
)
54+
55+
do {
56+
let request = apiClientService.createRequest(
57+
forRequest: requestURL,
58+
andMethod: .post,
59+
acceptValue: "application/json",
60+
contentTypeValue: nil,
61+
authorizationValue: "Bearer \(accessToken)"
62+
)
63+
64+
_ = try await apiClientService.sendRequest(
65+
request,
66+
withEncodingBody: requestBody
67+
)
68+
} catch {
69+
throw error
70+
}
71+
}
72+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//
2+
// AppBskyBookmarkDeleteBookmarkMethod.swift
3+
// ATProtoKit
4+
//
5+
// Created by Christopher Jr Riley on 2025-09-26.
6+
//
7+
8+
import Foundation
9+
#if canImport(FoundationNetworking)
10+
import FoundationNetworking
11+
#endif
12+
13+
extension ATProtoKit {
14+
15+
/// Deletes a private bookmark for the specified record.
16+
///
17+
/// - Note: According to the AT Protocol specifications: "Deletes a private bookmark for the
18+
/// specified record. Currently, only `app.bsky.feed.post` records are supported.
19+
/// Requires authentication."
20+
///
21+
/// - SeeAlso: This is based on the [`app.bsky.bookmark.deleteBookmark`][github] lexicon.
22+
///
23+
/// [github]: https://github.com/bluesky-social/atproto/blob/main/lexicons/app/bsky/bookmark/deleteBookmark.json
24+
///
25+
/// - Parameter uri: The URI of the bookmark.
26+
///
27+
/// - Throws: An ``ATProtoError``-conforming error type, depending on the issue. Go to
28+
/// ``ATAPIError`` and ``ATRequestPrepareError`` for more details.
29+
public func deleteBookmark(uri: String) async throws {
30+
guard let session = try await self.getUserSession(),
31+
let keychain = sessionConfiguration?.keychainProtocol else {
32+
throw ATRequestPrepareError.missingActiveSession
33+
}
34+
35+
try await sessionConfiguration?.ensureValidToken()
36+
let accessToken = try await keychain.retrieveAccessToken()
37+
let sessionURL = session.serviceEndpoint.absoluteString
38+
39+
guard let requestURL = URL(string: "\(sessionURL)/xrpc/app.bsky.bookmark.deleteBookmark") else {
40+
throw ATRequestPrepareError.invalidRequestURL
41+
}
42+
43+
let requestBody = AppBskyLexicon.Bookmark.DeleteBookmarkRequestBody(
44+
uri: uri
45+
)
46+
47+
do {
48+
let request = apiClientService.createRequest(
49+
forRequest: requestURL,
50+
andMethod: .post,
51+
acceptValue: "application/json",
52+
contentTypeValue: nil,
53+
authorizationValue: "Bearer \(accessToken)"
54+
)
55+
56+
_ = try await apiClientService.sendRequest(
57+
request,
58+
withEncodingBody: requestBody
59+
)
60+
} catch {
61+
throw error
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)