103 lines
3.4 KiB
Zig
103 lines
3.4 KiB
Zig
const std = @import("std");
|
|
const Config = @import("Config.zig");
|
|
const Cache = @import("cache/Cache.zig");
|
|
const MetNo = @import("weather/MetNo.zig");
|
|
const Server = @import("http/Server.zig");
|
|
const RateLimiter = @import("http/RateLimiter.zig");
|
|
const GeoIp = @import("location/GeoIp.zig");
|
|
const GeoCache = @import("location/GeoCache.zig");
|
|
const Airports = @import("location/Airports.zig");
|
|
const Resolver = @import("location/resolver.zig").Resolver;
|
|
const GeoLite2 = @import("location/GeoLite2.zig");
|
|
const version = @import("build_options").version;
|
|
|
|
pub fn main() !u8 {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
const cfg = try Config.load(allocator);
|
|
defer cfg.deinit(allocator);
|
|
|
|
std.log.info("wttr version {s} starting on {s}:{d}", .{ version, cfg.listen_host, cfg.listen_port });
|
|
std.log.info("Cache size: {d}", .{cfg.cache_size});
|
|
std.log.info("Cache dir: {s}", .{cfg.cache_dir});
|
|
std.log.info("GeoLite2 path: {s}", .{cfg.geolite_path});
|
|
if (cfg.geocache_file) |f| {
|
|
std.log.info("Geocache file: {s}", .{f});
|
|
} else {
|
|
std.log.info("Geocache: in-memory only", .{});
|
|
}
|
|
|
|
var metno = MetNo.init(allocator, null) catch |err| {
|
|
if (err == MetNo.MissingIdentificationError) return 1;
|
|
return err;
|
|
};
|
|
defer metno.deinit();
|
|
|
|
// Ensure GeoLite2 database exists
|
|
try GeoLite2.ensureDatabase(allocator, cfg.geolite_path);
|
|
|
|
// Initialize GeoIP database with optional IP2Location fallback
|
|
var geoip = GeoIp.init(
|
|
allocator,
|
|
cfg.geolite_path,
|
|
cfg.ip2location_api_key,
|
|
if (cfg.ip2location_api_key != null) cfg.ip2location_cache_file else null,
|
|
) catch |err| {
|
|
std.log.err("Failed to load GeoIP database from {s}: {}", .{ cfg.geolite_path, err });
|
|
return err;
|
|
};
|
|
defer geoip.deinit();
|
|
|
|
// Initialize geocoding cache
|
|
var geocache = try GeoCache.init(allocator, cfg.geocache_file);
|
|
defer geocache.deinit();
|
|
|
|
// Initialize airports database
|
|
var airports_db = try Airports.init(allocator);
|
|
defer airports_db.deinit();
|
|
|
|
// Initialize location resolver
|
|
var resolver = Resolver.init(allocator, &geoip, &geocache, &airports_db);
|
|
|
|
const cache = try Cache.init(allocator, .{
|
|
.max_entries = cfg.cache_size,
|
|
.cache_dir = cfg.cache_dir,
|
|
});
|
|
defer cache.deinit();
|
|
|
|
var rate_limiter = try RateLimiter.init(allocator, .{
|
|
.capacity = 300,
|
|
.refill_rate = 5,
|
|
.refill_interval_ms = 200,
|
|
});
|
|
defer rate_limiter.deinit();
|
|
|
|
var server = try Server.init(allocator, cfg.listen_host, cfg.listen_port, .{
|
|
.provider = metno.provider(cache),
|
|
.resolver = &resolver,
|
|
.geoip = &geoip,
|
|
}, &rate_limiter);
|
|
|
|
try server.listen();
|
|
return 0;
|
|
}
|
|
|
|
test {
|
|
std.testing.refAllDecls(@This());
|
|
_ = @import("Config.zig");
|
|
_ = @import("cache/Lru.zig");
|
|
_ = @import("weather/Mock.zig");
|
|
_ = @import("http/RateLimiter.zig");
|
|
_ = @import("http/query.zig");
|
|
_ = @import("http/help.zig");
|
|
_ = @import("render/line.zig");
|
|
_ = @import("render/json.zig");
|
|
_ = @import("render/v2.zig");
|
|
_ = @import("render/custom.zig");
|
|
_ = @import("location/GeoIp.zig");
|
|
_ = @import("location/GeoCache.zig");
|
|
_ = @import("location/Airports.zig");
|
|
_ = @import("location/resolver.zig");
|
|
}
|