From cb4f28cdeba0e0aadf1dd1c27423d6d55b40e0d0 Mon Sep 17 00:00:00 2001 From: wushuo Date: Mon, 28 Oct 2024 00:26:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=85=E5=9C=A8=E4=B8=BBRSS=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=90=8E=E5=88=A0=E9=99=A4=E5=A4=87=E7=94=A8RSS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/ani/rss/download/Aria2.java | 13 ++- .../java/ani/rss/download/BaseDownload.java | 4 +- .../java/ani/rss/download/Transmission.java | 42 +++++--- .../java/ani/rss/download/qBittorrent.java | 29 +++-- src/main/java/ani/rss/entity/Config.java | 5 + .../ani/rss/enums/ServerChanTypeEnum.java | 10 +- src/main/java/ani/rss/enums/TorrentsTags.java | 15 +++ src/main/java/ani/rss/task/RenameTask.java | 4 + src/main/java/ani/rss/util/ConfigUtil.java | 1 + src/main/java/ani/rss/util/TorrentUtil.java | 102 +++++++++++++----- .../resources/transmission/torrent-add.json | 5 +- ui/src/config/Download.vue | 4 + ui/src/home/Config.vue | 1 + 13 files changed, 168 insertions(+), 67 deletions(-) create mode 100644 src/main/java/ani/rss/enums/TorrentsTags.java diff --git a/src/main/java/ani/rss/download/Aria2.java b/src/main/java/ani/rss/download/Aria2.java index 9367b3f6..58d6f4ed 100644 --- a/src/main/java/ani/rss/download/Aria2.java +++ b/src/main/java/ani/rss/download/Aria2.java @@ -162,16 +162,21 @@ public Boolean download(Item item, String savePath, File torrentFile, Boolean ov } @Override - public void delete(TorrentsInfo torrentsInfo) { + public Boolean delete(TorrentsInfo torrentsInfo) { String host = config.getHost(); String password = config.getPassword(); String id = torrentsInfo.getId(); String body = ResourceUtil.readUtf8Str("aria2/removeDownloadResult.json"); body = StrFormatter.format(body, password, id); - HttpReq.post(host + "/jsonrpc", false) - .body(body) - .thenFunction(HttpResponse::isOk); + try { + return HttpReq.post(host + "/jsonrpc", false) + .body(body) + .thenFunction(HttpResponse::isOk); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } } @Override diff --git a/src/main/java/ani/rss/download/BaseDownload.java b/src/main/java/ani/rss/download/BaseDownload.java index 736fe609..22675f08 100644 --- a/src/main/java/ani/rss/download/BaseDownload.java +++ b/src/main/java/ani/rss/download/BaseDownload.java @@ -16,8 +16,6 @@ public interface BaseDownload { Cache renameCache = CacheUtil.newFIFOCache(512); - String tag = "ani-rss"; - List videoFormat = List.of("mp4", "mkv", "avi", "wmv"); List subtitleFormat = List.of("ass", "ssa", "sub", "srt", "lyc"); @@ -50,7 +48,7 @@ public interface BaseDownload { * * @param torrentsInfo */ - void delete(TorrentsInfo torrentsInfo); + Boolean delete(TorrentsInfo torrentsInfo); /** * 重命名 diff --git a/src/main/java/ani/rss/download/Transmission.java b/src/main/java/ani/rss/download/Transmission.java index cd6bca74..daefd14b 100644 --- a/src/main/java/ani/rss/download/Transmission.java +++ b/src/main/java/ani/rss/download/Transmission.java @@ -3,6 +3,7 @@ import ani.rss.entity.Config; import ani.rss.entity.Item; import ani.rss.entity.TorrentsInfo; +import ani.rss.enums.TorrentsTags; import ani.rss.util.ExceptionUtil; import ani.rss.util.GsonStatic; import ani.rss.util.HttpReq; @@ -95,7 +96,7 @@ public List getTorrentsInfos() { JsonObject item = jsonElement.getAsJsonObject(); List tags = item.get("labels").getAsJsonArray() .asList().stream().map(JsonElement::getAsString).collect(Collectors.toList()); - if (!tags.contains(tag)) { + if (!tags.contains(TorrentsTags.ANI_RSS.getValue())) { continue; } List files = item.get("files").getAsJsonArray().asList() @@ -135,6 +136,7 @@ public List getTorrentsInfos() { @Override public Boolean download(Item item, String savePath, File torrentFile, Boolean ova) { String name = item.getReName(); + Boolean master = item.getMaster(); String subgroup = item.getSubgroup(); subgroup = StrUtil.blankToDefault(subgroup, "未知字幕组"); String body = ResourceUtil.readUtf8Str("transmission/torrent-add.json"); @@ -142,13 +144,21 @@ public Boolean download(Item item, String savePath, File torrentFile, Boolean ov if (StrUtil.isBlank(extName)) { return false; } - String torrent = ""; + + List tags = new ArrayList<>(); + tags.add(TorrentsTags.ANI_RSS.getValue()); + tags.add(subgroup); + if (!master) { + tags.add(TorrentsTags.BACK_RSS.getValue()); + } + + String torrent; if ("txt".equals(extName)) { torrent = FileUtil.readUtf8String(torrentFile); - body = StrFormatter.format(body, tag, subgroup, savePath, "", torrent); + body = StrFormatter.format(body, GsonStatic.toJson(tags), savePath, "", torrent); } else { torrent = Base64.encode(torrentFile); - body = StrFormatter.format(body, tag, subgroup, savePath, torrent, ""); + body = StrFormatter.format(body, GsonStatic.toJson(tags), savePath, torrent, ""); } String id = HttpReq.post(host + "/transmission/rpc", false) @@ -191,14 +201,19 @@ public Boolean download(Item item, String savePath, File torrentFile, Boolean ov } @Override - public void delete(TorrentsInfo torrentsInfo) { + public Boolean delete(TorrentsInfo torrentsInfo) { String body = ResourceUtil.readUtf8Str("transmission/torrent-remove.json"); body = StrFormatter.format(body, torrentsInfo.getId()); - HttpReq.post(host + "/transmission/rpc", false) - .header(Header.AUTHORIZATION, authorization) - .header("X-Transmission-Session-Id", sessionId) - .body(body) - .then(HttpResponse::isOk); + try { + return HttpReq.post(host + "/transmission/rpc", false) + .header(Header.AUTHORIZATION, authorization) + .header("X-Transmission-Session-Id", sessionId) + .body(body) + .thenFunction(HttpResponse::isOk); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } } @Override @@ -233,10 +248,11 @@ public void rename(TorrentsInfo torrentsInfo) { } @Override - public Boolean addTags(TorrentsInfo torrentsInfo, String tags) { + public Boolean addTags(TorrentsInfo torrentsInfo, String tag) { String id = torrentsInfo.getId(); - List strings = new ArrayList<>(List.of(torrentsInfo.getTags().split(","))); - strings.add(tags); + String tags = torrentsInfo.getTags(); + List strings = new ArrayList<>(StrUtil.split(tags, ",", true, true)); + strings.add(tag); String body = ResourceUtil.readUtf8Str("transmission/torrent-set.json"); body = StrFormatter.format(body, GsonStatic.toJson(strings), id); diff --git a/src/main/java/ani/rss/download/qBittorrent.java b/src/main/java/ani/rss/download/qBittorrent.java index 07c74692..87fb7585 100644 --- a/src/main/java/ani/rss/download/qBittorrent.java +++ b/src/main/java/ani/rss/download/qBittorrent.java @@ -4,6 +4,7 @@ import ani.rss.entity.Item; import ani.rss.entity.TorrentsInfo; import ani.rss.enums.StringEnum; +import ani.rss.enums.TorrentsTags; import ani.rss.util.ExceptionUtil; import ani.rss.util.GsonStatic; import ani.rss.util.HttpReq; @@ -84,7 +85,7 @@ public List getTorrentsInfos() { continue; } // 包含标签 - if (StrUtil.split(tags, ",", true, true).contains(tag)) { + if (StrUtil.split(tags, ",", true, true).contains(TorrentsTags.ANI_RSS.getValue())) { torrentsInfoList.add(torrentsInfo); } } @@ -95,10 +96,19 @@ public List getTorrentsInfos() { @Override public Boolean download(Item item, String savePath, File torrentFile, Boolean ova) { String name = item.getReName(); + Boolean master = item.getMaster(); String subgroup = item.getSubgroup(); subgroup = StrUtil.blankToDefault(subgroup, "未知字幕组"); String host = config.getHost(); Boolean qbUseDownloadPath = config.getQbUseDownloadPath(); + + List tags = new ArrayList<>(); + tags.add(TorrentsTags.ANI_RSS.getValue()); + tags.add(subgroup); + if (!master) { + tags.add(TorrentsTags.BACK_RSS.getValue()); + } + HttpRequest httpRequest = HttpReq.post(host + "/api/v2/torrents/add", false) .form("addToTopOfQueue", false) .form("autoTMM", false) @@ -113,7 +123,7 @@ public Boolean download(Item item, String savePath, File torrentFile, Boolean ov .form("stopCondition", "None") .form("upLimit", 102400) .form("useDownloadPath", qbUseDownloadPath) - .form("tags", "ani-rss," + subgroup); + .form("tags", CollUtil.join(tags, ",")); String extName = FileUtil.extName(torrentFile); if ("txt".equals(extName)) { @@ -150,13 +160,18 @@ public Boolean download(Item item, String savePath, File torrentFile, Boolean ov } @Override - public void delete(TorrentsInfo torrentsInfo) { + public Boolean delete(TorrentsInfo torrentsInfo) { String host = config.getHost(); String hash = torrentsInfo.getHash(); - HttpReq.post(host + "/api/v2/torrents/delete", false) - .form("hashes", hash) - .form("deleteFiles", false) - .thenFunction(HttpResponse::isOk); + try { + return HttpReq.post(host + "/api/v2/torrents/delete", false) + .form("hashes", hash) + .form("deleteFiles", false) + .thenFunction(HttpResponse::isOk); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } } @Override diff --git a/src/main/java/ani/rss/entity/Config.java b/src/main/java/ani/rss/entity/Config.java index 33a30efa..07b1ef51 100644 --- a/src/main/java/ani/rss/entity/Config.java +++ b/src/main/java/ani/rss/entity/Config.java @@ -108,6 +108,11 @@ public class Config implements Serializable { */ private Boolean delete; + /** + * 仅在主RSS更新后删除备用RSS + */ + private Boolean deleteBackRSSOnly; + /** * 自动推断剧集偏移 */ diff --git a/src/main/java/ani/rss/enums/ServerChanTypeEnum.java b/src/main/java/ani/rss/enums/ServerChanTypeEnum.java index c32563df..4eaf4284 100644 --- a/src/main/java/ani/rss/enums/ServerChanTypeEnum.java +++ b/src/main/java/ani/rss/enums/ServerChanTypeEnum.java @@ -1,8 +1,10 @@ package ani.rss.enums; +import lombok.AllArgsConstructor; import lombok.Getter; @Getter +@AllArgsConstructor public enum ServerChanTypeEnum { SERVER_CHAN("serverChan", "server酱", "https://sctapi.ftqq.com/.send", "SCT"), SERVER_CHAN_3("serverChan3", "server酱³", "https://.push.ft07.com/send/.send", "sct"); @@ -11,12 +13,4 @@ public enum ServerChanTypeEnum { private final String name; private final String url; private final String sendkeyPrefix; - - ServerChanTypeEnum(String type, String name, String url, String sendKeyPrefix) { - this.type = type; - this.name = name; - this.url = url; - this.sendkeyPrefix = sendKeyPrefix; - } - } diff --git a/src/main/java/ani/rss/enums/TorrentsTags.java b/src/main/java/ani/rss/enums/TorrentsTags.java new file mode 100644 index 00000000..5269d203 --- /dev/null +++ b/src/main/java/ani/rss/enums/TorrentsTags.java @@ -0,0 +1,15 @@ +package ani.rss.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum TorrentsTags { + ANI_RSS("ani-rss"), + RENAME("RENAME"), + BACK_RSS("备用RSS"), + DOWNLOAD_COMPLETE("下载完成"); + + private final String value; +} diff --git a/src/main/java/ani/rss/task/RenameTask.java b/src/main/java/ani/rss/task/RenameTask.java index 7805e5db..62de5e6f 100644 --- a/src/main/java/ani/rss/task/RenameTask.java +++ b/src/main/java/ani/rss/task/RenameTask.java @@ -29,6 +29,7 @@ public void run() { super.setName("rename-task-thread"); Config config = ConfigUtil.CONFIG; double renameSleep = config.getRenameSleep(); + Boolean deleteBackRSSOnly = config.getDeleteBackRSSOnly(); log.info("{} 当前设置间隔为 {} 分钟", getName(), renameSleep); while (loop.get()) { @@ -45,6 +46,9 @@ public void run() { try { TorrentUtil.rename(torrentsInfo); TorrentUtil.notification(torrentsInfo); + if (deleteBackRSSOnly) { + continue; + } TorrentUtil.delete(torrentsInfo); } catch (Exception e) { log.error(e.getMessage(), e); diff --git a/src/main/java/ani/rss/util/ConfigUtil.java b/src/main/java/ani/rss/util/ConfigUtil.java index 856fb966..4c13bc5f 100644 --- a/src/main/java/ani/rss/util/ConfigUtil.java +++ b/src/main/java/ani/rss/util/ConfigUtil.java @@ -38,6 +38,7 @@ public class ConfigUtil { .setFileExist(false) .setAwaitStalledUP(true) .setDelete(false) + .setDeleteBackRSSOnly(false) .setOffset(false) .setTitleYear(false) .setAcronym(false) diff --git a/src/main/java/ani/rss/util/TorrentUtil.java b/src/main/java/ani/rss/util/TorrentUtil.java index 46fbc246..4bdbcc09 100644 --- a/src/main/java/ani/rss/util/TorrentUtil.java +++ b/src/main/java/ani/rss/util/TorrentUtil.java @@ -7,6 +7,7 @@ import ani.rss.entity.TorrentsInfo; import ani.rss.enums.MessageEnum; import ani.rss.enums.StringEnum; +import ani.rss.enums.TorrentsTags; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; @@ -38,6 +39,7 @@ public static synchronized void downloadAni(Ani ani) { Boolean autoDisabled = config.getAutoDisabled(); Integer downloadCount = config.getDownloadCount(); Integer delayedDownload = config.getDelayedDownload(); + Boolean deleteBackRSSOnly = config.getDeleteBackRSSOnly(); String title = ani.getTitle(); Integer season = ani.getSeason(); @@ -102,6 +104,29 @@ public static synchronized void downloadAni(Ani ani) { } } + // 仅在主RSS更新后删除备用RSS + if (master && deleteBackRSSOnly) { + TorrentsInfo backRSS = torrentsInfos + .stream() + .filter(torrentsInfo -> { + if (!reName.equals(torrentsInfo.getName())) { + return false; + } + List strings = new ArrayList<>(List.of(torrentsInfo.getTags().split(","))); + return strings.contains(TorrentsTags.BACK_RSS.getValue()); + }) + .findFirst() + .orElse(null); + + if (Objects.nonNull(backRSS)) { + if (!delete(backRSS)) { + // 删除失败或者不允许删除 + continue; + } + torrentsInfos.remove(backRSS); + } + } + // 已经下载过 if (hashList.contains(hash) || downloadNameList.contains(reName)) { log.debug("已有下载任务 {}", reName); @@ -639,20 +664,24 @@ public static synchronized void notification(TorrentsInfo torrentsInfo) { // 添加下载完成标签,防止重复通知 String tags = torrentsInfo.getTags(); List tagList = StrUtil.split(tags, ",", true, true); - if (tagList.contains("下载完成")) { + if (tagList.contains(TorrentsTags.DOWNLOAD_COMPLETE.getValue())) { return; } - Boolean b = TorrentUtil.addTags(torrentsInfo, "下载完成"); + Boolean b = TorrentUtil.addTags(torrentsInfo, TorrentsTags.DOWNLOAD_COMPLETE.getValue()); if (!b) { return; } Ani ani = null; try { ani = findAniByName(name); + + Set allTags = Arrays.stream(TorrentsTags.values()) + .map(TorrentsTags::getValue) + .collect(Collectors.toSet()); + String subgroup = tagList .stream() - .filter(s -> !BaseDownload.tag.equals(s)) - .filter(s -> !"RENAME".equals(s)) + .filter(s -> !allTags.contains(s)) .findFirst() .orElse(""); subgroup = StrUtil.blankToDefault(subgroup, "未知字幕组"); @@ -739,47 +768,64 @@ public static synchronized Ani findAniByName(String name) { } /** - * 删除已完成任务 + * 判断种子是否可以删除 * * @param torrentsInfo + * @return */ - public static synchronized void delete(TorrentsInfo torrentsInfo) { + public static Boolean isDelete(TorrentsInfo torrentsInfo) { Config config = ConfigUtil.CONFIG; - Boolean delete = config.getDelete(); Boolean awaitStalledUP = config.getAwaitStalledUP(); TorrentsInfo.State state = torrentsInfo.getState(); - String name = torrentsInfo.getName(); if (Objects.isNull(state)) { - return; + return false; } // 是否等待做种完毕 if (awaitStalledUP) { - if (!List.of( - TorrentsInfo.State.pausedUP.name(), - TorrentsInfo.State.stoppedUP.name() - ).contains(state.name())) { - return; - } - } else { - if (!List.of( - TorrentsInfo.State.uploading.name(), - TorrentsInfo.State.stalledUP.name(), + return List.of( TorrentsInfo.State.pausedUP.name(), TorrentsInfo.State.stoppedUP.name() - ).contains(state.name())) { - return; - } + ).contains(state.name()); + } + + return List.of( + TorrentsInfo.State.uploading.name(), + TorrentsInfo.State.stalledUP.name(), + TorrentsInfo.State.pausedUP.name(), + TorrentsInfo.State.stoppedUP.name() + ).contains(state.name()); + } + + /** + * 删除已完成任务 + * + * @param torrentsInfo + */ + public static synchronized Boolean delete(TorrentsInfo torrentsInfo) { + Config config = ConfigUtil.CONFIG; + Boolean delete = config.getDelete(); + + if (!isDelete(torrentsInfo)) { + return false; } + String name = torrentsInfo.getName(); - if (delete) { - log.info("删除已完成任务 {}", name); - ThreadUtil.sleep(1000); - baseDownload.delete(torrentsInfo); + if (!delete) { + return false; + } + log.info("删除已完成任务 {}", name); + ThreadUtil.sleep(500); + Boolean b = baseDownload.delete(torrentsInfo); + if (b) { + log.info("删除任务成功 {}", name); + } else { + log.error("删除任务失败 {}", name); } + return b; } /** @@ -796,13 +842,13 @@ public static synchronized void rename(TorrentsInfo torrentsInfo) { String tags = torrentsInfo.getTags(); if (StrUtil.split(tags, ",", true, true) - .contains("RENAME")) { + .contains(TorrentsTags.RENAME.getValue())) { return; } ThreadUtil.sleep(1000); baseDownload.rename(torrentsInfo); - addTags(torrentsInfo, "RENAME"); + addTags(torrentsInfo, TorrentsTags.RENAME.getValue()); } public static Boolean addTags(TorrentsInfo torrentsInfo, String tags) { diff --git a/src/main/resources/transmission/torrent-add.json b/src/main/resources/transmission/torrent-add.json index 7c7bcd53..b7b9e276 100644 --- a/src/main/resources/transmission/torrent-add.json +++ b/src/main/resources/transmission/torrent-add.json @@ -1,9 +1,6 @@ { "arguments": { - "labels": [ - "{}", - "{}" - ], + "labels": {}, "download-dir": "{}", "metainfo": "{}", "filename": "{}", diff --git a/ui/src/config/Download.vue b/ui/src/config/Download.vue index 4aa169ff..3a6fe0fc 100644 --- a/ui/src/config/Download.vue +++ b/ui/src/config/Download.vue @@ -46,6 +46,10 @@ :disabled="!props.config.delete" label="等待做种完毕"/>
+ +
自动删除已完成的任务, 不会删除本地文件
diff --git a/ui/src/home/Config.vue b/ui/src/home/Config.vue index 593834a8..c9bb9a49 100644 --- a/ui/src/home/Config.vue +++ b/ui/src/home/Config.vue @@ -79,6 +79,7 @@ const config = ref({ 'fileExist': true, 'awaitStalledUP': true, 'delete': false, + 'deleteBackRSSOnly': false, 'offset': false, 'acronym': false, 'titleYear': false,