DevTools Papago Translate

This commit is contained in:
Blu3train 2021-05-15 11:07:22 +02:00
parent 1782292662
commit 76d716956d
3 changed files with 180 additions and 0 deletions

View File

@ -45,6 +45,7 @@ foreach ($language in @{
"Copy to Clipboard", "Copy to Clipboard",
"DeepL Translate", "DeepL Translate",
"DevTools DeepL Translate", "DevTools DeepL Translate",
"DevTools Papago Translate",
"Extra Newlines", "Extra Newlines",
"Extra Window", "Extra Window",
"Google Translate", "Google Translate",

View File

@ -7,6 +7,7 @@ add_library(Bing\ Translate MODULE bingtranslate.cpp translatewrapper.cpp networ
add_library(Copy\ to\ Clipboard MODULE copyclipboard.cpp extensionimpl.cpp) add_library(Copy\ to\ Clipboard MODULE copyclipboard.cpp extensionimpl.cpp)
add_library(DeepL\ Translate MODULE deepltranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp) add_library(DeepL\ Translate MODULE deepltranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
add_library(DevTools\ DeepL\ Translate MODULE devtoolsdeepltranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp) add_library(DevTools\ DeepL\ Translate MODULE devtoolsdeepltranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
add_library(DevTools\ Papago\ Translate MODULE devtoolspapagotranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
add_library(Extra\ Newlines MODULE extranewlines.cpp extensionimpl.cpp) add_library(Extra\ Newlines MODULE extranewlines.cpp extensionimpl.cpp)
add_library(Extra\ Window MODULE extrawindow.cpp extensionimpl.cpp) add_library(Extra\ Window MODULE extrawindow.cpp extensionimpl.cpp)
add_library(Google\ Translate MODULE googletranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp) add_library(Google\ Translate MODULE googletranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
@ -24,6 +25,7 @@ target_precompile_headers(Bing\ Translate REUSE_FROM pch)
target_precompile_headers(Copy\ to\ Clipboard REUSE_FROM pch) target_precompile_headers(Copy\ to\ Clipboard REUSE_FROM pch)
target_precompile_headers(DeepL\ Translate REUSE_FROM pch) target_precompile_headers(DeepL\ Translate REUSE_FROM pch)
target_precompile_headers(DevTools\ DeepL\ Translate REUSE_FROM pch) target_precompile_headers(DevTools\ DeepL\ Translate REUSE_FROM pch)
target_precompile_headers(DevTools\ Papago\ Translate REUSE_FROM pch)
target_precompile_headers(Extra\ Newlines REUSE_FROM pch) target_precompile_headers(Extra\ Newlines REUSE_FROM pch)
target_precompile_headers(Extra\ Window REUSE_FROM pch) target_precompile_headers(Extra\ Window REUSE_FROM pch)
target_precompile_headers(Google\ Translate REUSE_FROM pch) target_precompile_headers(Google\ Translate REUSE_FROM pch)
@ -40,6 +42,7 @@ target_precompile_headers(Thread\ Linker REUSE_FROM pch)
target_link_libraries(Bing\ Translate winhttp Qt5::Widgets) target_link_libraries(Bing\ Translate winhttp Qt5::Widgets)
target_link_libraries(DeepL\ Translate winhttp Qt5::Widgets) target_link_libraries(DeepL\ Translate winhttp Qt5::Widgets)
target_link_libraries(DevTools\ DeepL\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets) target_link_libraries(DevTools\ DeepL\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
target_link_libraries(DevTools\ Papago\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
target_link_libraries(Extra\ Window Qt5::Widgets) target_link_libraries(Extra\ Window Qt5::Widgets)
target_link_libraries(Google\ Translate winhttp Qt5::Widgets) target_link_libraries(Google\ Translate winhttp Qt5::Widgets)
target_link_libraries(Lua lua53 Qt5::Widgets) target_link_libraries(Lua lua53 Qt5::Widgets)
@ -56,4 +59,10 @@ if (NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5WebSockets.dll AND NOT EXISTS
COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin
COMMAND Qt5::windeployqt --dir ${CMAKE_FINAL_OUTPUT_DIRECTORY} "${CMAKE_FINAL_OUTPUT_DIRECTORY}/DevTools\ DeepL\ Translate.dll" COMMAND Qt5::windeployqt --dir ${CMAKE_FINAL_OUTPUT_DIRECTORY} "${CMAKE_FINAL_OUTPUT_DIRECTORY}/DevTools\ DeepL\ Translate.dll"
) )
add_custom_command(TARGET DevTools\ Papago\ Translate
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/windeployqt"
COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin
COMMAND Qt5::windeployqt --dir ${CMAKE_FINAL_OUTPUT_DIRECTORY} "${CMAKE_FINAL_OUTPUT_DIRECTORY}/DevTools\ Papago\ Translate.dll"
)
endif() endif()

View File

@ -0,0 +1,170 @@
#include "qtcommon.h"
#include "devtools.h"
#include <QFileDialog>
#include <QMouseEvent>
#include <ShlObj.h>
extern const wchar_t* TRANSLATION_ERROR;
extern const char* CHROME_LOCATION;
extern const char* START_DEVTOOLS;
extern const char* STOP_DEVTOOLS;
extern const char* HEADLESS_MODE;
extern const char* DEVTOOLS_STATUS;
extern const char* AUTO_START;
extern const wchar_t* ERROR_START_CHROME;
extern Synchronized<std::wstring> translateTo, translateFrom;
extern QFormLayout* display;
extern Settings settings;
const char* TRANSLATION_PROVIDER = "DevTools Papago Translate";
const char* GET_API_KEY_FROM = nullptr;
bool translateSelectedOnly = true, rateLimitAll = false, rateLimitSelected = false, useCache = true, useFilter = true;
int tokenCount = 30, tokenRestoreDelay = 60000, maxSentenceSize = 2500;
QStringList languages
{
"Chinese (Simplified): zh-CN",
"Chinese (traditional): zt-TW",
"English: en",
"French: fr",
"German: de",
"Hindi: hi",
"Indonesian: id",
"Italian: it",
"Japanese: ja",
"Korean: ko",
"Portuguese: pt",
"Russian: ru",
"Spanish: es",
"Thai: th",
"Vietnamese: vi",
};
std::wstring autoDetectLanguage = L"auto";
QStringList languagesTo
{
"Chinese (Simplified): zh-CN",
"Chinese (traditional): zt-TW",
"English: en",
"French: fr",
"German: de",
"Hindi: hi",
"Indonesian: id",
"Italian: it",
"Japanese: ja",
"Korean: ko",
"Portuguese: pt",
"Russian: ru",
"Spanish: es",
"Thai: th",
"Vietnamese: vi",
};
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
QString chromePath = settings.value(CHROME_LOCATION).toString();
wchar_t programFiles[MAX_PATH + 100] = {};
if (chromePath.isEmpty()) for (auto folder : { CSIDL_PROGRAM_FILESX86, CSIDL_PROGRAM_FILES, CSIDL_LOCAL_APPDATA })
{
SHGetFolderPathW(NULL, folder, NULL, SHGFP_TYPE_CURRENT, programFiles);
wcscat_s(programFiles, L"/Google/Chrome/Application/chrome.exe");
if (std::filesystem::exists(programFiles)) chromePath = S(programFiles);
}
auto chromePathEdit = new QLineEdit(chromePath);
static struct : QObject
{
bool eventFilter(QObject* object, QEvent* event)
{
if (auto mouseEvent = dynamic_cast<QMouseEvent*>(event))
if (mouseEvent->button() == Qt::LeftButton)
if (QString chromePath = QFileDialog::getOpenFileName(nullptr, TRANSLATION_PROVIDER, "/", "Chrome (*.exe)"); !chromePath.isEmpty())
((QLineEdit*)object)->setText(chromePath);
return false;
}
} chromeSelector;
chromePathEdit->installEventFilter(&chromeSelector);
QObject::connect(chromePathEdit, &QLineEdit::textChanged, [chromePathEdit](QString path) { settings.setValue(CHROME_LOCATION, path); });
display->addRow(CHROME_LOCATION, chromePathEdit);
auto statusLabel = new QLabel("Stopped");
auto startButton = new QPushButton(START_DEVTOOLS), stopButton = new QPushButton(STOP_DEVTOOLS);
auto headlessCheck = new QCheckBox();
headlessCheck->setChecked(settings.value(HEADLESS_MODE, true).toBool());
QObject::connect(headlessCheck, &QCheckBox::clicked, [](bool headless) { settings.setValue(HEADLESS_MODE, headless); });
QObject::connect(startButton, &QPushButton::clicked, [statusLabel, chromePathEdit, headlessCheck]
{
DevTools::Start(
S(chromePathEdit->text()),
[statusLabel](QString status)
{
QMetaObject::invokeMethod(statusLabel, std::bind(&QLabel::setText, statusLabel, status));
if (status == "ConnectedState") std::thread([]
{
if (HttpRequest httpRequest{
L"Mozilla/5.0 Textractor",
L"127.0.0.1",
L"POST",
L"/json/version",
"",
NULL,
9222,
NULL,
WINHTTP_FLAG_ESCAPE_DISABLE
})
if (auto userAgent = Copy(JSON::Parse(httpRequest.response)[L"User-Agent"].String()))
if (userAgent->find(L"Headless") != std::string::npos)
DevTools::SendRequest(
"Network.setUserAgentOverride",
FormatString(LR"({"userAgent":"%s"})", userAgent->replace(userAgent->find(L"Headless"), 8, L""))
);
}).detach();
},
headlessCheck->isChecked()
);
});
QObject::connect(stopButton, &QPushButton::clicked, &DevTools::Close);
auto buttons = new QHBoxLayout();
buttons->addWidget(startButton);
buttons->addWidget(stopButton);
display->addRow(HEADLESS_MODE, headlessCheck);
auto autoStartCheck = new QCheckBox();
autoStartCheck->setChecked(settings.value(AUTO_START, false).toBool());
QObject::connect(autoStartCheck, &QCheckBox::clicked, [](bool autoStart) { settings.setValue(AUTO_START, autoStart); });
display->addRow(AUTO_START, autoStartCheck);
display->addRow(buttons);
statusLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
display->addRow(DEVTOOLS_STATUS, statusLabel);
if (autoStartCheck->isChecked()) QMetaObject::invokeMethod(startButton, &QPushButton::click, Qt::QueuedConnection);
}
break;
case DLL_PROCESS_DETACH:
{
DevTools::Close();
}
break;
}
return TRUE;
}
std::pair<bool, std::wstring> Translate(const std::wstring& text)
{
if (!DevTools::Connected()) return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, ERROR_START_CHROME) };
// DevTools can't handle concurrent translations yet
static std::mutex translationMutex;
std::scoped_lock lock(translationMutex);
DevTools::SendRequest("Page.navigate", FormatString(LR"({"url":"https://papago.naver.com/?sk=%s&tk=%s&st=%s"})", translateFrom.Copy(), translateTo.Copy(), Escape(text)));
for (int retry = 0; ++retry < 100; Sleep(100))
if (auto translation = Copy(DevTools::SendRequest("Runtime.evaluate",
LR"({"expression":"document.querySelector('#txtTarget').textContent.trim() ","returnByValue":true})"
)[L"result"][L"value"].String())) if (!translation->empty()) return { true, translation.value() };
if (auto errorMessage = Copy(DevTools::SendRequest("Runtime.evaluate",
LR"({"expression":"document.querySelector('div.lmt__system_notification').innerHTML","returnByValue":true})"
)[L"result"][L"value"].String())) return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, errorMessage.value()) };
return { false, TRANSLATION_ERROR };
}