3 Commits

Author SHA1 Message Date
aa5ad064a8 feat: 添加微软翻译接口 2026-01-23 22:51:00 +08:00
36bd572e38 fix: 更新百度翻译接口;一些小修改 2026-01-23 22:50:42 +08:00
2b8f30b72d feat: 更新依赖 2026-01-23 22:40:05 +08:00
14 changed files with 201 additions and 78 deletions

38
pom.xml
View File

@ -30,15 +30,16 @@
<junit.version>5.11.0</junit.version> <junit.version>5.11.0</junit.version>
<javafx.version>21.0.4</javafx.version> <javafx.version>21.0.4</javafx.version>
<slf4j.version>2.0.16</slf4j.version> <slf4j.version>2.0.17</slf4j.version>
<logback.version>1.5.7</logback.version> <logback.version>1.5.25</logback.version>
<fastjson.version>2.0.52</fastjson.version> <fastjson.version>2.0.52</fastjson.version>
<common-lang3.version>3.16.0</common-lang3.version> <common-lang3.version>3.20.0</common-lang3.version>
<common-io.version>2.17.0</common-io.version> <common-io.version>2.21.0</common-io.version>
<common-exec.version>1.4.0</common-exec.version> <common-exec.version>1.6.0</common-exec.version>
<lombok.version>1.18.32</lombok.version> <lombok.version>1.18.42</lombok.version>
<jackson.version>2.15.4</jackson.version> <jackson.version>3.0.3</jackson.version>
<ikonli.version>12.3.1</ikonli.version> <ikonli.version>12.4.0</ikonli.version>
<jjwt.version>0.13.0</jjwt.version>
</properties> </properties>
<dependencies> <dependencies>
@ -66,11 +67,13 @@
<version>2.0.1</version> <version>2.0.1</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version> <version>${slf4j.version}</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId> <artifactId>logback-classic</artifactId>
@ -124,10 +127,12 @@
</dependency> </dependency>
<!-- jackson --> <!-- jackson -->
<!-- Source: https://mvnrepository.com/artifact/tools.jackson.dataformat/jackson-dataformat-yaml -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId> <groupId>tools.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId> <artifactId>jackson-dataformat-yaml</artifactId>
<version>${jackson.version}</version> <version>${jackson.version}</version>
<scope>compile</scope>
</dependency> </dependency>
<!-- Hutool --> <!-- Hutool -->
@ -135,7 +140,7 @@
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId> <artifactId>hutool-core</artifactId>
<version>5.8.34</version> <version>5.8.43</version>
</dependency> </dependency>
<!-- https://kordamp.org/ikonli/ --> <!-- https://kordamp.org/ikonli/ -->
@ -151,6 +156,19 @@
<groupId>org.kordamp.ikonli</groupId> <groupId>org.kordamp.ikonli</groupId>
<artifactId>ikonli-feather-pack</artifactId> <artifactId>ikonli-feather-pack</artifactId>
</dependency> </dependency>
<!-- jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies> </dependencies>
<dependencyManagement> <dependencyManagement>

View File

