Update provider ChatForAi && GptForLove (#39)

* Update provider ChatForAi && GptForLove

* update chatg gpt README
This commit is contained in:
Dmitry Afanasyev 2023-10-15 12:02:49 +03:00 committed by GitHub
parent 4c3c6039e3
commit a273a89ba0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 274 additions and 444 deletions

View File

@ -64,15 +64,15 @@ docker pull fantasypeak/freegpt:latest
Run the application using Docker:
```
docker run -p 8858:8858 -it --name freegpt fantasypeak/freegpt:latest
docker run --rm -p 8858:8858 -it --name freegpt fantasypeak/freegpt:latest
// OR
docker run --net=host -it --name freegpt fantasypeak/freegpt:latest
docker run --rm --net=host -it --name freegpt fantasypeak/freegpt:latest
// use http_proxy
docker run -p 8858:8858 -it --name freegpt -e HTTP_PROXY=http://127.0.0.1:8080 -e CHAT_PATH=/chat fantasypeak/freegpt:latest
docker run --rm -p 8858:8858 -it --name freegpt -e HTTP_PROXY=http://127.0.0.1:8080 -e CHAT_PATH=/chat fantasypeak/freegpt:latest
// set active providers
docker run -p 8858:8858 -it --name freegpt -e CHAT_PATH=/chat -e PROVIDERS="[\"gpt-4-ChatgptAi\",\"gpt-3.5-turbo-stream-DeepAi\"]" fantasypeak/freegpt:latest
docker run --rm -p 8858:8858 -it --name freegpt -e CHAT_PATH=/chat -e PROVIDERS="[\"gpt-4-ChatgptAi\",\"gpt-3.5-turbo-stream-DeepAi\"]" fantasypeak/freegpt:latest
// enable ip white list function
docker run -p 8858:8858 -it --name freegpt -e IP_WHITE_LIST="[\"127.0.0.1\",\"192.168.1.1\"]" fantasypeak/freegpt:latest
docker run --rm -p 8858:8858 -it --name freegpt -e IP_WHITE_LIST="[\"127.0.0.1\",\"192.168.1.1\"]" fantasypeak/freegpt:latest
```
### Start the Zeus Service
@ -88,7 +88,7 @@ docker run --rm --net=host -it --name freegpt fantasypeak/freegpt:latest
### Call OpenAi Api
```
// It supports calling OpenAI's API, but need set API_KEY
docker run -p 8858:8858 -it --name freegpt -e CHAT_PATH=/chat -e API_KEY=a40f22f2-c1a2-4b1d-a47f-55ae1a7ddbed fantasypeak/freegpt:latest
docker run --rm -p 8858:8858 -it --name freegpt -e CHAT_PATH=/chat -e API_KEY=a40f22f2-c1a2-4b1d-a47f-55ae1a7ddbed fantasypeak/freegpt:latest
```
### WebUI

View File

@ -1072,3 +1072,62 @@ boost::asio::awaitable<void> FreeGpt::aivvm(std::shared_ptr<Channel> ch, nlohman
});
co_return;
}
std::string generateHexStr(int length) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 15);
std::stringstream ss;
ss << std::hex;
for (int i = 0; i < length; i++)
ss << std::nouppercase << std::setw(1) << std::setfill('0') << dis(gen);
return ss.str();
}
std::string encrypt(const std::string& raw_data) {
auto random_key_str = generateHexStr(16);
auto random_iv_str = generateHexStr(16);
char key_buffer[17]{};
memcpy(key_buffer, random_key_str.c_str(), random_key_str.size());
std::vector<unsigned char> key = plusaes::key_from_string(&key_buffer); // 16-char = 128-bit
unsigned char iv[16]{};
memcpy(iv, random_iv_str.data(), 16);
const unsigned long encrypted_size = plusaes::get_padded_encrypted_size(raw_data.size());
std::vector<unsigned char> encrypted(encrypted_size);
plusaes::encrypt_cbc((unsigned char*)raw_data.data(), raw_data.size(), &key[0], key.size(), &iv, &encrypted[0],
encrypted.size(), true);
std::stringstream ss;
std::transform(encrypted.begin(), encrypted.end(), std::ostream_iterator<std::string>(ss),
[](unsigned char c) -> std::string { return std::format("{:02x}", int(c)); });
return ss.str() + random_key_str + random_iv_str;
}
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/stream.hpp>
std::expected<std::string, std::string> decompress(auto& res) {
try {
boost::iostreams::array_source src{res.body().data(), res.body().size()};
boost::iostreams::filtering_istream is;
if (res["Content-Encoding"] == "deflate") {
SPDLOG_INFO("decompressing: {}", res["Content-Encoding"]);
is.push(boost::iostreams::zlib_decompressor{-MAX_WBITS}); // deflate
} else if (res["Content-Encoding"] == "gzip") {
SPDLOG_INFO("decompressing: {}", res["Content-Encoding"]);
is.push(boost::iostreams::gzip_decompressor{}); // gzip
} else if (res["Content-Encoding"] == "") {
SPDLOG_INFO("uncompressed: {}", res["Content-Encoding"]);
}
is.push(src);
std::stringstream strstream;
boost::iostreams::copy(is, strstream);
return strstream.str();
} catch (const std::exception& e) {
return std::unexpected(e.what());
}
}

