/* This file is part of FediBlock-backend. * Copyright © 2020 tastytea * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #include "gitea.hpp" #include "config.hpp" #include "files.hpp" #include "json.hpp" #include "types.hpp" #include #include #include #include #include #include namespace FediBlock::gitea { using fmt::format; using std::runtime_error; using std::string; using std::string_view; using std::to_string; CURL *_connection; string _curl_buffer_body; uint64_t _last_pr_number{0}; void init() { _connection = curl_easy_init(); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) CURLcode code{curl_easy_setopt(_connection, CURLOPT_FOLLOWLOCATION, 1L)}; if (code != CURLE_OK) { throw runtime_error{"HTTP is not supported."}; } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) curl_easy_setopt(_connection, CURLOPT_MAXREDIRS, 5L); // Add extra headers. struct curl_slist *headers{nullptr}; string authheader{"Authorization: token " + files::get_access_token()}; headers = curl_slist_append(headers, authheader.c_str()); headers = curl_slist_append(headers, "Accept: application/json"); headers = curl_slist_append(headers, "Content-Type: application/json"); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) code = curl_easy_setopt(_connection, CURLOPT_HTTPHEADER, headers); if (code != CURLE_OK) { throw runtime_error{"Could not add headers"}; } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) curl_easy_setopt(_connection, CURLOPT_WRITEFUNCTION, writer_body); } void cleanup() { curl_easy_cleanup(gitea::_connection); } size_t writer_body(char *data, size_t size, size_t nmemb) { if (data == nullptr) { return 0; } _curl_buffer_body.append(data, size * nmemb); return size * nmemb; } string api_request(const http_method method, const string_view path, const string_view body) { CURLcode code{}; string url{format("https://{:s}{:s}", config::forge_domain, path)}; _curl_buffer_body.clear(); switch (method) { case http_method::GET: { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) curl_easy_setopt(_connection, CURLOPT_HTTPGET, 1L); url += body; break; } case http_method::POST: { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) curl_easy_setopt(_connection, CURLOPT_POSTFIELDSIZE, body.size()); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) code = curl_easy_setopt(_connection, CURLOPT_POSTFIELDS, body.data()); if (code != CURLE_OK) { throw runtime_error{"Couldn't set up data to send"}; } break; } } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) code = curl_easy_setopt(_connection, CURLOPT_URL, url.c_str()); if (code != CURLE_OK) { throw runtime_error{format("Couldn't set URL: {:d}", code)}; } code = curl_easy_perform(_connection); if (code != CURLE_OK) { throw runtime_error{format("libcurl error: {:d}", code)}; } long http_status{0}; // NOLINT(google-runtime-int) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) curl_easy_getinfo(_connection, CURLINFO_RESPONSE_CODE, &http_status); if (http_status < 200 || http_status >= 300) { throw runtime_error{format("HTTP error: {:d}", http_status)}; } return _curl_buffer_body; } void pull_request(const string_view branch, const entry_type &entry) { api_request(http_method::POST, format("/api/v1/repos/{:s}/{:s}/pulls", config::forge_org, config::forge_repo_data), json::pull_request_body(branch, entry)); ++_last_pr_number; } uint64_t get_last_pr_number() { if (_last_pr_number == 0) { const auto answer{ api_request(http_method::GET, format("/api/v1/repos/{:s}/{:s}/pulls", config::forge_org, config::forge_repo_data), "?sort=newest&limit=1")}; if (answer == "[]") { return 0; } const auto json{nlohmann::json::parse(answer)}; _last_pr_number = json.front().front()["number"].get(); } return _last_pr_number; } } // namespace FediBlock::gitea