基本通信测试通过。
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