Files
bible/Bible-Week/BibleAPI.swift
Matheus A Silveira bf49716639 Move API key para Secrets.swift fora do versionamento
- Secrets.swift entra no .gitignore; Secrets.swift.example fica como modelo
- Adiciona .gitignore (xcuserdata, DerivedData) e README com instruções

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-04 19:49:33 -03:00

89 lines
2.4 KiB
Swift

//
// BibleAPI.swift
// Bible-Week
//
// Cliente da API da Bíblia (NBV - Nova Bíblia Viva).
//
import Foundation
// MARK: - Modelos
/// Um livro da Bíblia (ex.: Gênesis, João).
struct Book: Decodable, Identifiable, Hashable {
let code: String
let name: String
let testament: String
let bookOrder: Int
let chapterCount: Int
var id: String { code }
enum CodingKeys: String, CodingKey {
case code, name, testament
case bookOrder = "book_order"
case chapterCount = "chapter_count"
}
}
/// Resposta de `GET /v1/books`.
struct BooksResponse: Decodable {
let books: [Book]
}
/// Um versículo com seu número e texto.
struct Verse: Decodable, Identifiable, Hashable {
let verse: Int
let text: String
var id: Int { verse }
}
/// Resposta de um capítulo completo.
struct Chapter: Decodable, Hashable {
let translation: String
let book: String
let bookName: String
let chapter: Int
let verses: [Verse]
}
// MARK: - Serviço
/// Cliente mínimo, somente leitura, para a API da Bíblia.
enum BibleAPI {
static let baseURL = URL(string: "https://bible.falehandix.com.br")!
// A chave vive em Secrets.swift (gitignored) ver Secrets.swift.example.
static let apiKey = Secrets.bibleAPIKey
/// Faz um GET na API e decodifica a resposta JSON.
static func get<T: Decodable>(_ path: String, query: [URLQueryItem] = []) async throws -> T {
var components = URLComponents(
url: baseURL.appendingPathComponent(path),
resolvingAgainstBaseURL: false
)!
if !query.isEmpty { components.queryItems = query }
var request = URLRequest(url: components.url!)
request.setValue(apiKey, forHTTPHeaderField: "X-API-Key")
let (data, response) = try await URLSession.shared.data(for: request)
guard let http = response as? HTTPURLResponse, 200..<300 ~= http.statusCode else {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(T.self, from: data)
}
/// Busca todos os 66 livros em ordem canônica.
static func books() async throws -> [Book] {
let response: BooksResponse = try await get("/v1/books")
return response.books
}
/// Busca o texto completo de um capítulo.
static func chapter(book code: String, chapter: Int) async throws -> Chapter {
try await get("/v1/books/\(code)/chapters/\(chapter)")
}
}