Add mqtv
This commit is contained in:
parent
5de9617f5b
commit
b8cddac5e9
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.github.catvod.bean.mqtv;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Data {
|
||||||
|
|
||||||
|
@SerializedName("data")
|
||||||
|
private List<Data> data;
|
||||||
|
@SerializedName("id")
|
||||||
|
private String id;
|
||||||
|
@SerializedName("name")
|
||||||
|
private String name;
|
||||||
|
@SerializedName("stat")
|
||||||
|
private Stat stat;
|
||||||
|
|
||||||
|
public static Data objectFrom(String str) {
|
||||||
|
return new Gson().fromJson(str, Data.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Data> getData() {
|
||||||
|
return data == null ? Collections.emptyList() : data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id == null ? "" : id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name == null ? "" : name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stat getStat() {
|
||||||
|
return stat == null ? new Stat() : stat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.github.catvod.bean.mqtv;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Stat {
|
||||||
|
|
||||||
|
@SerializedName("UserIpList")
|
||||||
|
private List<String> userIpList;
|
||||||
|
|
||||||
|
public List<String> getUserIpList() {
|
||||||
|
return userIpList == null ? Collections.emptyList() : userIpList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.github.catvod.bean.mqtv;
|
||||||
|
|
||||||
|
public class User {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String mac;
|
||||||
|
|
||||||
|
public User(String id, String mac) {
|
||||||
|
this.id = id;
|
||||||
|
this.mac = mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMac() {
|
||||||
|
return mac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,13 +7,15 @@ import android.widget.Button;
|
||||||
import com.github.catvod.R;
|
import com.github.catvod.R;
|
||||||
import com.github.catvod.crawler.Spider;
|
import com.github.catvod.crawler.Spider;
|
||||||
import com.github.catvod.spider.Init;
|
import com.github.catvod.spider.Init;
|
||||||
import com.github.catvod.spider.PTT;
|
import com.github.catvod.spider.MQtv;
|
||||||
|
import com.github.catvod.spider.Proxy;
|
||||||
import com.orhanobut.logger.AndroidLogAdapter;
|
import com.orhanobut.logger.AndroidLogAdapter;
|
||||||
import com.orhanobut.logger.Logger;
|
import com.orhanobut.logger.Logger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
|
@ -32,12 +34,16 @@ public class MainActivity extends Activity {
|
||||||
Button detailContent = findViewById(R.id.detailContent);
|
Button detailContent = findViewById(R.id.detailContent);
|
||||||
Button playerContent = findViewById(R.id.playerContent);
|
Button playerContent = findViewById(R.id.playerContent);
|
||||||
Button searchContent = findViewById(R.id.searchContent);
|
Button searchContent = findViewById(R.id.searchContent);
|
||||||
|
Button liveContent = findViewById(R.id.liveContent);
|
||||||
|
Button proxy = findViewById(R.id.proxy);
|
||||||
homeContent.setOnClickListener(view -> executor.execute(this::homeContent));
|
homeContent.setOnClickListener(view -> executor.execute(this::homeContent));
|
||||||
homeVideoContent.setOnClickListener(view -> executor.execute(this::homeVideoContent));
|
homeVideoContent.setOnClickListener(view -> executor.execute(this::homeVideoContent));
|
||||||
categoryContent.setOnClickListener(view -> executor.execute(this::categoryContent));
|
categoryContent.setOnClickListener(view -> executor.execute(this::categoryContent));
|
||||||
detailContent.setOnClickListener(view -> executor.execute(this::detailContent));
|
detailContent.setOnClickListener(view -> executor.execute(this::detailContent));
|
||||||
playerContent.setOnClickListener(view -> executor.execute(this::playerContent));
|
playerContent.setOnClickListener(view -> executor.execute(this::playerContent));
|
||||||
searchContent.setOnClickListener(view -> executor.execute(this::searchContent));
|
searchContent.setOnClickListener(view -> executor.execute(this::searchContent));
|
||||||
|
liveContent.setOnClickListener(view -> executor.execute(this::liveContent));
|
||||||
|
proxy.setOnClickListener(view -> executor.execute(this::proxy));
|
||||||
Logger.addLogAdapter(new AndroidLogAdapter());
|
Logger.addLogAdapter(new AndroidLogAdapter());
|
||||||
executor = Executors.newCachedThreadPool();
|
executor = Executors.newCachedThreadPool();
|
||||||
executor.execute(this::initSpider);
|
executor.execute(this::initSpider);
|
||||||
|
|
@ -46,7 +52,7 @@ public class MainActivity extends Activity {
|
||||||
private void initSpider() {
|
private void initSpider() {
|
||||||
try {
|
try {
|
||||||
Init.init(getApplicationContext());
|
Init.init(getApplicationContext());
|
||||||
spider = new PTT();
|
spider = new MQtv();
|
||||||
spider.init(this, "");
|
spider.init(this, "");
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
@ -103,4 +109,21 @@ public class MainActivity extends Activity {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void liveContent() {
|
||||||
|
try {
|
||||||
|
Logger.t("liveContent").d(spider.liveContent(""));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void proxy() {
|
||||||
|
try {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
Logger.t("liveContent").d(Proxy.proxy(params));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
package com.github.catvod.spider;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.github.catvod.bean.mqtv.Data;
|
||||||
|
import com.github.catvod.bean.mqtv.User;
|
||||||
|
import com.github.catvod.crawler.Spider;
|
||||||
|
import com.github.catvod.crawler.SpiderDebug;
|
||||||
|
import com.github.catvod.net.OkHttp;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class MQtv extends Spider {
|
||||||
|
|
||||||
|
private static List<User> users;
|
||||||
|
private static String ext;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Context context, String extend) throws Exception {
|
||||||
|
users = new ArrayList<>();
|
||||||
|
ext = extend;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String liveContent(String url) {
|
||||||
|
List<Data> data;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
loadUser(data = Data.objectFrom(OkHttp.string("http://" + ext + "/api/post?item=itv_traffic")).getData());
|
||||||
|
for (Data item : data) sb.append(item.getName()).append(",").append("proxy://do=mqtv").append("&id=").append(item.getId()).append("&type=m3u8").append("\n");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object[] proxy(Map<String, String> params) {
|
||||||
|
String id = params.get("id");
|
||||||
|
String ip = params.get("ip");
|
||||||
|
if (ip != null) ext = ip;
|
||||||
|
String token = getToken();
|
||||||
|
String auth = authChannel(id, token);
|
||||||
|
SpiderDebug.log("id=" + id + ", token=" + token + ", auth=" + auth);
|
||||||
|
Object[] result = new Object[3];
|
||||||
|
result[0] = 200;
|
||||||
|
result[1] = "application/vnd.apple.mpegurl";
|
||||||
|
result[2] = new ByteArrayInputStream(getM3u8(id, token).getBytes());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void loadUser(List<Data> data) {
|
||||||
|
Pattern userPattern = Pattern.compile(".*?([0-9a-zA-Z]{11,}).*", Pattern.CASE_INSENSITIVE);
|
||||||
|
Pattern macPattern = Pattern.compile(".*?(([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}).*", Pattern.CASE_INSENSITIVE);
|
||||||
|
for (Data item : data) {
|
||||||
|
for (String userIp : item.getStat().getUserIpList()) {
|
||||||
|
Matcher userMatcher = userPattern.matcher(userIp);
|
||||||
|
Matcher macMatcher = macPattern.matcher(userIp);
|
||||||
|
String user = userMatcher.matches() ? userMatcher.group(1) : "";
|
||||||
|
String mac = macMatcher.matches() ? macMatcher.group(1) : "";
|
||||||
|
if (!user.isEmpty() && !mac.isEmpty()) users.add(new User(user, mac));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static User choose() {
|
||||||
|
if (users == null) users = new ArrayList<>();
|
||||||
|
if (users.isEmpty()) loadUser(Data.objectFrom(OkHttp.string("http://" + ext + "/api/post?item=itv_traffic")).getData());
|
||||||
|
return users.get(ThreadLocalRandom.current().nextInt(users.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getToken() {
|
||||||
|
User user = choose();
|
||||||
|
String url = String.format(Locale.getDefault(), "http://%s/HSAndroidLogin.ecgi?ty=json&net_account=%s&mac_address1=%s&_=%d", ext, user.getId(), user.getMac(), System.currentTimeMillis());
|
||||||
|
Pattern pattern = Pattern.compile("\"Token\"\\s*:\\s*\"(.*?)\"", Pattern.CASE_INSENSITIVE);
|
||||||
|
Matcher matcher = pattern.matcher(OkHttp.string(url));
|
||||||
|
if (matcher.find()) return matcher.group(1);
|
||||||
|
return getToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String authChannel(String id, String token) {
|
||||||
|
String data = OkHttp.string("http://" + ext + "/ualive?cid=" + id + "&token=" + token);
|
||||||
|
Matcher matcher = Pattern.compile("\"Reason\":\"(.*?)\"", Pattern.CASE_INSENSITIVE).matcher(data);
|
||||||
|
if (matcher.find()) return matcher.group(1);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getM3u8(String id, String token) {
|
||||||
|
String base = "http://" + ext.split(":")[0] + ":" + 5003 + "/";
|
||||||
|
String m3u8 = base + id + ".m3u8?token=" + token;
|
||||||
|
String[] lines = OkHttp.string(m3u8).split("\\r?\\n");
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String line : lines) {
|
||||||
|
if (!line.startsWith("#")) line = base + line;
|
||||||
|
sb.append(line).append("\n");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,8 @@ public class Proxy {
|
||||||
switch (params.get("do")) {
|
switch (params.get("do")) {
|
||||||
case "ck":
|
case "ck":
|
||||||
return new Object[]{200, "text/plain; charset=utf-8", new ByteArrayInputStream("ok".getBytes(StandardCharsets.UTF_8))};
|
return new Object[]{200, "text/plain; charset=utf-8", new ByteArrayInputStream("ok".getBytes(StandardCharsets.UTF_8))};
|
||||||
|
case "mqtv":
|
||||||
|
return MQtv.proxy(params);
|
||||||
case "bili":
|
case "bili":
|
||||||
return Bili.proxy(params);
|
return Bili.proxy(params);
|
||||||
case "webdav":
|
case "webdav":
|
||||||
|
|
|
||||||
|
|
@ -65,5 +65,13 @@
|
||||||
android:text="liveContent"
|
android:text="liveContent"
|
||||||
android:textAllCaps="false" />
|
android:textAllCaps="false" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/proxy"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="proxy"
|
||||||
|
android:textAllCaps="false" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
Binary file not shown.
|
|
@ -1 +1 @@
|
||||||
6286b095a005799c81f27da197beb39f
|
27f9920dc42d81a5b6a45a8f2c0cbf11
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue