| 38 | void GitHubFileListProvider::set_root_path(const std::wstring &root_path) { m_root_path = root_path; } |
| 39 | |
| 40 | void GitHubFileListProvider::update_file_list() { |
| 41 | constexpr auto default_timeout = 3000; |
| 42 | std::wstring proxy_string; |
| 43 | if (m_settings.data.use_proxy && m_settings.data.proxy_type == ProxyType::web_proxy) |
| 44 | proxy_string = m_settings.data.proxy_host_name + L":" + std::to_wstring(m_settings.data.proxy_port); |
| 45 | using task_result_t = std::variant<std::monostate, std::vector<FileDescription>, std::string /*error*/>; |
| 46 | // TODO: possibly separate settings required for proxy connection to a struct to pass them instead of whole settings |
| 47 | auto task = [root_path = m_root_path, proxy_string, default_timeout, settings_data = m_settings.data |
| 48 | ](Concurrency::cancellation_token token) -> task_result_t { |
| 49 | try { |
| 50 | auto inet = create_global_handle(settings_data); |
| 51 | const auto url_to_json = [&](const std::wstring &path) { |
| 52 | auto url_handle = create_url_handle(settings_data, inet, path.c_str()); |
| 53 | const auto text = WinInet::download_text_file(url_handle); |
| 54 | return nlohmann::json::parse(text); |
| 55 | }; |
| 56 | |
| 57 | auto rate_limit_data = url_to_json(L"https://api.github.com/rate_limit"); |
| 58 | auto core_limit_data = rate_limit_data["resources"]["core"]; |
| 59 | if (core_limit_data["remaining"] == 0) { |
| 60 | auto reset_secs = core_limit_data["reset"].get<time_t>(); |
| 61 | std::wstringstream wss; |
| 62 | wss << std::put_time(std::localtime(&reset_secs), L"%H:%M"); |
| 63 | return to_string(wstring_printf(rc_str(IDS_GITHUB_API_RATE_LIMIT_EXCEEDED_PD_PS).c_str(), core_limit_data["limit"].get<int>(), |
| 64 | wss.str().c_str())); |
| 65 | } |
| 66 | nlohmann::json nodes; |
| 67 | std::wstring download_url; |
| 68 | for (auto branch_name : {L"master", L"main"}) { |
| 69 | download_url = UrlHelpers::github_file_url_to_download_url(root_path, branch_name); |
| 70 | nodes = url_to_json(UrlHelpers::github_url_to_api_recursive_tree_url(root_path, branch_name))["tree"]; |
| 71 | if (!nodes.empty()) |
| 72 | break; |
| 73 | } |
| 74 | std::vector<FileDescription> result; |
| 75 | for (auto &node : nodes) { |
| 76 | if (token.is_canceled()) |
| 77 | return {}; |
| 78 | if (!node.is_object() || node["type"] != "blob") |
| 79 | continue; |
| 80 | std::string path = node["path"]; |
| 81 | if (!ends_with(path, aff_ext)) |
| 82 | continue; |
| 83 | |
| 84 | auto dic_name = path.substr(0, path.length() - 4) + dic_ext.data(); |
| 85 | if (std::find_if(nodes.begin(), nodes.end(), [&](const auto &f) { return f["path"] == dic_name; }) == nodes.end()) |
| 86 | continue; |
| 87 | auto start_pos = path.rfind('/') + 1; |
| 88 | result.push_back({utf8_to_wstring(path.substr(start_pos, path.length() - start_pos - aff_ext.length()).c_str()), |
| 89 | download_url + utf8_to_wstring(node["path"].get<std::string>().c_str())}); |
| 90 | } |
| 91 | return result; |
| 92 | } catch (const std::exception &exception) { |
| 93 | return exception.what(); |
| 94 | } |
| 95 | }; |
| 96 | m_get_file_list_task.do_deferred(task, [this](task_result_t &&result) { |
| 97 | std::visit(overload([](std::monostate) { |
no test coverage detected