diff --git a/README.md b/README.md index 8fe68eaeaf..af878b78f8 100644 --- a/README.md +++ b/README.md @@ -352,6 +352,11 @@ server: 不是的,进度检查器会累加此 IP 地址在特定种子上的下载进度。如果对方出现进度回退、断开更换端口重连、更换 PeerID、更换 Client name 重新下载时,下载器会认为这是一个新客户端,并从头开始计算下载数据(吸血者也使用此手段绕过吸血检查)。但对于 PBH 来说,只要对方 IP 地址未改变(或者处于特定区间内),并且下载的种子未更换的情况下,下载进度会持续增量累积,避免对方欺骗反吸血检查。例如一个文件大小是 1000MB,对方下载 102% 代表对方在这个 1000MB 大小的种子上,实际下载了 1020MB 的数据。 +### PBH 提示我的下载器 “连续多次登录失败” ,并暂停了该怎么办? + +您可以点击下载器的编辑按钮,然后直接点击确定保存。PBH 将会解除暂停状态并重新尝试登陆,此时会显示登陆失败的原因。请根据原因进行故障排查(例如:网络连接问题、WebUI +是否启用、用户名密码是否正确等) + ## Install4j PeerBanHelper 使用 [Install4j multi-platform installer builder](https://www.ej-technologies.com/products/install4j/overview.html) 打包多平台安装程序。感谢 ej-technolgies 的开放源代码许可证。点击链接或者下面的图片下载 install4j。 diff --git a/pom.xml b/pom.xml index dd689a3cc5..ccfa368ff3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.ghostchu.peerbanhelper peerbanhelper - 5.0.3 + 5.0.4 takari-jar PeerBanHelper diff --git a/src/main/java/com/ghostchu/peerbanhelper/Main.java b/src/main/java/com/ghostchu/peerbanhelper/Main.java index 8e60b484e9..1b21ff119c 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/Main.java +++ b/src/main/java/com/ghostchu/peerbanhelper/Main.java @@ -26,6 +26,7 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import javax.swing.*; import java.awt.*; import java.io.File; import java.io.IOException; @@ -36,7 +37,6 @@ import java.util.Arrays; import java.util.Locale; import java.util.Map; -import java.util.logging.Level; @Slf4j public class Main { @@ -131,6 +131,7 @@ private static void setupProxySettings() { if (proxySection == null) return; String host = proxySection.getString("host"); String port = String.valueOf(proxySection.getInt("port")); + String nonProxyHost = proxySection.getString("non-proxy-hosts", ""); switch (proxySection.getInt("setting")) { case 1 -> System.setProperty("java.net.useSystemProxies", "true"); case 2 -> { @@ -138,10 +139,13 @@ private static void setupProxySettings() { System.setProperty("http.proxyPort", port); System.setProperty("https.proxyHost", host); System.setProperty("https.proxyPort", port); + System.setProperty("http.nonProxyHosts", nonProxyHost); + System.setProperty("https.nonProxyHosts", nonProxyHost); } case 3 -> { System.setProperty("socksProxyHost", host); System.setProperty("socksProxyPort", port); + System.setProperty("socksNonProxyHosts", nonProxyHost); } default -> System.setProperty("java.net.useSystemProxies", "false"); } @@ -180,7 +184,7 @@ private static YamlConfiguration loadConfiguration(File file) { configuration.load(file); } catch (IOException | InvalidConfigurationException e) { log.error("Unable to load configuration: invalid YAML configuration // 无法加载配置文件:无效的 YAML 配置,请检查是否有语法错误", e); - guiManager.createDialog(Level.SEVERE, "Invalid YAML configuration | 无效 YAML 配置文件", String.format("Failed to read configuration: %s", file)); + JOptionPane.showMessageDialog(null, "Invalid/Corrupted YAML configuration | 无效或损坏的 YAML 配置文件", String.format("Failed to read configuration: %s", file), JOptionPane.ERROR_MESSAGE); System.exit(1); } return configuration; diff --git a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java index ec4ecec58f..e2e5dd2fac 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java +++ b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java @@ -6,6 +6,7 @@ import com.ghostchu.peerbanhelper.database.dao.impl.BanListDao; import com.ghostchu.peerbanhelper.downloader.Downloader; import com.ghostchu.peerbanhelper.downloader.DownloaderLastStatus; +import com.ghostchu.peerbanhelper.downloader.DownloaderLoginResult; import com.ghostchu.peerbanhelper.downloader.impl.biglybt.BiglyBT; import com.ghostchu.peerbanhelper.downloader.impl.deluge.Deluge; import com.ghostchu.peerbanhelper.downloader.impl.qbittorrent.QBittorrent; @@ -344,7 +345,7 @@ private void registerBanWaveTimer() { return thread; }); log.info(tlUI(Lang.PBH_BAN_WAVE_STARTED)); - BAN_WAVE_SERVICE.scheduleAtFixedRate(this::banWave, 1, profileConfig.getLong("check-interval", 5000), TimeUnit.MILLISECONDS); + BAN_WAVE_SERVICE.scheduleWithFixedDelay(this::banWave, 1, profileConfig.getLong("check-interval", 5000), TimeUnit.MILLISECONDS); } @@ -598,6 +599,9 @@ public Map> collectPeers(Downloader downloader) { if (!loginResult.success()) { log.error(tlUI(Lang.ERR_CLIENT_LOGIN_FAILURE_SKIP, downloader.getName(), downloader.getEndpoint(), tlUI(loginResult.getMessage()))); downloader.setLastStatus(DownloaderLastStatus.ERROR, loginResult.getMessage()); + if (loginResult.getStatus() == DownloaderLoginResult.Status.MISSING_COMPONENTS || loginResult.getStatus() == DownloaderLoginResult.Status.REQUIRE_TAKE_ACTIONS) { + downloader.setLastStatus(DownloaderLastStatus.NEED_TAKE_ACTION, loginResult.getMessage()); + } return Collections.emptyMap(); } List torrents = downloader.getTorrents(); diff --git a/src/main/java/com/ghostchu/peerbanhelper/config/MainConfigUpdateScript.java b/src/main/java/com/ghostchu/peerbanhelper/config/MainConfigUpdateScript.java index f2ea5172d2..088b254bf6 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/config/MainConfigUpdateScript.java +++ b/src/main/java/com/ghostchu/peerbanhelper/config/MainConfigUpdateScript.java @@ -28,6 +28,10 @@ private void validate() { } } + @UpdateScript(version = 14) + public void proxyServerConfigSectionEnhanced() { + conf.set("proxy.non-proxy-host", "127.0.0.1|localhost"); + } @UpdateScript(version = 13) public void proxyServerConfigSection() { conf.set("proxy.setting", 0); diff --git a/src/main/java/com/ghostchu/peerbanhelper/database/dao/impl/TorrentDao.java b/src/main/java/com/ghostchu/peerbanhelper/database/dao/impl/TorrentDao.java index f8c95aa2e5..4519b9a11e 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/database/dao/impl/TorrentDao.java +++ b/src/main/java/com/ghostchu/peerbanhelper/database/dao/impl/TorrentDao.java @@ -17,9 +17,11 @@ public TorrentDao(@Autowired Database database) throws SQLException { @Override public synchronized TorrentEntity createIfNotExists(TorrentEntity data) throws SQLException { - List list = queryForMatchingArgs(data); + List list = queryForEq("infoHash", data.getInfoHash()); if (list.isEmpty()) { - return super.createIfNotExists(data); + long id = create(data); + data.setId(id); + return data; } return list.getFirst(); } diff --git a/src/main/java/com/ghostchu/peerbanhelper/database/table/TorrentEntity.java b/src/main/java/com/ghostchu/peerbanhelper/database/table/TorrentEntity.java index 3616b06474..f35b02c9ab 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/database/table/TorrentEntity.java +++ b/src/main/java/com/ghostchu/peerbanhelper/database/table/TorrentEntity.java @@ -13,9 +13,9 @@ public final class TorrentEntity { @DatabaseField(generatedId = true) private Long id; - @DatabaseField(canBeNull = false, uniqueIndex = true, uniqueCombo = true) + @DatabaseField(canBeNull = false, uniqueIndex = true) private String infoHash; - @DatabaseField(canBeNull = false, uniqueCombo = true) + @DatabaseField(canBeNull = false) private String name; @DatabaseField(canBeNull = false) private Long size; diff --git a/src/main/java/com/ghostchu/peerbanhelper/downloader/AbstractDownloader.java b/src/main/java/com/ghostchu/peerbanhelper/downloader/AbstractDownloader.java new file mode 100644 index 0000000000..e84b8f7540 --- /dev/null +++ b/src/main/java/com/ghostchu/peerbanhelper/downloader/AbstractDownloader.java @@ -0,0 +1,69 @@ +package com.ghostchu.peerbanhelper.downloader; + +import com.ghostchu.peerbanhelper.text.Lang; +import com.ghostchu.peerbanhelper.text.TranslationComponent; +import com.ghostchu.peerbanhelper.util.MsgUtil; + +import java.util.Date; + +public abstract class AbstractDownloader implements Downloader { + protected String name; + private DownloaderLastStatus lastStatus = DownloaderLastStatus.UNKNOWN; + private TranslationComponent statusMessage; + private int failedLoginAttempts = 0; + private long nextLoginTry = 0L; + + public AbstractDownloader(String name) { + this.name = name; + } + + @Override + public DownloaderLoginResult login() { + if (nextLoginTry >= System.currentTimeMillis()) { + return new DownloaderLoginResult(DownloaderLoginResult.Status.REQUIRE_TAKE_ACTIONS + , new TranslationComponent(Lang.TOO_MANY_FAILED_ATTEMPT, MsgUtil.getDateFormatter().format(new Date(nextLoginTry))) + ); + } + DownloaderLoginResult result; + try { + result = login0(); + if (result.success()) { + failedLoginAttempts = 0; + return result; + } + failedLoginAttempts++; + return result; + } catch (Throwable e) { + failedLoginAttempts++; + throw e; + } finally { + if (failedLoginAttempts >= 15) { + nextLoginTry = System.currentTimeMillis() + (1000 * 60 * 30); + failedLoginAttempts = 0; + } + } + } + + public abstract DownloaderLoginResult login0(); + + @Override + public DownloaderLastStatus getLastStatus() { + return lastStatus; + } + + @Override + public void setLastStatus(DownloaderLastStatus lastStatus, TranslationComponent statusMessage) { + this.lastStatus = lastStatus; + this.statusMessage = statusMessage; + } + + @Override + public TranslationComponent getLastStatusMessage() { + return statusMessage; + } + + @Override + public String getName() { + return name; + } +} diff --git a/src/main/java/com/ghostchu/peerbanhelper/downloader/DownloaderLoginResult.java b/src/main/java/com/ghostchu/peerbanhelper/downloader/DownloaderLoginResult.java index 8bd7e95b6b..b96133704f 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/downloader/DownloaderLoginResult.java +++ b/src/main/java/com/ghostchu/peerbanhelper/downloader/DownloaderLoginResult.java @@ -22,6 +22,7 @@ public enum Status { INCORRECT_CREDENTIAL, MISSING_COMPONENTS, NETWORK_ERROR, - EXCEPTION + EXCEPTION, + REQUIRE_TAKE_ACTIONS } } diff --git a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/biglybt/BiglyBT.java b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/biglybt/BiglyBT.java index 071a03da5a..20274943b0 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/biglybt/BiglyBT.java +++ b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/biglybt/BiglyBT.java @@ -1,7 +1,6 @@ package com.ghostchu.peerbanhelper.downloader.impl.biglybt; -import com.ghostchu.peerbanhelper.downloader.Downloader; -import com.ghostchu.peerbanhelper.downloader.DownloaderLastStatus; +import com.ghostchu.peerbanhelper.downloader.AbstractDownloader; import com.ghostchu.peerbanhelper.downloader.DownloaderLoginResult; import com.ghostchu.peerbanhelper.downloader.impl.biglybt.network.bean.clientbound.BanBean; import com.ghostchu.peerbanhelper.downloader.impl.biglybt.network.bean.clientbound.BanListReplacementBean; @@ -47,17 +46,14 @@ import static com.ghostchu.peerbanhelper.text.TextManager.tlUI; -public class BiglyBT implements Downloader { +public class BiglyBT extends AbstractDownloader { private static final Logger log = org.slf4j.LoggerFactory.getLogger(BiglyBT.class); private final String apiEndpoint; private final HttpClient httpClient; private final Config config; - private DownloaderLastStatus lastStatus = DownloaderLastStatus.UNKNOWN; - private String name; - private TranslationComponent statusMessage; public BiglyBT(String name, Config config) { - this.name = name; + super(name); this.config = config; this.apiEndpoint = config.getEndpoint(); CookieManager cm = new CookieManager(); @@ -100,7 +96,8 @@ public YamlConfiguration saveDownloader() { return config.saveToYaml(); } - public DownloaderLoginResult login() { + @Override + public DownloaderLoginResult login0() { HttpResponse resp; try { resp = httpClient.send(MutableRequest.GET(apiEndpoint + "/metadata"), HttpResponse.BodyHandlers.discarding()); @@ -114,7 +111,6 @@ public DownloaderLoginResult login() { } catch (Exception e) { return new DownloaderLoginResult(DownloaderLoginResult.Status.NETWORK_ERROR, new TranslationComponent(Lang.DOWNLOADER_LOGIN_IO_EXCEPTION, e.getClass().getName() + ": " + e.getMessage())); } - } @Override @@ -122,31 +118,6 @@ public String getEndpoint() { return apiEndpoint; } -// @Override -// public String getWebUIEndpoint() { -// return config.getEndpoint(); -// } - -// @Override -// public @Nullable DownloaderBasicAuth getDownloaderBasicAuth() { -// return null; -// } -// -// @Override -// public @Nullable WebViewScriptCallback getWebViewJavaScript() { -// return null; -// } -// -// @Override -// public boolean isSupportWebview() { -// return false; -// } - - @Override - public String getName() { - return name; - } - @Override public String getType() { return "BiglyBT"; @@ -267,22 +238,6 @@ private void setBanListFull(Collection peerAddresses) { } } - @Override - public DownloaderLastStatus getLastStatus() { - return lastStatus; - } - - @Override - public void setLastStatus(DownloaderLastStatus lastStatus, TranslationComponent statusMessage) { - this.lastStatus = lastStatus; - this.statusMessage = statusMessage; - } - - @Override - public TranslationComponent getLastStatusMessage() { - return statusMessage; - } - @Override public void close() { diff --git a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/deluge/Deluge.java b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/deluge/Deluge.java index 8e83f87e46..a2a733245b 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/deluge/Deluge.java +++ b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/deluge/Deluge.java @@ -1,7 +1,6 @@ package com.ghostchu.peerbanhelper.downloader.impl.deluge; -import com.ghostchu.peerbanhelper.downloader.Downloader; -import com.ghostchu.peerbanhelper.downloader.DownloaderLastStatus; +import com.ghostchu.peerbanhelper.downloader.AbstractDownloader; import com.ghostchu.peerbanhelper.downloader.DownloaderLoginResult; import com.ghostchu.peerbanhelper.peer.Peer; import com.ghostchu.peerbanhelper.peer.PeerFlag; @@ -35,7 +34,7 @@ import static com.ghostchu.peerbanhelper.text.TextManager.tlUI; -public class Deluge implements Downloader { +public class Deluge extends AbstractDownloader { private static final Logger log = org.slf4j.LoggerFactory.getLogger(Deluge.class); private static final List MUST_HAVE_METHODS = ImmutableList.of( "peerbanhelperadapter.replace_blocklist", @@ -43,13 +42,11 @@ public class Deluge implements Downloader { "peerbanhelperadapter.get_active_torrents_info", "peerbanhelperadapter.ban_ips" ); - private final String name; private final DelugeServer client; private final Config config; - private DownloaderLastStatus lastStatus = DownloaderLastStatus.UNKNOWN; - private TranslationComponent statusMessage; public Deluge(String name, Config config) { + super(name); this.name = name; this.config = config; this.client = new DelugeServer(config.getEndpoint() + config.getRpcUrl(), config.getPassword(), config.isVerifySsl(), HttpClient.Version.valueOf(config.getHttpVersion()), null, null); @@ -65,8 +62,6 @@ public static Deluge loadFromConfig(String name, JsonObject section) { return new Deluge(name, config); } - - @Override public JsonObject saveDownloaderJson() { return JsonUtil.getGson().toJsonTree(config).getAsJsonObject(); @@ -82,38 +77,13 @@ public String getEndpoint() { return config.getEndpoint(); } -// @Override -// public String getWebUIEndpoint() { -// return config.getEndpoint(); -// } - -// @Override -// public @Nullable DownloaderBasicAuth getDownloaderBasicAuth() { -// return null; -// } -// -// @Override -// public @Nullable WebViewScriptCallback getWebViewJavaScript() { -// return null; -// } -// -// @Override -// public boolean isSupportWebview() { -// return true; -// } - - @Override - public String getName() { - return name; - } - @Override public String getType() { return "Deluge"; } @Override - public DownloaderLoginResult login() { + public DownloaderLoginResult login0() { try { if (!this.client.login().isLoggedIn()) { return new DownloaderLoginResult(DownloaderLoginResult.Status.INCORRECT_CREDENTIAL, new TranslationComponent(Lang.DOWNLOADER_LOGIN_INCORRECT_CRED)); @@ -210,22 +180,6 @@ public void relaunchTorrentIfNeededByTorrentWrapper(Collection t } - @Override - public DownloaderLastStatus getLastStatus() { - return lastStatus; - } - - @Override - public void setLastStatus(DownloaderLastStatus lastStatus, TranslationComponent statusMessage) { - this.lastStatus = lastStatus; - this.statusMessage = statusMessage; - } - - @Override - public TranslationComponent getLastStatusMessage() { - return statusMessage; - } - @Override public void close() { diff --git a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/qbittorrent/QBittorrent.java b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/qbittorrent/QBittorrent.java index d52dafcb51..1172dbc854 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/qbittorrent/QBittorrent.java +++ b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/qbittorrent/QBittorrent.java @@ -1,7 +1,6 @@ package com.ghostchu.peerbanhelper.downloader.impl.qbittorrent; -import com.ghostchu.peerbanhelper.downloader.Downloader; -import com.ghostchu.peerbanhelper.downloader.DownloaderLastStatus; +import com.ghostchu.peerbanhelper.downloader.AbstractDownloader; import com.ghostchu.peerbanhelper.downloader.DownloaderLoginResult; import com.ghostchu.peerbanhelper.peer.Peer; import com.ghostchu.peerbanhelper.text.Lang; @@ -39,16 +38,12 @@ import static com.ghostchu.peerbanhelper.text.TextManager.tlUI; @Slf4j -public class QBittorrent implements Downloader { +public class QBittorrent extends AbstractDownloader { private final String apiEndpoint; private final HttpClient httpClient; private final Config config; - private DownloaderLastStatus lastStatus = DownloaderLastStatus.UNKNOWN; - private String name; - private TranslationComponent statusMessage; - public QBittorrent(String name, Config config) { - this.name = name; + super(name); this.config = config; this.apiEndpoint = config.getEndpoint() + "/api/v2"; CookieManager cm = new CookieManager(); @@ -95,7 +90,7 @@ public YamlConfiguration saveDownloader() { return config.saveToYaml(); } - public DownloaderLoginResult login() { + public DownloaderLoginResult login0() { if (isLoggedIn()) return new DownloaderLoginResult(DownloaderLoginResult.Status.SUCCESS, new TranslationComponent(Lang.STATUS_TEXT_OK)); // 重用 Session 会话 try { @@ -124,52 +119,6 @@ public String getEndpoint() { return apiEndpoint; } -// @Override -// public String getWebUIEndpoint() { -// return config.getEndpoint(); -// } -// -// @Override -// public @Nullable DownloaderBasicAuth getDownloaderBasicAuth() { -// if (config.getBasicAuth() != null) { -// return new DownloaderBasicAuth(config.getEndpoint(), config.getBasicAuth().getUser(), config.getBasicAuth().getPass()); -// } -// return null; -// } -// -// @Override -// public @Nullable WebViewScriptCallback getWebViewJavaScript() { -// return (url, content) -> { -// if (content.contains("loginform")) { -// return String.format(""" -// const xhr = new XMLHttpRequest(); -// xhr.open('POST', 'api/v2/auth/login', true); -// xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8'); -// xhr.addEventListener('readystatechange', function() { -// if (xhr.readyState === 4) { // DONE state -// if ((xhr.status === 200) && (xhr.responseText === "Ok.")) -// location.reload(true); -// } -// } -// ); -// const queryString = "username=%s&password=%s"; -// xhr.send(queryString); -// """, UrlEncoderDecoder.encodePath(config.getUsername()), UrlEncoderDecoder.encodePath(config.getPassword())); -// } else { -// return null; -// } -// }; -// } -// -// @Override -// public boolean isSupportWebview() { -// return true; -// } - - @Override - public String getName() { - return name; - } @Override public String getType() { @@ -331,25 +280,10 @@ private void setBanListFull(Collection peerAddresses) { } @Override - public DownloaderLastStatus getLastStatus() { - return lastStatus; - } - - @Override - public void setLastStatus(DownloaderLastStatus lastStatus, TranslationComponent statusMessage) { - this.lastStatus = lastStatus; - this.statusMessage = statusMessage; - } + public void close() throws Exception { - @Override - public TranslationComponent getLastStatusMessage() { - return statusMessage; } - @Override - public void close() { - - } @NoArgsConstructor @Data diff --git a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/transmission/Transmission.java b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/transmission/Transmission.java index 6223a68b9a..d73b558af9 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/transmission/Transmission.java +++ b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/transmission/Transmission.java @@ -1,7 +1,6 @@ package com.ghostchu.peerbanhelper.downloader.impl.transmission; -import com.ghostchu.peerbanhelper.downloader.Downloader; -import com.ghostchu.peerbanhelper.downloader.DownloaderLastStatus; +import com.ghostchu.peerbanhelper.downloader.AbstractDownloader; import com.ghostchu.peerbanhelper.downloader.DownloaderLoginResult; import com.ghostchu.peerbanhelper.peer.Peer; import com.ghostchu.peerbanhelper.text.Lang; @@ -34,21 +33,18 @@ import static com.ghostchu.peerbanhelper.text.TextManager.tlUI; -public class Transmission implements Downloader { +public class Transmission extends AbstractDownloader { private static final Logger log = org.slf4j.LoggerFactory.getLogger(Transmission.class); - private final String name; private final TrClient client; private final String blocklistUrl; private final Config config; - private DownloaderLastStatus lastStatus = DownloaderLastStatus.UNKNOWN; - private TranslationComponent statusMessage; /* API 受限,实际实现起来意义不大 */ public Transmission(String name, String blocklistUrl, Config config) { - this.name = name; + super(name); this.config = config; this.client = new TrClient(config.getEndpoint() + config.getRpcUrl(), config.getUsername(), config.getPassword(), config.isVerifySsl(), HttpClient.Version.valueOf(config.getHttpVersion())); this.blocklistUrl = blocklistUrl; @@ -84,32 +80,6 @@ public String getEndpoint() { return config.getEndpoint(); } -// @Override -// public String getWebUIEndpoint() { -// return config.getEndpoint(); -// } - -// @Override -// public @Nullable DownloaderBasicAuth getDownloaderBasicAuth() { -// return new DownloaderBasicAuth(config.getEndpoint(), config.getUsername(), config.getPassword()); -// } -// -// @Override -// public @Nullable WebViewScriptCallback getWebViewJavaScript() { -// return null; -// } -// -// @Override -// public boolean isSupportWebview() { -// return true; -// } - - - @Override - public String getName() { - return name; - } - @Override public String getType() { return "Transmission"; @@ -117,7 +87,7 @@ public String getType() { @SneakyThrows(InterruptedException.class) @Override - public DownloaderLoginResult login() { + public DownloaderLoginResult login0() { RqSessionGet get = new RqSessionGet(); TypedResponse resp = client.execute(get); // 执行任意 RPC 操作以刷新 session String version = resp.getArgs().getVersion(); @@ -211,23 +181,6 @@ public void relaunchTorrentIfNeededByTorrentWrapper(Collection t }).map(t -> Long.parseLong(t.getId())).toList()); } - @Override - public DownloaderLastStatus getLastStatus() { - return lastStatus; - } - - @Override - public void setLastStatus(DownloaderLastStatus lastStatus, TranslationComponent statusMessage) { - this.lastStatus = lastStatus; - this.statusMessage = statusMessage; - } - - @Override - public TranslationComponent getLastStatusMessage() { - return statusMessage; - } - - @Override public void close() { client.shutdown(); diff --git a/src/main/java/com/ghostchu/peerbanhelper/gui/impl/javafx/JavaFxImpl.java b/src/main/java/com/ghostchu/peerbanhelper/gui/impl/javafx/JavaFxImpl.java index 23d78c6f0d..2ebae739e5 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/gui/impl/javafx/JavaFxImpl.java +++ b/src/main/java/com/ghostchu/peerbanhelper/gui/impl/javafx/JavaFxImpl.java @@ -358,23 +358,17 @@ public void createDialog(Level level, String title, String description) { @Override public void createNotification(Level level, String title, String description) { - Alert.AlertType alertType = Alert.AlertType.NONE; - if (level.equals(Level.WARNING)) { - alertType = Alert.AlertType.WARNING; - } - if (level.equals(Level.SEVERE)) { - alertType = Alert.AlertType.ERROR; - } - if (level.equals(Level.INFO)) { - alertType = Alert.AlertType.INFORMATION; + if (trayIcon != null) { + TrayIcon.MessageType messageType = TrayIcon.MessageType.INFO; + if (level.equals(Level.WARNING)) { + messageType = TrayIcon.MessageType.WARNING; + } + if (level.equals(Level.SEVERE)) { + messageType = TrayIcon.MessageType.ERROR; + } + trayIcon.displayMessage(title, description, messageType); + return; } - Alert.AlertType finalAlertType = alertType; - Platform.runLater(() -> { - Alert alert = new Alert(finalAlertType); - alert.setTitle(title); - alert.setHeaderText(title); - alert.setContentText(description); - alert.show(); - }); + createDialog(level, title, description); } } diff --git a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java index 0058d89a8f..255c471adb 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java +++ b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java @@ -295,7 +295,8 @@ public enum Lang { USER_MANUALLY_BAN_RULE, USER_MANUALLY_BAN_REASON, SCHEDULED_OPERATIONS, - ARB_BANNED_REASON + ARB_BANNED_REASON, + TOO_MANY_FAILED_ATTEMPT ; diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/MsgUtil.java b/src/main/java/com/ghostchu/peerbanhelper/util/MsgUtil.java index d7b2dc0b97..4d5c664114 100644 --- a/src/main/java/com/ghostchu/peerbanhelper/util/MsgUtil.java +++ b/src/main/java/com/ghostchu/peerbanhelper/util/MsgUtil.java @@ -8,10 +8,12 @@ import java.lang.management.ThreadInfo; import java.text.CharacterIterator; import java.text.DecimalFormat; +import java.text.SimpleDateFormat; import java.text.StringCharacterIterator; public class MsgUtil { private static final DecimalFormat df = new DecimalFormat("0.00%"); + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static String humanReadableByteCountBin(long bytes) { long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes); if (absB < 1024) { @@ -107,6 +109,9 @@ public static DecimalFormat getPercentageFormatter() { return df; } + public static SimpleDateFormat getDateFormatter() { + return sdf; + } /** * Replace args in raw to args diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 1a5d5c07e4..d46c2176cc 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,4 +1,4 @@ -config-version: 12 +config-version: 13 # 设置程序语言 # default 跟随操作系统 (Follow the operating system) # en_us English (US) @@ -118,3 +118,5 @@ proxy: host: "127.0.0.1" # 代理服务器端口号 port: 7890 + # 代理例外地址,使用 | 分隔不同条目 + non-proxy-host: "127.0.0.1|localhost" diff --git a/src/main/resources/lang/en_us/messages.yml b/src/main/resources/lang/en_us/messages.yml index ec23578bc5..9290bb678b 100644 --- a/src/main/resources/lang/en_us/messages.yml +++ b/src/main/resources/lang/en_us/messages.yml @@ -118,9 +118,9 @@ GUI_TRAY_MESSAGE_DESCRIPTION: "Click the tray icon to reopen the window; right-c GUI_TABBED_LOGS: "Run Logs" GUI_TABBED_PEERS: "Connected Peers" ABOUT_VIEW_GITHUB: "View GitHub page..." -IPDB_UPDATING: "{} database is outdated and needs updating, please wait while PBH connects to Maxmind servers to update data..." -IPDB_UPDATE_FAILED: "Error downloading database {} from Maxmind: {}" -IPDB_UPDATE_SUCCESS: "Successfully updated database {} from Maxmind!" +IPDB_UPDATING: "{} database is outdated and needs updating, please wait while PBH connects to the server to update data..." +IPDB_UPDATE_FAILED: "Error downloading database {} from server: {}" +IPDB_UPDATE_SUCCESS: "Successfully updated database {} from server!" IPDB_INVALID: "IPDB feature automatically disabled due to an error during initialization. Please check the log file to fix the issue" IPDB_NEED_CONFIG: "IPDB feature requires configuration, please fill in the relevant information in ip-database in config.yml" DOWNLOAD_PROGRESS_DETERMINED: "Download progress: downloaded {}/{} bytes, progress: {}%" @@ -309,4 +309,6 @@ USER_SCRIPT_RULE: "User Aviator Script Custom Rule" USER_SCRIPT_RUN_RESULT: "UserScript {}: {}" SCHEDULED_OPERATIONS: "[Scheduled Tasks] Processed {} ban list external changes" -ARB_BANNED_REASON: "IP address {} is in the same ban range as another banned IP address {}, performing chain ban operation: {}@{}" \ No newline at end of file +ARB_BANNED_REASON: "IP address {} is in the same ban range as another banned IP address {}, performing chain ban operation: {}@{}" + +TOO_MANY_FAILED_ATTEMPT: "Too many failed login attempts. We paused attempt until {}." \ No newline at end of file diff --git a/src/main/resources/lang/messages_fallback.yml b/src/main/resources/lang/messages_fallback.yml index 28d3923e96..ad9719eed5 100644 --- a/src/main/resources/lang/messages_fallback.yml +++ b/src/main/resources/lang/messages_fallback.yml @@ -309,4 +309,6 @@ USER_SCRIPT_RULE: "用户 Aviator Script 自定脚本规则" USER_SCRIPT_RUN_RESULT: "用户脚本 {}: {}" SCHEDULED_OPERATIONS: "[计划任务] 已处理 {} 个封禁列表的外部计划更改" -ARB_BANNED_REASON: "IP 地址 {} 与另一个已封禁的 IP 地址 {} 处于同一封禁区间内,执行连锁封禁操作:{}@{}" \ No newline at end of file +ARB_BANNED_REASON: "IP 地址 {} 与另一个已封禁的 IP 地址 {} 处于同一封禁区间内,执行连锁封禁操作:{}@{}" + +TOO_MANY_FAILED_ATTEMPT: "连接此下载器时连续多次错误,已暂停登录尝试。暂停状态将于 {} 恢复" \ No newline at end of file diff --git a/src/main/resources/lang/zh_cn/messages.yml b/src/main/resources/lang/zh_cn/messages.yml index 28d3923e96..8780255a0d 100644 --- a/src/main/resources/lang/zh_cn/messages.yml +++ b/src/main/resources/lang/zh_cn/messages.yml @@ -118,9 +118,9 @@ GUI_TRAY_MESSAGE_DESCRIPTION: "点击托盘图标重新打开窗口;右键托 GUI_TABBED_LOGS: "运行日志" GUI_TABBED_PEERS: "已连接的Peers" ABOUT_VIEW_GITHUB: "查看 Github 页面..." -IPDB_UPDATING: "{} 数据库已过期且需要更新,请等待 PBH 连接到 Maxmind 服务器更新数据……" -IPDB_UPDATE_FAILED: "从 Maxmind 下载数据库 {} 时出现错误:{}" -IPDB_UPDATE_SUCCESS: "从 Maxmind 更新数据库 {} 成功!" +IPDB_UPDATING: "{} 数据库已过期且需要更新,请等待 PBH 连接到服务器更新数据……" +IPDB_UPDATE_FAILED: "下载数据库 {} 时出现错误:{}" +IPDB_UPDATE_SUCCESS: "更新数据库 {} 成功!" IPDB_INVALID: "由于在初始化过程中出现错误,IPDB 功能已被自动禁用。请检查日志文件以修复问题" IPDB_NEED_CONFIG: "IPDB 功能需要配置才能使用,请在 config.yml 的 ip-database 中填写相关配置信息" DOWNLOAD_PROGRESS_DETERMINED: "下载进度:已下载 {}/{} 字节,进度:{}%" @@ -309,4 +309,6 @@ USER_SCRIPT_RULE: "用户 Aviator Script 自定脚本规则" USER_SCRIPT_RUN_RESULT: "用户脚本 {}: {}" SCHEDULED_OPERATIONS: "[计划任务] 已处理 {} 个封禁列表的外部计划更改" -ARB_BANNED_REASON: "IP 地址 {} 与另一个已封禁的 IP 地址 {} 处于同一封禁区间内,执行连锁封禁操作:{}@{}" \ No newline at end of file +ARB_BANNED_REASON: "IP 地址 {} 与另一个已封禁的 IP 地址 {} 处于同一封禁区间内,执行连锁封禁操作:{}@{}" + +TOO_MANY_FAILED_ATTEMPT: "连接此下载器时连续多次错误,已暂停登录尝试,请检查用户名密码和网络连接。暂停状态将于 {} 恢复" \ No newline at end of file diff --git a/src/main/resources/profile.yml b/src/main/resources/profile.yml index 66beeffa82..c2fdf8abbd 100644 --- a/src/main/resources/profile.yml +++ b/src/main/resources/profile.yml @@ -158,7 +158,7 @@ module: # IPV4 前缀长度 ipv4: 30 # /32 = 单个 IP,/24 = 整个 ?.?.?.x 段 # IPV6 前缀长度 - ipv6: 64 # /64 = ISP 通常分配给家宽用户的前缀长度 + ipv6: 60 # /60 = ISP 通常分配给家宽用户的前缀长度 # 启用来自 BTN 网络的规则 btn: enabled: true