This commit is contained in:
GH Action - Upstream Sync 2023-11-20 12:32:47 +00:00
commit ac199497b3
20 changed files with 145 additions and 202 deletions

View File

@ -17,6 +17,7 @@ import com.github.catvod.BuildConfig;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Sub;
import com.github.catvod.bean.Vod;
import com.github.catvod.bean.ali.Cache;
import com.github.catvod.bean.ali.Code;
import com.github.catvod.bean.ali.Data;
import com.github.catvod.bean.ali.Download;
@ -60,9 +61,7 @@ public class AliYun {
private AlertDialog dialog;
private String refreshToken;
private Share share;
private OAuth oauth;
private Drive drive;
private User user;
private Cache cache;
private static class Loader {
static volatile AliYun INSTANCE = new AliYun();
@ -72,23 +71,14 @@ public class AliYun {
return Loader.INSTANCE;
}
public File getUserCache() {
return Path.cache("aliyundrive_user");
}
public File getOAuthCache() {
return Path.cache("aliyundrive_oauth");
}
public File getDriveCache() {
return Path.cache("aliyundrive_drive");
public File getCache() {
return Path.tv("aliyun");
}
private AliYun() {
Init.checkPermission();
tempIds = new ArrayList<>();
user = User.objectFrom(Path.read(getUserCache()));
oauth = OAuth.objectFrom(Path.read(getOAuthCache()));
drive = Drive.objectFrom(Path.read(getDriveCache()));
cache = Cache.objectFrom(Path.read(getCache()));
}
public void setRefreshToken(String token) {
@ -99,7 +89,7 @@ public class AliYun {
Object[] result = new Object[3];
result[0] = 200;
result[1] = "text/plain";
result[2] = new ByteArrayInputStream(user.getRefreshToken().getBytes());
result[2] = new ByteArrayInputStream(cache.getUser().getRefreshToken().getBytes());
return result;
}
@ -114,13 +104,13 @@ public class AliYun {
HashMap<String, String> headers = getHeader();
headers.put("x-share-token", share.getShareToken());
headers.put("X-Canary", "client=Android,app=adrive,version=v4.3.1");
if (user.isAuthed()) headers.put("authorization", user.getAuthorization());
if (cache.getUser().isAuthed()) headers.put("authorization", cache.getUser().getAuthorization());
return headers;
}
private HashMap<String, String> getHeaderOpen() {
HashMap<String, String> headers = getHeader();
headers.put("authorization", oauth.getAuthorization());
headers.put("authorization", cache.getOAuth().getAuthorization());
return headers;
}
@ -129,7 +119,7 @@ public class AliYun {
OkResult result = OkHttp.post(api, param.toString(), getHeader());
SpiderDebug.log(result.getCode() + "," + api + "," + result.getBody());
if (isManyRequest(result.getBody())) return false;
oauth = OAuth.objectFrom(result.getBody()).save();
cache.setOAuth(OAuth.objectFrom(result.getBody()));
return true;
}
@ -160,7 +150,7 @@ public class AliYun {
private boolean isManyRequest(String result) {
if (!result.contains("Too Many Requests")) return false;
Utils.notify("洗洗睡吧Too Many Requests。");
oauth.clean().save();
cache.getOAuth().clean();
return true;
}
@ -184,31 +174,31 @@ public class AliYun {
try {
SpiderDebug.log("refreshAccessToken...");
JsonObject param = new JsonObject();
String token = user.getRefreshToken();
String token = cache.getUser().getRefreshToken();
if (token.isEmpty()) token = refreshToken;
if (token != null && token.startsWith("http")) token = OkHttp.string(token).trim();
param.addProperty("refresh_token", token);
param.addProperty("grant_type", "refresh_token");
String json = post("https://auth.aliyundrive.com/v2/account/token", param);
user = User.objectFrom(json).save();
if (user.getAccessToken().isEmpty()) throw new Exception(json);
cache.setUser(User.objectFrom(json));
if (cache.getUser().getAccessToken().isEmpty()) throw new Exception(json);
return true;
} catch (Exception e) {
if (e instanceof TimeoutException) return onTimeout();
cache.getUser().clean();
e.printStackTrace();
user.clean().save();
stopService();
startFlow();
return true;
} finally {
while (user.getAccessToken().isEmpty()) SystemClock.sleep(250);
while (cache.getUser().getAccessToken().isEmpty()) SystemClock.sleep(250);
}
}
private void getDriveId() {
SpiderDebug.log("Get Drive Id...");
String json = auth("https://user.aliyundrive.com/v2/user/get", "{}", true);
drive = Drive.objectFrom(json).save();
cache.setDrive(Drive.objectFrom(json));
}
private boolean oauthRequest() {
@ -230,11 +220,11 @@ public class AliYun {
}
private boolean refreshOpenToken() {
if (oauth.getRefreshToken().isEmpty()) return oauthRequest();
if (cache.getOAuth().getRefreshToken().isEmpty()) return oauthRequest();
SpiderDebug.log("refreshOpenToken...");
JsonObject param = new JsonObject();
param.addProperty("grant_type", "refresh_token");
param.addProperty("refresh_token", oauth.getRefreshToken());
param.addProperty("refresh_token", cache.getOAuth().getRefreshToken());
return alist("token", param);
}
@ -247,7 +237,7 @@ public class AliYun {
List<Item> subs = new ArrayList<>();
listFiles(shareId, new Item(getParentFileId(fileId, share)), files, subs);
Collections.sort(files);
List<String> playFrom = Arrays.asList("原畫", "普畫");
List<String> playFrom = Arrays.asList("原畫", "普畫", "極速");
List<String> episode = new ArrayList<>();
List<String> playUrl = new ArrayList<>();
for (Item file : files) episode.add(file.getDisplayName() + "$" + shareId + "+" + file.getFileId() + findSubs(file.getName(), subs));
@ -337,7 +327,7 @@ public class AliYun {
tempIds.add(0, copy(shareId, fileId));
JsonObject param = new JsonObject();
param.addProperty("file_id", tempIds.get(0));
param.addProperty("drive_id", drive.getDriveId());
param.addProperty("drive_id", cache.getDrive().getDriveId());
String json = oauth("openFile/getDownloadUrl", param.toString(), true);
return Download.objectFrom(json).getUrl();
} catch (Exception e) {
@ -355,7 +345,7 @@ public class AliYun {
tempIds.add(0, copy(shareId, fileId));
JsonObject param = new JsonObject();
param.addProperty("file_id", tempIds.get(0));
param.addProperty("drive_id", drive.getDriveId());
param.addProperty("drive_id", cache.getDrive().getDriveId());
param.addProperty("category", "live_transcoding");
param.addProperty("url_expire_sec", "14400");
String json = oauth("openFile/getVideoPreviewPlayInfo", param.toString(), true);
@ -368,9 +358,16 @@ public class AliYun {
}
}
public String playerContent(String[] ids, boolean original) {
if (original) return Result.get().url(getMultiThreadedDownloadUrl(ids[0], ids[1])).octet().subs(getSubs(ids)).header(getHeader()).string();
else return getPreviewContent(ids);
public String playerContent(String[] ids, String flag) {
if (flag.split("#")[0].equals("普畫")) {
return getPreviewContent(ids);
} else if (flag.split("#")[0].equals("原畫")) {
return Result.get().url(getDownloadUrl(ids[0], ids[1])).octet().subs(getSubs(ids)).header(getHeader()).string();
} else if (flag.split("#")[0].equals("極速")) {
return Result.get().url(MultiThread.url(getDownloadUrl(ids[0], ids[1]), 4)).octet().subs(getSubs(ids)).header(getHeader()).string();
} else {
return "";
}
}
private String getPreviewContent(String[] ids) {
@ -398,10 +395,10 @@ public class AliYun {
}
private String copy(String shareId, String fileId) {
if (drive.getDriveId().isEmpty()) getDriveId();
if (cache.getDrive().getDriveId().isEmpty()) getDriveId();
SpiderDebug.log("Copy..." + fileId);
String json = "{\"requests\":[{\"body\":{\"file_id\":\"%s\",\"share_id\":\"%s\",\"auto_rename\":true,\"to_parent_file_id\":\"root\",\"to_drive_id\":\"%s\"},\"headers\":{\"Content-Type\":\"application/json\"},\"id\":\"0\",\"method\":\"POST\",\"url\":\"/file/copy\"}],\"resource\":\"file\"}";
json = String.format(json, fileId, shareId, drive.getDriveId());
json = String.format(json, fileId, shareId, cache.getDrive().getDriveId());
Resp resp = Resp.objectFrom(auth("adrive/v2/batch", json, true));
return resp.getResponse().getBody().getFileId();
}
@ -417,17 +414,11 @@ public class AliYun {
private boolean delete(String fileId) {
SpiderDebug.log("Delete..." + fileId);
String json = "{\"requests\":[{\"body\":{\"drive_id\":\"%s\",\"file_id\":\"%s\"},\"headers\":{\"Content-Type\":\"application/json\"},\"id\":\"%s\",\"method\":\"POST\",\"url\":\"/file/delete\"}],\"resource\":\"file\"}";
json = String.format(json, drive.getDriveId(), fileId, fileId);
json = String.format(json, cache.getDrive().getDriveId(), fileId, fileId);
Resp resp = Resp.objectFrom(auth("adrive/v2/batch", json, true));
return resp.getResponse().getStatus() == 404;
}
public String getMultiThreadedDownloadUrl(String shareId, String fileId) {
String url = getDownloadUrl(shareId, fileId);
url = MultiThread.proxyUrl(url, 20);
return url;
}
public Object[] proxySub(Map<String, String> params) throws Exception {
String fileId = params.get("fileId");
String shareId = params.get("shareId");
@ -515,9 +506,9 @@ public class AliYun {
}
private void setToken(String value) {
cache.getUser().setRefreshToken(value);
SpiderDebug.log("Token:" + value);
Utils.notify("Token:" + value);
user.setRefreshToken(value);
refreshAccessToken();
stopService();
}

View File

@ -0,0 +1,58 @@
package com.github.catvod.bean.ali;
import com.github.catvod.api.AliYun;
import com.github.catvod.spider.Init;
import com.github.catvod.utils.Path;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class Cache {
@SerializedName("user")
private User user;
@SerializedName("oauth")
private OAuth oauth;
@SerializedName("drive")
private Drive drive;
public static Cache objectFrom(String str) {
Cache item = new Gson().fromJson(str, Cache.class);
return item == null ? new Cache() : item;
}
public User getUser() {
return user == null ? new User() : user;
}
public void setUser(User user) {
this.user = user;
this.save();
}
public OAuth getOAuth() {
return oauth == null ? new OAuth() : oauth;
}
public void setOAuth(OAuth oauth) {
this.oauth = oauth;
this.save();
}
public Drive getDrive() {
return drive == null ? new Drive() : drive;
}
public void setDrive(Drive drive) {
this.drive = drive;
this.save();
}
public void save() {
Init.execute(() -> Path.write(AliYun.get().getCache(), toString()));
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}

View File

@ -2,9 +2,6 @@ package com.github.catvod.bean.ali;
import android.text.TextUtils;
import com.github.catvod.api.AliYun;
import com.github.catvod.utils.FileUtil;
import com.github.catvod.utils.Path;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
@ -31,20 +28,4 @@ public class Drive {
public String getDriveId() {
return getResourceDriveId().isEmpty() ? getDefaultDriveId() : getResourceDriveId();
}
public Drive clean() {
this.defaultDriveId = "";
this.resourceDriveId = "";
return this;
}
public Drive save() {
Path.write(AliYun.get().getDriveCache(), toString());
return this;
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}

View File

@ -2,9 +2,6 @@ package com.github.catvod.bean.ali;
import android.text.TextUtils;
import com.github.catvod.api.AliYun;
import com.github.catvod.utils.FileUtil;
import com.github.catvod.utils.Path;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
@ -38,19 +35,8 @@ public class OAuth {
return getTokenType() + " " + getAccessToken();
}
public OAuth clean() {
public void clean() {
this.refreshToken = "";
this.accessToken = "";
return this;
}
public OAuth save() {
Path.write(AliYun.get().getOAuthCache(), toString());
return this;
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}

View File

@ -2,18 +2,11 @@ package com.github.catvod.bean.ali;
import android.text.TextUtils;
import com.github.catvod.api.AliYun;
import com.github.catvod.utils.FileUtil;
import com.github.catvod.utils.Path;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class User {
@SerializedName("default_drive_id")
private String driveId;
@SerializedName("user_id")
private String userId;
@SerializedName("token_type")
private String tokenType;
@SerializedName("access_token")
@ -26,14 +19,6 @@ public class User {
return item == null ? new User() : item;
}
public String getDriveId() {
return TextUtils.isEmpty(driveId) ? "" : driveId;
}
public String getUserId() {
return TextUtils.isEmpty(userId) ? "" : userId;
}
public String getTokenType() {
return TextUtils.isEmpty(tokenType) ? "" : tokenType;
}
@ -58,19 +43,8 @@ public class User {
return getTokenType().length() > 0 && getAccessToken().length() > 0;
}
public User clean() {
public void clean() {
this.refreshToken = "";
this.accessToken = "";
return this;
}
public User save() {
Path.write(AliYun.get().getUserCache(), toString());
return this;
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}

View File

@ -56,7 +56,7 @@ class OkRequest {
}
private RequestBody getRequestBody() {
if (!TextUtils.isEmpty(json)) return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
if (!TextUtils.isEmpty(json)) return RequestBody.create(MediaType.get("application/json; charset=utf-8"), json);
FormBody.Builder formBody = new FormBody.Builder();
if (params != null) for (String key : params.keySet()) formBody.add(key, params.get(key));
return formBody.build();

View File

@ -37,7 +37,7 @@ public class Ali extends Spider {
@Override
public String playerContent(String flag, String id, List<String> vipFlags) {
return AliYun.get().playerContent(id.split("\\+"), flag.split("#")[0].equals("原畫"));
return AliYun.get().playerContent(id.split("\\+"), flag);
}
private Vod parseVod(Matcher matcher, String id) {
@ -54,10 +54,11 @@ public class Ali extends Spider {
*/
public String detailContentVodPlayFrom(List<String> ids) {
List<String> playFrom = new ArrayList<>();
if (ids.size() < 2) return TextUtils.join("$$$", Arrays.asList("原畫", "普畫"));
if (ids.size() < 2) return TextUtils.join("$$$", Arrays.asList("原畫", "普畫", "極速"));
for (int i = 1; i <= ids.size(); i++) {
playFrom.add(String.format(Locale.getDefault(), "原畫#%02d", i));
playFrom.add(String.format(Locale.getDefault(), "普畫#%02d", i));
playFrom.add(String.format(Locale.getDefault(), "極速#%02d", i));
}
return TextUtils.join("$$$", playFrom);
}

View File

@ -66,7 +66,7 @@ public class Bili extends Spider {
private void setCookie() {
cookie = extend.get("cookie").getAsString();
if (cookie.startsWith("http")) cookie = OkHttp.string(cookie).trim();
if (TextUtils.isEmpty(cookie)) cookie = Path.read(getUserCache());
if (TextUtils.isEmpty(cookie)) cookie = Path.read(getCache());
if (TextUtils.isEmpty(cookie)) cookie = COOKIE;
}
@ -77,8 +77,8 @@ public class Bili extends Spider {
return items;
}
private File getUserCache() {
return Path.cache("bilibili_user");
private File getCache() {
return Path.tv("bilibili");
}
@Override

View File

@ -1,8 +1,10 @@
package com.github.catvod.spider;
import android.Manifest;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@ -53,6 +55,16 @@ public class Init {
get().handler.postDelayed(runnable, delay);
}
public static void checkPermission() {
try {
Activity activity = Init.getActivity();
if (activity == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 9999);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Activity getActivity() throws Exception {
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);

View File

@ -1,11 +1,9 @@
package com.github.catvod.spider;
import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import com.github.catvod.bean.Class;
import com.github.catvod.bean.Result;
@ -46,7 +44,7 @@ public class Market extends Spider {
public void init(Context context, String extend) throws Exception {
if (extend.startsWith("http")) extend = OkHttp.string(extend);
datas = Data.arrayFrom(extend);
checkPermission();
Init.checkPermission();
}
@Override
@ -72,15 +70,6 @@ public class Market extends Spider {
return Result.string(vod);
}
private void checkPermission() {
try {
Activity activity = Init.getActivity();
if (activity != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 9999);
} catch (Exception e) {
e.printStackTrace();
}
}
private void finish() {
try {
Activity activity = Init.getActivity();

View File

@ -15,10 +15,6 @@ import java.util.zip.ZipFile;
public class FileUtil {
public static File getWall(int index) {
return Path.files("wallpaper_" + index);
}
public static void openFile(File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

View File

@ -1,6 +1,5 @@
package com.github.catvod.utils;
import com.github.catvod.downloader.MultiThreadedMemoryDownloader;
import com.github.catvod.spider.Proxy;
import java.net.URLEncoder;
@ -11,27 +10,20 @@ import fi.iki.elonen.NanoHTTPD;
public class MultiThread {
public static String proxyUrl(String url, int thread) {
public static String url(String url, int thread) {
return String.format(Proxy.getUrl() + "?do=multi&url=%s&thread=%d", URLEncoder.encode(url), thread);
}
public static Object[] proxy(Map<String, String> params) throws Exception {
String url = params.get("url");
int threadNum = Integer.parseInt(params.get("thread"));
int thread = Integer.parseInt(params.get("thread"));
Map<String, String> reqHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (Map.Entry<String, String> entry : params.entrySet()) {
if (entry.getKey() != null) {
reqHeaders.put(entry.getKey(), entry.getValue());
}
}
for (String key : params.keySet()) reqHeaders.put(key, params.get(key));
if (reqHeaders.containsKey("do")) reqHeaders.remove("do");
if (reqHeaders.containsKey("url")) reqHeaders.remove("url");
if (reqHeaders.containsKey("thread")) reqHeaders.remove("thread");
MultiThreadedMemoryDownloader downloader = new MultiThreadedMemoryDownloader(url, reqHeaders, threadNum);
MultiThreadedDownloader downloader = new MultiThreadedDownloader(url, reqHeaders, thread);
NanoHTTPD.Response response = downloader.start();
Object[] result = new Object[1];
result[0] = response;
return result;
return new Object[]{response};
}
}

View File

@ -1,4 +1,4 @@
package com.github.catvod.downloader;
package com.github.catvod.utils;
import static java.lang.Thread.sleep;
import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
@ -21,7 +21,8 @@ import fi.iki.elonen.NanoHTTPD;
import okhttp3.Response;
// 多线程内存下载器
public class MultiThreadedMemoryDownloader {
public class MultiThreadedDownloader {
private String url; // 资源URL
private Map<String, String> headers; // HTTP Headers. 主要关注`Range-Bytes`这个字段.
private int chunkSize = 1024 * 128; // 每个线程每轮下载的字节数.
@ -36,7 +37,7 @@ public class MultiThreadedMemoryDownloader {
private BlockingQueue<Chunk> readyChunkQueue = new LinkedBlockingQueue<>(); // 已开始下载的chunk队列有序.
private Lock lock = new ReentrantLock(); // .
public MultiThreadedMemoryDownloader(String url, Map<String, String> headers, int numThreads) {
public MultiThreadedDownloader(String url, Map<String, String> headers, int numThreads) {
this.url = url;
this.headers = headers;
this.numThreads = numThreads;
@ -115,7 +116,7 @@ public class MultiThreadedMemoryDownloader {
if (hContentLength == null) {
throw new Exception("missing response header: Content-Length");
}
Long contentLength = Long.parseLong(hContentLength);
long contentLength = Long.parseLong(hContentLength);
// 尝试从Content-Range获取下载结束的偏移量
if (this.endOffset <= 0) {
@ -142,9 +143,7 @@ public class MultiThreadedMemoryDownloader {
// 开启多线程下载
this.running = true;
for (int i = 0; i < this.numThreads; ++i) {
new Thread(() -> {
MultiThreadedMemoryDownloader.this.worker();
}).start();
new Thread(MultiThreadedDownloader.this::worker).start();
}
// 构造response
@ -153,7 +152,7 @@ public class MultiThreadedMemoryDownloader {
NanoHTTPD.Response mResponse = newFixedLengthResponse(status, contentType, input, contentLength);
for (String key : response.headers().names()) {
String value = response.headers().get(key);
if (key != null && !key.equalsIgnoreCase("Content-Type") && !key.equalsIgnoreCase("Content-Length")) {
if (!key.equalsIgnoreCase("Content-Type") && !key.equalsIgnoreCase("Content-Length")) {
mResponse.addHeader(key, value);
}
}
@ -296,11 +295,8 @@ public class MultiThreadedMemoryDownloader {
}
}
private boolean shouldFilterRequestHeaderKey(String key) {
if (key == null) {
return true;
}
if (key == null) return true;
key = key.toLowerCase();
return key.equals("host") || key.equals("http-client-ip") || key.equals("remote-addr");
}
@ -309,9 +305,10 @@ public class MultiThreadedMemoryDownloader {
this.running = false;
}
private class Chunk {
private long startOffset;
private long endOffset;
private static class Chunk {
private final long startOffset;
private final long endOffset;
private byte[] buffer;
public Chunk(long startOffset, long endOffset) {

View File

@ -3,8 +3,6 @@ package com.github.catvod.utils;
import android.os.Environment;
import android.util.Log;
import com.github.catvod.spider.Init;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@ -24,52 +22,21 @@ public class Path {
return file;
}
public static boolean exists(String path) {
return new File(path.replace("file://", "")).exists();
public static File download() {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
}
public static File root() {
return Environment.getExternalStorageDirectory();
}
public static File cache() {
return Init.context().getCacheDir();
public static File tv() {
return check(new File(root() + File.separator + "TV"));
}
public static File files() {
return Init.context().getFilesDir();
}
public static File download() {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
}
public static String rootPath() {
return root().getAbsolutePath();
}
public static File root(String name) {
return new File(root(), name);
}
public static File root(String child, String name) {
return new File(check(new File(root(), child)), name);
}
public static File cache(String name) {
return new File(cache(), name);
}
public static File files(String name) {
return new File(files(), name);
}
public static String asset(String fileName) {
try {
return read(Init.context().getAssets().open(fileName));
} catch (Exception e) {
return "";
}
public static File tv(String name) {
if (!name.startsWith(".")) name = "." + name;
return new File(tv(), name);
}
public static String read(File file) {

Binary file not shown.

View File

@ -1 +1 @@
a71b8fa729618f6a1f11fb1b96b5278f
41ef471afad9198e7273a12f9912578a

View File

@ -1,5 +1,5 @@
{
"spider": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;a71b8fa729618f6a1f11fb1b96b5278f",
"spider": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;41ef471afad9198e7273a12f9912578a",
"wallpaper": "https://gao.chuqiuyu.tk",
"sites": [
{

View File

@ -1,5 +1,5 @@
{
"spider": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;a71b8fa729618f6a1f11fb1b96b5278f",
"spider": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;41ef471afad9198e7273a12f9912578a",
"wallpaper": "http://饭太硬.top/深色壁纸/api.php",
"sites": [
{

View File

@ -276,10 +276,9 @@
},
{
"name": "香雅情",
"url": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/zip/XYQTVBox_本地包.zip",
"url": "https://gh-proxy.com/https://raw.githubusercontent.com/xyq254245/xyqtvbox/main/XYQTVBox_本地包.zip",
"icon": "https://i.imgs.ovh/2023/10/20/2IO0D.jpeg",
"copy": "file://Download/XYQTVBox/XYQTVBox.json",
"version": "11/16"
"copy": "file://Download/XYQTVBox/XYQTVBox.json"
}
]
}

Binary file not shown.