#include "powertrail.h" #include "debug.h" #include "common.h" #include #include #include #include #include using json = nlohmann::json; static const std::string url = "https://opencaching.pl/powerTrail.php?ptAction=showSerie&ptrail="; static const std::string url2 = "https://opencaching.pl/powerTrail/ajaxGetPowerTrailCaches.php?ptAction=showSerie&ptrail="; static const std::regex regex_name("(.*?)"); static const std::regex regex_type("(.*?)"); static const std::regex regex_date("(.*?)"); static const std::regex regex_perc("(.*?)"); static const std::regex regex_cache(".*?" + safe_name() + ""; } std::string Powertrail::safe_name() const { std::string tmp = name; htmlencode(tmp); return tmp; } std::string Powertrail::get_type() const { return types[type]; } PowertrailDB::PowertrailDB() { curl = curl_easy_init(); if (!curl) { curl_global_cleanup(); throw 0; } curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&curl_output); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5); } PowertrailDB::~PowertrailDB() { curl_easy_cleanup(curl); } void PowertrailDB::get_trail(uint n) { CURLcode curl_res; std::smatch res; Powertrail T; T.number = n; curl_output.clear(); curl_easy_setopt(curl, CURLOPT_URL, (url + std::to_string(n)).c_str()); curl_res = curl_easy_perform(curl); if (curl_res != CURLE_OK) { Debug(1) << "Connection failed: " << curl_easy_strerror(curl_res) << '\n'; curl_easy_cleanup(curl); std::exit(EXIT_FAILURE); } if (std::regex_search(curl_output, res, regex_name) && res.size() == 2) { T.name = res[1].str(); if (T.name.empty()) return; Debug(2) << "Read name: " << T.name; } else return; if (std::regex_search(curl_output, res, regex_type) && res.size() == 2) { if (res[1].str() == "Geo-szkic") T.type = geoszkic; else if (res[1].str() == "Krajoznawcza") T.type = krajoznawcza; else if (res[1].str() == "Przyrodnicza") T.type = przyrodnicza; else if (res[1].str() == "Tematyczna") T.type = tematyczna; else T.type = unknown_type; } if (std::regex_search(curl_output, res, regex_date) && res.size() == 2) { strptime(res[1].str().c_str(), "%d-%m-%Y", &T.date); T.date_str = res[1].str(); Debug(2) << "Read time: " << T.date_str; } if (std::regex_search(curl_output, res, regex_perc) && res.size() == 2) { T.treshold_perc = std::stoi(res[1].str()); Debug(2) << "Read percent: " << T.treshold_perc; } curl_output.clear(); curl_easy_setopt(curl, CURLOPT_URL, (url2 + std::to_string(n)).c_str()); curl_res = curl_easy_perform(curl); if (curl_res != CURLE_OK) { Debug(1) << "Connection failed: " << curl_easy_strerror(curl_res) << '\n'; curl_easy_cleanup(curl); std::exit(EXIT_FAILURE); } auto caches_begin = std::sregex_iterator(curl_output.begin(), curl_output.end(), regex_cache); auto caches_end = std::sregex_iterator(); Debug(2) << "Found " << std::distance(caches_begin, caches_end) << " caches.\n"; for (std::sregex_iterator i = caches_begin; i != caches_end; i++) { std::smatch match = *i; T.caches.insert(match[1].str()); if (match[2].str() == "16x16-published") T.active_caches++; } T.treshold = (T.caches.size() * T.treshold_perc + 99) / 100; // Integer division rounding up data.insert({ n, T }); } // Callback for cURL easy interface used to save received output to std::string object size_t PowertrailDB::write_cb(char* ptr, __attribute__((unused)) size_t size, size_t nmemb, void* userdata) { std::string* str = reinterpret_cast(userdata); str->append(ptr, nmemb); return nmemb; } void PowertrailDB::read_from_json(std::string file) { std::ifstream datafile(file); try { json j; datafile >> j; data = j.get>(); } catch (...) { Debug(1) << "Cache file: " << file << " corrupted."; std::exit(EXIT_FAILURE); } for (auto& p : data) p.second.number = p.first; }; void PowertrailDB::save_to_json(std::string file) { std::ofstream datafile(file); json j(data); datafile << j; }; Caches_in_Powertrails::Caches_in_Powertrails(const PowertrailDB& db) { for (auto& t : db.data) { for (auto& c : t.second.caches) { data.insert({ c, t.second.number }); } } } void Caches_in_Powertrails::read_from_json(std::string file) { std::ifstream datafile(file); try { json j; datafile >> j; data = j.get>(); } catch (...) { Debug(1) << "Cache file: " << file << " corrupted."; std::exit(EXIT_FAILURE); } }; void Caches_in_Powertrails::save_to_json(std::string file) { std::ofstream datafile(file); json j(data); datafile << j; };