blob: 5ca7c0490e15b2bebfa995c1a796b0bbd419d1c0 [file] [log] [blame]
package cheat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import org.apache.commons.lang3.tuple.Pair;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import com.querydsl.jpa.impl.JPAQueryFactory;
import entity.Seed;
import entity.Appeal;
import entity.QAppeal;
import entity.QSeed;
import entity.User;
import entity.config;
import entity.QUser;
import entity.TTorent;
import entity.QTransRecord;
import entity.TransRecord;
public class Cheat implements CheatInterfnterface {
@PersistenceContext
private EntityManagerFactory emf;
public Cheat() {
config cfg = new config();
Map<String,Object> props = new HashMap<>();
props.put("javax.persistence.jdbc.url",
"jdbc:mysql://" + cfg.SqlURL + "/" + cfg.Database);
props.put("javax.persistence.jdbc.user", cfg.SqlUsername);
props.put("javax.persistence.jdbc.password", cfg.SqlPassword);
this.emf = Persistence.createEntityManagerFactory("myPersistenceUnit", props);
}
@Override
@Transactional
public boolean AddAppeal(Appeal appeal) {
EntityManager entityManager = emf.createEntityManager();
try {
entityManager.getTransaction().begin();
entityManager.persist(appeal);
entityManager.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
if (entityManager.getTransaction().isActive()) {
entityManager.getTransaction().rollback();
}
return false;
}
return true;
}
@Override
public Appeal GetAppeal(String appealid) {
try {
EntityManager entityManager = emf.createEntityManager();
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QAppeal qAppeal = QAppeal.appeal;
Appeal appeal = queryFactory
.selectFrom(qAppeal)
.where(qAppeal.appealid.eq(appealid))
.fetchOne();
return appeal;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public Appeal[] GetAppealList() {
EntityManager entityManager = emf.createEntityManager();
try {
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QAppeal qAppeal = QAppeal.appeal;
List<Appeal> appeals = queryFactory
.selectFrom(qAppeal)
.fetch();
return appeals.toArray(new Appeal[0]);
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (entityManager != null) {
entityManager.close();
}
}
}
@Override
public boolean HandleAppeal(String appealid, Integer status) {
EntityManager entityManager = emf.createEntityManager();
try {
Appeal appeal = GetAppeal(appealid);
if (appeal != null) {
appeal.status = status;
entityManager.getTransaction().begin();
entityManager.merge(appeal);
User user = entityManager.find(User.class, appeal.appealuserid);
// if (user != null && user.accountstate != false) {
if (user != null) {
if (status == 1) {
user.accountstate = false;
}
entityManager.merge(user);
}
entityManager.getTransaction().commit();
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
if (emf.createEntityManager().getTransaction().isActive()) {
emf.createEntityManager().getTransaction().rollback();
}
return false;
} finally {
if (entityManager != null) {
entityManager.close();
}
}
}
@Override
public Pair<String, String>[] GetFakeSeed() {
List<Pair<String, String>> fakeSeeds = new ArrayList<>();
try {
EntityManager entityManager = emf.createEntityManager();
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QSeed qSeed = QSeed.seed;
List<com.querydsl.core.Tuple> results = queryFactory
.select(qSeed.seedid, qSeed.seeduserid)
.from(qSeed)
.where(qSeed.faketime.gt(config.getFakeTime()))
.fetch();
for (com.querydsl.core.Tuple result : results) {
String seedid = result.get(qSeed.seedid);
String userid = result.get(qSeed.seeduserid);
fakeSeeds.add(Pair.of(seedid, userid));
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return fakeSeeds.toArray(new Pair[0]);
}
@Override
public String[] GetPunishedUserList() {
List<String> punishedUsers = new ArrayList<>();
try {
EntityManager entityManager = emf.createEntityManager();
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
entity.QUser qUser = entity.QUser.user;
List<String> results = queryFactory
.select(qUser.userid)
.from(qUser)
.where(qUser.accountstate.isTrue())
.fetch();
for (String userid : results) {
punishedUsers.add(userid);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return punishedUsers.toArray(new String[0]);
}
@Override
public void DetectTrans() {
EntityManager entityManager = emf.createEntityManager();
try {
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QSeed qSeed = QSeed.seed;
QTransRecord qTransRecord = QTransRecord.transRecord;
// 获取所有种子
List<Seed> seeds = queryFactory
.selectFrom(qSeed)
.fetch();
// 存储每个种子的delta值
List<Double> allDeltas = new ArrayList<>();
Map<String, Double> seedDeltaMap = new HashMap<>();
// 计算每个种子的delta值(只考虑account_status不为1的用户)
for (Seed seed : seeds) {
List<TransRecord> tasks = queryFactory
.selectFrom(qTransRecord)
.leftJoin(qTransRecord.uploader).fetchJoin()
.leftJoin(qTransRecord.downloader).fetchJoin()
.where(qTransRecord.seedid.eq(seed.seedid))
.fetch();
// 过滤掉account_status为1的用户的记录
List<TransRecord> validTasks = new ArrayList<>();
for (TransRecord task : tasks) {
boolean shouldInclude = true;
// 检查上传者
if (task.uploaduserid != null) {
User uploader = entityManager.find(User.class, task.uploaduserid);
if (uploader != null && uploader.accountstate) {
shouldInclude = false;
}
}
// 检查下载者
if (task.downloaduserid != null) {
User downloader = entityManager.find(User.class, task.downloaduserid);
if (downloader != null && downloader.accountstate) {
shouldInclude = false;
}
}
if (shouldInclude) {
validTasks.add(task);
}
}
if (validTasks.isEmpty()) continue;
// 计算该种子的总delta
double totalDelta = 0;
for (TransRecord task : validTasks) {
long upload = task.upload != null ? task.upload : 0L;
long download = task.download != null ? task.download : 0L;
totalDelta += (upload - download);
}
allDeltas.add(totalDelta);
seedDeltaMap.put(seed.seedid, totalDelta);
}
if (allDeltas.size() < 2) return; // 需要至少2个种子才能计算标准差
// 计算平均值和标准差
double sum = 0;
for (double delta : allDeltas) {
sum += delta;
}
double mean = sum / allDeltas.size();
double variance = 0;
for (double delta : allDeltas) {
variance += Math.pow(delta - mean, 2);
}
double stdDev = Math.sqrt(variance / allDeltas.size());
// 检测异常种子并处理参与者
for (Seed seed : seeds) {
Double seedDelta = seedDeltaMap.get(seed.seedid);
if (seedDelta == null) continue;
// 检查是否偏离1个标准差
if (Math.abs(seedDelta - mean) > stdDev) {
// 获取该种子的所有传输记录参与者
List<TransRecord> suspiciousTasks = queryFactory
.selectFrom(qTransRecord)
.where(qTransRecord.seedid.eq(seed.seedid))
.fetch();
// 更新所有参与者的detectedCount
for (TransRecord task : suspiciousTasks) {
// 处理上传者
if (task.uploaduserid != null) {
User uploader = entityManager.find(User.class, task.uploaduserid);
if (uploader != null && !uploader.accountstate) {
uploader.detectedCount++;
uploader.lastDetectedTime = new java.util.Date();
entityManager.merge(uploader);
}
}
// 处理下载者
if (task.downloaduserid != null) {
User downloader = entityManager.find(User.class, task.downloaduserid);
if (downloader != null && !downloader.accountstate) {
downloader.detectedCount++;
downloader.lastDetectedTime = new java.util.Date();
entityManager.merge(downloader);
}
}
}
}
}
} finally {
if (entityManager != null) {
entityManager.close();
}
}
}
@Override
@Transactional
public void DetectFakeSeed(){
EntityManager entityManager = emf.createEntityManager();
try {
String torrentDir = entity.config.TORRENT_STORAGE_DIR;
String scriptPath = "./src/main/java/cheat/fakeSeed.bash";
ProcessBuilder processBuilder = new ProcessBuilder("bash", scriptPath, torrentDir);
processBuilder.inheritIO();
Process process = processBuilder.start();
int exitCode = process.waitFor();
if (exitCode == 0) {
System.out.println("FakeSeed detection completed successfully");
// 处理检测结果
String failedDir = torrentDir + "/failed_torrents";
java.io.File failedDirFile = new java.io.File(failedDir);
// 获取失败种子文件列表
java.util.Set<String> failedTorrentNames = new java.util.HashSet<>();
if (failedDirFile.exists() && failedDirFile.isDirectory()) {
java.io.File[] failedFiles = failedDirFile.listFiles((dir, name) -> name.endsWith(".torrent"));
if (failedFiles != null) {
for (java.io.File file : failedFiles) {
failedTorrentNames.add(file.getName());
}
}
}
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QSeed qSeed = QSeed.seed;
// 收集假种子的拥有者
java.util.Set<String> fakeOwners = new java.util.HashSet<>();
// 更新数据库中的fake_hits字段
List<Seed> allSeeds = queryFactory
.selectFrom(qSeed)
.where(qSeed.url.isNotNull())
.fetch();
for (Seed seed : allSeeds) {
java.io.File seedFile = new java.io.File(seed.url);
String fileName = seedFile.getName();
if (failedTorrentNames.contains(fileName)) {
// 失败种子,fake_hits + 1
seed.faketime++;
seed.lastfakecheck = new java.util.Date();
fakeOwners.add(seed.seeduserid);
System.out.println("Found fake seed: " + seed.seedid + " (fake_hits: " + seed.faketime + ")");
} else {
// 正常种子,fake_hits 清零
if (seed.faketime > 0) {
seed.faketime = 0;
seed.lastfakecheck = new java.util.Date();
System.out.println("Reset fake_hits for seed: " + seed.seedid);
}
}
entityManager.merge(seed);
}
// 更新所有用户的 fakeDetectedCount 和 fakeLastDetectedTime
entity.QUser qUser = entity.QUser.user;
List<User> allUsers = queryFactory
.selectFrom(qUser)
.fetch();
java.util.Date now = new java.util.Date();
for (User user : allUsers) {
if (fakeOwners.contains(user.userid)) {
// 假种子拥有者,fakeDetectedCount + 1
user.fakeDetectedCount++;
System.out.println("Increased fake detection count for user: " + user.userid + " (count: " + user.fakeDetectedCount + ")");
} else {
// 其他用户,fakeDetectedCount 清零
if (user.fakeDetectedCount > 0) {
user.fakeDetectedCount = 0;
System.out.println("Reset fake detection count for user: " + user.userid);
}
}
// 更新所有用户的检测时间
user.fakeLastDetectedTime = now;
entityManager.merge(user);
}
System.out.println("Fake seed detection and database update completed");
} else {
System.err.println("FakeSeed detection failed with exit code: " + exitCode);
}
} catch (Exception e) {
System.err.println("Error running FakeSeed detection script: " + e.getMessage());
e.printStackTrace();
} finally {
if (entityManager != null) {
entityManager.close();
}
}
}
@Override
public boolean DetectFakeSeed(String seedid){
return false;
}
@Override
public void PunishUser(){
EntityManager entityManager = emf.createEntityManager();
try {
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
entity.QUser qUser = entity.QUser.user;
List<User> users = queryFactory
.selectFrom(qUser)
.where(qUser.detectedCount.gt(config.getCheatTime())
.or(qUser.fakeDetectedCount.gt(config.getFakeTime())))
.fetch();
if (users.isEmpty()) {
System.out.println("No users to punish.");
return;
}
entityManager.getTransaction().begin();
for (User user : users) {
user.accountstate = true;
entityManager.merge(user);
}
entityManager.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (entityManager != null) {
entityManager.close();
}
}
}
@Override
public User[] GetCheatUsers() {
EntityManager entityManager = emf.createEntityManager();
List<User> cheatUsers = new ArrayList<>();
try {
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QUser qUser = QUser.user;
cheatUsers = queryFactory
.selectFrom(qUser)
.where(qUser.accountstate.eq(true))
.fetch();
return cheatUsers.toArray(new User[0]);
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (entityManager != null){
entityManager.close();
}
}
}
@Override
public User[] GetSuspiciousUsers() {
EntityManager entityManager = emf.createEntityManager();
List<User> suspiciousUsers = new ArrayList<>();
try {
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QUser qUser = QUser.user;
suspiciousUsers = queryFactory
.selectFrom(qUser)
.where((qUser.detectedCount.gt(0)
.or(qUser.fakeDetectedCount.gt(0)))
.and(qUser.accountstate.eq(false)))
.fetch();
return suspiciousUsers.toArray(new User[0]);
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (entityManager != null){
entityManager.close();
}
}
}
@Override
public int UnbanUser(String userid) {
EntityManager entityManager = emf.createEntityManager();
try {
User user = entityManager.find(User.class, userid);
if (user == null) {
return 1; // 用户不存在
}
if (user.accountstate) {
user.accountstate = false; // 解封用户
entityManager.getTransaction().begin();
entityManager.merge(user);
entityManager.getTransaction().commit();
return 0; // 成功解封
}
return 2; // 用户未被封禁
} catch (Exception e) {
e.printStackTrace();
if (entityManager.getTransaction().isActive()) {
entityManager.getTransaction().rollback();
}
return -1; // 出现异常
} finally {
if (entityManager != null){
entityManager.close();
}
}
}
@Override
public int BanUser(String userid) {
EntityManager entityManager = emf.createEntityManager();
try {
User user = entityManager.find(User.class, userid);
if (user == null) {
return 1; // 用户不存在
}
if (!user.accountstate) {
user.accountstate = true; // 封禁用户
entityManager.getTransaction().begin();
entityManager.merge(user);
entityManager.getTransaction().commit();
return 0; // 成功封禁
}
return 2; // 用户已被封禁
} catch (Exception e) {
e.printStackTrace();
if (entityManager.getTransaction().isActive()) {
entityManager.getTransaction().rollback();
}
return -1; // 出现异常
} finally {
if (entityManager != null){
entityManager.close();
}
}
}
@Override
public int SubmitAppeal(String userid, String content, File file) {
EntityManager entityManager = emf.createEntityManager();
try {
User user = entityManager.find(User.class, userid);
if (user == null) {
return 1; // 用户不存在
}
Appeal appeal = new Appeal();
appeal.appealid = java.util.UUID.randomUUID().toString();
appeal.appealuserid = userid;
appeal.content = content;
appeal.user = user; // 设置关联的用户
Path storageDir = Paths.get(config.APPEAL_STORAGE_DIR);
if (!Files.exists(storageDir)) {
Files.createDirectories(storageDir);
}
String filename = file.getName();
Path target = storageDir.resolve(appeal.appealid + "_" + filename);
Files.copy(file.toPath(), target, StandardCopyOption.REPLACE_EXISTING);
appeal.status = 0; // 初始状态为未处理
appeal.fileURL = target.toString(); // 设置文件存储路径
entityManager.getTransaction().begin();
entityManager.persist(appeal);
entityManager.getTransaction().commit();
return 0; // 成功提交申诉
} catch (Exception e) {
e.printStackTrace();
if (entityManager.getTransaction().isActive()) {
entityManager.getTransaction().rollback();
}
return -1; // 出现异常
} finally {
if (entityManager != null){
entityManager.close();
}
}
}
}