277 lines
9.8 KiB
C++
277 lines
9.8 KiB
C++
#include "server/api_server.hpp"
|
|
|
|
#include "util/file_util.hpp"
|
|
#include "util/http_util.hpp"
|
|
|
|
namespace lm {
|
|
|
|
void ApiServer::registerMediaRoutes(httplib::Server& svr)
|
|
{
|
|
svr.Get("/api/sites", [this](const httplib::Request&, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = nlohmann::json({{"sites", site_store_.list()}}).dump();
|
|
});
|
|
|
|
svr.Post("/api/sites", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
nlohmann::json body;
|
|
try
|
|
{
|
|
body = nlohmann::json::parse(req.body);
|
|
}
|
|
catch (...)
|
|
{
|
|
return HttpUtil::jsonError(res, 400, "invalid JSON");
|
|
}
|
|
std::string err;
|
|
const auto created = site_store_.create(body, err);
|
|
if (!created)
|
|
return HttpUtil::jsonError(res, 400, err);
|
|
res.status = 201;
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = created->dump();
|
|
});
|
|
|
|
svr.Put(R"(/api/sites/([^/]+)$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
nlohmann::json body;
|
|
try
|
|
{
|
|
body = nlohmann::json::parse(req.body);
|
|
}
|
|
catch (...)
|
|
{
|
|
return HttpUtil::jsonError(res, 400, "invalid JSON");
|
|
}
|
|
std::string err;
|
|
if (!site_store_.update(id, body, err))
|
|
return HttpUtil::jsonError(res, 404, err);
|
|
const auto updated = site_store_.find(id);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = updated ? updated->dump() : nlohmann::json::object().dump();
|
|
});
|
|
|
|
svr.Delete(R"(/api/sites/([^/]+)$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
std::string err;
|
|
if (!site_store_.remove(id, err))
|
|
return HttpUtil::jsonError(res, 400, err);
|
|
res.status = 204;
|
|
});
|
|
|
|
svr.Get("/api/maps", [this](const httplib::Request&, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = nlohmann::json({{"maps", map_store_.list()}}).dump();
|
|
});
|
|
|
|
svr.Get(R"(/api/maps/([^/]+)$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
const auto map = map_store_.find(id);
|
|
if (!map)
|
|
return HttpUtil::jsonError(res, 404, "map not found");
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = map->dump();
|
|
});
|
|
|
|
svr.Post("/api/maps", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
nlohmann::json body;
|
|
try
|
|
{
|
|
body = nlohmann::json::parse(req.body);
|
|
}
|
|
catch (...)
|
|
{
|
|
return HttpUtil::jsonError(res, 400, "invalid JSON");
|
|
}
|
|
std::string err;
|
|
const auto created = map_store_.create(body, err);
|
|
if (!created)
|
|
return HttpUtil::jsonError(res, 400, err);
|
|
res.status = 201;
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = created->dump();
|
|
});
|
|
|
|
svr.Put(R"(/api/maps/([^/]+)$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
nlohmann::json body;
|
|
try
|
|
{
|
|
body = nlohmann::json::parse(req.body);
|
|
}
|
|
catch (...)
|
|
{
|
|
return HttpUtil::jsonError(res, 400, "invalid JSON");
|
|
}
|
|
std::string err;
|
|
if (!map_store_.update(id, body, err))
|
|
return HttpUtil::jsonError(res, 404, err);
|
|
const auto updated = map_store_.find(id);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = updated ? updated->dump() : nlohmann::json::object().dump();
|
|
});
|
|
|
|
svr.Delete(R"(/api/maps/([^/]+)$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
std::string err;
|
|
if (!map_store_.remove(id, err))
|
|
return HttpUtil::jsonError(res, 404, err);
|
|
robot_runtime_.clearActiveMapIf(id);
|
|
res.status = 204;
|
|
});
|
|
|
|
svr.Get(R"(/api/maps/([^/]+)/image$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
const auto path = map_store_.imagePath(id);
|
|
if (!path)
|
|
return HttpUtil::jsonError(res, 404, "map image not found");
|
|
res.set_header("Content-Type", HttpUtil::contentTypeForPath(*path));
|
|
res.body = FileUtil::readBinary(*path);
|
|
});
|
|
|
|
svr.Post(R"(/api/maps/([^/]+)/image$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
if (!req.form.has_file("file"))
|
|
return HttpUtil::jsonError(res, 400, "file is required");
|
|
const auto& file = req.form.get_file("file");
|
|
const std::string filename = file.filename.empty() ? "map.png" : file.filename;
|
|
std::string err;
|
|
if (!map_store_.saveImageFile(id, filename, file.content, err))
|
|
return HttpUtil::jsonError(res, 400, err);
|
|
const auto updated = map_store_.find(id);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = updated ? updated->dump() : nlohmann::json::object().dump();
|
|
});
|
|
|
|
svr.Get(R"(/api/maps/([^/]+)/yaml$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
const auto path = map_store_.yamlPath(id);
|
|
if (!path)
|
|
return HttpUtil::jsonError(res, 404, "map yaml not found");
|
|
res.set_header("Content-Type", "text/yaml; charset=utf-8");
|
|
res.body = FileUtil::readBinary(*path);
|
|
});
|
|
|
|
svr.Post(R"(/api/maps/([^/]+)/yaml$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
if (req.body.empty())
|
|
return HttpUtil::jsonError(res, 400, "yaml body is required");
|
|
std::string err;
|
|
if (!map_store_.saveYamlFile(id, req.body, err))
|
|
return HttpUtil::jsonError(res, 400, err);
|
|
const auto updated = map_store_.find(id);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = updated ? updated->dump() : nlohmann::json::object().dump();
|
|
});
|
|
|
|
svr.Get("/api/sounds", [this](const httplib::Request&, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = nlohmann::json({{"sounds", sound_store_.list()}}).dump();
|
|
});
|
|
|
|
svr.Get(R"(/api/sounds/([^/]+)$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
const auto sound = sound_store_.find(id);
|
|
if (!sound)
|
|
return HttpUtil::jsonError(res, 404, "sound not found");
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = sound->dump();
|
|
});
|
|
|
|
svr.Post("/api/sounds", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
nlohmann::json body;
|
|
try
|
|
{
|
|
body = nlohmann::json::parse(req.body);
|
|
}
|
|
catch (...)
|
|
{
|
|
return HttpUtil::jsonError(res, 400, "invalid JSON");
|
|
}
|
|
std::string err;
|
|
const auto created = sound_store_.create(body, err);
|
|
if (!created)
|
|
return HttpUtil::jsonError(res, 400, err);
|
|
res.status = 201;
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = created->dump();
|
|
});
|
|
|
|
svr.Put(R"(/api/sounds/([^/]+)$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
nlohmann::json body;
|
|
try
|
|
{
|
|
body = nlohmann::json::parse(req.body);
|
|
}
|
|
catch (...)
|
|
{
|
|
return HttpUtil::jsonError(res, 400, "invalid JSON");
|
|
}
|
|
std::string err;
|
|
if (!sound_store_.update(id, body, err))
|
|
return HttpUtil::jsonError(res, 404, err);
|
|
const auto updated = sound_store_.find(id);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = updated ? updated->dump() : nlohmann::json::object().dump();
|
|
});
|
|
|
|
svr.Delete(R"(/api/sounds/([^/]+)$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
std::string err;
|
|
if (!sound_store_.remove(id, err))
|
|
return HttpUtil::jsonError(res, 404, err);
|
|
res.status = 204;
|
|
});
|
|
|
|
svr.Get(R"(/api/sounds/([^/]+)/file$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
const auto path = sound_store_.filePath(id);
|
|
if (!path)
|
|
return HttpUtil::jsonError(res, 404, "sound file not found");
|
|
res.set_header("Content-Type", HttpUtil::contentTypeForPath(*path));
|
|
res.body = FileUtil::readBinary(*path);
|
|
});
|
|
|
|
svr.Post(R"(/api/sounds/([^/]+)/file$)", [this](const httplib::Request& req, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
const std::string id = req.matches[1];
|
|
if (!req.form.has_file("file"))
|
|
return HttpUtil::jsonError(res, 400, "file is required");
|
|
const auto& file = req.form.get_file("file");
|
|
const std::string filename = file.filename.empty() ? (id + ".wav") : file.filename;
|
|
std::string err;
|
|
if (!sound_store_.saveFile(id, filename, file.content, err))
|
|
return HttpUtil::jsonError(res, 400, err);
|
|
const auto updated = sound_store_.find(id);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = updated ? updated->dump() : nlohmann::json::object().dump();
|
|
});
|
|
|
|
svr.Get("/api/recordings", [](const httplib::Request&, httplib::Response& res) {
|
|
HttpUtil::addCors(res);
|
|
res.set_header("Content-Type", "application/json; charset=utf-8");
|
|
res.body = nlohmann::json({{"recordings", nlohmann::json::array()}}).dump();
|
|
});
|
|
}
|
|
|
|
} // namespace lm
|