Compare commits

...

12 Commits

Author SHA1 Message Date
75aa78a3d7 [Version] 更新版本(2.5.2-20200606.1-SNAPSHOT -> 2.5.2-20200609.1-SNAPSHOT); 2020-06-09 10:12:02 +08:00
18a8ad95a1 [Change] PixivUgoiraBuilderTest 调整测试细节; 2020-06-09 10:07:54 +08:00
438d0a95d3 [Add] pom.xml 增加JLine库;
[Update] ConsoleMain 增强Cli使用体验;
[Add] BotEventHandler 增加同步执行命令的方法'executeMessageEvent(MessageEvent, boolean)';
[Change] Main 适配ConsoleMain的更改;
2020-06-09 09:50:16 +08:00
6789b5b7c5 [Change] CacheStoreCentral 调整'getImageById'方法中对'pageIndex'的参数值检查时机;
[Change] MiraiMessageSender 增加警告忽略注释;
2020-06-08 19:13:51 +08:00
ad289f952f [Fix] log4j2.xml 修复SYSTEM_OUT级别限定错误的问题; 2020-06-08 18:47:53 +08:00
3ae0e4cd8d [Change] HotDataCacheStore 调整日志输出级别(DEBUG -> TRACE); 2020-06-08 16:08:13 +08:00
5550c7aef1 [Clear] CacheStoreCentral 删除无用的运行器代码; 2020-06-08 15:57:38 +08:00
d4d3432c76 [Add] PixivUgoiraBuilder 增加方法'buildUgoira(OutputStream, boolean)'以提供输出流给Builder输出已构建的动图数据;
[Add] PixivUgoiraBuilder 增加方法'getUgoiraMeta():JsonObject'方法, 可通过该方法获取动图元数据;
2020-06-08 15:30:22 +08:00
d1aeda012e [Fix] BotCommandProcess 修复因'getImageById'迁移导致'image'命令不可用的问题;
[Clear] CacheStoreCentral 清除无用代码;
2020-06-08 09:37:06 +08:00
683a38bc17 [Add] BotGlobal BotGlobal在初始化时将检查Redis连通性;
[Change] RandomRankingArtworksSender 支持外部设置groupId, 以使用群组配置;
[Change] BotCommandProcess, BotAdminCommandProcess 适配RandomRankingArtworksSender更改;
2020-06-08 09:24:17 +08:00
188309509b [Change] BotCommandProcess 简化Search参数'ContentOption'的名称('contentOption' -> 'option'); 2020-06-06 19:27:55 +08:00
3915712337 [Delete] search.txt 删除旧文档; 2020-06-06 17:57:24 +08:00
15 changed files with 181 additions and 78 deletions

View File

@ -1,24 +0,0 @@
搜索标签信息https://www.pixiv.net/ajax/search/tags/标签名
搜索接口:
https://www.pixiv.net/ajax/search/{Type}/搜索内容
Type = illustrations(插画) / top(顶部?) / manga(漫画) / novels(小说)
word=搜索内容 [参数可能不是必须的]
s_mode=s_tag(标签-部分一致) / s_tag_full(标签-完全一致) / s_tc(标题、说明文字)
type= all(插画、漫画、动图_动态插图) / illust_and_ugoira(插画、动图) / illust(插画) / manga(漫画) / ugoira(动图)
p=页数 [超出页数的情况下将获取不到数据(即"body.illust.data"是空数组)]
order=date(按旧排序) / date_d(按新排序) / Unknown(按热门度排序, 需要会员)
mode= all(全部) / safe(全年龄) / r18(咳咳)
可选参数:
wlt=最小宽度像素
wgt=最高宽度像素
hlt=最小高度像素
hgt=最高高度像素
ratio=0.5(横图) / -0.5(纵图) / 0(正方形) [可能不能改变参数, 三个值是固定的]
tool=使用工具, 不是很重要晚些再加
scd=开始时间(yyyy-MM-dd)
ecd=结束时间(yyyy-MM-dd)
最小收藏数 = 收藏数限定参数为会员功能, 无法获取

View File

@ -6,7 +6,7 @@
<groupId>net.lamgc</groupId>
<artifactId>ContentGrabbingJi</artifactId>
<version>2.5.2-20200606.1-SNAPSHOT</version>
<version>2.5.2-20200609.1-SNAPSHOT</version>
<repositories>
<repository>
@ -179,6 +179,11 @@
<artifactId>gifencoder</artifactId>
<version>0.10.1</version>
</dependency>
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline</artifactId>
<version>3.15.0</version>
</dependency>
</dependencies>
</project>

View File

@ -93,7 +93,7 @@ public class Main {
}
@Command
public static void consoleMode() {
public static void consoleMode() throws IOException {
ConsoleMain.start();
}

View File

@ -271,6 +271,7 @@ public class BotAdminCommandProcess {
AutoSender sender = new RandomRankingArtworksSender(
MessageSenderBuilder.getMessageSender(MessageSource.Group, id),
id,
rankingStart,
rankingEnd,
rankingMode, rankingContentType,

View File

@ -14,8 +14,6 @@ import net.lamgc.cgj.pixiv.PixivDownload;
import net.lamgc.cgj.pixiv.PixivDownload.PageQuality;
import net.lamgc.cgj.pixiv.PixivSearchBuilder;
import net.lamgc.cgj.pixiv.PixivURL;
import net.lamgc.cgj.pixiv.PixivURL.RankingContentType;
import net.lamgc.cgj.pixiv.PixivURL.RankingMode;
import net.lamgc.utils.base.runner.Argument;
import net.lamgc.utils.base.runner.Command;
import org.slf4j.Logger;
@ -257,12 +255,33 @@ public class BotCommandProcess {
* 随机获取一副作品
*/
@Command(commandName = "random")
public static String randomImage() {
public static String randomImage(
@Argument(name = "$fromGroup") long fromGroup,
@Argument(force = false, name = "mode", defaultValue = "DAILY") String contentMode,
@Argument(force = false, name = "type", defaultValue = "ILLUST") String contentType) {
PixivURL.RankingMode mode;
try {
String rankingModeValue = contentMode.toUpperCase();
mode = PixivURL.RankingMode.valueOf(rankingModeValue.startsWith("MODE_") ?
rankingModeValue : "MODE_" + rankingModeValue);
} catch (IllegalArgumentException e) {
log.warn("无效的RankingMode值: {}", contentMode);
return "参数无效, 请查看帮助信息";
}
PixivURL.RankingContentType type;
try {
String contentTypeValue = contentType.toUpperCase();
type = PixivURL.RankingContentType.valueOf(
contentTypeValue.startsWith("TYPE_") ? contentTypeValue : "TYPE_" + contentTypeValue);
} catch (IllegalArgumentException e) {
log.warn("无效的RankingContentType值: {}", contentType);
return "参数无效, 请查看帮助信息";
}
BufferMessageEvent event = new BufferMessageEvent();
RandomRankingArtworksSender artworksSender =
new RandomRankingArtworksSender(event, 1, 200,
RankingMode.MODE_MALE,
RankingContentType.TYPE_ALL,
new RandomRankingArtworksSender(event, fromGroup, 1, 200, mode, type,
PageQuality.ORIGINAL);
artworksSender.send();
return event.getBufferMessage();
@ -289,7 +308,7 @@ public class BotCommandProcess {
@Argument(name = "area", force = false) String area,
@Argument(name = "in", force = false) String includeKeywords,
@Argument(name = "ex", force = false) String excludeKeywords,
@Argument(name = "contentOption", force = false) String contentOption,
@Argument(name = "option", force = false) String contentOption,
@Argument(name = "page", force = false, defaultValue = "1") int pagesIndex
) throws IOException {
log.info("正在执行搜索...");
@ -458,6 +477,16 @@ public class BotCommandProcess {
log.warn("缓存删除完成.");
}
@Command(commandName = "image")
public static String getImageById(
@Argument(name = "$fromGroup") long fromGroup,
@Argument(name = "id") int illustId,
@Argument(name = "quality", force = false) PixivDownload.PageQuality quality,
@Argument(name = "page", force = false, defaultValue = "1") int pageIndex
) {
return CacheStoreCentral.getImageById(fromGroup, illustId, quality, pageIndex);
}
/**
* 举报某一作品
* @param fromGroup 来源群(系统提供)

View File

@ -19,6 +19,7 @@ import java.util.Random;
public class RandomRankingArtworksSender extends AutoSender {
private final Logger log;
private final long groupId;
private final int rankingStart;
private final int rankingStop;
private final PixivURL.RankingMode mode;
@ -35,8 +36,37 @@ public class RandomRankingArtworksSender extends AutoSender {
* @param quality 图片质量, 详见{@link PixivDownload.PageQuality}
* @throws IndexOutOfBoundsException 当 rankingStart > rankingStop时抛出
*/
public RandomRankingArtworksSender(MessageSender messageSender, int rankingStart, int rankingStop, PixivURL.RankingMode mode, PixivURL.RankingContentType contentType, PixivDownload.PageQuality quality) {
public RandomRankingArtworksSender(
MessageSender messageSender,
int rankingStart,
int rankingStop,
PixivURL.RankingMode mode,
PixivURL.RankingContentType contentType,
PixivDownload.PageQuality quality) {
this(messageSender, 0, rankingStart, rankingStop, mode, contentType, quality);
}
/**
* 构造一个推荐作品发送器
* @param messageSender 消息发送器
* @param groupId 群组Id, 如果发送目标为群组, 则可设置群组Id, 以使用群组配置.
* @param rankingStart 排行榜开始范围(从1开始, 名次)如传入0或负数则为默认值默认为1
* @param rankingStop 排名榜结束范围(包括该名次)如传入0或负数则为默认值默认为150
* @param mode 排行榜模式
* @param contentType 排行榜内容类型
* @param quality 图片质量, 详见{@link PixivDownload.PageQuality}
* @throws IndexOutOfBoundsException 当 rankingStart > rankingStop时抛出
*/
public RandomRankingArtworksSender(
MessageSender messageSender,
long groupId,
int rankingStart,
int rankingStop,
PixivURL.RankingMode mode,
PixivURL.RankingContentType contentType,
PixivDownload.PageQuality quality) {
super(messageSender);
this.groupId = groupId;
this.mode = mode;
this.contentType = contentType;
log = LoggerFactory.getLogger(this.toString());
@ -78,7 +108,7 @@ public class RandomRankingArtworksSender extends AutoSender {
JsonObject rankingInfo = rankingList.get(0);
int illustId = rankingInfo.get("illust_id").getAsInt();
if(BotCommandProcess.isNoSafe(illustId,
SettingProperties.getProperties(SettingProperties.GLOBAL), false)) {
SettingProperties.getProperties(groupId), false)) {
log.warn("作品为r18作品, 取消本次发送.");
return;
} else if(BotCommandProcess.isReported(illustId)) {

View File

@ -8,7 +8,9 @@ import org.apache.http.HttpHost;
import org.apache.http.client.CookieStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;
import java.io.File;
import java.io.IOException;
@ -56,6 +58,12 @@ public final class BotGlobal {
this.redisServer = new JedisPool(
getRedisUri().getHost(),
getRedisUri().getPort() == -1 ? 6379 : getRedisUri().getPort());
try (Jedis jedis = this.redisServer.getResource()) {
log.warn("Redis连接状态(Ping): {}", jedis.ping().equalsIgnoreCase("pong"));
} catch(JedisConnectionException e) {
log.warn("Redis连接失败, 将会影响到后续功能运行.", e);
}
String dataStoreDirPath = System.getProperty("cgj.botDataDir");
this.dataStoreDir = new File((!dataStoreDirPath.endsWith("/") || !dataStoreDirPath.endsWith("\\")) ?
dataStoreDirPath + System.getProperty("file.separator") : dataStoreDirPath);
@ -95,13 +103,6 @@ public final class BotGlobal {
return proxy;
}
public CookieStore getCookieStore() {
if(pixivDownload == null) {
throw new IllegalStateException("CookieStore needs to be set before PixivDownload can be obtained");
}
return cookieStore;
}
public void setCookieStore(CookieStore cookieStore) {
if(this.cookieStore != null) {
throw new IllegalStateException("CookieStore set");

View File

@ -12,8 +12,6 @@ import net.lamgc.cgj.pixiv.PixivDownload;
import net.lamgc.cgj.pixiv.PixivSearchBuilder;
import net.lamgc.cgj.pixiv.PixivURL;
import net.lamgc.cgj.util.URLs;
import net.lamgc.utils.base.runner.Argument;
import net.lamgc.utils.base.runner.Command;
import net.lamgc.utils.encrypt.MessageDigestUtils;
import net.lz1998.cq.utils.CQCode;
import org.apache.http.HttpResponse;
@ -98,13 +96,12 @@ public final class CacheStoreCentral {
* @param pageIndex 指定页面索引, 从1开始
* @return 如果成功, 返回BotCode, 否则返回错误信息.
*/
@Command(commandName = "image")
public static String getImageById(
@Argument(name = "$fromGroup") long fromGroup,
@Argument(name = "id") int illustId,
@Argument(name = "quality", force = false) PixivDownload.PageQuality quality,
@Argument(name = "page", force = false, defaultValue = "1") int pageIndex) {
public static 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);
return "指定的页数不能小于或等于0";
}
try {
if (BotCommandProcess.isNoSafe(illustId, SettingProperties.getProperties(fromGroup), false)) {
@ -135,7 +132,7 @@ public final class CacheStoreCentral {
log.debug(logBuilder.toString());
}
if (pagesList.size() < pageIndex || pageIndex <= 0) {
if (pagesList.size() < pageIndex) {
log.warn("指定的页数超出了总页数({} / {})", pageIndex, pagesList.size());
return "指定的页数超出了范围(总共 " + pagesList.size() + " 页)";
}

View File

@ -39,7 +39,7 @@ public class HotDataCacheStore<T> implements CacheStore<T>, Cleanable {
AutoCleanTimer.add(this);
}
log.debug("HotDataCacheStore初始化完成. " +
log.trace("HotDataCacheStore初始化完成. " +
"(Parent: {}, Current: {}, expireTime: {}, expireFloatRange: {}, autoClean: {})",
parent, current, expireTime, expireFloatRange, autoClean);
}
@ -58,24 +58,24 @@ public class HotDataCacheStore<T> implements CacheStore<T>, Cleanable {
@Override
public T getCache(String key) {
if(!exists(key)) {
log.debug("查询缓存键名不存在, 直接返回null.");
log.trace("查询缓存键名不存在, 直接返回null.");
return null;
}
T result = current.getCache(key);
if(Objects.isNull(result)) {
log.debug("Current缓存库未命中, 查询Parent缓存库");
log.trace("Current缓存库未命中, 查询Parent缓存库");
T parentResult = parent.getCache(key);
if(Objects.isNull(parentResult)) {
log.debug("Parent缓存库未命中, 缓存不存在");
log.trace("Parent缓存库未命中, 缓存不存在");
return null;
}
log.debug("Parent缓存命中, 正在更新Current缓存库...");
log.trace("Parent缓存命中, 正在更新Current缓存库...");
current.update(key, parentResult,
expireTime + (expireFloatRange <= 0 ? 0 : random.nextInt(expireFloatRange)));
log.debug("Current缓存库更新完成.");
log.trace("Current缓存库更新完成.");
result = parentResult;
} else {
log.debug("Current缓存库缓存命中.");
log.trace("Current缓存库缓存命中.");
}
return result;
}

View File

@ -120,6 +120,20 @@ public class BotEventHandler implements EventHandler {
*/
@NotAccepted
public static void executeMessageEvent(MessageEvent event) {
try {
executeMessageEvent(event, false);
} catch (InterruptedException e) {
log.error("执行时发生异常", e);
throw new RuntimeException(e);
}
}
/**
* 投递消息事件
* @param event 事件对象
*/
@NotAccepted
public static void executeMessageEvent(MessageEvent event, boolean sync) throws InterruptedException {
String debuggerName = SettingProperties.getProperty(0, "debug.debugger");
if(!event.getMessage().startsWith(ADMIN_COMMAND_PREFIX) &&
!Strings.isNullOrEmpty(debuggerName)) {
@ -132,10 +146,14 @@ public class BotEventHandler implements EventHandler {
} catch (Exception e) {
log.error("事件调试处理时发生异常", e);
}
} else {
if(sync) {
BotEventHandler.executor.executorSync(event);
} else {
BotEventHandler.executor.executor(event);
}
}
}
/**
* 以事件形式处理消息事件

View File

@ -3,22 +3,36 @@ package net.lamgc.cgj.bot.framework.cli;
import net.lamgc.cgj.bot.boot.ApplicationBoot;
import net.lamgc.cgj.bot.event.BotEventHandler;
import net.lamgc.cgj.bot.message.MessageSenderBuilder;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.impl.history.DefaultHistory;
import org.jline.terminal.TerminalBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Scanner;
import java.io.IOException;
public class ConsoleMain {
public static void start() {
MessageSenderBuilder.setCurrentMessageSenderFactory(new ConsoleMessageSenderFactory());
private final static Logger log = LoggerFactory.getLogger(ConsoleMain.class);
public static void start() throws IOException {
ConsoleMessageSenderFactory senderFactory = new ConsoleMessageSenderFactory();
MessageSenderBuilder.setCurrentMessageSenderFactory(senderFactory);
ApplicationBoot.initialBot();
Scanner scanner = new Scanner(System.in);
System.out.print("会话QQ:");
long qqId = scanner.nextLong();
System.out.print("会话群组号:");
long groupId = scanner.nextLong();
LineReader lineReader = LineReaderBuilder.builder()
.appName("CGJ")
.history(new DefaultHistory())
.terminal(TerminalBuilder.builder()
.dumb(true)
.build())
.build();
long qqId = Long.parseLong(lineReader.readLine("会话QQ: "));
long groupId = Long.parseLong(lineReader.readLine("会话群组号:"));
boolean isGroup = false;
do {
String input = scanner.nextLine();
String input = lineReader.readLine("App " + qqId + (isGroup ? "@" + groupId : "$private") + " >");
if(input.equalsIgnoreCase("#exit")) {
System.out.println("退出应用...");
break;
@ -27,7 +41,11 @@ public class ConsoleMain {
System.out.println("System: 群模式状态已变更: " + isGroup);
continue;
}
BotEventHandler.executeMessageEvent(new ConsoleMessageEvent(isGroup ? groupId : 0, qqId, input));
try {
BotEventHandler.executeMessageEvent(new ConsoleMessageEvent(isGroup ? groupId : 0, qqId, input), true);
} catch (InterruptedException e) {
log.error("执行时发生中断", e);
}
} while(true);
}

View File

@ -134,6 +134,7 @@ public class MiraiMessageSender implements MessageSender {
* @param code 图片BotCode
* @return Image对象
*/
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
public Image uploadImage(BotCode code) {
log.debug("传入BotCode信息:\n{}", code);
String absolutePath = code.getParameter("absolutePath");

View File

@ -82,7 +82,33 @@ public final class PixivUgoiraBuilder {
log.debug("IllustId: {}, UgoiraMeta: {}", this.illustId, this.ugoiraMeta);
}
/**
* 获取动图元数据
* @return 动图元数据, 返回的对象不影响Builder中的meta对象
*/
public JsonObject getUgoiraMeta() {
return this.ugoiraMeta.deepCopy();
}
/**
* 构建动图
* @param original 是否为原图画质
* @return 返回动图数据输入流
* @throws IOException 当获取数据发生异常时抛出
*/
public InputStream buildUgoira(boolean original) throws IOException {
ByteArrayOutputStream bufferOutput = new ByteArrayOutputStream();
buildUgoira(bufferOutput, original);
return new ByteArrayInputStream(bufferOutput.toByteArray());
}
/**
* 构建动图
* @param outputStream 动图输出流
* @param original 是否为原图画质
* @throws IOException 当获取数据发生异常时抛出
*/
public void buildUgoira(OutputStream outputStream, boolean original) throws IOException {
getUgoiraImageSize();
log.debug("动图尺寸信息: Height: {}, Width: {}", height, width);
@ -95,7 +121,6 @@ public final class PixivUgoiraBuilder {
HttpResponse response = httpClient.execute(request);
log.trace("请求已发送, 正在处理响应...");
ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(response.getEntity().getContent(), 64 * 1024));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipEntry entry;
ByteArrayOutputStream cacheOutputStream = new ByteArrayOutputStream(512);
HashMap<String, InputStream> frameMap = new HashMap<>(frames.size());
@ -140,7 +165,6 @@ public final class PixivUgoiraBuilder {
}
});
encoder.finishEncoding();
return new ByteArrayInputStream(outputStream.toByteArray());
}
/**

View File

@ -11,7 +11,8 @@
<Console name="CONSOLE_STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="${pattern}" charset="${charset}"/>
<Filters>
<LevelRangeFilter minLevel="INFO" maxLevel="INFO" />
<ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</Console>
<Console name="CONSOLE_STDERR" target="SYSTEM_ERR">
@ -31,7 +32,7 @@
<Loggers>
<Logger level="INFO" name="org.apache.http"/>
<Root level="TRACE">
<Root level="INFO">
<AppenderRef ref="CONSOLE_STDOUT"/>
<AppenderRef ref="CONSOLE_STDERR"/>
<AppenderRef ref="rollingFile"/>

View File

@ -1,11 +1,12 @@
package net.lamgc.cgj.pixiv;
import org.apache.http.HttpHost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.bouncycastle.util.io.Streams;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@ -18,8 +19,9 @@ public class PixivUgoiraBuilderTest {
@Test
public void buildTest() throws IOException {
File outputFile = new File("./output2.gif");
CloseableHttpClient httpClient = HttpClientBuilder.create().setProxy(new HttpHost("127.0.0.1", 1001)).build();
PixivUgoiraBuilder builder = new PixivUgoiraBuilder(httpClient, 80766493);
HttpClient httpClient = HttpClientBuilder.create().setProxy(new HttpHost("127.0.0.1", 1080)).build();
PixivUgoiraBuilder builder = new PixivUgoiraBuilder(httpClient, 81163967);
LoggerFactory.getLogger(PixivUgoiraBuilderTest.class).info("UgoiraMeta: {}", builder.getUgoiraMeta());
InputStream inputStream = builder.buildUgoira(true);
Files.write(outputFile.toPath(), Streams.readAll(inputStream));
}