summaryrefslogtreecommitdiff
path: root/Hutch/Extensions/SRHTWebURL.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-03-17 23:19:22 -0500
committerChristian Cleberg <[email protected]>2026-03-17 23:19:22 -0500
commit8f2057c53e9009c2529c9c4849c914666c0e4b40 (patch)
tree77b5a93625fe9ea98baf4ab0d137055524705dad /Hutch/Extensions/SRHTWebURL.swift
parentd27726d8755a5631fbd2105f735811a95379c4ab (diff)
downloadhutch-8f2057c53e9009c2529c9c4849c914666c0e4b40.tar.gz
hutch-8f2057c53e9009c2529c9c4849c914666c0e4b40.tar.bz2
hutch-8f2057c53e9009c2529c9c4849c914666c0e4b40.zip
create privacy policy
Diffstat (limited to 'Hutch/Extensions/SRHTWebURL.swift')
-rw-r--r--Hutch/Extensions/SRHTWebURL.swift84
1 files changed, 84 insertions, 0 deletions
diff --git a/Hutch/Extensions/SRHTWebURL.swift b/Hutch/Extensions/SRHTWebURL.swift
new file mode 100644
index 0000000..53556de
--- /dev/null
+++ b/Hutch/Extensions/SRHTWebURL.swift
@@ -0,0 +1,84 @@
+import Foundation
+
+enum SRHTWebURL {
+ static func repository(_ repository: RepositorySummary) -> URL? {
+ userScopedURL(
+ host: "\(repository.service.rawValue).sr.ht",
+ ownerCanonicalName: repository.owner.canonicalName,
+ pathComponents: [repository.name]
+ )
+ }
+
+ static func build(jobId: Int, ownerCanonicalName: String) -> URL? {
+ userScopedURL(
+ host: "builds.sr.ht",
+ ownerCanonicalName: ownerCanonicalName,
+ pathComponents: ["job", String(jobId)]
+ )
+ }
+
+ static func tracker(ownerUsername: String, trackerName: String) -> URL? {
+ userScopedURL(
+ host: "todo.sr.ht",
+ ownerUsername: ownerUsername,
+ pathComponents: [trackerName]
+ )
+ }
+
+ static func ticket(ownerUsername: String, trackerName: String, ticketId: Int) -> URL? {
+ userScopedURL(
+ host: "todo.sr.ht",
+ ownerUsername: ownerUsername,
+ pathComponents: [trackerName, String(ticketId)]
+ )
+ }
+
+ static func profile(canonicalName: String) -> URL? {
+ userScopedURL(
+ host: "meta.sr.ht",
+ ownerCanonicalName: canonicalName,
+ pathComponents: []
+ )
+ }
+
+ private static func userScopedURL(
+ host: String,
+ ownerCanonicalName: String,
+ pathComponents: [String]
+ ) -> URL? {
+ userScopedURL(
+ host: host,
+ ownerUsername: username(from: ownerCanonicalName),
+ pathComponents: pathComponents
+ )
+ }
+
+ private static func userScopedURL(
+ host: String,
+ ownerUsername: String,
+ pathComponents: [String]
+ ) -> URL? {
+ var components = URLComponents()
+ components.scheme = "https"
+ components.host = host
+
+ let encodedComponents = (["~\(ownerUsername)"] + pathComponents).map { pathComponent in
+ pathComponent.addingPercentEncoding(withAllowedCharacters: pathComponentCharacterSet) ?? pathComponent
+ }
+ components.percentEncodedPath = "/" + encodedComponents.joined(separator: "/")
+ return components.url
+ }
+
+ private static func username(from canonicalName: String) -> String {
+ if canonicalName.hasPrefix("~") {
+ return String(canonicalName.dropFirst())
+ }
+ return canonicalName
+ }
+
+ private static let pathComponentCharacterSet: CharacterSet = {
+ var characterSet = CharacterSet.urlPathAllowed
+ characterSet.remove(charactersIn: "/")
+ return characterSet
+ }()
+}