import Foundation struct GiteaUser: Decodable, Sendable { let login: String let id: Int } struct GiteaRepo: Codable, Identifiable, Hashable, Sendable { let id: Int let fullName: String let name: String let owner: Owner let updatedAt: Date struct Owner: Codable, Hashable, Sendable { let login: String } enum CodingKeys: String, CodingKey { case id, name, owner case fullName = "full_name" case updatedAt = "updated_at" } } struct GiteaRepoSearch: Decodable, Sendable { let data: [GiteaRepo] } struct GiteaIssue: Decodable, Sendable { let id: Int let number: Int let htmlUrl: String enum CodingKeys: String, CodingKey { case id, number case htmlUrl = "html_url" } } struct GiteaIssueAsset: Decodable, Sendable { let id: Int let name: String let browserDownloadUrl: String enum CodingKeys: String, CodingKey { case id, name case browserDownloadUrl = "browser_download_url" } } enum GiteaError: LocalizedError { case notConfigured case invalidBaseURL case http(Int, String) case decoding(String) var errorDescription: String? { switch self { case .notConfigured: "Open the Gitea Issue app and set your base URL + token." case .invalidBaseURL: "Base URL is not a valid URL." case .http(let code, let body): "Gitea returned \(code). \(body)" case .decoding(let msg): "Couldn't read response: \(msg)" } } }