2026-02-26 20:18:57 +08:00
|
|
|
package com.coloryr.allmusic.server.netapi;
|
2020-03-17 15:18:29 +08:00
|
|
|
|
2024-04-19 09:46:54 +08:00
|
|
|
import com.coloryr.allmusic.server.core.AllMusic;
|
2026-02-26 20:18:57 +08:00
|
|
|
import com.coloryr.allmusic.server.core.IMusicApi;
|
|
|
|
|
import com.coloryr.allmusic.server.core.music.LyricSave;
|
2024-04-19 09:46:54 +08:00
|
|
|
import com.coloryr.allmusic.server.core.objs.HttpResObj;
|
|
|
|
|
import com.coloryr.allmusic.server.core.objs.SearchMusicObj;
|
2026-02-26 20:35:11 +08:00
|
|
|
import com.coloryr.allmusic.server.core.objs.message.ARG;
|
|
|
|
|
import com.coloryr.allmusic.server.core.objs.music.SearchPageObj;
|
|
|
|
|
import com.coloryr.allmusic.server.core.objs.music.SongInfoObj;
|
|
|
|
|
import com.coloryr.allmusic.server.core.sql.DataSql;
|
2026-02-26 20:18:57 +08:00
|
|
|
import com.coloryr.allmusic.server.core.utils.Function;
|
|
|
|
|
import com.coloryr.allmusic.server.netapi.obj.music.info.InfoObj;
|
|
|
|
|
import com.coloryr.allmusic.server.netapi.obj.music.list.DataObj;
|
|
|
|
|
import com.coloryr.allmusic.server.netapi.obj.music.lyric.WLyricObj;
|
|
|
|
|
import com.coloryr.allmusic.server.netapi.obj.music.search.SearchDataObj;
|
|
|
|
|
import com.coloryr.allmusic.server.netapi.obj.music.search.songs;
|
|
|
|
|
import com.coloryr.allmusic.server.netapi.obj.music.trialinfo.TrialInfoObj;
|
|
|
|
|
import com.coloryr.allmusic.server.netapi.obj.program.info.PrInfoObj;
|
2021-06-09 01:38:40 +08:00
|
|
|
import com.google.gson.JsonObject;
|
2020-03-17 15:18:29 +08:00
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
2026-02-26 20:18:57 +08:00
|
|
|
public class NetiApiMain implements IMusicApi {
|
2020-03-17 15:18:29 +08:00
|
|
|
|
2024-04-17 22:15:12 +08:00
|
|
|
private boolean isUpdate;
|
2020-03-17 15:18:29 +08:00
|
|
|
|
2026-02-26 20:18:57 +08:00
|
|
|
public NetiApiMain() {
|
2026-03-04 16:05:57 +08:00
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<yellow>正在初始化网络爬虫");
|
2026-02-26 20:18:57 +08:00
|
|
|
|
|
|
|
|
HttpResObj res = NetApiHttpClient.get("https://music.163.com", "");
|
2026-03-04 16:05:57 +08:00
|
|
|
if (res == null || !res.ok) {
|
|
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<red>初始化net api失败");
|
2021-06-08 23:28:03 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-26 20:18:57 +08:00
|
|
|
@Override
|
|
|
|
|
public boolean isBusy() {
|
|
|
|
|
return isUpdate;
|
2026-01-31 19:06:53 +08:00
|
|
|
}
|
|
|
|
|
|
2026-02-26 20:18:57 +08:00
|
|
|
@Override
|
|
|
|
|
public String getMusicId(String arg) {
|
|
|
|
|
if (arg.contains("id=") && !arg.contains("/?userid")) {
|
|
|
|
|
if (arg.contains("&uct2")) {
|
|
|
|
|
return Function.getString(arg, "id=", "&uct2");
|
|
|
|
|
} else if (arg.contains("&user"))
|
|
|
|
|
return Function.getString(arg, "id=", "&user");
|
|
|
|
|
else
|
|
|
|
|
return Function.getString(arg, "id=", null);
|
|
|
|
|
} else if (arg.contains("song/")) {
|
|
|
|
|
if (arg.contains("/?userid"))
|
|
|
|
|
return Function.getString(arg, "song/", "/?userid");
|
|
|
|
|
else
|
|
|
|
|
return Function.getString(arg, "song/", null);
|
|
|
|
|
} else
|
|
|
|
|
return arg;
|
2026-01-31 19:06:53 +08:00
|
|
|
}
|
|
|
|
|
|
2026-02-26 20:18:57 +08:00
|
|
|
@Override
|
|
|
|
|
public boolean checkId(String id) {
|
|
|
|
|
return Function.isInteger(id);
|
2024-04-17 22:15:12 +08:00
|
|
|
}
|
|
|
|
|
|
2023-01-06 17:27:35 +08:00
|
|
|
/**
|
|
|
|
|
* 获取音乐详情
|
|
|
|
|
*
|
|
|
|
|
* @param id 音乐ID
|
|
|
|
|
* @param player 用户名
|
|
|
|
|
* @param isList 是否是空闲列表
|
|
|
|
|
* @return 结果
|
|
|
|
|
*/
|
2023-01-06 18:15:10 +08:00
|
|
|
private SongInfoObj getMusicDetail(String id, String player, boolean isList) {
|
2021-06-09 01:38:40 +08:00
|
|
|
JsonObject params = new JsonObject();
|
2023-01-06 17:27:35 +08:00
|
|
|
params.addProperty("c", "[{\"id\":" + id + "}]");
|
2021-06-08 23:28:03 +08:00
|
|
|
|
2026-02-26 20:18:57 +08:00
|
|
|
HttpResObj res = NetApiHttpClient.post("https://music.163.com/api/v3/song/detail", params, EncryptType.WEAPI, null);
|
2026-03-04 16:05:57 +08:00
|
|
|
if (res != null && res.ok) {
|
|
|
|
|
InfoObj temp = AllMusic.gson.fromJson(res.data, InfoObj.class);
|
2023-01-06 18:15:10 +08:00
|
|
|
if (temp.isOk()) {
|
2021-06-09 01:38:40 +08:00
|
|
|
params = new JsonObject();
|
2023-01-06 17:27:35 +08:00
|
|
|
params.addProperty("ids", "[" + id + "]");
|
2021-06-09 01:38:40 +08:00
|
|
|
params.addProperty("br", "320000");
|
2026-02-26 20:18:57 +08:00
|
|
|
res = NetApiHttpClient.post("https://music.163.com/weapi/song/enhance/player/url", params, EncryptType.WEAPI, null);
|
2026-03-04 16:05:57 +08:00
|
|
|
if (res == null || !res.ok) {
|
|
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<red>版权检索失败");
|
2021-06-08 23:28:03 +08:00
|
|
|
return null;
|
|
|
|
|
}
|
2026-03-04 16:05:57 +08:00
|
|
|
TrialInfoObj obj = AllMusic.gson.fromJson(res.data, TrialInfoObj.class);
|
2023-01-06 18:15:10 +08:00
|
|
|
return new SongInfoObj(temp.getAuthor(), temp.getName(),
|
2023-01-06 17:27:35 +08:00
|
|
|
id, temp.getAlia(), player, temp.getAl(), isList, temp.getLength(),
|
2026-02-26 20:35:11 +08:00
|
|
|
temp.getPicUrl(), obj.isTrial(), obj.getFreeTrialInfo(),
|
|
|
|
|
getId());
|
2021-01-19 23:54:14 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-26 20:18:57 +08:00
|
|
|
@Override
|
|
|
|
|
public String getId() {
|
|
|
|
|
return "netapi";
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 17:27:35 +08:00
|
|
|
/**
|
|
|
|
|
* 获取音乐数据
|
|
|
|
|
*
|
|
|
|
|
* @param id 音乐ID
|
|
|
|
|
* @param player 用户名
|
|
|
|
|
* @param isList 是否是空闲列表
|
|
|
|
|
* @return 结果
|
|
|
|
|
*/
|
2023-01-06 18:15:10 +08:00
|
|
|
public SongInfoObj getMusic(String id, String player, boolean isList) {
|
|
|
|
|
SongInfoObj info = getMusicDetail(id, player, isList);
|
2021-01-19 23:54:14 +08:00
|
|
|
if (info != null)
|
|
|
|
|
return info;
|
2021-06-09 01:38:40 +08:00
|
|
|
JsonObject params = new JsonObject();
|
2023-01-06 17:27:35 +08:00
|
|
|
params.addProperty("id", id);
|
2026-02-26 20:18:57 +08:00
|
|
|
HttpResObj res = NetApiHttpClient.post("https://music.163.com/api/dj/program/detail", params, EncryptType.WEAPI, null);
|
2026-03-04 16:05:57 +08:00
|
|
|
if (res != null && res.ok) {
|
|
|
|
|
PrInfoObj temp = AllMusic.gson.fromJson(res.data, PrInfoObj.class);
|
2023-01-06 18:15:10 +08:00
|
|
|
if (temp.isOk()) {
|
|
|
|
|
return new SongInfoObj(temp.getAuthor(), temp.getName(),
|
2021-06-08 23:28:03 +08:00
|
|
|
temp.getId(), temp.getAlia(), player, "电台", isList, temp.getLength(),
|
2026-02-26 20:35:11 +08:00
|
|
|
null, false, null, getId());
|
2020-03-17 15:18:29 +08:00
|
|
|
} else {
|
2026-03-04 16:05:57 +08:00
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<red>歌曲信息获取为空");
|
2020-03-17 15:18:29 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 17:27:35 +08:00
|
|
|
/**
|
|
|
|
|
* 获取播放链接
|
|
|
|
|
*
|
|
|
|
|
* @param id 音乐ID
|
|
|
|
|
* @return 结果
|
|
|
|
|
*/
|
|
|
|
|
public String getPlayUrl(String id) {
|
2021-06-09 01:38:40 +08:00
|
|
|
JsonObject params = new JsonObject();
|
2023-01-06 17:27:35 +08:00
|
|
|
params.addProperty("ids", "[" + id + "]");
|
2026-03-28 15:36:33 +08:00
|
|
|
params.addProperty("level", "exhigh");
|
2026-02-02 22:54:19 +08:00
|
|
|
params.addProperty("encodeType", "aac");
|
2026-02-26 20:18:57 +08:00
|
|
|
HttpResObj res = NetApiHttpClient.post("https://music.163.com/weapi/song/enhance/player/url/v1", params, EncryptType.WEAPI, null);
|
2026-03-04 16:05:57 +08:00
|
|
|
if (res != null && res.ok) {
|
2020-12-23 23:40:34 +08:00
|
|
|
try {
|
2026-03-04 16:05:57 +08:00
|
|
|
TrialInfoObj obj = AllMusic.gson.fromJson(res.data, TrialInfoObj.class);
|
2021-06-09 01:38:40 +08:00
|
|
|
return obj.getUrl();
|
2020-12-23 23:40:34 +08:00
|
|
|
} catch (Exception e) {
|
2026-03-04 16:05:57 +08:00
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<red>播放连接解析错误:" + res.data);
|
2020-12-23 23:40:34 +08:00
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-17 15:18:29 +08:00
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 17:27:35 +08:00
|
|
|
/**
|
|
|
|
|
* 添加空闲歌单
|
|
|
|
|
*
|
|
|
|
|
* @param id 歌单id
|
|
|
|
|
* @param sender 发送者
|
|
|
|
|
*/
|
|
|
|
|
public void setList(String id, Object sender) {
|
2021-06-09 01:38:40 +08:00
|
|
|
final Thread thread = new Thread(() -> {
|
|
|
|
|
JsonObject params = new JsonObject();
|
2023-01-06 17:27:35 +08:00
|
|
|
params.addProperty("id", id);
|
2021-06-09 01:38:40 +08:00
|
|
|
params.addProperty("n", 100000);
|
|
|
|
|
params.addProperty("s", 8);
|
2026-02-26 20:18:57 +08:00
|
|
|
HttpResObj res = NetApiHttpClient.post("https://music.163.com/api/v6/playlist/detail", params, EncryptType.API, null);
|
2026-03-04 16:05:57 +08:00
|
|
|
if (res != null && res.ok)
|
2020-03-17 15:18:29 +08:00
|
|
|
try {
|
2024-04-17 22:15:12 +08:00
|
|
|
isUpdate = true;
|
2026-03-04 16:05:57 +08:00
|
|
|
DataObj obj = AllMusic.gson.fromJson(res.data, DataObj.class);
|
2026-02-26 20:18:57 +08:00
|
|
|
DataSql.addIdleList(obj.getPlaylist(), getId());
|
2025-09-24 22:16:24 +08:00
|
|
|
AllMusic.side.sendMessageTask(sender, AllMusic.getMessage().musicPlay.listMusic.get.replace(ARG.name, obj.getName()));
|
2020-03-17 15:18:29 +08:00
|
|
|
} catch (Exception e) {
|
2026-03-04 16:05:57 +08:00
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<red>歌曲列表获取错误");
|
2020-03-17 15:18:29 +08:00
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
2024-04-17 22:15:12 +08:00
|
|
|
isUpdate = false;
|
2021-08-25 14:19:47 +08:00
|
|
|
}, "AllMusic_setList");
|
2020-03-17 15:18:29 +08:00
|
|
|
thread.start();
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 17:27:35 +08:00
|
|
|
/**
|
|
|
|
|
* 获取歌词
|
|
|
|
|
*
|
|
|
|
|
* @param id 歌曲id
|
|
|
|
|
* @return 结果
|
|
|
|
|
*/
|
2023-01-08 16:03:28 +08:00
|
|
|
public LyricSave getLyric(String id) {
|
|
|
|
|
LyricSave lyric = new LyricSave();
|
2021-06-09 01:38:40 +08:00
|
|
|
JsonObject params = new JsonObject();
|
2023-01-06 17:27:35 +08:00
|
|
|
params.addProperty("id", id);
|
2023-01-08 14:31:20 +08:00
|
|
|
params.addProperty("cp", false);
|
|
|
|
|
params.addProperty("tv", 0);
|
|
|
|
|
params.addProperty("lv", 0);
|
|
|
|
|
params.addProperty("rv", 0);
|
|
|
|
|
params.addProperty("kv", 0);
|
|
|
|
|
params.addProperty("yv", 0);
|
|
|
|
|
params.addProperty("ytv", 0);
|
|
|
|
|
params.addProperty("rtv", 0);
|
2026-02-26 20:18:57 +08:00
|
|
|
HttpResObj res = NetApiHttpClient.post("https://interface3.music.163.com/eapi/song/lyric/v1",
|
2023-01-08 14:31:20 +08:00
|
|
|
params, EncryptType.EAPI, "/api/song/lyric/v1");
|
2026-03-04 16:05:57 +08:00
|
|
|
if (res != null && res.ok) {
|
2020-03-17 15:18:29 +08:00
|
|
|
try {
|
2026-03-04 16:05:57 +08:00
|
|
|
WLyricObj obj = AllMusic.gson.fromJson(res.data, WLyricObj.class);
|
2026-04-04 12:33:44 +08:00
|
|
|
LyricDecoder docoder = new LyricDecoder();
|
2020-03-19 20:54:55 +08:00
|
|
|
for (int times = 0; times < 3; times++) {
|
2026-04-04 12:33:44 +08:00
|
|
|
if (docoder.check(obj)) {
|
2026-03-04 16:05:57 +08:00
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<red>歌词解析错误,正在进行第" + times + "重试");
|
2020-03-19 20:54:55 +08:00
|
|
|
} else {
|
2026-04-04 12:33:44 +08:00
|
|
|
if (docoder.isHave) {
|
2024-04-17 22:15:12 +08:00
|
|
|
lyric.setHaveLyric(AllMusic.getConfig().sendLyric);
|
2026-04-04 12:33:44 +08:00
|
|
|
lyric.setLyric(docoder.getLyrics());
|
|
|
|
|
if (docoder.isHaveK) {
|
|
|
|
|
lyric.setKlyric(docoder.getKLyric());
|
2023-01-08 16:03:28 +08:00
|
|
|
}
|
2020-03-31 11:02:27 +08:00
|
|
|
}
|
2023-01-08 16:03:28 +08:00
|
|
|
return lyric;
|
2020-03-17 15:18:29 +08:00
|
|
|
}
|
|
|
|
|
Thread.sleep(1000);
|
|
|
|
|
}
|
2026-03-04 16:05:57 +08:00
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<red>歌词解析失败");
|
2020-03-17 15:18:29 +08:00
|
|
|
} catch (Exception e) {
|
2026-03-04 16:05:57 +08:00
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<red>歌词解析错误");
|
2020-03-17 15:18:29 +08:00
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-08 16:03:28 +08:00
|
|
|
return lyric;
|
2020-03-17 15:18:29 +08:00
|
|
|
}
|
|
|
|
|
|
2023-01-06 17:27:35 +08:00
|
|
|
/**
|
|
|
|
|
* 搜歌
|
|
|
|
|
*
|
|
|
|
|
* @param name 关键字
|
|
|
|
|
* @param isDefault 是否是默认方式
|
|
|
|
|
* @return 结果
|
|
|
|
|
*/
|
2023-01-06 18:15:10 +08:00
|
|
|
public SearchPageObj search(String[] name, boolean isDefault) {
|
2023-01-09 15:56:26 +08:00
|
|
|
List<SearchMusicObj> resData = new ArrayList<>();
|
2020-03-17 15:18:29 +08:00
|
|
|
int maxpage;
|
|
|
|
|
|
|
|
|
|
StringBuilder name1 = new StringBuilder();
|
2020-08-19 19:18:38 +08:00
|
|
|
for (int a = isDefault ? 0 : 1; a < name.length; a++) {
|
2020-03-17 15:18:29 +08:00
|
|
|
name1.append(name[a]).append(" ");
|
|
|
|
|
}
|
|
|
|
|
String MusicName = name1.toString();
|
|
|
|
|
MusicName = MusicName.substring(0, MusicName.length() - 1);
|
2021-06-08 23:28:03 +08:00
|
|
|
|
2021-06-09 01:38:40 +08:00
|
|
|
JsonObject params = new JsonObject();
|
|
|
|
|
params.addProperty("s", MusicName);
|
|
|
|
|
params.addProperty("type", 1);
|
|
|
|
|
params.addProperty("limit", 30);
|
|
|
|
|
params.addProperty("offset", 0);
|
2021-06-08 23:28:03 +08:00
|
|
|
|
2026-02-26 20:18:57 +08:00
|
|
|
HttpResObj res = NetApiHttpClient.post("https://music.163.com/weapi/search/get", params, EncryptType.WEAPI, null);
|
2026-03-04 16:05:57 +08:00
|
|
|
if (res != null && res.ok) {
|
|
|
|
|
SearchDataObj obj = AllMusic.gson.fromJson(res.data, SearchDataObj.class);
|
2023-01-06 18:15:10 +08:00
|
|
|
if (obj != null && obj.isOk()) {
|
2020-03-17 15:18:29 +08:00
|
|
|
List<songs> res1 = obj.getResult();
|
2023-01-09 15:56:26 +08:00
|
|
|
SearchMusicObj item;
|
2020-03-17 15:18:29 +08:00
|
|
|
for (songs temp : res1) {
|
2024-04-29 08:33:18 +08:00
|
|
|
item = new SearchMusicObj(String.valueOf(temp.getId()), temp.getName(),
|
|
|
|
|
temp.getArtists(), temp.getAlbum());
|
2020-03-17 15:18:29 +08:00
|
|
|
resData.add(item);
|
|
|
|
|
}
|
|
|
|
|
maxpage = res1.size() / 10;
|
2026-02-26 20:18:57 +08:00
|
|
|
return new SearchPageObj(resData, maxpage, getId());
|
2020-03-17 15:18:29 +08:00
|
|
|
} else {
|
2026-03-04 16:05:57 +08:00
|
|
|
AllMusic.log.data("<light_purple>[AllMusic3]<red>歌曲搜索出现错误");
|
2020-04-03 20:15:33 +08:00
|
|
|
|
2020-03-17 15:18:29 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|