// Sends a push message to a Gotify server #include "helpers.hpp" #include #include #include #include #include #include #include #include #include #include #include struct message { std::string base_url; std::string token; std::string title; std::string body; std::int16_t priority{5}; } __attribute__((aligned(128))) message; void read_options(int argc, char *argv[]) { namespace po = boost::program_options; po::options_description options("Options"); // clang-format off options.add_options() ("help,h", "Display this help and exit.") ("baseurl", po::value()->required(), "Example: https://push.example.org") ("token", po::value()->required(), "Application token") ("title", po::value()->required(), "Title of the message") ("message", po::value(), "Body of the message") ("priority", po::value(), "Priority of the message. Default is 5. " "0 = no notification, 1-3 = silent, 4-7 = sound, 8-10 = popup."); // clang-format on po::variables_map vm; po::store(po::command_line_parser(argc, argv).options(options).run(), vm); std::ifstream configfile(helpers::get_config_file_path("pushmsg.cfg")); po::store(po::parse_config_file(configfile, options, true), vm); configfile.close(); if (vm.count("help") != 0) { std::cout << options; std::exit(0); // NOLINT(concurrency-mt-unsafe) } po::notify(vm); message.base_url = vm["baseurl"].as(); message.token = vm["token"].as(); message.title = vm["title"].as(); if (vm.count("message") != 0) { message.body = vm["message"].as(); } if (vm.count("priority") != 0) { message.priority = vm["priority"].as(); } } int main(int argc, char *argv[]) { using std::cerr; try { read_options(argc, argv); RestClient::init(); RestClient::Connection conn(message.base_url); conn.FollowRedirects(true, 5); conn.SetTimeout(30); conn.SetHeaders({{"Content-Type", "application/json; charset=utf-8"}}); const nlohmann::json json{{"title", message.title}, {"message", message.body}, {"priority", message.priority}}; std::cout << json.dump() << '\n'; auto response{ conn.post("/message?token=" + message.token, json.dump())}; switch (response.code) { case 200: { break; } case 400: { cerr << "HTTP status 400: Bad Request.\n"; break; } case 401: { cerr << "HTTP status 401: Unauthorized (invalid token).\n"; break; } case 403: { cerr << "HTTP status 403: Forbidden.\n"; break; } case 404: { cerr << "HTTP status 404: Not Found.\n"; break; } case 502: { cerr << "HTTP status 502: Bad Gateway (server down).\n"; break; } default: { cerr << "HTTP status " << response.code << ".\n"; break; } } RestClient::disable(); } catch (const std::exception &e) { cerr << e.what() << '\n'; return 1; } }