diff --git a/.github/workflows/jvm-ci.yml b/.github/workflows/jvm-ci.yml
index 5f9ef06936..52b75044af 100644
--- a/.github/workflows/jvm-ci.yml
+++ b/.github/workflows/jvm-ci.yml
@@ -71,7 +71,7 @@ jobs:
type=raw,ci
type=sha
- name: Build and push Docker image
- uses: docker/build-push-action@v6.4.0
+ uses: docker/build-push-action@v6.4.1
with:
context: .
file: ./Dockerfile-CI
diff --git a/.github/workflows/jvm-release.yml b/.github/workflows/jvm-release.yml
index 8a69ae444e..c2df7a629f 100644
--- a/.github/workflows/jvm-release.yml
+++ b/.github/workflows/jvm-release.yml
@@ -82,7 +82,7 @@ jobs:
type=raw,latest
type=sha
- name: Build and push Docker image
- uses: docker/build-push-action@v6.4.0
+ uses: docker/build-push-action@v6.4.1
with:
context: .
file: ./Dockerfile
@@ -114,7 +114,7 @@ jobs:
type=raw,latest
type=sha
- name: Build and push Aliyun ACR
- uses: docker/build-push-action@v6.4.0
+ uses: docker/build-push-action@v6.4.1
with:
context: .
file: ./Dockerfile
diff --git a/README.md b/README.md
index 7b2f798ee3..8fe68eaeaf 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,9 @@
> [!TIP]
> 您只需要正确连接 PBH 到下载器就可以正常工作,大多数情况下,并不需要额外配置
+> [!TIP]
+> 为获得最佳效果,建议配合我们维护的 IP 规则库 [PBH-BTN/BTN-Collected-Rules](https://github.com/PBH-BTN/BTN-Collected-Rules) 和 [BTN 网络](https://github.com/PBH-BTN/PeerBanHelper/wiki/BTN-%E7%BD%91%E7%BB%9C) 一起食用,不过这是完全可选的。
+
| 主界面 | 封禁列表 | 封禁日志 | 封禁统计 | 规则统计 | 规则订阅 |
|---------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| | | | | | |
@@ -318,26 +321,16 @@ client:
![image](https://github.com/Ghost-chu/PeerBanHelper/assets/30802565/20d49093-bf99-41f6-971f-c0c574d493af)
-### 非本机(例如:NAS上、Docker里)的 PBH 的 WebUI 打不开怎么办?
-
-打开 `config.yml`,找到 `address`,它的默认值是 `127.0.0.1`(只有PBH所在机器可以访问),请更改为 `0.0.0.0` 开启外部访问。
-**对于下面的 prefix 选项,除非你知道那是干什么的,否则请保持默认,或者询问其它用户**
-
### 管理 Token 在哪里?
-在 config.yml 中:
+您可以从 GUI 界面的 WebUI->复制Token 获得 Token。通过 GUI 唤起浏览器打开的 WebUI 将自动填写 Token。如果是首次使用,也会在日志中显示您的 Token。
+除此之外,您还可以从 config.yml 中找到 Token ↓
```yaml
# Http 服务器设置
server:
- # 监听端口
http: 9898
- # 客户端远程 URL 设置
- # Docker 网络请改 host 模式使用或者设置容器端口暴露
- # 当客户端需要与 PBH 通信时,客户端的 URL 会被更改为 http://
:/
- address: 127.0.0.1
- # 在 PBH 需要给下载器传递地址时,将使用此地址传递,请确保此地址最终可被下载器访问,请【不要】以 / 结尾
- prefix: http://127.0.0.1:9898
+ ...<省略>...
token: "*************************" # <-- 你的管理 Token
```
diff --git a/pom.xml b/pom.xml
index 34ba0392e8..dd689a3cc5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.ghostchu.peerbanhelper
peerbanhelper
- 5.0.2
+ 5.0.3
takari-jar
PeerBanHelper
diff --git a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
index 7568b7dcb2..ec4ecec58f 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
@@ -566,7 +566,7 @@ private void registerModules() {
//moduleManager.register(new ActiveProbing(this, profile));
moduleManager.register(AutoRangeBan.class);
moduleManager.register(BtnNetworkOnline.class);
- moduleManager.register(DownloaderCIDRBlockList.class);
+ moduleManager.register(BlockListController.class);
moduleManager.register(IPBlackRuleList.class);
moduleManager.register(PBHMetricsController.class);
moduleManager.register(PBHBanController.class);
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 776441c720..071a03da5a 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
@@ -219,6 +219,7 @@ public List getPeers(Torrent torrent) {
for (PeerRecord peer : peerManagerRecord.getPeers()) {
peersList.add(new PeerImpl(
new PeerAddress(peer.getIp(), peer.getPort()),
+ peer.getIp(),
new String(Base64.getDecoder().decode(peer.getPeerIdBase64()), StandardCharsets.ISO_8859_1),
peer.getClient(),
peer.getStats().getRtDownloadSpeed(),
diff --git a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/deluge/DelugePeer.java b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/deluge/DelugePeer.java
index 10499655b9..7b4c579f1a 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/deluge/DelugePeer.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/deluge/DelugePeer.java
@@ -18,4 +18,9 @@ public final class DelugePeer implements Peer {
private long uploadSpeed;
private double progress;
private PeerFlag flags;
+
+ @Override
+ public String getRawIp() {
+ return peerAddress.getIp();
+ }
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/qbittorrent/QBPeer.java b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/qbittorrent/QBPeer.java
index 7ca7b2b979..f98f4035ce 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/qbittorrent/QBPeer.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/qbittorrent/QBPeer.java
@@ -43,6 +43,7 @@ public final class QBPeer implements Peer {
@SerializedName("uploaded")
private Long uploaded;
private transient PeerAddress peerAddress;
+ private String rawIp;
public QBPeer() {
}
@@ -97,6 +98,11 @@ public PeerFlag getFlags() {
return new PeerFlag(flags);
}
+ @Override
+ public String getRawIp() {
+ return rawIp == null ? ip : rawIp;
+ }
+
@Override
public String toString() {
return "SingleTorrentPeer{" +
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 f334949a5d..d52dafcb51 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
@@ -9,7 +9,6 @@
import com.ghostchu.peerbanhelper.torrent.Torrent;
import com.ghostchu.peerbanhelper.torrent.TorrentImpl;
import com.ghostchu.peerbanhelper.util.HTTPUtil;
-import com.ghostchu.peerbanhelper.util.IPAddressUtil;
import com.ghostchu.peerbanhelper.util.JsonUtil;
import com.ghostchu.peerbanhelper.wrapper.BanMetadata;
import com.ghostchu.peerbanhelper.wrapper.PeerAddress;
@@ -21,7 +20,6 @@
import com.google.gson.JsonParser;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
-import inet.ipaddr.IPAddress;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -256,25 +254,25 @@ public List getPeers(Torrent torrent) {
qbPeer.setClient(mid);
}
}
+ qbPeer.setRawIp(s);
peersList.add(qbPeer);
}
return peersList;
}
private void setBanListIncrement(Collection added) {
- added.forEach(meta -> {
- IPAddress ipAddress = IPAddressUtil.getIPAddress(meta.getPeer().getAddress().getIp());
- String peers;
- if (ipAddress.isIPv4()) {
- peers = meta.getPeer().getAddress().getIp() + ":" + meta.getPeer().getAddress().getPort();
- } else {
- peers = "[" + meta.getPeer().getAddress().getIp() + "]" + ":" + meta.getPeer().getAddress().getPort();
- }
+ Map banTasks = new HashMap<>();
+ added.forEach(p -> {
+ StringJoiner joiner = banTasks.getOrDefault(p.getTorrent().getHash(), new StringJoiner("|"));
+ joiner.add(p.getPeer().getRawIp());
+ banTasks.put(p.getTorrent().getHash(), joiner);
+ });
+ banTasks.forEach((hash, peers) -> {
try {
HttpResponse request = httpClient.send(MutableRequest
.POST(apiEndpoint + "/transfer/banPeers", FormBodyPublisher.newBuilder()
- .query("hash", meta.getTorrent().getHash())
- .query("peers", peers).build())
+ .query("hash", hash)
+ .query("peers", peers.toString()).build())
.header("Content-Type", "application/x-www-form-urlencoded")
, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
if (request.statusCode() != 200) {
diff --git a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/transmission/TRPeer.java b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/transmission/TRPeer.java
index be370583ee..559949fe31 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/transmission/TRPeer.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/downloader/impl/transmission/TRPeer.java
@@ -62,4 +62,9 @@ public PeerFlag getFlags() {
return new PeerFlag(backend.getFlagStr());
}
+ @Override
+ public String getRawIp() {
+ return backend.getAddress();
+ }
+
}
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 8c2cc8f746..6223a68b9a 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
@@ -56,7 +56,7 @@ public Transmission(String name, String blocklistUrl, Config config) {
}
private static String generateBlocklistUrl(String pbhServerAddress) {
- return pbhServerAddress + "/blocklist/transmission";
+ return pbhServerAddress + "/blocklist/p2p-plain-format";
}
public static Transmission loadFromConfig(String name, String pbhServerAddress, ConfigurationSection section) {
@@ -115,6 +115,7 @@ public String getType() {
return "Transmission";
}
+ @SneakyThrows(InterruptedException.class)
@Override
public DownloaderLoginResult login() {
RqSessionGet get = new RqSessionGet();
@@ -123,6 +124,17 @@ public DownloaderLoginResult login() {
if (version.startsWith("0.") || version.startsWith("1.") || version.startsWith("2.")) {
return new DownloaderLoginResult(DownloaderLoginResult.Status.EXCEPTION, new TranslationComponent(Lang.DOWNLOADER_TR_KNOWN_INCOMPATIBILITY, "API Version"));
}
+ if (!resp.getArgs().getBlocklistEnabled() || !resp.getArgs().getBlocklistUrl().startsWith(blocklistUrl)) {
+ RqSessionSet set = RqSessionSet.builder()
+ .blocklistUrl(blocklistUrl + "?t=" + System.currentTimeMillis()) // 更改 URL 来确保更改生效
+ .blocklistEnabled(true)
+ .build();
+ TypedResponse sessionSetResp = client.execute(set);
+ if (!sessionSetResp.isSuccess()) {
+ log.error(tlUI(Lang.DOWNLOADER_TR_INCORRECT_BANLIST_API_RESP), sessionSetResp.getResult());
+ }
+ Thread.sleep(3000);
+ }
return new DownloaderLoginResult(DownloaderLoginResult.Status.SUCCESS, new TranslationComponent(Lang.STATUS_TEXT_OK));
}
@@ -145,15 +157,6 @@ public List getPeers(Torrent torrent) {
@SneakyThrows
@Override
public void setBanList(Collection fullList, @Nullable Collection added, @Nullable Collection removed) {
- RqSessionSet set = RqSessionSet.builder()
- .blocklistUrl(blocklistUrl + "?t=" + System.currentTimeMillis()) // 更改 URL 来确保更改生效
- .blocklistEnabled(true)
- .build();
- TypedResponse sessionSetResp = client.execute(set);
- if (!sessionSetResp.isSuccess()) {
- log.error(tlUI(Lang.DOWNLOADER_TR_INCORRECT_BANLIST_API_RESP), sessionSetResp.getResult());
- }
- Thread.sleep(3000); // Transmission 在这里疑似有崩溃问题?
RqBlockList updateBlockList = new RqBlockList();
TypedResponse updateBlockListResp = client.execute(updateBlockList);
if (!updateBlockListResp.isSuccess()) {
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/AutoRangeBan.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/AutoRangeBan.java
index 4ec60519af..b5d3948fd5 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/AutoRangeBan.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/AutoRangeBan.java
@@ -10,6 +10,7 @@
import com.ghostchu.peerbanhelper.torrent.Torrent;
import com.ghostchu.peerbanhelper.web.JavalinWebContainer;
import com.ghostchu.peerbanhelper.web.Role;
+import com.ghostchu.peerbanhelper.wrapper.BanMetadata;
import com.ghostchu.peerbanhelper.wrapper.PeerAddress;
import inet.ipaddr.IPAddress;
import io.javalin.http.Context;
@@ -85,7 +86,8 @@ private void reloadConfig() {
if (peerAddress.isIPv4Convertible()) {
peerAddress = peerAddress.toIPv4();
}
- for (PeerAddress bannedPeer : getServer().getBannedPeers().keySet()) {
+ for (Map.Entry bannedPeerEntry : getServer().getBannedPeers().entrySet()) {
+ PeerAddress bannedPeer = bannedPeerEntry.getKey();
IPAddress bannedAddress = bannedPeer.getAddress().withoutPrefixLength();
if (bannedAddress.isIPv4Convertible()) {
bannedAddress = bannedAddress.toIPv4();
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/DownloaderCIDRBlockList.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/BlockListController.java
similarity index 67%
rename from src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/DownloaderCIDRBlockList.java
rename to src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/BlockListController.java
index 6d7004c7a8..db1f234932 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/DownloaderCIDRBlockList.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/BlockListController.java
@@ -1,10 +1,12 @@
package com.ghostchu.peerbanhelper.module.impl.webapi;
import com.ghostchu.peerbanhelper.module.AbstractFeatureModule;
+import com.ghostchu.peerbanhelper.util.IPAddressUtil;
import com.ghostchu.peerbanhelper.web.JavalinWebContainer;
import com.ghostchu.peerbanhelper.web.Role;
import com.ghostchu.peerbanhelper.wrapper.BanMetadata;
import com.ghostchu.peerbanhelper.wrapper.PeerAddress;
+import inet.ipaddr.IPAddress;
import io.javalin.http.HttpStatus;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -17,7 +19,7 @@
import java.util.UUID;
@Component
-public class DownloaderCIDRBlockList extends AbstractFeatureModule {
+public class BlockListController extends AbstractFeatureModule {
@Autowired
private JavalinWebContainer webContainer;
@Override
@@ -28,7 +30,7 @@ public boolean isConfigurable() {
@Override
public void onEnable() {
webContainer.javalin()
- .get("/blocklist/transmission", ctx -> {
+ .get("/blocklist/p2p-plain-format", ctx -> {
StringBuilder builder = new StringBuilder();
for (Map.Entry pair : getServer().getBannedPeers().entrySet()) {
String ruleName = UUID.randomUUID().toString().replace("-", "");
@@ -38,6 +40,17 @@ public void onEnable() {
}
ctx.status(HttpStatus.OK);
ctx.result(builder.toString());
+ }, Role.ANYONE)
+ .get("/blocklist/dat-emule", ctx -> {
+ StringBuilder builder = new StringBuilder();
+ for (Map.Entry pair : getServer().getBannedPeers().entrySet()) {
+ IPAddress ipAddress = IPAddressUtil.getIPAddress(pair.getKey().getIp());
+ if (ipAddress == null) continue;
+ String fullIp = ipAddress.toFullString();
+ builder.append(fullIp).append(" - ").append(fullIp).append(" , 000 , ").append(UUID.randomUUID().toString().replace("-", "")).append("\n");
+ }
+ ctx.status(HttpStatus.OK);
+ ctx.result(builder.toString());
}, Role.ANYONE);
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/PBHDownloaderController.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/PBHDownloaderController.java
index 6125a76e3b..b270b7a618 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/PBHDownloaderController.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/PBHDownloaderController.java
@@ -210,6 +210,7 @@ private void handleDownloaderTorrents(@NotNull Context ctx, String downloaderNam
List torrentWrappers = getServer().getLivePeersSnapshot()
.values().stream().filter(p -> p.getDownloader().equals(downloader.getName()))
.map(PeerMetadata::getTorrent)
+ .distinct()
.sorted((o1, o2) -> Long.compare(o2.getRtUploadSpeed(), o1.getRtUploadSpeed()))
.toList();
ctx.status(HttpStatus.OK);
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/PBHMetricsController.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/PBHMetricsController.java
index 60fd97d4b9..1edf759d80 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/PBHMetricsController.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/PBHMetricsController.java
@@ -11,6 +11,7 @@
import com.ghostchu.peerbanhelper.web.JavalinWebContainer;
import com.ghostchu.peerbanhelper.web.Role;
import com.ghostchu.peerbanhelper.wrapper.BanMetadata;
+import com.ghostchu.peerbanhelper.wrapper.PeerAddress;
import io.javalin.http.Context;
import io.javalin.http.HttpStatus;
import lombok.AllArgsConstructor;
@@ -166,8 +167,9 @@ private void handleRules(Context ctx) {
if (obj.getKey().matcherName() != null) {
ruleType = obj.getKey().matcherName();
}
- dict.put(obj.getKey().matcherIdentifier(), tl(locale, ruleType));
- return new RuleData(obj.getKey().matcherIdentifier(), obj.getValue().getHitCounter(), obj.getValue().getQueryCounter(), obj.getKey().metadata());
+ // 返回特定计算值作为字典键,这样不需要修改前端
+ dict.put(tl(locale, ruleType), tl(locale, ruleType));
+ return new RuleData(tl(locale, ruleType), obj.getValue().getHitCounter(), obj.getValue().getQueryCounter(), obj.getKey().metadata());
})
.sorted((o1, o2) -> Long.compare(o2.getHit(), o1.getHit()))
.toList();
@@ -184,6 +186,7 @@ private void handleBasicCounter(Context ctx) {
map.put("peerBanCounter", metrics.getPeerBanCounter());
map.put("peerUnbanCounter", metrics.getPeerUnbanCounter());
map.put("banlistCounter", getServer().getBannedPeers().size());
+ map.put("bannedIpCounter", getServer().getBannedPeers().keySet().stream().map(PeerAddress::getIp).distinct().count());
ctx.status(HttpStatus.OK);
ctx.json(map);
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/peer/Peer.java b/src/main/java/com/ghostchu/peerbanhelper/peer/Peer.java
index 9d8226d977..be3fb04707 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/peer/Peer.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/peer/Peer.java
@@ -80,4 +80,11 @@ default String getCacheKey() {
//return "pa=" + this.getPeerAddress().toString() + ",pid=" + this.getPeerId() + ",pname=" + this.getClientName();
return getPeerAddress().getIp() + ':' + getPeerAddress().getPort();
}
+
+ /**
+ * 获取该 Peer 的原始 IP 表示法,用于返回给下载器封禁 Peer
+ *
+ * @return 原始IP
+ */
+ String getRawIp();
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/peer/PeerImpl.java b/src/main/java/com/ghostchu/peerbanhelper/peer/PeerImpl.java
index 1e58b591c1..71948d5484 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/peer/PeerImpl.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/peer/PeerImpl.java
@@ -6,6 +6,7 @@
@Setter
public class PeerImpl implements Peer {
private PeerAddress peerAddress;
+ private String rawIp;
private String peerId;
private String clientName;
private long downloadSpeed;
@@ -15,8 +16,9 @@ public class PeerImpl implements Peer {
private double progress;
private PeerFlag flags;
- public PeerImpl(PeerAddress peerAddress, String peerId, String clientName, long downloadSpeed, long downloaded, long uploadSpeed, long uploaded, double progress, PeerFlag flags) {
+ public PeerImpl(PeerAddress peerAddress, String rawIp, String peerId, String clientName, long downloadSpeed, long downloaded, long uploadSpeed, long uploaded, double progress, PeerFlag flags) {
this.peerAddress = peerAddress;
+ this.rawIp = rawIp;
this.peerId = peerId;
this.clientName = clientName;
this.downloadSpeed = downloadSpeed;
@@ -71,4 +73,9 @@ public double getProgress() {
public PeerFlag getFlags() {
return flags;
}
+
+ @Override
+ public String getRawIp() {
+ return rawIp;
+ }
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
index 3006c82fdd..0058d89a8f 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
@@ -294,7 +294,8 @@ public enum Lang {
USER_SCRIPT_RULE,
USER_MANUALLY_BAN_RULE,
USER_MANUALLY_BAN_REASON,
- SCHEDULED_OPERATIONS
+ SCHEDULED_OPERATIONS,
+ ARB_BANNED_REASON
;
diff --git a/src/main/java/com/ghostchu/peerbanhelper/text/TextManager.java b/src/main/java/com/ghostchu/peerbanhelper/text/TextManager.java
index ffdb2e451a..9578847278 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/text/TextManager.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/text/TextManager.java
@@ -49,7 +49,7 @@ public TextManager() {
}
public static String tlUI(Lang key, Object... params) {
- return tl(DEF_LOCALE, new TranslationComponent(key.getKey(), INSTANCE_HOLDER.convert(params)));
+ return tl(DEF_LOCALE, new TranslationComponent(key.getKey(), (Object[]) TextManager.convert(DEF_LOCALE, params)));
}
public static String tlUI(TranslationComponent translationComponent) {
@@ -60,7 +60,7 @@ public static String tlUI(TranslationComponent translationComponent) {
// }
public static String tl(String locale, Lang key, Object... params) {
- return tl(locale, new TranslationComponent(key.getKey(), INSTANCE_HOLDER.convert(params)));
+ return tl(locale, new TranslationComponent(key.getKey(), (Object[]) TextManager.convert(locale, params)));
}
public static String tl(String locale, TranslationComponent translationComponent) {
@@ -74,9 +74,10 @@ public static String tl(String locale, TranslationComponent translationComponent
if (str == null) {
return translationComponent.getKey();
}
+ String[] params = convert(locale, translationComponent.getParams());
for (PostProcessor postProcessor : INSTANCE_HOLDER.postProcessors) {
try {
- str = postProcessor.process(str, locale, translationComponent.getParams());
+ str = postProcessor.process(str, locale, params);
} catch (Exception e) {
log.warn("Unable to process post processor: key={}, locale={}, params={}", translationComponent.getKey(), locale, translationComponent.getParams());
}
@@ -84,6 +85,37 @@ public static String tl(String locale, TranslationComponent translationComponent
return str;
}
+ @NotNull
+ public static String[] convert(String locale, @Nullable Object... args) {
+ if (args == null || args.length == 0) {
+ return new String[0];
+ }
+ String[] components = new String[args.length];
+ for (int i = 0; i < args.length; i++) {
+ Object obj = args[i];
+ if (obj == null) {
+ components[i] = "null";
+ continue;
+ }
+ // Class> clazz = obj.getClass();
+ // Check
+
+ try {
+ if (obj instanceof TranslationComponent translationComponent) {
+ components[i] = tl(locale, translationComponent);
+ continue;
+ }
+ components[i] = obj.toString();
+ } catch (Exception exception) {
+ log.debug("Failed to process the object: {}", obj);
+ components[i] = String.valueOf(obj); // null safe
+ }
+ // undefined
+
+ }
+ return components;
+ }
+
/**
* Loading Crowdin OTA module and i18n system
*/
@@ -294,32 +326,6 @@ public void register(@NotNull String locale, @NotNull String path, @NotNull Stri
languageFilesManager.deploy(locale, configuration);
}
- @NotNull
- public String[] convert(@Nullable Object... args) {
- if (args == null || args.length == 0) {
- return new String[0];
- }
- String[] components = new String[args.length];
- for (int i = 0; i < args.length; i++) {
- Object obj = args[i];
- if (obj == null) {
- components[i] = "null";
- continue;
- }
- // Class> clazz = obj.getClass();
- // Check
- try {
- components[i] = obj.toString();
- } catch (Exception exception) {
- log.debug("Failed to process the object: {}", obj);
- components[i] = String.valueOf(obj); // null safe
- }
- // undefined
-
- }
- return components;
- }
-
/**
* Return the set of available Languages
*
diff --git a/src/main/java/com/ghostchu/peerbanhelper/text/TranslationComponent.java b/src/main/java/com/ghostchu/peerbanhelper/text/TranslationComponent.java
index 3895e342d3..7586136c92 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/text/TranslationComponent.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/text/TranslationComponent.java
@@ -7,14 +7,19 @@
@Getter
public class TranslationComponent {
private final String key;
- private final String[] params;
+ private final Object[] params;
public TranslationComponent(String key) {
this.key = key;
this.params = new String[0];
}
- public TranslationComponent(String key, String... params) {
+ /**
+ * 注意:Params 的所有对象必须都可以被 Gson 序列化/反序列化!
+ * @param key
+ * @param params
+ */
+ public TranslationComponent(String key, Object... params) {
this.key = key;
this.params = params;
}
@@ -22,8 +27,12 @@ public TranslationComponent(String key, String... params) {
public TranslationComponent(Lang key) {
this(key.getKey());
}
-
- public TranslationComponent(Lang key, String... params) {
+ /**
+ * 注意:Params 的所有对象必须都可以被 Gson 序列化/反序列化!
+ * @param key
+ * @param params
+ */
+ public TranslationComponent(Lang key, Object... params) {
this(key.getKey(), params);
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/IPAddressUtil.java b/src/main/java/com/ghostchu/peerbanhelper/util/IPAddressUtil.java
index fd4f63d94b..4aa694ba32 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/IPAddressUtil.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/IPAddressUtil.java
@@ -6,6 +6,7 @@
import inet.ipaddr.IPAddressString;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -32,6 +33,7 @@ public class IPAddressUtil {
* @param ip
* @return
*/
+ @Nullable
public static IPAddress getIPAddress(String ip) {
try {
return IP_ADDRESS_CACHE.get(ip, () -> {
diff --git a/src/main/java/com/ghostchu/peerbanhelper/wrapper/PeerWrapper.java b/src/main/java/com/ghostchu/peerbanhelper/wrapper/PeerWrapper.java
index 292a92017a..8dc71937e6 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/wrapper/PeerWrapper.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/wrapper/PeerWrapper.java
@@ -11,6 +11,7 @@
@AllArgsConstructor
public final class PeerWrapper {
private PeerAddressWrapper address;
+ private String rawIp;
private String id;
private String clientName;
private long downloaded;
@@ -22,6 +23,7 @@ public final class PeerWrapper {
public PeerWrapper(Peer peer) {
this.id = peer.getPeerId();
+ this.rawIp = peer.getRawIp();
this.address = new PeerAddressWrapper(peer.getPeerAddress());
this.clientName = peer.getClientName();
this.downloaded = peer.getDownloaded();
diff --git a/src/main/resources/lang/en_us/messages.yml b/src/main/resources/lang/en_us/messages.yml
index d43e129db0..ec23578bc5 100644
--- a/src/main/resources/lang/en_us/messages.yml
+++ b/src/main/resources/lang/en_us/messages.yml
@@ -307,4 +307,6 @@ DOWNLOADER_LOGIN_INCORRECT_CRED: "Unable to authenticate to downloader, check th
USER_SCRIPT_RULE: "User Aviator Script Custom Rule"
USER_SCRIPT_RUN_RESULT: "UserScript {}: {}"
-SCHEDULED_OPERATIONS: "[Scheduled Tasks] Processed {} ban list external changes"
\ No newline at end of file
+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
diff --git a/src/main/resources/lang/messages_fallback.yml b/src/main/resources/lang/messages_fallback.yml
index e76541bfb3..28d3923e96 100644
--- a/src/main/resources/lang/messages_fallback.yml
+++ b/src/main/resources/lang/messages_fallback.yml
@@ -307,4 +307,6 @@ DOWNLOADER_LOGIN_INCORRECT_CRED: "鉴权失败,错误的登录凭据。请检
USER_SCRIPT_RULE: "用户 Aviator Script 自定脚本规则"
USER_SCRIPT_RUN_RESULT: "用户脚本 {}: {}"
-SCHEDULED_OPERATIONS: "[计划任务] 已处理 {} 个封禁列表的外部计划更改"
\ No newline at end of file
+SCHEDULED_OPERATIONS: "[计划任务] 已处理 {} 个封禁列表的外部计划更改"
+
+ARB_BANNED_REASON: "IP 地址 {} 与另一个已封禁的 IP 地址 {} 处于同一封禁区间内,执行连锁封禁操作:{}@{}"
\ 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 e76541bfb3..28d3923e96 100644
--- a/src/main/resources/lang/zh_cn/messages.yml
+++ b/src/main/resources/lang/zh_cn/messages.yml
@@ -307,4 +307,6 @@ DOWNLOADER_LOGIN_INCORRECT_CRED: "鉴权失败,错误的登录凭据。请检
USER_SCRIPT_RULE: "用户 Aviator Script 自定脚本规则"
USER_SCRIPT_RUN_RESULT: "用户脚本 {}: {}"
-SCHEDULED_OPERATIONS: "[计划任务] 已处理 {} 个封禁列表的外部计划更改"
\ No newline at end of file
+SCHEDULED_OPERATIONS: "[计划任务] 已处理 {} 个封禁列表的外部计划更改"
+
+ARB_BANNED_REASON: "IP 地址 {} 与另一个已封禁的 IP 地址 {} 处于同一封禁区间内,执行连锁封禁操作:{}@{}"
\ No newline at end of file
diff --git a/src/main/resources/profile.yml b/src/main/resources/profile.yml
index d4feb15890..66beeffa82 100644
--- a/src/main/resources/profile.yml
+++ b/src/main/resources/profile.yml
@@ -172,8 +172,8 @@ module:
# 子网掩码长度
# IP地址前多少位相同的视为同一个子网,位数越少范围越大,一般不需要修改
subnet-mask-length: 24
- # 对于同小区IPv6地址应该取多少位掩码没有调查过,64位是不会误杀的保险值
- subnet-mask-v6-length: 64
+ # IPv6 地址前缀长度
+ subnet-mask-v6-length: 60
# 容许同一网段下载同一种子的IP数量,正整数
# 防止DHCP重新分配IP、碰巧有同一小区的用户下载同一种子等导致的误判
tolerate-num: 5
@@ -241,25 +241,10 @@ module:
# 规则列表
rules:
# 规则ID(任意)
- dt_torrents:
+ all-in-one:
# 是否启用
enabled: true
# 显示名称
- name: dt_torrents_示例规则
+ name: all-in-one
# 规则文件订阅地址
- url: https://cdn.jsdelivr.net/gh/PBH-BTN/BTN-Collected-Rules@master/dt_torrent.txt
- # 规则ID(任意)
- hp_torrents:
- # 是否启用
- enabled: true
- # 显示名称
- name: hp_torrents_示例规则
- # 规则文件订阅地址
- url: https://cdn.jsdelivr.net/gh/PBH-BTN/BTN-Collected-Rules@master/hp_torrent.txt
- multi-dial:
- # 是否启用
- enabled: true
- # 显示名称
- name: dt_torrents_示例规则
- # 规则文件订阅地址
- url: https://cdn.jsdelivr.net/gh/PBH-BTN/BTN-Collected-Rules@master/multi-dial.txt
+ url: https://cdn.jsdelivr.net/gh/PBH-BTN/BTN-Collected-Rules@master/combine/all.txt