#include #include #include #include "config.h" #include "pixivclient.h" #include "servehelper.h" #include "numberhelper.h" #include "routes/routes.h" int main(int argc, char** argv) { if (argc != 2) { fprintf(stderr, "Usage: %s \n", argc > 0 ? argv[0] : "pixwhile"); return 1; } Config config; try { config = load_config(argv[1]); } catch (const std::exception& e) { fprintf(stderr, "Failed to load config: %s\n", e.what()); return 1; } PixivClient pixiv_client; httplib::Server server; server.Get("/", [&](const httplib::Request& req, httplib::Response& res) { home_route(req, res, config); }); server.Get("/style\\.css", css_route); server.Get("/users/(\\d+)", [&](const httplib::Request& req, httplib::Response& res) { users_route(req, res, config, pixiv_client); }); server.Get("/users/(\\d+)/illustrations", [&](const httplib::Request& req, httplib::Response& res) { user_illustrations_route(req, res, config, pixiv_client); }); server.Get("/member\\.php", [&](const httplib::Request& req, httplib::Response& res) { std::string id = req.get_param_value("id"); if (id.empty() || id.find_first_not_of("1234567890") != std::string::npos) { res.status = 400; serve_error(req, res, config, "400: Bad Request", "Missing or invalid user ID"); return; } serve_redirect(req, res, config, get_origin(req, config) + "/users/" + id); }); server.Get("/member_illust\\.php", [&](const httplib::Request& req, httplib::Response& res) { std::string illust_id = req.get_param_value("illust_id"); if (illust_id.empty() || illust_id.find_first_not_of("1234567890") != std::string::npos) { res.status = 400; serve_error(req, res, config, "400: Bad Request", "Missing or invalid illust ID"); return; } serve_redirect(req, res, config, get_origin(req, config) + "/artworks/" + illust_id); }); #ifndef NDEBUG // TODO remove server.Get("/debug/illust", [&](const httplib::Request& req, httplib::Response& res) { Illust illust = pixiv_client.get_illust(to_ull(req.get_param_value("id"))); res.set_content(illust.title, "text/plain; charset=utf-8"); }); server.Get("/debug/exception/known", [](const httplib::Request& req, httplib::Response& res) { throw std::runtime_error("awoo"); }); server.Get("/debug/exception/unknown", [](const httplib::Request& req, httplib::Response& res) { throw "cope"; }); #endif server.Get(".*", [&](const httplib::Request& req, httplib::Response& res) { res.status = 404; serve_error(req, res, config, "404: Page not found"); }); server.set_exception_handler([&](const httplib::Request& req, httplib::Response& res, std::exception_ptr ep) { res.status = 500; try { std::rethrow_exception(ep); } catch (const std::exception& e) { fprintf(stderr, "Exception thrown on %s: %s\n", req.path.c_str(), e.what()); serve_error(req, res, config, "500: Internal server error", std::nullopt, e.what()); } catch (...) { fprintf(stderr, "Exception thrown on %s: Unknown exception\n", req.path.c_str()); serve_error(req, res, config, "500: Internal server error", std::nullopt, "Unknown exception"); } }); if (config.bind_port != 0) { if (!server.bind_to_port(config.bind_host, config.bind_port)) { fprintf(stderr, "Failed to bind to %s:%d\n", config.bind_host.c_str(), config.bind_port); return 1; } } else { int port = server.bind_to_any_port(config.bind_host); if (port == -1) { fprintf(stderr, "Failed to bind to %s:\n", config.bind_host.c_str()); return 1; } config.bind_port = port; } printf("Listening on %s:%d...\n", config.bind_host.c_str(), config.bind_port); if (!server.listen_after_bind()) { fprintf(stderr, "Failed to listen on %s:%d\n", config.bind_host.c_str(), config.bind_port); return 1; } }