import gleam/dynamic/decode.{type Decoder} import gleam/option.{type Option} import utils/api.{type ApiResponse} import utils/auth.{NoAuth} pub type Stats { Stats( accounts: Option(Int), agents: Int, ships: Int, systems: Int, waypoints: Int, ) } fn stats_decoder() -> Decoder(Stats) { use accounts <- decode.optional_field( "accounts", option.None, decode.optional(decode.int), ) use agents <- decode.field("agents", decode.int) use ships <- decode.field("ships", decode.int) use systems <- decode.field("systems", decode.int) use waypoints <- decode.field("waypoints", decode.int) decode.success(Stats(accounts:, agents:, ships:, systems:, waypoints:)) } pub type Health { Health(last_market_update: Option(String)) } fn health_decoder() -> Decoder(Health) { use last_market_update <- decode.optional_field( "lastMarketUpdate", option.None, decode.optional(decode.string), ) decode.success(Health(last_market_update:)) } pub type CreditLeaderboardEntry { CreditLeaderboardEntry(agent_symbol: String, credits: Int) } fn credit_leaderboard_entry_decoder() -> Decoder(CreditLeaderboardEntry) { use agent_symbol <- decode.field("agentSymbol", decode.string) use credits <- decode.field("credits", decode.int) decode.success(CreditLeaderboardEntry(agent_symbol:, credits:)) } pub type ChartLeaderboardEntry { ChartLeaderboardEntry(agent_symbol: String, chart_count: Int) } fn chart_leaderboard_entry_decoder() -> Decoder(ChartLeaderboardEntry) { use agent_symbol <- decode.field("agentSymbol", decode.string) use chart_count <- decode.field("chartCount", decode.int) decode.success(ChartLeaderboardEntry(agent_symbol:, chart_count:)) } pub type Leaderboards { Leaderboards( most_credits: List(CreditLeaderboardEntry), most_submitted_charts: List(ChartLeaderboardEntry), ) } fn leaderboards_decoder() -> Decoder(Leaderboards) { use most_credits <- decode.field( "mostCredits", decode.list(credit_leaderboard_entry_decoder()), ) use most_submitted_charts <- decode.field( "mostSubmittedCharts", decode.list(chart_leaderboard_entry_decoder()), ) decode.success(Leaderboards(most_credits:, most_submitted_charts:)) } pub type ServerResets { ServerResets(next: String, frequency: String) } fn server_resets_decoder() -> Decoder(ServerResets) { use next <- decode.field("next", decode.string) use frequency <- decode.field("frequency", decode.string) decode.success(ServerResets(next:, frequency:)) } pub type Announcement { Announcement(title: String, body: String) } fn announcement_decoder() -> Decoder(Announcement) { use title <- decode.field("title", decode.string) use body <- decode.field("body", decode.string) decode.success(Announcement(title:, body:)) } pub type Link { Link(name: String, url: String) } fn link_decoder() -> Decoder(Link) { use name <- decode.field("name", decode.string) use url <- decode.field("url", decode.string) decode.success(Link(name:, url:)) } pub type GetServerStatusResponse { GetServerStatusResponse( status: String, version: String, reset_date: String, description: String, stats: Stats, health: Health, leaderboards: Leaderboards, server_resets: ServerResets, announcements: List(Announcement), links: List(Link), ) } fn get_server_status_response_decoder() -> Decoder(GetServerStatusResponse) { use status <- decode.field("status", decode.string) use version <- decode.field("version", decode.string) use reset_date <- decode.field("resetDate", decode.string) use description <- decode.field("description", decode.string) use stats <- decode.field("stats", stats_decoder()) use health <- decode.field("health", health_decoder()) use leaderboards <- decode.field("leaderboards", leaderboards_decoder()) use server_resets <- decode.field("serverResets", server_resets_decoder()) use announcements <- decode.field( "announcements", decode.list(announcement_decoder()), ) use links <- decode.field("links", decode.list(link_decoder())) decode.success(GetServerStatusResponse( status:, version:, reset_date:, description:, stats:, health:, leaderboards:, server_resets:, announcements:, links:, )) } pub fn get_server_status() -> ApiResponse(GetServerStatusResponse) { let request = api.get(NoAuth, "/") use response <- api.try_send(request) case response.status { 200 -> api.parse_response(response, get_server_status_response_decoder()) _ -> api.parse_error_response(response) } } pub type ErrorCode { ErrorCode(code: Int, name: String) } fn error_code_decoder() -> Decoder(ErrorCode) { use code <- decode.field("code", decode.int) use name <- decode.field("name", decode.string) decode.success(ErrorCode(code:, name:)) } pub type ListErrorCodesResponse { ListErrorCodesResponse(error_codes: List(ErrorCode)) } fn list_error_codes_response_decoder() -> Decoder(ListErrorCodesResponse) { use error_codes <- decode.field( "errorCodes", decode.list(error_code_decoder()), ) decode.success(ListErrorCodesResponse(error_codes:)) } pub fn list_error_codes() -> ApiResponse(ListErrorCodesResponse) { let request = api.get(NoAuth, "/error-codes") use response <- api.try_send(request) case response.status { 200 -> api.parse_response(response, list_error_codes_response_decoder()) _ -> api.parse_error_response(response) } }