View File

@ -11,15 +11,8 @@
#include <curl/curl.h>
#include <openssl/md5.h>
#include <spdlog/spdlog.h>
#include <zlib.h>
#include <boost/algorithm/string/replace.hpp>
#include <boost/asio/as_tuple.hpp>
#include <boost/asio/experimental/channel.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/stream.hpp>
#include <plusaes/plusaes.hpp>
#include "free_gpt.h"
@ -65,37 +58,6 @@ std::string md5(const std::string& str, bool reverse = true) {
return md5_str;
}
std::string generateHexStr(int length) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 15);
std::stringstream ss;
ss << std::hex;
for (int i = 0; i < length; i++)
ss << std::nouppercase << std::setw(1) << std::setfill('0') << dis(gen);
return ss.str();
}
std::string encrypt(const std::string& raw_data) {
auto random_key_str = generateHexStr(16);
auto random_iv_str = generateHexStr(16);
char key_buffer[17]{};
memcpy(key_buffer, random_key_str.c_str(), random_key_str.size());
std::vector<unsigned char> key = plusaes::key_from_string(&key_buffer); // 16-char = 128-bit
unsigned char iv[16]{};
memcpy(iv, random_iv_str.data(), 16);
const unsigned long encrypted_size = plusaes::get_padded_encrypted_size(raw_data.size());
std::vector<unsigned char> encrypted(encrypted_size);
plusaes::encrypt_cbc((unsigned char*)raw_data.data(), raw_data.size(), &key[0], key.size(), &iv, &encrypted[0],
encrypted.size(), true);
std::stringstream ss;
std::transform(encrypted.begin(), encrypted.end(), std::ostream_iterator<std::string>(ss),
[](unsigned char c) -> std::string { return std::format("{:02x}", int(c)); });
return ss.str() + random_key_str + random_iv_str;
}
auto splitString(const std::string& input, const std::string& delimiter) {
std::vector<std::string> fields;
std::string::size_type start = 0;
@ -123,119 +85,32 @@ std::vector<std::string> findAll(const std::string& pattern, const std::string&
return matches;
}
std::string charToHex(char c) {
std::string result;
char first, second;
first = (c & 0xF0) / 16;
first += first > 9 ? 'A' - 10 : '0';
second = c & 0x0F;
second += second > 9 ? 'A' - 10 : '0';
result.append(1, first);
result.append(1, second);
return result;
}
std::string urlEncode(const std::string& src) {
std::string result;
std::string::const_iterator iter;
for (iter = src.begin(); iter != src.end(); ++iter) {
switch (*iter) {
case ' ':
result.append(1, '+');
break;
// alnum
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// mark
case '-':
case '_':
case '.':
case '!':
case '~':
case '*':
case '\'':
case '(':
case ')':
case '&':
case '=':
case '/':
case '\\':
case '?':
result.append(1, *iter);
break;
// escape
default:
result.append(1, '%');
result.append(charToHex(*iter));
break;
std::string paramsToQueryStr(const std::multimap<std::string, std::string>& params) {
auto encode_query_param = [](const std::string& value) {
std::ostringstream escaped;
escaped.fill('0');
escaped << std::hex;
for (auto c : value) {
if (std::isalnum(static_cast<uint8_t>(c)) || c == '-' || c == '_' || c == '.' || c == '!' || c == '~' ||
c == '*' || c == '\'' || c == '(' || c == ')') {
escaped << c;
} else {
escaped << std::uppercase;
escaped << '%' << std::setw(2) << static_cast<int>(static_cast<unsigned char>(c));
escaped << std::nouppercase;
}
}
return escaped.str();
};
std::string query;
for (auto it = params.begin(); it != params.end(); ++it) {
if (it != params.begin())
query += "&";
query += it->first;
query += "=";
query += encode_query_param(it->second);
}
return result;
return query;
}
enum class Status : uint8_t {
@ -352,28 +227,6 @@ boost::asio::awaitable<Status> sendRequestRecvChunk(
co_return ret;
}
std::expected<std::string, std::string> decompress(auto& res) {
try {
boost::iostreams::array_source src{res.body().data(), res.body().size()};
boost::iostreams::filtering_istream is;
if (res["Content-Encoding"] == "deflate") {
SPDLOG_INFO("decompressing: {}", res["Content-Encoding"]);
is.push(boost::iostreams::zlib_decompressor{-MAX_WBITS}); // deflate
} else if (res["Content-Encoding"] == "gzip") {
SPDLOG_INFO("decompressing: {}", res["Content-Encoding"]);
is.push(boost::iostreams::gzip_decompressor{}); // gzip
} else if (res["Content-Encoding"] == "") {
SPDLOG_INFO("uncompressed: {}", res["Content-Encoding"]);
}
is.push(src);
std::stringstream strstream;
boost::iostreams::copy(is, strstream);
return strstream.str();
} catch (const std::exception& e) {
return std::unexpected(e.what());
}
}
boost::asio::awaitable<
std::expected<std::tuple<boost::beast::http::response<boost::beast::http::string_body>, boost::asio::ssl::context,
boost::beast::ssl_stream<boost::beast::tcp_stream>>,
@ -433,154 +286,12 @@ uint64_t getTimestamp(std::chrono::time_point<std::chrono::system_clock> now = s
return timestamp;
}
struct HttpResponse {
int32_t http_response_code;
std::vector<std::unordered_multimap<std::string, std::string>> http_header;
std::string body;
};
// export CURL_IMPERSONATE=chrome110
std::optional<HttpResponse> getCookie(CURL* curl, const std::string& url, const std::string& proxy) {
bool auto_clean = curl ? false : true;
if (!curl) {
curl = curl_easy_init();
if (!curl) {
SPDLOG_ERROR("curl_easy_init() failed");
return std::nullopt;
}
}
HttpResponse http_response;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
if (!proxy.empty())
curl_easy_setopt(curl, CURLOPT_PROXY, proxy.c_str());
auto write_callback = [](void* contents, size_t size, size_t nmemb, void* userp) -> size_t {
static_cast<std::string*>(userp)->append((char*)contents, size * nmemb);
return size * nmemb;
};
size_t (*fn_write_callback)(void* contents, size_t size, size_t nmemb, void* userp) = write_callback;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fn_write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &http_response.body);
auto header_callback = [](char* buffer, size_t size, size_t nitems, void* userdata) {
static_cast<std::string*>(userdata)->append((char*)buffer, size * nitems);
return nitems * size;
};
size_t (*fn_header_callback)(char* buffer, size_t size, size_t nitems, void* userdata) = header_callback;
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, fn_header_callback);
std::string buffer;
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &buffer);
curlEasySetopt(curl);
ScopeExit auto_exit{[=] {
if (auto_clean)
curl_easy_cleanup(curl);
}};
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
SPDLOG_ERROR("curl_easy_perform() failed: [{}]", curl_easy_strerror(res));
return std::nullopt;
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response.http_response_code);
auto header_data = splitString(buffer, "\n");
std::unordered_multimap<std::string, std::string> headers;
for (auto& str : header_data) {
// if (str.ends_with("Connection established\n\n"))
// continue;
if (str.size() == 1 && !headers.empty()) {
http_response.http_header.emplace_back(std::move(headers));
headers.clear();
continue;
}
if (!str.contains(": ")) {
auto value = splitString(str, " ");
if (value.size() >= 2)
headers.emplace("http_response_code", value[1]);
} else {
auto value = splitString(str, ": ");
if (value.size() >= 2)
headers.emplace(value[0], value[1]);
}
}
if (!headers.empty()) {
http_response.http_header.emplace_back(std::move(headers));
}
for (auto& value : http_response.http_header) {
SPDLOG_INFO("=========================================");
for (auto& [k, v] : value)
SPDLOG_INFO("{}: {}", k, v);
}
return http_response;
}
std::expected<nlohmann::json, std::string> callZeus(const std::string& host, const std::string& request_body) {
CURLcode res;
CURL* curl = curl_easy_init();
if (!curl) {
auto error_info = std::format("callZeus curl_easy_init() failed:{}", curl_easy_strerror(res));
return std::unexpected(error_info);
}
curl_easy_setopt(curl, CURLOPT_URL, host.data());
struct Input {
std::string recv;
};
Input input;
auto action_cb = [](void* contents, size_t size, size_t nmemb, void* userp) -> size_t {
auto input_ptr = static_cast<Input*>(userp);
std::string data{(char*)contents, size * nmemb};
auto& [recv] = *input_ptr;
recv.append(data);
return size * nmemb;
};
size_t (*action_fn)(void* contents, size_t size, size_t nmemb, void* userp) = action_cb;
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, action_fn);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &input);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request_body.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) {
auto error_info = std::format("callZeus curl_easy_perform() failed:{}", curl_easy_strerror(res));
return std::unexpected(error_info);
}
int32_t response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code != 200) {
return std::unexpected(std::format("callZeus http code:{}", response_code));
}
nlohmann::json rsp = nlohmann::json::parse(input.recv, nullptr, false);
if (rsp.is_discarded()) {
SPDLOG_ERROR("json parse error");
return std::unexpected("parse callZeus error");
}
return rsp;
}
struct CurlHttpRequest {
CURL* curl;
CURL* curl{nullptr};
std::string url;
std::string_view http_proxy;
size_t (*cb)(void* contents, size_t size, size_t nmemb, void* userp);
void* input;
size_t (*cb)(void* contents, size_t size, size_t nmemb, void* userp){nullptr};
void* input{nullptr};
std::unordered_map<std::string, std::string>& headers;
std::string body;
std::multimap<std::string, std::string>* response_header_ptr{nullptr};
@ -659,6 +370,49 @@ std::optional<std::string> sendHttpRequest(const CurlHttpRequest& curl_http_requ
return std::nullopt;
}
std::expected<nlohmann::json, std::string> callZeus(const std::string& host, const std::string& request_body) {
CURLcode res;
CURL* curl = curl_easy_init();
if (!curl) {
auto error_info = std::format("callZeus curl_easy_init() failed:{}", curl_easy_strerror(res));
return std::unexpected(error_info);
}
ScopeExit auto_exit{[=] { curl_easy_cleanup(curl); }};
std::string http_proxy;
std::string recv;
auto ret = sendHttpRequest(CurlHttpRequest{
.curl = curl,
.url = host,
.http_proxy = http_proxy,
.cb = [](void* contents, size_t size, size_t nmemb, void* userp) mutable -> size_t {
auto recv_ptr = static_cast<std::string*>(userp);
std::string data{(char*)contents, size * nmemb};
recv_ptr->append(data);
return size * nmemb;
},
.input = &recv,
.headers = [&] -> auto& {
static std::unordered_map<std::string, std::string> headers{
{"Content-Type", "application/json"},
};
return headers;
}(),
.body = request_body,
.response_header_ptr = nullptr,
.expect_response_code = 200,
.ssl_verify = false,
});
if (ret)
return std::unexpected(ret.value());
nlohmann::json rsp = nlohmann::json::parse(recv, nullptr, false);
if (rsp.is_discarded()) {
SPDLOG_ERROR("json parse error");
return std::unexpected("parse callZeus error");
}
return rsp;
}
} // namespace
FreeGpt::FreeGpt(Config& cfg)
@ -970,16 +724,17 @@ create_client:
request.set(boost::beast::http::field::user_agent, user_agent);
request.set("Content-Type", "application/x-www-form-urlencoded");
std::stringstream ss;
ss << "message=" << urlEncode(std::format("user: {}\nassistant: ", prompt)) << "&";
ss << "_wpnonce=" << nonce << "&";
ss << "post_id=" << post_id << "&";
ss << "url=" << urlEncode("https://chatgpt.ai") << "&";
ss << "action=wpaicg_chat_shortcode_message&";
ss << "bot_id=" << bot_id;
SPDLOG_INFO("request: {}", ss.str());
request.body() = ss.str();
std::multimap<std::string, std::string> params{
{"message", std::format("user: {}\nassistant: ", prompt)},
{"_wpnonce", nonce},
{"post_id", post_id},
{"url", "https://chatgpt.ai"},
{"action", "wpaicg_chat_shortcode_message"},
{"bot_id", bot_id},
};
auto str = paramsToQueryStr(params);
SPDLOG_INFO("request: {}", str);
request.body() = str;
request.prepare_payload();
auto [ec, count] = co_await boost::beast::http::async_write(stream_, request, use_nothrow_awaitable);
@ -1001,7 +756,7 @@ create_client:
co_await ch->async_send(err, response.reason(), use_nothrow_awaitable);
co_return;
}
ss.clear();
std::stringstream ss;
ss << response.base();
SPDLOG_INFO("{}", ss.str());
SPDLOG_INFO("response.body(): {}", response.body());
@ -1310,81 +1065,108 @@ boost::asio::awaitable<void> FreeGpt::huggingChat(std::shared_ptr<Channel> ch, n
}
boost::asio::awaitable<void> FreeGpt::you(std::shared_ptr<Channel> ch, nlohmann::json json) {
boost::asio::post(*m_thread_pool_ptr, [=, this] {
boost::system::error_code err{};
ScopeExit _exit{[=] { boost::asio::post(ch->get_executor(), [=] { ch->close(); }); }};
co_await boost::asio::post(boost::asio::bind_executor(*m_thread_pool_ptr, boost::asio::use_awaitable));
boost::system::error_code err{};
ScopeExit _exit{[=] { boost::asio::post(ch->get_executor(), [=] { ch->close(); }); }};
auto prompt = json.at("meta").at("content").at("parts").at(0).at("content").get<std::string>();
static std::mutex mtx;
static std::queue<std::tuple<std::chrono::time_point<std::chrono::system_clock>, std::string>> cookie_queue;
std::tuple<std::chrono::time_point<std::chrono::system_clock>, std::string> cookie_cache;
std::queue<std::tuple<std::chrono::time_point<std::chrono::system_clock>, std::string>> tmp_queue;
std::unique_lock lk(mtx);
while (!cookie_queue.empty()) {
auto& [time_point, code] = cookie_queue.front();
if (std::chrono::system_clock::now() - time_point < std::chrono::minutes(15))
tmp_queue.push(std::move(cookie_queue.front()));
cookie_queue.pop();
}
cookie_queue = std::move(tmp_queue);
SPDLOG_INFO("cookie_queue size: {}", cookie_queue.size());
if (cookie_queue.empty()) {
lk.unlock();
auto cookie_opt = getCookie(nullptr, "https://you.com", m_cfg.http_proxy);
if (!cookie_opt) {
boost::asio::post(ch->get_executor(), [=] { ch->try_send(err, "get cookie error!!!"); });
return;
}
auto& [http_response_code, http_header, body] = cookie_opt.value();
if (!cookie_opt) {
boost::asio::post(ch->get_executor(), [=] { ch->try_send(err, "http header is empty!!!"); });
return;
}
SPDLOG_INFO("http_response_code: {}", http_response_code);
std::string cookie;
auto range = http_header.back().equal_range("set-cookie");
for (auto it = range.first; it != range.second; ++it) {
if (it->second.contains("__cf_bm=")) {
auto fields = splitString(it->second, " ");
if (fields.size() < 1) {
boost::asio::post(ch->get_executor(), [=] { ch->try_send(err, "can't get cookie"); });
return;
}
cookie = std::move(fields[0]);
break;
}
}
if (cookie.empty()) {
boost::asio::post(ch->get_executor(), [=] { ch->try_send(err, "cookie is empty"); });
return;
}
cookie_cache = std::make_tuple(std::chrono::system_clock::now(), std::move(cookie));
} else {
cookie_cache = std::move(cookie_queue.front());
cookie_queue.pop();
lk.unlock();
}
SPDLOG_INFO("cookie: {}", std::get<1>(cookie_cache));
auto prompt = json.at("meta").at("content").at("parts").at(0).at("content").get<std::string>();
static std::mutex mtx;
static std::queue<std::tuple<std::chrono::time_point<std::chrono::system_clock>, std::string>> cookie_queue;
std::tuple<std::chrono::time_point<std::chrono::system_clock>, std::string> cookie_cache;
std::queue<std::tuple<std::chrono::time_point<std::chrono::system_clock>, std::string>> tmp_queue;
std::unique_lock lk(mtx);
while (!cookie_queue.empty()) {
auto& [time_point, code] = cookie_queue.front();
if (std::chrono::system_clock::now() - time_point < std::chrono::minutes(15))
tmp_queue.push(std::move(cookie_queue.front()));
cookie_queue.pop();
}
cookie_queue = std::move(tmp_queue);
SPDLOG_INFO("cookie_queue size: {}", cookie_queue.size());
if (cookie_queue.empty()) {
lk.unlock();
CURL* curl = curl_easy_init();
if (!curl) {
auto error_info = std::format("curl_easy_init() failed");
boost::asio::post(ch->get_executor(), [=] { ch->try_send(err, error_info); });
return;
co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable));
ch->try_send(err, std::format("curl_easy_init() failed"));
co_return;
}
auto url = std::format(
"https://you.com/api/"
"streamingSearch?q={}&page=1&count=10&safeSearch=Off&onShoppingPage=False&mkt=&responseFilter="
"WebPages%"
"2CTranslations%2CTimeZone%2CComputation%2CRelatedSearches&domain=youchat&queryTraceId={}",
urlEncode(prompt), createUuidString());
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
if (!m_cfg.http_proxy.empty())
curl_easy_setopt(curl, CURLOPT_PROXY, m_cfg.http_proxy.c_str());
auto cb = [](void* contents, size_t size, size_t nmemb, void* userp) -> size_t {
ScopeExit auto_exit{[=] { curl_easy_cleanup(curl); }};
std::multimap<std::string, std::string> response_header;
std::unordered_map<std::string, std::string> headers;
auto ret = sendHttpRequest(CurlHttpRequest{
.curl = curl,
.url = "https://you.com",
.http_proxy = m_cfg.http_proxy,
.cb = [](void* contents, size_t size, size_t nmemb, void* userp) mutable -> size_t {
return size * nmemb;
},
.headers = headers,
.response_header_ptr = &response_header,
});
if (ret) {
co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable));
ch->try_send(err, ret.value());
co_return;
}
std::string cookie;
auto range = response_header.equal_range("set-cookie");
for (auto it = range.first; it != range.second; ++it) {
if (!(it->second.contains("__cf_bm=")))
continue;
auto view = it->second | std::views::drop_while(isspace) | std::views::reverse |
std::views::drop_while(isspace) | std::views::reverse;
auto fields = splitString(std::string{view.begin(), view.end()}, " ");
if (fields.size() < 1) {
co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable));
ch->try_send(err, "can't get cookie");
co_return;
}
cookie = std::move(fields[0]);
break;
}
if (cookie.empty()) {
co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable));
ch->try_send(err, "cookie is empty");
co_return;
}
cookie_cache = std::make_tuple(std::chrono::system_clock::now(), std::move(cookie));
} else {
cookie_cache = std::move(cookie_queue.front());
cookie_queue.pop();
lk.unlock();
}
SPDLOG_INFO("cookie: {}", std::get<1>(cookie_cache));
CURL* curl = curl_easy_init();
if (!curl) {
co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable));
ch->try_send(err, std::format("curl_easy_init() failed"));
co_return;
}
ScopeExit auto_exit{[=] { curl_easy_cleanup(curl); }};
auto cookie_str =
std::format("uuid_guest={}; safesearch_guest=Off; {}", createUuidString(), std::get<1>(cookie_cache));
curl_easy_setopt(curl, CURLOPT_COOKIE, std::get<1>(cookie_cache).c_str());
auto ret = sendHttpRequest(CurlHttpRequest{
.curl = curl,
.url = [&] -> auto {
std::multimap<std::string, std::string> params{
{"q", prompt},
{"page", "1"},
{"count", "10"},
{"safeSearch", "Off"},
{"onShoppingPage", "False"},
{"mkt", ""},
{"responseFilter", "WebPages,Translations,TimeZone,Computation,RelatedSearches"},
{"domain", "youchat"},
{"queryTraceId", createUuidString()},
};
return std::format("https://you.com/api/streamingSearch?{}", paramsToQueryStr(params));
}(),
.http_proxy = m_cfg.http_proxy,
.cb = [](void* contents, size_t size, size_t nmemb, void* userp) -> size_t {
boost::system::error_code err{};
auto ch_ptr = static_cast<FreeGpt::Channel*>(userp);
std::string data{(char*)contents, size * nmemb};
@ -1404,41 +1186,25 @@ boost::asio::awaitable<void> FreeGpt::you(std::shared_ptr<Channel> ch, nlohmann:
boost::asio::post(ch_ptr->get_executor(), [=] { ch_ptr->try_send(err, str); });
}
return size * nmemb;
};
size_t (*fn)(void* contents, size_t size, size_t nmemb, void* userp) = cb;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fn);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, ch.get());
auto cookie_str =
std::format("uuid_guest={}; safesearch_guest=Off; {}", createUuidString(), std::get<1>(cookie_cache));
curl_easy_setopt(curl, CURLOPT_COOKIE, std::get<1>(cookie_cache).c_str());
curlEasySetopt(curl);
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "referer: https://you.com/search?q=gpt4&tbm=youchat");
headers = curl_slist_append(headers, "Accept: text/event-stream");
ScopeExit auto_exit{[=] {
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}};
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
auto error_info = std::format("curl_easy_perform() failed:{}", curl_easy_strerror(res));
boost::asio::post(ch->get_executor(), [=] { ch->try_send(err, error_info); });
return;
}
int32_t response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code != 200) {
boost::asio::post(ch->get_executor(),
[=] { ch->try_send(err, std::format("you http code:{}", response_code)); });
}
{
std::lock_guard lk(mtx);
cookie_queue.push(std::move(cookie_cache));
}
return;
},
.input = ch.get(),
.headers = []() -> auto& {
static std::unordered_map<std::string, std::string> headers{
{"referer", "https://you.com/search?q=gpt4&tbm=youchat"},
{"Accept", "text/event-stream"},
};
return headers;
}(),
});
if (ret) {
co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable));
ch->try_send(err, ret.value());
co_return;
}
{
std::lock_guard lk(mtx);
cookie_queue.push(std::move(cookie_cache));
}
co_return;
}
@ -1739,8 +1505,13 @@ boost::asio::awaitable<void> FreeGpt::gptGo(std::shared_ptr<Channel> ch, nlohman
ch->try_send(err, error_info);
co_return;
}
auto get_token_url =
std::format("https://gptgo.ai/action_get_token.php?q={}&hlgpt=default&hl=en", urlEncode(prompt));
std::multimap<std::string, std::string> params{
{"q", prompt},
{"hlgpt", "default"},
{"hl", "en"},
};
auto get_token_url = std::format("https://gptgo.ai/action_get_token.php?{}", paramsToQueryStr(params));
curl_easy_setopt(curl, CURLOPT_URL, get_token_url.c_str());
if (!m_cfg.http_proxy.empty())
curl_easy_setopt(curl, CURLOPT_PROXY, m_cfg.http_proxy.c_str());
@ -1971,7 +1742,7 @@ boost::asio::awaitable<void> FreeGpt::chatForAi(std::shared_ptr<Channel> ch, nlo
ch->try_send(err, error_info);
co_return;
}
curl_easy_setopt(curl, CURLOPT_URL, "https://chatforai.com/api/handle/provider-openai");
curl_easy_setopt(curl, CURLOPT_URL, "https://chatforai.store/api/handle/provider-openai");
if (!m_cfg.http_proxy.empty())
curl_easy_setopt(curl, CURLOPT_PROXY, m_cfg.http_proxy.c_str());
@ -2581,7 +2352,7 @@ boost::asio::awaitable<void> FreeGpt::gptForLove(std::shared_ptr<Channel> ch, nl
constexpr std::string_view request_str{R"({
"prompt": "hello",
"options": {},
"systemMessage": "You are ChatGPT, the version is GPT3.5, a large language model trained by OpenAI. Follow the user's instructions carefully. Respond using markdown.",
"systemMessage": "You are ChatGPT, the version is GPT3.5, a large language model trained by OpenAI. Follow the user's instructions carefully.",
"temperature": 0.8,
"top_p": 1,
"secret": "U2FsdGVkX18vdtlMj0nP1LoUzEqJTP0is+Q2+bQJNMk=",

View File

@ -38,9 +38,9 @@ def deepai_refresh():
@app.route("/gptforlove", methods=["POST"])
def get_gptforlove_secret():
dir = os.path.dirname(__file__)
dir += "/npm/node_modules/crypto-js"
include = dir + "/npm/node_modules/crypto-js/crypto-js"
source = """
CryptoJS = require('{dir}/crypto-js')
CryptoJS = require({include})
var k = '14487141bvirvvG'
, e = Math.floor(new Date().getTime() / 1e3);
var t = CryptoJS.enc.Utf8.parse(e)
@ -50,7 +50,7 @@ var t = CryptoJS.enc.Utf8.parse(e)
});
return o.toString()
"""
source = source.replace("{dir}", dir)
source = source.replace("{include}", json.dumps(include))
dict = {"secret": execjs.compile(source).call("")}
return json.dumps(dict)