diff --git a/README.md b/README.md index 044f153..3500285 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ python main.py ```shell cd bot_microservice - poetry run uvicorn --factory --host 0.0.0.0 --port 8080 --reload --workers 2 --log-level warning + poetry run uvicorn main:create_app --factory --host 0.0.0.0 --port 8080 --forwarded-allow-ips='*' --proxy-headers --reload --workers 2 --log-level warning ``` To start on polling mode set `START_WITH_WEBHOOK` to blank diff --git a/chatgpt_microservice/src/free_gpt.cpp b/chatgpt_microservice/src/free_gpt.cpp index 07ef464..286fe0a 100644 --- a/chatgpt_microservice/src/free_gpt.cpp +++ b/chatgpt_microservice/src/free_gpt.cpp @@ -1648,97 +1648,59 @@ boost::asio::awaitable FreeGpt::freeGpt(std::shared_ptr ch, nlohm ScopeExit _exit{[=] { boost::asio::post(ch->get_executor(), [=] { ch->close(); }); }}; auto prompt = json.at("meta").at("content").at("parts").at(0).at("content").get(); - CURLcode res; - CURL* curl = curl_easy_init(); - if (!curl) { - auto error_info = std::format("curl_easy_init() failed:{}", curl_easy_strerror(res)); + Curl curl; + auto ret = curl.setUrl("https://r.aifree.site/api/generate") + .setProxy(m_cfg.http_proxy) + .setRecvBodyCallback([&](std::string str) mutable { + boost::asio::post(ch->get_executor(), [=, str = std::move(str)] { ch->try_send(err, str); }); + return; + }) + .setBody([&] { + auto generate_signature = [](int timestamp, const std::string& message, + const std::string& secret = "") { + std::stringstream ss; + ss << timestamp << ":" << message << ":" << secret; + std::string data = ss.str(); + + unsigned char digest[SHA256_DIGEST_LENGTH]; + SHA256(reinterpret_cast(data.c_str()), data.length(), digest); + + std::stringstream sha_stream; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + sha_stream << std::setfill('0') << std::setw(2) << std::hex + << static_cast(digest[i]); + } + return sha_stream.str(); + }; + uint64_t timestamp = getTimestamp(); + std::string signature = generate_signature(timestamp, prompt); + + constexpr std::string_view request_str{R"({ + "messages":[ + { + "role":"user", + "content":"hello" + } + ], + "pass":null, + "sign":"7c2700b5813053ff8000cb9fb1ebdadbfcf62882829da59e4474bee466de7c89", + "time":1695716667 + })"}; + nlohmann::json request = nlohmann::json::parse(request_str, nullptr, false); + + request["sign"] = signature; + request["time"] = timestamp; + request["messages"] = getConversationJson(json); + + auto str = request.dump(); + SPDLOG_INFO("request : [{}]", str); + return str; + }()) + .perform(); + if (ret.has_value()) { + SPDLOG_ERROR("https://r.aifree.site/api/generate: [{}]", ret.value()); co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable)); - ch->try_send(err, error_info); - co_return; - } - curl_easy_setopt(curl, CURLOPT_URL, "https://k.aifree.site/api/generate"); - if (!m_cfg.http_proxy.empty()) - curl_easy_setopt(curl, CURLOPT_PROXY, m_cfg.http_proxy.c_str()); - - struct Input { - std::shared_ptr ch; - std::string recv; - }; - Input input{ch}; - auto action_cb = [](void* contents, size_t size, size_t nmemb, void* userp) -> size_t { - boost::system::error_code err{}; - auto input_ptr = static_cast(userp); - std::string data{(char*)contents, size * nmemb}; - auto& [ch, recv] = *input_ptr; - boost::asio::post(ch->get_executor(), [=] { ch->try_send(err, data); }); - return size * nmemb; - }; - size_t (*action_fn)(void* contents, size_t size, size_t nmemb, void* userp) = action_cb; - curlEasySetopt(curl); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, action_fn); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &input); - - auto generate_signature = [](int timestamp, const std::string& message, const std::string& secret = "") { - std::stringstream ss; - ss << timestamp << ":" << message << ":" << secret; - std::string data = ss.str(); - - unsigned char digest[SHA256_DIGEST_LENGTH]; - SHA256(reinterpret_cast(data.c_str()), data.length(), digest); - - std::stringstream sha_stream; - for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { - sha_stream << std::setfill('0') << std::setw(2) << std::hex << static_cast(digest[i]); - } - return sha_stream.str(); - }; - uint64_t timestamp = getTimestamp(); - std::string signature = generate_signature(timestamp, prompt); - - constexpr std::string_view request_str{R"({ - "messages":[ - { - "role":"user", - "content":"hello" - } - ], - "pass":null, - "sign":"7c2700b5813053ff8000cb9fb1ebdadbfcf62882829da59e4474bee466de7c89", - "time":1695716667 - })"}; - nlohmann::json request = nlohmann::json::parse(request_str, nullptr, false); - - request["sign"] = signature; - request["time"] = timestamp; - request["messages"] = getConversationJson(json); - - auto str = request.dump(); - SPDLOG_INFO("request : [{}]", str); - - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, str.c_str()); - - struct curl_slist* headers = nullptr; - headers = curl_slist_append(headers, "Content-Type: application/json"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - - ScopeExit auto_exit{[=] { - curl_slist_free_all(headers); - curl_easy_cleanup(curl); - }}; - - res = curl_easy_perform(curl); - - if (res != CURLE_OK) { - co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable)); - auto error_info = std::format("curl_easy_perform() failed:{}", curl_easy_strerror(res)); - ch->try_send(err, error_info); - co_return; - } - int32_t response_code; - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); - if (response_code != 200) { - co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable)); - ch->try_send(err, std::format("you http code:{}", response_code)); + ch->try_send(err, ret.value()); co_return; } co_return;