Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

新增 BTN Peers 活动历史记录协议 #607

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/com/ghostchu/peerbanhelper/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ private static void initGUI(String[] args) {
}

public static String getUserAgent() {
return "PeerBanHelper/" + meta.getVersion() + " BTN-Protocol/0.0.1";
return "PeerBanHelper/" + meta.getVersion() + " BTN-Protocol/0.0.2";
}

public static boolean loadDependencies(String mavenManifestPath) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.ghostchu.peerbanhelper.PeerBanHelperServer;
import com.ghostchu.peerbanhelper.btn.ability.*;
import com.ghostchu.peerbanhelper.database.dao.impl.PeerRecordDao;
import com.ghostchu.peerbanhelper.text.Lang;
import com.ghostchu.peerbanhelper.util.HTTPUtil;
import com.ghostchu.peerbanhelper.util.rule.ModuleMatchCache;
Expand Down Expand Up @@ -31,7 +32,7 @@
@Slf4j
@Getter
public class BtnNetwork {
private static final int PBH_BTN_PROTOCOL_IMPL_VERSION = 7;
private static final int PBH_BTN_PROTOCOL_IMPL_VERSION = 8;
@Getter
private final Map<Class<? extends BtnAbility>, BtnAbility> abilities = new HashMap<>();
@Getter
Expand All @@ -48,6 +49,7 @@ public class BtnNetwork {
private PeerBanHelperServer server;
private final AtomicBoolean configSuccess = new AtomicBoolean(false);
@Autowired
private PeerRecordDao peerRecordDao;
private ModuleMatchCache moduleMatchCache;

public BtnNetwork(PeerBanHelperServer server, String userAgent, String configUrl, boolean submit, String appId, String appSecret) {
Expand Down Expand Up @@ -99,6 +101,9 @@ public void configBtnNetwork() {
if (ability.has("submit_bans") && submit) {
abilities.put(BtnAbilitySubmitBans.class, new BtnAbilitySubmitBans(this, ability.get("submit_bans").getAsJsonObject()));
}
if (ability.has("submit_histories") && submit) {
abilities.put(BtnAbilitySubmitHistory.class, new BtnAbilitySubmitHistory(this, ability.get("submit_histories").getAsJsonObject()));
}
// if (ability.has("submit_hitrate") && submit) {
// abilities.put(BtnAbilitySubmitRulesHitRate.class, new BtnAbilitySubmitRulesHitRate(this, ability.get("submit_hitrate").getAsJsonObject()));
// }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.ghostchu.peerbanhelper.btn.ability;

import com.ghostchu.peerbanhelper.btn.BtnNetwork;
import com.ghostchu.peerbanhelper.btn.ping.BtnPeerHistory;
import com.ghostchu.peerbanhelper.btn.ping.BtnPeerHistoryPing;
import com.ghostchu.peerbanhelper.text.Lang;
import com.ghostchu.peerbanhelper.util.HTTPUtil;
import com.ghostchu.peerbanhelper.util.json.JsonUtil;
import com.ghostchu.peerbanhelper.util.paging.Pageable;
import com.github.mizosoft.methanol.MutableRequest;
import com.google.gson.JsonObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.ghostchu.peerbanhelper.text.TextManager.tlUI;

@Slf4j
public class BtnAbilitySubmitHistory extends AbstractBtnAbility {
private final BtnNetwork btnNetwork;
private final long interval;
private final String endpoint;
private final long randomInitialDelay;
private long lastSubmitAt = System.currentTimeMillis();

public BtnAbilitySubmitHistory(BtnNetwork btnNetwork, JsonObject ability) {
this.btnNetwork = btnNetwork;
this.interval = ability.get("interval").getAsLong();
this.endpoint = ability.get("endpoint").getAsString();
this.randomInitialDelay = ability.get("random_initial_delay").getAsLong();
}


@Override
public void load() {
setLastStatus(true, "No content reported to remote yet");
btnNetwork.getExecuteService().scheduleWithFixedDelay(this::submit, interval + new Random().nextLong(randomInitialDelay), interval, TimeUnit.MILLISECONDS);
}

private void submit() {
try {
log.info(tlUI(Lang.BTN_SUBMITTING_PEERS));
List<BtnPeerHistory> btnPeers = generatePing();
if (btnPeers.isEmpty()) {
setLastStatus(true, "Last report is empty, skipped.");
return;
}
BtnPeerHistoryPing ping = new BtnPeerHistoryPing(
System.currentTimeMillis(),
btnPeers
);
MutableRequest request = MutableRequest.POST(endpoint
, HTTPUtil.gzipBody(JsonUtil.getGson().toJson(ping).getBytes(StandardCharsets.UTF_8))
).header("Content-Encoding", "gzip");
HTTPUtil.nonRetryableSend(btnNetwork.getHttpClient(), request, HttpResponse.BodyHandlers.ofString())
.thenAccept(r -> {
if (r.statusCode() != 200) {
log.error(tlUI(Lang.BTN_REQUEST_FAILS, r.statusCode() + " - " + r.body()));
setLastStatus(false, "HTTP Error: " + r.statusCode() + " - " + r.body());
} else {
log.info(tlUI(Lang.BTN_SUBMITTED_PEERS, btnPeers.size()));
setLastStatus(true, "Reported " + btnPeers.size() + " entries.");
lastSubmitAt = System.currentTimeMillis();
}
})
.exceptionally(e -> {
log.warn(tlUI(Lang.BTN_REQUEST_FAILS), e);
setLastStatus(false, e.getClass().getName() + ": " + e.getMessage());
return null;
});
} catch (Throwable e) {
log.error("Unable to submit peers", e);
setLastStatus(false, "Unknown Error: " + e.getClass().getName() + ": " + e.getMessage());
}
}


@SneakyThrows
private List<BtnPeerHistory> generatePing() {
Pageable pageable = new Pageable(0, 10000); // 再多的话,担心爆内存
return btnNetwork.getPeerRecordDao().getPendingSubmitPeerRecords(pageable,
new Timestamp(lastSubmitAt)).getResults().stream()
.map(BtnPeerHistory::from).collect(Collectors.toList());
}

@Override
public void unload() {

}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.ghostchu.peerbanhelper.btn.ping;

import com.ghostchu.peerbanhelper.database.table.PeerRecordEntity;
import com.ghostchu.peerbanhelper.util.time.InfoHashUtil;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.sql.Timestamp;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BtnPeerHistory {
@SerializedName("ip_address")
private String ipAddress;
@SerializedName("peer_id")
private String peerId;
@SerializedName("client_name")
private String clientName;
@SerializedName("torrent_identifier")
private String torrentIdentifier;
@SerializedName("torrent_size")
private long torrentSize;
@SerializedName("downloaded")
private long downloaded;
@SerializedName("downloaded_offset")
private long downloadedOffset;
@SerializedName("uploaded")
private long uploaded;
@SerializedName("uploaded_offset")
private long uploadedOffset;
@SerializedName("first_time_seen")
private Timestamp firstTimeSeen;
@SerializedName("last_time_seen")
private Timestamp lastTimeSeen;
@SerializedName("peer_flag")
private String peerFlag;

public static BtnPeerHistory from(PeerRecordEntity peer) {
BtnPeerHistory btnPeer = new BtnPeerHistory();
btnPeer.setIpAddress(peer.getAddress());
btnPeer.setPeerId(peer.getPeerId());
btnPeer.setClientName(peer.getClientName());
String hashedId = InfoHashUtil.getHashedIdentifier(peer.getTorrent().getInfoHash());
btnPeer.setTorrentIdentifier(hashedId);
btnPeer.setTorrentSize(peer.getTorrent().getSize());
btnPeer.setDownloaded(peer.getDownloaded());
btnPeer.setDownloadedOffset(peer.getDownloadedOffset());
btnPeer.setUploaded(peer.getUploaded());
btnPeer.setUploadedOffset(peer.getUploadedOffset());
btnPeer.setFirstTimeSeen(peer.getFirstTimeSeen());
btnPeer.setLastTimeSeen(peer.getLastTimeSeen());
btnPeer.setPeerFlag(peer.getLastFlags() == null ? null : peer.getLastFlags());
return btnPeer;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.ghostchu.peerbanhelper.btn.ping;

import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BtnPeerHistoryPing {
@SerializedName("populate_time")
private long populateTime;
@SerializedName("peers")
private List<BtnPeerHistory> peers;

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.ghostchu.peerbanhelper.database.dao.AbstractPBHDao;
import com.ghostchu.peerbanhelper.database.table.PeerRecordEntity;
import com.ghostchu.peerbanhelper.database.table.TorrentEntity;
import com.ghostchu.peerbanhelper.util.paging.Page;
import com.ghostchu.peerbanhelper.util.paging.Pageable;
import com.ghostchu.peerbanhelper.wrapper.PeerWrapper;
import com.ghostchu.peerbanhelper.wrapper.TorrentWrapper;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -38,6 +40,16 @@ public void syncPendingTasks(Deque<BatchHandleTasks> tasks) throws SQLException
});
}

public Page<PeerRecordEntity> getPendingSubmitPeerRecords(Pageable pageable, Timestamp afterThan) throws SQLException {
var queryBuilder = queryBuilder().where()
.gt("lastSubmitAt", afterThan)
.or()
.isNull("lastSubmitAt")
.queryBuilder()
.orderBy("lastTimeSeen", false);
return queryByPaging(queryBuilder, pageable);
}

private int writeToDatabase(long timestamp, String downloader, TorrentWrapper torrent, PeerWrapper peer) throws SQLException {
TorrentEntity torrentEntity = torrentDao.createIfNotExists(new TorrentEntity(
null,
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public enum Lang {
BTN_INCOMPATIBLE_SERVER,
BTN_SUBMITTING_PEERS,
BTN_SUBMITTED_PEERS,
BTN_SUBMITTING_HISTORIES,
BTN_SUBMITTED_HISTORIES,
BTN_SUBMITTING_BANS,
BTN_SUBMITTED_BANS,
BTN_SUBMITTING_HITRATE,
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/lang/en_us/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ BTN_SUBMITTING_BANS: "[BTN Network] Scheduled task submitting new ban entries si
BTN_SUBMITTED_BANS: "[BTN Network] Submitted {} ban records to BTN network, thank you for supporting the BTN network!"
BTN_SUBMITTING_HITRATE: "[BTN Network] Scheduled task reporting rule hit rate data to BTN network, please wait"
BTN_SUBMITTED_HITRATE: "[BTN Network] Reported hit rate data of {} rules to BTN network, thank you for supporting the BTN network!"
BTN_SUBMITTING_HISTORIES: "[BTN Network] Scheduled task submitting {} peers history activities to network, please wait..."
BTN_SUBMITTED_HISTORIES: "[BTN Network] Submitted {} peers history activities, thank you for supporting the BTN network!"
CONFIG_CHECKING: "[Configuration Upgrade Utility] Please wait while we check configuration file updates..."
CONFIG_MIGRATING: "[Configuration Upgrade Utility] Migrating configuration file: from {} to {} ..."
CONFIG_EXECUTE_MIGRATE: "[Configuration Upgrade Utility] Executing configuration file upgrade script: {}"
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/lang/messages_fallback.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ BTN_SUBMITTING_BANS: "[BTN 网络] 计划任务正在向 BTN 网络提交自上
BTN_SUBMITTED_BANS: "[BTN 网络] 已向 BTN 网络提交 {} 个封禁记录,感谢您对 BTN 网络的支持!"
BTN_SUBMITTING_HITRATE: "[BTN 网络] 计划任务正在向 BTN 网络回报规则命中率数据,请稍等"
BTN_SUBMITTED_HITRATE: "[BTN 网络] 已向 BTN 网络回报 {} 个规则的命中率数据,感谢您对 BTN 网络的支持!"
BTN_SUBMITTING_HISTORIES: "[BTN 网络] 计划任务正在向 BTN 网络提交 {} 个 Peer 活动历史记录,请稍等……"
BTN_SUBMITTED_HISTORIES: "[BTN 网络] 已向 BTN 网络提交 {} 个 Peer 活动历史记录,感谢您对 BTN 网络的支持!"
CONFIG_CHECKING: "[配置升级实用工具] 请等待检查配置文件更新……"
CONFIG_MIGRATING: "[配置升级实用工具] 迁移配置文件:从 {} 至 {} ……"
CONFIG_EXECUTE_MIGRATE: "[配置升级实用工具] 执行配置文件升级脚本:{}"
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/lang/zh_cn/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ BTN_SUBMITTING_BANS: "[BTN 网络] 计划任务正在向 BTN 网络提交自上
BTN_SUBMITTED_BANS: "[BTN 网络] 已向 BTN 网络提交 {} 个封禁记录,感谢您对 BTN 网络的支持!"
BTN_SUBMITTING_HITRATE: "[BTN 网络] 计划任务正在向 BTN 网络回报规则命中率数据,请稍等"
BTN_SUBMITTED_HITRATE: "[BTN 网络] 已向 BTN 网络回报 {} 个规则的命中率数据,感谢您对 BTN 网络的支持!"
BTN_SUBMITTING_HISTORIES: "[BTN 网络] 计划任务正在向 BTN 网络提交 {} 个 Peer 活动历史记录,请稍等……"
BTN_SUBMITTED_HISTORIES: "[BTN 网络] 已向 BTN 网络提交 {} 个 Peer 活动历史记录,感谢您对 BTN 网络的支持!"
CONFIG_CHECKING: "[配置升级实用工具] 请等待检查配置文件更新……"
CONFIG_MIGRATING: "[配置升级实用工具] 迁移配置文件:从 {} 至 {} ……"
CONFIG_EXECUTE_MIGRATE: "[配置升级实用工具] 执行配置文件升级脚本:{}"
Expand Down
Loading