/* * * Copyright (C) 2026 Andromeda * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ module radapi; import std::io; import std::core::string; import curl; enum Request : int (String path, int args) { DELEGATES_REPOS { "/delegates/$1/repos", 1 }, NODE { "/node", 0 }, NODE_POLICIES_REPOS { "/node/policies/repos", 0 }, NODE_POLICIES_REPO { "/node/policies/repos/$1", 1 }, NODES { "/nodes/$1", 1 }, NODES_INVENTORY { "/nodes/$1/inventory", 1 }, REPO_ROOT { "/repos", 0 }, REPO_SEARCH { "/repos/search", 0 }, REPO { "/repos/$1", 1 }, HISTORY { "/repos/$1/commits", 1 }, COMMIT { "/repos/$1/commits/$2", 2 }, DIFF { "/repos/$1/diff/$2/$3", 3 }, ACTIVITY { "/repos/$1/activity", 1 }, TREE_ROOT { "/repos/$1/tree/$2/", 2 }, TREE { "/repos/$1/tree/$2/$3", 3 }, STATS_TREE { "/repos/$1/stats/tree/$2", 2 }, REMOTES { "/repos/$1/remotes", 1 }, REMOTE { "/repos/$1/remotes/$2", 2 }, BLOB { "/repos/$1/blob/$2/$3", 3 }, README { "/repos/$1/readme/$2", 2 }, JOB { "/repos/$1/jobs/$2", 2 }, ISSUES { "/repos/$1/issues", 1 }, ISSUE { "/repos/$1/issues/$2", 2 }, PATCHES { "/repos/$1/patches", 1 }, PATCH { "/repos/$1/patches/$2", 2 }, STATS { "/stats", 0 }, } struct Client { Curl* c; char[10485760]* buffer; String endpoint; usz buffer_index; } fn Client* new_client(String endpoint) { Client* self = mem::alloc(Client); self.c = curl::easy_init(); self.endpoint = endpoint; self.buffer = mem::alloc(char[10485760]); curl::easy_setopt(self.c, CurlOption.WRITEFUNCTION, &cb); curl::easy_setopt(self.c, CurlOption.WRITEDATA, self); return self; } fn CurlResult Client.request(Client* self, Request r, String params, String... args) { self.buffer_index = 0; CurlResult cr; String s; @pool() { s = self.endpoint.tconcat(r.path); int i; while (i < r.args) { s = s.treplace(string::tformat("$%d", i+1), args[i]); i++; } s = s.tconcat(params); curl::easy_setopt(self.c, CurlOption.URL, s); cr = curl::easy_perform(self.c); }; return cr; } fn String Client.response(Client* self) { return (String)self.buffer.[..self.buffer_index]; } fn usz cb(char* buffer, usz size, usz nitems, Client* client) { client.buffer.[client.buffer_index..client.buffer_index+nitems-1] = buffer[..nitems-1]; client.buffer_index += nitems; return nitems; }