pull/69/head
FongMi 2 years ago
parent 2eae93858a
commit e5ad6b7537
  1. 87
      app/src/main/java/com/github/catvod/api/AliYun.java
  2. 1
      app/src/main/java/com/github/catvod/spider/Ali.java
  3. 39
      app/src/main/java/com/github/catvod/utils/MultiThreadedDownloader.java
  4. 47
      app/src/main/java/com/github/catvod/utils/ProxyVideo.java
  5. 32
      app/src/main/java/com/github/catvod/utils/Utils.java

@ -34,7 +34,6 @@ import com.github.catvod.net.OkHttp;
import com.github.catvod.net.OkResult; import com.github.catvod.net.OkResult;
import com.github.catvod.spider.Init; import com.github.catvod.spider.Init;
import com.github.catvod.spider.Proxy; import com.github.catvod.spider.Proxy;
import com.github.catvod.utils.MultiThread;
import com.github.catvod.utils.MultiThreadedDownloader; import com.github.catvod.utils.MultiThreadedDownloader;
import com.github.catvod.utils.Path; import com.github.catvod.utils.Path;
import com.github.catvod.utils.ProxyVideo; import com.github.catvod.utils.ProxyVideo;
@ -58,21 +57,21 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import fi.iki.elonen.NanoHTTPD;
import okhttp3.Response; import okhttp3.Response;
public class AliYun { public class AliYun {
private ScheduledExecutorService service; private final Map<String, Map<String, String>> m3u8MediaMap;
private final Map<String, String> shareDownloadMap;
private final Map<String, String> downloadMap;
private final List<String> tempIds; private final List<String> tempIds;
private final ReentrantLock lock;
private final Cache cache;
private ScheduledExecutorService service;
private AlertDialog dialog; private AlertDialog dialog;
private String refreshToken; private String refreshToken;
private Share share; private Share share;
private Cache cache;
private Map<String, String> downloadMap;
private Map<String, String> shareDownloadMap;
private Map<String, Map<String, String>> m3u8MediaMap;
private final ReentrantLock rLock;
private static class Loader { private static class Loader {
static volatile AliYun INSTANCE = new AliYun(); static volatile AliYun INSTANCE = new AliYun();
@ -88,26 +87,18 @@ public class AliYun {
private AliYun() { private AliYun() {
Init.checkPermission(); Init.checkPermission();
lock = new ReentrantLock();
tempIds = new ArrayList<>(); tempIds = new ArrayList<>();
cache = Cache.objectFrom(Path.read(getCache()));
downloadMap = new HashMap<>(); downloadMap = new HashMap<>();
shareDownloadMap = new HashMap<>();
m3u8MediaMap = new HashMap<>(); m3u8MediaMap = new HashMap<>();
rLock = new ReentrantLock(); shareDownloadMap = new HashMap<>();
cache = Cache.objectFrom(Path.read(getCache()));
} }
public void setRefreshToken(String token) { public void setRefreshToken(String token) {
this.refreshToken = token; this.refreshToken = token;
} }
public Object[] getToken() {
Object[] result = new Object[3];
result[0] = 200;
result[1] = "text/plain";
result[2] = new ByteArrayInputStream(cache.getUser().getRefreshToken().getBytes());
return result;
}
public HashMap<String, String> getHeader() { public HashMap<String, String> getHeader() {
HashMap<String, String> headers = new HashMap<>(); HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Utils.CHROME); headers.put("User-Agent", Utils.CHROME);
@ -477,8 +468,7 @@ public class AliYun {
private static boolean isExpire(String url) { private static boolean isExpire(String url) {
String expires = new UrlQuerySanitizer(url).getValue("x-oss-expires"); String expires = new UrlQuerySanitizer(url).getValue("x-oss-expires");
if (TextUtils.isEmpty(expires)) return false; if (TextUtils.isEmpty(expires)) return false;
if (new Long(expires) - getTimeStamp() <= 60) return true; return Long.parseLong(expires) - getTimeStamp() <= 60;
return false;
} }
private static long getTimeStamp() { private static long getTimeStamp() {
@ -486,56 +476,52 @@ public class AliYun {
} }
public Object[] proxyVideo(Map<String, String> params) throws Exception { public Object[] proxyVideo(Map<String, String> params) throws Exception {
String fileId = params.get("fileId");
String shareId = params.get("shareId");
String cate = params.get("cate");
String templateId = params.get("templateId"); String templateId = params.get("templateId");
String shareId = params.get("shareId");
String mediaId = params.get("mediaId"); String mediaId = params.get("mediaId");
String fileId = params.get("fileId");
String cate = params.get("cate");
String downloadUrl = ""; String downloadUrl = "";
int thread = 1; int thread = 1;
switch (cate) {
case "preview": if ("preview".equals(cate)) {
return previewProxy(shareId, fileId, templateId); return previewProxy(shareId, fileId, templateId);
case "m3u8": }
rLock.lock();
if ("open".equals(cate)) {
downloadUrl = getDownloadUrl(shareId, fileId);
thread = 30;
} else if ("share".equals(cate)) {
downloadUrl = getShareDownloadUrl(shareId, fileId);
thread = 30;
} else if ("m3u8".equals(cate)) {
lock.lock();
String mediaUrl = m3u8MediaMap.get(fileId).get(mediaId); String mediaUrl = m3u8MediaMap.get(fileId).get(mediaId);
if (isExpire(mediaUrl)) { if (isExpire(mediaUrl)) {
getM3u8(shareId, fileId, templateId); getM3u8(shareId, fileId, templateId);
mediaUrl = m3u8MediaMap.get(fileId).get(mediaId); mediaUrl = m3u8MediaMap.get(fileId).get(mediaId);
} }
rLock.unlock(); lock.unlock();
downloadUrl = mediaUrl; downloadUrl = mediaUrl;
break;
case "open":
downloadUrl = getDownloadUrl(shareId, fileId);
thread = 30;
break;
case "share":
downloadUrl = getShareDownloadUrl(shareId, fileId);
thread = 30;
break;
default:
break;
} }
Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (String key : params.keySet()) headers.put(key, params.get(key)); for (String key : params.keySet()) headers.put(key, params.get(key));
headers.remove("do"); headers.remove("do");
headers.remove("host");
headers.remove("type"); headers.remove("type");
headers.remove("cate"); headers.remove("cate");
headers.remove("fileId"); headers.remove("fileId");
headers.remove("shareId"); headers.remove("shareId");
headers.remove("templateId");
headers.remove("mediaId"); headers.remove("mediaId");
headers.remove("host"); headers.remove("templateId");
headers.remove("remote-addr"); headers.remove("remote-addr");
headers.remove("http-client-ip"); headers.remove("http-client-ip");
NanoHTTPD.Response mResponse;
if (thread == 1) { if (thread == 1) {
mResponse = ProxyVideo.proxy(downloadUrl, headers); return new Object[]{ProxyVideo.proxy(downloadUrl, headers)};
} else { } else {
mResponse = new MultiThreadedDownloader(downloadUrl, headers, thread).start(); return new Object[]{new MultiThreadedDownloader(downloadUrl, headers, thread).start()};
} }
return new Object[]{mResponse};
} }
private Object[] previewProxy(String shareId, String fileId, String templateId) { private Object[] previewProxy(String shareId, String fileId, String templateId) {
@ -550,8 +536,7 @@ public class AliYun {
for (int i = 0; i < url.size(); i = i + 2) { for (int i = 0; i < url.size(); i = i + 2) {
previewMap.put(url.get(i), url.get(i + 1)); previewMap.put(url.get(i), url.get(i + 1));
} }
String m3u8Url = previewMap.get(templateId); return previewMap.get(templateId);
return m3u8Url;
} }
private String getM3u8(String shareId, String fileId, String templateId) { private String getM3u8(String shareId, String fileId, String templateId) {
@ -572,8 +557,7 @@ public class AliYun {
listM3u8.add(thisOne); listM3u8.add(thisOne);
} }
m3u8MediaMap.put(fileId, media); m3u8MediaMap.put(fileId, media);
String content = TextUtils.join("\n", listM3u8); return TextUtils.join("\n", listM3u8);
return content;
} }
public Object[] proxySub(Map<String, String> params) throws Exception { public Object[] proxySub(Map<String, String> params) throws Exception {
@ -613,8 +597,7 @@ public class AliYun {
dismiss(); dismiss();
Init.execute(() -> { Init.execute(() -> {
if (text.startsWith("http")) setToken(OkHttp.string(text)); if (text.startsWith("http")) setToken(OkHttp.string(text));
else if (text.length() == 32) setToken(text); else setToken(text);
else if (text.contains(":")) setToken(OkHttp.string("http://" + text + "/proxy?do=ali&type=token"));
}); });
} }

@ -82,7 +82,6 @@ public class Ali extends Spider {
String type = params.get("type"); String type = params.get("type");
if ("video".equals(type)) return AliYun.get().proxyVideo(params); if ("video".equals(type)) return AliYun.get().proxyVideo(params);
if ("sub".equals(type)) return AliYun.get().proxySub(params); if ("sub".equals(type)) return AliYun.get().proxySub(params);
if ("token".equals(type)) return AliYun.get().getToken();
return null; return null;
} }
} }

@ -94,43 +94,10 @@ public class MultiThreadedDownloader {
//获取header //获取header
String contentType = response.headers().get("Content-Type"); String contentType = response.headers().get("Content-Type");
String contentDisposition = response.headers().get("Content-Disposition"); String contentDisposition = response.headers().get("Content-Disposition");
if (contentDisposition != null) { if (contentDisposition != null) contentType = Utils.getMimeType(contentDisposition);
if (contentDisposition.endsWith(".mp4")) { if (contentType == null) throw new Exception("missing response header: Content-Type");
contentType = "video/mp4";
} else if (contentDisposition.endsWith(".webm")) {
contentType = "video/webm";
} else if (contentDisposition.endsWith(".avi")) {
contentType = "video/x-msvideo";
} else if (contentDisposition.endsWith(".wmv")) {
contentType = "video/x-ms-wmv";
} else if (contentDisposition.endsWith(".flv")) {
contentType = "video/x-flv";
} else if (contentDisposition.endsWith(".mov")) {
contentType = "video/quicktime";
} else if (contentDisposition.endsWith(".mkv")) {
contentType = "video/x-matroska";
} else if (contentDisposition.endsWith(".mpeg")) {
contentType = "video/mpeg";
} else if (contentDisposition.endsWith(".3gp")) {
contentType = "video/3gpp";
} else if (contentDisposition.endsWith(".ts")) {
contentType = "video/MP2T";
} else if (contentDisposition.endsWith(".mp3")) {
contentType = "audio/mp3";
} else if (contentDisposition.endsWith(".wav")) {
contentType = "audio/wav";
} else if (contentDisposition.endsWith(".aac")) {
contentType = "audio/aac";
}
}
if (contentType == null) {
throw new Exception("missing response header: Content-Type");
}
String hContentLength = response.headers().get("Content-Length"); String hContentLength = response.headers().get("Content-Length");
if (hContentLength == null) { if (hContentLength == null) throw new Exception("missing response header: Content-Length");
throw new Exception("missing response header: Content-Length");
}
long contentLength = Long.parseLong(hContentLength); long contentLength = Long.parseLong(hContentLength);
//尝试从Content-Range获取下载结束的偏移量 //尝试从Content-Range获取下载结束的偏移量

@ -1,8 +1,11 @@
package com.github.catvod.utils; package com.github.catvod.utils;
import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse; import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
import com.github.catvod.net.OkHttp; import com.github.catvod.net.OkHttp;
import java.util.Map; import java.util.Map;
import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD;
import okhttp3.Response; import okhttp3.Response;
@ -14,42 +17,12 @@ public class ProxyVideo {
headers.put("Range", "bytes=0-"); headers.put("Range", "bytes=0-");
status = NanoHTTPD.Response.Status.OK; status = NanoHTTPD.Response.Status.OK;
} }
Response dResponse = OkHttp.newCall(url, headers); Response response = OkHttp.newCall(url, headers);
String hContentLength = dResponse.headers().get("Content-Length"); String contentType = response.headers().get("Content-Type");
long contentLength = Long.parseLong(hContentLength); String hContentLength = response.headers().get("Content-Length");
String contentType = dResponse.headers().get("Content-Type"); String contentDisposition = response.headers().get("Content-Disposition");
String contentDisposition = dResponse.headers().get("Content-Disposition"); long contentLength = hContentLength != null ? Long.parseLong(hContentLength) : 0;
if (contentDisposition != null) { if (contentDisposition != null) contentType = Utils.getMimeType(contentDisposition);
if (contentDisposition.endsWith(".mp4")) { return newFixedLengthResponse(status, contentType, response.body().byteStream(), contentLength);
contentType = "video/mp4";
} else if (contentDisposition.endsWith(".webm")) {
contentType = "video/webm";
} else if (contentDisposition.endsWith(".avi")) {
contentType = "video/x-msvideo";
} else if (contentDisposition.endsWith(".wmv")) {
contentType = "video/x-ms-wmv";
} else if (contentDisposition.endsWith(".flv")) {
contentType = "video/x-flv";
} else if (contentDisposition.endsWith(".mov")) {
contentType = "video/quicktime";
} else if (contentDisposition.endsWith(".mkv")) {
contentType = "video/x-matroska";
} else if (contentDisposition.endsWith(".mpeg")) {
contentType = "video/mpeg";
} else if (contentDisposition.endsWith(".3gp")) {
contentType = "video/3gpp";
} else if (contentDisposition.endsWith(".ts")) {
contentType = "video/MP2T";
} else if (contentDisposition.endsWith(".mp3")) {
contentType = "audio/mp3";
} else if (contentDisposition.endsWith(".wav")) {
contentType = "audio/wav";
} else if (contentDisposition.endsWith(".aac")) {
contentType = "audio/aac";
}
} }
return newFixedLengthResponse(status, contentType, dResponse.body().byteStream(), contentLength);
}
} }

@ -216,4 +216,36 @@ public class Utils {
return ""; return "";
} }
} }
public static String getMimeType(String contentDisposition) {
if (contentDisposition.endsWith(".mp4")) {
return "video/mp4";
} else if (contentDisposition.endsWith(".webm")) {
return "video/webm";
} else if (contentDisposition.endsWith(".avi")) {
return "video/x-msvideo";
} else if (contentDisposition.endsWith(".wmv")) {
return "video/x-ms-wmv";
} else if (contentDisposition.endsWith(".flv")) {
return "video/x-flv";
} else if (contentDisposition.endsWith(".mov")) {
return "video/quicktime";
} else if (contentDisposition.endsWith(".mkv")) {
return "video/x-matroska";
} else if (contentDisposition.endsWith(".mpeg")) {
return "video/mpeg";
} else if (contentDisposition.endsWith(".3gp")) {
return "video/3gpp";
} else if (contentDisposition.endsWith(".ts")) {
return "video/MP2T";
} else if (contentDisposition.endsWith(".mp3")) {
return "audio/mp3";
} else if (contentDisposition.endsWith(".wav")) {
return "audio/wav";
} else if (contentDisposition.endsWith(".aac")) {
return "audio/aac";
} else {
return null;
}
}
} }

Loading…
Cancel
Save