mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2025-12-19 05:43:03 +00:00
add 酷狗音乐, 酷我音乐, 网易云音乐, QQ音乐
This commit is contained in:
@@ -211,7 +211,7 @@ public class ReverseProxyVerticle extends AbstractVerticle {
|
|||||||
port = 80;
|
port = 80;
|
||||||
}
|
}
|
||||||
String originPath = url.getPath();
|
String originPath = url.getPath();
|
||||||
LOGGER.info("Conf(path, originPath, host, port) ----> {},{},{},{}", path, originPath, host, port);
|
LOGGER.info("path {}, originPath {}, to {}:{}", path, originPath, host, port);
|
||||||
|
|
||||||
// 注意这里不能origin多个代理地址, 一个实例只能代理一个origin
|
// 注意这里不能origin多个代理地址, 一个实例只能代理一个origin
|
||||||
final HttpProxy httpProxy = HttpProxy.reverseProxy(httpClient);
|
final HttpProxy httpProxy = HttpProxy.reverseProxy(httpClient);
|
||||||
|
|||||||
@@ -10,6 +10,11 @@
|
|||||||
</parent>
|
</parent>
|
||||||
<artifactId>parser</artifactId>
|
<artifactId>parser</artifactId>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>${project.groupId}:${project.artifactId}</name>
|
||||||
|
<description>NFD parser</description>
|
||||||
|
<url>https://qaiu.top</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -46,10 +51,39 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.13.2</version>
|
<version>${junit.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>MIT License</name>
|
||||||
|
<url>https://opensource.org/license/mit</url>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>qaiu</name>
|
||||||
|
<email>qaiu00@gmail.com</email>
|
||||||
|
<organization>https://qaiu.top</organization>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git@github.com:qaiu/netdisk-fast-download.git</connection>
|
||||||
|
<developerConnection>scm:git@github.com:qaiu/netdisk-fast-download.git</developerConnection>
|
||||||
|
<url>git@github.com:qaiu/netdisk-fast-download.git</url>
|
||||||
|
</scm>
|
||||||
|
<distributionManagement>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>sonatype</id>
|
||||||
|
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
<repository>
|
||||||
|
<id>sonatype</id>
|
||||||
|
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
@@ -62,6 +96,49 @@
|
|||||||
<target>${java.version}</target>
|
<target>${java.version}</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<attach>true</attach>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-site-plugin</artifactId>
|
||||||
|
<version>3.7.1</version>
|
||||||
|
</plugin>
|
||||||
|
<!-- Gpg Signature -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
|
<version>1.6</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>sign-artifacts</id>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>sign</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.sonatype.central</groupId>
|
||||||
|
<artifactId>central-publishing-maven-plugin</artifactId>
|
||||||
|
<version>0.6.0</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<publishingServerId>central</publishingServerId>
|
||||||
|
<autoPublish>true</autoPublish>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cn.qaiu.parser;
|
|||||||
|
|
||||||
import cn.qaiu.WebClientVertxInit;
|
import cn.qaiu.WebClientVertxInit;
|
||||||
import cn.qaiu.entity.ShareLinkInfo;
|
import cn.qaiu.entity.ShareLinkInfo;
|
||||||
|
import io.vertx.core.Future;
|
||||||
import io.vertx.core.Handler;
|
import io.vertx.core.Handler;
|
||||||
import io.vertx.core.Promise;
|
import io.vertx.core.Promise;
|
||||||
import io.vertx.core.json.DecodeException;
|
import io.vertx.core.json.DecodeException;
|
||||||
@@ -13,11 +14,14 @@ import io.vertx.ext.web.client.WebClientSession;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析器抽象类包含promise, HTTP Client, 默认失败方法等;
|
* 解析器抽象类包含promise, HTTP Client, 默认失败方法等;
|
||||||
* 新增网盘解析器需要继承该类. <br>
|
* 新增网盘解析器需要继承该类. <br>
|
||||||
* <h2>实现类命名规则: </h2>
|
* <h2>实现类命名规则: </h2>
|
||||||
* <p>{网盘标识}Tool, 网盘标识不超过3个字符, 可以取网盘名称首字母缩写或拼音首字母, <br>
|
* <p>{网盘标识}Tool, 网盘标识不超过5个字符, 可以取网盘名称首字母缩写或拼音首字母, <br>
|
||||||
* 音乐类型的解析以M开头, 例如网易云音乐Mne</p>
|
* 音乐类型的解析以M开头, 例如网易云音乐Mne</p>
|
||||||
*/
|
*/
|
||||||
public abstract class PanBase implements IPanTool {
|
public abstract class PanBase implements IPanTool {
|
||||||
@@ -73,11 +77,11 @@ public abstract class PanBase implements IPanTool {
|
|||||||
try {
|
try {
|
||||||
String s = String.format(errorMsg.replaceAll("\\{}", "%s"), args);
|
String s = String.format(errorMsg.replaceAll("\\{}", "%s"), args);
|
||||||
log.error("解析异常: " + s, t.fillInStackTrace());
|
log.error("解析异常: " + s, t.fillInStackTrace());
|
||||||
promise.fail(this.getClass().getSimpleName() + ": 解析异常: " + s + " -> " + t);
|
promise.fail(shareLinkInfo.getPanName() + "-" + shareLinkInfo.getType() + ": 解析异常: " + s + " -> " + t);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("ErrorMsg format fail. The parameter has been discarded", e);
|
log.error("ErrorMsg format fail. The parameter has been discarded", e);
|
||||||
log.error("解析异常: " + errorMsg, t.fillInStackTrace());
|
log.error("解析异常: " + errorMsg, t.fillInStackTrace());
|
||||||
promise.fail(this.getClass().getSimpleName() + ": 解析异常: " + errorMsg + " -> " + t);
|
promise.fail(shareLinkInfo.getPanName() + "-" + shareLinkInfo.getType() + ": 解析异常: " + errorMsg + " -> " + t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,11 +95,11 @@ public abstract class PanBase implements IPanTool {
|
|||||||
try {
|
try {
|
||||||
String s = String.format(errorMsg.replaceAll("\\{}", "%s"), args);
|
String s = String.format(errorMsg.replaceAll("\\{}", "%s"), args);
|
||||||
log.error("解析异常: " + s);
|
log.error("解析异常: " + s);
|
||||||
promise.fail(this.getClass().getSimpleName() + " - 解析异常: " + s);
|
promise.fail(shareLinkInfo.getPanName() + "-" + shareLinkInfo.getType() + " - 解析异常: " + s);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("ErrorMsg format fail. The parameter has been discarded", e);
|
log.error("ErrorMsg format fail. The parameter has been discarded", e);
|
||||||
log.error("解析异常: " + errorMsg);
|
log.error("解析异常: " + errorMsg);
|
||||||
promise.fail(this.getClass().getSimpleName() + " - 解析异常: " + errorMsg);
|
promise.fail(shareLinkInfo.getPanName() + "-" + shareLinkInfo.getType() + " - 解析异常: " + errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +110,7 @@ public abstract class PanBase implements IPanTool {
|
|||||||
* @return Handler
|
* @return Handler
|
||||||
*/
|
*/
|
||||||
protected Handler<Throwable> handleFail(String errorMsg) {
|
protected Handler<Throwable> handleFail(String errorMsg) {
|
||||||
return t -> fail(this.getClass().getSimpleName() + " - 请求异常 {}: -> {}", errorMsg, t.fillInStackTrace());
|
return t -> fail(shareLinkInfo.getPanName() + "-" + shareLinkInfo.getType() + " - 请求异常 {}: -> {}", errorMsg, t.fillInStackTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -128,4 +132,30 @@ public abstract class PanBase implements IPanTool {
|
|||||||
promise.complete(url);
|
promise.complete(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Future<String> future() {
|
||||||
|
return promise.future();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用下一个解析器, 通用域名解析
|
||||||
|
*/
|
||||||
|
protected void nextParser() {
|
||||||
|
Iterator<PanDomainTemplate> iterator = Arrays.asList(PanDomainTemplate.values()).iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
if (iterator.next().name().equalsIgnoreCase(shareLinkInfo.getType())) {
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
PanDomainTemplate next = iterator.next();
|
||||||
|
log.debug("规则不匹配, 处理解析器转发: {} -> {}", shareLinkInfo.getPanName(), next.getDisplayName());
|
||||||
|
ParserCreate.fromType(next.name())
|
||||||
|
.fromAnyShareUrl(shareLinkInfo.getShareUrl())
|
||||||
|
.createTool()
|
||||||
|
.parse()
|
||||||
|
.onComplete(promise);
|
||||||
|
} else {
|
||||||
|
fail("error: 没有下一个解析处理器");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,11 @@ import cn.qaiu.parser.impl.*;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.util.regex.Pattern.compile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 枚举类 PanDomainTemplate 定义了不同网盘服务的模板信息,包括:
|
* 枚举类 PanDomainTemplate 定义了不同网盘服务的模板信息,包括:
|
||||||
* <ul>
|
* <ul>
|
||||||
@@ -20,126 +23,144 @@ import java.util.stream.Collectors;
|
|||||||
*/
|
*/
|
||||||
public enum PanDomainTemplate {
|
public enum PanDomainTemplate {
|
||||||
|
|
||||||
|
|
||||||
// 网盘定义
|
// 网盘定义
|
||||||
LZ("蓝奏云",
|
LZ("蓝奏云",
|
||||||
"https://([a-z0-9-]+)?\\.?lanzou[a-z]\\.com/(.+/)?(.+)",
|
compile("https://([a-z0-9-]+)?\\.?lanzou[a-z]\\.com/(.+/)?(?<KEY>.+)"),
|
||||||
"https://lanzoux.com/{shareKey}",
|
"https://lanzoux.com/{shareKey}",
|
||||||
LzTool.class),
|
LzTool.class),
|
||||||
|
|
||||||
// https://www.feijix.com/s/
|
// https://www.feijix.com/s/
|
||||||
// https://share.feijipan.com/s/
|
// https://share.feijipan.com/s/
|
||||||
FJ("小飞机网盘",
|
FJ("小飞机网盘",
|
||||||
"https://(share\\.feijipan\\.com|www\\.feijix\\.com)/s/(.+)",
|
compile("https://(share\\.feijipan\\.com|www\\.feijix\\.com)/s/(?<KEY>.+)"),
|
||||||
"https://www.feijix.com/s/{shareKey}",
|
"https://www.feijix.com/s/{shareKey}",
|
||||||
FjTool.class),
|
FjTool.class),
|
||||||
|
|
||||||
// https://lecloud.lenovo.com/share/
|
// https://lecloud.lenovo.com/share/
|
||||||
LE("联想乐云",
|
LE("联想乐云",
|
||||||
"https://lecloud?\\.lenovo\\.com/share/(.+)",
|
compile("https://lecloud?\\.lenovo\\.com/share/(?<KEY>.+)"),
|
||||||
"https://lecloud.lenovo.com/share/{shareKey}",
|
"https://lecloud.lenovo.com/share/{shareKey}",
|
||||||
LeTool.class),
|
LeTool.class),
|
||||||
|
|
||||||
// https://v2.fangcloud.com/s/
|
// https://v2.fangcloud.com/s/
|
||||||
FC("亿方云",
|
FC("亿方云",
|
||||||
"https://v2\\.fangcloud\\.(com|cn)/(s|sharing)/([^/]+)",
|
compile("https://v2\\.fangcloud\\.(com|cn)/(s|sharing)/(?<KEY>.+)"),
|
||||||
"https://v2.fangcloud.com/s/{shareKey}",
|
"https://v2.fangcloud.com/s/{shareKey}",
|
||||||
FcTool.class),
|
FcTool.class),
|
||||||
// https://www.ilanzou.com/s/
|
// https://www.ilanzou.com/s/
|
||||||
IZ("蓝奏云优享",
|
IZ("蓝奏云优享",
|
||||||
"https://www\\.ilanzou\\.com/s/(.+)",
|
compile("https://www\\.ilanzou\\.com/s/(?<KEY>.+)"),
|
||||||
"https://www.ilanzou.com/s/{shareKey}",
|
"https://www.ilanzou.com/s/{shareKey}",
|
||||||
IzTool.class),
|
IzTool.class),
|
||||||
// https://wx.mail.qq.com/ftn/download?
|
// https://wx.mail.qq.com/ftn/download?
|
||||||
QQ("QQ邮箱中转站",
|
QQ("QQ邮箱中转站",
|
||||||
"https://i?wx\\.mail\\.qq\\.com/ftn/download\\?(.+)",
|
compile("https://i?wx\\.mail\\.qq\\.com/ftn/download\\?(?<KEY>.+)"),
|
||||||
"https://iwx.mail.qq.com/ftn/download/{shareKey}",
|
"https://iwx.mail.qq.com/ftn/download/{shareKey}",
|
||||||
QQTool.class),
|
QQTool.class),
|
||||||
// https://f.ws59.cn/f/或者https://www.wenshushu.cn/f/
|
// https://f.ws59.cn/f/或者https://www.wenshushu.cn/f/
|
||||||
WS("文叔叔",
|
WS("文叔叔",
|
||||||
"https://(f\\.ws([0-9]{2})\\.cn|www\\.wenshushu\\.cn)/f/(.+)",
|
compile("https://(f\\.ws([0-9]{2})\\.cn|www\\.wenshushu\\.cn)/f/(?<KEY>.+)"),
|
||||||
"https://www.wenshushu.cn/f/{shareKey}",
|
"https://www.wenshushu.cn/f/{shareKey}",
|
||||||
WsTool.class),
|
WsTool.class),
|
||||||
// https://www.123pan.com/s/
|
// https://www.123pan.com/s/
|
||||||
YE("123网盘",
|
YE("123网盘",
|
||||||
"https://www\\.(123pan|123865|123684)\\.com/s/(.+)",
|
compile("https://www\\.(123pan|123865|123684)\\.com/s/(?<KEY>.+)(.html)?"),
|
||||||
"https://www.123pan.com/s/{shareKey}",
|
"https://www.123pan.com/s/{shareKey}",
|
||||||
YeTool.class),
|
YeTool.class),
|
||||||
// https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data={code}&isShare=1
|
// https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data={code}&isShare=1
|
||||||
EC("移动云空间",
|
EC("移动云空间",
|
||||||
"https://www\\.ecpan\\.cn/web(/%23|/#)?/yunpanProxy\\?path=.*&data=" +
|
compile("https://www\\.ecpan\\.cn/web(/%23|/#)?/yunpanProxy\\?path=.*&data=" +
|
||||||
"([^&]+)&isShare=1",
|
"(?<KEY>[^&]+)&isShare=1"),
|
||||||
"https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data={shareKey}&isShare=1",
|
"https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data={shareKey}&isShare=1",
|
||||||
EcTool.class),
|
EcTool.class),
|
||||||
// https://cowtransfer.com/s/
|
// https://cowtransfer.com/s/
|
||||||
COW("奶牛快传",
|
COW("奶牛快传",
|
||||||
"https://(.*)cowtransfer\\.com/s/(.+)",
|
compile("https://(.*)cowtransfer\\.com/s/(?<KEY>.+)"),
|
||||||
"https://cowtransfer.com/s/{shareKey}",
|
"https://cowtransfer.com/s/{shareKey}",
|
||||||
CowTool.class),
|
CowTool.class),
|
||||||
CT("城通网盘",
|
CT("城通网盘",
|
||||||
"https://474b\\.com/file/(.+)",
|
compile("https://474b\\.com/file/(?<KEY>.+)"),
|
||||||
"https://474b.com/file/{shareKey}",
|
"https://474b.com/file/{shareKey}",
|
||||||
CtTool.class),
|
CtTool.class),
|
||||||
|
|
||||||
// =====================音乐类解析 分享链接标志->MxxS (单歌曲/普通音质)==========================
|
// =====================音乐类解析 分享链接标志->MxxS (单歌曲/普通音质)==========================
|
||||||
// http://163cn.tv/xxx
|
// http://163cn.tv/xxx
|
||||||
MNES("网易云音乐分享",
|
MNES("网易云音乐分享",
|
||||||
"http(s)?://163cn\\.tv/(.+)",
|
compile("http(s)?://163cn\\.tv/(?<KEY>.+)"),
|
||||||
"http://163cn.tv/{shareKey}",
|
"http://163cn.tv/{shareKey}",
|
||||||
MnesTool.class),
|
MnesTool.class),
|
||||||
MNE("网易云音乐",
|
// https://music.163.com/#/song?id=xxx
|
||||||
"https://music\\.163\\.com/(#/)?song\\?id=(.+)",
|
MNE("网易云音乐歌曲详情",
|
||||||
|
compile("https://music\\.163\\.com/(#/)?song\\?id=(?<KEY>.+)"),
|
||||||
"https://music.163.com/#/song?id={shareKey}",
|
"https://music.163.com/#/song?id={shareKey}",
|
||||||
MnesTool.MneTool.class),
|
MnesTool.MneTool.class),
|
||||||
// https://c6.y.qq.com/base/fcgi-bin/u?__=xxx
|
// https://c6.y.qq.com/base/fcgi-bin/u?__=xxx
|
||||||
MQQS("QQ音乐分享",
|
MQQS("QQ音乐分享",
|
||||||
"https://(.+)\\.y\\.qq\\.com/base/fcgi-bin/u\\?__=(.+)",
|
compile("https://(.+)\\.y\\.qq\\.com/base/fcgi-bin/u\\?__=(?<KEY>.+)"),
|
||||||
"https://c6.y.qq.com/base/fcgi-bin/u?__={shareKey}",
|
"https://c6.y.qq.com/base/fcgi-bin/u?__={shareKey}",
|
||||||
MqqTool.class),
|
MqqsTool.class),
|
||||||
// https://y.qq.com/n/ryqq/songDetail/000XjcLg0fbRjv?songtype=0
|
// https://y.qq.com/n/ryqq/songDetail/000XjcLg0fbRjv?songtype=0
|
||||||
MQQ("QQ音乐",
|
MQQ("QQ音乐歌曲详情",
|
||||||
"https://y\\.qq\\.com/n/ryqq/songDetail/(.+)\\?.*",
|
compile("https://y\\.qq\\.com/n/ryqq/songDetail/(?<KEY>.+)(\\?.*)?"),
|
||||||
"https://y.qq.com/n/ryqq/songDetail/{shareKey}",
|
"https://y.qq.com/n/ryqq/songDetail/{shareKey}",
|
||||||
MqqTool.class),
|
MqqsTool.MqqTool.class),
|
||||||
|
|
||||||
// https://t1.kugou.com/song.html?id=xxx
|
// https://t1.kugou.com/song.html?id=xxx
|
||||||
MKGS("酷狗音乐分享",
|
MKGS("酷狗音乐分享",
|
||||||
"https://(.+)\\.kugou\\.com/song\\.html\\?id=(.+)",
|
compile("https://(.+)\\.kugou\\.com/song\\.html\\?id=(?<KEY>.+)"),
|
||||||
"https://t1.kugou.com/song.html?id={shareKey}",
|
"https://t1.kugou.com/song.html?id={shareKey}",
|
||||||
MkgsTool.class),
|
MkgsTool.class),
|
||||||
// https://www.kugou.com/share/2bi8Fe9CSV3.html?id=2bi8Fe9CSV3#6ed9gna4"
|
// https://www.kugou.com/share/2bi8Fe9CSV3.html?id=2bi8Fe9CSV3#6ed9gna4"
|
||||||
MKGS2("酷狗音乐分享2",
|
MKGS2("酷狗音乐分享2",
|
||||||
"https://www\\.kugou\\.com/share/(.+).html\\?.*",
|
compile("https://(.+)\\.kugou\\.com/share/(?<KEY>.+).html.*"),
|
||||||
"https://www.kugou.com/share/{shareKey}.html",
|
"https://www.kugou.com/share/{shareKey}.html",
|
||||||
MkgsTool.Mkgs2Tool.class),
|
MkgsTool.Mkgs2Tool.class),
|
||||||
// https://www.kugou.com/mixsong/2bi8Fe9CSV3
|
// https://www.kugou.com/mixsong/2bi8Fe9CSV3
|
||||||
MKG("酷狗音乐",
|
MKG("酷狗音乐歌曲详情",
|
||||||
"https://(.+)\\.kugou\\.com/song\\.html\\?id=(.+)",
|
compile("https://(.+)\\.kugou\\.com/mixsong/(?<KEY>.+)\\.html.*"),
|
||||||
"https://www.kugou.com/mixsong/{shareKey}",
|
"https://www.kugou.com/mixsong/{shareKey}.html",
|
||||||
MkgsTool.MkgTool.class),
|
MkgsTool.MkgTool.class),
|
||||||
//
|
// https://kuwo.cn/play_detail/395500809
|
||||||
MKWS("酷我音乐分享*",
|
MKWS("酷我音乐分享*",
|
||||||
"https://(.+)\\.kugou\\.com/song\\.html\\?id=(.+)",
|
compile("https://kuwo\\.cn/play_detail/(?<KEY>.+)"),
|
||||||
"https://t1.kugou.com/song.html?id={shareKey}",
|
"https://kuwo.cn/play_detail/{shareKey}",
|
||||||
MkwTool.class),
|
MkwTool.class),
|
||||||
//
|
// https://music.migu.cn/v3/music/song/6326951FKBJ?channelId=001002H
|
||||||
MMGS("咪咕音乐分享",
|
MMGS("咪咕音乐分享",
|
||||||
"https://(.+)\\.kugou\\.com/song\\.html\\?id=(.+)",
|
compile("https://music\\.migu\\.cn/v3/music/song/(?<KEY>.+)(\\?.*)?"),
|
||||||
"https://t1.kugou.com/song.html?id={shareKey}",
|
"https://music.migu.cn/v3/music/song/{shareKey}",
|
||||||
MkwTool.class),
|
MkwTool.class),
|
||||||
// =====================私有盘解析==========================
|
// =====================私有盘解析==========================
|
||||||
|
|
||||||
|
// Cloudreve自定义域名解析, 解析器CeTool兜底策略, 即任意域名如果匹配不到对应的规则, 则由CeTool统一处理,
|
||||||
|
// 如果不属于Cloudreve盘 则调用下一个自定义域名解析器, 若都处理不了则抛出异常, 这种匹配模式类似责任链
|
||||||
// https://pan.huang1111.cn/s/xxx
|
// https://pan.huang1111.cn/s/xxx
|
||||||
// 通用域名([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}
|
// 通用域名([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}
|
||||||
CE("Cloudreve",
|
CE("Cloudreve",
|
||||||
"https://([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,}/s/(.+)",
|
compile("https://([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}(/s)?/(?<KEY>.+)"),
|
||||||
"https://{CloudreveDomainName}/s/{shareKey}",
|
"https://{any}/s/{shareKey}",
|
||||||
CeTool.class);
|
CeTool.class),
|
||||||
|
// 可道云自定义域名解析
|
||||||
|
KD("可道云",
|
||||||
|
compile("http(s)?://([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}(/#s)?/(?<KEY>.+)"),
|
||||||
|
"https://{any}/#s/{shareKey}",
|
||||||
|
KdTool.class),
|
||||||
|
// 其他自定义域名解析
|
||||||
|
OTHER("其他网盘",
|
||||||
|
compile("http(s)?://([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}/(?<KEY>.+)"),
|
||||||
|
"https://{any}/{shareKey}",
|
||||||
|
OtherTool.class);
|
||||||
|
|
||||||
|
public static final String KEY = "KEY";
|
||||||
|
|
||||||
// 网盘的显示名称,用于用户界面显示
|
// 网盘的显示名称,用于用户界面显示
|
||||||
private final String displayName;
|
private final String displayName;
|
||||||
|
|
||||||
// 用于匹配和解析分享链接的正则表达式,保证最后一个捕捉组能匹配到分享key
|
// 用于匹配和解析分享链接的正则表达式,保证最后一个捕捉组能匹配到分享key
|
||||||
private final String regexPattern;
|
private final Pattern pattern;
|
||||||
|
|
||||||
|
private final String regex;
|
||||||
|
|
||||||
// 网盘的标准链接模板,不含占位符,用于规范化分享链接
|
// 网盘的标准链接模板,不含占位符,用于规范化分享链接
|
||||||
private final String standardUrlTemplate;
|
private final String standardUrlTemplate;
|
||||||
@@ -147,10 +168,11 @@ public enum PanDomainTemplate {
|
|||||||
// 指向解析工具IPanTool实现类
|
// 指向解析工具IPanTool实现类
|
||||||
private final Class<? extends IPanTool> toolClass;
|
private final Class<? extends IPanTool> toolClass;
|
||||||
|
|
||||||
PanDomainTemplate(String displayName, String regexPattern, String standardUrlTemplate,
|
PanDomainTemplate(String displayName, Pattern pattern, String standardUrlTemplate,
|
||||||
Class<? extends IPanTool> toolClass) {
|
Class<? extends IPanTool> toolClass) {
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
this.regexPattern = regexPattern;
|
this.pattern = pattern;
|
||||||
|
this.regex = pattern.pattern();
|
||||||
this.standardUrlTemplate = standardUrlTemplate;
|
this.standardUrlTemplate = standardUrlTemplate;
|
||||||
this.toolClass = toolClass;
|
this.toolClass = toolClass;
|
||||||
}
|
}
|
||||||
@@ -159,8 +181,12 @@ public enum PanDomainTemplate {
|
|||||||
return displayName;
|
return displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRegexPattern() {
|
public Pattern getPattern() {
|
||||||
return regexPattern;
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRegex() {
|
||||||
|
return regex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStandardUrlTemplate() {
|
public String getStandardUrlTemplate() {
|
||||||
@@ -174,7 +200,7 @@ public enum PanDomainTemplate {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// 校验重复
|
// 校验重复
|
||||||
Set<String> collect =
|
Set<String> collect =
|
||||||
Arrays.stream(PanDomainTemplate.values()).map(PanDomainTemplate::getRegexPattern).collect(Collectors.toSet());
|
Arrays.stream(PanDomainTemplate.values()).map(PanDomainTemplate::getRegex).collect(Collectors.toSet());
|
||||||
if (collect.size()<PanDomainTemplate.values().length) {
|
if (collect.size()<PanDomainTemplate.values().length) {
|
||||||
System.out.println("有重复枚举正则");
|
System.out.println("有重复枚举正则");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
package cn.qaiu.parser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="https://qaiu.top">QAIU</a>
|
|
||||||
* @date 2023/6/13 4:26
|
|
||||||
*/
|
|
||||||
public enum PanType {
|
|
||||||
LZ("lz"),
|
|
||||||
COW("cow");
|
|
||||||
|
|
||||||
PanType(String type) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,8 @@ import cn.qaiu.entity.ShareLinkInfo;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
import static cn.qaiu.parser.PanDomainTemplate.KEY;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,15 +35,14 @@ public class ParserCreate {
|
|||||||
if (StringUtils.isEmpty(shareUrl)) {
|
if (StringUtils.isEmpty(shareUrl)) {
|
||||||
throw new IllegalArgumentException("ShareLinkInfo shareUrl is empty");
|
throw new IllegalArgumentException("ShareLinkInfo shareUrl is empty");
|
||||||
}
|
}
|
||||||
Pattern pattern = Pattern.compile(this.panDomainTemplate.getRegexPattern());
|
Matcher matcher = this.panDomainTemplate.getPattern().matcher(shareUrl);
|
||||||
Matcher matcher = pattern.matcher(shareUrl);
|
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
String shareKey = matcher.group(matcher.groupCount());
|
String shareKey = matcher.group(KEY);
|
||||||
// 返回规范化的标准链接
|
// 返回规范化的标准链接
|
||||||
String standardUrl = getStandardUrlTemplate().replace("{shareKey}", shareKey);
|
String standardUrl = getStandardUrlTemplate().replace("{shareKey}", shareKey);
|
||||||
shareLinkInfo.setShareUrl(shareUrl);
|
shareLinkInfo.setShareUrl(shareUrl);
|
||||||
shareLinkInfo.setShareKey(shareKey);
|
shareLinkInfo.setShareKey(shareKey);
|
||||||
if (!(panDomainTemplate == PanDomainTemplate.CE)) {
|
if (!(panDomainTemplate.ordinal() >= PanDomainTemplate.CE.ordinal())) {
|
||||||
shareLinkInfo.setStandardUrl(standardUrl);
|
shareLinkInfo.setStandardUrl(standardUrl);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
@@ -68,7 +68,7 @@ public class ParserCreate {
|
|||||||
|
|
||||||
// set share key
|
// set share key
|
||||||
public ParserCreate shareKey(String shareKey) {
|
public ParserCreate shareKey(String shareKey) {
|
||||||
if (panDomainTemplate == PanDomainTemplate.CE) {
|
if (panDomainTemplate.ordinal() >= PanDomainTemplate.CE.ordinal()) {
|
||||||
// 处理Cloudreve(ce)类: pan.huang1111.cn_s_wDz5TK _ -> /
|
// 处理Cloudreve(ce)类: pan.huang1111.cn_s_wDz5TK _ -> /
|
||||||
String[] s = shareKey.split("_");
|
String[] s = shareKey.split("_");
|
||||||
String standardUrl = "https://" + String.join("/", s);
|
String standardUrl = "https://" + String.join("/", s);
|
||||||
@@ -82,6 +82,13 @@ public class ParserCreate {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set any share url
|
||||||
|
public ParserCreate fromAnyShareUrl(String url) {
|
||||||
|
shareLinkInfo.setStandardUrl(url);
|
||||||
|
shareLinkInfo.setShareUrl(url);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getStandardUrlTemplate() {
|
public String getStandardUrlTemplate() {
|
||||||
return this.panDomainTemplate.getStandardUrlTemplate();
|
return this.panDomainTemplate.getStandardUrlTemplate();
|
||||||
}
|
}
|
||||||
@@ -98,12 +105,12 @@ public class ParserCreate {
|
|||||||
// 根据分享链接获取PanDomainTemplate实例
|
// 根据分享链接获取PanDomainTemplate实例
|
||||||
public synchronized static ParserCreate fromShareUrl(String shareUrl) {
|
public synchronized static ParserCreate fromShareUrl(String shareUrl) {
|
||||||
for (PanDomainTemplate panDomainTemplate : PanDomainTemplate.values()) {
|
for (PanDomainTemplate panDomainTemplate : PanDomainTemplate.values()) {
|
||||||
if (shareUrl.matches(panDomainTemplate.getRegexPattern())) {
|
if (panDomainTemplate.getPattern().matcher(shareUrl).matches()) {
|
||||||
ShareLinkInfo shareLinkInfo = ShareLinkInfo.newBuilder()
|
ShareLinkInfo shareLinkInfo = ShareLinkInfo.newBuilder()
|
||||||
.type(panDomainTemplate.name().toLowerCase())
|
.type(panDomainTemplate.name().toLowerCase())
|
||||||
.panName(panDomainTemplate.getDisplayName())
|
.panName(panDomainTemplate.getDisplayName())
|
||||||
.shareUrl(shareUrl).build();
|
.shareUrl(shareUrl).build();
|
||||||
if (panDomainTemplate == PanDomainTemplate.CE) {
|
if (panDomainTemplate.ordinal() >= PanDomainTemplate.CE.ordinal()) {
|
||||||
shareLinkInfo.setStandardUrl(shareUrl);
|
shareLinkInfo.setStandardUrl(shareUrl);
|
||||||
}
|
}
|
||||||
ParserCreate parserCreate = new ParserCreate(panDomainTemplate, shareLinkInfo);
|
ParserCreate parserCreate = new ParserCreate(panDomainTemplate, shareLinkInfo);
|
||||||
@@ -119,6 +126,7 @@ public class ParserCreate {
|
|||||||
PanDomainTemplate panDomainTemplate = Enum.valueOf(PanDomainTemplate.class, type.toUpperCase());
|
PanDomainTemplate panDomainTemplate = Enum.valueOf(PanDomainTemplate.class, type.toUpperCase());
|
||||||
ShareLinkInfo shareLinkInfo = ShareLinkInfo.newBuilder()
|
ShareLinkInfo shareLinkInfo = ShareLinkInfo.newBuilder()
|
||||||
.type(type.toLowerCase()).build();
|
.type(type.toLowerCase()).build();
|
||||||
|
shareLinkInfo.setPanName(panDomainTemplate.getDisplayName());
|
||||||
return new ParserCreate(panDomainTemplate, shareLinkInfo);
|
return new ParserCreate(panDomainTemplate, shareLinkInfo);
|
||||||
} catch (IllegalArgumentException ignore) {
|
} catch (IllegalArgumentException ignore) {
|
||||||
// 如果没有找到对应的枚举实例,抛出异常
|
// 如果没有找到对应的枚举实例,抛出异常
|
||||||
|
|||||||
@@ -2,12 +2,16 @@ package cn.qaiu.parser.impl;
|
|||||||
|
|
||||||
import cn.qaiu.entity.ShareLinkInfo;
|
import cn.qaiu.entity.ShareLinkInfo;
|
||||||
import cn.qaiu.parser.PanBase;
|
import cn.qaiu.parser.PanBase;
|
||||||
|
import cn.qaiu.parser.PanDomainTemplate;
|
||||||
|
import cn.qaiu.parser.ParserCreate;
|
||||||
import io.vertx.core.Future;
|
import io.vertx.core.Future;
|
||||||
import io.vertx.core.buffer.Buffer;
|
import io.vertx.core.buffer.Buffer;
|
||||||
import io.vertx.core.json.JsonObject;
|
import io.vertx.core.json.JsonObject;
|
||||||
import io.vertx.ext.web.client.HttpRequest;
|
import io.vertx.ext.web.client.HttpRequest;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <a href="https://github.com/cloudreve/Cloudreve">Cloudreve自建网盘解析</a> <br>
|
* <a href="https://github.com/cloudreve/Cloudreve">Cloudreve自建网盘解析</a> <br>
|
||||||
@@ -42,22 +46,32 @@ public class CeTool extends PanBase {
|
|||||||
String downloadApiUrl = url.getProtocol() + "://" + url.getHost() + DOWNLOAD_API_PATH + key + "?path" +
|
String downloadApiUrl = url.getProtocol() + "://" + url.getHost() + DOWNLOAD_API_PATH + key + "?path" +
|
||||||
"=undefined/undefined;";
|
"=undefined/undefined;";
|
||||||
String shareApiUrl = url.getProtocol() + "://" + url.getHost() + SHARE_API_PATH + key;
|
String shareApiUrl = url.getProtocol() + "://" + url.getHost() + SHARE_API_PATH + key;
|
||||||
|
|
||||||
// 设置cookie
|
// 设置cookie
|
||||||
HttpRequest<Buffer> httpRequest = clientSession.getAbs(shareApiUrl);
|
HttpRequest<Buffer> httpRequest = clientSession.getAbs(shareApiUrl);
|
||||||
if (pwd != null) {
|
if (pwd != null) {
|
||||||
httpRequest.addQueryParam("password", pwd);
|
httpRequest.addQueryParam("password", pwd);
|
||||||
}
|
}
|
||||||
// 获取下载链接
|
// 获取下载链接
|
||||||
httpRequest.send().onSuccess(res -> getDownURL(downloadApiUrl)).onFailure(handleFail(shareApiUrl));
|
httpRequest.send().onSuccess(res -> {
|
||||||
|
try {
|
||||||
|
if (res.statusCode() == 200 && res.bodyAsJsonObject().containsKey("code")) {
|
||||||
|
getDownURL(downloadApiUrl);
|
||||||
|
} else {
|
||||||
|
nextParser();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
nextParser();
|
||||||
|
}
|
||||||
|
}).onFailure(handleFail(shareApiUrl));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail(e, "URL解析错误");
|
fail(e, "URL解析错误");
|
||||||
}
|
}
|
||||||
return promise.future();
|
return promise.future();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getDownURL(String apiUrl) {
|
|
||||||
clientSession.putAbs(apiUrl).send().onSuccess(res -> {
|
private void getDownURL(String shareApiUrl) {
|
||||||
|
clientSession.putAbs(shareApiUrl).send().onSuccess(res -> {
|
||||||
JsonObject jsonObject = asJson(res);
|
JsonObject jsonObject = asJson(res);
|
||||||
System.out.println(jsonObject.encodePrettily());
|
System.out.println(jsonObject.encodePrettily());
|
||||||
if (jsonObject.containsKey("code") && jsonObject.getInteger("code") == 0) {
|
if (jsonObject.containsKey("code") && jsonObject.getInteger("code") == 0) {
|
||||||
@@ -65,6 +79,6 @@ public class CeTool extends PanBase {
|
|||||||
} else {
|
} else {
|
||||||
fail("JSON解析失败: {}", jsonObject.encodePrettily());
|
fail("JSON解析失败: {}", jsonObject.encodePrettily());
|
||||||
}
|
}
|
||||||
}).onFailure(handleFail(apiUrl));
|
}).onFailure(handleFail(shareApiUrl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
parser/src/main/java/cn/qaiu/parser/impl/KdTool.java
Normal file
26
parser/src/main/java/cn/qaiu/parser/impl/KdTool.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package cn.qaiu.parser.impl;
|
||||||
|
|
||||||
|
import cn.qaiu.entity.ShareLinkInfo;
|
||||||
|
import cn.qaiu.parser.PanBase;
|
||||||
|
import io.vertx.core.Future;
|
||||||
|
import io.vertx.core.json.JsonArray;
|
||||||
|
import io.vertx.core.json.JsonObject;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <a href="https://kodcloud.com/">可道云</a>
|
||||||
|
*/
|
||||||
|
public class KdTool extends PanBase {
|
||||||
|
private static final String API_URL_PREFIX = "";
|
||||||
|
|
||||||
|
public KdTool(ShareLinkInfo shareLinkInfo) {
|
||||||
|
super(shareLinkInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Future<String> parse() {
|
||||||
|
nextParser();
|
||||||
|
// TODO
|
||||||
|
return future();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package cn.qaiu.parser.impl;
|
|||||||
import cn.qaiu.entity.ShareLinkInfo;
|
import cn.qaiu.entity.ShareLinkInfo;
|
||||||
import cn.qaiu.parser.PanBase;
|
import cn.qaiu.parser.PanBase;
|
||||||
import io.vertx.core.Future;
|
import io.vertx.core.Future;
|
||||||
import io.vertx.uritemplate.UriTemplate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 咪咕音乐分享
|
* 咪咕音乐分享
|
||||||
@@ -20,6 +19,8 @@ public class MmgTool extends PanBase {
|
|||||||
public Future<String> parse() {
|
public Future<String> parse() {
|
||||||
String shareUrl = shareLinkInfo.getStandardUrl();
|
String shareUrl = shareLinkInfo.getStandardUrl();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
promise.complete("暂未实现, 敬请期待");
|
||||||
return promise.future();
|
return promise.future();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,12 @@ public class MnesTool extends PanBase {
|
|||||||
String id = URLUtil.from(locationURL).getParam("id");
|
String id = URLUtil.from(locationURL).getParam("id");
|
||||||
clientNoRedirects.getAbs(UriTemplate.of(API_URL)).setTemplateParam("id", id).send()
|
clientNoRedirects.getAbs(UriTemplate.of(API_URL)).setTemplateParam("id", id).send()
|
||||||
.onSuccess(res2 -> {
|
.onSuccess(res2 -> {
|
||||||
promise.complete(res2.headers().get("Location"));
|
String location = res2.headers().get("Location");
|
||||||
|
if (location.endsWith("/404")) {
|
||||||
|
fail("链接已失效: id={}", id);
|
||||||
|
} else {
|
||||||
|
promise.complete(location);
|
||||||
|
}
|
||||||
}).onFailure(handleFail(API_URL.replace("{id}", id)));
|
}).onFailure(handleFail(API_URL.replace("{id}", id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import io.vertx.uritemplate.UriTemplate;
|
|||||||
* <a href="https://c6.y.qq.com/base/fcgi-bin/u?__=w3lqEpOHACLO">分享示例</a>
|
* <a href="https://c6.y.qq.com/base/fcgi-bin/u?__=w3lqEpOHACLO">分享示例</a>
|
||||||
* <a href="https://y.qq.com/n/ryqq/songDetail/000XjcLg0fbRjv?songtype=0">详情页</a>
|
* <a href="https://y.qq.com/n/ryqq/songDetail/000XjcLg0fbRjv?songtype=0">详情页</a>
|
||||||
*/
|
*/
|
||||||
public class MqqTool extends PanBase {
|
public class MqqsTool extends PanBase {
|
||||||
|
|
||||||
public static final String API_URL = "https://u.y.qq.com/cgi-bin/musicu" +
|
public static final String API_URL = "https://u.y.qq.com/cgi-bin/musicu" +
|
||||||
".fcg?-=getplaysongvkey2682247447678878&g_tk=5381&loginUin=956581739&hostUin=0&format=json&inCharset=utf8" +
|
".fcg?-=getplaysongvkey2682247447678878&g_tk=5381&loginUin=956581739&hostUin=0&format=json&inCharset=utf8" +
|
||||||
@@ -24,7 +24,7 @@ public class MqqTool extends PanBase {
|
|||||||
"%2C%22loginflag%22%3A1%2C%22platform%22%3A%2220%22%7D%7D%2C%22comm%22%3A%7B%22uin%22%3A956581739%2C" +
|
"%2C%22loginflag%22%3A1%2C%22platform%22%3A%2220%22%7D%7D%2C%22comm%22%3A%7B%22uin%22%3A956581739%2C" +
|
||||||
"%22format%22%3A%22json%22%2C%22ct%22%3A24%2C%22cv%22%3A0%7D%7D";
|
"%22format%22%3A%22json%22%2C%22ct%22%3A24%2C%22cv%22%3A0%7D%7D";
|
||||||
|
|
||||||
public MqqTool(ShareLinkInfo shareLinkInfo) {
|
public MqqsTool(ShareLinkInfo shareLinkInfo) {
|
||||||
super(shareLinkInfo);
|
super(shareLinkInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,9 +36,16 @@ public class MqqTool extends PanBase {
|
|||||||
clientNoRedirects.getAbs(shareUrl).send().onSuccess(res -> {
|
clientNoRedirects.getAbs(shareUrl).send().onSuccess(res -> {
|
||||||
String locationURL = res.headers().get("Location");
|
String locationURL = res.headers().get("Location");
|
||||||
String id = URLUtil.from(locationURL).getParam("songmid");
|
String id = URLUtil.from(locationURL).getParam("songmid");
|
||||||
|
downUrl(id);
|
||||||
|
}).onFailure(handleFail(shareUrl));
|
||||||
|
|
||||||
|
return promise.future();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void downUrl(String id) {
|
||||||
clientNoRedirects.getAbs(UriTemplate.of(API_URL)).setTemplateParam("songmid", id).send().onSuccess(res2 -> {
|
clientNoRedirects.getAbs(UriTemplate.of(API_URL)).setTemplateParam("songmid", id).send().onSuccess(res2 -> {
|
||||||
JsonObject jsonObject = asJson(res2);
|
JsonObject jsonObject = asJson(res2);
|
||||||
System.out.println(jsonObject.encodePrettily());
|
log.debug(jsonObject.encodePrettily());
|
||||||
try {
|
try {
|
||||||
JsonObject data = jsonObject.getJsonObject("req_0").getJsonObject("data");
|
JsonObject data = jsonObject.getJsonObject("req_0").getJsonObject("data");
|
||||||
String path = data.getJsonArray("midurlinfo").getJsonObject(0).getString("purl");
|
String path = data.getJsonArray("midurlinfo").getJsonObject(0).getString("purl");
|
||||||
@@ -48,18 +55,24 @@ public class MqqTool extends PanBase {
|
|||||||
}
|
}
|
||||||
String downURL = data.getJsonArray("sip").getString(0)
|
String downURL = data.getJsonArray("sip").getString(0)
|
||||||
.replace("http://", "https://") + path;
|
.replace("http://", "https://") + path;
|
||||||
System.out.println(downURL);
|
|
||||||
promise.complete(downURL);
|
promise.complete(downURL);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail("获取失败");
|
fail("获取失败");
|
||||||
}
|
}
|
||||||
}).onFailure(handleFail(API_URL.replace("{id}", id)));
|
}).onFailure(handleFail(API_URL.replace("{id}", id)));
|
||||||
}).onFailure(handleFail(shareUrl));
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class MqqTool extends MqqsTool{
|
||||||
|
|
||||||
|
public MqqTool(ShareLinkInfo shareLinkInfo) {
|
||||||
|
super(shareLinkInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<String> parse() {
|
||||||
|
downUrl(shareLinkInfo.getShareKey());
|
||||||
return promise.future();
|
return promise.future();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
new MqqTool(ShareLinkInfo.newBuilder().build()).parse();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
22
parser/src/main/java/cn/qaiu/parser/impl/OtherTool.java
Normal file
22
parser/src/main/java/cn/qaiu/parser/impl/OtherTool.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package cn.qaiu.parser.impl;
|
||||||
|
|
||||||
|
import cn.qaiu.entity.ShareLinkInfo;
|
||||||
|
import cn.qaiu.parser.PanBase;
|
||||||
|
import io.vertx.core.Future;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 其他网盘解析
|
||||||
|
*/
|
||||||
|
public class OtherTool extends PanBase {
|
||||||
|
private static final String API_URL_PREFIX = "";
|
||||||
|
|
||||||
|
public OtherTool(ShareLinkInfo shareLinkInfo) {
|
||||||
|
super(shareLinkInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Future<String> parse() {
|
||||||
|
// TODO
|
||||||
|
fail("暂未实现, 敬请期待");
|
||||||
|
return future();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,32 @@
|
|||||||
package cn.qaiu.util;
|
package cn.qaiu.util;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class URLUtil {
|
public class URLUtil {
|
||||||
|
|
||||||
private Map<String, String> queryParams = new HashMap<>();
|
private final Map<String, String> queryParams = new HashMap<>();
|
||||||
|
|
||||||
// 构造函数,传入URL并解析参数
|
// 构造函数,传入URL并解析参数
|
||||||
private URLUtil(String url) {
|
private URLUtil(String url) {
|
||||||
try {
|
try {
|
||||||
URL parsedUrl = new URL(url);
|
URL parsedUrl = new URL(url);
|
||||||
|
String ref = parsedUrl.getRef();
|
||||||
|
if (StringUtils.isNotEmpty(ref)) {
|
||||||
|
parsedUrl = new URL(parsedUrl.getProtocol() + "://" + parsedUrl.getHost() + ref);
|
||||||
|
}
|
||||||
String query = parsedUrl.getQuery();
|
String query = parsedUrl.getQuery();
|
||||||
if (query != null) {
|
if (query != null) {
|
||||||
String[] pairs = query.split("&");
|
String[] pairs = query.split("&");
|
||||||
for (String pair : pairs) {
|
for (String pair : pairs) {
|
||||||
String[] keyValue = pair.split("=");
|
String[] keyValue = pair.split("=");
|
||||||
String key = URLDecoder.decode(keyValue[0], "UTF-8");
|
String key = URLDecoder.decode(keyValue[0], StandardCharsets.UTF_8);
|
||||||
String value = keyValue.length > 1 ? URLDecoder.decode(keyValue[1], "UTF-8") : "";
|
String value = keyValue.length > 1 ? URLDecoder.decode(keyValue[1], StandardCharsets.UTF_8) : "";
|
||||||
queryParams.put(key, value);
|
queryParams.put(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,10 @@ public class TestRegex {
|
|||||||
@Test
|
@Test
|
||||||
public void regexYFC() {
|
public void regexYFC() {
|
||||||
String html = """
|
String html = """
|
||||||
<input type="hidden" id="typed_id" value="file_559003251828">
|
https://www.kugou.com/mixsong/9q98o5b9.html
|
||||||
<input type="hidden" id="share_link_token" value="9cbe4b73521ba4d65a8cd38a8c">
|
|
||||||
""";
|
""";
|
||||||
|
|
||||||
Pattern compile = Pattern.compile("id=\"typed_id\"\\s+value=\"file_(\\d+)\"");
|
Pattern compile = Pattern.compile("https://(.+)\\.kugou\\.com/mixsong/(?<KEY>.+).html");
|
||||||
Matcher matcher = compile.matcher(html);
|
Matcher matcher = compile.matcher(html);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
System.out.println(matcher.group(0));
|
System.out.println(matcher.group(0));
|
||||||
|
|||||||
@@ -28,10 +28,6 @@ public class URLParamUtil {
|
|||||||
if (params.contains("url")) {
|
if (params.contains("url")) {
|
||||||
String encodedUrl = params.get("url");
|
String encodedUrl = params.get("url");
|
||||||
url = handleTruncatedUrl(encodedUrl, params);
|
url = handleTruncatedUrl(encodedUrl, params);
|
||||||
if (url.endsWith(".html")) {
|
|
||||||
// 123云盘的后缀处理
|
|
||||||
url = url.replace(".html", "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ https://music.163.com/song?id=233334
|
|||||||
|
|
||||||
###
|
###
|
||||||
#@no-redirect
|
#@no-redirect
|
||||||
https://music.163.com/song/media/outer/url?id=233334
|
https://music.163.com/song/media/outer/url?id=2020593612
|
||||||
|
|
||||||
|
###
|
||||||
|
https://music.163.com/#/song?id=092087
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
@@ -166,3 +169,13 @@ https://ws6.stream.qqmusic.qq.com/C400003mAan70zUy5O.m4a?guid=2796982635&vkey=B2
|
|||||||
|
|
||||||
###
|
###
|
||||||
https://ws.stream.qqmusic.qq.com/C400003mAan70zUy5O.m4a?fromtag=666&guid=2796982635&vkey=B2EDD08E318F0C0D2B3A9462FC5754CBCA9AEFD796FA0662C83A102821425D31547F957451751901F195095830842E1565FF8815B210B25A
|
https://ws.stream.qqmusic.qq.com/C400003mAan70zUy5O.m4a?fromtag=666&guid=2796982635&vkey=B2EDD08E318F0C0D2B3A9462FC5754CBCA9AEFD796FA0662C83A102821425D31547F957451751901F195095830842E1565FF8815B210B25A
|
||||||
|
|
||||||
|
###
|
||||||
|
https://y.qq.com/n/ryqq/songDetail/000KKjzb2Eq15b
|
||||||
|
|
||||||
|
###
|
||||||
|
# @no-redirect
|
||||||
|
https://c6.y.qq.com/base/fcgi-bin/u?__=k8gafY6HAQ5Y
|
||||||
|
|
||||||
|
###
|
||||||
|
https://u.y.qq.com/cgi-bin/musicu.fcg?-=getplaysongvkey2682247447678878&g_tk=5381&loginUin=956581739&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0&data=%7B%22req_0%22%3A%7B%22module%22%3A%22vkey.GetVkeyServer%22%2C%22method%22%3A%22CgiGetVkey%22%2C%22param%22%3A%7B%22guid%22%3A%222796982635%22%2C%22songmid%22%3A%5B%22000KKjzb2Eq15b%22%5D%2C%22songtype%22%3A%5B1%5D%2C%22uin%22%3A%22956581739%22%2C%22loginflag%22%3A1%2C%22platform%22%3A%2220%22%7D%7D%2C%22comm%22%3A%7B%22uin%22%3A956581739%2C%22format%22%3A%22json%22%2C%22ct%22%3A24%2C%22cv%22%3A0%7D%7D
|
||||||
|
|||||||
@@ -64,3 +64,15 @@ sec-fetch-user: ?1
|
|||||||
upgrade-insecure-requests: 1
|
upgrade-insecure-requests: 1
|
||||||
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
|
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
|
###
|
||||||
|
GET https://blog.qaiu.top/api/v3/share/download/nLNsQ
|
||||||
|
|
||||||
|
###
|
||||||
|
# @no-redirect
|
||||||
|
GET http://127.0.0.1:6401/parser?url=https://blog.qaiu.top/s/nLNsQ1
|
||||||
|
|
||||||
|
###
|
||||||
|
# @no-redirect
|
||||||
|
GET http://127.0.0.1:6401/parser?url=https://pan.seeoss.com/s/nLNsQ1
|
||||||
|
|
||||||
|
|||||||
@@ -153,8 +153,14 @@ GET http://127.0.0.1:6400/json/ce/pan.huang1111.cn_s_g31PcQ@qaiu
|
|||||||
#GET http://127.0.0.1:6400/parser?url=https://pan.huang1111.cn/s/g31PcQ&pwd=qaiu
|
#GET http://127.0.0.1:6400/parser?url=https://pan.huang1111.cn/s/g31PcQ&pwd=qaiu
|
||||||
|
|
||||||
# @no-redirect
|
# @no-redirect
|
||||||
GET http://127.0.0.1:6400/parser?url=https://pan.seeoss.com/s/nLNsQ
|
GET http://127.0.0.1:6401/parser?url=https://pan.seeoss.com/s/nLNsQ
|
||||||
|
|
||||||
|
###
|
||||||
|
# @no-redirect
|
||||||
|
GET http://127.0.0.1:6401/parser?url=https://blog.qaiu.top/s/nLNsQ
|
||||||
|
|
||||||
|
###
|
||||||
|
PUT https://blog.qaiu.top/s/nLNsQ
|
||||||
|
|
||||||
|
|
||||||
### PASS QQ
|
### PASS QQ
|
||||||
@@ -197,15 +203,37 @@ GET http://127.0.0.1:6401/parser?url=https://474b.com/file/4015376-131945810
|
|||||||
|
|
||||||
### PASS MNE
|
### PASS MNE
|
||||||
# @no-redirect
|
# @no-redirect
|
||||||
GET http://127.0.0.1:6401/parser?url=http://163cn.tv/ykLZJJT
|
GET http://127.0.0.1:6401/json/parser?url=http://163cn.tv/ykLZJJT
|
||||||
|
### PASS MNE2
|
||||||
|
# @no-redirect
|
||||||
|
GET http://127.0.0.1:6401/parser?url=https://music.163.com/#/song?id=472194327
|
||||||
|
|
||||||
|
|
||||||
### PASS MQQ
|
### PASS MQQ
|
||||||
# @no-redirect
|
# @no-redirect
|
||||||
GET http://127.0.0.1:6401/parser?url=https://c6.y.qq.com/base/fcgi-bin/u?__=k8gafY6HAQ5Y
|
GET http://127.0.0.1:6401/parser?url=https://c6.y.qq.com/base/fcgi-bin/u?__=k8gafY6HAQ5Y
|
||||||
|
### PASS MQQ2
|
||||||
|
# @no-redirect
|
||||||
|
GET http://127.0.0.1:6401/parser?url=https://y.qq.com/n/ryqq/songDetail/000KKjzb2Eq15b
|
||||||
|
|
||||||
|
### PASS MKG0 酷狗
|
||||||
|
# @no-redirect
|
||||||
|
GET http://127.0.0.1:6401/parser?url=https://www.kugou.com/share/2bi8Fe9CSV3.html
|
||||||
### PASS MKG
|
### PASS MKG
|
||||||
# @no-redirect
|
# @no-redirect
|
||||||
|
GET http://127.0.0.1:6401/json/parser?url=https://www.kugou.com/share/2bi8Fe9CSV3.html?id=2bi8Fe9CSV3#6ed9gna4
|
||||||
|
### PASS MKG2
|
||||||
|
# @no-redirect
|
||||||
GET http://127.0.0.1:6401/parser?url=https://t1.kugou.com/song.html?id=2bi8Fe9CSV3
|
GET http://127.0.0.1:6401/parser?url=https://t1.kugou.com/song.html?id=2bi8Fe9CSV3
|
||||||
|
### PASS MKG3
|
||||||
|
# @no-redirect
|
||||||
|
GET http://127.0.0.1:6401/parser?url=https://www.kugou.com/mixsong/9q98o5b9.html
|
||||||
|
|
||||||
|
### PASS MQW 酷我
|
||||||
|
# @no-redirect
|
||||||
|
GET http://127.0.0.1:6401/parser?url=https://kuwo.cn/play_detail/395500809
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### n1
|
### n1
|
||||||
http://127.0.0.1:6401/n1/statisticsInfo
|
http://127.0.0.1:6401/n1/statisticsInfo
|
||||||
|
|||||||
Reference in New Issue
Block a user