diff options
Diffstat (limited to 'Hutch/Extensions/SRHTWebURL.swift')
| -rw-r--r-- | Hutch/Extensions/SRHTWebURL.swift | 84 |
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 + }() +} |
