mirror of
https://github.com/LamGC/ContentGrabbingJi.git
synced 2025-04-29 22:27:33 +00:00
[Add] PixivURL 增加搜索推荐接口Url; [Add] PixivSearchLinkBuilder 增加`getContent`方法以允许外部获取搜索原始内容; [Add] CacheStoreCentral 增加`getSearchBody(PixivSearchLinkBuilder)`方法以允许直接提供builder进行请求; [Change] CacheStoreCentral, PixivUtils 移除`getSearchBody(String, ...)`方法对PixivSearchLinkBuilder的构建, 将该部分转移至`PixivUtils.buildSearchLinkBuilder`方法; [Update] BotCommandProcess 增加`addRecommendKeywords(PixivSearchLinkBuilder, int)`方法以针对PixivSearchLinkBuilder的搜索原始内容增加指定数量的搜索推荐关键词;
410 lines
11 KiB
Java
410 lines
11 KiB
Java
package net.lamgc.cgj.pixiv;
|
|
|
|
import com.google.common.base.Strings;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.net.URLEncoder;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Date;
|
|
import java.util.HashSet;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* Pixiv搜索URL构造器
|
|
* <p>该构造器通过分析Pixiv搜索链接可用的参数而开发, 对搜索链接的构造有高度自定义能力.</p>
|
|
* @author LamGC
|
|
* @see PixivURL#PIXIV_SEARCH_CONTENT_URL
|
|
*/
|
|
@SuppressWarnings("unused")
|
|
public class PixivSearchLinkBuilder {
|
|
|
|
private final String content;
|
|
|
|
private SearchArea searchArea = SearchArea.ARTWORKS;
|
|
private SearchMode searchMode = SearchMode.TAG_FULL;
|
|
private SearchType searchType = SearchType.ILLUST_AND_UGOIRA;
|
|
private SearchOrder searchOrder = SearchOrder.DATE_D;
|
|
private SearchContentOption searchContentOption = SearchContentOption.ALL;
|
|
|
|
private final HashSet<String> includeKeywords = new HashSet<>(0);
|
|
private final HashSet<String> excludeKeywords = new HashSet<>(0);
|
|
|
|
private int page = 1;
|
|
|
|
private int wgt = 0;
|
|
private int hgt = 0;
|
|
|
|
private int wlt = 0;
|
|
private int hlt = 0;
|
|
|
|
private RatioOption ratioOption = null;
|
|
|
|
private Date startDate = null;
|
|
private Date endDate = null;
|
|
|
|
public PixivSearchLinkBuilder(String searchContent) {
|
|
this.content = Objects.requireNonNull(searchContent);
|
|
}
|
|
|
|
public String buildURL() {
|
|
StringBuilder builder;
|
|
try {
|
|
builder = new StringBuilder(PixivURL.PIXIV_SEARCH_CONTENT_URL.replaceAll("\\{area}", searchArea.name().toLowerCase())
|
|
.replaceAll("\\{content}",
|
|
URLEncoder.encode(getSearchCondition(), "UTF-8").replaceAll("\\+", "%20")
|
|
)
|
|
);
|
|
} catch (UnsupportedEncodingException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
if(searchArea.equals(SearchArea.TOP)) {
|
|
return builder.toString();
|
|
}
|
|
|
|
builder.append("&s_mode=").append(searchMode.name().toLowerCase());
|
|
builder.append("&type=").append(searchType.name().toLowerCase());
|
|
builder.append("&p=").append(page);
|
|
builder.append("&order=").append(searchOrder.name().toLowerCase());
|
|
builder.append("&mode=").append(searchContentOption.name().toLowerCase());
|
|
|
|
//可选参数
|
|
if(wgt > 0 && hgt > 0) {
|
|
builder.append("&wgt=").append(wgt);
|
|
builder.append("&hgt").append(hgt);
|
|
}
|
|
|
|
//可选参数
|
|
if(wlt > 0 && hlt > 0) {
|
|
builder.append("&wlt=").append(wlt);
|
|
builder.append("&hlt").append(hlt);
|
|
}
|
|
|
|
if (ratioOption != null) {
|
|
builder.append("&ratio=").append(ratioOption.value);
|
|
}
|
|
|
|
|
|
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
|
if (startDate != null) {
|
|
builder.append("&scd=").append(format.format(startDate));
|
|
}
|
|
if (endDate != null) {
|
|
builder.append("&ecd=").append(format.format(endDate));
|
|
}
|
|
|
|
return builder.toString();
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) return true;
|
|
if (o == null || getClass() != o.getClass()) return false;
|
|
PixivSearchLinkBuilder that = (PixivSearchLinkBuilder) o;
|
|
return page == that.page &&
|
|
wgt == that.wgt &&
|
|
hgt == that.hgt &&
|
|
wlt == that.wlt &&
|
|
hlt == that.hlt &&
|
|
content.equals(that.content) &&
|
|
searchArea == that.searchArea &&
|
|
searchMode == that.searchMode &&
|
|
searchType == that.searchType &&
|
|
searchOrder == that.searchOrder &&
|
|
searchContentOption == that.searchContentOption &&
|
|
includeKeywords.equals(that.includeKeywords) &&
|
|
excludeKeywords.equals(that.excludeKeywords) &&
|
|
ratioOption == that.ratioOption &&
|
|
Objects.equals(startDate, that.startDate) &&
|
|
Objects.equals(endDate, that.endDate);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(
|
|
content,
|
|
searchArea,
|
|
searchMode,
|
|
searchType,
|
|
searchOrder,
|
|
searchContentOption,
|
|
includeKeywords,
|
|
excludeKeywords,
|
|
page,
|
|
wgt,
|
|
hgt,
|
|
wlt,
|
|
hlt,
|
|
ratioOption,
|
|
startDate,
|
|
endDate);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "PixivSearchLinkBuilder{" +
|
|
"content='" + content + '\'' +
|
|
", searchArea=" + searchArea +
|
|
", searchMode=" + searchMode +
|
|
", searchType=" + searchType +
|
|
", searchOrder=" + searchOrder +
|
|
", searchContentOption=" + searchContentOption +
|
|
", includeKeywords=" + includeKeywords +
|
|
", excludeKeywords=" + excludeKeywords +
|
|
", page=" + page +
|
|
", wgt=" + wgt +
|
|
", hgt=" + hgt +
|
|
", wlt=" + wlt +
|
|
", hlt=" + hlt +
|
|
", ratioOption=" + ratioOption +
|
|
", startDate=" + startDate +
|
|
", endDate=" + endDate +
|
|
'}';
|
|
}
|
|
|
|
public String getContent() {
|
|
return content;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setSearchArea(SearchArea searchArea) {
|
|
this.searchArea = Objects.requireNonNull(searchArea);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* 获取搜索条件.
|
|
* @return 搜索条件内容
|
|
*/
|
|
public String getSearchCondition() {
|
|
StringBuilder searchContent = new StringBuilder(Strings.nullToEmpty(this.content));
|
|
if(searchArea.equals(SearchArea.TOP)) {
|
|
return searchContent.toString();
|
|
}
|
|
|
|
excludeKeywords.forEach(keyword -> searchContent.append(" -").append(keyword));
|
|
if(!includeKeywords.isEmpty()) {
|
|
if(!Strings.isNullOrEmpty(searchContent.toString())) {
|
|
searchContent.append(" (");
|
|
}
|
|
includeKeywords.forEach(keyword -> searchContent.append(keyword).append(" OR "));
|
|
int deleteStart = searchContent.lastIndexOf(" OR ");
|
|
if(searchContent.length() >= 4 && deleteStart != -1) {
|
|
searchContent.delete(deleteStart, searchContent.length());
|
|
}
|
|
if(!Strings.isNullOrEmpty(searchContent.toString())) {
|
|
searchContent.append(")");
|
|
}
|
|
}
|
|
|
|
return searchContent.toString();
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setSearchMode(SearchMode searchMode) {
|
|
this.searchMode = Objects.requireNonNull(searchMode);
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setSearchType(SearchType searchType) {
|
|
this.searchType = Objects.requireNonNull(searchType);
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setSearchOrder(SearchOrder searchOrder) {
|
|
this.searchOrder = Objects.requireNonNull(searchOrder);
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setSearchContentOption(SearchContentOption searchContentOption) {
|
|
this.searchContentOption = Objects.requireNonNull(searchContentOption);
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setRatioOption(RatioOption ratioOption) {
|
|
this.ratioOption = Objects.requireNonNull(ratioOption);
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setDateRange(Date startDate, Date endDate) {
|
|
this.startDate = startDate;
|
|
this.endDate = endDate;
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setMaxSize(int width, int height) {
|
|
this.wgt = width;
|
|
this.hgt = height;
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setMinSize(int width, int height) {
|
|
this.wlt = width;
|
|
this.hlt = height;
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder setPage(int pageIndex) {
|
|
if (pageIndex <= 0) {
|
|
throw new IllegalArgumentException("Invalid pageIndex: " + pageIndex);
|
|
}
|
|
this.page = pageIndex;
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder addExcludeKeyword(String keyword) {
|
|
excludeKeywords.add(keyword);
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder removeExcludeKeyword(String keyword) {
|
|
excludeKeywords.remove(keyword);
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder addIncludeKeyword(String keyword) {
|
|
includeKeywords.add(keyword);
|
|
return this;
|
|
}
|
|
|
|
public PixivSearchLinkBuilder removeIncludeKeyword(String keyword) {
|
|
includeKeywords.remove(keyword);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* 搜索区域
|
|
*/
|
|
public enum SearchArea {
|
|
/**
|
|
* 所有(可能是 插画 + 漫画)
|
|
*/
|
|
ARTWORKS("illustManga"),
|
|
/**
|
|
* 顶部(所有内容)
|
|
* 同时包含了:
|
|
* {@link #ILLUSTRATIONS}
|
|
* {@link #MANGA}
|
|
* {@link #NOVELS}
|
|
* 选择此项后, 将直接显示所有与content相关内容, 而忽略所有附加搜索条件.
|
|
* 因为无法指定pageIndex, 数据只有24项
|
|
*/
|
|
TOP(null),
|
|
/**
|
|
* 插画
|
|
*/
|
|
ILLUSTRATIONS("illust"),
|
|
/**
|
|
* 漫画
|
|
*/
|
|
MANGA("manga"),
|
|
/**
|
|
* 小说
|
|
*/
|
|
NOVELS("novel");
|
|
|
|
public final String jsonKey;
|
|
|
|
SearchArea(String jsonKey) {
|
|
this.jsonKey = jsonKey;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* 搜索模式
|
|
*/
|
|
public enum SearchMode {
|
|
/**
|
|
* 按标签搜索, 部分一致
|
|
*/
|
|
TAG,
|
|
/**
|
|
* 按标签搜索, 完全一致
|
|
*/
|
|
TAG_FULL,
|
|
/**
|
|
* 按标题和说明文字搜索
|
|
*/
|
|
TC
|
|
}
|
|
|
|
/**
|
|
* 搜索内容类型
|
|
*/
|
|
public enum SearchType {
|
|
/**
|
|
* 全部内容(插画、漫画、动图)
|
|
*/
|
|
ALL,
|
|
/**
|
|
* 插画和动图(不包括漫画)
|
|
*/
|
|
ILLUST_AND_UGOIRA,
|
|
/**
|
|
* 插图
|
|
*/
|
|
ILLUST,
|
|
/**
|
|
* 漫画
|
|
*/
|
|
MANGA,
|
|
/**
|
|
* 动图
|
|
*/
|
|
UGOIRA
|
|
}
|
|
|
|
public enum SearchOrder {
|
|
/**
|
|
* 按旧排序
|
|
*/
|
|
DATE,
|
|
/**
|
|
* 按新排序
|
|
*/
|
|
DATE_D
|
|
}
|
|
|
|
/**
|
|
* 搜索内容选项
|
|
*/
|
|
public enum SearchContentOption {
|
|
/**
|
|
* 所有内容
|
|
*/
|
|
ALL,
|
|
/**
|
|
* 全年龄
|
|
*/
|
|
SAFE,
|
|
/**
|
|
* R18
|
|
*/
|
|
R18
|
|
}
|
|
|
|
public enum RatioOption {
|
|
/**
|
|
* 横向
|
|
*/
|
|
TRANSVERSE(0.5F),
|
|
/**
|
|
* 纵向
|
|
*/
|
|
PORTRAIT(-0.5F),
|
|
/**
|
|
* 正方形
|
|
*/
|
|
SQUARE(0F)
|
|
;
|
|
|
|
public final float value;
|
|
|
|
RatioOption(float ratio) {
|
|
this.value = ratio;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|