diff --git a/src/main/java/net/lamgc/cgj/bot/BotCommandProcess.java b/src/main/java/net/lamgc/cgj/bot/BotCommandProcess.java index b7bca5e..5c6b711 100644 --- a/src/main/java/net/lamgc/cgj/bot/BotCommandProcess.java +++ b/src/main/java/net/lamgc/cgj/bot/BotCommandProcess.java @@ -100,7 +100,7 @@ public class BotCommandProcess { return "阅览禁止:该作品已被封印!!"; } - JsonObject illustPreLoadData = CacheStoreCentral.getIllustPreLoadData(illustId, false); + JsonObject illustPreLoadData = CacheStoreCentral.getCentral().getIllustPreLoadData(illustId, false); // 在 Java 6 开始, 编译器会将用'+'进行的字符串拼接将自动转换成StringBuilder拼接 return "色图姬帮你了解了这个作品的信息!\n" + "---------------- 作品信息 ----------------" + "\n作品Id: " + illustId + @@ -114,7 +114,7 @@ public class BotCommandProcess { "\n页数:" + illustPreLoadData.get(PreLoadDataComparator.Attribute.PAGE.attrName).getAsInt() + "页" + "\n作品链接:" + artworksLink(fromGroup, illustId) + "\n" + "---------------- 作品图片 ----------------\n" + - CacheStoreCentral.getImageById(fromGroup, illustId, PageQuality.REGULAR, 1) + "\n" + + CacheStoreCentral.getCentral().getImageById(fromGroup, illustId, PageQuality.REGULAR, 1) + "\n" + "使用 \".cgj image -id " + illustId + "\" 获取原图。\n如有不当作品,可使用\".cgj report -id " + @@ -209,7 +209,7 @@ public class BotCommandProcess { log.warn("配置项 {} 的参数值格式有误!", imageLimitPropertyKey); } - List rankingInfoList = CacheStoreCentral + List rankingInfoList = CacheStoreCentral.getCentral() .getRankingInfoByCache(type, mode, queryDate, 1, Math.max(0, itemLimit), false); if(rankingInfoList.isEmpty()) { return "无法查询排行榜,可能排行榜尚未更新。"; @@ -228,7 +228,7 @@ public class BotCommandProcess { .append(pagesCount).append("p.\n"); if (index <= imageLimit) { resultBuilder - .append(CacheStoreCentral + .append(CacheStoreCentral.getCentral() .getImageById(fromGroup, illustId, PixivDownload.PageQuality.REGULAR, 1)) .append("\n"); } @@ -312,7 +312,7 @@ public class BotCommandProcess { @Argument(name = "page", force = false, defaultValue = "1") int pagesIndex ) throws IOException { log.info("正在执行搜索..."); - JsonObject resultBody = CacheStoreCentral + JsonObject resultBody = CacheStoreCentral.getCentral() .getSearchBody(content, type, area, includeKeywords, excludeKeywords, contentOption); StringBuilder result = new StringBuilder("内容 " + content + " 的搜索结果:\n"); @@ -365,8 +365,8 @@ public class BotCommandProcess { PixivURL.getPixivRefererLink(illustId) ); - String imageMsg = - CacheStoreCentral.getImageById(fromGroup, illustId, PixivDownload.PageQuality.REGULAR, 1); + String imageMsg = CacheStoreCentral.getCentral() + .getImageById(fromGroup, illustId, PixivDownload.PageQuality.REGULAR, 1); if (isNoSafe(illustId, SettingProperties.getProperties(fromGroup), false)) { log.warn("作品Id {} 为R-18作品, 跳过.", illustId); continue; @@ -375,7 +375,8 @@ public class BotCommandProcess { continue; } - JsonObject illustPreLoadData = CacheStoreCentral.getIllustPreLoadData(illustId, false); + 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()) @@ -463,7 +464,7 @@ public class BotCommandProcess { static void clearCache() { log.warn("正在清除所有缓存..."); - CacheStoreCentral.clearCache(); + CacheStoreCentral.getCentral().clearCache(); File imageStoreDir = new File(BotGlobal.getGlobal().getDataStoreDir(), "data/image/cgj/"); File[] listFiles = imageStoreDir.listFiles(); if (listFiles == null) { @@ -484,7 +485,7 @@ public class BotCommandProcess { @Argument(name = "quality", force = false) PixivDownload.PageQuality quality, @Argument(name = "page", force = false, defaultValue = "1") int pageIndex ) { - return CacheStoreCentral.getImageById(fromGroup, illustId, quality, pageIndex); + return CacheStoreCentral.getCentral().getImageById(fromGroup, illustId, quality, pageIndex); } /** @@ -532,7 +533,7 @@ public class BotCommandProcess { */ public static boolean isNoSafe(int illustId, Properties settingProp, boolean returnRaw) throws IOException, NoSuchElementException { - JsonObject illustInfo = CacheStoreCentral.getIllustInfo(illustId, false); + JsonObject illustInfo = CacheStoreCentral.getCentral().getIllustInfo(illustId, false); JsonArray tags = illustInfo.getAsJsonArray("tags"); boolean rawValue = illustInfo.get("xRestrict").getAsInt() != 0; if(!rawValue) { diff --git a/src/main/java/net/lamgc/cgj/bot/RandomRankingArtworksSender.java b/src/main/java/net/lamgc/cgj/bot/RandomRankingArtworksSender.java index e6fbe4c..93af1f9 100644 --- a/src/main/java/net/lamgc/cgj/bot/RandomRankingArtworksSender.java +++ b/src/main/java/net/lamgc/cgj/bot/RandomRankingArtworksSender.java @@ -92,7 +92,7 @@ public class RandomRankingArtworksSender extends AutoSender { int selectRanking = rankingStart + new Random().nextInt(rankingStop - rankingStart + 1); try { - List rankingList = CacheStoreCentral.getRankingInfoByCache( + List rankingList = CacheStoreCentral.getCentral().getRankingInfoByCache( contentType, mode, queryDate, @@ -119,7 +119,7 @@ public class RandomRankingArtworksSender extends AutoSender { String message = "#美图推送 - 今日排行榜 第 " + rankingInfo.get("rank").getAsInt() + " 名\n" + "标题:" + rankingInfo.get("title").getAsString() + "(" + illustId + ")\n" + "作者:" + rankingInfo.get("user_name").getAsString() + "\n" + - CacheStoreCentral.getImageById(0, illustId, quality, 1) + + CacheStoreCentral.getCentral().getImageById(0, illustId, quality, 1) + "\n如有不当作品,可使用\".cgj report -id " + illustId + "\"向色图姬反馈。"; getMessageSender().sendMessage(message); } catch (Exception e) { diff --git a/src/main/java/net/lamgc/cgj/bot/cache/CacheStoreCentral.java b/src/main/java/net/lamgc/cgj/bot/cache/CacheStoreCentral.java index 09fa4c7..84b6cd3 100644 --- a/src/main/java/net/lamgc/cgj/bot/cache/CacheStoreCentral.java +++ b/src/main/java/net/lamgc/cgj/bot/cache/CacheStoreCentral.java @@ -31,27 +31,44 @@ import java.util.concurrent.atomic.AtomicInteger; @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public final class CacheStoreCentral { - private CacheStoreCentral() {} - private final static Logger log = LoggerFactory.getLogger(CacheStoreCentral.class); - private final static Hashtable imageCache = new Hashtable<>(); + private static CacheStoreCentral central = new CacheStoreCentral(); - private final static JsonRedisCacheStore imageChecksumCache = + public static CacheStoreCentral getCentral() { + if(central == null) { + initialCentral(); + } + return central; + } + + private synchronized static void initialCentral() { + if(central != null) { + return; + } + + central = new CacheStoreCentral(); + } + + private CacheStoreCentral() {} + + private final Hashtable imageCache = new Hashtable<>(); + + private final CacheStore imageChecksumCache = new JsonRedisCacheStore(BotGlobal.getGlobal().getRedisServer(), "imageChecksum", BotGlobal.getGlobal().getGson()); /** * 作品信息缓存 - 不过期 */ - private final static CacheStore illustInfoCache = + private final CacheStore illustInfoCache = new JsonRedisCacheStore(BotGlobal.getGlobal().getRedisServer(), "illustInfo", BotGlobal.getGlobal().getGson()); /** * 作品信息预加载数据 - 有效期 2 小时, 本地缓存有效期1 ± 0.25 */ - private final static CacheStore illustPreLoadDataCache = + private final CacheStore illustPreLoadDataCache = CacheStoreUtils.hashLocalHotDataStore( new JsonRedisCacheStore(BotGlobal.getGlobal().getRedisServer(), "illustPreLoadData", BotGlobal.getGlobal().getGson()), @@ -59,27 +76,27 @@ public final class CacheStoreCentral { /** * 搜索内容缓存, 有效期 2 小时 */ - private final static CacheStore searchBodyCache = + private final CacheStore searchBodyCache = new JsonRedisCacheStore(BotGlobal.getGlobal().getRedisServer(), "searchBody", BotGlobal.getGlobal().getGson()); /** * 排行榜缓存, 不过期 */ - private final static CacheStore> rankingCache = + private final CacheStore> rankingCache = new JsonObjectRedisListCacheStore(BotGlobal.getGlobal().getRedisServer(), "ranking", BotGlobal.getGlobal().getGson()); /** * 作品页面下载链接缓存 - 不过期 */ - private final static CacheStore> pagesCache = + private final CacheStore> pagesCache = new StringListRedisCacheStore(BotGlobal.getGlobal().getRedisServer(), "imagePages"); /** * 清空所有缓存 */ - public static void clearCache() { + public void clearCache() { imageCache.clear(); illustInfoCache.clear(); illustPreLoadDataCache.clear(); @@ -96,7 +113,7 @@ public final class CacheStoreCentral { * @param pageIndex 指定页面索引, 从1开始 * @return 如果成功, 返回BotCode, 否则返回错误信息. */ - public static String getImageById(long fromGroup, int illustId, PixivDownload.PageQuality quality, int pageIndex) { + public String getImageById(long fromGroup, int illustId, PixivDownload.PageQuality quality, int pageIndex) { log.debug("IllustId: {}, Quality: {}, PageIndex: {}", illustId, quality.name(), pageIndex); if(pageIndex <= 0) { log.warn("指定的页数不能小于或等于0: {}", pageIndex); @@ -118,7 +135,7 @@ public final class CacheStoreCentral { List pagesList; try { - pagesList = CacheStoreCentral.getIllustPages(illustId, quality, false); + pagesList = getIllustPages(illustId, quality, false); } catch (IOException e) { log.error("获取下载链接列表时发生异常", e); return "发生网络异常,无法获取图片!"; @@ -190,7 +207,7 @@ public final class CacheStoreCentral { * @return 返回设定好参数的BotCode */ @SuppressWarnings("SameParameterValue") - private static BotCode getImageToBotCode(File targetFile, boolean updateCache) { + private BotCode getImageToBotCode(File targetFile, boolean updateCache) { String fileName = Objects.requireNonNull(targetFile, "targetFile is null").getName(); BotCode code = BotCode.parse( CQCode.image(BotGlobal.getGlobal().getImageStoreDir().getName() + "/" + fileName)); @@ -208,7 +225,7 @@ public final class CacheStoreCentral { * @throws IOException 当Http请求发生异常时抛出 * @throws NoSuchElementException 当作品未找到时抛出 */ - public static JsonObject getIllustInfo(int illustId, boolean flushCache) + public JsonObject getIllustInfo(int illustId, boolean flushCache) throws IOException, NoSuchElementException { String illustIdStr = buildSyncKey(Integer.toString(illustId)); JsonObject illustInfoObj = null; @@ -236,7 +253,7 @@ public final class CacheStoreCentral { * @return 成功返回JsonObject对象 * @throws IOException 当Http请求处理发生异常时抛出 */ - public static JsonObject getIllustPreLoadData(int illustId, boolean flushCache) throws IOException { + public JsonObject getIllustPreLoadData(int illustId, boolean flushCache) throws IOException { String illustIdStr = buildSyncKey(Integer.toString(illustId)); JsonObject result = null; if (!illustPreLoadDataCache.exists(illustIdStr) || flushCache) { @@ -272,7 +289,7 @@ public final class CacheStoreCentral { return result; } - public static List getIllustPages(int illustId, PixivDownload.PageQuality quality, boolean flushCache) + public List getIllustPages(int illustId, PixivDownload.PageQuality quality, boolean flushCache) throws IOException { String pagesSign = buildSyncKey(Integer.toString(illustId), ".", quality.name()); List result = null; @@ -295,7 +312,7 @@ public final class CacheStoreCentral { return result; } - private final static Random expireTimeFloatRandom = new Random(); + private final Random expireTimeFloatRandom = new Random(); /** * 获取排行榜 * @param contentType 排行榜类型 @@ -307,7 +324,7 @@ public final class CacheStoreCentral { * @return 成功返回有值List, 失败且无异常返回空 * @throws IOException 获取异常时抛出 */ - public static List getRankingInfoByCache(PixivURL.RankingContentType contentType, + public List getRankingInfoByCache(PixivURL.RankingContentType contentType, PixivURL.RankingMode mode, Date queryDate, int start, int range, boolean flushCache) throws IOException { @@ -363,7 +380,7 @@ public final class CacheStoreCentral { * @return 返回完整搜索结果 * @throws IOException 当请求发生异常, 或接口返回异常信息时抛出. */ - public static JsonObject getSearchBody( + public JsonObject getSearchBody( String content, String type, String area, @@ -457,7 +474,7 @@ public final class CacheStoreCentral { return resultBody; } - protected static ImageChecksum getImageChecksum(int illustId, int pageIndex) { + protected ImageChecksum getImageChecksum(int illustId, int pageIndex) { String cacheKey = illustId + ":" + pageIndex; if(!imageChecksumCache.exists(cacheKey)) { return null; @@ -466,7 +483,7 @@ public final class CacheStoreCentral { } } - protected static void setImageChecksum(ImageChecksum checksum) { + protected void setImageChecksum(ImageChecksum checksum) { String cacheKey = checksum.getIllustId() + ":" + checksum.getPage(); imageChecksumCache.update(cacheKey, ImageChecksum.toJsonObject(checksum), 0); } diff --git a/src/main/java/net/lamgc/cgj/bot/cache/ImageCacheHandler.java b/src/main/java/net/lamgc/cgj/bot/cache/ImageCacheHandler.java index c2b092b..9cd4c26 100644 --- a/src/main/java/net/lamgc/cgj/bot/cache/ImageCacheHandler.java +++ b/src/main/java/net/lamgc/cgj/bot/cache/ImageCacheHandler.java @@ -80,7 +80,7 @@ public class ImageCacheHandler implements EventHandler { ); bufferInputStream.reset(); Streams.copy(bufferInputStream, fileOutputStream, false); - CacheStoreCentral.setImageChecksum(imageChecksum); + CacheStoreCentral.getCentral().setImageChecksum(imageChecksum); } catch (IOException e) { log.error("下载图片时发生异常", e); throw e; diff --git a/src/main/java/net/lamgc/cgj/bot/sort/PreLoadDataComparator.java b/src/main/java/net/lamgc/cgj/bot/sort/PreLoadDataComparator.java index 96e805e..5b9aaa9 100644 --- a/src/main/java/net/lamgc/cgj/bot/sort/PreLoadDataComparator.java +++ b/src/main/java/net/lamgc/cgj/bot/sort/PreLoadDataComparator.java @@ -39,10 +39,10 @@ public class PreLoadDataComparator implements Comparator { } } try { - JsonObject illustPreLoadData1 = - CacheStoreCentral.getIllustPreLoadData(o1.getAsJsonObject().get("illustId").getAsInt(), false); - JsonObject illustPreLoadData2 = - CacheStoreCentral.getIllustPreLoadData(o2.getAsJsonObject().get("illustId").getAsInt(), false); + JsonObject illustPreLoadData1 = CacheStoreCentral.getCentral() + .getIllustPreLoadData(o1.getAsJsonObject().get("illustId").getAsInt(), false); + JsonObject illustPreLoadData2 = CacheStoreCentral.getCentral() + .getIllustPreLoadData(o2.getAsJsonObject().get("illustId").getAsInt(), false); return Integer.compare( illustPreLoadData2.get(attribute.attrName).getAsInt(), illustPreLoadData1.get(attribute.attrName).getAsInt());