From 2f3417705ddff24f85d2311ee8502187de0dfa83 Mon Sep 17 00:00:00 2001 From: LamGC Date: Wed, 29 Jul 2020 02:43:49 +0800 Subject: [PATCH] =?UTF-8?q?[Add]=20=E4=B8=BA=E6=90=9C=E7=B4=A2=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E4=BC=98=E5=8C=96=E7=BF=BB=E9=A1=B5=E5=8A=9F=E8=83=BD?= =?UTF-8?q?;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Change] BotCommandProcess 重制search命令, 增加用于获取范围相关搜索结果页面的`getSearchResult`方法, 调整消息格式; --- .../net/lamgc/cgj/bot/BotCommandProcess.java | 197 ++++++++++-------- 1 file changed, 112 insertions(+), 85 deletions(-) diff --git a/src/main/java/net/lamgc/cgj/bot/BotCommandProcess.java b/src/main/java/net/lamgc/cgj/bot/BotCommandProcess.java index 126a35a..841d0f8 100644 --- a/src/main/java/net/lamgc/cgj/bot/BotCommandProcess.java +++ b/src/main/java/net/lamgc/cgj/bot/BotCommandProcess.java @@ -13,8 +13,10 @@ import net.lamgc.cgj.bot.sort.PreLoadDataAttribute; import net.lamgc.cgj.bot.sort.PreLoadDataAttributeComparator; import net.lamgc.cgj.pixiv.PixivDownload; import net.lamgc.cgj.pixiv.PixivDownload.PageQuality; +import net.lamgc.cgj.pixiv.PixivSearchAttribute; import net.lamgc.cgj.pixiv.PixivSearchLinkBuilder; import net.lamgc.cgj.pixiv.PixivURL; +import net.lamgc.cgj.util.PixivUtils; import net.lamgc.utils.base.runner.Argument; import net.lamgc.utils.base.runner.Command; import org.slf4j.Logger; @@ -40,6 +42,8 @@ public class BotCommandProcess { private final static RankingUpdateTimer updateTimer = new RankingUpdateTimer(); + private final static int SEARCH_PAGE_MAX_ITEM = 60; + public static void initialize() { log.info("正在初始化..."); @@ -321,12 +325,9 @@ public class BotCommandProcess { @Argument(name = "option", force = false) String contentOption, @Argument(name = "p", force = false, defaultValue = "1") int pagesIndex ) throws IOException, InterruptedException { + PixivSearchLinkBuilder searchLinkBuilder = PixivUtils.buildSearchLinkBuilderFromString(content, type, area, + includeKeywords, excludeKeywords, contentOption, pagesIndex); log.debug("正在执行搜索..."); - JsonObject resultBody = CacheStoreCentral.getCentral() - .getSearchBody(content, type, area, includeKeywords, excludeKeywords, contentOption, pagesIndex); - - StringBuilder result = new StringBuilder("内容 " + content + " 的搜索结果:\n"); - log.debug("正在处理信息..."); int limit = 8; try { limit = Integer.parseInt(SettingProperties. @@ -334,95 +335,121 @@ public class BotCommandProcess { } catch (Exception e) { log.warn("参数转换异常!将使用默认值(" + limit + ")", e); } + int totalCount = 0; - for (PixivSearchLinkBuilder.SearchArea searchArea : PixivSearchLinkBuilder.SearchArea.values()) { - if (!resultBody.has(searchArea.jsonKey) || - resultBody.getAsJsonObject(searchArea.jsonKey).getAsJsonArray("data").size() == 0) { - log.debug("返回数据不包含 {}", searchArea.jsonKey); - continue; - } - JsonArray illustsArray = resultBody - .getAsJsonObject(searchArea.jsonKey).getAsJsonArray("data"); - ArrayList illustsList = new ArrayList<>(); - illustsArray.forEach(illustsList::add); - illustsList.sort(new PreLoadDataAttributeComparator(PreLoadDataAttribute.BOOKMARK)); + StringBuilder result = new StringBuilder("内容 " + content + " 的搜索结果:\n"); + List artworkList = getSearchResult(searchLinkBuilder, fromGroup, limit, pagesIndex); + artworkList.sort(new PreLoadDataAttributeComparator(PreLoadDataAttribute.LIKE)); + int startIndex = limit * pagesIndex - limit + 1; + int pageStartIndex = startIndex % SEARCH_PAGE_MAX_ITEM; + for(int index = pageStartIndex; totalCount < limit && index < artworkList.size(); index++) { + int illustId = artworkList.get(index - 1).get("illustId").getAsInt(); + // 预加载数据有更多信息可以提供 + JsonObject artworkPreLoadData = CacheStoreCentral.getCentral() + .getIllustPreLoadData(illustId, false); - log.debug("已找到与 {} 相关插图信息({}):", content, searchArea.name().toLowerCase()); - int count = 1; - for (JsonElement jsonElement : illustsList) { - if (count > limit) { - break; - } - JsonObject illustObj = jsonElement.getAsJsonObject(); - if (!illustObj.has("illustId")) { - continue; - } - int illustId = illustObj.get("illustId").getAsInt(); - StringBuilder builder = new StringBuilder("["); - illustObj.get("tags").getAsJsonArray().forEach(el -> builder.append(el.getAsString()).append(", ")); - builder.replace(builder.length() - 2, builder.length(), "]"); - log.debug("{} ({} / {})\n\t作品id: {}, \n\t作者名(作者id): {} ({}), \n\t" + - "作品标题: {}, \n\t作品Tags: {}, \n\t页数: {}页, \n\t作品链接: {}", - searchArea.name(), - count, - illustsList.size(), - illustId, - illustObj.get("userName").getAsString(), - illustObj.get("userId").getAsInt(), - illustObj.get("illustTitle").getAsString(), - builder, - illustObj.get("pageCount").getAsInt(), - PixivURL.getPixivRefererLink(illustId) - ); - - String imageMsg; - try { - imageMsg = CacheStoreCentral.getCentral() - .getImageById(fromGroup, illustId, PixivDownload.PageQuality.REGULAR, 1); - } catch (NoSuchElementException e) { - if(e.getMessage().startsWith("No work found: ")) { - log.warn("作品 {} 不存在, 跳过该作品...", illustId); - continue; - } - throw e; - } - if (isNoSafe(illustId, SettingProperties.getProperties(fromGroup), false)) { - log.warn("作品Id {} 为R-18作品, 跳过.", illustId); - continue; - } else if(isReported(illustId)) { - log.warn("作品Id {} 被报告, 正在等待审核, 跳过该作品.", illustId); - continue; - } - - JsonObject illustPreLoadData = CacheStoreCentral.getCentral() - .getIllustPreLoadData(illustId, false); - result.append(searchArea.name()).append(" (").append(count).append(" / ") - .append(limit).append(")\n\t作品id: ").append(illustId) - .append(", \n\t作者名: ").append(illustObj.get("userName").getAsString()) - .append("\n\t作品标题: ").append(illustObj.get("illustTitle").getAsString()) - .append("\n\t作品页数: ").append(illustObj.get("pageCount").getAsInt()).append("页") - .append("\n\t点赞数:") - .append(illustPreLoadData.get(PreLoadDataAttribute.LIKE.attrName).getAsInt()) - .append("\n\t收藏数:") - .append(illustPreLoadData.get(PreLoadDataAttribute.BOOKMARK.attrName).getAsInt()) - .append("\n\t围观数:") - .append(illustPreLoadData.get(PreLoadDataAttribute.VIEW.attrName).getAsInt()) - .append("\n\t评论数:") - .append(illustPreLoadData.get(PreLoadDataAttribute.COMMENT.attrName).getAsInt()) - .append("\n").append(imageMsg).append("\n"); - count++; - totalCount++; - } - if (count > limit) { - break; - } + // 构造消息内容 + result.append(startIndex++).append(". (").append(artworkPreLoadData.get("illustId").getAsInt()).append(") ") + .append(artworkPreLoadData.get("illustTitle").getAsString()); + result.append("\n\t").append("作者:").append(artworkPreLoadData.get("userName").getAsString()); + result.append("\n\t").append("作品页数:").append(artworkPreLoadData.get("pageCount").getAsInt()).append(" 页"); + result.append("\n\t").append("点赞数:") + .append(artworkPreLoadData.get(PreLoadDataAttribute.LIKE.attrName).getAsInt()).append(" 页"); + result.append("\n\t").append("收藏数:") + .append(artworkPreLoadData.get(PreLoadDataAttribute.BOOKMARK.attrName).getAsInt()).append(" 页"); + result.append("\n\t").append("围观数:") + .append(artworkPreLoadData.get(PreLoadDataAttribute.VIEW.attrName).getAsInt()).append(" 页"); + result.append("\n\t").append("评论数:") + .append(artworkPreLoadData.get(PreLoadDataAttribute.COMMENT.attrName).getAsInt()).append(" 页"); + result.append(CacheStoreCentral.getCentral() + .getImageById(fromGroup, illustId, PageQuality.REGULAR, 1)).append("\n"); + totalCount++; } + return totalCount <= 0 ? "搜索完成,未找到相关作品。" : Strings.nullToEmpty(result.toString()) + "预览图片并非原图,使用“.cgj image -id 作品id”获取原图\n" + "如有不当作品,可使用\".cgj report -id 作品id\"向色图姬反馈。"; } + /** + * 获取 length 涉及的多个页的搜索结果. + * 例如: + * pageMaxItem = 60; + * length = 150; + * page = 3; + * 那么: + * endItemIndex = length * page = 450; + * startItemIndex = endItemIndex - length + 1 = 301; + * startPageIndex = ceil(startItemIndex / pageMaxItem) = 6; + * pageRange = ceil((endItemIndex - length + 1) / pageMaxItem) = 3; + * endPageIndex = startPageIndex - pageRange - 1 = 8; + * 该方法将会取搜索结果的 6 ~ 8 页结果并返回; + * @param searchLinkBuilder 已构造好除 Page 参数外其他参数的 {@link PixivSearchLinkBuilder} + * @param length 所需结果的范围 + * @param page 所需结果的页数 + * @return 返回包含范围的涉及页面所有搜索结果. + * @throws IOException 如获取发生异常则抛出. + */ + private static List getSearchResult(PixivSearchLinkBuilder searchLinkBuilder, long groupId, int length, int page) throws IOException { + List artworkList = new ArrayList<>(length); + + int endsItemIndex = length * page; + int startsItemIndex = endsItemIndex - length + 1; + int startPageIndex = (int) Math.ceil(startsItemIndex / (double) SEARCH_PAGE_MAX_ITEM); + int pageRange = (int) Math.ceil((endsItemIndex - startsItemIndex) / (double) SEARCH_PAGE_MAX_ITEM); + PixivSearchAttribute areaAttribute = PixivSearchAttribute.valueOf(searchLinkBuilder.getSearchArea().toString()); + Properties properties = SettingProperties.getProperties(groupId); + int expectedQuantity = pageRange * SEARCH_PAGE_MAX_ITEM; + // 一个可能不算最好的去重方法?我已经对Pixiv搜索结果完全重复的情况感到无语了 :( + Set artworkIdSet = new HashSet<>(); + int addItemCount = 0; + for(int pageIndex = startPageIndex; + pageIndex <= startPageIndex + pageRange - 1 || artworkList.size() < length || artworkList.size() < expectedQuantity; + pageIndex++) { + searchLinkBuilder.setPage(pageIndex); + JsonObject searchBody = CacheStoreCentral.getCentral().getSearchBody(searchLinkBuilder); + for(String areaAttributeName : areaAttribute.attributeNames) { + JsonObject areaResult = searchBody.getAsJsonObject(areaAttributeName); + if(areaResult == null || !areaResult.has("data")) { + log.debug("作品类型属性 {} 无搜索结果, 跳过...", areaAttributeName); + continue; + } + + JsonArray areaArray = areaResult.getAsJsonArray("data"); + for(JsonElement element : areaArray) { + JsonObject artworkInfo = element.getAsJsonObject(); + if(!artworkInfo.has("illustId")) { + log.warn("发现未含有illustId的JsonObject: '{}'", artworkInfo.toString()); + continue; + } + final int illustId = artworkInfo.get("illustId").getAsInt(); + if(isNoSafe(illustId, properties, false)) { + log.warn("作品 {} 为R18作品, 跳过.", illustId); + continue; + } else if(isReported(illustId)) { + log.warn("作品 {} 被报告, 跳过.", illustId); + continue; + } + if(artworkIdSet.contains(illustId)) { + continue; + } + + artworkIdSet.add(illustId); + artworkList.add(artworkInfo); + addItemCount++; + } + } + if(addItemCount == 0) { + log.warn("已无法获取更多作品, 停止搜索."); + break; + } + addItemCount = 0; + } + + return artworkList; + } + /** * 获取作品页面的下载链接 * @param illustId 作品Id