mirror of
https://github.com/Syping/dtranslatebot.git
synced 2026-04-01 13:20:40 +02:00
ported translator to curl, removed EL7 + Windows support
This commit is contained in:
parent
ecece11eac
commit
63399a010d
18 changed files with 250 additions and 101 deletions
94
src/core/http_request.cpp
Normal file
94
src/core/http_request.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*****************************************************************************
|
||||
* dtranslatebot Discord Translate Bot
|
||||
* Copyright (C) 2026 Syping
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* This software is provided as-is, no warranties are given to you, we are not
|
||||
* responsible for anything with use of the software, you are self responsible.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "http_request.h"
|
||||
|
||||
http_request::http_request() {
|
||||
instance = curl_easy_init();
|
||||
if (!instance)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
http_response http_request::get(const std::string &url, const dpp::http_headers &headers) {
|
||||
http_response response;
|
||||
curl_easy_setopt(instance, CURLOPT_URL, url.c_str());
|
||||
curl_slist *header_slist = nullptr;
|
||||
if (!headers.empty()) {
|
||||
for (const auto &header : headers) {
|
||||
header_slist = curl_slist_append(header_slist, std::string(header.first + ": " + header.second).c_str());
|
||||
if (!header_slist)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
if (!header_slist)
|
||||
curl_easy_setopt(instance, CURLOPT_HTTPHEADER, header_slist);
|
||||
curl_easy_setopt(instance, CURLOPT_WRITEDATA, &response.content);
|
||||
curl_easy_setopt(instance, CURLOPT_WRITEFUNCTION, &writer);
|
||||
CURLcode result = curl_easy_perform(instance);
|
||||
if (result == CURLE_OK)
|
||||
curl_easy_getinfo(instance, CURLINFO_RESPONSE_CODE, &response.status);
|
||||
curl_easy_reset(instance);
|
||||
curl_slist_free_all(header_slist);
|
||||
return response;
|
||||
}
|
||||
|
||||
http_response http_request::post(const std::string &url, const std::string &content, const std::string &content_type, const dpp::http_headers &headers) {
|
||||
http_response response;
|
||||
curl_easy_setopt(instance, CURLOPT_URL, url.c_str());
|
||||
curl_slist *header_slist = nullptr;
|
||||
if (!content_type.empty()) {
|
||||
header_slist = curl_slist_append(header_slist, std::string("Content-Type: " + content_type).c_str());
|
||||
if (!header_slist)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
if (!headers.empty()) {
|
||||
for (const auto &header : headers) {
|
||||
header_slist = curl_slist_append(header_slist, std::string(header.first + ": " + header.second).c_str());
|
||||
if (!header_slist)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
if (!header_slist)
|
||||
curl_easy_setopt(instance, CURLOPT_HTTPHEADER, header_slist);
|
||||
curl_easy_setopt(instance, CURLOPT_POSTFIELDS, content.data());
|
||||
curl_easy_setopt(instance, CURLOPT_POSTFIELDSIZE, content.size());
|
||||
curl_easy_setopt(instance, CURLOPT_WRITEDATA, &response.content);
|
||||
curl_easy_setopt(instance, CURLOPT_WRITEFUNCTION, &writer);
|
||||
CURLcode result = curl_easy_perform(instance);
|
||||
if (result == CURLE_OK)
|
||||
curl_easy_getinfo(instance, CURLINFO_RESPONSE_CODE, &response.status);
|
||||
curl_easy_reset(instance);
|
||||
curl_slist_free_all(header_slist);
|
||||
return response;
|
||||
}
|
||||
|
||||
std::string http_request::legacy_url(const std::string &hostname, uint16_t port, const std::string &url, bool tls) {
|
||||
return (tls ? "https://" : "http://") + hostname + ":" + std::to_string(port) + (url.empty() ? "/" : (url.front() != '/' ? "/" + url : url));
|
||||
}
|
||||
|
||||
http_request::~http_request() {
|
||||
curl_easy_cleanup(instance);
|
||||
}
|
||||
|
||||
size_t http_request::writer(char *source, size_t size, size_t nmemb, std::string *target) {
|
||||
if (target == nullptr)
|
||||
return 0;
|
||||
size_t write_size = size * nmemb;
|
||||
target->append(source, write_size);
|
||||
return write_size;
|
||||
}
|
||||
40
src/core/http_request.h
Normal file
40
src/core/http_request.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*****************************************************************************
|
||||
* dtranslatebot Discord Translate Bot
|
||||
* Copyright (C) 2026 Syping
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* This software is provided as-is, no warranties are given to you, we are not
|
||||
* responsible for anything with use of the software, you are self responsible.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef HTTP_REQUEST_H
|
||||
#define HTTP_REQUEST_H
|
||||
#include <curl/curl.h>
|
||||
#include <cstdint>
|
||||
#include <dpp/httpsclient.h>
|
||||
#include "http_response.h"
|
||||
|
||||
class http_request
|
||||
{
|
||||
public:
|
||||
http_request();
|
||||
~http_request();
|
||||
http_response get(const std::string &url, const dpp::http_headers &headers = {});
|
||||
http_response post(const std::string &url, const std::string &content, const std::string &content_type, const dpp::http_headers &headers = {});
|
||||
static std::string legacy_url(const std::string &hostname, uint16_t port, const std::string &url, bool tls);
|
||||
|
||||
private:
|
||||
static size_t writer(char *source, size_t size, size_t nmemb, std::string *target);
|
||||
CURL *instance;
|
||||
};
|
||||
|
||||
#endif // HTTP_REQUEST_H
|
||||
29
src/core/http_response.h
Normal file
29
src/core/http_response.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*****************************************************************************
|
||||
* dtranslatebot Discord Translate Bot
|
||||
* Copyright (C) 2026 Syping
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* This software is provided as-is, no warranties are given to you, we are not
|
||||
* responsible for anything with use of the software, you are self responsible.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef HTTP_RESPONSE_H
|
||||
#define HTTP_RESPONSE_H
|
||||
#include <string>
|
||||
|
||||
struct http_response
|
||||
{
|
||||
std::string content;
|
||||
long status;
|
||||
};
|
||||
|
||||
#endif // HTTP_RESPONSE_H
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <curl/curl.h>
|
||||
#include "message_queue.h"
|
||||
#include "settings.h"
|
||||
#include "slashcommands.h"
|
||||
|
|
@ -45,6 +46,12 @@ int main(int argc, char* argv[]) {
|
|||
if (!settings.parse_file(args.at(0)))
|
||||
return 1;
|
||||
|
||||
CURLcode result = curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
if (result != CURLE_OK) {
|
||||
std::cerr << "[Error] Failed to initialise curl" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
std::cout << "[Launch] Requesting supported languages..." << std::endl;
|
||||
if (!settings.get_translator()->get_languages().empty()) {
|
||||
|
|
@ -88,5 +95,7 @@ int main(int argc, char* argv[]) {
|
|||
submit_queue.terminate();
|
||||
submit_queue_loop.join();
|
||||
|
||||
curl_global_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* dtranslatebot Discord Translate Bot
|
||||
* Copyright (C) 2023-2024 Syping
|
||||
* Copyright (C) 2023-2026 Syping
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* dtranslatebot Discord Translate Bot
|
||||
* Copyright (C) 2024 Syping
|
||||
* Copyright (C) 2024-2026 Syping
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <dpp/json.h>
|
||||
#include <dpp/httpsclient.h>
|
||||
#include "../../core/http_request.h"
|
||||
#include "deepl.h"
|
||||
using namespace bot::translator;
|
||||
using namespace std::chrono_literals;
|
||||
|
|
@ -42,12 +43,13 @@ const std::vector<language> deepl::get_languages()
|
|||
}
|
||||
|
||||
try {
|
||||
dpp::https_client http_request(&m_cluster, m_hostname, 443, "/v2/languages?type=target", "GET", {}, { {"Authorization"s, "DeepL-Auth-Key " + m_apiKey} }, false);
|
||||
if (http_request.get_status() == 200) {
|
||||
const dpp::json response = dpp::json::parse(http_request.get_content());
|
||||
if (response.is_array()) {
|
||||
http_request request;
|
||||
http_response response = request.get(http_request::legacy_url(m_hostname, 443, "/v2/languages?type=target", true), { {"Authorization"s, "DeepL-Auth-Key " + m_apiKey} });
|
||||
if (response.status == 200) {
|
||||
const dpp::json json_response = dpp::json::parse(response.content);
|
||||
if (json_response.is_array()) {
|
||||
m_languages.languages.clear();
|
||||
for (auto json_language = response.begin(); json_language != response.end(); json_language++) {
|
||||
for (auto json_language = json_response.begin(); json_language != json_response.end(); json_language++) {
|
||||
if (json_language->is_object()) {
|
||||
language language;
|
||||
|
||||
|
|
@ -93,12 +95,13 @@ const std::string deepl::translate(const std::string &text, const std::string &s
|
|||
};
|
||||
|
||||
try {
|
||||
dpp::https_client http_request(&m_cluster, m_hostname, 443, "/v2/translate", "POST", json_body.dump(), http_headers, false);
|
||||
if (http_request.get_status() == 200) {
|
||||
const dpp::json response = dpp::json::parse(http_request.get_content());
|
||||
if (response.is_object()) {
|
||||
auto translations = response.find("translations");
|
||||
if (translations != response.end() && translations->is_array()) {
|
||||
http_request request;
|
||||
http_response response = request.post(http_request::legacy_url(m_hostname, 443, "/v2/translate", true), json_body.dump(), "application/json", { {"Authorization"s, "DeepL-Auth-Key " + m_apiKey} });
|
||||
if (response.status == 200) {
|
||||
const dpp::json json_response = dpp::json::parse(response.content);
|
||||
if (json_response.is_object()) {
|
||||
auto translations = json_response.find("translations");
|
||||
if (translations != json_response.end() && translations->is_array()) {
|
||||
for (auto translation = translations->begin(); translation != translations->end(); translation++) {
|
||||
auto tr_text = translation->find("text");
|
||||
if (tr_text != translation->end())
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* dtranslatebot Discord Translate Bot
|
||||
* Copyright (C) 2024 Syping
|
||||
* Copyright (C) 2024-2026 Syping
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
|
|
@ -32,7 +32,6 @@ namespace bot {
|
|||
const std::string translate(const std::string &text, const std::string &source, const std::string &target) override;
|
||||
|
||||
private:
|
||||
dpp::cluster m_cluster;
|
||||
std::string m_apiKey;
|
||||
std::string m_hostname;
|
||||
supported_languages m_languages;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* dtranslatebot Discord Translate Bot
|
||||
* Copyright (C) 2023-2024 Syping
|
||||
* Copyright (C) 2023-2026 Syping
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <dpp/json.h>
|
||||
#include <dpp/httpsclient.h>
|
||||
#include "../../core/http_request.h"
|
||||
#include "libretranslate.h"
|
||||
using namespace bot::translator;
|
||||
using namespace std::chrono_literals;
|
||||
|
|
@ -42,12 +43,13 @@ const std::vector<language> libretranslate::get_languages()
|
|||
}
|
||||
|
||||
try {
|
||||
dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "languages", "GET", {}, {}, !m_tls);
|
||||
if (http_request.get_status() == 200) {
|
||||
const dpp::json response = dpp::json::parse(http_request.get_content());
|
||||
if (response.is_array()) {
|
||||
http_request request;
|
||||
http_response response = request.get(http_request::legacy_url(m_hostname, m_port, m_url + "languages", m_tls));
|
||||
if (response.status == 200) {
|
||||
const dpp::json json_response = dpp::json::parse(response.content);
|
||||
if (json_response.is_array()) {
|
||||
m_languages.languages.clear();
|
||||
for (auto json_language = response.begin(); json_language != response.end(); json_language++) {
|
||||
for (auto json_language = json_response.begin(); json_language != json_response.end(); json_language++) {
|
||||
if (json_language->is_object()) {
|
||||
language language;
|
||||
|
||||
|
|
@ -91,12 +93,13 @@ const std::string libretranslate::translate(const std::string &text, const std::
|
|||
json_body["apiKey"] = m_apiKey;
|
||||
|
||||
try {
|
||||
dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "translate", "POST", json_body.dump(), http_headers, !m_tls);
|
||||
if (http_request.get_status() == 200) {
|
||||
const dpp::json response = dpp::json::parse(http_request.get_content());
|
||||
if (response.is_object()) {
|
||||
auto tr_text = response.find("translatedText");
|
||||
if (tr_text != response.end())
|
||||
http_request request;
|
||||
http_response response = request.post(http_request::legacy_url(m_hostname, m_port, m_url + "translate", m_tls), json_body.dump(), "application/json");
|
||||
if (response.status == 200) {
|
||||
const dpp::json json_response = dpp::json::parse(response.content);
|
||||
if (json_response.is_object()) {
|
||||
auto tr_text = json_response.find("translatedText");
|
||||
if (tr_text != json_response.end())
|
||||
return *tr_text;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ namespace bot {
|
|||
const std::string translate(const std::string &text, const std::string &source, const std::string &target) override;
|
||||
|
||||
private:
|
||||
dpp::cluster m_cluster;
|
||||
std::string m_apiKey;
|
||||
std::string m_hostname;
|
||||
supported_languages m_languages;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* dtranslatebot Discord Translate Bot
|
||||
* Copyright (C) 2024 Syping
|
||||
* Copyright (C) 2024-2026 Syping
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
#include <dpp/json.h>
|
||||
#include <dpp/httpsclient.h>
|
||||
#include <dpp/utility.h>
|
||||
#include "../../core/http_request.h"
|
||||
#include "lingvatranslate.h"
|
||||
using namespace bot::translator;
|
||||
using namespace std::chrono_literals;
|
||||
|
|
@ -43,12 +44,13 @@ const std::vector<language> lingvatranslate::get_languages()
|
|||
}
|
||||
|
||||
try {
|
||||
dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "api/v1/languages/target", "GET", {}, {}, !m_tls);
|
||||
if (http_request.get_status() == 200) {
|
||||
const dpp::json response = dpp::json::parse(http_request.get_content());
|
||||
if (response.is_object()) {
|
||||
auto languages = response.find("languages");
|
||||
if (languages != response.end()) {
|
||||
http_request request;
|
||||
http_response response = request.get(http_request::legacy_url(m_hostname, m_port, m_url + "api/v1/languages/target", m_tls));
|
||||
if (response.status == 200) {
|
||||
const dpp::json json_response = dpp::json::parse(response.content);
|
||||
if (json_response.is_object()) {
|
||||
auto languages = json_response.find("languages");
|
||||
if (languages != json_response.end()) {
|
||||
m_languages.languages.clear();
|
||||
for (auto json_language = languages->begin(); json_language != languages->end(); json_language++) {
|
||||
if (json_language->is_object()) {
|
||||
|
|
@ -81,14 +83,15 @@ const std::vector<language> lingvatranslate::get_languages()
|
|||
const std::string lingvatranslate::translate(const std::string &text, const std::string &source, const std::string &target)
|
||||
{
|
||||
try {
|
||||
dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "api/v1/" + source + "/" + target + "/" + dpp::utility::url_encode(text), "GET", {}, {}, !m_tls);
|
||||
if (http_request.get_status() == 200) {
|
||||
const dpp::json response = dpp::json::parse(http_request.get_content());
|
||||
if (response.is_object()) {
|
||||
auto tr_text = response.find("translation");
|
||||
if (tr_text != response.end())
|
||||
http_request request;
|
||||
http_response response = request.get(http_request::legacy_url(m_hostname, m_port, m_url + "api/v1/" + source + "/" + target + "/" + dpp::utility::url_encode(text), m_tls));
|
||||
if (response.status == 200) {
|
||||
const dpp::json json_response = dpp::json::parse(response.content);
|
||||
if (json_response.is_object()) {
|
||||
auto tr_text = json_response.find("translation");
|
||||
if (tr_text != json_response.end())
|
||||
return *tr_text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &exception) {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ namespace bot {
|
|||
const std::string translate(const std::string &text, const std::string &source, const std::string &target) override;
|
||||
|
||||
private:
|
||||
dpp::cluster m_cluster;
|
||||
std::string m_hostname;
|
||||
supported_languages m_languages;
|
||||
uint16_t m_port;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* dtranslatebot Discord Translate Bot
|
||||
* Copyright (C) 2024 Syping
|
||||
* Copyright (C) 2024-2026 Syping
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
#include <dpp/json.h>
|
||||
#include <dpp/httpsclient.h>
|
||||
#include <dpp/utility.h>
|
||||
#include "../../core/http_request.h"
|
||||
#include "mozhi.h"
|
||||
using namespace bot::translator;
|
||||
using namespace std::chrono_literals;
|
||||
|
|
@ -46,12 +47,13 @@ const std::vector<language> mozhi::get_languages()
|
|||
const std::string parameters = dpp::utility::make_url_parameters({
|
||||
{"engine"s, m_engine}
|
||||
});
|
||||
dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "api/target_languages" + parameters, "GET", {}, {}, !m_tls);
|
||||
if (http_request.get_status() == 200) {
|
||||
const dpp::json response = dpp::json::parse(http_request.get_content());
|
||||
if (response.is_array()) {
|
||||
http_request request;
|
||||
http_response response = request.get(http_request::legacy_url(m_hostname, m_port, m_url + "api/target_languages", m_tls));
|
||||
if (response.status == 200) {
|
||||
const dpp::json json_response = dpp::json::parse(response.content);
|
||||
if (json_response.is_array()) {
|
||||
m_languages.languages.clear();
|
||||
for (auto json_language = response.begin(); json_language != response.end(); json_language++) {
|
||||
for (auto json_language = json_response.begin(); json_language != json_response.end(); json_language++) {
|
||||
if (json_language->is_object()) {
|
||||
language language;
|
||||
|
||||
|
|
@ -87,12 +89,13 @@ const std::string mozhi::translate(const std::string &text, const std::string &s
|
|||
{"to"s, target},
|
||||
{"text"s, text},
|
||||
});
|
||||
dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "api/translate" + parameters, "GET", {}, {}, !m_tls);
|
||||
if (http_request.get_status() == 200) {
|
||||
const dpp::json response = dpp::json::parse(http_request.get_content());
|
||||
if (response.is_object()) {
|
||||
auto tr_text = response.find("translated-text");
|
||||
if (tr_text != response.end())
|
||||
http_request request;
|
||||
http_response response = request.get(http_request::legacy_url(m_hostname, m_port, m_url + "api/translate" + parameters, m_tls));
|
||||
if (response.status == 200) {
|
||||
const dpp::json json_response = dpp::json::parse(response.content);
|
||||
if (json_response.is_object()) {
|
||||
auto tr_text = json_response.find("translated-text");
|
||||
if (tr_text != json_response.end())
|
||||
return *tr_text;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ namespace bot {
|
|||
const std::string translate(const std::string &text, const std::string &source, const std::string &target) override;
|
||||
|
||||
private:
|
||||
dpp::cluster m_cluster;
|
||||
std::string m_engine;
|
||||
std::string m_hostname;
|
||||
supported_languages m_languages;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue