mirror of
https://github.com/LamGC/ContentGrabbingJi.git
synced 2025-07-02 05:17:26 +00:00
Compare commits
15 Commits
v2.5.1
...
v2.5.2-202
Author | SHA1 | Date | |
---|---|---|---|
60fa641962 | |||
3ab373cc70 | |||
461cd246d8 | |||
f040f130d7 | |||
1f402fbbac | |||
f7f3c3beaf | |||
04c1753c22 | |||
d993e9d719 | |||
60e91987d1 | |||
65392fc2fe | |||
d38934a0f4 | |||
7943357d96 | |||
a170ff040b | |||
cb2ebfdb73 | |||
66b22c543a |
14
.gitignore
vendored
14
.gitignore
vendored
@ -1,6 +1,16 @@
|
||||
# Ignore test date folder
|
||||
/pluginData/
|
||||
/logs/
|
||||
/.idea/
|
||||
/CGJ_2.iml
|
||||
/cookies.store
|
||||
/target/
|
||||
|
||||
# Ignore Idea files
|
||||
/.idea/
|
||||
/CGJ_2.iml
|
||||
|
||||
# Ignore Visual Studio Code files
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
/.settings/
|
||||
/.vscode/
|
||||
|
18
documents/interfaces/Pixiv接口标准返回格式.md
Normal file
18
documents/interfaces/Pixiv接口标准返回格式.md
Normal file
@ -0,0 +1,18 @@
|
||||
## Pixiv接口标准返回格式 ##
|
||||
Pixiv大部分接口在返回数据时都会遵循以下格式:
|
||||
```json
|
||||
{
|
||||
"error": false,
|
||||
"message": "",
|
||||
"body": {
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
大部分是如此(部分接口比较特别, 不是这个格式)
|
||||
|
||||
属性|类型|说明
|
||||
---|---|---
|
||||
error|Boolean|如果接口返回错误信息, 该属性为`true`
|
||||
message|String|如果`error`属性为`true`, 则该属性不为空字符串
|
||||
body|Object/Array|如果`error`不为`true`, 该属性有数据, 否则属性可能不存在
|
16
documents/interfaces/Pixiv搜索接口.md
Normal file
16
documents/interfaces/Pixiv搜索接口.md
Normal file
@ -0,0 +1,16 @@
|
||||
## Pixiv内容搜索接口 ##
|
||||
接口地址:
|
||||
```
|
||||
GET https://www.pixiv.net/ajax/search/{Type}/{Content}?{参数...}
|
||||
```
|
||||
变量名:
|
||||
- `Type`: 内容类型
|
||||
- illustrations(插画)
|
||||
- top(推荐)
|
||||
- manga(漫画)
|
||||
- novels(小说)
|
||||
- `Content`: 搜索内容
|
||||
|
||||
|
||||
参数列表:
|
||||
- `word`
|
127
documents/interfaces/Pixiv首页数据接口.md
Normal file
127
documents/interfaces/Pixiv首页数据接口.md
Normal file
@ -0,0 +1,127 @@
|
||||
## Pixiv首页数据接口 ##
|
||||
|
||||
说明:
|
||||
该接口涉及用户账户隐私, 不要尝试对该接口返回数据做不安全云端存储, 或未经用户允许的发送出去.
|
||||
|
||||
接口地址:
|
||||
```
|
||||
GET https://www.pixiv.net/ajax/top/{type}?mode={mode}&lang={lang}
|
||||
```
|
||||
|
||||
参数:
|
||||
- `type`: 首页类型
|
||||
- `illust`: 插画
|
||||
- `manga`: 漫画
|
||||
- `novel`: 小说
|
||||
- `mode`: 内容类型
|
||||
- `all`: 不限类型
|
||||
- `r18`: 成人内容
|
||||
- `lang`: 语言(只写几个)
|
||||
- `zh`: 中文
|
||||
|
||||
> 是否需要登录: `是`
|
||||
> 是否为Pixiv接口标准返回格式: `是`
|
||||
> 是否需要Referer请求头: `未知`
|
||||
|
||||
请求Url示例:
|
||||
```
|
||||
GET https://www.pixiv.net/ajax/top/illust?mode=all&lang=zh
|
||||
```
|
||||
|
||||
响应示例:
|
||||
```
|
||||
(内容过长, 略)
|
||||
```
|
||||
|
||||
返回内容(Json):
|
||||
- `page`: 网页相关内容
|
||||
- `tags`: (`Object[]`) 热门标签
|
||||
- `tag`: (`String`) 标签名
|
||||
- `count`: (`Number`) 作品数量?
|
||||
- `lev`: (`Number`) 不明?
|
||||
- `ids`: (`Number[]`) 作品数组
|
||||
- `follow`: (`Number[]`) 已关注作者的作品推荐
|
||||
- `mypixiv`: (`?[]`) 不明
|
||||
- `recommend`: (`String[]` -> `Number[]`) 推荐作品的Id?
|
||||
- `recommendByTag`: (`Object[]`) 标签的推荐作品
|
||||
- `tag`: (`String`) 标签名
|
||||
- `ids`: ((`String[]` -> `Number[]`) 作品Id数组
|
||||
- `ranking`: (`Object`) 排行榜前100名数据
|
||||
- `date`: (`String`) 排行榜日期(`yyyyMMdd`)
|
||||
- `items`: (`Object[]`) 排行榜简略数据
|
||||
- `rank`: (`String` -> `Number`) 排行榜名次
|
||||
- `id`: (`String` -> `Number`) 作品Id
|
||||
- `pixivision`: (`Object[]`) Pixiv的推荐文章
|
||||
- `id`: (`String` -> `Number`) 文章Id
|
||||
- `title`: (`String`) 文章标题
|
||||
- `thumbnailUrl`: (`String`) 文章封面图的Url地址
|
||||
- `abtestId`: (`String` -> `Number`) pixivision文章地址的参数`utm_content`的值
|
||||
- `recommendUser`: (`Object[]`) 推荐用户及其作品
|
||||
- `id`: (`Number`) 用户Id
|
||||
- `illustIds`: (`String[]` -> `Number[]`) 插画作品Id
|
||||
- `novelIds`: (`String[]` -> `Number[]`) 小说作品Id
|
||||
- `contestOngoing`: (`Object[]`) 进行中的比赛活动(没找到更多信息了, 先这么说着)
|
||||
- (待完善)
|
||||
- `contestResult`: (`Object[]`) 比赛结果信息
|
||||
- `slug`: (`String`) 比赛代号?
|
||||
- `type`: (`String`) 比赛作品类型?
|
||||
- `name`: (`String`) 比赛名
|
||||
- `url`: (`String`) 结果公布链接
|
||||
- `iconUrl`: (`String`) 图标链接(不明意义的图标)
|
||||
- `editorRecommend`: (`Object[]`) 编辑推荐(小说), 后续可能会删除, 这个应该是配合活动出的数据
|
||||
- (待完善)
|
||||
- `boothFollowItemIds`: (`String[]` -> `Number[]`) 已关注用户的最新商品
|
||||
- `sketchLiveFollowIds`: (`?[]`) 不明?
|
||||
- `sketchLivePopularIds`: (`String[]` -> `Number[]`) 不明?
|
||||
- `myFavoriteTags`: (`?[]`) 关注的标签
|
||||
- `newPost`: (`String[]` -> `Number[]`) 不明?
|
||||
- `thumbnails`: (`Object`) 已关注用户的作品
|
||||
- `illust`: (`Object[]`) 插画作品
|
||||
- `illustId`: (`String` -> `Number`) 作品Id(或者准确来讲是 插画Id?)
|
||||
- `illustTitle`: (`String`) 插画标题
|
||||
- `id`: (`String` -> `Number`) 作品Id
|
||||
- `title`: (`String`) 作品标题
|
||||
- `illustType`: (`Number`) 作品类型
|
||||
- `xRestrict`: (`Number`) 不明?
|
||||
- `restrict`: (`Number`) 不明?
|
||||
- `sl`: (`Number`) 不明?
|
||||
- `url`: (`String`) 作品在主页的封面图Url
|
||||
- `description`: (`String`) 作品说明?
|
||||
- `tags`: (`String[]`) 标签原始名数组(不带翻译的原始名称)
|
||||
- `userId`: (`String` -> `Number`) 用户Id
|
||||
- `userName`: (`String`) 用户名
|
||||
- `width`: (`Number`) 作品宽度
|
||||
- `height`: (`Number`) 作品高度
|
||||
- `pageCount`: (`Number`) 作品页数
|
||||
- `isBookmarkable`: (`Boolean`) 不明?
|
||||
- `bookmarkData`: (`?`) 不明?
|
||||
- `alt`: (`String`) 简略信息
|
||||
- `isAdContainer`: (`Boolean`) 广告标识?
|
||||
- `titleCaptionTranslation`: (`Object`) 不明?
|
||||
- (待完善)
|
||||
- `urls`: (`Object`) 其他封面图尺寸的链接
|
||||
- (略)
|
||||
- `seriesId`: (`?`) 不明?
|
||||
- `seriesTitle`: (`?`) 不明?
|
||||
- `profileImageUrl`: (`String`) 用户头像图链接
|
||||
- `users`: (`Object[]`) 用户信?
|
||||
- `userId`: (`String` -> `Number`) 用户Id
|
||||
- `name`: (`String`) 用户名
|
||||
- `image`: (`String`) 用户头像图链接
|
||||
- `imageBig`: (`String`) 用户大尺寸头像图链接
|
||||
- `premium`: (`Boolean`) 是否为Pixiv高级会员
|
||||
- `isFollowed`: (`Boolean`) 是否关注
|
||||
- `isMypixiv`: (`Boolean`) 不明?
|
||||
- `isBlocking`: (`Boolean`) 是否为黑名单?
|
||||
- `background`: (`?`) 不明?
|
||||
- `partial`: (`Number`) 不明?
|
||||
- `tagTranslation`: 标签翻译名
|
||||
- `key=${标签原始名}`: (`Object`) 标签翻译信息
|
||||
- `${语言代码}`: (`String`) 对应语言代码的翻译, 不一定有
|
||||
- `boothItems`: (`Object[]`) 商品信息
|
||||
- (待完善)
|
||||
- `sketchLives`: (`Object[]`) 不明?
|
||||
- (待完善)
|
||||
- `zoneConfig`: (`Object`) 不明?
|
||||
- (待完善)
|
||||
|
6
pom.xml
6
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>net.lamgc</groupId>
|
||||
<artifactId>ContentGrabbingJi</artifactId>
|
||||
<version>2.5.1</version>
|
||||
<version>2.5.2-20200520.1-SNAPSHOT</version>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
@ -19,7 +19,7 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
<mirai.CoreVersion>0.39.4</mirai.CoreVersion>
|
||||
<mirai.CoreVersion>1.0-RC2-1</mirai.CoreVersion>
|
||||
<mirai.JaptVersion>1.1.1</mirai.JaptVersion>
|
||||
<kotlin.version>1.3.71</kotlin.version>
|
||||
<ktor.version>1.3.2</ktor.version>
|
||||
@ -86,7 +86,7 @@
|
||||
<dependency>
|
||||
<groupId>net.lamgc</groupId>
|
||||
<artifactId>java-utils</artifactId>
|
||||
<version>1.2.0_20200505.1-SNAPSHOT</version>
|
||||
<version>1.2.0_20200514.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -86,13 +86,15 @@ public class Main {
|
||||
File cookieStoreFile = new File(System.getProperty("cgj.botDataDir"), "cookies.store");
|
||||
if(!cookieStoreFile.exists()) {
|
||||
log.warn("未找到cookies.store文件, 是否启动PixivLoginProxyServer? (yes/no)");
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
if(scanner.nextLine().trim().equalsIgnoreCase("yes")) {
|
||||
startPixivLoginProxyServer();
|
||||
} else {
|
||||
System.exit(1);
|
||||
return;
|
||||
try(Scanner scanner = new Scanner(System.in)) {
|
||||
if(scanner.nextLine().trim().equalsIgnoreCase("yes")) {
|
||||
startPixivLoginProxyServer();
|
||||
} else {
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(cookieStoreFile));
|
||||
cookieStore = (CookieStore) ois.readObject();
|
||||
@ -137,7 +139,9 @@ public class Main {
|
||||
|
||||
@Command
|
||||
public static void botMode(@Argument(name = "args", force = false) String argsStr) {
|
||||
new MiraiMain().init();
|
||||
MiraiMain main = new MiraiMain();
|
||||
main.init();
|
||||
main.close();
|
||||
}
|
||||
|
||||
@Command
|
||||
@ -398,7 +402,7 @@ public class Main {
|
||||
private static void saveCookieStoreToFile() throws IOException {
|
||||
log.info("正在保存CookieStore...");
|
||||
File outputFile = new File(System.getProperty("cgj.botDataDir"), "cookies.store");
|
||||
if(!outputFile.exists() && !outputFile.delete() && !outputFile.createNewFile()){
|
||||
if(!outputFile.exists() && !outputFile.createNewFile()){
|
||||
log.error("保存CookieStore失败.");
|
||||
return;
|
||||
}
|
||||
@ -423,23 +427,25 @@ public class Main {
|
||||
proxyServerStartThread.setName("LoginProxyServerThread");
|
||||
proxyServerStartThread.start();
|
||||
//System.console().readLine();
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
|
||||
log.info("登录完成后, 使用\"done\"命令结束登录过程.");
|
||||
while(true) {
|
||||
if (scanner.nextLine().equalsIgnoreCase("done")) {
|
||||
log.info("关闭PLPS服务器...");
|
||||
proxyServer.close();
|
||||
cookieStore = proxyServer.getCookieStore();
|
||||
try {
|
||||
log.info("正在保存CookieStore...");
|
||||
saveCookieStoreToFile();
|
||||
log.info("CookieStore保存完成.");
|
||||
} catch (IOException e) {
|
||||
log.error("CookieStore保存时发生异常, 本次CookieStore仅可在本次运行使用.", e);
|
||||
try(Scanner scanner = new Scanner(System.in)) {
|
||||
while(true) {
|
||||
if (scanner.nextLine().equalsIgnoreCase("done")) {
|
||||
log.info("关闭PLPS服务器...");
|
||||
proxyServer.close();
|
||||
cookieStore = proxyServer.getCookieStore();
|
||||
try {
|
||||
log.info("正在保存CookieStore...");
|
||||
saveCookieStoreToFile();
|
||||
log.info("CookieStore保存完成.");
|
||||
} catch (IOException e) {
|
||||
log.error("CookieStore保存时发生异常, 本次CookieStore仅可在本次运行使用.", e);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
log.warn("要结束登录过程, 请使用\"done\"命令.");
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
log.warn("要结束登录过程, 请使用\"done\"命令.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
package net.lamgc.cgj.bot;
|
||||
|
||||
import net.lz1998.cq.robot.CoolQ;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class AutoArtworksSender {
|
||||
|
||||
private final CoolQ CQ;
|
||||
private final ReceiveType receiveType;
|
||||
private final long targetReceiveId;
|
||||
private Timer timer = new Timer();
|
||||
private TimerTask task = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
HttpGet request = new HttpGet();
|
||||
|
||||
// https://api.imjad.cn/pixiv/v2/?type=tags
|
||||
}
|
||||
};
|
||||
|
||||
public AutoArtworksSender(CoolQ cq, ReceiveType receiveType, long receiveId) {
|
||||
this.CQ = cq;
|
||||
this.receiveType = receiveType;
|
||||
this.targetReceiveId = receiveId;
|
||||
}
|
||||
|
||||
public void reset(long time) {
|
||||
if(time <= 0) {
|
||||
timer.schedule(task, new Random().nextInt(10 * 60 * 60 * 1000) + 7200000L); //2H ~ 12H
|
||||
} else {
|
||||
timer.schedule(task, time);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(String message, boolean auto_escape) {
|
||||
switch (receiveType) {
|
||||
case GROUP:
|
||||
CQ.sendGroupMsg(targetReceiveId, message, auto_escape);
|
||||
break;
|
||||
case Discuss:
|
||||
CQ.sendDiscussMsg(targetReceiveId, message, auto_escape);
|
||||
break;
|
||||
case PRIVATE:
|
||||
CQ.sendPrivateMsg(targetReceiveId, message, auto_escape);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ReceiveType {
|
||||
PRIVATE, GROUP, Discuss
|
||||
}
|
||||
|
||||
}
|
@ -7,10 +7,14 @@ import io.netty.handler.codec.http.HttpHeaderNames;
|
||||
import net.lamgc.cgj.Main;
|
||||
import net.lamgc.cgj.bot.cache.*;
|
||||
import net.lamgc.cgj.bot.event.BotEventHandler;
|
||||
import net.lamgc.cgj.bot.event.BufferMessageEvent;
|
||||
import net.lamgc.cgj.bot.sort.PreLoadDataComparator;
|
||||
import net.lamgc.cgj.pixiv.PixivDownload;
|
||||
import net.lamgc.cgj.pixiv.PixivSearchBuilder;
|
||||
import net.lamgc.cgj.pixiv.PixivURL;
|
||||
import net.lamgc.cgj.pixiv.PixivDownload.PageQuality;
|
||||
import net.lamgc.cgj.pixiv.PixivURL.RankingContentType;
|
||||
import net.lamgc.cgj.pixiv.PixivURL.RankingMode;
|
||||
import net.lamgc.cgj.util.URLs;
|
||||
import net.lamgc.utils.base.runner.Argument;
|
||||
import net.lamgc.utils.base.runner.Command;
|
||||
@ -109,7 +113,7 @@ public class BotCommandProcess {
|
||||
helpStrBuilder.append("CGJ Bot使用指南").append("\n");
|
||||
helpStrBuilder.append("使用方法:.cgj <命令> [参数...]").append("\n");
|
||||
helpStrBuilder.append("例如查询作品信息功能:").append("\n");
|
||||
helpStrBuilder.append(".cgj artwork -id 80846159").append("\n");
|
||||
helpStrBuilder.append(".cgj info -id 80846159").append("\n");
|
||||
helpStrBuilder.append("目前可用的命令:").append("\n");
|
||||
helpStrBuilder.append("\t").append("ranking - 获取今天或指定日期排行榜的前10名作品").append("\n");
|
||||
helpStrBuilder.append("\t\t").append("-date - 指定查询日期(年-月-日)").append("\n");
|
||||
@ -295,6 +299,18 @@ public class BotCommandProcess {
|
||||
return "功能未完成";
|
||||
}
|
||||
|
||||
@Command(commandName = "st")
|
||||
public static String r18Image() {
|
||||
BufferMessageEvent event = new BufferMessageEvent();
|
||||
RandomRankingArtworksSender artworksSender =
|
||||
new RandomRankingArtworksSender(event, 1, 200,
|
||||
RankingMode.MODE_MALE,
|
||||
RankingContentType.TYPE_ALL,
|
||||
PageQuality.ORIGINAL);
|
||||
artworksSender.send();
|
||||
return event.getBufferMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索命令
|
||||
* @param fromGroup 来源群(系统提供)
|
||||
|
@ -27,7 +27,8 @@ public class RankingUpdateTimer {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(firstRunDate == null ? new Date() : firstRunDate);
|
||||
LocalDate currentLocalDate = LocalDate.now();
|
||||
if(cal.get(Calendar.DAY_OF_YEAR) <= currentLocalDate.getDayOfYear() && cal.get(Calendar.HOUR_OF_DAY) >= 12) {
|
||||
if(cal.get(Calendar.DAY_OF_YEAR) <= currentLocalDate.getDayOfYear() &&
|
||||
cal.get(Calendar.HOUR_OF_DAY) >= 11 && cal.get(Calendar.MINUTE) >= 30) {
|
||||
cal.set(Calendar.DAY_OF_YEAR, currentLocalDate.getDayOfYear() + 1);
|
||||
}
|
||||
cal.set(Calendar.HOUR_OF_DAY, 11);
|
||||
@ -35,13 +36,14 @@ public class RankingUpdateTimer {
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
log.warn("已设置排行榜定时更新, 首次运行时间: {}", cal.getTime());
|
||||
long delay = cal.getTime().getTime() - (System.currentTimeMillis());
|
||||
log.warn("已设置排行榜定时更新, 首次运行时间: {} ({}min)", cal.getTime(), delay / 1000 / 60);
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
now(null);
|
||||
}
|
||||
}, cal.getTime(), 86400000); // 1 Day
|
||||
}, delay, 86400000); // 1 Day
|
||||
}
|
||||
|
||||
public void now(Date queryDate) {
|
||||
|
@ -10,7 +10,7 @@ import java.util.*;
|
||||
|
||||
public final class SettingProperties {
|
||||
|
||||
private final static Logger log = LoggerFactory.getLogger("SettingProperties");
|
||||
private final static Logger log = LoggerFactory.getLogger(SettingProperties.class.getName());
|
||||
|
||||
private final static File globalPropFile = new File(getPropertiesDir(), "global.properties");
|
||||
private final static Properties globalProp = new Properties();
|
||||
@ -95,7 +95,7 @@ public final class SettingProperties {
|
||||
|
||||
private static void saveGroupProperties(Long groupId, Properties properties) throws IOException {
|
||||
File groupPropFile = new File(getPropertiesDir(), "group." + groupId + ".properties");
|
||||
if((!groupPropFile.exists() || !groupPropFile.isFile()) && (!groupPropFile.delete() || !groupPropFile.createNewFile())) {
|
||||
if(!groupPropFile.exists() && !groupPropFile.createNewFile()) {
|
||||
log.error("群组 {} 配置文件创建失败!", groupId);
|
||||
return;
|
||||
}
|
||||
@ -122,7 +122,7 @@ public final class SettingProperties {
|
||||
*/
|
||||
private static void saveGlobalProperties() {
|
||||
try {
|
||||
if((!globalPropFile.exists() || !globalPropFile.isFile()) && (!globalPropFile.delete() || !globalPropFile.createNewFile())) {
|
||||
if(!globalPropFile.exists() && !globalPropFile.createNewFile()) {
|
||||
log.error("创建全局配置文件失败.");
|
||||
return;
|
||||
}
|
||||
@ -158,7 +158,7 @@ public final class SettingProperties {
|
||||
*/
|
||||
private static File getPropertiesDir() {
|
||||
File propDir = new File(System.getProperty("cgj.botDataDir"), "/setting/");
|
||||
if((!propDir.exists() || !propDir.isDirectory()) && (!propDir.delete() || !propDir.mkdirs())) {
|
||||
if(!propDir.exists() && !propDir.mkdirs()) {
|
||||
log.warn("Setting文件夹创建失败!");
|
||||
}
|
||||
return propDir;
|
||||
|
@ -8,7 +8,6 @@ import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public final class ImageCacheStore {
|
||||
@ -102,8 +101,6 @@ public final class ImageCacheStore {
|
||||
|
||||
public final AtomicReference<TaskState> taskState = new AtomicReference<>(TaskState.READY);
|
||||
|
||||
public final Condition condition = lock.newCondition();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,19 +12,45 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
* 基于Hashtable的本地缓存库
|
||||
* @param <T> 缓存类型
|
||||
*/
|
||||
public class LocalHashCacheStore<T> implements CacheStore<T> {
|
||||
public class LocalHashCacheStore<T> implements CacheStore<T>, Cleanable {
|
||||
|
||||
private final Hashtable<String, CacheObject<T>> cache;
|
||||
|
||||
/**
|
||||
* 构造一个基于Hashtable的本地缓存库
|
||||
* @see Hashtable
|
||||
*/
|
||||
public LocalHashCacheStore() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造一个基于Hashtable的本地缓存库
|
||||
* @param initialCapacity 初始容量
|
||||
* @see Hashtable
|
||||
*/
|
||||
public LocalHashCacheStore(int initialCapacity) {
|
||||
this(initialCapacity, 0F);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造一个基于Hashtable的本地缓存库
|
||||
* @param initialCapacity 初始容量
|
||||
* @param loadFactor 重载因子
|
||||
* @see Hashtable
|
||||
*/
|
||||
public LocalHashCacheStore(int initialCapacity, float loadFactor) {
|
||||
this(initialCapacity, loadFactor, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造一个基于Hashtable的本地缓存库
|
||||
* @param initialCapacity 初始容量
|
||||
* @param loadFactor 重载因子
|
||||
* @param autoClean 是否自动清理
|
||||
* @see Hashtable
|
||||
*/
|
||||
public LocalHashCacheStore(int initialCapacity, float loadFactor, boolean autoClean) {
|
||||
if(initialCapacity != 0) {
|
||||
if(loadFactor <= 0F) {
|
||||
cache = new Hashtable<>(initialCapacity);
|
||||
@ -34,6 +60,10 @@ public class LocalHashCacheStore<T> implements CacheStore<T> {
|
||||
} else {
|
||||
cache = new Hashtable<>();
|
||||
}
|
||||
|
||||
if(autoClean) {
|
||||
AutoCleanTimer.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -118,6 +148,15 @@ public class LocalHashCacheStore<T> implements CacheStore<T> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clean() throws Exception {
|
||||
Date currentDate = new Date();
|
||||
cache.forEach((key, value) -> {
|
||||
if(value.isExpire(currentDate)) {
|
||||
cache.remove(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class CacheObject<T> implements Comparable<CacheObject<T>> {
|
||||
|
||||
|
@ -224,7 +224,7 @@ public class BotEventHandler implements EventHandler {
|
||||
}
|
||||
}
|
||||
long processTime = System.currentTimeMillis() - time;
|
||||
if(Objects.requireNonNull(result) instanceof String && !isMute(event.getFromGroup())) {
|
||||
if(!Objects.isNull(result) && result instanceof String && !isMute(event.getFromGroup())) {
|
||||
try {
|
||||
event.sendMessage((String) result);
|
||||
} catch (Exception e) {
|
||||
|
@ -0,0 +1,59 @@
|
||||
package net.lamgc.cgj.bot.event;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class BufferMessageEvent extends MessageEvent {
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
public final MessageEvent parent;
|
||||
|
||||
/**
|
||||
* 以空消息空Id生成BufferMessageEvent
|
||||
*/
|
||||
public BufferMessageEvent() {
|
||||
super(0, 0, "");
|
||||
parent = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供消息内容构造BufferMessageEvent
|
||||
* @param message 传入的消息内容
|
||||
*/
|
||||
public BufferMessageEvent(String message) {
|
||||
super(0, 0, message);
|
||||
parent = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用事件构造BufferMessageEvent
|
||||
* @param parentEvent 父级消息事件对象
|
||||
*/
|
||||
public BufferMessageEvent(MessageEvent parentEvent) {
|
||||
super(parentEvent.getFromGroup(), parentEvent.getFromQQ(), parentEvent.getMessage());
|
||||
parent = parentEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sendMessage(String message) {
|
||||
buffer.append(message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当提供了父级消息事件时, 本方法调用父级消息事件对象的{@code getImageUrl(String)}, 如果没有, 返回{@code null}
|
||||
*/
|
||||
@Override
|
||||
public String getImageUrl(String image) {
|
||||
return Objects.isNull(this.parent) ? null : this.parent.getImageUrl(image);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓冲区消息内容
|
||||
* @return 消息内容
|
||||
*/
|
||||
public String getBufferMessage() {
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
@ -12,7 +12,7 @@ public abstract class MessageEvent implements EventObject, MessageSender {
|
||||
public MessageEvent(long fromGroup, long fromQQ, String message) {
|
||||
this.fromGroup = fromGroup;
|
||||
this.fromQQ = fromQQ;
|
||||
this.message = message;
|
||||
this.message = message.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,9 +9,7 @@ import net.mamoe.mirai.BotFactoryJvm;
|
||||
import net.mamoe.mirai.event.events.BotMuteEvent;
|
||||
import net.mamoe.mirai.event.events.BotUnmuteEvent;
|
||||
import net.mamoe.mirai.japt.Events;
|
||||
import net.mamoe.mirai.message.ContactMessage;
|
||||
import net.mamoe.mirai.message.FriendMessage;
|
||||
import net.mamoe.mirai.message.GroupMessage;
|
||||
import net.mamoe.mirai.message.*;
|
||||
import net.mamoe.mirai.utils.BotConfiguration;
|
||||
import org.apache.commons.net.util.Base64;
|
||||
import org.slf4j.Logger;
|
||||
@ -45,9 +43,11 @@ public class MiraiMain implements Closeable {
|
||||
return;
|
||||
}
|
||||
|
||||
bot = BotFactoryJvm.newBot(Long.parseLong(botProperties.getProperty("bot.qq", "0")), Base64.decodeBase64(botProperties.getProperty("bot.password", "")), new BotConfiguration());
|
||||
Events.subscribeAlways(GroupMessage.class, this::executeMessageEvent);
|
||||
Events.subscribeAlways(FriendMessage.class, this::executeMessageEvent);
|
||||
BotConfiguration configuration = new BotConfiguration();
|
||||
configuration.setProtocol(BotConfiguration.MiraiProtocol.ANDROID_PAD);
|
||||
bot = BotFactoryJvm.newBot(Long.parseLong(botProperties.getProperty("bot.qq", "0")), Base64.decodeBase64(botProperties.getProperty("bot.password", "")), configuration);
|
||||
Events.subscribeAlways(GroupMessageEvent.class, this::executeMessageEvent);
|
||||
Events.subscribeAlways(FriendMessageEvent.class, this::executeMessageEvent);
|
||||
Events.subscribeAlways(BotMuteEvent.class,
|
||||
event -> BotEventHandler.setMuteState(event.getGroup().getId(), true));
|
||||
Events.subscribeAlways(BotUnmuteEvent.class,
|
||||
@ -62,20 +62,27 @@ public class MiraiMain implements Closeable {
|
||||
* 处理消息事件
|
||||
* @param message 消息事件对象
|
||||
*/
|
||||
private void executeMessageEvent(ContactMessage message) {
|
||||
if(message instanceof GroupMessage) {
|
||||
GroupMessage groupMessage = (GroupMessage) message;
|
||||
if(BotEventHandler.isMute(groupMessage.getGroup().getId(), true) == null) {
|
||||
BotEventHandler.setMuteState(groupMessage.getGroup().getId(),
|
||||
((GroupMessage) message).getGroup().getBotMuteRemaining() != 0);
|
||||
private void executeMessageEvent(MessageEvent message) {
|
||||
if(message instanceof GroupMessageEvent) {
|
||||
GroupMessageEvent GroupMessageEvent = (GroupMessageEvent) message;
|
||||
if(BotEventHandler.isMute(GroupMessageEvent.getGroup().getId(), true) == null) {
|
||||
BotEventHandler.setMuteState(GroupMessageEvent.getGroup().getId(),
|
||||
((GroupMessageEvent) message).getGroup().getBotMuteRemaining() != 0);
|
||||
}
|
||||
}
|
||||
BotEventHandler.executeMessageEvent(new MiraiMessageEvent(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭机器人
|
||||
*/
|
||||
public void close() {
|
||||
if(bot == null) {
|
||||
return;
|
||||
}
|
||||
log.warn("正在关闭机器人...");
|
||||
bot.close(null);
|
||||
bot = null;
|
||||
log.warn("机器人已关闭.");
|
||||
}
|
||||
|
||||
|
@ -1,29 +1,27 @@
|
||||
package net.lamgc.cgj.bot.framework.mirai.message;
|
||||
|
||||
import net.lamgc.cgj.bot.event.MessageEvent;
|
||||
import net.lamgc.cgj.bot.message.MessageSender;
|
||||
import net.lamgc.cgj.bot.message.MessageSource;
|
||||
import net.mamoe.mirai.message.ContactMessage;
|
||||
import net.mamoe.mirai.message.GroupMessage;
|
||||
import net.mamoe.mirai.message.GroupMessageEvent;
|
||||
import net.mamoe.mirai.message.MessageEvent;
|
||||
import net.mamoe.mirai.message.data.MessageUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MiraiMessageEvent extends MessageEvent {
|
||||
public class MiraiMessageEvent extends net.lamgc.cgj.bot.event.MessageEvent {
|
||||
|
||||
private final ContactMessage messageObject;
|
||||
private final MessageEvent messageObject;
|
||||
private final MessageSender messageSender;
|
||||
|
||||
public MiraiMessageEvent(ContactMessage message) {
|
||||
super(message instanceof GroupMessage ? ((GroupMessage) message).getGroup().getId() : 0,
|
||||
public MiraiMessageEvent(MessageEvent message) {
|
||||
super(message instanceof GroupMessageEvent ? ((GroupMessageEvent) message).getGroup().getId() : 0,
|
||||
message.getSender().getId(), getMessageBodyWithoutSource(message.getMessage().toString()));
|
||||
this.messageObject = Objects.requireNonNull(message);
|
||||
if(message instanceof GroupMessage) {
|
||||
messageSender = new MiraiMessageSender(((GroupMessage) message).getGroup(), MessageSource.Group);
|
||||
if(message instanceof GroupMessageEvent) {
|
||||
messageSender = new MiraiMessageSender(((GroupMessageEvent) message).getGroup(), MessageSource.Group);
|
||||
} else {
|
||||
messageSender = new MiraiMessageSender(message.getSender(), MessageSource.Private);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,10 +11,7 @@ import net.lamgc.cgj.bot.message.MessageSender;
|
||||
import net.lamgc.cgj.bot.message.MessageSource;
|
||||
import net.mamoe.mirai.Bot;
|
||||
import net.mamoe.mirai.contact.Contact;
|
||||
import net.mamoe.mirai.message.data.Image;
|
||||
import net.mamoe.mirai.message.data.Message;
|
||||
import net.mamoe.mirai.message.data.MessageChain;
|
||||
import net.mamoe.mirai.message.data.MessageUtils;
|
||||
import net.mamoe.mirai.message.data.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -60,7 +57,7 @@ public class MiraiMessageSender implements MessageSender {
|
||||
public int sendMessage(final String message) {
|
||||
log.debug("处理前的消息内容:\n{}", message);
|
||||
Message msgBody = processMessage(Objects.requireNonNull(message));
|
||||
log.debug("处理后的消息内容(可能出现乱序的情况, 但实际上顺序是没问题的):\n{}", msgBody);
|
||||
log.debug("处理后的消息内容(可能出现乱序的情况, 但实际上顺序是没问题的):\n{}", msgBody.contentToString());
|
||||
member.sendMessage(msgBody);
|
||||
return 0;
|
||||
}
|
||||
@ -117,6 +114,15 @@ public class MiraiMessageSender implements MessageSender {
|
||||
} else {
|
||||
return img;
|
||||
}
|
||||
case "face":
|
||||
if(!code.containsParameter("id")) {
|
||||
return MessageUtils.newChain("(无效的表情Id)");
|
||||
}
|
||||
int faceId = Integer.parseInt(code.getParameter("id"));
|
||||
if(faceId <= 0) {
|
||||
return MessageUtils.newChain("(无效的表情Id)");
|
||||
}
|
||||
return new Face(faceId);
|
||||
default:
|
||||
log.warn("解析到不支持的BotCode: {}", code);
|
||||
return MessageUtils.newChain("(不支持的BotCode)");
|
||||
|
@ -5,6 +5,8 @@ import net.lamgc.cgj.bot.message.MessageSenderFactory;
|
||||
import net.lamgc.cgj.bot.message.MessageSource;
|
||||
import net.mamoe.mirai.Bot;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MiraiMessageSenderFactory implements MessageSenderFactory {
|
||||
|
||||
private final Bot bot;
|
||||
@ -14,15 +16,11 @@ public class MiraiMessageSenderFactory implements MessageSenderFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageSender createMessageSender(MessageSource source, long id) throws Exception {
|
||||
switch(source) {
|
||||
case Group:
|
||||
case Discuss:
|
||||
return new MiraiMessageSender(bot.getGroup(id), source);
|
||||
case Private:
|
||||
return new MiraiMessageSender(bot.getFriend(id), source);
|
||||
default:
|
||||
throw new NoSuchFieldException(source.toString());
|
||||
public MessageSender createMessageSender(MessageSource source, long id) {
|
||||
Objects.requireNonNull(source);
|
||||
if(id <= 0) {
|
||||
throw new IllegalArgumentException("id cannot be 0 or negative: " + id);
|
||||
}
|
||||
return new MiraiMessageSender(bot, source, id);
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ public class PixivAccessProxyServer {
|
||||
}*/
|
||||
log.info("Response Cookie: " + value);
|
||||
BasicClientCookie cookie = parseRawCookie(value);
|
||||
cookieStore.addCookie(null);
|
||||
cookieStore.addCookie(cookie);
|
||||
});
|
||||
httpResponse.headers().remove(HttpHeaderNames.SET_COOKIE);
|
||||
super.afterResponse(clientChannel, proxyChannel, httpResponse, pipeline);
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.lamgc.cgj.util;
|
||||
|
||||
import net.lamgc.cgj.pixiv.PixivDownload;
|
||||
import net.lamgc.cgj.pixiv.PixivURL;
|
||||
import net.lamgc.utils.base.runner.StringParameterParser;
|
||||
|
||||
public class PagesQualityParser implements StringParameterParser<PixivDownload.PageQuality> {
|
||||
|
Reference in New Issue
Block a user