基本通信测试通过。
This commit is contained in:
20
.clang-format
Normal file
20
.clang-format
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
PointerAlignment: Left
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
ReflowComments: true
|
||||||
|
SpacesBeforeTrailingComments: 3
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BraceWrapping:
|
||||||
|
AfterFunction: true
|
||||||
|
AfterClass: true
|
||||||
|
TabWidth: 4
|
||||||
|
ColumnLimit: 130
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<.*>'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^".*"'
|
||||||
|
Priority: 2
|
||||||
12
.clangd
Normal file
12
.clangd
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Hover:
|
||||||
|
ShowAKA: Yes
|
||||||
|
Diagnostics:
|
||||||
|
UnusedIncludes: None # 禁用未使用头文件提示
|
||||||
|
Suppress: [
|
||||||
|
anon_type_definition, # 禁用匿名的typedef提示
|
||||||
|
unused-variable, # 禁用未使用变量提示
|
||||||
|
unused-function, # 禁用未使用函数提示
|
||||||
|
unused-includes,
|
||||||
|
]
|
||||||
|
ClangTidy:
|
||||||
|
Remove: misc-unused-alias-decls
|
||||||
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
build/
|
||||||
|
.cache/
|
||||||
|
.qtcreator/
|
||||||
|
.vs
|
||||||
|
out/
|
||||||
|
CMakeUserPresets.json
|
||||||
150
.vscode/settings.json
vendored
Normal file
150
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
{
|
||||||
|
"files.autoSave": "onFocusChange",
|
||||||
|
"editor.fontSize": 14,
|
||||||
|
"editor.fontFamily": "'Source Code Pro', 'Source Code Pro', 'Source Code Pro'",
|
||||||
|
"editor.wordWrap": "on",
|
||||||
|
"terminal.integrated.fontFamily": "'Source Code Pro'",
|
||||||
|
"cmake.configureOnOpen": true,
|
||||||
|
//"C_Cpp.intelliSenseEngine": "disabled",
|
||||||
|
"cmake.debugConfig": {
|
||||||
|
"console": "externalTerminal",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "-gdb-set charset utf-8",
|
||||||
|
"text": "-gdb-set charset UTF-8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Enable gdb pretty-printing",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
//"visualizerFile": "${workspaceRoot}/.vscode/qt6.natvis",
|
||||||
|
"args": [
|
||||||
|
"--test-request",
|
||||||
|
"-c",
|
||||||
|
"baidu_fanyi.json"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"cmake.configureArgs": [
|
||||||
|
"-Wno-dev"
|
||||||
|
],
|
||||||
|
// "cmake.configureSettings": {
|
||||||
|
// "CMAKE_TOOLCHAIN_FILE": "${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
|
||||||
|
// },
|
||||||
|
|
||||||
|
"cmake.options.statusBarVisibility": "visible",
|
||||||
|
"cmake.generator": "Ninja",
|
||||||
|
"C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json",
|
||||||
|
"C_Cpp.default.cppStandard": "c++17",
|
||||||
|
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
|
||||||
|
"editor.inlayHints.enabled": "off",
|
||||||
|
"editor.unicodeHighlight.allowedLocales": {
|
||||||
|
"ja": true,
|
||||||
|
"zh-hant": true,
|
||||||
|
"zh-hans": true
|
||||||
|
},
|
||||||
|
"files.associations": {
|
||||||
|
"*.cfg": "json",
|
||||||
|
"xstring": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"charconv": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"filesystem": "cpp",
|
||||||
|
"forward_list": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"ios": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"locale": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"xfacet": "cpp",
|
||||||
|
"xhash": "cpp",
|
||||||
|
"xiosbase": "cpp",
|
||||||
|
"xlocale": "cpp",
|
||||||
|
"xlocbuf": "cpp",
|
||||||
|
"xlocinfo": "cpp",
|
||||||
|
"xlocmes": "cpp",
|
||||||
|
"xlocmon": "cpp",
|
||||||
|
"xlocnum": "cpp",
|
||||||
|
"xloctime": "cpp",
|
||||||
|
"xmemory": "cpp",
|
||||||
|
"xmemory0": "cpp",
|
||||||
|
"xstddef": "cpp",
|
||||||
|
"xtr1common": "cpp",
|
||||||
|
"xtree": "cpp",
|
||||||
|
"xutility": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"coroutine": "cpp",
|
||||||
|
"format": "cpp",
|
||||||
|
"stop_token": "cpp",
|
||||||
|
"bitset": "cpp",
|
||||||
|
"complex": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"variant": "cpp",
|
||||||
|
"expected": "cpp",
|
||||||
|
"source_location": "cpp",
|
||||||
|
"regex": "cpp",
|
||||||
|
"*.in": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"future": "cpp",
|
||||||
|
"queue": "cpp",
|
||||||
|
"resumable": "cpp",
|
||||||
|
"any": "cpp",
|
||||||
|
"codecvt": "cpp",
|
||||||
|
"csignal": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"shared_mutex": "cpp",
|
||||||
|
"cinttypes": "cpp",
|
||||||
|
"cfenv": "cpp",
|
||||||
|
"unordered_set": "cpp",
|
||||||
|
"ranges": "cpp",
|
||||||
|
"typeindex": "cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
48
CMakeLists.txt
Normal file
48
CMakeLists.txt
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(baidu_fanyi LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
add_compile_options(/utf-8)
|
||||||
|
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||||
|
add_definitions(-D_WIN32_WINNT=0x0601)
|
||||||
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE})
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/)
|
||||||
|
|
||||||
|
find_package(CURL CONFIG REQUIRED)
|
||||||
|
find_package(OpenSSL CONFIG REQUIRED)
|
||||||
|
find_package(Xlnt CONFIG REQUIRED)
|
||||||
|
find_package(nlohmann_json CONFIG REQUIRED)
|
||||||
|
find_package(CLI11 CONFIG REQUIRED)
|
||||||
|
find_package(spdlog CONFIG REQUIRED)
|
||||||
|
find_package(fmt CONFIG REQUIRED)
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
bf.config.cpp bf.config.h
|
||||||
|
bf.request.cpp bf.request.h
|
||||||
|
bf.interface.cpp bf.interface.h
|
||||||
|
bf.util.cpp bf.util.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(baidu_fanyi main.cpp ${SOURCES})
|
||||||
|
target_link_libraries(baidu_fanyi PRIVATE
|
||||||
|
xlnt::xlnt OpenSSL::SSL OpenSSL::Crypto
|
||||||
|
CURL::libcurl nlohmann_json::nlohmann_json
|
||||||
|
CLI11::CLI11 spdlog::spdlog fmt::fmt
|
||||||
|
)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
${CMAKE_BINARY_DIR}/compile_commands.json
|
||||||
|
${CMAKE_SOURCE_DIR}/build/compile_commands.json
|
||||||
|
RESULT_VARIABLE copy_result
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_QUIET
|
||||||
|
)
|
||||||
62
bf.config.cpp
Normal file
62
bf.config.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#include "bf.config.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include "bf.util.h"
|
||||||
|
|
||||||
|
bool BF_Config::parseConfig(const std::string& file)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
std::ifstream ifs(file);
|
||||||
|
if (!ifs.is_open()) {
|
||||||
|
gLogger->error("Failed to open config file: {}", file);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nlohmann::json configJson;
|
||||||
|
ifs >> configJson;
|
||||||
|
|
||||||
|
if (!configJson.contains("baseUrl")) {
|
||||||
|
gLogger->error("Missing 'baseUrl' field in config file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
baseUrl = configJson["baseUrl"];
|
||||||
|
|
||||||
|
if (!configJson.contains("appId")) {
|
||||||
|
gLogger->error("Missing 'appId' field in config file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
appId = configJson["appId"];
|
||||||
|
|
||||||
|
if (!configJson.contains("appKey")) {
|
||||||
|
gLogger->error("Missing 'appKey' field in config file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
appKey = configJson["appKey"];
|
||||||
|
|
||||||
|
if (!configJson.contains("appSecret")) {
|
||||||
|
gLogger->error("Missing 'appSecret' field in config file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
appSecret = configJson["appSecret"];
|
||||||
|
|
||||||
|
if (configJson.contains("type")) {
|
||||||
|
int typeValue = configJson["type"];
|
||||||
|
if (typeValue == BFT_AI) {
|
||||||
|
type = BFT_AI;
|
||||||
|
} else {
|
||||||
|
type = BFT_COMMON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gLogger->info("Config loaded successfully from: {}", file);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (const nlohmann::json::exception& e) {
|
||||||
|
gLogger->error("JSON parsing error: {}", e.what());
|
||||||
|
return false;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
gLogger->error("Failed to parse config: {}", e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
bf.config.h
Normal file
32
bf.config.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef BF_CONFIG_H
|
||||||
|
#define BF_CONFIG_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
enum BF_Type {
|
||||||
|
BFT_COMMON = 0,
|
||||||
|
BFT_AI
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XlsxTask {
|
||||||
|
int startRow;
|
||||||
|
int startCol;
|
||||||
|
int endRow;
|
||||||
|
int endCol;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BF_Config
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BF_Config() = default;
|
||||||
|
bool parseConfig(const std::string& file);
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string baseUrl;
|
||||||
|
std::string appId;
|
||||||
|
std::string appKey;
|
||||||
|
std::string appSecret;
|
||||||
|
BF_Type type = BFT_COMMON;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BF_CONFIG_H
|
||||||
10
bf.interface.cpp
Normal file
10
bf.interface.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "bf.interface.h"
|
||||||
|
|
||||||
|
BF_Interface::~BF_Interface()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BF_Interface::setConfig(std::shared_ptr<BF_Config> config)
|
||||||
|
{
|
||||||
|
config_ = config;
|
||||||
|
}
|
||||||
24
bf.interface.h
Normal file
24
bf.interface.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef BF_INTERFACE_H
|
||||||
|
#define BF_INTERFACE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "bf.config.h"
|
||||||
|
#include "bf.util.h"
|
||||||
|
|
||||||
|
class BF_Interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BF_Interface() = default;
|
||||||
|
virtual ~BF_Interface();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setConfig(std::shared_ptr<BF_Config> config);
|
||||||
|
virtual std::string doReady(const std::string& words, const std::string& from, const std::string& to) = 0;
|
||||||
|
virtual std::string getResult(const std::string& data) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<BF_Config> config_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BF_INTERFACE_H
|
||||||
61
bf.request.cpp
Normal file
61
bf.request.cpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#include "bf.request.h"
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "bf.util.h"
|
||||||
|
|
||||||
|
BF_Request::BF_Request()
|
||||||
|
{
|
||||||
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
curl_ = curl_easy_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
BF_Request::~BF_Request()
|
||||||
|
{
|
||||||
|
curl_easy_cleanup(curl_);
|
||||||
|
curl_global_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BF_Request::getResult(const std::string& url)
|
||||||
|
{
|
||||||
|
std::string reponse;
|
||||||
|
if (!curl_) {
|
||||||
|
gLogger->error("curl init failed.");
|
||||||
|
return reponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
|
||||||
|
curl_easy_setopt(curl_, CURLOPT_POST, 0L);
|
||||||
|
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, writeData);
|
||||||
|
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &reponse);
|
||||||
|
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
|
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
|
||||||
|
CURLcode res = curl_easy_perform(curl_);
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
gLogger->error("curl request failed. error code: {}", static_cast<int>(res));
|
||||||
|
return reponse;
|
||||||
|
}
|
||||||
|
return reponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BF_Request::doReady(const std::string& words, const std::string& from, const std::string& to)
|
||||||
|
{
|
||||||
|
char* buffer = new char[2048]{};
|
||||||
|
auto rs = BF_Util::RandomStrNum();
|
||||||
|
auto s = fmt::format("{}{}{}{}", config_->appId, words, rs, config_->appSecret);
|
||||||
|
auto md5 = BF_Util::MD5(s);
|
||||||
|
auto reqWords = BF_Util::urlEncode(words);
|
||||||
|
std::snprintf(buffer, 2048, "q=%s&from=%s&to=%s&appid=%s&salt=%s&sign=%s", reqWords.c_str(), from.c_str(), to.c_str(),
|
||||||
|
config_->appId.c_str(), rs.c_str(), md5.c_str());
|
||||||
|
std::string data(buffer);
|
||||||
|
delete[] buffer;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t BF_Request::writeData(void* buffer, size_t size, size_t nmemb, std::string* str)
|
||||||
|
{
|
||||||
|
auto totalSize = size * nmemb;
|
||||||
|
str->append(static_cast<char*>(buffer), totalSize);
|
||||||
|
return totalSize;
|
||||||
|
}
|
||||||
27
bf.request.h
Normal file
27
bf.request.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef BF_REQUEST_H
|
||||||
|
#define BF_REQUEST_H
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
#include "bf.interface.h"
|
||||||
|
#include "bf.util.h"
|
||||||
|
#include "bf.config.h"
|
||||||
|
|
||||||
|
class BF_Request : public BF_Interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BF_Request();
|
||||||
|
~BF_Request() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string getResult(const std::string& url) override;
|
||||||
|
std::string doReady(const std::string& words, const std::string& from, const std::string& to) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static size_t writeData(void* buffer, size_t size, size_t nmemb, std::string* str);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CURL* curl_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
82
bf.util.cpp
Normal file
82
bf.util.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#include "bf.util.h"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <random>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
std::shared_ptr<spdlog::logger> gLogger = nullptr;
|
||||||
|
|
||||||
|
void BF_Util::initLogger()
|
||||||
|
{
|
||||||
|
if (!gLogger) {
|
||||||
|
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||||
|
console_sink->set_pattern("%^[%Y-%m-%d %H:%M:%S.%e][%l]: %v%$");
|
||||||
|
std::vector<spdlog::sink_ptr> sinks{console_sink};
|
||||||
|
gLogger = std::make_shared<spdlog::logger>("baidu_fanyi", sinks.begin(), sinks.end());
|
||||||
|
gLogger->set_level(spdlog::level::debug);
|
||||||
|
spdlog::register_logger(gLogger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BF_Util::setLogLevel(spdlog::level::level_enum level)
|
||||||
|
{
|
||||||
|
if (gLogger) {
|
||||||
|
gLogger->set_level(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BF_Util::MD5(const std::string& data)
|
||||||
|
{
|
||||||
|
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
|
||||||
|
if (!mdctx) {
|
||||||
|
gLogger->error("EVP_MD_CTX_new failed");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
std::shared_ptr<void> d(nullptr, [mdctx](void*) { EVP_MD_CTX_free(mdctx); });
|
||||||
|
auto ir = EVP_DigestInit_ex(mdctx, EVP_md5(), nullptr);
|
||||||
|
if (!ir) {
|
||||||
|
gLogger->error("EVP_DigestInit_ex failed");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
auto ur = EVP_DigestUpdate(mdctx, data.c_str(), data.length());
|
||||||
|
if (!ur) {
|
||||||
|
gLogger->error("EVP_DigestUpdate failed");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||||
|
unsigned int md_len;
|
||||||
|
auto fr = EVP_DigestFinal_ex(mdctx, md_value, &md_len);
|
||||||
|
if (!fr) {
|
||||||
|
gLogger->error("EVP_DigestFinal_ex failed");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
std::ostringstream os;
|
||||||
|
for (unsigned int i = 0; i < md_len; i++) {
|
||||||
|
os << std::setw(2) << std::setfill('0') << std::hex << (int)md_value[i];
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BF_Util::RandomStrNum()
|
||||||
|
{
|
||||||
|
static std::random_device rd;
|
||||||
|
static std::mt19937 gen(rd());
|
||||||
|
static std::uniform_int_distribution<> dis(100000000, 999999999);
|
||||||
|
long long num = dis(gen);
|
||||||
|
return std::to_string(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BF_Util::urlEncode(const std::string& data)
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
for (unsigned char c : data) {
|
||||||
|
if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
|
||||||
|
os << c;
|
||||||
|
} else {
|
||||||
|
os << '%' << std::uppercase << std::setw(2) << std::setfill('0') << std::hex << (int)c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
23
bf.util.h
Normal file
23
bf.util.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef BF_UTIL_H
|
||||||
|
#define BF_UTIL_H
|
||||||
|
|
||||||
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern std::shared_ptr<spdlog::logger> gLogger;
|
||||||
|
|
||||||
|
class BF_Util
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BF_Util() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void initLogger();
|
||||||
|
static void setLogLevel(spdlog::level::level_enum level);
|
||||||
|
static std::string MD5(const std::string& data);
|
||||||
|
static std::string RandomStrNum();
|
||||||
|
static std::string urlEncode(const std::string& data);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
20
conanfile.py
Normal file
20
conanfile.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from conan import ConanFile
|
||||||
|
import os
|
||||||
|
|
||||||
|
class CompressorRecipe(ConanFile):
|
||||||
|
|
||||||
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
generators = "CMakeToolchain", "CMakeDeps"
|
||||||
|
|
||||||
|
def requirements(self):
|
||||||
|
self.requires("libcurl/8.18.0")
|
||||||
|
self.requires("openssl/3.6.1")
|
||||||
|
self.requires("xlnt/1.6.1", options={"shared": True})
|
||||||
|
self.requires("nlohmann_json/3.12.0")
|
||||||
|
self.requires("cli11/2.6.0")
|
||||||
|
self.requires("spdlog/1.17.0")
|
||||||
|
self.requires("fmt/12.1.0")
|
||||||
|
|
||||||
|
def layout(self):
|
||||||
|
self.folders.generators = os.path.join("build", str(self.settings.build_type), "generators")
|
||||||
|
self.folders.build = os.path.join("build", str(self.settings.build_type))
|
||||||
113
main.cpp
Normal file
113
main.cpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#include <CLI/CLI.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <xlnt/xlnt.hpp>
|
||||||
|
|
||||||
|
#include "bf.request.h"
|
||||||
|
#include "bf.util.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "Windows.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
#endif
|
||||||
|
CLI::App app{"百度翻译xlsx批量工具。"};
|
||||||
|
|
||||||
|
std::string workbook;
|
||||||
|
std::string sheetName;
|
||||||
|
std::string from = "auto";
|
||||||
|
std::string to = "en";
|
||||||
|
bool testRequest = false;
|
||||||
|
std::vector<std::string> tasks; // 存储多个字符串
|
||||||
|
|
||||||
|
app.add_option("-t,--task", tasks, "要处理的行列范围(起始行,起始列,结束行,结束列),如:1,1,10,10)")->multi_option_policy();
|
||||||
|
app.add_option("-s,--sheet", sheetName, "工作表名称");
|
||||||
|
app.add_option("-w,--workbook", workbook, "工作簿");
|
||||||
|
app.add_option("-f,--from", from, "源语言(默认auto)");
|
||||||
|
app.add_option("--to-language,--to", to, "目标语言(默认en)");
|
||||||
|
app.add_flag("--test-request", testRequest, "测试请求");
|
||||||
|
|
||||||
|
// 添加其他可选参数
|
||||||
|
std::string config = "baidu_fanyi.json";
|
||||||
|
app.add_option("-c,--config", config, "配置文件(默认baidu_fanyi.json)");
|
||||||
|
|
||||||
|
bool verbose = false;
|
||||||
|
app.add_flag("-v,--verbose", verbose, "详细输出");
|
||||||
|
|
||||||
|
// 解析命令行参数
|
||||||
|
CLI11_PARSE(app, argc, argv);
|
||||||
|
|
||||||
|
BF_Util::initLogger();
|
||||||
|
BF_Util::setLogLevel(spdlog::level::debug);
|
||||||
|
|
||||||
|
// 测试参数,这里直接返回。
|
||||||
|
// for (const auto& task : tasks) {
|
||||||
|
// gLogger->info("任务:{}", task);
|
||||||
|
// }
|
||||||
|
// return 0;
|
||||||
|
|
||||||
|
BF_Interface* request = new BF_Request();
|
||||||
|
std::shared_ptr<void> del(nullptr, [request](void*) { delete request; });
|
||||||
|
|
||||||
|
std::shared_ptr<BF_Config> bc = std::make_shared<BF_Config>();
|
||||||
|
if (!bc->parseConfig(config)) {
|
||||||
|
gLogger->error("解析配置文件失败!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
request->setConfig(bc);
|
||||||
|
|
||||||
|
if (testRequest) {
|
||||||
|
gLogger->info("测试请求开始...");
|
||||||
|
gLogger->info("测试内容:[你好,世界。] from auto to en.");
|
||||||
|
std::string readyData = request->doReady("你好,世界。", from, to);
|
||||||
|
std::string data = fmt::format("{}{}", bc->baseUrl, readyData);
|
||||||
|
std::string result = request->getResult(data);
|
||||||
|
gLogger->info("测试请求结束!");
|
||||||
|
gLogger->info("结果:[{}]", result);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::workbook wb;
|
||||||
|
xlnt::worksheet ws;
|
||||||
|
try {
|
||||||
|
wb.load("");
|
||||||
|
ws = wb.sheet_by_title(sheetName);
|
||||||
|
std::vector<XlsxTask> tasks;
|
||||||
|
for (auto& task : tasks) {
|
||||||
|
for (int i = task.startRow; i <= task.endRow; i++) {
|
||||||
|
for (int j = task.startCol; j <= task.endCol; j++) {
|
||||||
|
xlnt::cell cell = ws.cell(i, j);
|
||||||
|
std::string text = cell.value<std::string>();
|
||||||
|
if (text.empty()) {
|
||||||
|
gLogger->error("数据为空,跳过:[{}][{}]", i, j);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto readyData = request->doReady(text, from, to);
|
||||||
|
if (readyData.empty()) {
|
||||||
|
gLogger->error("doReady数据为空,跳过:[{}][{}][{}]", i, j, text);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto data = fmt::format("{}{}", bc->baseUrl, readyData);
|
||||||
|
std::string result = request->getResult(data);
|
||||||
|
if (result.empty()) {
|
||||||
|
gLogger->error("getResult数据为空,跳过:[{}][{}][{}]", i, j, text);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gLogger->info("翻译成功:[{}][{}][{}][{}]", i, j, text, result);
|
||||||
|
cell.value(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
gLogger->error(e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
wb.save(fmt::format("{}_out.xlsx", workbook));
|
||||||
|
gLogger->info("结束!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user