diff --git a/libs/odin-curl b/libs/odin-curl new file mode 160000 index 0000000..cf072c1 --- /dev/null +++ b/libs/odin-curl @@ -0,0 +1 @@ +Subproject commit cf072c11233c1226b0ccfcb65fa9d93224de8e01 diff --git a/main.odin b/main.odin new file mode 100644 index 0000000..0e019ae --- /dev/null +++ b/main.odin @@ -0,0 +1,84 @@ +package main + +import curl "./libs/odin-curl/" +import "core:encoding/json" +import "core:flags" +import "core:fmt" +import "core:mem" +import vmem "core:mem/virtual" +import "core:os" +import "core:strings" +import "core:time" + +HOST :: "https://api.openweathermap.org/data/2.5/weather?q=" + +main :: proc() { + arena: vmem.Arena + arena_err := vmem.arena_init_growing(&arena) + ensure(arena_err == nil) //make sure it doesnt fuck up + arena_alloc := vmem.arena_allocator(&arena) + defer vmem.arena_destroy(&arena) //clean up at end + + city := "" //city name e.g. London + code := "" //code e.g. UK, JP, GE + api_key := "" //openweather api key + + sb := strings.builder_make(allocator = arena_alloc) + buf1: [64]u8 + buf2: [64]u8 + + // parse os.args in this order + // city -> code -> api_key + program_name := os.args[0] + if len(os.args) < 3 { + print_usage() + } else if len(os.args) > 4 { + print_usage() + } + city = os.args[1] + code = os.args[2] + api_key = os.args[3] + + strings.write_string(&sb, HOST) + strings.write_string(&sb, city) + strings.write_string(&sb, ",") + strings.write_string(&sb, code) + strings.write_string(&sb, "&units=metric") + strings.write_string(&sb, "&appid=") + strings.write_string(&sb, api_key) + + full_url := strings.to_string(sb) + data := curl_web(full_url) + + weather: WeatherResponse + unmarshal_err := json.unmarshal_any(data, &weather) + if unmarshal_err != nil { + fmt.eprintln("Failed to unmarshal the file!") + return + } + + weather_location := weather.name + weather_code := weather.sys.country + weather_resp := weather.weather[0].main + weather_resp_detail := weather.weather[0].description + //weather_icon := weather.weather[0].icon + temperature := weather.main.temp + feels_like_temp := weather.main.feels_like + temp_min := weather.main.temp_min + temp_max := weather.main.temp_max + sunset_time := time.to_string_hms_12(time.unix(weather.sys.sunset, 0), buf1[:]) + sunrise_time := time.to_string_hms_12(time.unix(weather.sys.sunrise, 0), buf2[:]) + + fmt.println("Location:", weather_location) + fmt.println("Country Code:", weather_code) + fmt.println("Weather:", weather_resp) + fmt.println("Weather Detail:", weather_resp_detail) + //fmt.println("Weather Icon:", weather_icon) + fmt.println("Temperature:", temperature) + fmt.println("Feels Like Temperature:", feels_like_temp) + fmt.println("Min Temperature:", temp_min) + fmt.println("Max Temperature:", temp_max) + fmt.println("Sunset Time:", sunset_time) + fmt.println("Sunrise Time:", sunrise_time) + +} diff --git a/test.json b/test.json new file mode 100644 index 0000000..68fb601 --- /dev/null +++ b/test.json @@ -0,0 +1,32 @@ +[ + { + "arrival": "2025-01-01", + "departure": "2025-01-16", + "name": "John Doe", + "reference": "GFYHD4" + }, + { + "arrival": "2025-03-01", + "departure": "2025-03-04", + "name": "Jonathan Davis", + "reference": "TRICQ23" + }, + { + "arrival": "2025-01-15", + "departure": "2025-01-18", + "name": "Daniel Dumile", + "reference": "YH74H1" + }, + { + "arrival": "2025-02-05", + "departure": "2025-02-15", + "name": "Nasir Jones", + "reference": "XNASL2" + }, + { + "arrival": "2025-02-15", + "departure": "2025-02-21", + "name": "Adam Carter", + "reference": "93TILIN" + } +] diff --git a/util.odin b/util.odin new file mode 100644 index 0000000..8aae4f7 --- /dev/null +++ b/util.odin @@ -0,0 +1,61 @@ +package main + +import curl "./libs/odin-curl/" +import "base:runtime" +import "core:encoding/json" +import "core:fmt" +import "core:mem" +import vmem "core:mem/virtual" +import "core:os" +import "core:unicode/utf8" + +print_usage :: proc() { + fmt.printf("Usage:\n\t%s [city] [code] [api_key] \n", os.args[0]) + os.exit(1) +} + +DataContext :: struct { + data: []byte, + ctx: runtime.Context, +} + +curl_web :: proc(url: string) -> []u8 { + using curl + h := easy_init() + defer easy_cleanup(h) + + headers: ^curl_slist + headers = slist_append(nil, "content-type: application/json") + headers = slist_append(headers, "Accept: application/json") + headers = slist_append(headers, "charset: utf-8") + defer slist_free_all(headers) + + easy_setopt(h, CURLoption.URL, url) + hres := easy_setopt(h, CURLoption.HTTPHEADER, headers) + // Verify option was set correctly: + if hres != CURLcode.OK { + fmt.println("Failed to set HTTPHEADER: ", easy_strerror(hres)) + } + + easy_setopt(h, CURLoption.WRITEFUNCTION, write_callback) + data := DataContext{nil, context} + easy_setopt(h, .WRITEDATA, &data) + + result := easy_perform(h) + if result != CURLcode.OK { + fmt.println("Error occurred: ", result) + } + + return data.data +} + + +write_callback :: proc "c" (contents: rawptr, size: uint, nmemb: uint, userp: rawptr) -> uint { + dc := transmute(^DataContext)userp + context = dc.ctx + total_size := size * nmemb + content_str := transmute([^]u8)contents + dc.data = make([]byte, int(total_size)) // <-- ALLOCATION + mem.copy(&dc.data[0], content_str, int(total_size)) + return total_size +} diff --git a/weather b/weather new file mode 100755 index 0000000..3178763 Binary files /dev/null and b/weather differ diff --git a/weather.odin b/weather.odin new file mode 100644 index 0000000..8182d0b --- /dev/null +++ b/weather.odin @@ -0,0 +1,60 @@ +package main + +Clouds :: struct { + all: f32, +} + +Sys :: struct { + sunrise: i64, + sunset: i64, + country: string, +} + +Coord :: struct { + lon: f32, + lat: f32, +} + +Weather :: struct { + id: int, + main: string, + icon: string, + description: string, +} + +Main :: struct { + temp_min: f32, + feels_like: f32, + pressure: int, + temp_max: f32, + temp: f32, + humidity: int, + sea_level: int, + grnd_level: int, +} + +Wind :: struct { + gust: f32, + speed: f32, + deg: int, +} + +Visibility :: struct { + visibility: int, +} + +WeatherResponse :: struct { + clouds: Clouds, + sys: Sys, + name: string, + base: string, + coord: Coord, + timezone: int, + weather: []Weather, + main: Main, + visibility: int, + dt: f64, + id: int, + wind: Wind, + cod: int, +}