AndroidCatVodSpider/app/src/main/java/com/github/catvod/spider/TgSearchQuark.java

258 lines
9.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.github.catvod.spider;
import android.content.Context;
import android.text.TextUtils;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.net.OkHttp;
import com.github.catvod.net.OkResult;
import com.github.catvod.utils.Json;
import com.github.catvod.utils.Util;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.util.*;
public class TgSearchQuark extends Cloud {
private static final String KEY_API_URLS = "api_urls";
private static final String KEY_DOMAIN_MAP = "siteurl";
private static final String KEY_SOURCES = "sources";
private static final int DEFAULT_PAGE_SIZE = 10;
private List<String> apiUrls = new ArrayList<>();
private Map<String, String> domainMap = new HashMap<String, String>() {{
put("alipan", "阿里");
put("aliyundrive", "阿里");
put("quark", "夸克");
put("115cdn", "115");
put("baidu.com", "百度");
put("uc", "UC");
put("189.cn", "天翼");
put("139.com", "移动");
put("123", "123盘");
}};
private Set<String> sources = new HashSet<>();
private String[] extInfos = null;
@Override
public synchronized void init(Context context, String extend) throws Exception {
super.init(context, extend);
this.apiUrls.clear();
if (!TextUtils.isEmpty(extend)) {
try {
if (extend.contains("###")) {
String[] infos = extend.split("###");
this.extInfos = infos;
if (infos.length > 0 && !TextUtils.isEmpty(infos[0])) {
processExtendConfig(infos[0]);
}
} else {
this.extInfos = new String[]{extend};
processExtendConfig(extend);
}
} catch (Exception e) {
}
}
this.extInfos = null; // 重置,避免内存泄漏
}
private void processExtendConfig(String config) {
try {
// 检查是否为HTTP URL
if (isValidUrl(config)) {
if (!this.apiUrls.contains(config)) {
this.apiUrls.add(config);
}
return;
}
// 尝试JSON格式解析
JsonObject ext = Json.safeObject(config);
// 处理API URLs配置
processApiUrls(ext);
// 处理域名映射配置
processDomainMap(ext);
// 处理来源过滤配置
processSources(ext, true);
} catch (Exception e) {
// 可以添加日志记录
}
}
private void processApiUrls(JsonObject config) {
if (config.has(KEY_API_URLS) && config.get(KEY_API_URLS).isJsonArray()) {
JsonArray urlsArray = config.getAsJsonArray(KEY_API_URLS);
for (JsonElement element : urlsArray) {
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
String url = element.getAsString();
if (isValidUrl(url) && !this.apiUrls.contains(url)) {
this.apiUrls.add(url);
}
}
}
}
}
private void processDomainMap(JsonObject config) {
if (config.has(KEY_DOMAIN_MAP) && config.get(KEY_DOMAIN_MAP).isJsonObject()) {
JsonObject customDomains = config.getAsJsonObject(KEY_DOMAIN_MAP);
for (Map.Entry<String, JsonElement> entry : customDomains.entrySet()) {
if (entry == null || entry.getValue() == null) continue;
String domain = entry.getKey();
String sourceName = "";
try {
sourceName = entry.getValue().getAsString();
} catch (Exception e) {
continue;
}
if (!TextUtils.isEmpty(domain) && !TextUtils.isEmpty(sourceName) && !domainMap.containsKey(domain)) {
domainMap.put(domain, sourceName);
}
}
}
}
private void processSources(JsonObject config, boolean clearExisting) {
if (config.has(KEY_SOURCES) && config.get(KEY_SOURCES).isJsonArray()) {
if (clearExisting) {
this.sources.clear();
}
JsonArray sourcesArray = config.getAsJsonArray(KEY_SOURCES);
for (JsonElement element : sourcesArray) {
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
String source = element.getAsString();
if (!TextUtils.isEmpty(source) && !sources.contains(source)) {
sources.add(source);
}
}
}
}
}
private boolean isValidUrl(String url) {
return !TextUtils.isEmpty(url) && (url.startsWith("http://") || url.startsWith("https://"));
}
private Map<String, String> getHeader() {
Map<String, String> header = new HashMap<>();
header.put("User-Agent", Util.CHROME);
return header;
}
@Override
public String searchContent(String key, boolean quick) throws Exception {
if (key == null || key.trim().isEmpty()) {
return Result.error("关键词不能为空");
}
return performSearch(key, 1, DEFAULT_PAGE_SIZE);
}
private String performSearch(String key, int page, int pageSize) throws Exception {
List<Vod> list = new ArrayList<>();
int total = 0;
Map<String, String> params = new HashMap<>();
params.put("kw", key);
params.put("page", String.valueOf(page));
params.put("size", String.valueOf(pageSize));
for (String apiUrl : apiUrls) {
if (!isValidUrl(apiUrl)) continue;
try {
OkResult result = OkHttp.get(apiUrl, params, getHeader());
if (result.getCode() == 500 || TextUtils.isEmpty(result.getBody())) continue;
JsonObject jsonObject = Json.safeObject(result.getBody());
if (!jsonObject.has("code") || jsonObject.get("code").getAsInt() != 0 || !jsonObject.has("data"))
continue;
JsonObject data = jsonObject.getAsJsonObject("data");
total = data.has("total") && !data.get("total").isJsonNull() ? data.get("total").getAsInt() : 0;
// 直接检查merged_by_type字段无需三重判断
if (!data.has("merged_by_type") || !data.get("merged_by_type").isJsonObject()) continue;
JsonObject mergedByType = data.getAsJsonObject("merged_by_type");
for (Map.Entry<String, JsonElement> categoryEntry : mergedByType.entrySet()) {
if (!categoryEntry.getValue().isJsonArray()) continue;
JsonArray items = categoryEntry.getValue().getAsJsonArray();
for (JsonElement item : items) {
if (!item.isJsonObject()) continue;
JsonObject entry = item.getAsJsonObject();
String vodUrl = entry.has("url") && !entry.get("url").isJsonNull() ? entry.get("url").getAsString() : "";
if (TextUtils.isEmpty(vodUrl)) continue;
// 获取来源信息并映射
String originalSource = entry.has("source") && !entry.get("source").isJsonNull() ? entry.get("source").getAsString() : "未知来源";
String sourceName = mapSource(vodUrl, originalSource);
// 获取标题
String title = entry.has("note") && !entry.get("note").isJsonNull() ? entry.get("note").getAsString() : "未命名资源";
// 获取图片
String pic = getFirstImage(entry);
// 简化VodPlayBuilder的使用
Vod vod = new Vod(vodUrl, title, pic, sourceName + " (" + originalSource + ")");
// 由于只有一个播放源,直接设置播放信息
vod.setVodPlayFrom(sourceName);
vod.setVodPlayUrl("播放源$" + vodUrl);
// 来源过滤
if (sources.isEmpty() || sources.contains(sourceName)) {
list.add(vod);
}
}
}
int pageCount = total > 0 && pageSize > 0 ? (total + pageSize - 1) / pageSize : 1;
return Result.string(page, pageCount, pageSize, total, list);
} catch (Exception e) {
// 出错时继续尝试下一个API
continue;
}
}
return Result.error("无法连接到任何搜索API");
}
// 提取来源映射逻辑为单独方法
private String mapSource(String vodUrl, String originalSource) {
for (Map.Entry<String, String> domainEntry : domainMap.entrySet()) {
if (vodUrl.contains(domainEntry.getKey())) {
return domainEntry.getValue();
}
}
return originalSource;
}
// 提取图片获取逻辑为单独方法
private String getFirstImage(JsonObject entry) {
if (entry.has("images") && !entry.get("images").isJsonNull() && entry.get("images").isJsonArray()) {
JsonArray images = entry.getAsJsonArray("images");
if (images.size() > 0 && !images.get(0).isJsonNull() && images.get(0).isJsonPrimitive()) {
return images.get(0).getAsString();
}
}
return "";
}
}