金牌影视java
This commit is contained in:
parent
83e200663c
commit
daf80eed19
|
|
@ -3,6 +3,9 @@ package com.github.catvod.bean;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Vod {
|
public class Vod {
|
||||||
|
|
||||||
@SerializedName("type_name")
|
@SerializedName("type_name")
|
||||||
|
|
@ -171,4 +174,46 @@ public class Vod {
|
||||||
this.ratio = ratio;
|
this.ratio = ratio;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static class VodPlayBuilder{
|
||||||
|
private List<String> vodPlayFrom = new ArrayList<String>();
|
||||||
|
private List<String> vodPlayUrl = new ArrayList<String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式: from name1$$$name2$$$name3
|
||||||
|
* url name$url#name2$url2$$$(分类2)$$分类3
|
||||||
|
* @param playFrom
|
||||||
|
* @param playUrl
|
||||||
|
*/
|
||||||
|
public VodPlayBuilder append(String playFrom, List<PlayUrl> playUrl){
|
||||||
|
vodPlayFrom.add(playFrom);
|
||||||
|
vodPlayUrl.add(toPlayUrlStr(playUrl));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildResult build(){
|
||||||
|
BuildResult buildResult = new BuildResult();
|
||||||
|
buildResult.vodPlayFrom = String.join("$$$", vodPlayFrom);
|
||||||
|
buildResult.vodPlayUrl = String.join("$$$", vodPlayUrl);
|
||||||
|
return buildResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toPlayUrlStr(List<PlayUrl> playUrl) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
for (PlayUrl url : playUrl) {
|
||||||
|
list.add(url.name.replace("m3u8", "") + '$' + url.url);
|
||||||
|
}
|
||||||
|
return String.join("#", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BuildResult{
|
||||||
|
public String vodPlayFrom;
|
||||||
|
public String vodPlayUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PlayUrl {
|
||||||
|
public String flag; // 线路标志
|
||||||
|
public String name;
|
||||||
|
public String url;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
package com.github.catvod.spider
|
||||||
|
|
||||||
|
|
||||||
|
import com.github.catvod.bean.Class
|
||||||
|
import com.github.catvod.bean.Result
|
||||||
|
import com.github.catvod.bean.Vod
|
||||||
|
|
||||||
|
import com.github.catvod.crawler.Spider
|
||||||
|
import com.github.catvod.crawler.SpiderDebug
|
||||||
|
import com.github.catvod.net.OkHttp
|
||||||
|
import com.github.catvod.utils.Json
|
||||||
|
import com.github.catvod.utils.Util
|
||||||
|
import com.google.gson.JsonArray
|
||||||
|
import org.apache.commons.lang3.time.DateFormatUtils
|
||||||
|
import org.apache.commons.lang3.time.DateUtils
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class Glod : Spider() {
|
||||||
|
private val host = Util.base64Decode("aHR0cHM6Ly93d3cuY2Zrajg2LmNvbS8=")
|
||||||
|
|
||||||
|
private val epUrl = "/api/mw-movie/anonymous/v1/video/episode/url?id=%s&nid=%s"
|
||||||
|
|
||||||
|
private val deviceId = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
private val classList = listOf(Class("1", "电影"), Class("2", "电视剧"), Class("4", "动漫"), Class("3", "综艺"))
|
||||||
|
|
||||||
|
override fun homeContent(filter: Boolean): String {
|
||||||
|
val string = OkHttp.string(host, Util.webHeaders("https://www.bing.com"))
|
||||||
|
val vodList = parseFromJson(string, "home")
|
||||||
|
// val vodList = parseVodList(string)
|
||||||
|
return Result.string(classList, vodList)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun detailContent(ids: MutableList<String>): String {
|
||||||
|
val url = host + ids[0]
|
||||||
|
val string = OkHttp.string(url, Util.webHeaders(host))
|
||||||
|
val parse = Jsoup.parse(string)
|
||||||
|
val name = parse.select("h1.title").text()
|
||||||
|
val img = parse.select("div[class^=detail__CardImg] img").attr("src")
|
||||||
|
val tag = parse.select("div.tags > a.tag").eachText().joinToString(" ")
|
||||||
|
val vod = Vod(ids[0], name, img, tag)
|
||||||
|
val director = parse.select("div.director")
|
||||||
|
val d = director[0].select("a").text()
|
||||||
|
val actor = director[1].select("a").eachText().joinToString(" ")
|
||||||
|
vod.setVodActor(actor)
|
||||||
|
vod.setVodDirector(d)
|
||||||
|
val desc = parse.select("div.intro div.wrapper_more_text").text()
|
||||||
|
vod.vodContent = desc
|
||||||
|
|
||||||
|
val linkList = parse.select("div.listitem > a")
|
||||||
|
|
||||||
|
val playUrlList = mutableListOf<Vod.VodPlayBuilder.PlayUrl>()
|
||||||
|
for (element in linkList) {
|
||||||
|
val u = element.attr("href")
|
||||||
|
val n = element.text()
|
||||||
|
playUrlList.add(Vod.VodPlayBuilder.PlayUrl().also {
|
||||||
|
it.name = n
|
||||||
|
it.url = u
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
val buildResult = Vod.VodPlayBuilder().append("glod", playUrlList).build()
|
||||||
|
|
||||||
|
val time = parse.select("div.item:contains(上映时间)").select(".item-top").text()
|
||||||
|
vod.setVodYear(DateFormatUtils.format(DateUtils.parseDate(time, "yyyy-MM-dd"), "yyyy"))
|
||||||
|
vod.setVodPlayFrom(buildResult.vodPlayFrom)
|
||||||
|
vod.vodPlayUrl = buildResult.vodPlayUrl
|
||||||
|
return Result.string(vod)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求头
|
||||||
|
* t 时间戳
|
||||||
|
* sign 签名
|
||||||
|
* deviceId
|
||||||
|
* authorization 空的
|
||||||
|
* 还有cookie
|
||||||
|
*/
|
||||||
|
override fun playerContent(flag: String, id: String, vipFlags: MutableList<String>): String {
|
||||||
|
val list = id.split("/")
|
||||||
|
val i = list[3]
|
||||||
|
val nid = list[5]
|
||||||
|
val webHeaders = Util.webHeaders(host)
|
||||||
|
val time = Date().time.toString()
|
||||||
|
val sign = Util.sha1Hex(
|
||||||
|
Util.MD5("id=${i}&nid=${nid}&key=cb808529bae6b6be45ecfab29a4889bc&t=${time}")
|
||||||
|
)
|
||||||
|
webHeaders["t"] = time
|
||||||
|
webHeaders["deviceId"] = deviceId
|
||||||
|
webHeaders["Sign"] = sign
|
||||||
|
|
||||||
|
val string = OkHttp.string(host + String.format(epUrl, i, nid), webHeaders)
|
||||||
|
val parse = Json.parse(string).asJsonObject
|
||||||
|
if (parse.get("code").asInt != 200) {
|
||||||
|
SpiderDebug.log("glod 获取播放链接失败:$string")
|
||||||
|
return Result.error("获取播放链接失败")
|
||||||
|
}
|
||||||
|
val url = parse.get("data").asJsonObject.get("playUrl").asString
|
||||||
|
return Result.get().url(url).string()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun categoryContent(tid: String, pg: String, filter: Boolean, extend: HashMap<String, String>): String {
|
||||||
|
val url = "$host/type/$tid"
|
||||||
|
val string = OkHttp.string(url, Util.webHeaders(host))
|
||||||
|
val vodList = parseFromJson(string, "cate")
|
||||||
|
return Result.string(classList, vodList)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchContent(key: String, quick: Boolean): String {
|
||||||
|
val string = OkHttp.string("${host}vod/search/$key", Util.webHeaders(host))
|
||||||
|
val vodList = parseFromJson(string, "search")
|
||||||
|
return Result.string(vodList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseFromJson(string: String, type: String): List<Vod> {
|
||||||
|
val vodList = mutableListOf<Vod>()
|
||||||
|
val parse = Jsoup.parse(string)
|
||||||
|
val select = parse.select("script")
|
||||||
|
val data = select.find {
|
||||||
|
it.html().contains("操作成功")
|
||||||
|
}
|
||||||
|
if (data == null) {
|
||||||
|
SpiderDebug.log("glod 找不到json")
|
||||||
|
return vodList
|
||||||
|
}
|
||||||
|
val json = data.html().replace("self.__next_f.push(", "").replace(")", "")
|
||||||
|
|
||||||
|
val gson = Json.parse(json).asJsonArray.get(1).asString.replace("6:", "")
|
||||||
|
val resp = Json.parse(gson).asJsonArray.get(3).asJsonObject
|
||||||
|
if (type == "home") {
|
||||||
|
val element = resp.get("children").asJsonArray.get(3).asJsonObject.get("data").asJsonObject.get("data")
|
||||||
|
var vList = element.asJsonObject.get("homeNewMoviePageData").asJsonObject.get("list").asJsonArray
|
||||||
|
getVodList(vList, vodList)
|
||||||
|
vList = element.asJsonObject.get("homeBroadcastPageData").asJsonObject.get("list").asJsonArray
|
||||||
|
getVodList(vList, vodList)
|
||||||
|
vList = element.asJsonObject.get("homeManagerPageData").asJsonObject.get("list").asJsonArray
|
||||||
|
getVodList(vList, vodList)
|
||||||
|
vList = element.asJsonObject.get("newestTvPageData").asJsonObject.get("list").asJsonArray
|
||||||
|
getVodList(vList, vodList)
|
||||||
|
vList = element.asJsonObject.get("newestCartoonPageData").asJsonObject.get("list").asJsonArray
|
||||||
|
getVodList(vList, vodList)
|
||||||
|
} else if (type == "cate") {
|
||||||
|
for (jsonElement in resp.get("children").asJsonArray.get(3).asJsonObject.get("data").asJsonArray) {
|
||||||
|
val objList = jsonElement.asJsonObject.get("vodList").asJsonObject.get("list").asJsonArray
|
||||||
|
getVodList(objList, vodList)
|
||||||
|
}
|
||||||
|
} else if (type == "search") {
|
||||||
|
val asJsonArray =
|
||||||
|
resp.get("data").asJsonObject.get("data").asJsonObject.get("result").asJsonObject.get("list").asJsonArray
|
||||||
|
getVodList(asJsonArray, vodList)
|
||||||
|
}
|
||||||
|
return vodList
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getVodList(
|
||||||
|
objList: JsonArray, vodList: MutableList<Vod>
|
||||||
|
) {
|
||||||
|
for (oj in objList) {
|
||||||
|
val obj = oj.asJsonObject
|
||||||
|
val v = Vod()
|
||||||
|
v.setVodId("/detail/" + obj.get("vodId").asString)
|
||||||
|
v.setVodName(obj.get("vodName").asString)
|
||||||
|
// v.setVodActor(obj.get("vodActor").asString)
|
||||||
|
v.setVodRemarks(obj.get("vodScore").asString)
|
||||||
|
v.setVodPic(obj.get("vodPic").asString)
|
||||||
|
vodList.add(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseVodList(string: String): MutableList<Vod> {
|
||||||
|
val parse = Jsoup.parse(string)
|
||||||
|
val list = parse.select("div.content-card")
|
||||||
|
val vodList = mutableListOf<Vod>()
|
||||||
|
for (element in list) {
|
||||||
|
val id = element.select("a").attr("href")
|
||||||
|
val title = element.select("div.info-title-box > div.title").text()
|
||||||
|
val score = element.select("div.bottom div[class^=score]").text()
|
||||||
|
val img = element.select("img").attr("srcset")
|
||||||
|
vodList.add(Vod(id, title, host + img, score))
|
||||||
|
}
|
||||||
|
return vodList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,12 +14,15 @@ import android.webkit.WebViewClient;
|
||||||
|
|
||||||
import com.github.catvod.spider.Init;
|
import com.github.catvod.spider.Init;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.mozilla.universalchardet.UniversalDetector;
|
import org.mozilla.universalchardet.UniversalDetector;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -338,6 +341,31 @@ public class Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static String sha1Hex(String input) throws NoSuchAlgorithmException {
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||||
|
byte[] messageDigest = md.digest(input.getBytes(Charset.defaultCharset()));
|
||||||
|
return bytesToHex(messageDigest);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bytesToHex(byte[] bytes) {
|
||||||
|
StringBuilder hexString = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
String hex = Integer.toHexString(0xff & b);
|
||||||
|
if (hex.length() == 1) {
|
||||||
|
hexString.append('0');
|
||||||
|
}
|
||||||
|
hexString.append(hex);
|
||||||
|
}
|
||||||
|
return hexString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class LCSResult {
|
public static class LCSResult {
|
||||||
public int length;
|
public int length;
|
||||||
public String sequence;
|
public String sequence;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
import android.app.Application;
|
||||||
|
import com.github.catvod.spider.ChangZhang;
|
||||||
|
import com.github.catvod.spider.Glod;
|
||||||
|
import com.github.catvod.spider.Init;
|
||||||
|
import com.github.catvod.utils.Json;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public class GoldTest {
|
||||||
|
// @Mock
|
||||||
|
private Application mockContext;
|
||||||
|
|
||||||
|
private Glod spider;
|
||||||
|
|
||||||
|
@org.junit.Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mockContext = RuntimeEnvironment.application;
|
||||||
|
Init.init(mockContext);
|
||||||
|
spider = new Glod();
|
||||||
|
spider.init(mockContext, "https://www.czzy.site/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void homeContent() throws Exception {
|
||||||
|
String content = spider.homeContent(true);
|
||||||
|
JsonObject map = Json.safeObject(content);
|
||||||
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
|
System.out.println("homeContent--" + gson.toJson(map));
|
||||||
|
|
||||||
|
//Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void homeVideoContent() throws Exception {
|
||||||
|
String content = spider.homeVideoContent();
|
||||||
|
JsonObject map = Json.safeObject(content);
|
||||||
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
|
System.out.println("homeVideoContent--" + gson.toJson(map));
|
||||||
|
|
||||||
|
//Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void categoryContent() throws Exception {
|
||||||
|
String content = spider.categoryContent("2", "2", true, new HashMap<>());
|
||||||
|
JsonObject map = Json.safeObject(content);
|
||||||
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
System.out.println("categoryContent--" + gson.toJson(map));
|
||||||
|
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void detailContent() throws Exception {
|
||||||
|
|
||||||
|
String content = spider.detailContent(Arrays.asList("/detail/126164"));
|
||||||
|
JsonObject map = Json.safeObject(content);
|
||||||
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
System.out.println("detailContent--" + gson.toJson(map));
|
||||||
|
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void playerContent() throws Exception {
|
||||||
|
String froms = "glod";
|
||||||
|
String urls = "1$/vod/play/126164/sid/1057548#2$/vod/play/126164/sid/1057549#3$/vod/play/126164/sid/1057735#4$/vod/play/126164/sid/1057683";
|
||||||
|
for (int i = 0; i < urls.split("\\$\\$\\$").length; i++) {
|
||||||
|
String content = spider.playerContent(froms.split("\\$\\$\\$")[i], urls.split("\\$\\$\\$")[i].split("#")[0].split("\\$")[1], new ArrayList<>());
|
||||||
|
JsonObject map = Json.safeObject(content);
|
||||||
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
System.out.println("playerContent--" + gson.toJson(map));
|
||||||
|
Assert.assertFalse(map.getAsJsonPrimitive("url").getAsString().isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void searchContent() throws Exception {
|
||||||
|
String content = spider.searchContent("红", false);
|
||||||
|
JsonObject map = Json.safeObject(content);
|
||||||
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
System.out.println("searchContent--" + gson.toJson(map));
|
||||||
|
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -1 +1 @@
|
||||||
0dcb7bdf2bfb2e77fdea1d66f53d1d60
|
1766329347d5e433c0983b6800348229
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;0dcb7bdf2bfb2e77fdea1d66f53d1d60",
|
"spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;1766329347d5e433c0983b6800348229",
|
||||||
"lives": [
|
"lives": [
|
||||||
{
|
{
|
||||||
"name": "直播ipv6",
|
"name": "直播ipv6",
|
||||||
|
|
@ -190,6 +190,15 @@
|
||||||
"changeable": 0,
|
"changeable": 0,
|
||||||
"ext": {}
|
"ext": {}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "glod",
|
||||||
|
"name": "金牌 | 影视",
|
||||||
|
"type": 3,
|
||||||
|
"api": "csp_Glod",
|
||||||
|
"searchable": 1,
|
||||||
|
"changeable": 0,
|
||||||
|
"ext": {}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "newvision",
|
"key": "newvision",
|
||||||
"name":"(js)新视觉影院(不稳定)",
|
"name":"(js)新视觉影院(不稳定)",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;0dcb7bdf2bfb2e77fdea1d66f53d1d60",
|
"spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;1766329347d5e433c0983b6800348229",
|
||||||
"lives": [
|
"lives": [
|
||||||
{
|
{
|
||||||
"name": "直播ipv6",
|
"name": "直播ipv6",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;0dcb7bdf2bfb2e77fdea1d66f53d1d60",
|
"spider": "https://androidcatvodspider.pages.dev/jar/custom_spider.jar;md5;1766329347d5e433c0983b6800348229",
|
||||||
"lives": [
|
"lives": [
|
||||||
{
|
{
|
||||||
"name": "直播ipv6",
|
"name": "直播ipv6",
|
||||||
|
|
@ -190,6 +190,15 @@
|
||||||
"changeable": 0,
|
"changeable": 0,
|
||||||
"ext": {}
|
"ext": {}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "glod",
|
||||||
|
"name": "金牌 | 影视",
|
||||||
|
"type": 3,
|
||||||
|
"api": "csp_Glod",
|
||||||
|
"searchable": 1,
|
||||||
|
"changeable": 0,
|
||||||
|
"ext": {}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "newvision",
|
"key": "newvision",
|
||||||
"name":"(js)新视觉影院(不稳定)",
|
"name":"(js)新视觉影院(不稳定)",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue