2019-09-08 16:42:10 +00:00
|
|
|
#include "okapi.h"
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
#include <iostream>
|
2019-11-05 19:39:33 +00:00
|
|
|
#include <iomanip>
|
|
|
|
#include <sstream>
|
2020-02-16 18:06:23 +00:00
|
|
|
#include <algorithm>
|
2019-09-08 16:42:10 +00:00
|
|
|
|
|
|
|
#include <curl/curl.h>
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
|
|
|
|
using json = nlohmann::json;
|
|
|
|
|
2023-08-30 14:40:12 +00:00
|
|
|
Okapi::Okapi(const Service serv) : service(serv) {
|
|
|
|
#include "config_user.h"
|
|
|
|
|
|
|
|
switch (serv) {
|
|
|
|
case ocpl:
|
|
|
|
url = ocpl_url;
|
|
|
|
key = ocpl_key;
|
|
|
|
break;
|
|
|
|
case ocde:
|
|
|
|
url = ocde_url;
|
|
|
|
key = ocde_key;
|
|
|
|
break;
|
|
|
|
case ocus:
|
|
|
|
url = ocus_url;
|
|
|
|
key = ocus_key;
|
|
|
|
break;
|
|
|
|
case ocnl:
|
|
|
|
url = ocnl_url;
|
|
|
|
key = ocnl_key;
|
|
|
|
break;
|
|
|
|
case ocro:
|
|
|
|
url = ocro_url;
|
|
|
|
key = ocro_key;
|
|
|
|
break;
|
|
|
|
case ocuk:
|
|
|
|
url = ocuk_url;
|
|
|
|
key = ocuk_key;
|
|
|
|
break;
|
|
|
|
case none:
|
|
|
|
throw 1;
|
|
|
|
}
|
2020-08-06 19:53:13 +00:00
|
|
|
|
|
|
|
curl = curl_easy_init();
|
|
|
|
if (!curl) {
|
|
|
|
curl_global_cleanup();
|
|
|
|
throw 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&curl_output);
|
|
|
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
Okapi::~Okapi() {
|
|
|
|
curl_easy_cleanup(curl);
|
2020-01-25 15:49:32 +00:00
|
|
|
}
|
|
|
|
|
2019-09-10 12:03:01 +00:00
|
|
|
// Callback for cURL easy interface used to save received output to std::string object
|
2019-10-06 00:58:24 +00:00
|
|
|
size_t Okapi::write_cb(char* ptr, __attribute__((unused)) size_t size, size_t nmemb, void* userdata) {
|
2019-09-08 16:42:10 +00:00
|
|
|
std::string* str = reinterpret_cast<std::string*>(userdata);
|
|
|
|
str->append(ptr, nmemb);
|
|
|
|
return nmemb;
|
|
|
|
}
|
|
|
|
|
2020-08-06 19:53:13 +00:00
|
|
|
void Okapi::curl_post(const std::string& url, const std::string& post) const {
|
2019-09-08 16:42:10 +00:00
|
|
|
CURLcode res;
|
|
|
|
|
|
|
|
Debug(5) << "API query: " << post;
|
|
|
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post.c_str());
|
2020-08-06 19:53:13 +00:00
|
|
|
curl_output.clear();
|
2019-09-08 16:42:10 +00:00
|
|
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
if (res != CURLE_OK) {
|
2020-03-21 03:00:19 +00:00
|
|
|
Debug(1) << "Connection failed: " << curl_easy_strerror(res) << '\n';
|
2019-09-08 16:42:10 +00:00
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2020-08-06 19:53:13 +00:00
|
|
|
Debug(5) << "API query result: " << curl_output;
|
|
|
|
if (curl_output.starts_with("{\"error\"")) {
|
|
|
|
json j = json::parse(curl_output);
|
2019-09-08 16:42:10 +00:00
|
|
|
Debug(1) << "OKAPI error: " << j["error"]["developer_message"];
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-06 19:53:13 +00:00
|
|
|
void Okapi::get_user_caches_json(const std::string& uuid, int count, int offset) const {
|
2022-07-13 16:31:01 +00:00
|
|
|
std::string api_service = url + OKAPI_logs;
|
2020-02-29 01:14:31 +00:00
|
|
|
std::string query = "consumer_key=" + key + "&user_uuid=" + uuid + "&fields=cache_code|type|date|was_recommended&limit=" + std::to_string(count) + "&offset=" + std::to_string(offset);
|
2022-07-13 16:31:01 +00:00
|
|
|
curl_post(api_service, query);
|
2019-09-08 16:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// std::string Okapi::get_cache_json(std::string code) {
|
|
|
|
// std::string service = url + OKAPI_cache;
|
|
|
|
// std::string query = "consumer_key=" + key + "&cache_code=" + code + "&fields=code|name|location|type|status|difficulty|terrain";
|
|
|
|
// return curl_post(service, query);
|
|
|
|
// }
|
|
|
|
|
2020-08-06 19:53:13 +00:00
|
|
|
void Okapi::get_caches_json(const std::string& codes) const {
|
2022-07-13 16:31:01 +00:00
|
|
|
std::string api_service = url + OKAPI_caches;
|
2023-08-31 21:19:58 +00:00
|
|
|
std::string query = "consumer_key=" + key + "&cache_codes=" + codes + "&fields=code|name|location|type|status|difficulty|terrain|owner|region|country2|size2|date_hidden|date_created|recommendations|rating|founds|status|internal_id";
|
2022-07-13 16:31:01 +00:00
|
|
|
curl_post(api_service, query);
|
2019-09-08 16:42:10 +00:00
|
|
|
}
|
|
|
|
|
2023-08-30 20:43:49 +00:00
|
|
|
// void Okapi::get_caches_ratings_json(const std::string& codes) const {
|
|
|
|
// std::string api_service = url + OKAPI_caches;
|
|
|
|
// std::string query = "consumer_key=" + key + "&cache_codes=" + codes + "&fields=code|recommendations|rating|status";
|
|
|
|
// curl_post(api_service, query);
|
|
|
|
// }
|
2020-08-28 16:42:54 +00:00
|
|
|
|
2019-09-08 16:42:10 +00:00
|
|
|
// Cache Okapi::get_cache(std::string code) {
|
|
|
|
// std::string output = get_cache_json(code);
|
|
|
|
// json j = json::parse(output);
|
|
|
|
//
|
|
|
|
// Cache c;
|
|
|
|
// c.code = code;
|
|
|
|
// c.name = j["name"];
|
|
|
|
// c.type = j["type"];
|
|
|
|
// c.diff = j["difficulty"].get<float>();
|
|
|
|
// c.terr = j["terrain"].get<float>();
|
|
|
|
// // std::cout << j["difficulty"] << '\n';
|
|
|
|
// // std::cout << j["difficulty"].get<float>() << '\n';
|
|
|
|
// // std::cout << j["difficulty"].get<double>() << '\n';
|
|
|
|
// // std::cout << j["difficulty"].get<int>() << '\n';
|
|
|
|
//
|
|
|
|
// std::string loc = j["location"];
|
|
|
|
// int pos = loc.find("|");
|
2019-10-03 22:23:03 +00:00
|
|
|
// //c.pos.lat = stof(loc.substr(0, pos));
|
|
|
|
// //c.pos.lon = stof(loc.substr(pos + 1));
|
2019-09-08 16:42:10 +00:00
|
|
|
//
|
|
|
|
// return c;
|
|
|
|
// }
|
|
|
|
|
2020-02-29 22:05:11 +00:00
|
|
|
Caches Okapi::get_caches(const std::set<std::string>& codes) const {
|
2019-09-08 16:42:10 +00:00
|
|
|
Cache c;
|
2019-11-05 19:39:33 +00:00
|
|
|
Caches cc;
|
2019-09-08 16:42:10 +00:00
|
|
|
|
2020-02-11 16:34:23 +00:00
|
|
|
uint k;
|
2020-01-28 03:49:11 +00:00
|
|
|
std::string codes_list;
|
2020-02-29 22:20:03 +00:00
|
|
|
codes_list.reserve(MAX_CACHES * 8); // maximum of MAX_CACHES codes, 7 chars per code plus a separator
|
2020-01-28 03:49:11 +00:00
|
|
|
|
|
|
|
auto it = codes.begin();
|
|
|
|
while (it != codes.end()) {
|
2019-11-10 13:59:31 +00:00
|
|
|
k = 0;
|
|
|
|
|
2020-02-29 01:18:01 +00:00
|
|
|
while (it != codes.end() && k < MAX_CACHES) {
|
2020-02-29 01:04:55 +00:00
|
|
|
codes_list += *it;
|
2019-09-08 16:42:10 +00:00
|
|
|
codes_list += '|';
|
2020-01-28 03:49:11 +00:00
|
|
|
it++;
|
2019-11-10 13:59:31 +00:00
|
|
|
k++;
|
2019-09-08 16:42:10 +00:00
|
|
|
}
|
|
|
|
codes_list.pop_back(); // remove trailing '|'
|
|
|
|
|
2020-08-06 19:53:13 +00:00
|
|
|
get_caches_json(codes_list);
|
|
|
|
json j = json::parse(curl_output);
|
2020-01-28 03:49:11 +00:00
|
|
|
codes_list.clear();
|
2019-09-08 16:42:10 +00:00
|
|
|
|
|
|
|
for (auto& el : j.items()) {
|
2021-01-03 03:52:34 +00:00
|
|
|
if (el.value().is_null()) continue;
|
2019-09-08 16:42:10 +00:00
|
|
|
c.code = el.value()["code"];
|
2022-07-13 19:22:11 +00:00
|
|
|
if (el.value()["internal_id"].is_number())
|
|
|
|
c.internal_id = el.value()["internal_id"];
|
|
|
|
else
|
|
|
|
c.internal_id = std::stoi(el.value()["internal_id"].get<std::string>());
|
2019-09-08 16:42:10 +00:00
|
|
|
c.name = el.value()["name"];
|
|
|
|
c.type = el.value()["type"];
|
2019-11-08 21:50:21 +00:00
|
|
|
c.size = el.value()["size2"];
|
2019-09-12 11:58:54 +00:00
|
|
|
c.region = el.value()["region"];
|
2021-09-05 17:44:44 +00:00
|
|
|
c.country = el.value()["country2"];
|
2019-09-08 16:42:10 +00:00
|
|
|
c.diff = el.value()["difficulty"];
|
|
|
|
c.terr = el.value()["terrain"];
|
2019-09-11 17:48:03 +00:00
|
|
|
c.owner = el.value()["owner"]["username"];
|
|
|
|
c.owner_uuid = el.value()["owner"]["uuid"];
|
2022-05-16 19:11:43 +00:00
|
|
|
c.pos = Position(el.value()["location"].get<std::string>());
|
2020-01-25 15:49:32 +00:00
|
|
|
c.origin = service;
|
2020-01-25 15:12:29 +00:00
|
|
|
c.fav = el.value()["recommendations"];
|
2020-08-28 15:38:28 +00:00
|
|
|
if (!el.value()["rating"].is_null()) c.rating = el.value()["rating"];
|
2020-01-25 15:12:29 +00:00
|
|
|
c.founds = el.value()["founds"];
|
2020-01-25 14:26:14 +00:00
|
|
|
|
2020-03-06 09:55:57 +00:00
|
|
|
if (el.value()["status"] == "Available")
|
|
|
|
c.status = ok;
|
|
|
|
else if (el.value()["status"] == "Temporarily unavailable")
|
|
|
|
c.status = disabled;
|
|
|
|
else if (el.value()["status"] == "Archived")
|
|
|
|
c.status = archived;
|
|
|
|
else
|
|
|
|
c.status = unknown;
|
|
|
|
|
2020-01-25 14:26:14 +00:00
|
|
|
std::tm tmp;
|
2023-08-31 21:19:58 +00:00
|
|
|
std::stringstream ss(std::max(el.value()["date_hidden"].get<std::string>(), el.value()["date_created"].get<std::string>()));
|
2020-01-25 14:26:14 +00:00
|
|
|
ss >> std::get_time(&tmp, "%Y-%m-%dT%H:%M:%S+");
|
2023-08-30 13:10:54 +00:00
|
|
|
tmp.tm_isdst = -1;
|
2020-01-25 14:26:14 +00:00
|
|
|
c.set_date_hidden(tmp);
|
|
|
|
|
2020-02-29 01:04:55 +00:00
|
|
|
cc.push_back(c);
|
2019-09-08 16:42:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return cc;
|
|
|
|
}
|
|
|
|
|
2020-02-11 16:34:23 +00:00
|
|
|
Caches Okapi::get_user_caches(const std::string& uuid, int count) const {
|
2019-09-08 16:42:10 +00:00
|
|
|
Caches cc;
|
2020-02-29 22:05:11 +00:00
|
|
|
std::set<std::string> codes;
|
2020-02-29 01:04:55 +00:00
|
|
|
|
|
|
|
struct extra_data {
|
|
|
|
std::tm date;
|
2020-02-29 01:14:31 +00:00
|
|
|
bool was_recommended;
|
2020-02-29 01:04:55 +00:00
|
|
|
};
|
|
|
|
std::map<std::string, extra_data> tmp_data; // holds data from logs which needs to be added to Caches later
|
|
|
|
|
2019-09-08 16:42:10 +00:00
|
|
|
json j;
|
2019-11-05 19:39:33 +00:00
|
|
|
std::tm date;
|
2019-09-08 16:42:10 +00:00
|
|
|
int off = 0;
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
do {
|
2020-08-06 19:53:13 +00:00
|
|
|
get_user_caches_json(uuid, MAX_LOGS, off);
|
|
|
|
j = json::parse(curl_output);
|
2019-09-08 16:42:10 +00:00
|
|
|
|
|
|
|
for (auto& el : j.items()) {
|
2023-08-31 20:13:21 +00:00
|
|
|
if (el.value()["type"] == "Found it" || el.value()["type"] == "Attended") {
|
2019-11-05 19:39:33 +00:00
|
|
|
std::stringstream ss(el.value()["date"].get<std::string>());
|
2019-11-10 13:59:31 +00:00
|
|
|
// TODO need to take care of the time zone :/
|
|
|
|
ss >> std::get_time(&date, "%Y-%m-%dT%H:%M:%S+");
|
2023-08-30 13:10:54 +00:00
|
|
|
date.tm_isdst = -1;
|
2020-02-29 22:05:11 +00:00
|
|
|
codes.insert(el.value()["cache_code"].get<std::string>());
|
2020-02-29 01:14:31 +00:00
|
|
|
tmp_data[el.value()["cache_code"].get<std::string>()] = { date, el.value()["was_recommended"] };
|
2019-09-08 16:42:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
off += j.size();
|
|
|
|
} while (j.size() > 0);
|
|
|
|
else {
|
2020-02-29 01:18:01 +00:00
|
|
|
int count_req = (count > MAX_LOGS) ? MAX_LOGS : count;
|
2019-09-08 16:42:10 +00:00
|
|
|
do {
|
2020-08-06 19:53:13 +00:00
|
|
|
get_user_caches_json(uuid, count_req, off);
|
|
|
|
j = json::parse(curl_output);
|
2019-09-08 16:42:10 +00:00
|
|
|
|
|
|
|
for (auto& el : j.items()) {
|
2023-08-31 20:13:21 +00:00
|
|
|
if (el.value()["type"] == "Found it" || el.value()["type"] == "Attended") {
|
2019-11-05 19:39:33 +00:00
|
|
|
std::stringstream ss(el.value()["date"].get<std::string>());
|
|
|
|
ss >> std::get_time(&date, "%Y-%m-%dT%H-%M-%S");
|
2023-08-30 13:10:54 +00:00
|
|
|
date.tm_isdst = -1;
|
2020-02-29 22:05:11 +00:00
|
|
|
codes.insert(el.value()["cache_code"].get<std::string>());
|
2020-02-29 01:14:31 +00:00
|
|
|
tmp_data[el.value()["cache_code"].get<std::string>()] = { date, el.value()["was_recommended"] };
|
2019-09-08 16:42:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
off += j.size();
|
|
|
|
count -= count_req;
|
|
|
|
} while (j.size() > 0 && count > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
cc = get_caches(codes);
|
|
|
|
Debug(2) << "Caches read from OC: " << cc.size() << '\n';
|
2020-02-29 01:04:55 +00:00
|
|
|
std::map<std::string, Cache&> mcc;
|
|
|
|
for (auto& i : cc)
|
2020-08-06 21:58:14 +00:00
|
|
|
mcc.insert({ i.code, i });
|
2020-02-29 01:04:55 +00:00
|
|
|
|
2020-08-06 21:58:14 +00:00
|
|
|
// introduce extra data from the logs to Caches
|
2022-09-01 15:23:29 +00:00
|
|
|
for (const auto& el : tmp_data) {
|
2020-02-29 01:04:55 +00:00
|
|
|
auto& it = mcc.at(el.first);
|
|
|
|
it.set_date(el.second.date);
|
2020-02-29 01:14:31 +00:00
|
|
|
it.recommended = el.second.was_recommended;
|
2020-02-29 01:04:55 +00:00
|
|
|
}
|
|
|
|
|
2019-09-08 16:42:10 +00:00
|
|
|
return cc;
|
|
|
|
}
|
|
|
|
|
2023-08-30 14:40:12 +00:00
|
|
|
int Okapi::get_user_hidden_caches_no(const std::string& uuid) const {
|
2022-07-13 16:31:01 +00:00
|
|
|
std::string api_service = url + OKAPI_user;
|
2020-10-31 20:51:25 +00:00
|
|
|
std::string query = "consumer_key=" + key + "&user_uuid=" + uuid + "&fields=caches_hidden";
|
2022-07-13 16:31:01 +00:00
|
|
|
curl_post(api_service, query);
|
2020-10-31 20:51:25 +00:00
|
|
|
json j = json::parse(curl_output);
|
|
|
|
return j["caches_hidden"];
|
|
|
|
}
|
|
|
|
|
2020-08-05 00:26:40 +00:00
|
|
|
void Okapi::update_caches(Caches& cc) const {
|
|
|
|
std::set<std::string> codes;
|
|
|
|
for (auto& i : cc)
|
|
|
|
codes.insert(i.code);
|
|
|
|
cc = get_caches(codes);
|
|
|
|
}
|
|
|
|
|
2022-07-13 16:31:01 +00:00
|
|
|
// void Okapi::update_caches_ratings(Caches& cc) const {
|
|
|
|
// std::map<std::string, Cache*> pcc;
|
|
|
|
// std::string code;
|
2023-09-25 16:49:30 +00:00
|
|
|
//
|
2022-07-13 16:31:01 +00:00
|
|
|
// uint k;
|
|
|
|
// std::string codes_list;
|
|
|
|
// codes_list.reserve(MAX_CACHES * 8); // maximum of MAX_CACHES codes, 7 chars per code plus a separator
|
2023-09-25 16:49:30 +00:00
|
|
|
//
|
2022-07-13 16:31:01 +00:00
|
|
|
// auto it = cc.begin();
|
|
|
|
// while (it != cc.end()) {
|
|
|
|
// k = 0;
|
2023-09-25 16:49:30 +00:00
|
|
|
//
|
2022-07-13 16:31:01 +00:00
|
|
|
// while (it != cc.end() && k < MAX_CACHES) {
|
|
|
|
// codes_list += it->code;
|
|
|
|
// codes_list += '|';
|
|
|
|
// pcc[it->code] = &*it;
|
|
|
|
// it++;
|
|
|
|
// k++;
|
|
|
|
// }
|
|
|
|
// codes_list.pop_back(); // remove trailing '|'
|
2023-09-25 16:49:30 +00:00
|
|
|
//
|
2022-07-13 16:31:01 +00:00
|
|
|
// get_caches_ratings_json(codes_list);
|
|
|
|
// json j = json::parse(curl_output);
|
|
|
|
// codes_list.clear();
|
2023-09-25 16:49:30 +00:00
|
|
|
//
|
2022-07-13 16:31:01 +00:00
|
|
|
// for (auto& el : j.items()) {
|
|
|
|
// code = el.value()["code"];
|
|
|
|
// pcc[code]->fav = el.value()["recommendations"];
|
|
|
|
// if (!el.value()["rating"].is_null()) pcc[code]->rating = el.value()["rating"];
|
2023-09-25 16:49:30 +00:00
|
|
|
//
|
2022-07-13 16:31:01 +00:00
|
|
|
// if (el.value()["status"] == "Available")
|
|
|
|
// pcc[code]->status = ok;
|
|
|
|
// else if (el.value()["status"] == "Temporarily unavailable")
|
|
|
|
// pcc[code]->status = disabled;
|
|
|
|
// else if (el.value()["status"] == "Archived")
|
|
|
|
// pcc[code]->status = archived;
|
|
|
|
// else
|
|
|
|
// pcc[code]->status = unknown;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
2020-08-28 16:42:54 +00:00
|
|
|
|
2022-07-13 16:30:26 +00:00
|
|
|
std::string Okapi::get_uuid(const std::string& username, uint* id) const {
|
2022-07-13 16:31:01 +00:00
|
|
|
std::string api_service = url + OKAPI_username;
|
2020-08-06 21:58:14 +00:00
|
|
|
char* user_esc = curl_easy_escape(curl, username.c_str(), username.size());
|
2022-07-12 23:11:44 +00:00
|
|
|
std::string query = "consumer_key=" + key + "&username=" + user_esc + "&fields=uuid|internal_id";
|
2020-08-06 19:53:27 +00:00
|
|
|
curl_free(user_esc);
|
2022-07-13 16:31:01 +00:00
|
|
|
curl_post(api_service, query);
|
2020-08-06 19:53:13 +00:00
|
|
|
json j = json::parse(curl_output);
|
2022-07-12 23:11:44 +00:00
|
|
|
if (id) *id = j["internal_id"];
|
2019-09-08 16:42:10 +00:00
|
|
|
return j["uuid"];
|
|
|
|
}
|
2019-09-30 23:49:25 +00:00
|
|
|
|
2020-02-11 16:34:23 +00:00
|
|
|
std::string Okapi::get_profile_url(const std::string& uuid) const {
|
2022-07-13 16:31:01 +00:00
|
|
|
std::string api_service = url + OKAPI_user;
|
2020-01-04 18:24:00 +00:00
|
|
|
std::string query = "consumer_key=" + key + "&user_uuid=" + uuid + "&fields=profile_url";
|
2022-07-13 16:31:01 +00:00
|
|
|
curl_post(api_service, query);
|
2020-08-06 19:53:13 +00:00
|
|
|
json j = json::parse(curl_output);
|
2020-01-04 18:24:00 +00:00
|
|
|
return j["profile_url"];
|
|
|
|
}
|
|
|
|
|
2020-02-11 16:34:23 +00:00
|
|
|
std::string Okapi::get_changelog_json(int revision) const {
|
2022-07-13 16:31:01 +00:00
|
|
|
std::string api_service = url + OKAPI_changelog;
|
2019-09-30 23:49:25 +00:00
|
|
|
std::string query = "consumer_key=" + key + "&since=" + std::to_string(revision);
|
2022-07-13 16:31:01 +00:00
|
|
|
curl_post(api_service, query);
|
2020-08-06 19:53:13 +00:00
|
|
|
return curl_output;
|
2019-09-30 23:49:25 +00:00
|
|
|
}
|
2022-07-12 23:11:44 +00:00
|
|
|
|
2022-07-13 16:30:26 +00:00
|
|
|
void Okapi::get_ftf(uint uid, Caches& cc) const {
|
2023-08-30 20:43:49 +00:00
|
|
|
std::string ftf_url = "https://opencaching.pl/UserProfile/getUserFtfsAjax/" + std::to_string(uid);
|
2022-07-12 23:11:44 +00:00
|
|
|
CURLcode res;
|
|
|
|
|
2023-08-30 20:43:49 +00:00
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, ftf_url.c_str());
|
2022-07-12 23:11:44 +00:00
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
|
|
|
|
curl_output.clear();
|
|
|
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
if (res != CURLE_OK) {
|
|
|
|
Debug(1) << "Connection failed: " << curl_easy_strerror(res) << '\n';
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
Debug(5) << "FTF query result: " << curl_output;
|
|
|
|
json j = json::parse(curl_output);
|
|
|
|
for (auto& el : j.items()) {
|
|
|
|
if (el.value().is_null()) continue;
|
2022-09-30 19:29:08 +00:00
|
|
|
uint id = el.value()["cache_id"];
|
2022-07-13 16:31:01 +00:00
|
|
|
auto c = std::find_if(cc.begin(), cc.end(), [&](const auto& a) { return a.internal_id == id; });
|
|
|
|
if (c != std::end(cc))
|
|
|
|
c->ftf = 1;
|
2022-07-12 23:11:44 +00:00
|
|
|
}
|
|
|
|
}
|