fixes
This commit is contained in:
parent
dec748851d
commit
797076c379
13
monitarr/libmonitarr/include/args.hpp
Normal file
13
monitarr/libmonitarr/include/args.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef LIBMONITARR_INCLUDE_ARGS_HPP_
|
||||
#define LIBMONITARR_INCLUDE_ARGS_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
#include <optional>
|
||||
|
||||
namespace monitarr {
|
||||
[[nodiscard]] auto get_arg(std::string_view arg, int argc, char **argv)
|
||||
-> std::optional<std::string>;
|
||||
[[nodiscard]] auto has_arg(std::string_view arg, int argc, char **argv) -> bool;
|
||||
} // namespace monitarr
|
||||
|
||||
#endif // LIBMONITARR_INCLUDE_ARGS_HPP_
|
33
monitarr/libmonitarr/src/args.cpp
Normal file
33
monitarr/libmonitarr/src/args.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "args.hpp"
|
||||
|
||||
namespace monitarr {
|
||||
auto get_arg(std::string_view arg, int argc, char **argv)
|
||||
-> std::optional<std::string> {
|
||||
auto cmd_line = std::span(argv, static_cast<std::size_t>(argc)) |
|
||||
std::views::transform(
|
||||
[](char const *val) { return std::string_view(val); });
|
||||
auto iter =
|
||||
std::ranges::find_if(std::next(cmd_line.begin()), cmd_line.end(),
|
||||
[&arg](auto &&item) -> bool { return arg == item; });
|
||||
if (iter == cmd_line.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
iter = std::next(iter);
|
||||
if (iter == cmd_line.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::string{*iter};
|
||||
}
|
||||
|
||||
auto has_arg(std::string_view arg, int argc, char **argv) -> bool {
|
||||
auto cmd_line = std::span(argv, static_cast<std::size_t>(argc)) |
|
||||
std::views::transform(
|
||||
[](char const *val) { return std::string_view(val); });
|
||||
return std::ranges::find_if(std::next(cmd_line.begin()), cmd_line.end(),
|
||||
[&arg](auto &&item) -> bool {
|
||||
return arg == item;
|
||||
}) != cmd_line.end();
|
||||
}
|
||||
} // namespace monitarr
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "initialize.hpp"
|
||||
|
||||
#include "args.hpp"
|
||||
#include "data_db.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "utils/common.hpp"
|
||||
@ -29,12 +30,16 @@ namespace monitarr {
|
||||
|
||||
static void remove_stalled(std::string_view download_id, std::string_view title,
|
||||
std::uint64_t episode_id, std::uint64_t movie_id,
|
||||
const server_cfg &server, data_db &state_db) {
|
||||
const server_cfg &server,
|
||||
data_db *state_db = nullptr) {
|
||||
MONITARR_USES_FUNCTION_NAME();
|
||||
|
||||
fmt::println("remove and block {}|{}|{}|{}", server.id, server.url, title,
|
||||
download_id);
|
||||
state_db.remove(download_id);
|
||||
|
||||
if (state_db != nullptr) {
|
||||
state_db->remove(download_id);
|
||||
}
|
||||
|
||||
auto cli = create_client(server);
|
||||
auto response = cli.Delete(
|
||||
@ -54,8 +59,9 @@ static void remove_stalled(std::string_view download_id, std::string_view title,
|
||||
{"movieIds", {movie_id}},
|
||||
});
|
||||
|
||||
response = cli.Post("/api/{}/command", data.dump(), "application/json");
|
||||
if (response->status != httplib::StatusCode::OK_200) {
|
||||
response = cli.Post(fmt::format("/api/{}/command", server.api_version),
|
||||
data.dump(), "application/json");
|
||||
if (response->status != httplib::StatusCode::Created_201) {
|
||||
utils::error::handle_error(
|
||||
function_name,
|
||||
fmt::format("failed to search radarr|{}|{}|{}|{}|{}", server.id,
|
||||
@ -73,8 +79,9 @@ static void remove_stalled(std::string_view download_id, std::string_view title,
|
||||
{"episodeIds", {episode_id}},
|
||||
});
|
||||
|
||||
response = cli.Post("/api/{}/command", data.dump(), "application/json");
|
||||
if (response->status != httplib::StatusCode::OK_200) {
|
||||
response = cli.Post(fmt::format("/api/{}/command", server.api_version),
|
||||
data.dump(), "application/json");
|
||||
if (response->status != httplib::StatusCode::Created_201) {
|
||||
utils::error::handle_error(
|
||||
function_name,
|
||||
fmt::format("failed to search sonarr|{}|{}|{}|{}|{}", server.id,
|
||||
@ -82,6 +89,79 @@ static void remove_stalled(std::string_view download_id, std::string_view title,
|
||||
}
|
||||
}
|
||||
|
||||
static void display_queue(const server_cfg &server) {
|
||||
MONITARR_USES_FUNCTION_NAME();
|
||||
|
||||
auto cli = create_client(server);
|
||||
|
||||
std::uint16_t page{0U};
|
||||
while (++page != 0U) {
|
||||
httplib::Params params;
|
||||
params.emplace("page", std::to_string(page));
|
||||
params.emplace("pageSize", "100");
|
||||
|
||||
auto response =
|
||||
cli.Get(fmt::format("/api/{}/queue", server.api_version), params, {});
|
||||
if (response->status != httplib::StatusCode::OK_200) {
|
||||
utils::error::handle_error(
|
||||
function_name, fmt::format("check server request failed|{}|{}|{}",
|
||||
server.id, server.url, response->status));
|
||||
break;
|
||||
}
|
||||
|
||||
auto json_data = nlohmann::json::parse(response->body);
|
||||
if (json_data.at("page").get<std::uint32_t>() != page) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &record : json_data.at("records")) {
|
||||
fmt::println("{}", record.dump(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto get_download(std::uint64_t record_id,
|
||||
const server_cfg &server)
|
||||
-> std::optional<nlohmann::json> {
|
||||
MONITARR_USES_FUNCTION_NAME();
|
||||
|
||||
auto cli = create_client(server);
|
||||
|
||||
std::uint16_t page{0U};
|
||||
while (++page != 0U) {
|
||||
httplib::Params params;
|
||||
params.emplace("page", std::to_string(page));
|
||||
params.emplace("pageSize", "100");
|
||||
|
||||
auto response =
|
||||
cli.Get(fmt::format("/api/{}/queue", server.api_version), params, {});
|
||||
if (response->status != httplib::StatusCode::OK_200) {
|
||||
utils::error::handle_error(
|
||||
function_name, fmt::format("check server request failed|{}|{}|{}",
|
||||
server.id, server.url, response->status));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto json_data = nlohmann::json::parse(response->body);
|
||||
if (json_data.at("page").get<std::uint32_t>() != page) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto iter = std::ranges::find_if(
|
||||
json_data.at("records"),
|
||||
[&record_id](const nlohmann::json &record) -> bool {
|
||||
return record_id == record.at("id").get<std::uint64_t>();
|
||||
});
|
||||
if (iter == json_data.at("records").end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return *iter;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static void check_server(const server_cfg &server, data_db &state_db) {
|
||||
MONITARR_USES_FUNCTION_NAME();
|
||||
|
||||
@ -112,8 +192,8 @@ static void check_server(const server_cfg &server, data_db &state_db) {
|
||||
auto now = utils::time::get_time_now();
|
||||
|
||||
for (const auto &record : json_data.at("records")) {
|
||||
auto download_id = fmt::format(
|
||||
"{}/{}", server.id, record.at("downloadId").get<std::string>());
|
||||
auto download_id =
|
||||
fmt::format("{}/{}", server.id, record.at("id").get<std::uint64_t>());
|
||||
auto episode_id = record.contains("episodeId")
|
||||
? record["episodeId"].get<std::uint64_t>()
|
||||
: std::uint64_t{0U};
|
||||
@ -147,7 +227,7 @@ static void check_server(const server_cfg &server, data_db &state_db) {
|
||||
server.timeout) {
|
||||
if (size_left == data->size_left) {
|
||||
remove_stalled(download_id, title, episode_id, movie_id, server,
|
||||
state_db);
|
||||
&state_db);
|
||||
} else if (size_left == 0U || not is_downloading) {
|
||||
state_db.remove(download_id);
|
||||
} else {
|
||||
@ -203,7 +283,7 @@ static void check_server(const server_cfg &server, data_db &state_db) {
|
||||
|
||||
using namespace monitarr;
|
||||
|
||||
auto main(int /* argc */, char ** /* argv */) -> int {
|
||||
auto main(int argc, char **argv) -> int {
|
||||
MONITARR_USES_FUNCTION_NAME();
|
||||
|
||||
#if defined(PROJECT_ENABLE_BACKWARD_CPP)
|
||||
@ -214,71 +294,109 @@ auto main(int /* argc */, char ** /* argv */) -> int {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static std::mutex mtx;
|
||||
static std::condition_variable notify;
|
||||
static stop_type stop_requested{false};
|
||||
|
||||
static const auto quit_handler = [](int sig) {
|
||||
fmt::println("stop requested|{}", sig);
|
||||
stop_requested = true;
|
||||
|
||||
mutex_lock lock(mtx);
|
||||
notify.notify_all();
|
||||
};
|
||||
|
||||
std::signal(SIGINT, quit_handler);
|
||||
std::signal(SIGQUIT, quit_handler);
|
||||
std::signal(SIGTERM, quit_handler);
|
||||
|
||||
auto ret{0};
|
||||
|
||||
try {
|
||||
std::string cfg_file;
|
||||
auto cfg{load_config(cfg_file)};
|
||||
auto state_db{load_db()};
|
||||
|
||||
if (cfg.server_list.empty()) {
|
||||
utils::error::handle_error(function_name,
|
||||
"no servers have been configured");
|
||||
ret = 3;
|
||||
} else {
|
||||
while (not stop_requested) {
|
||||
std::for_each(std::execution::par, cfg.server_list.begin(),
|
||||
cfg.server_list.end(),
|
||||
[&state_db](const server_cfg &server) {
|
||||
if (stop_requested) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
check_server(server, state_db);
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
}
|
||||
});
|
||||
unique_mutex_lock lock(mtx);
|
||||
if (stop_requested) {
|
||||
continue;
|
||||
if (argc > 1) {
|
||||
try {
|
||||
std::string cfg_file;
|
||||
auto cfg{load_config(cfg_file)};
|
||||
if (has_arg("-d", argc, argv)) {
|
||||
fmt::println("{}", nlohmann::json(cfg).dump(2));
|
||||
} else if (has_arg("-l", argc, argv)) {
|
||||
auto idx = get_arg("-i", argc, argv);
|
||||
if (idx.has_value()) {
|
||||
auto &server = cfg.server_list.at(utils::string::to_uint64(*idx));
|
||||
fmt::println("queue|{}|{}", server.id, server.url);
|
||||
display_queue(server);
|
||||
}
|
||||
} else if (has_arg("-b", argc, argv)) {
|
||||
auto idx = get_arg("-i", argc, argv);
|
||||
if (idx.has_value()) {
|
||||
auto &server = cfg.server_list.at(utils::string::to_uint64(*idx));
|
||||
auto record_id = get_arg("-id", argc, argv);
|
||||
if (record_id.has_value()) {
|
||||
auto entry =
|
||||
get_download(utils::string::to_uint64(*record_id), server);
|
||||
if (entry.has_value()) {
|
||||
remove_stalled(fmt::format("{}/{}", server.id, *record_id),
|
||||
entry->at("title").get<std::string>(), 0U,
|
||||
entry->at("movieId").get<std::uint64_t>(), server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt::println("waiting for next check|{}", cfg.check_interval);
|
||||
notify.wait_for(lock, cfg.check_interval);
|
||||
}
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
ret = 2;
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
ret = 2;
|
||||
}
|
||||
} else {
|
||||
static std::mutex mtx;
|
||||
static std::condition_variable notify;
|
||||
static stop_type stop_requested{false};
|
||||
|
||||
static const auto quit_handler = [](int sig) {
|
||||
fmt::println("stop requested|{}", sig);
|
||||
stop_requested = true;
|
||||
|
||||
mutex_lock lock(mtx);
|
||||
notify.notify_all();
|
||||
};
|
||||
|
||||
std::signal(SIGINT, quit_handler);
|
||||
std::signal(SIGQUIT, quit_handler);
|
||||
std::signal(SIGTERM, quit_handler);
|
||||
|
||||
try {
|
||||
std::string cfg_file;
|
||||
auto cfg{load_config(cfg_file)};
|
||||
auto state_db{load_db()};
|
||||
|
||||
if (cfg.server_list.empty()) {
|
||||
utils::error::handle_error(function_name,
|
||||
"no servers have been configured");
|
||||
ret = 3;
|
||||
} else {
|
||||
while (not stop_requested) {
|
||||
std::for_each(std::execution::par, cfg.server_list.begin(),
|
||||
cfg.server_list.end(),
|
||||
[&state_db](const server_cfg &server) {
|
||||
if (stop_requested) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
check_server(server, state_db);
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
}
|
||||
});
|
||||
unique_mutex_lock lock(mtx);
|
||||
if (stop_requested) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fmt::println("waiting for next check|{}", cfg.check_interval);
|
||||
notify.wait_for(lock, cfg.check_interval);
|
||||
}
|
||||
}
|
||||
|
||||
cfg.save(cfg_file);
|
||||
state_db.close();
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
ret = 2;
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
ret = 2;
|
||||
}
|
||||
|
||||
cfg.save(cfg_file);
|
||||
state_db.close();
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
ret = 2;
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
ret = 2;
|
||||
fmt::println("terminating application|{}", ret);
|
||||
}
|
||||
|
||||
fmt::println("terminating application|{}", ret);
|
||||
monitarr::project_cleanup();
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user