@ -12,14 +12,15 @@ import cn.octopusyan.dmt.model.Translate;
import cn.octopusyan.dmt.model.UpgradeConfig; import cn.octopusyan.dmt.model.UpgradeConfig;
import cn.octopusyan.dmt.translate.TranslateApi; import cn.octopusyan.dmt.translate.TranslateApi;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import javafx.application.Platform; import javafx.application.Platform;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import tools.jackson.core.JacksonException;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.dataformat.yaml.YAMLMapper;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -38,7 +39,12 @@ import java.util.stream.Collectors;
*/ */
public class ConfigManager { public class ConfigManager {
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class); private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
public static ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
private static final ObjectMapper objectMapper = YAMLMapper.builder()
//对象的所有字段全部列入序列化
.changeDefaultPropertyInclusion(incl -> incl.withValueInclusion(JsonInclude.Include.NON_NULL))
.changeDefaultPropertyInclusion(incl -> incl.withContentInclusion(JsonInclude.Include.NON_NULL))
.build();
public static final UpgradeConfig upgradeConfig = new UpgradeConfig(); public static final UpgradeConfig upgradeConfig = new UpgradeConfig();
public static final String DEFAULT_THEME = new PrimerLight().getName(); public static final String DEFAULT_THEME = new PrimerLight().getName();
@ -53,11 +59,6 @@ public class ConfigManager {
private static ConfigModel configModel; private static ConfigModel configModel;
static {
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
}
public static void load() { public static void load() {
configModel = loadConfig(Constants.CONFIG_FILE_PATH, ConfigModel.class); configModel = loadConfig(Constants.CONFIG_FILE_PATH, ConfigModel.class);
if (configModel == null) if (configModel == null)
@ -89,7 +90,7 @@ public class ConfigManager {
public static void save() { public static void save() {
try { try {
objectMapper.writeValue(new File(Constants.CONFIG_FILE_PATH), configModel); objectMapper.writeValue(new File(Constants.CONFIG_FILE_PATH), configModel);
} catch (IOException e) { } catch (JacksonException e) {
logger.error("save config error", e); logger.error("save config error", e);
} }
} }

View File

@ -4,7 +4,7 @@ import cn.octopusyan.dmt.common.enums.ProxySetup;
import cn.octopusyan.dmt.common.manager.http.response.DownloadBodyHandler; import cn.octopusyan.dmt.common.manager.http.response.DownloadBodyHandler;
import cn.octopusyan.dmt.common.util.JsonUtil; import cn.octopusyan.dmt.common.util.JsonUtil;
import cn.octopusyan.dmt.model.ProxyInfo; import cn.octopusyan.dmt.model.ProxyInfo;
import com.fasterxml.jackson.databind.JsonNode; import tools.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.io.File; import java.io.File;
@ -111,8 +111,15 @@ public class HttpUtil {
} }
public String postForm(String uri, JsonNode header, JsonNode param) throws IOException, InterruptedException { public String postForm(String uri, JsonNode header, JsonNode param) throws IOException, InterruptedException {
return postForm(uri, header, param, null);
}
public String postForm(String uri, JsonNode header, JsonNode param, JsonNode body) throws IOException, InterruptedException {
HttpRequest.Builder request = getRequest(uri + createFormParams(param), header) HttpRequest.Builder request = getRequest(uri + createFormParams(param), header)
.POST(HttpRequest.BodyPublishers.noBody()); .POST(body == null ?
HttpRequest.BodyPublishers.noBody() :
HttpRequest.BodyPublishers.ofString(JsonUtil.toJsonString(body))
);
HttpResponse<String> response = httpClient.send(request.build(), HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); HttpResponse<String> response = httpClient.send(request.build(), HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
return response.body(); return response.body();
@ -172,8 +179,8 @@ public class HttpUtil {
for (Map.Entry<String, JsonNode> property : params.properties()) { for (Map.Entry<String, JsonNode> property : params.properties()) {
String key = property.getKey(); String key = property.getKey();
JsonNode value = params.get(key); JsonNode value = params.get(key);
if (value.isTextual()) { if (value.isString()) {
String value_ = URLEncoder.encode(String.valueOf(value.asText()), StandardCharsets.UTF_8); String value_ = URLEncoder.encode(String.valueOf(value.asString()), StandardCharsets.UTF_8);
formParams.append("&").append(key).append("=").append(value_); formParams.append("&").append(key).append("=").append(value_);
} else if (value.isNumber()) { } else if (value.isNumber()) {
formParams.append("&").append(key).append("=").append(value); formParams.append("&").append(key).append("=").append(value);

View File

@ -1,18 +1,20 @@
package cn.octopusyan.dmt.common.util; package cn.octopusyan.dmt.common.util;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import tools.jackson.core.JacksonException;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.SerializationFeature;
import tools.jackson.databind.cfg.DateTimeFeature;
import tools.jackson.databind.json.JsonMapper;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.TimeZone;
/** /**
* Jackson 封装工具类 * Jackson 封装工具类
@ -21,25 +23,26 @@ import java.text.SimpleDateFormat;
*/ */
public class JsonUtil { public class JsonUtil {
private static final Logger log = LoggerFactory.getLogger(JsonUtil.class); private static final Logger log = LoggerFactory.getLogger(JsonUtil.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
/** /**
* 时间日期格式 * 时间日期格式
*/ */
private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss"; private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
static { private static final ObjectMapper objectMapper = JsonMapper.builder()
//对象的所有字段全部列入序列化 //对象的所有字段全部列入序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); .changeDefaultPropertyInclusion(incl -> incl.withValueInclusion(JsonInclude.Include.NON_NULL))
//取消默认转换timestamps形式 .changeDefaultPropertyInclusion(incl -> incl.withContentInclusion(JsonInclude.Include.NON_NULL))
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); //取消默认转换timestamps形式
//忽略空Bean转json的错误 .disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); //忽略空Bean转json的错误
//所有的日期格式都统一为以下的格式即yyyy-MM-dd HH:mm:ss .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
objectMapper.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT)); //忽略 在json字符串中存在但在java对象中不存在对应属性的情况。防止错误
//忽略 在json字符串中存在但在java对象中不存在对应属性的情况。防止错误 .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); //所有的日期格式都统一为以下的格式即yyyy-MM-dd HH:mm:ss
} .defaultDateFormat(new SimpleDateFormat(STANDARD_FORMAT))
.defaultTimeZone(TimeZone.getDefault())
.build();
/** /**
* Json字符串 转 JavaBean * Json字符串 转 JavaBean
@ -53,7 +56,7 @@ public class JsonUtil {
T t = null; T t = null;
try { try {
t = objectMapper.readValue(jsonString, clazz); t = objectMapper.readValue(jsonString, clazz);
} catch (JsonProcessingException e) { } catch (JacksonException e) {
log.error("失败:{}", e.getMessage()); log.error("失败:{}", e.getMessage());
} }
return t; return t;
@ -71,7 +74,7 @@ public class JsonUtil {
T t = null; T t = null;
try { try {
t = objectMapper.readValue(file, clazz); t = objectMapper.readValue(file, clazz);
} catch (IOException e) { } catch (JacksonException e) {
log.error("失败:{}", e.getMessage()); log.error("失败:{}", e.getMessage());
} }
return t; return t;
@ -89,7 +92,7 @@ public class JsonUtil {
T t = null; T t = null;
try { try {
t = objectMapper.readValue(jsonArray, reference); t = objectMapper.readValue(jsonArray, reference);
} catch (JsonProcessingException e) { } catch (JacksonException e) {
log.error("失败:{}", e.getMessage()); log.error("失败:{}", e.getMessage());
} }
return t; return t;
@ -106,7 +109,7 @@ public class JsonUtil {
String jsonString = null; String jsonString = null;
try { try {
jsonString = objectMapper.writeValueAsString(object); jsonString = objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) { } catch (JacksonException e) {
log.error("失败:{}", e.getMessage()); log.error("失败:{}", e.getMessage());
} }
return jsonString; return jsonString;
@ -122,7 +125,7 @@ public class JsonUtil {
byte[] bytes = null; byte[] bytes = null;
try { try {
bytes = objectMapper.writeValueAsBytes(object); bytes = objectMapper.writeValueAsBytes(object);
} catch (JsonProcessingException e) { } catch (JacksonException e) {
log.error("失败:{}", e.getMessage()); log.error("失败:{}", e.getMessage());
} }
return bytes; return bytes;
@ -137,7 +140,7 @@ public class JsonUtil {
public static void objectToFile(File file, Object object) { public static void objectToFile(File file, Object object) {
try { try {
objectMapper.writeValue(file, object); objectMapper.writeValue(file, object);
} catch (Exception e) { } catch (JacksonException e) {
log.error("失败:{}", e.getMessage()); log.error("失败:{}", e.getMessage());
} }
} }
@ -153,7 +156,7 @@ public class JsonUtil {
JsonNode jsonNode = null; JsonNode jsonNode = null;
try { try {
jsonNode = objectMapper.readTree(jsonString); jsonNode = objectMapper.readTree(jsonString);
} catch (JsonProcessingException e) { } catch (JacksonException e) {
log.error("失败:{}", e.getMessage()); log.error("失败:{}", e.getMessage());
} }
return jsonNode; return jsonNode;
@ -179,7 +182,7 @@ public class JsonUtil {
String jsonString = null; String jsonString = null;
try { try {
jsonString = objectMapper.writeValueAsString(jsonNode); jsonString = objectMapper.writeValueAsString(jsonNode);
} catch (JsonProcessingException e) { } catch (JacksonException e) {
log.error("失败:{}", e.getMessage()); log.error("失败:{}", e.getMessage());
} }
return jsonString; return jsonString;

View File

@ -6,8 +6,8 @@ import cn.octopusyan.dmt.common.util.JsonUtil;
import cn.octopusyan.dmt.model.UpgradeConfig; import cn.octopusyan.dmt.model.UpgradeConfig;
import cn.octopusyan.dmt.task.base.BaseTask; import cn.octopusyan.dmt.task.base.BaseTask;
import cn.octopusyan.dmt.task.listener.DefaultTaskListener; import cn.octopusyan.dmt.task.listener.DefaultTaskListener;
import com.fasterxml.jackson.databind.JsonNode; import org.apache.commons.lang3.Strings;
import org.apache.commons.lang3.StringUtils; import tools.jackson.databind.JsonNode;
/** /**
* 检查更新任务 * 检查更新任务
@ -28,10 +28,10 @@ public class UpgradeTask extends BaseTask<UpgradeTask.UpgradeListener> {
JsonNode response = JsonUtil.parseJsonObject(responseStr); JsonNode response = JsonUtil.parseJsonObject(responseStr);
// TODO 校验返回内容 // TODO 校验返回内容
String newVersion = response.get("tag_name").asText(); String newVersion = response.get("tag_name").asString();
if (listener != null) if (listener != null)
listener.onChecked(!StringUtils.equals(upgradeConfig.getVersion(), newVersion), newVersion); listener.onChecked(!Strings.CS.equals(upgradeConfig.getVersion(), newVersion), newVersion);
} }
/** /**

View File

@ -12,6 +12,7 @@ import lombok.Getter;
public enum TranslateApi { public enum TranslateApi {
FREE_BAIDU("free_baidu", "百度", false), FREE_BAIDU("free_baidu", "百度", false),
FREE_GOOGLE("free_google", "谷歌", false), FREE_GOOGLE("free_google", "谷歌", false),
FREE_MICROSOFT("free_microsoft", "微软", false),
BAIDU("baidu", "百度(需认证)", true), BAIDU("baidu", "百度(需认证)", true),
; ;

View File

@ -3,10 +3,7 @@ package cn.octopusyan.dmt.translate.factory;
import cn.octopusyan.dmt.model.WordItem; import cn.octopusyan.dmt.model.WordItem;
import cn.octopusyan.dmt.translate.DelayWord; import cn.octopusyan.dmt.translate.DelayWord;
import cn.octopusyan.dmt.translate.TranslateApi; import cn.octopusyan.dmt.translate.TranslateApi;
import cn.octopusyan.dmt.translate.processor.AbstractTranslateProcessor; import cn.octopusyan.dmt.translate.processor.*;
import cn.octopusyan.dmt.translate.processor.BaiduTranslateProcessor;
import cn.octopusyan.dmt.translate.processor.FreeBaiduTranslateProcessor;
import cn.octopusyan.dmt.translate.processor.FreeGoogleTranslateProcessor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.util.*; import java.util.*;
@ -38,6 +35,7 @@ public class TranslateFactoryImpl implements TranslateFactory {
private void initProcessor() { private void initProcessor() {
processorList.addAll(Arrays.asList( processorList.addAll(Arrays.asList(
new FreeGoogleTranslateProcessor(), new FreeGoogleTranslateProcessor(),
new FreeMicrosoftTranslateProcessor(),
new FreeBaiduTranslateProcessor(), new FreeBaiduTranslateProcessor(),
new BaiduTranslateProcessor() new BaiduTranslateProcessor()
)); ));

View File

@ -3,7 +3,7 @@ package cn.octopusyan.dmt.translate.processor;
import cn.octopusyan.dmt.common.util.JsonUtil; import cn.octopusyan.dmt.common.util.JsonUtil;
import cn.octopusyan.dmt.translate.ApiKey; import cn.octopusyan.dmt.translate.ApiKey;
import cn.octopusyan.dmt.translate.TranslateApi; import cn.octopusyan.dmt.translate.TranslateApi;
import com.fasterxml.jackson.databind.JsonNode; import tools.jackson.databind.JsonNode;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -59,7 +59,7 @@ public class BaiduTranslateProcessor extends AbstractTranslateProcessor {
throw new RuntimeException(String.valueOf(errorMsg)); throw new RuntimeException(String.valueOf(errorMsg));
} }
return json.get("trans_result").get(0).get("dst").asText(); return json.get("trans_result").get(0).get("dst").asString();
} }
private String getSign(String appid, String q, String salt) { private String getSign(String appid, String q, String salt) {

View File

@ -3,7 +3,7 @@ package cn.octopusyan.dmt.translate.processor;
import cn.octopusyan.dmt.common.manager.http.CookieManager; import cn.octopusyan.dmt.common.manager.http.CookieManager;
import cn.octopusyan.dmt.common.util.JsonUtil; import cn.octopusyan.dmt.common.util.JsonUtil;
import cn.octopusyan.dmt.translate.TranslateApi; import cn.octopusyan.dmt.translate.TranslateApi;
import com.fasterxml.jackson.databind.JsonNode; import tools.jackson.databind.JsonNode;
import java.io.IOException; import java.io.IOException;
import java.net.HttpCookie; import java.net.HttpCookie;
@ -23,6 +23,7 @@ public class FreeBaiduTranslateProcessor extends AbstractTranslateProcessor {
static { static {
header.put("Origin", "https://fanyi.baidu.com"); header.put("Origin", "https://fanyi.baidu.com");
header.put("acs-token", "");
header.put("Referer", "https://fanyi.baidu.com"); header.put("Referer", "https://fanyi.baidu.com");
header.put("User-Agent", "Apifox/1.0.0 (https://apifox.com)"); header.put("User-Agent", "Apifox/1.0.0 (https://apifox.com)");
header.put("Accept","*/*"); header.put("Accept","*/*");
@ -56,7 +57,7 @@ public class FreeBaiduTranslateProcessor extends AbstractTranslateProcessor {
JsonNode json = JsonUtil.parseJsonObject(resp); JsonNode json = JsonUtil.parseJsonObject(resp);
if (!json.has("data")) { if (!json.has("data")) {
String errorMsg = json.get("errmsg").asText(); String errorMsg = json.get("errmsg").asString();
if("访问出现异常,请刷新后重试!".equals(errorMsg) && !header.containsKey("Cookie")) { if("访问出现异常,请刷新后重试!".equals(errorMsg) && !header.containsKey("Cookie")) {
checkCookie(); checkCookie();
return customTranslate(source); return customTranslate(source);
@ -64,14 +65,12 @@ public class FreeBaiduTranslateProcessor extends AbstractTranslateProcessor {
throw new RuntimeException(errorMsg); throw new RuntimeException(errorMsg);
} }
return json.get("data").get(0).get("dst").asText(); return json.get("data").get(0).get("dst").asString();
} }
private void checkCookie() throws IOException, InterruptedException { private void checkCookie() throws IOException, InterruptedException {
// 短时大量请求会被ban需要添加验证cookie // 短时大量请求会被ban需要添加验证cookie
if (header.containsKey("Cookie")) return;
List<HttpCookie> cookieList = CookieManager.getStore().get(URI.create("https://baidu.com")); List<HttpCookie> cookieList = CookieManager.getStore().get(URI.create("https://baidu.com"));
boolean noneMatch = cookieList.stream() boolean noneMatch = cookieList.stream()
.filter(cookie -> "ab_sr".equals(cookie.getName()) || "BAIDUID".equals(cookie.getName())) .filter(cookie -> "ab_sr".equals(cookie.getName()) || "BAIDUID".equals(cookie.getName()))

View File

@ -3,7 +3,7 @@ package cn.octopusyan.dmt.translate.processor;
import cn.octopusyan.dmt.common.util.JsonUtil; import cn.octopusyan.dmt.common.util.JsonUtil;
import cn.octopusyan.dmt.translate.TranslateApi; import cn.octopusyan.dmt.translate.TranslateApi;
import com.fasterxml.jackson.databind.JsonNode; import tools.jackson.databind.JsonNode;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
@ -34,22 +34,28 @@ public class FreeGoogleTranslateProcessor extends AbstractTranslateProcessor {
@Override @Override
public String customTranslate(String source) throws IOException, InterruptedException { public String customTranslate(String source) throws IOException, InterruptedException {
Map<String, Object> header = new HashMap<>();
header.put("User-Agent", "Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0");
header.put("Referer", "https://translate.google.com/");
header.put("Host", "translate.googleapis.com");
Map<String, Object> form = new HashMap<>(); Map<String, Object> form = new HashMap<>();
form.put("client", "gtx"); form.put("client", "gtx");
form.put("dt", "t"); form.put("dt", "t");
form.put("sl", "auto"); form.put("sl", "auto");
form.put("tl", "zh-CN"); form.put("tl", "zh-CN");
form.put("q", source);
Map<String, Object> header = new HashMap<>(); Map<String, Object> body = new HashMap<>();
body.put("q", source);
StringBuilder retStr = new StringBuilder(); StringBuilder retStr = new StringBuilder();
// TODO 短时大量请求会被ban需要浏览器验证添加cookie // TODO 短时大量请求会被ban需要浏览器验证添加cookie
String resp = httpUtil.get(url(), JsonUtil.parseJsonObject(header), JsonUtil.parseJsonObject(form)); String resp = httpUtil.postForm(url(), JsonUtil.parseJsonObject(header), JsonUtil.parseJsonObject(form), JsonUtil.parseJsonObject(body));
JsonNode json = JsonUtil.parseJsonObject(resp); JsonNode json = JsonUtil.parseJsonObject(resp);
for (JsonNode o : json.get(0)) { for (JsonNode o : json.get(0)) {
retStr.append(o.get(0).asText()); retStr.append(o.get(0).asString());
} }
return retStr.toString(); return retStr.toString();

View File

@ -0,0 +1,89 @@
package cn.octopusyan.dmt.translate.processor;
import cn.hutool.core.date.DateUtil;
import cn.octopusyan.dmt.common.util.JsonUtil;
import cn.octopusyan.dmt.translate.TranslateApi;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import tools.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 微软 免费翻译接口
*
* @author octopus_yan@foxmail.com
*/
public class FreeMicrosoftTranslateProcessor extends AbstractTranslateProcessor {
private String token;
public FreeMicrosoftTranslateProcessor() {
super(TranslateApi.FREE_MICROSOFT);
}
@Override
public String url() {
return "https://api.cognitive.microsofttranslator.com/translate";
}
/**
* 翻译处理
*
* @param source 待翻译单词
* @return 翻译结果
*/
@Override
public String customTranslate(String source) throws IOException, InterruptedException {
Map<String, Object> form = new HashMap<>();
form.put("api-version", "3.0");
form.put("to", "zh-Hans");
form.put("textType", "plain");
Map<String, Object> header = new HashMap<>();
header.put("Authorization", STR."Bearer \{oauth()}");
String body = STR."""
[
{
"Text": "\{source}"
}
]
""";
StringBuilder retStr = new StringBuilder();
String resp = httpUtil.postForm(url(), JsonUtil.parseJsonObject(header), JsonUtil.parseJsonObject(form), JsonUtil.parseJsonObject(body));
JsonNode json = JsonUtil.parseJsonObject(resp);
for (JsonNode o : json.get(0)) {
retStr.append(o.get(0).asString());
}
return retStr.toString();
}
private synchronized String oauth() throws IOException, InterruptedException {
if (token == null) {
token = httpUtil.get("https://edge.microsoft.com/translate/auth", null, null);
} else {
// 解析,对应的签名或者加密方式
Claims claims = Jwts.parser()
// .verifyWith(key) // 指定用于验证的密钥
// .decryptWith(key) // 加密方式,指定用于解密的密钥。
.build()
.parseSignedClaims(token) // 签名方式
// .parseEncryptedClaims(token) // 加密方式,对 JWT 进行解密,并获取其声明部分。
.getPayload(); // 获取解密后的声明claims内容。
if(DateUtil.compare(DateUtil.date(), claims.getExpiration()) > 0) {
token = null;
return oauth();
}
}
return token;
}
}

View File

@ -37,8 +37,8 @@ public class PBOUtil {
private static final ProcessesUtil processesUtil = ProcessesUtil.init(Constants.BIN_DIR_PATH); private static final ProcessesUtil processesUtil = ProcessesUtil.init(Constants.BIN_DIR_PATH);
private static final String UNPACK_COMMAND = STR."\"\{Constants.PBOC_FILE}\" unpack -o \"\{Constants.TMP_DIR_PATH}\" {}"; private static final String UNPACK_COMMAND = STR."\"\{Constants.PBOC_FILE}\" unpack {} -o \"\{Constants.TMP_DIR_PATH}\"";
private static final String PACK_COMMAND = STR."\"\{Constants.PBOC_FILE}\" pack -o {} {}"; private static final String PACK_COMMAND = STR."\"\{Constants.PBOC_FILE}\" pack {} -o {}";
private static final String CFG_COMMAND = STR."\"\{Constants.CFG_CONVERT_FILE}\" {} -dst {} {}"; private static final String CFG_COMMAND = STR."\"\{Constants.CFG_CONVERT_FILE}\" {} -dst {} {}";
private static final String FILE_NAME_STRING_TABLE = "stringtable.csv"; private static final String FILE_NAME_STRING_TABLE = "stringtable.csv";
@ -122,7 +122,7 @@ public class PBOUtil {
FileUtils.deleteQuietly(packFile); FileUtils.deleteQuietly(packFile);
} }
String command = ProcessesUtil.format(PACK_COMMAND, Constants.TMP_DIR_PATH, unpackPath); String command = ProcessesUtil.format(PACK_COMMAND, unpackPath, Constants.TMP_DIR_PATH);
consoleLog.debug(STR."pack command ==> [\{command}]"); consoleLog.debug(STR."pack command ==> [\{command}]");
boolean exec = processesUtil.exec(command); boolean exec = processesUtil.exec(command);

View File

@ -12,16 +12,17 @@ module cn.octopusyan.dmt {
requires static lombok; requires static lombok;
requires atlantafx.base; requires atlantafx.base;
requires com.fasterxml.jackson.annotation; requires com.fasterxml.jackson.annotation;
requires com.fasterxml.jackson.databind; requires tools.jackson.databind;
requires com.fasterxml.jackson.dataformat.yaml; requires tools.jackson.dataformat.yaml;
requires java.prefs; requires java.prefs;
requires org.kordamp.ikonli.javafx; requires org.kordamp.ikonli.javafx;
requires org.kordamp.ikonli.feather; requires org.kordamp.ikonli.feather;
requires java.management; requires java.management;
requires cn.hutool.core; requires cn.hutool.core;
requires jjwt.api;
exports cn.octopusyan.dmt; exports cn.octopusyan.dmt;
exports cn.octopusyan.dmt.model to com.fasterxml.jackson.databind; exports cn.octopusyan.dmt.model to tools.jackson.databind;
opens cn.octopusyan.dmt.model to javafx.base; opens cn.octopusyan.dmt.model to javafx.base;
opens cn.octopusyan.dmt.common.base to javafx.fxml; opens cn.octopusyan.dmt.common.base to javafx.fxml;
opens cn.octopusyan.dmt.controller to javafx.fxml; opens cn.octopusyan.dmt.controller to javafx.fxml;