diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
deleted file mode 100644
index 7ed5d035..00000000
--- a/.github/workflows/gradle.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Gradle构建
-on: [push]
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v2
- - name: 设置JDK8
- uses: actions/setup-java@v1
- with:
- java-version: 8
- - name: 设置权限
- run: chmod +x gradlew
- - name: 用Gradle构建
- run: ./gradlew shadowjar
- - name: 更新Jar
- uses: actions/upload-artifact@v2
- with:
- name: "AllMusic"
- path: build/libs
diff --git a/src/main/java/coloryr/allmusic/AllMusic.java b/core/AllMusic.java
similarity index 94%
rename from src/main/java/coloryr/allmusic/AllMusic.java
rename to core/AllMusic.java
index 2ff8bd11..543e1ef7 100644
--- a/src/main/java/coloryr/allmusic/AllMusic.java
+++ b/core/AllMusic.java
@@ -1,20 +1,20 @@
-package coloryr.allmusic;
+package coloryr.allmusic.core;
-import coloryr.allmusic.hud.DataSql;
-import coloryr.allmusic.hud.HudUtils;
-import coloryr.allmusic.music.api.APIMain;
-import coloryr.allmusic.music.play.MusicSearch;
-import coloryr.allmusic.music.play.PlayGo;
-import coloryr.allmusic.music.play.PlayMusic;
-import coloryr.allmusic.objs.ConfigObj;
-import coloryr.allmusic.objs.CookieObj;
-import coloryr.allmusic.objs.MessageObj;
-import coloryr.allmusic.objs.hud.SaveObj;
-import coloryr.allmusic.objs.music.SearchPageObj;
-import coloryr.allmusic.side.IMyLogger;
-import coloryr.allmusic.side.ISide;
-import coloryr.allmusic.sql.IEconomy;
-import coloryr.allmusic.utils.Logs;
+import coloryr.allmusic.core.hud.DataSql;
+import coloryr.allmusic.core.hud.HudUtils;
+import coloryr.allmusic.core.music.api.APIMain;
+import coloryr.allmusic.core.music.play.MusicSearch;
+import coloryr.allmusic.core.music.play.PlayGo;
+import coloryr.allmusic.core.music.play.PlayMusic;
+import coloryr.allmusic.core.objs.ConfigObj;
+import coloryr.allmusic.core.objs.CookieObj;
+import coloryr.allmusic.core.objs.MessageObj;
+import coloryr.allmusic.core.objs.hud.SaveObj;
+import coloryr.allmusic.core.objs.music.SearchPageObj;
+import coloryr.allmusic.core.side.IMyLogger;
+import coloryr.allmusic.core.side.ISide;
+import coloryr.allmusic.core.sql.IEconomy;
+import coloryr.allmusic.core.utils.Logs;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -109,7 +109,7 @@ public class AllMusic {
*/
public static void configCheck() {
if (config == null) {
- config = new ConfigObj();
+ config = ConfigObj.makeDefault();
log.warning("§d[AllMusic]§c配置文件config.json错误,已覆盖");
save();
} else if (config.check()) {
@@ -173,7 +173,7 @@ public class AllMusic {
public static ConfigObj getConfig() {
if (config == null) {
log.warning("§d[AllMusic]§c配置文件config.json错误,已使用默认配置文件");
- config = new ConfigObj();
+ config = ConfigObj.makeDefault();
}
return config;
}
diff --git a/src/main/java/coloryr/allmusic/AllMusicAPI.java b/core/AllMusicAPI.java
similarity index 92%
rename from src/main/java/coloryr/allmusic/AllMusicAPI.java
rename to core/AllMusicAPI.java
index 0a6d94fd..023fd10a 100644
--- a/src/main/java/coloryr/allmusic/AllMusicAPI.java
+++ b/core/AllMusicAPI.java
@@ -1,7 +1,7 @@
-package coloryr.allmusic;
+package coloryr.allmusic.core;
-import coloryr.allmusic.enums.HudPos;
-import coloryr.allmusic.side.ComType;
+import coloryr.allmusic.core.enums.HudPos;
+import coloryr.allmusic.core.side.ComType;
public class AllMusicAPI {
/**
diff --git a/src/main/java/coloryr/allmusic/command/CommandEX.java b/core/command/CommandEX.java
similarity index 98%
rename from src/main/java/coloryr/allmusic/command/CommandEX.java
rename to core/command/CommandEX.java
index 51ba6876..7ac17ea1 100644
--- a/src/main/java/coloryr/allmusic/command/CommandEX.java
+++ b/core/command/CommandEX.java
@@ -1,14 +1,14 @@
-package coloryr.allmusic.command;
+package coloryr.allmusic.core.command;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.hud.HudUtils;
-import coloryr.allmusic.music.play.MusicSearch;
-import coloryr.allmusic.music.play.PlayMusic;
-import coloryr.allmusic.objs.SearchMusicObj;
-import coloryr.allmusic.objs.hud.PosObj;
-import coloryr.allmusic.objs.music.MusicObj;
-import coloryr.allmusic.objs.music.SearchPageObj;
-import coloryr.allmusic.utils.Function;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.hud.HudUtils;
+import coloryr.allmusic.core.music.play.MusicSearch;
+import coloryr.allmusic.core.music.play.PlayMusic;
+import coloryr.allmusic.core.objs.SearchMusicObj;
+import coloryr.allmusic.core.objs.hud.PosObj;
+import coloryr.allmusic.core.objs.music.MusicObj;
+import coloryr.allmusic.core.objs.music.SearchPageObj;
+import coloryr.allmusic.core.utils.Function;
import java.util.Locale;
diff --git a/src/main/java/coloryr/allmusic/command/TabCommand.java b/core/command/TabCommand.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/command/TabCommand.java
rename to core/command/TabCommand.java
index 553a255a..3272c23d 100644
--- a/src/main/java/coloryr/allmusic/command/TabCommand.java
+++ b/core/command/TabCommand.java
@@ -1,6 +1,6 @@
-package coloryr.allmusic.command;
+package coloryr.allmusic.core.command;
-import coloryr.allmusic.AllMusic;
+import coloryr.allmusic.core.AllMusic;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/main/java/coloryr/allmusic/decoder/Bitstream.java b/core/decoder/Bitstream.java
similarity index 99%
rename from src/main/java/coloryr/allmusic/decoder/Bitstream.java
rename to core/decoder/Bitstream.java
index 499bb941..79de8f63 100644
--- a/src/main/java/coloryr/allmusic/decoder/Bitstream.java
+++ b/core/decoder/Bitstream.java
@@ -33,7 +33,7 @@
*----------------------------------------------------------------------
*/
-package coloryr.allmusic.decoder;
+package coloryr.allmusic.core.decoder;
import java.io.*;
diff --git a/src/main/java/coloryr/allmusic/decoder/BitstreamErrors.java b/core/decoder/BitstreamErrors.java
similarity index 97%
rename from src/main/java/coloryr/allmusic/decoder/BitstreamErrors.java
rename to core/decoder/BitstreamErrors.java
index 4e142185..57cd7049 100644
--- a/src/main/java/coloryr/allmusic/decoder/BitstreamErrors.java
+++ b/core/decoder/BitstreamErrors.java
@@ -19,7 +19,7 @@
*----------------------------------------------------------------------
*/
-package coloryr.allmusic.decoder;
+package coloryr.allmusic.core.decoder;
/**
* This interface describes all error codes that can be thrown
diff --git a/src/main/java/coloryr/allmusic/decoder/BitstreamException.java b/core/decoder/BitstreamException.java
similarity index 98%
rename from src/main/java/coloryr/allmusic/decoder/BitstreamException.java
rename to core/decoder/BitstreamException.java
index 87c0491e..c5ec3bca 100644
--- a/src/main/java/coloryr/allmusic/decoder/BitstreamException.java
+++ b/core/decoder/BitstreamException.java
@@ -18,7 +18,7 @@
*----------------------------------------------------------------------
*/
-package coloryr.allmusic.decoder;
+package coloryr.allmusic.core.decoder;
/**
* Instances of BitstreamException are thrown
diff --git a/src/main/java/coloryr/allmusic/decoder/Crc16.java b/core/decoder/Crc16.java
similarity index 98%
rename from src/main/java/coloryr/allmusic/decoder/Crc16.java
rename to core/decoder/Crc16.java
index 4fcfe002..d3acaa67 100644
--- a/src/main/java/coloryr/allmusic/decoder/Crc16.java
+++ b/core/decoder/Crc16.java
@@ -22,7 +22,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*----------------------------------------------------------------------
*/
-package coloryr.allmusic.decoder;
+package coloryr.allmusic.core.decoder;
/**
* 16-Bit CRC checksum
diff --git a/src/main/java/coloryr/allmusic/decoder/Header.java b/core/decoder/Header.java
similarity index 99%
rename from src/main/java/coloryr/allmusic/decoder/Header.java
rename to core/decoder/Header.java
index e04ee08b..4aad9a05 100644
--- a/src/main/java/coloryr/allmusic/decoder/Header.java
+++ b/core/decoder/Header.java
@@ -29,7 +29,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*----------------------------------------------------------------------
*/
-package coloryr.allmusic.decoder;
+package coloryr.allmusic.core.decoder;
/**
* Class for extracting information from a frame header.
diff --git a/src/main/java/coloryr/allmusic/decoder/JavaLayerErrors.java b/core/decoder/JavaLayerErrors.java
similarity index 97%
rename from src/main/java/coloryr/allmusic/decoder/JavaLayerErrors.java
rename to core/decoder/JavaLayerErrors.java
index af51731f..42a81bdf 100644
--- a/src/main/java/coloryr/allmusic/decoder/JavaLayerErrors.java
+++ b/core/decoder/JavaLayerErrors.java
@@ -18,7 +18,7 @@
*----------------------------------------------------------------------
*/
-package coloryr.allmusic.decoder;
+package coloryr.allmusic.core.decoder;
/**
* Exception erorr codes for components of the JavaLayer API.
diff --git a/src/main/java/coloryr/allmusic/decoder/JavaLayerException.java b/core/decoder/JavaLayerException.java
similarity index 97%
rename from src/main/java/coloryr/allmusic/decoder/JavaLayerException.java
rename to core/decoder/JavaLayerException.java
index e0f390d3..d624c3e8 100644
--- a/src/main/java/coloryr/allmusic/decoder/JavaLayerException.java
+++ b/core/decoder/JavaLayerException.java
@@ -18,7 +18,7 @@
*----------------------------------------------------------------------
*/
-package coloryr.allmusic.decoder;
+package coloryr.allmusic.core.decoder;
import java.io.PrintStream;
diff --git a/src/main/java/coloryr/allmusic/enums/EncryptType.java b/core/enums/EncryptType.java
similarity index 57%
rename from src/main/java/coloryr/allmusic/enums/EncryptType.java
rename to core/enums/EncryptType.java
index 8c255953..305bb5e2 100644
--- a/src/main/java/coloryr/allmusic/enums/EncryptType.java
+++ b/core/enums/EncryptType.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.enums;
+package coloryr.allmusic.core.enums;
public enum EncryptType {
WEAPI, EAPI, API
diff --git a/src/main/java/coloryr/allmusic/enums/HudPos.java b/core/enums/HudPos.java
similarity index 57%
rename from src/main/java/coloryr/allmusic/enums/HudPos.java
rename to core/enums/HudPos.java
index a52544af..026127b4 100644
--- a/src/main/java/coloryr/allmusic/enums/HudPos.java
+++ b/core/enums/HudPos.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.enums;
+package coloryr.allmusic.core.enums;
public enum HudPos {
info, list, lyric, pic
diff --git a/src/main/java/coloryr/allmusic/hud/DataSql.java b/core/hud/DataSql.java
similarity index 98%
rename from src/main/java/coloryr/allmusic/hud/DataSql.java
rename to core/hud/DataSql.java
index e24a1a77..b61a6556 100644
--- a/src/main/java/coloryr/allmusic/hud/DataSql.java
+++ b/core/hud/DataSql.java
@@ -1,8 +1,8 @@
-package coloryr.allmusic.hud;
+package coloryr.allmusic.core.hud;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.objs.hud.PosObj;
-import coloryr.allmusic.objs.hud.SaveObj;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.hud.PosObj;
+import coloryr.allmusic.core.objs.hud.SaveObj;
import java.io.File;
import java.sql.Connection;
diff --git a/src/main/java/coloryr/allmusic/hud/HudUtils.java b/core/hud/HudUtils.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/hud/HudUtils.java
rename to core/hud/HudUtils.java
index e4b34d47..d4c3131f 100644
--- a/src/main/java/coloryr/allmusic/hud/HudUtils.java
+++ b/core/hud/HudUtils.java
@@ -1,13 +1,13 @@
-package coloryr.allmusic.hud;
+package coloryr.allmusic.core.hud;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.enums.HudPos;
-import coloryr.allmusic.music.play.LyricSave;
-import coloryr.allmusic.music.play.PlayMusic;
-import coloryr.allmusic.objs.hud.PosObj;
-import coloryr.allmusic.objs.hud.SaveObj;
-import coloryr.allmusic.objs.music.SongInfoObj;
-import coloryr.allmusic.utils.Function;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.enums.HudPos;
+import coloryr.allmusic.core.music.play.LyricSave;
+import coloryr.allmusic.core.music.play.PlayMusic;
+import coloryr.allmusic.core.objs.hud.PosObj;
+import coloryr.allmusic.core.objs.hud.SaveObj;
+import coloryr.allmusic.core.objs.music.SongInfoObj;
+import coloryr.allmusic.core.utils.Function;
import com.google.gson.Gson;
import java.util.Map;
diff --git a/src/main/java/coloryr/allmusic/music/api/APIMain.java b/core/music/api/APIMain.java
similarity index 93%
rename from src/main/java/coloryr/allmusic/music/api/APIMain.java
rename to core/music/api/APIMain.java
index dbd0638c..f9057b23 100644
--- a/src/main/java/coloryr/allmusic/music/api/APIMain.java
+++ b/core/music/api/APIMain.java
@@ -1,22 +1,22 @@
-package coloryr.allmusic.music.api;
+package coloryr.allmusic.core.music.api;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.enums.EncryptType;
-import coloryr.allmusic.music.play.LyricDo;
-import coloryr.allmusic.music.play.LyricSave;
-import coloryr.allmusic.music.play.PlayMusic;
-import coloryr.allmusic.objs.HttpResObj;
-import coloryr.allmusic.objs.SearchMusicObj;
-import coloryr.allmusic.objs.api.music.info.InfoObj;
-import coloryr.allmusic.objs.api.music.list.DataObj;
-import coloryr.allmusic.objs.api.music.lyric.WLyricObj;
-import coloryr.allmusic.objs.api.music.search.SearchDataObj;
-import coloryr.allmusic.objs.api.music.search.songs;
-import coloryr.allmusic.objs.api.music.trialinfo.TrialInfoObj;
-import coloryr.allmusic.objs.api.program.info.PrInfoObj;
-import coloryr.allmusic.objs.music.SearchPageObj;
-import coloryr.allmusic.objs.music.SongInfoObj;
-import coloryr.allmusic.utils.Logs;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.enums.EncryptType;
+import coloryr.allmusic.core.music.play.LyricDo;
+import coloryr.allmusic.core.music.play.LyricSave;
+import coloryr.allmusic.core.music.play.PlayMusic;
+import coloryr.allmusic.core.objs.HttpResObj;
+import coloryr.allmusic.core.objs.SearchMusicObj;
+import coloryr.allmusic.core.objs.api.music.info.InfoObj;
+import coloryr.allmusic.core.objs.api.music.list.DataObj;
+import coloryr.allmusic.core.objs.api.music.lyric.WLyricObj;
+import coloryr.allmusic.core.objs.api.music.search.SearchDataObj;
+import coloryr.allmusic.core.objs.api.music.search.songs;
+import coloryr.allmusic.core.objs.api.music.trialinfo.TrialInfoObj;
+import coloryr.allmusic.core.objs.api.program.info.PrInfoObj;
+import coloryr.allmusic.core.objs.music.SearchPageObj;
+import coloryr.allmusic.core.objs.music.SongInfoObj;
+import coloryr.allmusic.core.utils.Logs;
import com.google.gson.JsonObject;
import okhttp3.Cookie;
diff --git a/src/main/java/coloryr/allmusic/music/api/CryptoUtil.java b/core/music/api/CryptoUtil.java
similarity index 97%
rename from src/main/java/coloryr/allmusic/music/api/CryptoUtil.java
rename to core/music/api/CryptoUtil.java
index 71de4f8d..2e7bb5d7 100644
--- a/src/main/java/coloryr/allmusic/music/api/CryptoUtil.java
+++ b/core/music/api/CryptoUtil.java
@@ -1,7 +1,7 @@
-package coloryr.allmusic.music.api;
+package coloryr.allmusic.core.music.api;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.objs.api.EncResObj;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.api.EncResObj;
import com.google.gson.JsonObject;
import javax.crypto.Cipher;
diff --git a/src/main/java/coloryr/allmusic/music/api/HttpClientUtil.java b/core/music/api/HttpClientUtil.java
similarity index 97%
rename from src/main/java/coloryr/allmusic/music/api/HttpClientUtil.java
rename to core/music/api/HttpClientUtil.java
index 5ee3aef8..d2eda7dd 100644
--- a/src/main/java/coloryr/allmusic/music/api/HttpClientUtil.java
+++ b/core/music/api/HttpClientUtil.java
@@ -1,9 +1,9 @@
-package coloryr.allmusic.music.api;
+package coloryr.allmusic.core.music.api;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.enums.EncryptType;
-import coloryr.allmusic.objs.HttpResObj;
-import coloryr.allmusic.objs.api.EncResObj;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.enums.EncryptType;
+import coloryr.allmusic.core.objs.HttpResObj;
+import coloryr.allmusic.core.objs.api.EncResObj;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import okhttp3.*;
diff --git a/src/main/java/coloryr/allmusic/music/api/MyCookieJar.java b/core/music/api/MyCookieJar.java
similarity index 94%
rename from src/main/java/coloryr/allmusic/music/api/MyCookieJar.java
rename to core/music/api/MyCookieJar.java
index d5241433..b9ebaa26 100644
--- a/src/main/java/coloryr/allmusic/music/api/MyCookieJar.java
+++ b/core/music/api/MyCookieJar.java
@@ -1,6 +1,6 @@
-package coloryr.allmusic.music.api;
+package coloryr.allmusic.core.music.api;
-import coloryr.allmusic.AllMusic;
+import coloryr.allmusic.core.AllMusic;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
diff --git a/src/main/java/coloryr/allmusic/music/play/LyricDo.java b/core/music/play/LyricDo.java
similarity index 95%
rename from src/main/java/coloryr/allmusic/music/play/LyricDo.java
rename to core/music/play/LyricDo.java
index cf2fb3e5..67b293bc 100644
--- a/src/main/java/coloryr/allmusic/music/play/LyricDo.java
+++ b/core/music/play/LyricDo.java
@@ -1,9 +1,9 @@
-package coloryr.allmusic.music.play;
+package coloryr.allmusic.core.music.play;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.objs.api.music.lyric.WLyricObj;
-import coloryr.allmusic.objs.music.LyricItemObj;
-import coloryr.allmusic.utils.Function;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.api.music.lyric.WLyricObj;
+import coloryr.allmusic.core.objs.music.LyricItemObj;
+import coloryr.allmusic.core.utils.Function;
import java.util.*;
import java.util.regex.Matcher;
diff --git a/src/main/java/coloryr/allmusic/music/play/LyricSave.java b/core/music/play/LyricSave.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/music/play/LyricSave.java
rename to core/music/play/LyricSave.java
index 3ff8e0d7..f53dc76b 100644
--- a/src/main/java/coloryr/allmusic/music/play/LyricSave.java
+++ b/core/music/play/LyricSave.java
@@ -1,6 +1,6 @@
-package coloryr.allmusic.music.play;
+package coloryr.allmusic.core.music.play;
-import coloryr.allmusic.objs.music.LyricItemObj;
+import coloryr.allmusic.core.objs.music.LyricItemObj;
import java.util.HashMap;
import java.util.Locale;
diff --git a/src/main/java/coloryr/allmusic/music/play/MusicSearch.java b/core/music/play/MusicSearch.java
similarity index 86%
rename from src/main/java/coloryr/allmusic/music/play/MusicSearch.java
rename to core/music/play/MusicSearch.java
index 4d97a152..9b4e206b 100644
--- a/src/main/java/coloryr/allmusic/music/play/MusicSearch.java
+++ b/core/music/play/MusicSearch.java
@@ -1,9 +1,9 @@
-package coloryr.allmusic.music.play;
+package coloryr.allmusic.core.music.play;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.command.CommandEX;
-import coloryr.allmusic.objs.music.MusicObj;
-import coloryr.allmusic.objs.music.SearchPageObj;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.command.CommandEX;
+import coloryr.allmusic.core.objs.music.MusicObj;
+import coloryr.allmusic.core.objs.music.SearchPageObj;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
diff --git a/src/main/java/coloryr/allmusic/music/play/PlayGo.java b/core/music/play/PlayGo.java
similarity index 98%
rename from src/main/java/coloryr/allmusic/music/play/PlayGo.java
rename to core/music/play/PlayGo.java
index 7297dacb..0ceadd3a 100644
--- a/src/main/java/coloryr/allmusic/music/play/PlayGo.java
+++ b/core/music/play/PlayGo.java
@@ -1,8 +1,8 @@
-package coloryr.allmusic.music.play;
+package coloryr.allmusic.core.music.play;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.hud.HudUtils;
-import coloryr.allmusic.objs.music.MusicObj;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.hud.HudUtils;
+import coloryr.allmusic.core.objs.music.MusicObj;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
diff --git a/src/main/java/coloryr/allmusic/music/play/PlayMusic.java b/core/music/play/PlayMusic.java
similarity index 95%
rename from src/main/java/coloryr/allmusic/music/play/PlayMusic.java
rename to core/music/play/PlayMusic.java
index 7df72f57..aec4624f 100644
--- a/src/main/java/coloryr/allmusic/music/play/PlayMusic.java
+++ b/core/music/play/PlayMusic.java
@@ -1,11 +1,11 @@
-package coloryr.allmusic.music.play;
+package coloryr.allmusic.core.music.play;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.decoder.Bitstream;
-import coloryr.allmusic.decoder.Header;
-import coloryr.allmusic.objs.music.MusicObj;
-import coloryr.allmusic.objs.music.SongInfoObj;
-import coloryr.allmusic.utils.Logs;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.decoder.Bitstream;
+import coloryr.allmusic.core.decoder.Header;
+import coloryr.allmusic.core.objs.music.MusicObj;
+import coloryr.allmusic.core.objs.music.SongInfoObj;
+import coloryr.allmusic.core.utils.Logs;
import java.io.BufferedInputStream;
import java.net.URL;
diff --git a/src/main/java/coloryr/allmusic/music/play/TopLyricSave.java b/core/music/play/TopLyricSave.java
similarity index 91%
rename from src/main/java/coloryr/allmusic/music/play/TopLyricSave.java
rename to core/music/play/TopLyricSave.java
index 3cb389cb..553a86f3 100644
--- a/src/main/java/coloryr/allmusic/music/play/TopLyricSave.java
+++ b/core/music/play/TopLyricSave.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.music.play;
+package coloryr.allmusic.core.music.play;
public class TopLyricSave extends LyricSave {
diff --git a/src/main/java/coloryr/allmusic/objs/ConfigObj.java b/core/objs/ConfigObj.java
similarity index 73%
rename from src/main/java/coloryr/allmusic/objs/ConfigObj.java
rename to core/objs/ConfigObj.java
index 57976897..7df3e2da 100644
--- a/src/main/java/coloryr/allmusic/objs/ConfigObj.java
+++ b/core/objs/ConfigObj.java
@@ -1,9 +1,9 @@
-package coloryr.allmusic.objs;
+package coloryr.allmusic.core.objs;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.objs.config.EconomyObj;
-import coloryr.allmusic.objs.config.FunConfigObj;
-import coloryr.allmusic.objs.hud.SaveObj;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.config.EconomyObj;
+import coloryr.allmusic.core.objs.config.FunConfigObj;
+import coloryr.allmusic.core.objs.hud.SaveObj;
import java.util.ArrayList;
import java.util.List;
@@ -141,48 +141,50 @@ public class ConfigObj {
*/
public FunConfigObj FunConfig;
- public ConfigObj() {
- MaxList = 10;
- MinVote = 3;
- Delay = 0;
- Admin = new ArrayList() {{
- this.add("CONSOLE");
+ public static ConfigObj makeDefault(){
+ return new ConfigObj(){{
+ MaxList = 10;
+ MinVote = 3;
+ Delay = 0;
+ Admin = new ArrayList() {{
+ this.add("CONSOLE");
+ }};
+ NoMusicServer = new ArrayList<>();
+ NoMusicPlayer = new ArrayList<>();
+ BanMusic = new ArrayList<>();
+ PlayList = new ArrayList<>();
+ PlayListSwitch = true;
+ PlayListRandom = true;
+ SendLyric = true;
+ NeedPermission = false;
+ DefaultHud = new SaveObj();
+
+ UseCost = false;
+ SearchCost = 20;
+ MutePlayMessage = false;
+ MuteAddMessage = false;
+ ShowInBar = false;
+ AddMusicCost = 10;
+
+ DefaultAddMusic = 0;
+ LoginUser = "";
+
+ MusicBR = "320000";
+
+ MaxMusicTime = 600;
+
+ TopPAPI = false;
+ MessageLimit = false;
+ MessageLimitSize = 40;
+
+ Economy = new EconomyObj();
+ FunConfig = new FunConfigObj();
+
+ KtvMode = true;
+ KDelay = 0;
+
+ Version = AllMusic.version;
}};
- NoMusicServer = new ArrayList<>();
- NoMusicPlayer = new ArrayList<>();
- BanMusic = new ArrayList<>();
- PlayList = new ArrayList<>();
- PlayListSwitch = true;
- PlayListRandom = true;
- SendLyric = true;
- NeedPermission = false;
- DefaultHud = new SaveObj();
-
- UseCost = false;
- SearchCost = 20;
- MutePlayMessage = false;
- MuteAddMessage = false;
- ShowInBar = false;
- AddMusicCost = 10;
-
- DefaultAddMusic = 0;
- LoginUser = "";
-
- MusicBR = "320000";
-
- MaxMusicTime = 600;
-
- TopPAPI = false;
- MessageLimit = false;
- MessageLimitSize = 40;
-
- Economy = new EconomyObj();
- FunConfig = new FunConfigObj();
-
- KtvMode = true;
- KDelay = 0;
-
- Version = AllMusic.version;
}
public void addBanID(String ID) {
diff --git a/src/main/java/coloryr/allmusic/objs/CookieObj.java b/core/objs/CookieObj.java
similarity index 82%
rename from src/main/java/coloryr/allmusic/objs/CookieObj.java
rename to core/objs/CookieObj.java
index 99527a52..28d69bbd 100644
--- a/src/main/java/coloryr/allmusic/objs/CookieObj.java
+++ b/core/objs/CookieObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs;
+package coloryr.allmusic.core.objs;
import okhttp3.Cookie;
diff --git a/src/main/java/coloryr/allmusic/objs/HttpResObj.java b/core/objs/HttpResObj.java
similarity index 84%
rename from src/main/java/coloryr/allmusic/objs/HttpResObj.java
rename to core/objs/HttpResObj.java
index 24ab88fa..103a44f7 100644
--- a/src/main/java/coloryr/allmusic/objs/HttpResObj.java
+++ b/core/objs/HttpResObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs;
+package coloryr.allmusic.core.objs;
public class HttpResObj {
public final String data;
diff --git a/src/main/java/coloryr/allmusic/objs/MessageObj.java b/core/objs/MessageObj.java
similarity index 94%
rename from src/main/java/coloryr/allmusic/objs/MessageObj.java
rename to core/objs/MessageObj.java
index bcfec413..aebc1ca2 100644
--- a/src/main/java/coloryr/allmusic/objs/MessageObj.java
+++ b/core/objs/MessageObj.java
@@ -1,8 +1,8 @@
-package coloryr.allmusic.objs;
+package coloryr.allmusic.core.objs;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.objs.message.SearchObj;
-import coloryr.allmusic.objs.message.*;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.message.SearchObj;
+import coloryr.allmusic.core.objs.message.*;
public class MessageObj {
public MusicPlayObj MusicPlay;
diff --git a/src/main/java/coloryr/allmusic/objs/SearchMusicObj.java b/core/objs/SearchMusicObj.java
similarity index 90%
rename from src/main/java/coloryr/allmusic/objs/SearchMusicObj.java
rename to core/objs/SearchMusicObj.java
index 8439d3d2..e0d70963 100644
--- a/src/main/java/coloryr/allmusic/objs/SearchMusicObj.java
+++ b/core/objs/SearchMusicObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs;
+package coloryr.allmusic.core.objs;
public class SearchMusicObj {
public final String id;
diff --git a/src/main/java/coloryr/allmusic/objs/api/EncResObj.java b/core/objs/api/EncResObj.java
similarity index 84%
rename from src/main/java/coloryr/allmusic/objs/api/EncResObj.java
rename to core/objs/api/EncResObj.java
index 303871f6..7409dad0 100644
--- a/src/main/java/coloryr/allmusic/objs/api/EncResObj.java
+++ b/core/objs/api/EncResObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api;
+package coloryr.allmusic.core.objs.api;
public class EncResObj {
public String params;
diff --git a/src/main/java/coloryr/allmusic/objs/api/music/info/InfoObj.java b/core/objs/api/music/info/InfoObj.java
similarity index 98%
rename from src/main/java/coloryr/allmusic/objs/api/music/info/InfoObj.java
rename to core/objs/api/music/info/InfoObj.java
index 6a2f6439..67ad7a31 100644
--- a/src/main/java/coloryr/allmusic/objs/api/music/info/InfoObj.java
+++ b/core/objs/api/music/info/InfoObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api.music.info;
+package coloryr.allmusic.core.objs.api.music.info;
import java.util.List;
diff --git a/src/main/java/coloryr/allmusic/objs/api/music/info/PlayObj.java b/core/objs/api/music/info/PlayObj.java
similarity index 89%
rename from src/main/java/coloryr/allmusic/objs/api/music/info/PlayObj.java
rename to core/objs/api/music/info/PlayObj.java
index 68250c58..3901e43f 100644
--- a/src/main/java/coloryr/allmusic/objs/api/music/info/PlayObj.java
+++ b/core/objs/api/music/info/PlayObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api.music.info;
+package coloryr.allmusic.core.objs.api.music.info;
import java.util.List;
diff --git a/src/main/java/coloryr/allmusic/objs/api/music/list/DataObj.java b/core/objs/api/music/list/DataObj.java
similarity index 93%
rename from src/main/java/coloryr/allmusic/objs/api/music/list/DataObj.java
rename to core/objs/api/music/list/DataObj.java
index 7aa48275..4620e9ca 100644
--- a/src/main/java/coloryr/allmusic/objs/api/music/list/DataObj.java
+++ b/core/objs/api/music/list/DataObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api.music.list;
+package coloryr.allmusic.core.objs.api.music.list;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/main/java/coloryr/allmusic/objs/api/music/lyric/WLyricObj.java b/core/objs/api/music/lyric/WLyricObj.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/objs/api/music/lyric/WLyricObj.java
rename to core/objs/api/music/lyric/WLyricObj.java
index 6cf6989d..7822afd7 100644
--- a/src/main/java/coloryr/allmusic/objs/api/music/lyric/WLyricObj.java
+++ b/core/objs/api/music/lyric/WLyricObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api.music.lyric;
+package coloryr.allmusic.core.objs.api.music.lyric;
public class WLyricObj {
private lrc lrc;
diff --git a/src/main/java/coloryr/allmusic/objs/api/music/search/SearchDataObj.java b/core/objs/api/music/search/SearchDataObj.java
similarity index 91%
rename from src/main/java/coloryr/allmusic/objs/api/music/search/SearchDataObj.java
rename to core/objs/api/music/search/SearchDataObj.java
index 7f236096..89f269e7 100644
--- a/src/main/java/coloryr/allmusic/objs/api/music/search/SearchDataObj.java
+++ b/core/objs/api/music/search/SearchDataObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api.music.search;
+package coloryr.allmusic.core.objs.api.music.search;
import java.util.List;
diff --git a/src/main/java/coloryr/allmusic/objs/api/music/search/songs.java b/core/objs/api/music/search/songs.java
similarity index 91%
rename from src/main/java/coloryr/allmusic/objs/api/music/search/songs.java
rename to core/objs/api/music/search/songs.java
index 1fe71572..8364dbd8 100644
--- a/src/main/java/coloryr/allmusic/objs/api/music/search/songs.java
+++ b/core/objs/api/music/search/songs.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api.music.search;
+package coloryr.allmusic.core.objs.api.music.search;
import java.util.List;
diff --git a/src/main/java/coloryr/allmusic/objs/api/music/trialinfo/TrialInfoObj.java b/core/objs/api/music/trialinfo/TrialInfoObj.java
similarity index 94%
rename from src/main/java/coloryr/allmusic/objs/api/music/trialinfo/TrialInfoObj.java
rename to core/objs/api/music/trialinfo/TrialInfoObj.java
index 1acabe55..009f8bf2 100644
--- a/src/main/java/coloryr/allmusic/objs/api/music/trialinfo/TrialInfoObj.java
+++ b/core/objs/api/music/trialinfo/TrialInfoObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api.music.trialinfo;
+package coloryr.allmusic.core.objs.api.music.trialinfo;
import java.util.List;
diff --git a/src/main/java/coloryr/allmusic/objs/api/music/trialinfo/freeTrialInfo.java b/core/objs/api/music/trialinfo/freeTrialInfo.java
similarity index 81%
rename from src/main/java/coloryr/allmusic/objs/api/music/trialinfo/freeTrialInfo.java
rename to core/objs/api/music/trialinfo/freeTrialInfo.java
index 45cc8a6f..3753496b 100644
--- a/src/main/java/coloryr/allmusic/objs/api/music/trialinfo/freeTrialInfo.java
+++ b/core/objs/api/music/trialinfo/freeTrialInfo.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api.music.trialinfo;
+package coloryr.allmusic.core.objs.api.music.trialinfo;
public class freeTrialInfo {
private int start;
diff --git a/src/main/java/coloryr/allmusic/objs/api/program/info/PrInfoObj.java b/core/objs/api/program/info/PrInfoObj.java
similarity index 97%
rename from src/main/java/coloryr/allmusic/objs/api/program/info/PrInfoObj.java
rename to core/objs/api/program/info/PrInfoObj.java
index b89fc173..e8692207 100644
--- a/src/main/java/coloryr/allmusic/objs/api/program/info/PrInfoObj.java
+++ b/core/objs/api/program/info/PrInfoObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.api.program.info;
+package coloryr.allmusic.core.objs.api.program.info;
public class PrInfoObj {
diff --git a/src/main/java/coloryr/allmusic/objs/config/EconomyObj.java b/core/objs/config/EconomyObj.java
similarity index 88%
rename from src/main/java/coloryr/allmusic/objs/config/EconomyObj.java
rename to core/objs/config/EconomyObj.java
index 4a341beb..c570345d 100644
--- a/src/main/java/coloryr/allmusic/objs/config/EconomyObj.java
+++ b/core/objs/config/EconomyObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.config;
+package coloryr.allmusic.core.objs.config;
public class EconomyObj {
public String MysqlUrl;
diff --git a/src/main/java/coloryr/allmusic/objs/config/FunConfigObj.java b/core/objs/config/FunConfigObj.java
similarity index 78%
rename from src/main/java/coloryr/allmusic/objs/config/FunConfigObj.java
rename to core/objs/config/FunConfigObj.java
index 6e96fd0a..7a675e24 100644
--- a/src/main/java/coloryr/allmusic/objs/config/FunConfigObj.java
+++ b/core/objs/config/FunConfigObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.config;
+package coloryr.allmusic.core.objs.config;
public class FunConfigObj {
public boolean Rain;
diff --git a/src/main/java/coloryr/allmusic/objs/hud/PosObj.java b/core/objs/hud/PosObj.java
similarity index 86%
rename from src/main/java/coloryr/allmusic/objs/hud/PosObj.java
rename to core/objs/hud/PosObj.java
index 20f4f3e7..bc1890af 100644
--- a/src/main/java/coloryr/allmusic/objs/hud/PosObj.java
+++ b/core/objs/hud/PosObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.hud;
+package coloryr.allmusic.core.objs.hud;
public class PosObj {
public int x;
diff --git a/src/main/java/coloryr/allmusic/objs/hud/SaveObj.java b/core/objs/hud/SaveObj.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/objs/hud/SaveObj.java
rename to core/objs/hud/SaveObj.java
index cc3de42b..d5345761 100644
--- a/src/main/java/coloryr/allmusic/objs/hud/SaveObj.java
+++ b/core/objs/hud/SaveObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.hud;
+package coloryr.allmusic.core.objs.hud;
public class SaveObj {
public PosObj List;
diff --git a/src/main/java/coloryr/allmusic/objs/message/AddMusicObj.java b/core/objs/message/AddMusicObj.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/objs/message/AddMusicObj.java
rename to core/objs/message/AddMusicObj.java
index 36789b29..e5c41c2c 100644
--- a/src/main/java/coloryr/allmusic/objs/message/AddMusicObj.java
+++ b/core/objs/message/AddMusicObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class AddMusicObj {
public String ListFull;
diff --git a/src/main/java/coloryr/allmusic/objs/message/ClickObj.java b/core/objs/message/ClickObj.java
similarity index 87%
rename from src/main/java/coloryr/allmusic/objs/message/ClickObj.java
rename to core/objs/message/ClickObj.java
index 3a7a567f..2df00562 100644
--- a/src/main/java/coloryr/allmusic/objs/message/ClickObj.java
+++ b/core/objs/message/ClickObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class ClickObj {
public String This;
diff --git a/src/main/java/coloryr/allmusic/objs/message/CommandObj.java b/core/objs/message/CommandObj.java
similarity index 89%
rename from src/main/java/coloryr/allmusic/objs/message/CommandObj.java
rename to core/objs/message/CommandObj.java
index 6f8a4812..6f528da6 100644
--- a/src/main/java/coloryr/allmusic/objs/message/CommandObj.java
+++ b/core/objs/message/CommandObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class CommandObj {
public String Error;
diff --git a/src/main/java/coloryr/allmusic/objs/message/CostObj.java b/core/objs/message/CostObj.java
similarity index 93%
rename from src/main/java/coloryr/allmusic/objs/message/CostObj.java
rename to core/objs/message/CostObj.java
index 5bbbd363..f02a6ef0 100644
--- a/src/main/java/coloryr/allmusic/objs/message/CostObj.java
+++ b/core/objs/message/CostObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class CostObj {
public String Search;
diff --git a/src/main/java/coloryr/allmusic/objs/message/CustomObj.java b/core/objs/message/CustomObj.java
similarity index 80%
rename from src/main/java/coloryr/allmusic/objs/message/CustomObj.java
rename to core/objs/message/CustomObj.java
index 634611bb..c555efc1 100644
--- a/src/main/java/coloryr/allmusic/objs/message/CustomObj.java
+++ b/core/objs/message/CustomObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class CustomObj {
public String Info;
diff --git a/src/main/java/coloryr/allmusic/objs/message/FunObj.java b/core/objs/message/FunObj.java
similarity index 86%
rename from src/main/java/coloryr/allmusic/objs/message/FunObj.java
rename to core/objs/message/FunObj.java
index 200bf7e2..c39776d1 100644
--- a/src/main/java/coloryr/allmusic/objs/message/FunObj.java
+++ b/core/objs/message/FunObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class FunObj {
public String Rain;
diff --git a/src/main/java/coloryr/allmusic/objs/message/HelpAdminObj.java b/core/objs/message/HelpAdminObj.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/objs/message/HelpAdminObj.java
rename to core/objs/message/HelpAdminObj.java
index c377516d..74e67bbb 100644
--- a/src/main/java/coloryr/allmusic/objs/message/HelpAdminObj.java
+++ b/core/objs/message/HelpAdminObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class HelpAdminObj {
public String Reload;
diff --git a/src/main/java/coloryr/allmusic/objs/message/HelpNormalObj.java b/core/objs/message/HelpNormalObj.java
similarity index 97%
rename from src/main/java/coloryr/allmusic/objs/message/HelpNormalObj.java
rename to core/objs/message/HelpNormalObj.java
index d13f708d..6e8fe501 100644
--- a/src/main/java/coloryr/allmusic/objs/message/HelpNormalObj.java
+++ b/core/objs/message/HelpNormalObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class HelpNormalObj {
public String Head;
diff --git a/src/main/java/coloryr/allmusic/objs/message/HelpObj.java b/core/objs/message/HelpObj.java
similarity index 91%
rename from src/main/java/coloryr/allmusic/objs/message/HelpObj.java
rename to core/objs/message/HelpObj.java
index 5665e64a..f25cecc9 100644
--- a/src/main/java/coloryr/allmusic/objs/message/HelpObj.java
+++ b/core/objs/message/HelpObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class HelpObj {
public HelpNormalObj Normal;
diff --git a/src/main/java/coloryr/allmusic/objs/message/HudListObj.java b/core/objs/message/HudListObj.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/objs/message/HudListObj.java
rename to core/objs/message/HudListObj.java
index 027b097b..0df96d75 100644
--- a/src/main/java/coloryr/allmusic/objs/message/HudListObj.java
+++ b/core/objs/message/HudListObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class HudListObj {
public String List;
diff --git a/src/main/java/coloryr/allmusic/objs/message/HudObj.java b/core/objs/message/HudObj.java
similarity index 97%
rename from src/main/java/coloryr/allmusic/objs/message/HudObj.java
rename to core/objs/message/HudObj.java
index 4a8243a5..3a05de9f 100644
--- a/src/main/java/coloryr/allmusic/objs/message/HudObj.java
+++ b/core/objs/message/HudObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class HudObj {
public String State;
diff --git a/src/main/java/coloryr/allmusic/objs/message/ListMusicObj.java b/core/objs/message/ListMusicObj.java
similarity index 92%
rename from src/main/java/coloryr/allmusic/objs/message/ListMusicObj.java
rename to core/objs/message/ListMusicObj.java
index fa2f5dc3..8eca85a8 100644
--- a/src/main/java/coloryr/allmusic/objs/message/ListMusicObj.java
+++ b/core/objs/message/ListMusicObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class ListMusicObj {
public String Head;
diff --git a/src/main/java/coloryr/allmusic/objs/message/LyricObj.java b/core/objs/message/LyricObj.java
similarity index 86%
rename from src/main/java/coloryr/allmusic/objs/message/LyricObj.java
rename to core/objs/message/LyricObj.java
index ff0789bd..79d718c0 100644
--- a/src/main/java/coloryr/allmusic/objs/message/LyricObj.java
+++ b/core/objs/message/LyricObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class LyricObj {
public String Data;
diff --git a/src/main/java/coloryr/allmusic/objs/message/MusicPlayObj.java b/core/objs/message/MusicPlayObj.java
similarity index 98%
rename from src/main/java/coloryr/allmusic/objs/message/MusicPlayObj.java
rename to core/objs/message/MusicPlayObj.java
index 2063b88a..df34eac8 100644
--- a/src/main/java/coloryr/allmusic/objs/message/MusicPlayObj.java
+++ b/core/objs/message/MusicPlayObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class MusicPlayObj {
public String StopPlay;
diff --git a/src/main/java/coloryr/allmusic/objs/message/PAPIObj.java b/core/objs/message/PAPIObj.java
similarity index 81%
rename from src/main/java/coloryr/allmusic/objs/message/PAPIObj.java
rename to core/objs/message/PAPIObj.java
index 4716cf39..db3a1975 100644
--- a/src/main/java/coloryr/allmusic/objs/message/PAPIObj.java
+++ b/core/objs/message/PAPIObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class PAPIObj {
public String NoMusic;
diff --git a/src/main/java/coloryr/allmusic/objs/message/PageObj.java b/core/objs/message/PageObj.java
similarity index 92%
rename from src/main/java/coloryr/allmusic/objs/message/PageObj.java
rename to core/objs/message/PageObj.java
index e23a0fa0..c92f67d4 100644
--- a/src/main/java/coloryr/allmusic/objs/message/PageObj.java
+++ b/core/objs/message/PageObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class PageObj {
public String Choice;
diff --git a/src/main/java/coloryr/allmusic/objs/message/SearchObj.java b/core/objs/message/SearchObj.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/objs/message/SearchObj.java
rename to core/objs/message/SearchObj.java
index 3cdbe5d9..e821d0a9 100644
--- a/src/main/java/coloryr/allmusic/objs/message/SearchObj.java
+++ b/core/objs/message/SearchObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class SearchObj {
public String NoPer;
diff --git a/src/main/java/coloryr/allmusic/objs/message/VoteObj.java b/core/objs/message/VoteObj.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/objs/message/VoteObj.java
rename to core/objs/message/VoteObj.java
index 40acee3b..7a3150b2 100644
--- a/src/main/java/coloryr/allmusic/objs/message/VoteObj.java
+++ b/core/objs/message/VoteObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.message;
+package coloryr.allmusic.core.objs.message;
public class VoteObj {
public String NoPermission;
diff --git a/src/main/java/coloryr/allmusic/objs/music/LyricItemObj.java b/core/objs/music/LyricItemObj.java
similarity index 88%
rename from src/main/java/coloryr/allmusic/objs/music/LyricItemObj.java
rename to core/objs/music/LyricItemObj.java
index a89def7d..02a0f3c6 100644
--- a/src/main/java/coloryr/allmusic/objs/music/LyricItemObj.java
+++ b/core/objs/music/LyricItemObj.java
@@ -1,6 +1,6 @@
-package coloryr.allmusic.objs.music;
+package coloryr.allmusic.core.objs.music;
-import coloryr.allmusic.AllMusic;
+import coloryr.allmusic.core.AllMusic;
public class LyricItemObj {
public String lyric;
diff --git a/src/main/java/coloryr/allmusic/objs/music/MusicObj.java b/core/objs/music/MusicObj.java
similarity index 91%
rename from src/main/java/coloryr/allmusic/objs/music/MusicObj.java
rename to core/objs/music/MusicObj.java
index d62ff873..93ebb0a5 100644
--- a/src/main/java/coloryr/allmusic/objs/music/MusicObj.java
+++ b/core/objs/music/MusicObj.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.objs.music;
+package coloryr.allmusic.core.objs.music;
public class MusicObj {
/**
diff --git a/src/main/java/coloryr/allmusic/objs/music/SearchPageObj.java b/core/objs/music/SearchPageObj.java
similarity index 91%
rename from src/main/java/coloryr/allmusic/objs/music/SearchPageObj.java
rename to core/objs/music/SearchPageObj.java
index aa97aec2..0170c970 100644
--- a/src/main/java/coloryr/allmusic/objs/music/SearchPageObj.java
+++ b/core/objs/music/SearchPageObj.java
@@ -1,6 +1,6 @@
-package coloryr.allmusic.objs.music;
+package coloryr.allmusic.core.objs.music;
-import coloryr.allmusic.objs.SearchMusicObj;
+import coloryr.allmusic.core.objs.SearchMusicObj;
import java.util.List;
diff --git a/src/main/java/coloryr/allmusic/objs/music/SongInfoObj.java b/core/objs/music/SongInfoObj.java
similarity index 95%
rename from src/main/java/coloryr/allmusic/objs/music/SongInfoObj.java
rename to core/objs/music/SongInfoObj.java
index f1de5337..bc98983a 100644
--- a/src/main/java/coloryr/allmusic/objs/music/SongInfoObj.java
+++ b/core/objs/music/SongInfoObj.java
@@ -1,7 +1,7 @@
-package coloryr.allmusic.objs.music;
+package coloryr.allmusic.core.objs.music;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.objs.api.music.trialinfo.freeTrialInfo;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.api.music.trialinfo.freeTrialInfo;
public class SongInfoObj {
/**
diff --git a/src/main/java/coloryr/allmusic/objs/music/TopSongInfoObj.java b/core/objs/music/TopSongInfoObj.java
similarity index 90%
rename from src/main/java/coloryr/allmusic/objs/music/TopSongInfoObj.java
rename to core/objs/music/TopSongInfoObj.java
index 7ee55ab2..7869fe4a 100644
--- a/src/main/java/coloryr/allmusic/objs/music/TopSongInfoObj.java
+++ b/core/objs/music/TopSongInfoObj.java
@@ -1,6 +1,6 @@
-package coloryr.allmusic.objs.music;
+package coloryr.allmusic.core.objs.music;
-import coloryr.allmusic.objs.api.music.trialinfo.freeTrialInfo;
+import coloryr.allmusic.core.objs.api.music.trialinfo.freeTrialInfo;
public class TopSongInfoObj extends SongInfoObj {
public TopSongInfoObj() {
diff --git a/src/main/java/coloryr/allmusic/side/ComType.java b/core/side/ComType.java
similarity index 91%
rename from src/main/java/coloryr/allmusic/side/ComType.java
rename to core/side/ComType.java
index cedea6ec..5095dd4b 100644
--- a/src/main/java/coloryr/allmusic/side/ComType.java
+++ b/core/side/ComType.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.side;
+package coloryr.allmusic.core.side;
public class ComType {
public static final String lyric = "[Lyric]";
diff --git a/src/main/java/coloryr/allmusic/side/IMyLogger.java b/core/side/IMyLogger.java
similarity index 71%
rename from src/main/java/coloryr/allmusic/side/IMyLogger.java
rename to core/side/IMyLogger.java
index c00c6a01..427829e4 100644
--- a/src/main/java/coloryr/allmusic/side/IMyLogger.java
+++ b/core/side/IMyLogger.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.side;
+package coloryr.allmusic.core.side;
public interface IMyLogger {
void warning(String data);
diff --git a/src/main/java/coloryr/allmusic/side/ISide.java b/core/side/ISide.java
similarity index 96%
rename from src/main/java/coloryr/allmusic/side/ISide.java
rename to core/side/ISide.java
index 0e5f6394..22fab1d4 100644
--- a/src/main/java/coloryr/allmusic/side/ISide.java
+++ b/core/side/ISide.java
@@ -1,8 +1,8 @@
-package coloryr.allmusic.side;
+package coloryr.allmusic.core.side;
-import coloryr.allmusic.AllMusic;
-import coloryr.allmusic.objs.music.MusicObj;
-import coloryr.allmusic.objs.music.SongInfoObj;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.music.MusicObj;
+import coloryr.allmusic.core.objs.music.SongInfoObj;
public abstract class ISide {
/**
diff --git a/src/main/java/coloryr/allmusic/sql/IEconomy.java b/core/sql/IEconomy.java
similarity index 76%
rename from src/main/java/coloryr/allmusic/sql/IEconomy.java
rename to core/sql/IEconomy.java
index a680e04f..385d16f3 100644
--- a/src/main/java/coloryr/allmusic/sql/IEconomy.java
+++ b/core/sql/IEconomy.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.sql;
+package coloryr.allmusic.core.sql;
public interface IEconomy {
boolean check(String name, int cost);
diff --git a/src/main/java/coloryr/allmusic/sql/MysqlConn.java b/core/sql/MysqlConn.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/sql/MysqlConn.java
rename to core/sql/MysqlConn.java
diff --git a/src/main/java/coloryr/allmusic/utils/Function.java b/core/utils/Function.java
similarity index 95%
rename from src/main/java/coloryr/allmusic/utils/Function.java
rename to core/utils/Function.java
index 26a8a23e..58809d80 100644
--- a/src/main/java/coloryr/allmusic/utils/Function.java
+++ b/core/utils/Function.java
@@ -1,4 +1,4 @@
-package coloryr.allmusic.utils;
+package coloryr.allmusic.core.utils;
import java.util.regex.Pattern;
diff --git a/src/main/java/coloryr/allmusic/utils/Logs.java b/core/utils/Logs.java
similarity index 93%
rename from src/main/java/coloryr/allmusic/utils/Logs.java
rename to core/utils/Logs.java
index 0fc7891b..60bb3af5 100644
--- a/src/main/java/coloryr/allmusic/utils/Logs.java
+++ b/core/utils/Logs.java
@@ -1,6 +1,6 @@
-package coloryr.allmusic.utils;
+package coloryr.allmusic.core.utils;
-import coloryr.allmusic.AllMusic;
+import coloryr.allmusic.core.AllMusic;
import java.io.File;
import java.io.FileWriter;
diff --git a/link.cmd b/link.cmd
new file mode 100644
index 00000000..432aa9d8
--- /dev/null
+++ b/link.cmd
@@ -0,0 +1 @@
+mklink /d "server/src/main/java/coloryr/allmusic/core" "core"
\ No newline at end of file
diff --git a/.gitattributes b/server/.gitattributes
similarity index 100%
rename from .gitattributes
rename to server/.gitattributes
diff --git a/.gitignore b/server/.gitignore
similarity index 100%
rename from .gitignore
rename to server/.gitignore
diff --git a/build.gradle b/server/build.gradle
similarity index 98%
rename from build.gradle
rename to server/build.gradle
index 5a84fd30..e3005654 100644
--- a/build.gradle
+++ b/server/build.gradle
@@ -3,7 +3,7 @@ plugins {
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '6.1.0'
}
-version = "2.18.3"
+version = "2.18.5"
repositories {
mavenCentral()
diff --git a/gradle/wrapper/gradle-wrapper.jar b/server/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
rename from gradle/wrapper/gradle-wrapper.jar
rename to server/gradle/wrapper/gradle-wrapper.jar
diff --git a/gradle/wrapper/gradle-wrapper.properties b/server/gradle/wrapper/gradle-wrapper.properties
similarity index 100%
rename from gradle/wrapper/gradle-wrapper.properties
rename to server/gradle/wrapper/gradle-wrapper.properties
diff --git a/gradlew b/server/gradlew
similarity index 100%
rename from gradlew
rename to server/gradlew
diff --git a/gradlew.bat b/server/gradlew.bat
similarity index 100%
rename from gradlew.bat
rename to server/gradlew.bat
diff --git a/settings.gradle b/server/settings.gradle
similarity index 93%
rename from settings.gradle
rename to server/settings.gradle
index 4a25ca66..90f2f75e 100644
--- a/settings.gradle
+++ b/server/settings.gradle
@@ -15,4 +15,4 @@ include 'api'
include 'services:webservice'
*/
-rootProject.name = 'AllMusic'
+rootProject.name = 'AllMusic_Server'
diff --git a/src/main/java/coloryr/allmusic/AllMusicBC.java b/server/src/main/java/coloryr/allmusic/AllMusicBC.java
similarity index 95%
rename from src/main/java/coloryr/allmusic/AllMusicBC.java
rename to server/src/main/java/coloryr/allmusic/AllMusicBC.java
index ae8b8ff2..2be5f030 100644
--- a/src/main/java/coloryr/allmusic/AllMusicBC.java
+++ b/server/src/main/java/coloryr/allmusic/AllMusicBC.java
@@ -1,5 +1,6 @@
package coloryr.allmusic;
+import coloryr.allmusic.core.AllMusic;
import coloryr.allmusic.side.bc.*;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
diff --git a/src/main/java/coloryr/allmusic/AllMusicBukkit.java b/server/src/main/java/coloryr/allmusic/AllMusicBukkit.java
similarity index 94%
rename from src/main/java/coloryr/allmusic/AllMusicBukkit.java
rename to server/src/main/java/coloryr/allmusic/AllMusicBukkit.java
index f984d5bc..b5248457 100644
--- a/src/main/java/coloryr/allmusic/AllMusicBukkit.java
+++ b/server/src/main/java/coloryr/allmusic/AllMusicBukkit.java
@@ -1,8 +1,9 @@
package coloryr.allmusic;
-import coloryr.allmusic.music.play.PlayMusic;
-import coloryr.allmusic.music.play.TopLyricSave;
-import coloryr.allmusic.objs.music.TopSongInfoObj;
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.music.play.PlayMusic;
+import coloryr.allmusic.core.music.play.TopLyricSave;
+import coloryr.allmusic.core.objs.music.TopSongInfoObj;
import coloryr.allmusic.side.bukkit.*;
import coloryr.allmusic.side.bukkit.hooks.AllMusicPAPI;
import coloryr.allmusic.side.bukkit.hooks.VaultHook;
diff --git a/src/main/java/coloryr/allmusic/AllMusicVelocity.java b/server/src/main/java/coloryr/allmusic/AllMusicVelocity.java
similarity index 98%
rename from src/main/java/coloryr/allmusic/AllMusicVelocity.java
rename to server/src/main/java/coloryr/allmusic/AllMusicVelocity.java
index 1b5a7cad..35a1b41c 100644
--- a/src/main/java/coloryr/allmusic/AllMusicVelocity.java
+++ b/server/src/main/java/coloryr/allmusic/AllMusicVelocity.java
@@ -1,5 +1,6 @@
package coloryr.allmusic;
+import coloryr.allmusic.core.AllMusic;
import coloryr.allmusic.side.velocity.*;
import com.google.inject.Inject;
import com.velocitypowered.api.command.CommandMeta;
diff --git a/src/main/java/coloryr/allmusic/bstats/MetricsBase.java b/server/src/main/java/coloryr/allmusic/bstats/MetricsBase.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/MetricsBase.java
rename to server/src/main/java/coloryr/allmusic/bstats/MetricsBase.java
diff --git a/src/main/java/coloryr/allmusic/bstats/charts/AdvancedBarChart.java b/server/src/main/java/coloryr/allmusic/bstats/charts/AdvancedBarChart.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/charts/AdvancedBarChart.java
rename to server/src/main/java/coloryr/allmusic/bstats/charts/AdvancedBarChart.java
diff --git a/src/main/java/coloryr/allmusic/bstats/charts/AdvancedPie.java b/server/src/main/java/coloryr/allmusic/bstats/charts/AdvancedPie.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/charts/AdvancedPie.java
rename to server/src/main/java/coloryr/allmusic/bstats/charts/AdvancedPie.java
diff --git a/src/main/java/coloryr/allmusic/bstats/charts/CustomChart.java b/server/src/main/java/coloryr/allmusic/bstats/charts/CustomChart.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/charts/CustomChart.java
rename to server/src/main/java/coloryr/allmusic/bstats/charts/CustomChart.java
diff --git a/src/main/java/coloryr/allmusic/bstats/charts/DrilldownPie.java b/server/src/main/java/coloryr/allmusic/bstats/charts/DrilldownPie.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/charts/DrilldownPie.java
rename to server/src/main/java/coloryr/allmusic/bstats/charts/DrilldownPie.java
diff --git a/src/main/java/coloryr/allmusic/bstats/charts/MultiLineChart.java b/server/src/main/java/coloryr/allmusic/bstats/charts/MultiLineChart.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/charts/MultiLineChart.java
rename to server/src/main/java/coloryr/allmusic/bstats/charts/MultiLineChart.java
diff --git a/src/main/java/coloryr/allmusic/bstats/charts/SimpleBarChart.java b/server/src/main/java/coloryr/allmusic/bstats/charts/SimpleBarChart.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/charts/SimpleBarChart.java
rename to server/src/main/java/coloryr/allmusic/bstats/charts/SimpleBarChart.java
diff --git a/src/main/java/coloryr/allmusic/bstats/charts/SimplePie.java b/server/src/main/java/coloryr/allmusic/bstats/charts/SimplePie.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/charts/SimplePie.java
rename to server/src/main/java/coloryr/allmusic/bstats/charts/SimplePie.java
diff --git a/src/main/java/coloryr/allmusic/bstats/charts/SingleLineChart.java b/server/src/main/java/coloryr/allmusic/bstats/charts/SingleLineChart.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/charts/SingleLineChart.java
rename to server/src/main/java/coloryr/allmusic/bstats/charts/SingleLineChart.java
diff --git a/src/main/java/coloryr/allmusic/bstats/config/MetricsConfig.java b/server/src/main/java/coloryr/allmusic/bstats/config/MetricsConfig.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/config/MetricsConfig.java
rename to server/src/main/java/coloryr/allmusic/bstats/config/MetricsConfig.java
diff --git a/src/main/java/coloryr/allmusic/bstats/json/JsonObjectBuilder.java b/server/src/main/java/coloryr/allmusic/bstats/json/JsonObjectBuilder.java
similarity index 100%
rename from src/main/java/coloryr/allmusic/bstats/json/JsonObjectBuilder.java
rename to server/src/main/java/coloryr/allmusic/bstats/json/JsonObjectBuilder.java
diff --git a/server/src/main/java/coloryr/allmusic/core/AllMusic.java b/server/src/main/java/coloryr/allmusic/core/AllMusic.java
new file mode 100644
index 00000000..543e1ef7
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/AllMusic.java
@@ -0,0 +1,481 @@
+package coloryr.allmusic.core;
+
+import coloryr.allmusic.core.hud.DataSql;
+import coloryr.allmusic.core.hud.HudUtils;
+import coloryr.allmusic.core.music.api.APIMain;
+import coloryr.allmusic.core.music.play.MusicSearch;
+import coloryr.allmusic.core.music.play.PlayGo;
+import coloryr.allmusic.core.music.play.PlayMusic;
+import coloryr.allmusic.core.objs.ConfigObj;
+import coloryr.allmusic.core.objs.CookieObj;
+import coloryr.allmusic.core.objs.MessageObj;
+import coloryr.allmusic.core.objs.hud.SaveObj;
+import coloryr.allmusic.core.objs.music.SearchPageObj;
+import coloryr.allmusic.core.side.IMyLogger;
+import coloryr.allmusic.core.side.ISide;
+import coloryr.allmusic.core.sql.IEconomy;
+import coloryr.allmusic.core.utils.Logs;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.*;
+
+public class AllMusic {
+ public static final Gson gson = new Gson();
+
+ /**
+ * 客户端插件信道名
+ */
+ public static final String channel = "allmusic:channel";
+ /**
+ * BC插件信道名
+ */
+ public static final String channelBC = "allmusic:channelbc";
+ /**
+ * 插件版本号
+ */
+ public static final String version = "2.18.3";
+ /**
+ * 配置文件版本号
+ */
+ public static final String configVersion = "103";
+ /**
+ * 语言文件配置版本号
+ */
+ public static final String messageVersion = "103";
+ /**
+ * 搜歌结果
+ * 玩家名 结果
+ */
+ private static final Map searchSave = new HashMap<>();
+ /**
+ * 投票的玩家
+ */
+ private static final List votePlayer = new ArrayList<>();
+ /**
+ * 正在播放的玩家
+ */
+ private static final List nowPlayPlayer = new ArrayList<>();
+ /**
+ * 日志
+ */
+ public static IMyLogger log;
+ /**
+ * 服务器端操作
+ */
+ public static ISide side;
+ /**
+ * 是否在运行
+ */
+ public static boolean isRun;
+ /**
+ * Cookie对象
+ */
+ public static CookieObj cookie;
+ /**
+ * 经济插件对象
+ */
+ public static IEconomy economy;
+ /**
+ * 网易API
+ */
+ private static APIMain apiMusic;
+ /**
+ * 配置对象
+ */
+ private static ConfigObj config;
+ /**
+ * 语言对象
+ */
+ private static MessageObj message;
+ /**
+ * 配置文件
+ */
+ private static File configFile;
+ /**
+ * Cookie文件
+ */
+ private static File cookieFile;
+ /**
+ * 语言文件
+ */
+ private static File messageFile;
+
+ /**
+ * 检查配置文件完整性
+ */
+ public static void configCheck() {
+ if (config == null) {
+ config = ConfigObj.makeDefault();
+ log.warning("§d[AllMusic]§c配置文件config.json错误,已覆盖");
+ save();
+ } else if (config.check()) {
+ log.warning("§d[AllMusic]§c配置文件config.json错误,已覆盖");
+ save();
+ }
+ }
+
+ /**
+ * 检查语言文件完整性
+ */
+ private static void messageCheck() {
+ if (message == null) {
+ message = new MessageObj();
+ log.warning("§d[AllMusic]§c配置文件message.json错误,已覆盖");
+ save();
+ } else if (message.check()) {
+ log.warning("§d[AllMusic]§c配置文件message.json错误,已覆盖");
+ save();
+ }
+ }
+
+ /**
+ * 检查是否需要
+ *
+ * @param name 用户名
+ * @param server 服务器名
+ * @param checkList 是否检查正在播放的列表
+ * @return 结果
+ */
+ public static boolean isOK(String name, String server, boolean checkList) {
+ try {
+ if (AllMusic.getConfig().NoMusicServer
+ .contains(server))
+ return true;
+ if (server != null && AllMusic.getConfig().NoMusicPlayer.contains(name))
+ return true;
+ if (!checkList)
+ return false;
+ return AllMusic.containNowPlay(name);
+ } catch (NoSuchElementException e) {
+ return true;
+ }
+ }
+
+ /**
+ * 是否存在正在播放的玩家
+ *
+ * @param player 用户名
+ * @return 是否存在
+ */
+ public static boolean containNowPlay(String player) {
+ return !nowPlayPlayer.contains(player);
+ }
+
+ /**
+ * 获取配置文件
+ *
+ * @return 配置对象
+ */
+ public static ConfigObj getConfig() {
+ if (config == null) {
+ log.warning("§d[AllMusic]§c配置文件config.json错误,已使用默认配置文件");
+ config = ConfigObj.makeDefault();
+ }
+ return config;
+ }
+
+ /**
+ * 获取语言文件
+ *
+ * @return 语言对象
+ */
+ public static MessageObj getMessage() {
+ if (message == null) {
+ log.warning("§d[AllMusic]§c配置文件message.json错误,已使用默认配置文件");
+ message = new MessageObj();
+ }
+ return message;
+ }
+
+ /**
+ * 添加搜歌结果
+ *
+ * @param player 用户名
+ * @param page 结果
+ */
+ public static void addSearch(String player, SearchPageObj page) {
+ searchSave.put(player, page);
+ }
+
+ /**
+ * 获取搜歌结果
+ *
+ * @param player 用户名
+ * @return 结果
+ */
+ public static SearchPageObj getSearch(String player) {
+ return searchSave.get(player);
+ }
+
+ /**
+ * 删除搜歌结果
+ *
+ * @param player 用户名
+ */
+ public static void removeSearch(String player) {
+ searchSave.remove(player);
+ }
+
+ /**
+ * 添加投票的玩家
+ *
+ * @param player 用户名
+ */
+ public static void addVote(String player) {
+ if (!votePlayer.contains(player))
+ votePlayer.add(player);
+ }
+
+ /**
+ * 获取投票数量
+ *
+ * @return 数量
+ */
+ public static int getVoteCount() {
+ return votePlayer.size();
+ }
+
+ /**
+ * 清空投票
+ */
+ public static void clearVote() {
+ votePlayer.clear();
+ }
+
+ /**
+ * 是否已经投票了
+ *
+ * @param player 用户名
+ * @return 结果
+ */
+ public static boolean containVote(String player) {
+ return votePlayer.contains(player);
+ }
+
+ /**
+ * 添加正在播放的玩家
+ *
+ * @param player 用户名
+ */
+ public static void addNowPlayPlayer(String player) {
+ if (!nowPlayPlayer.contains(player))
+ nowPlayPlayer.add(player);
+ }
+
+ /**
+ * 删除正在播放的玩家
+ *
+ * @param player 用户名
+ */
+ public static void removeNowPlayPlayer(String player) {
+ nowPlayPlayer.remove(player);
+ }
+
+ /**
+ * 清空正在播放玩家的列表
+ */
+ public static void clearNowPlayer() {
+ nowPlayPlayer.clear();
+ }
+
+ /**
+ * 保存配置文件
+ */
+ public static void save() {
+ try {
+ String data = new GsonBuilder().setPrettyPrinting().create().toJson(config);
+ FileOutputStream out = new FileOutputStream(configFile);
+ OutputStreamWriter write = new OutputStreamWriter(
+ out, StandardCharsets.UTF_8);
+ write.write(data);
+ write.close();
+ data = new GsonBuilder().setPrettyPrinting().create().toJson(message);
+ out = new FileOutputStream(messageFile);
+ write = new OutputStreamWriter(
+ out, StandardCharsets.UTF_8);
+ write.write(data);
+ write.close();
+ } catch (Exception e) {
+ log.warning("§d[AllMusic]§c配置文件保存错误");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 保存Cookie
+ */
+ public static void saveCookie() {
+ try {
+ String data = new GsonBuilder().setPrettyPrinting().create().toJson(cookie);
+ FileOutputStream out = new FileOutputStream(cookieFile);
+ OutputStreamWriter write = new OutputStreamWriter(
+ out, StandardCharsets.UTF_8);
+ write.write(data);
+ write.close();
+ } catch (Exception e) {
+ log.warning("§d[AllMusic]§c配置文件保存错误");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 启动插件
+ */
+ public static void start() {
+ PlayMusic.start();
+ PlayGo.start();
+ MusicSearch.start();
+ DataSql.start();
+
+ log.info("§d[AllMusic]§e已启动-" + version);
+ }
+
+ /**
+ * 停止插件
+ */
+ public static void stop() {
+ try {
+ clearVote();
+ Logs.stop();
+ side.sendStop();
+ MusicSearch.stop();
+ PlayMusic.stop();
+ PlayGo.stop();
+ DataSql.stop();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ log.info("§d[AllMusic]§2§e已停止,感谢使用");
+ }
+
+ /**
+ * 获取音乐API
+ *
+ * @return 音乐API
+ */
+ public static APIMain getMusicApi() {
+ if (apiMusic == null) {
+ AllMusic.apiMusic = new APIMain();
+ }
+ return apiMusic;
+ }
+
+ /**
+ * 加载配置文件
+ */
+ private static void loadConfig() {
+ try {
+ InputStreamReader reader = new InputStreamReader(
+ Files.newInputStream(configFile.toPath()), StandardCharsets.UTF_8);
+ BufferedReader bf = new BufferedReader(reader);
+ config = new Gson().fromJson(bf, ConfigObj.class);
+ bf.close();
+ reader.close();
+ configCheck();
+
+ reader = new InputStreamReader(Files.newInputStream(messageFile.toPath()), StandardCharsets.UTF_8);
+ bf = new BufferedReader(reader);
+ message = new Gson().fromJson(bf, MessageObj.class);
+ bf.close();
+ reader.close();
+ messageCheck();
+
+ log.info("§d[AllMusic]§e当前语言配置文件版本为:" + messageVersion
+ + ",你的语言文件版本为:" + config.Version);
+
+ if (!message.Version.equalsIgnoreCase(messageVersion)) {
+ log.warning("§d[AllMusic]§c语言文件版本号错误,运行可能会发生问题,请删除后重载");
+ }
+
+ reader = new InputStreamReader(Files.newInputStream(cookieFile.toPath()), StandardCharsets.UTF_8);
+ bf = new BufferedReader(reader);
+ cookie = new Gson().fromJson(bf, CookieObj.class);
+ bf.close();
+ reader.close();
+ if (cookie == null) {
+ cookie = new CookieObj();
+ saveCookie();
+ }
+
+ log.info("§d[AllMusic]§e当前插件配置文件版本为:" + configVersion
+ + ",你的配置文件版本为:" + config.Version);
+
+ if (!AllMusic.configVersion.equalsIgnoreCase(config.Version)) {
+ log.warning("§d[AllMusic]§c请及时更新配置文件");
+ }
+ } catch (Exception e) {
+ log.warning("§d[AllMusic]§c读取配置文件错误");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 加入时播放
+ *
+ * @param player 用户名
+ */
+ public static void joinPlay(String player) {
+ if (getConfig().NoMusicPlayer.contains(player))
+ return;
+
+ AllMusic.side.runTask(() -> {
+ if (PlayMusic.nowPlayMusic != null) {
+ SaveObj obj = HudUtils.get(player);
+ String data = gson.toJson(obj);
+ AllMusic.side.send(data, player);
+ AllMusic.side.sendMusic(player, PlayGo.url);
+ if (!PlayMusic.nowPlayMusic.isUrl()) {
+ AllMusic.side.runTask(() ->
+ AllMusic.side.sendPic(player, PlayMusic.nowPlayMusic.getPicUrl()), 15);
+ }
+ AllMusic.side.runTask(() ->
+ AllMusic.side.sendPos(player, PlayMusic.musicNowTime + 1000), 40);
+ }
+ }, 40);
+ }
+
+ /**
+ * 读取配置文件
+ *
+ * @param file 配置文件文件夹
+ */
+ public void init(File file) {
+ log.info("§d[AllMusic]§2§e正在启动,感谢使用,本插件交流群:571239090");
+ try {
+ if (!file.exists())
+ file.mkdir();
+ if (configFile == null)
+ configFile = new File(file, "config.json");
+ if (messageFile == null)
+ messageFile = new File(file, "message.json");
+ if (cookieFile == null)
+ cookieFile = new File(file, "cookie.json");
+ if (Logs.file == null)
+ Logs.file = new File(file, "logs.log");
+ if (DataSql.sqlFile == null)
+ DataSql.sqlFile = new File(file, "data.db");
+ if (!configFile.exists()) {
+ Files.copy(this.getClass().getResourceAsStream("/config.json"), configFile.toPath());
+ }
+ if (!messageFile.exists()) {
+ Files.copy(this.getClass().getResourceAsStream("/message.json"), messageFile.toPath());
+ }
+ if (!cookieFile.exists()) {
+ cookieFile.createNewFile();
+ }
+ if (!Logs.file.exists()) {
+ Logs.file.createNewFile();
+ }
+ loadConfig();
+ isRun = true;
+ } catch (IOException e) {
+ isRun = false;
+ log.warning("§d[AllMusic]§c启动失败");
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/AllMusicAPI.java b/server/src/main/java/coloryr/allmusic/core/AllMusicAPI.java
new file mode 100644
index 00000000..023fd10a
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/AllMusicAPI.java
@@ -0,0 +1,68 @@
+package coloryr.allmusic.core;
+
+import coloryr.allmusic.core.enums.HudPos;
+import coloryr.allmusic.core.side.ComType;
+
+public class AllMusicAPI {
+ /**
+ * 发送播放音乐
+ *
+ * @param name 用户名
+ * @param url 链接
+ */
+ public static void playMusic(String name, String url) {
+ AllMusic.side.send(name, ComType.play + url);
+ }
+
+ /**
+ * 更新玩家Hud数据
+ *
+ * @param name 用户名
+ * @param pos 位置
+ * @param data 数据
+ */
+ public static void sendHud(String name, HudPos pos, String data) {
+ String temp = getType(pos);
+ if (temp == null)
+ return;
+ AllMusic.side.send(name, temp + data);
+ }
+
+ /**
+ * 发送图片
+ *
+ * @param name 用户名
+ * @param url 图片地址
+ */
+ public static void sendPic(String name, String url) {
+ AllMusic.side.send(name, ComType.img + url);
+ }
+
+ /**
+ * 停止播放
+ *
+ * @param name 用户名
+ */
+ public static void sendStop(String name) {
+ AllMusic.side.sendStop(name);
+ }
+
+ /**
+ * 获取位置字符串
+ *
+ * @param pos 位置
+ * @return 字符串
+ */
+ private static String getType(HudPos pos) {
+ switch (pos) {
+ case info:
+ return ComType.info;
+ case lyric:
+ return ComType.lyric;
+ case list:
+ return ComType.list;
+ }
+
+ return null;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/command/CommandEX.java b/server/src/main/java/coloryr/allmusic/core/command/CommandEX.java
new file mode 100644
index 00000000..7ac17ea1
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/command/CommandEX.java
@@ -0,0 +1,510 @@
+package coloryr.allmusic.core.command;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.hud.HudUtils;
+import coloryr.allmusic.core.music.play.MusicSearch;
+import coloryr.allmusic.core.music.play.PlayMusic;
+import coloryr.allmusic.core.objs.SearchMusicObj;
+import coloryr.allmusic.core.objs.hud.PosObj;
+import coloryr.allmusic.core.objs.music.MusicObj;
+import coloryr.allmusic.core.objs.music.SearchPageObj;
+import coloryr.allmusic.core.utils.Function;
+
+import java.util.Locale;
+
+public class CommandEX {
+ /**
+ * 搜索音乐
+ *
+ * @param sender 发送者
+ * @param name 用户名
+ * @param args 参数
+ * @param isDefault 是否是默认点歌方式
+ */
+ private static void searchMusic(Object sender, String name, String[] args, boolean isDefault) {
+ MusicObj obj = new MusicObj();
+ obj.sender = sender;
+ obj.name = name;
+ obj.args = args;
+ obj.isDefault = isDefault;
+
+ if (AllMusic.side.onMusicAdd(sender, obj)) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().AddMusic.Cancel);
+ return;
+ }
+
+ MusicSearch.addSearch(obj);
+ }
+
+ /**
+ * 检查金额是否够
+ *
+ * @param sender 发送者
+ * @param name 用户名
+ * @param cost 金额
+ * @return 结果
+ */
+ private static boolean checkMoney(Object sender, String name, int cost) {
+ if (!AllMusic.getConfig().UseCost || AllMusic.economy == null) {
+ return false;
+ }
+
+ if (!AllMusic.economy.check(name, cost)) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Cost.NoMoney);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 扣钱
+ *
+ * @param sender 发送者
+ * @param name 用户名
+ * @param cost 金额
+ * @param message 结果消息
+ * @return 结果
+ */
+ private static boolean cost(Object sender, String name, int cost, String message) {
+ if (!AllMusic.getConfig().UseCost || AllMusic.economy == null) {
+ return false;
+ }
+
+ if (AllMusic.economy.cost(name, cost)) {
+ AllMusic.side.sendMessage(sender, message
+ .replace("%Cost%", "" + cost));
+ return false;
+ } else {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Cost.CostFail);
+ return true;
+ }
+ }
+
+ /**
+ * 添加音乐
+ *
+ * @param sender 发送者
+ * @param name 用户名
+ * @param args 参数
+ */
+ private static void addMusic(Object sender, String name, String[] args) {
+ String musicID;
+ if (args[0].contains("id=") && !args[0].contains("/?userid")) {
+ if (args[0].contains("&user"))
+ musicID = Function.getString(args[0], "id=", "&user");
+ else
+ musicID = Function.getString(args[0], "id=", null);
+ } else if (args[0].contains("song/")) {
+ if (args[0].contains("/?userid"))
+ musicID = Function.getString(args[0], "song/", "/?userid");
+ else
+ musicID = Function.getString(args[0], "song/", null);
+ } else
+ musicID = args[0];
+ if (Function.isInteger(musicID)) {
+ if (PlayMusic.getSize() >= AllMusic.getConfig().MaxList) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().AddMusic.ListFull);
+ } else if (AllMusic.getConfig().BanMusic.contains(musicID)) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().AddMusic.BanMusic);
+ } else if (PlayMusic.isHave(musicID)) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().AddMusic.ExistMusic);
+ } else {
+ if (checkMoney(sender, name, AllMusic.getConfig().AddMusicCost)) {
+ return;
+ }
+ if (cost(sender, name, AllMusic.getConfig().AddMusicCost,
+ AllMusic.getMessage().Cost.AddMusic)) {
+ return;
+ }
+ AllMusic.getConfig().RemoveNoMusicPlayer(name);
+ if (AllMusic.side.needPlay()) {
+ MusicObj obj = new MusicObj();
+ obj.sender = sender;
+ obj.id = musicID;
+ obj.name = name;
+ obj.isDefault = false;
+
+ if (AllMusic.side.onMusicAdd(sender, obj)) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().AddMusic.Cancel);
+ return;
+ }
+
+ PlayMusic.addTask(obj);
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().AddMusic.Success);
+ } else
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().AddMusic.NoPlayer);
+ }
+ } else
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().AddMusic.NoID);
+ }
+
+ /**
+ * 展示搜歌结果
+ *
+ * @param sender 发送者
+ * @param search 搜歌结果
+ */
+ public static void showSearch(Object sender, SearchPageObj search) {
+ int index = search.getIndex();
+ SearchMusicObj item;
+ String info;
+ AllMusic.side.sendMessage(sender, "");
+ if (search.haveLastPage()) {
+ AllMusic.side.sendMessageRun(sender, "§d[AllMusic]§2输入/music lastpage上一页",
+ AllMusic.getMessage().Page.Last, "/music lastpage");
+ }
+ for (int a = 0; a < index; a++) {
+ item = search.getRes(a + search.getPage() * 10);
+ info = AllMusic.getMessage().Page.Choice;
+ info = info.replace("%index%", "" + (a + 1))
+ .replace("%MusicName%", item.name)
+ .replace("%MusicAuthor%", item.author)
+ .replace("%MusicAl%", item.al);
+ AllMusic.side.sendMessageRun(sender, info,
+ AllMusic.getMessage().Click.This, "/music select " + (a + 1));
+ }
+ if (search.haveNextPage()) {
+ AllMusic.side.sendMessageRun(sender, "§d[AllMusic]§2输入/music nextpage下一页",
+ AllMusic.getMessage().Page.Next, "/music nextpage");
+ }
+ AllMusic.side.sendMessage(sender, "");
+ }
+
+ /**
+ * 执行命令
+ *
+ * @param sender 发送者
+ * @param name 用户名
+ * @param args 参数
+ */
+ public static void ex(Object sender, String name, String[] args) {
+ if (args.length == 0) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.Error);
+ return;
+ } else if (args[0].equalsIgnoreCase("help")) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Help.Normal.Head);
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Normal.Base,
+ AllMusic.getMessage().Click.Check, "/music ");
+ AllMusic.side.sendMessageRun(sender, AllMusic.getMessage().Help.Normal.Stop,
+ AllMusic.getMessage().Click.This, "/music stop");
+ AllMusic.side.sendMessageRun(sender, AllMusic.getMessage().Help.Normal.List,
+ AllMusic.getMessage().Click.This, "/music list");
+ AllMusic.side.sendMessageRun(sender, AllMusic.getMessage().Help.Normal.Vote,
+ AllMusic.getMessage().Click.This, "/music vote");
+ AllMusic.side.sendMessageRun(sender, AllMusic.getMessage().Help.Normal.NoMusic,
+ AllMusic.getMessage().Click.This, "/music nomusic");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Normal.Search,
+ AllMusic.getMessage().Click.Check, "/music search ");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Normal.Select,
+ AllMusic.getMessage().Click.Check, "/music select ");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Normal.Hud1,
+ AllMusic.getMessage().Click.Check, "/music hud enable ");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Normal.Hud2,
+ AllMusic.getMessage().Click.Check, "/music hud ");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Normal.Hud3,
+ AllMusic.getMessage().Click.Check, "/music hud picsize ");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Normal.Hud4,
+ AllMusic.getMessage().Click.Check, "/music hud picrotate ");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Normal.Hud5,
+ AllMusic.getMessage().Click.Check, "/music hud picrotatespeed ");
+ if (AllMusic.getConfig().Admin.contains(name)) {
+ AllMusic.side.sendMessageRun(sender, AllMusic.getMessage().Help.Admin.Reload,
+ AllMusic.getMessage().Click.This, "/music reload");
+ AllMusic.side.sendMessageRun(sender, AllMusic.getMessage().Help.Admin.Next,
+ AllMusic.getMessage().Click.This, "/music next");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Admin.Ban,
+ AllMusic.getMessage().Click.Check, "/music ban ");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Admin.Url,
+ AllMusic.getMessage().Click.Check, "/music url ");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Admin.Delete,
+ AllMusic.getMessage().Click.Check, "/music delete ");
+ AllMusic.side.sendMessageSuggest(sender, AllMusic.getMessage().Help.Admin.AddList,
+ AllMusic.getMessage().Click.Check, "/music addlist ");
+ AllMusic.side.sendMessageRun(sender, AllMusic.getMessage().Help.Admin.ClearList,
+ AllMusic.getMessage().Click.This, "/music clearlist");
+ AllMusic.side.sendMessageRun(sender, AllMusic.getMessage().Help.Admin.Login,
+ AllMusic.getMessage().Click.This, "/music login");
+ }
+ return;
+ } else if (args[0].equalsIgnoreCase("stop")) {
+ AllMusic.side.clearHud(name);
+ AllMusic.side.sendStop(name);
+ HudUtils.clearHud(name);
+ AllMusic.removeNowPlayPlayer(name);
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().MusicPlay.StopPlay);
+ return;
+ } else if (args[0].equalsIgnoreCase("list")) {
+ if (PlayMusic.nowPlayMusic == null || PlayMusic.nowPlayMusic.isNull()) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().MusicPlay.NoMusic);
+ } else {
+ String info = AllMusic.getMessage().MusicPlay.Play;
+ info = info.replace("%MusicName%", PlayMusic.nowPlayMusic.getName())
+ .replace("%MusicAuthor%", PlayMusic.nowPlayMusic.getAuthor())
+ .replace("%MusicAl%", PlayMusic.nowPlayMusic.getAl())
+ .replace("%MusicAlia%", PlayMusic.nowPlayMusic.getAlia())
+ .replace("%PlayerName%", PlayMusic.nowPlayMusic.getCall());
+ AllMusic.side.sendMessage(sender, info);
+ }
+ if (PlayMusic.getSize() == 0) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().MusicPlay.NoPlay);
+ } else {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().MusicPlay.ListMusic.Head
+ .replace("&Count&", "" + PlayMusic.getSize()));
+ AllMusic.side.sendMessage(sender, PlayMusic.getAllList());
+ }
+ return;
+ } else if (args[0].equalsIgnoreCase("vote")) {
+ if (AllMusic.getConfig().NeedPermission &&
+ AllMusic.side.checkPermission(name, "allmusic.vote")) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Vote.NoPermission);
+ return;
+ }
+ if (PlayMusic.getSize() == 0 && AllMusic.getConfig().PlayList.size() == 0) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().MusicPlay.NoPlay);
+ } else if (PlayMusic.voteTime == 0) {
+ PlayMusic.voteTime = 30;
+ AllMusic.addVote(name);
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Vote.DoVote);
+ String data = AllMusic.getMessage().Vote.BQ;
+ AllMusic.side.bq(data.replace("%PlayerName%", name));
+ } else if (PlayMusic.voteTime > 0) {
+ if (!AllMusic.containVote(name)) {
+ AllMusic.addVote(name);
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Vote.Agree);
+ String data = AllMusic.getMessage().Vote.BQAgree;
+ data = data.replace("%PlayerName%", name)
+ .replace("%Count%", "" + AllMusic.getVoteCount());
+ AllMusic.side.bq(data);
+ } else {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Vote.ARAgree);
+ }
+ }
+ AllMusic.getConfig().RemoveNoMusicPlayer(name);
+ return;
+ } else if (args[0].equalsIgnoreCase("nomusic")) {
+ AllMusic.side.sendStop(name);
+ AllMusic.side.clearHud(name);
+ AllMusic.getConfig().AddNoMusicPlayer(name);
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().MusicPlay.NoPlayMusic);
+ return;
+ } else if (args[0].equalsIgnoreCase("search") && args.length >= 2) {
+ if (AllMusic.getConfig().NeedPermission &&
+ AllMusic.side.checkPermission(name, "allmusic.search")) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.NoPer);
+ return;
+ }
+ if (checkMoney(sender, name, AllMusic.getConfig().SearchCost)) {
+ return;
+ }
+ if (cost(sender, name, AllMusic.getConfig().SearchCost,
+ AllMusic.getMessage().Cost.Search)) {
+ return;
+ }
+
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.StartSearch);
+ searchMusic(sender, name, args, false);
+ return;
+ } else if (args[0].equalsIgnoreCase("select") && args.length == 2) {
+ if (AllMusic.getConfig().NeedPermission &&
+ AllMusic.side.checkPermission(name, "allmusic.search")) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.NoPer);
+ return;
+ }
+ SearchPageObj obj = AllMusic.getSearch(name);
+ if (obj == null) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.NoSearch);
+ } else if (!args[1].isEmpty() && Function.isInteger(args[1])) {
+ int a = Integer.parseInt(args[1]);
+ if (a == 0) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.ErrorNum);
+ return;
+ }
+ String[] ID = new String[1];
+ ID[0] = obj.getSong((obj.getPage() * 10) + (a - 1));
+ AllMusic.side.sendMessage(sender,
+ AllMusic.getMessage().Search.Chose.replace("%Num%", "" + a));
+ addMusic(sender, name, ID);
+ AllMusic.removeSearch(name);
+ } else {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.ErrorNum);
+ }
+ return;
+ } else if (args[0].equalsIgnoreCase("nextpage")) {
+ if (AllMusic.getConfig().NeedPermission &&
+ AllMusic.side.checkPermission(name, "allmusic.search")) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.NoPer);
+ return;
+ }
+ SearchPageObj obj = AllMusic.getSearch(name);
+ if (obj == null) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.NoSearch);
+ } else if (obj.nextPage()) {
+ showSearch(sender, obj);
+ } else {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.CantNext);
+ }
+ return;
+ } else if (args[0].equalsIgnoreCase("lastpage")) {
+ if (AllMusic.getConfig().NeedPermission &&
+ AllMusic.side.checkPermission(name, "allmusic.search")) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.NoPer);
+ return;
+ }
+ SearchPageObj obj = AllMusic.getSearch(name);
+ if (obj == null) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.NoSearch);
+ } else if (obj.lastPage()) {
+ showSearch(sender, obj);
+ } else {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Search.CantLast);
+ }
+ return;
+ } else if (args[0].equalsIgnoreCase("hud")) {
+ if (args.length == 1) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.Error);
+ } else {
+ if (args[1].equalsIgnoreCase("enable")) {
+ if (args.length == 3) {
+ try {
+ String pos = args[2].toLowerCase(Locale.ROOT);
+ boolean temp = HudUtils.setHudEnable(name, pos);
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Hud.State
+ .replace("%State%", temp ? "启用" : "关闭")
+ .replace("%Hud%", AllMusic.getMessage().HudList.Get(pos)));
+ } catch (Exception e) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.Error);
+ }
+ } else {
+ boolean temp = HudUtils.setHudEnable(name, null);
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Hud.State
+ .replace("%State%", temp ? "启用" : "关闭")
+ .replace("%Hud%", AllMusic.getMessage().HudList.All));
+ }
+ } else if (args[1].equalsIgnoreCase("reset")) {
+ HudUtils.reset(name);
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Hud.Reset);
+ } else if (args[1].equalsIgnoreCase("picsize")) {
+ if (args.length != 3 || !HudUtils.setPicSize(name, args[2])) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.Error);
+ return;
+ }
+ AllMusic.side.sendMessage(sender,
+ AllMusic.getMessage().Hud.PicSize.replace("%Size%", args[2]));
+ } else if (args[1].equalsIgnoreCase("picrotate")) {
+ if (args.length != 3) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.Error);
+ return;
+ }
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Hud.PicRotate
+ .replace("%State%", String.valueOf(HudUtils.setPicRotate(name, args[2]))));
+ } else if (args[1].equalsIgnoreCase("picrotatespeed")) {
+ if (args.length != 3 || !HudUtils.setPicRotateSpeed(name, args[2])) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.Error);
+ return;
+ }
+ AllMusic.side.sendMessage(sender,
+ AllMusic.getMessage().Hud.PicRotateSpeed.replace("%Size%", args[2]));
+ } else if (args.length != 4) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.Error);
+ } else {
+ try {
+ PosObj obj = HudUtils.setHudPos(name, args[1], args[2], args[3]);
+ if (obj == null) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.Error);
+ } else {
+ String temp = AllMusic.getMessage().Hud.Set
+ .replace("%Hud%", args[1])
+ .replace("%x%", args[2])
+ .replace("%y%", args[3]);
+ AllMusic.side.sendMessage(sender, temp);
+ }
+ } catch (Exception e) {
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.Error);
+ }
+ }
+ }
+ return;
+ } else if (args[0].equalsIgnoreCase("reload")) {
+ AllMusic.side.reload();
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2已重读配置文件");
+ return;
+ } else if (AllMusic.getConfig().Admin.contains(name)) {
+ if (args[0].equalsIgnoreCase("next")) {
+ PlayMusic.musicLessTime = 1;
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2已强制切歌");
+ AllMusic.getConfig().RemoveNoMusicPlayer(name);
+ return;
+ } else if (args[0].equalsIgnoreCase("ban") && args.length == 2) {
+ if (Function.isInteger(args[1])) {
+ AllMusic.getConfig().addBanID(args[1]);
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2已禁止" + args[1]);
+ } else {
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2请输入有效的ID");
+ }
+ return;
+ } else if (args[0].equalsIgnoreCase("url") && args.length == 2) {
+ MusicObj obj = new MusicObj();
+ obj.sender = sender;
+ obj.isUrl = true;
+ obj.url = args[1];
+ PlayMusic.addTask(obj);
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().AddMusic.Success);
+ return;
+ } else if (args[0].equalsIgnoreCase("delete") && args.length == 2) {
+ if (!args[1].isEmpty() && Function.isInteger(args[1])) {
+ int music = Integer.parseInt(args[1]);
+ if (music == 0) {
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2请输入有效的序列ID");
+ return;
+ }
+ if (music > PlayMusic.getSize()) {
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2序列号过大");
+ return;
+ }
+ PlayMusic.remove(music - 1);
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2已删除序列" + music);
+ } else {
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2请输入有效的序列ID");
+ }
+ return;
+ } else if (args[0].equalsIgnoreCase("addlist") && args.length == 2) {
+ if (Function.isInteger(args[1])) {
+ AllMusic.getMusicApi().setList(args[1], sender);
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2添加空闲音乐列表" + args[1]);
+ } else {
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2请输入有效的音乐列表ID");
+ }
+ return;
+ } else if (args[0].equalsIgnoreCase("clearlist")) {
+ AllMusic.getConfig().PlayList.clear();
+ AllMusic.save();
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§2添加空闲音乐列表已清空");
+ return;
+ } else if (args[0].equalsIgnoreCase("code")) {
+ AllMusic.getMusicApi().sendCode(sender);
+ return;
+ } else if (args[0].equalsIgnoreCase("login")) {
+ if (args.length != 2) {
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§c没有手机验证码");
+ return;
+ }
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§d重新登录网易云账户");
+ AllMusic.getMusicApi().login(sender, args[1]);
+ return;
+ }
+ }
+ if (AllMusic.getConfig().NeedPermission &&
+ AllMusic.side.checkPermission(name, "allmusic.addmusic"))
+ AllMusic.side.sendMessage(sender, AllMusic.getMessage().Command.NoPer);
+ else {
+ switch (AllMusic.getConfig().DefaultAddMusic) {
+ case 1:
+ searchMusic(sender, name, args, true);
+ break;
+ case 0:
+ default:
+ addMusic(sender, name, args);
+ }
+ }
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/command/TabCommand.java b/server/src/main/java/coloryr/allmusic/core/command/TabCommand.java
new file mode 100644
index 00000000..3272c23d
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/command/TabCommand.java
@@ -0,0 +1,96 @@
+package coloryr.allmusic.core.command;
+
+import coloryr.allmusic.core.AllMusic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TabCommand {
+ /**
+ * 个人的指令
+ */
+ private static final List normal = new ArrayList() {{
+ this.add("stop");
+ this.add("list");
+ this.add("vote");
+ this.add("nomusic");
+ this.add("search");
+ this.add("hud");
+ }};
+
+ /**
+ * 搜歌的指令
+ */
+ private static final List search = new ArrayList() {{
+ this.add("select");
+ this.add("nextpage");
+ this.add("lastpage");
+ }};
+
+ /**
+ * 管理员的指令
+ */
+ private static final List admin = new ArrayList() {{
+ this.add("reload");
+ this.add("next");
+ this.add("ban");
+ this.add("delete");
+ this.add("addlist");
+ this.add("clearlist");
+ this.add("login");
+ }};
+
+ /**
+ * Hud的指令
+ */
+ private static final List hudlist = new ArrayList() {{
+ this.add("info");
+ this.add("list");
+ this.add("lyric");
+ this.add("pic");
+ }};
+
+ /**
+ * Hud的指令
+ */
+ private static final List hud = new ArrayList() {{
+ this.add("info");
+ this.add("list");
+ this.add("lyric");
+ this.add("pic");
+ this.add("picsize");
+ this.add("picrotate");
+ this.add("picrotatespeed");
+ this.add("enable");
+ this.add("reset");
+ }};
+
+ /**
+ * 获取Tab指令列表
+ *
+ * @param name 用户名
+ * @param arg 参数
+ * @return 指令列表
+ */
+ public static List getTabList(String name, String[] arg) {
+ List arguments = new ArrayList<>();
+ if (arg.length == 1 || arg.length == 0) {
+ arguments.addAll(normal);
+ if (AllMusic.getSearch(name) != null) {
+ arguments.addAll(search);
+ }
+ if (AllMusic.getConfig().Admin.contains(name)) {
+ arguments.addAll(admin);
+ }
+ } else if (arg[0].equalsIgnoreCase("hud")) {
+ if (arg.length == 2) {
+ arguments.addAll(hud);
+ } else if (arg.length == 3) {
+ if (arg[1].equalsIgnoreCase("enable")) {
+ arguments.addAll(hudlist);
+ }
+ }
+ }
+ return arguments;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/decoder/Bitstream.java b/server/src/main/java/coloryr/allmusic/core/decoder/Bitstream.java
new file mode 100644
index 00000000..79de8f63
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/decoder/Bitstream.java
@@ -0,0 +1,536 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ *
+ * 11/17/04 Uncomplete frames discarded. E.B, javalayer@javazoom.net
+ *
+ * 12/05/03 ID3v2 tag returned. E.B, javalayer@javazoom.net
+ *
+ * 12/12/99 Based on Ibitstream. Exceptions thrown on errors,
+ * Temporary removed seek functionality. mdm@techie.com
+ *
+ * 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net
+ *
+ * 04/14/97 : Added function prototypes for new syncing and seeking
+ * mechanisms. Also made this file portable. Changes made by Jeff Tsay
+ *
+ * @(#) ibitstream.h 1.5, last edit: 6/15/94 16:55:34
+ * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
+ * @(#) Berlin University of Technology
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package coloryr.allmusic.core.decoder;
+
+import java.io.*;
+
+
+/**
+ * The Bistream class is responsible for parsing
+ * an MPEG audio bitstream.
+ *
+ * REVIEW: much of the parsing currently occurs in the
+ * various decoders. This should be moved into this class and associated
+ * inner classes.
+ */
+public final class Bitstream implements BitstreamErrors {
+ /**
+ * Maximum size of the frame buffer.
+ */
+ private static final int BUFFER_INT_SIZE = 433;
+ /**
+ * Synchronization control constant for the initial
+ * synchronization to the start of a frame.
+ */
+ static byte INITIAL_SYNC = 0;
+
+ // max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC
+ /**
+ * Synchronization control constant for non-initial frame
+ * synchronizations.
+ */
+ static byte STRICT_SYNC = 1;
+ /**
+ * The frame buffer that holds the data for the current frame.
+ */
+ private final int[] framebuffer = new int[BUFFER_INT_SIZE];
+ private final int[] bitmask = {0, // dummy
+ 0x00000001, 0x00000003, 0x00000007, 0x0000000F,
+ 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
+ 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
+ 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
+ 0x0001FFFF};
+ private final PushbackInputStream source;
+ private final Header header = new Header();
+ private final byte[] syncbuf = new byte[4];
+ /**
+ * The bytes read from the stream.
+ */
+ private final byte[] frame_bytes = new byte[BUFFER_INT_SIZE * 4];
+ private final Crc16[] crc = new Crc16[1];
+ /**
+ * Number of valid bytes in the frame buffer.
+ */
+ private int framesize;
+ //private int current_frame_number;
+ //private int last_frame_number;
+ /**
+ * Index into framebuffer where the next bits are
+ * retrieved.
+ */
+ private int wordpointer;
+ /**
+ * Number (0-31, from MSB to LSB) of next bit for get_bits()
+ */
+ private int bitindex;
+ /**
+ * The current specified syncword
+ */
+ private int syncword;
+ /**
+ * Audio header position in stream.
+ */
+ private int header_pos = 0;
+ /**
+ *
+ */
+ private boolean single_ch_mode;
+ private byte[] rawid3v2 = null;
+
+ private boolean firstframe = true;
+
+
+ /**
+ * Construct a IBitstream that reads data from a
+ * given InputStream.
+ *
+ * @param in The InputStream to read from.
+ */
+ public Bitstream(InputStream in) {
+ if (in == null) throw new NullPointerException("in");
+ in = new BufferedInputStream(in);
+ loadID3v2(in);
+ firstframe = true;
+ //source = new PushbackInputStream(in, 1024);
+ source = new PushbackInputStream(in, BUFFER_INT_SIZE * 4);
+
+ closeFrame();
+ //current_frame_number = -1;
+ //last_frame_number = -1;
+ }
+
+ /**
+ * Return position of the first audio header.
+ *
+ * @return size of ID3v2 tag frames.
+ */
+ public int header_pos() {
+ return header_pos;
+ }
+
+ /**
+ * Load ID3v2 frames.
+ *
+ * @param in MP3 InputStream.
+ * @author JavaZOOM
+ */
+ private void loadID3v2(InputStream in) {
+ int size = -1;
+ try {
+ // Read ID3v2 header (10 bytes).
+ in.mark(10);
+ size = readID3v2Header(in);
+ header_pos = size;
+ } catch (IOException e) {
+ } finally {
+ try {
+ // Unread ID3v2 header (10 bytes).
+ in.reset();
+ } catch (IOException e) {
+ }
+ }
+ // Load ID3v2 tags.
+ try {
+ if (size > 0) {
+ rawid3v2 = new byte[size];
+ in.read(rawid3v2, 0, rawid3v2.length);
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ /**
+ * Parse ID3v2 tag header to find out size of ID3v2 frames.
+ *
+ * @param in MP3 InputStream
+ * @return size of ID3v2 frames + header
+ * @throws IOException
+ * @author JavaZOOM
+ */
+ private int readID3v2Header(InputStream in) throws IOException {
+ byte[] id3header = new byte[4];
+ int size = -10;
+ in.read(id3header, 0, 3);
+ // Look for ID3v2
+ if ((id3header[0] == 'I') && (id3header[1] == 'D') && (id3header[2] == '3')) {
+ in.read(id3header, 0, 3);
+ int majorVersion = id3header[0];
+ int revision = id3header[1];
+ in.read(id3header, 0, 4);
+ size = (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]);
+ }
+ return (size + 10);
+ }
+
+ /**
+ * Return raw ID3v2 frames + header.
+ *
+ * @return ID3v2 InputStream or null if ID3v2 frames are not available.
+ */
+ public InputStream getRawID3v2() {
+ if (rawid3v2 == null) return null;
+ else {
+ return new ByteArrayInputStream(rawid3v2);
+ }
+ }
+
+ /**
+ * Close the Bitstream.
+ *
+ * @throws BitstreamException
+ */
+ public void close() throws BitstreamException {
+ try {
+ source.close();
+ } catch (IOException ex) {
+ throw newBitstreamException(STREAM_ERROR, ex);
+ }
+ }
+
+ /**
+ * Reads and parses the next frame from the input source.
+ *
+ * @return the Header describing details of the frame read,
+ * or null if the end of the stream has been reached.
+ */
+ public Header readFrame() throws BitstreamException {
+ Header result = null;
+ try {
+ result = readNextFrame();
+ // E.B, Parse VBR (if any) first frame.
+ if (firstframe) {
+ result.parseVBR(frame_bytes);
+ firstframe = false;
+ }
+ } catch (BitstreamException ex) {
+ if ((ex.getErrorCode() == INVALIDFRAME)) {
+ // Try to skip this frame.
+ //System.out.println("INVALIDFRAME");
+ try {
+ closeFrame();
+ result = readNextFrame();
+ } catch (BitstreamException e) {
+ if ((e.getErrorCode() != STREAM_EOF)) {
+ // wrap original exception so stack trace is maintained.
+ throw newBitstreamException(e.getErrorCode(), e);
+ }
+ }
+ } else if ((ex.getErrorCode() != STREAM_EOF)) {
+ // wrap original exception so stack trace is maintained.
+ throw newBitstreamException(ex.getErrorCode(), ex);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Read next MP3 frame.
+ *
+ * @return MP3 frame header.
+ * @throws BitstreamException
+ */
+ private Header readNextFrame() throws BitstreamException {
+ if (framesize == -1) {
+ nextFrame();
+ }
+ return header;
+ }
+
+
+ /**
+ * Read next MP3 frame.
+ *
+ * @throws BitstreamException
+ */
+ private void nextFrame() throws BitstreamException {
+ // entire frame is read by the header class.
+ header.read_header(this, crc);
+ }
+
+ /**
+ * Unreads the bytes read from the frame.
+ *
+ * @throws BitstreamException
+ */
+ // REVIEW: add new error codes for this.
+ public void unreadFrame() throws BitstreamException {
+ if (wordpointer == -1 && bitindex == -1 && (framesize > 0)) {
+ try {
+ source.unread(frame_bytes, 0, framesize);
+ } catch (IOException ex) {
+ throw newBitstreamException(STREAM_ERROR);
+ }
+ }
+ }
+
+ /**
+ * Close MP3 frame.
+ */
+ public void closeFrame() {
+ framesize = -1;
+ wordpointer = -1;
+ bitindex = -1;
+ }
+
+ /**
+ * Determines if the next 4 bytes of the stream represent a
+ * frame header.
+ */
+ public boolean isSyncCurrentPosition(int syncmode) throws BitstreamException {
+ int read = readBytes(syncbuf, 0, 4);
+ int headerstring = ((syncbuf[0] << 24) & 0xFF000000) | ((syncbuf[1] << 16) & 0x00FF0000) | ((syncbuf[2] << 8) & 0x0000FF00) | ((syncbuf[3] << 0) & 0x000000FF);
+
+ try {
+ source.unread(syncbuf, 0, read);
+ } catch (IOException ex) {
+ }
+
+ boolean sync = false;
+ switch (read) {
+ case 0:
+ sync = true;
+ break;
+ case 4:
+ sync = isSyncMark(headerstring, syncmode, syncword);
+ break;
+ }
+
+ return sync;
+ }
+
+ BitstreamException newBitstreamException(int errorcode) {
+ return new BitstreamException(errorcode, null);
+ }
+
+ private BitstreamException newBitstreamException(int errorcode, Throwable throwable) {
+ return new BitstreamException(errorcode, throwable);
+ }
+
+ /**
+ * Get next 32 bits from bitstream.
+ * They are stored in the headerstring.
+ * syncmod allows Synchro flag ID
+ * The returned value is False at the end of stream.
+ */
+
+ int syncHeader(byte syncmode) throws BitstreamException {
+ boolean sync;
+ int headerstring;
+ // read additional 2 bytes
+ int bytesRead = readBytes(syncbuf, 0, 3);
+
+ if (bytesRead != 3) throw newBitstreamException(STREAM_EOF, null);
+
+ headerstring = ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00) | ((syncbuf[2]) & 0x000000FF);
+
+ do {
+ headerstring <<= 8;
+
+ if (readBytes(syncbuf, 3, 1) != 1)
+ throw newBitstreamException(STREAM_EOF, null);
+
+ headerstring |= (syncbuf[3] & 0x000000FF);
+
+ sync = isSyncMark(headerstring, syncmode, syncword);
+ }
+ while (!sync);
+
+ return headerstring;
+ }
+
+ public boolean isSyncMark(int headerstring, int syncmode, int word) {
+ boolean sync = false;
+
+ if (syncmode == INITIAL_SYNC) {
+ sync = ((headerstring & 0xFFE00000) == 0xFFE00000); // SZD: MPEG 2.5
+ } else {
+ sync = ((headerstring & 0xFFF80C00) == word) &&
+ (((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
+ }
+
+ // filter out invalid sample rate
+ if (sync)
+ sync = (((headerstring >>> 10) & 3) != 3);
+ // filter out invalid layer
+ if (sync)
+ sync = (((headerstring >>> 17) & 3) != 0);
+ // filter out invalid version
+ if (sync)
+ sync = (((headerstring >>> 19) & 3) != 1);
+
+ return sync;
+ }
+
+ /**
+ * Reads the data for the next frame. The frame is not parsed
+ * until parse frame is called.
+ */
+ int read_frame_data(int bytesize) throws BitstreamException {
+ int numread = readFully(frame_bytes, 0, bytesize);
+ framesize = bytesize;
+ wordpointer = -1;
+ bitindex = -1;
+ return numread;
+ }
+
+ /**
+ * Parses the data previously read with read_frame_data().
+ */
+ void parse_frame() throws BitstreamException {
+ // Convert Bytes read to int
+ int b = 0;
+ byte[] byteread = frame_bytes;
+ int bytesize = framesize;
+
+ for (int k = 0; k < bytesize; k = k + 4) {
+ int convert = 0;
+ byte b0 = 0;
+ byte b1 = 0;
+ byte b2 = 0;
+ byte b3 = 0;
+ b0 = byteread[k];
+ if (k + 1 < bytesize) b1 = byteread[k + 1];
+ if (k + 2 < bytesize) b2 = byteread[k + 2];
+ if (k + 3 < bytesize) b3 = byteread[k + 3];
+ framebuffer[b++] = ((b0 << 24) & 0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00) | (b3 & 0x000000FF);
+ }
+ wordpointer = 0;
+ bitindex = 0;
+ }
+
+ /**
+ * Read bits from buffer into the lower bits of an unsigned int.
+ * The LSB contains the latest read bit of the stream.
+ * (1 <= number_of_bits <= 16)
+ */
+ public int get_bits(int number_of_bits) {
+ int returnvalue = 0;
+ int sum = bitindex + number_of_bits;
+
+ // E.B
+ // There is a problem here, wordpointer could be -1 ?!
+ if (wordpointer < 0) wordpointer = 0;
+ // E.B : End.
+
+ if (sum <= 32) {
+ // all bits contained in *wordpointer
+ returnvalue = (framebuffer[wordpointer] >>> (32 - sum)) & bitmask[number_of_bits];
+ // returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits];
+ if ((bitindex += number_of_bits) == 32) {
+ bitindex = 0;
+ wordpointer++; // added by me!
+ }
+ return returnvalue;
+ }
+
+ int Right = (framebuffer[wordpointer] & 0x0000FFFF);
+ wordpointer++;
+ int Left = (framebuffer[wordpointer] & 0xFFFF0000);
+ returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16) & 0x0000FFFF);
+
+ returnvalue >>>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32 - bitindex))
+ returnvalue &= bitmask[number_of_bits];
+ bitindex = sum - 32;
+ return returnvalue;
+ }
+
+ /**
+ * Set the word we want to sync the header to.
+ * In Big-Endian byte order
+ */
+ void set_syncword(int syncword0) {
+ syncword = syncword0 & 0xFFFFFF3F;
+ single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
+ }
+
+ /**
+ * Reads the exact number of bytes from the source
+ * input stream into a byte array.
+ *
+ * @param b The byte array to read the specified number
+ * of bytes into.
+ * @param offs The index in the array where the first byte
+ * read should be stored.
+ * @param len the number of bytes to read.
+ * @throws BitstreamException is thrown if the specified
+ * number of bytes could not be read from the stream.
+ */
+ private int readFully(byte[] b, int offs, int len)
+ throws BitstreamException {
+ int nRead = 0;
+ try {
+ while (len > 0) {
+ int bytesread = source.read(b, offs, len);
+ if (bytesread == -1) {
+ while (len-- > 0) {
+ b[offs++] = 0;
+ }
+ break;
+ //throw newBitstreamException(UNEXPECTED_EOF, new EOFException());
+ }
+ nRead = nRead + bytesread;
+ offs += bytesread;
+ len -= bytesread;
+ }
+ } catch (IOException ex) {
+ throw newBitstreamException(STREAM_ERROR, ex);
+ }
+ return nRead;
+ }
+
+ /**
+ * Simlar to readFully, but doesn't throw exception when
+ * EOF is reached.
+ */
+ private int readBytes(byte[] b, int offs, int len)
+ throws BitstreamException {
+ int totalBytesRead = 0;
+ try {
+ while (len > 0) {
+ int bytesread = source.read(b, offs, len);
+ if (bytesread == -1) {
+ break;
+ }
+ totalBytesRead += bytesread;
+ offs += bytesread;
+ len -= bytesread;
+ }
+ } catch (IOException ex) {
+ throw newBitstreamException(STREAM_ERROR, ex);
+ }
+ return totalBytesRead;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/decoder/BitstreamErrors.java b/server/src/main/java/coloryr/allmusic/core/decoder/BitstreamErrors.java
new file mode 100644
index 00000000..57cd7049
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/decoder/BitstreamErrors.java
@@ -0,0 +1,55 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 11/17/04 INVALIDFRAME code added. javalayer@javazoom.net
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package coloryr.allmusic.core.decoder;
+
+/**
+ * This interface describes all error codes that can be thrown
+ * in BistreamExceptions.
+ *
+ * @author MDM 12/12/99
+ * @see BitstreamException
+ * @since 0.0.6
+ */
+
+public interface BitstreamErrors extends JavaLayerErrors {
+
+ /**
+ * An undeterminable error occurred.
+ */
+ int UNKNOWN_ERROR = BITSTREAM_ERROR;
+
+ /**
+ * A problem occurred reading from the stream.
+ */
+ int STREAM_ERROR = BITSTREAM_ERROR + 2;
+
+ /**
+ * The end of the stream was reached.
+ */
+ int STREAM_EOF = BITSTREAM_ERROR + 4;
+
+ /**
+ * Frame data are missing.
+ */
+ int INVALIDFRAME = BITSTREAM_ERROR + 5;
+
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/decoder/BitstreamException.java b/server/src/main/java/coloryr/allmusic/core/decoder/BitstreamException.java
new file mode 100644
index 00000000..c5ec3bca
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/decoder/BitstreamException.java
@@ -0,0 +1,65 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package coloryr.allmusic.core.decoder;
+
+/**
+ * Instances of BitstreamException are thrown
+ * when operations on a Bitstream fail.
+ *
+ * The exception provides details of the exception condition
+ * in two ways:
+ *
-
+ * as an error-code describing the nature of the error
+ *
-
+ * as the
Throwable instance, if any, that was thrown
+ * indicating that an exceptional condition has occurred.
+ *
+ *
+ * @author MDM 12/12/99
+ * @since 0.0.6
+ */
+
+public class BitstreamException extends JavaLayerException
+ implements BitstreamErrors {
+ private int errorcode = UNKNOWN_ERROR;
+
+ public BitstreamException(String msg, Throwable t) {
+ super(msg, t);
+ }
+
+ public BitstreamException(int errorcode, Throwable t) {
+ this(getErrorString(errorcode), t);
+ this.errorcode = errorcode;
+ }
+
+ static public String getErrorString(int errorcode) {
+ // REVIEW: use resource bundle to map error codes
+ // to locale-sensitive strings.
+
+ return "Bitstream errorcode " + Integer.toHexString(errorcode);
+ }
+
+ public int getErrorCode() {
+ return errorcode;
+ }
+
+
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/decoder/Crc16.java b/server/src/main/java/coloryr/allmusic/core/decoder/Crc16.java
new file mode 100644
index 00000000..d3acaa67
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/decoder/Crc16.java
@@ -0,0 +1,64 @@
+/*
+ * 11/19/04 : 1.0 moved to LGPL.
+ *
+ * 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net
+ *
+ * @(#) crc.h 1.5, last edit: 6/15/94 16:55:32
+ * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
+ * @(#) Berlin University of Technology
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+package coloryr.allmusic.core.decoder;
+
+/**
+ * 16-Bit CRC checksum
+ */
+public final class Crc16 {
+ private short crc;
+
+ /**
+ * Dummy Constructor
+ */
+ public Crc16() {
+ crc = (short) 0xFFFF;
+ }
+
+ /**
+ * Feed a bitstring to the crc calculation (0 < length <= 32).
+ */
+ public void add_bits(int bitstring, int length) {
+ int bitmask = 1 << (length - 1);
+ do
+ if (((crc & 0x8000) == 0) ^ ((bitstring & bitmask) == 0)) {
+ crc <<= 1;
+ short polynomial = (short) 0x8005;
+ crc ^= polynomial;
+ } else
+ crc <<= 1;
+ while ((bitmask >>>= 1) != 0);
+ }
+
+ /**
+ * Return the calculated checksum.
+ * Erase it for next calls to add_bits().
+ */
+ public short checksum() {
+ short sum = crc;
+ crc = (short) 0xFFFF;
+ return sum;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/decoder/Header.java b/server/src/main/java/coloryr/allmusic/core/decoder/Header.java
new file mode 100644
index 00000000..4aad9a05
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/decoder/Header.java
@@ -0,0 +1,618 @@
+/*
+ * 11/19/04 : 1.0 moved to LGPL.
+ * VBRI header support added, E.B javalayer@javazoom.net
+ *
+ * 12/04/03 : VBR (XING) header support added, E.B javalayer@javazoom.net
+ *
+ * 02/13/99 : Java Conversion by JavaZOOM , E.B javalayer@javazoom.net
+ *
+ * Declarations for MPEG header class
+ * A few layer III, MPEG-2 LSF, and seeking modifications made by Jeff Tsay.
+ * Last modified : 04/19/97
+ *
+ * @(#) header.h 1.7, last edit: 6/15/94 16:55:33
+ * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
+ * @(#) Berlin University of Technology
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+package coloryr.allmusic.core.decoder;
+
+/**
+ * Class for extracting information from a frame header.
+ */
+public final class Header {
+ public static final int[][] frequencies =
+ {{22050, 24000, 16000, 1},
+ {44100, 48000, 32000, 1},
+ {11025, 12000, 8000, 1}}; // SZD: MPEG25
+
+ /**
+ * Constant for MPEG-2 LSF version
+ */
+ public static final int MPEG2_LSF = 0;
+ public static final int MPEG25_LSF = 2; // SZD
+
+ /**
+ * Constant for MPEG-1 version
+ */
+ public static final int MPEG1 = 1;
+
+ public static final int STEREO = 0;
+ public static final int JOINT_STEREO = 1;
+ public static final int DUAL_CHANNEL = 2;
+ public static final int SINGLE_CHANNEL = 3;
+ public static final int FOURTYFOUR_POINT_ONE = 0;
+ public static final int FOURTYEIGHT = 1;
+ public static final int THIRTYTWO = 2;
+ // E.B -> private to public
+ public static final int[][][] bitrates = {
+ {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,
+ 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000, 0},
+ {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
+ 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},
+ {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
+ 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},
+
+ {{0 /*free format*/, 32000, 64000, 96000, 128000, 160000, 192000,
+ 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0},
+ {0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,
+ 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0},
+ {0 /*free format*/, 32000, 40000, 48000, 56000, 64000, 80000,
+ 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0}},
+ // SZD: MPEG2.5
+ {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,
+ 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000, 0},
+ {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
+ 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},
+ {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
+ 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},
+
+ };
+ // E.B -> private to public
+ public static final String[][][] bitrate_str = {
+ {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",
+ "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s",
+ "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s",
+ "forbidden"},
+ {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
+ "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
+ "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
+ "forbidden"},
+ {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
+ "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
+ "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
+ "forbidden"}},
+
+ {{"free format", "32 kbit/s", "64 kbit/s", "96 kbit/s", "128 kbit/s",
+ "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "288 kbit/s",
+ "320 kbit/s", "352 kbit/s", "384 kbit/s", "416 kbit/s", "448 kbit/s",
+ "forbidden"},
+ {"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",
+ "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "160 kbit/s",
+ "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s", "384 kbit/s",
+ "forbidden"},
+ {"free format", "32 kbit/s", "40 kbit/s", "48 kbit/s", "56 kbit/s",
+ "64 kbit/s", "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s",
+ "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s",
+ "forbidden"}},
+ // SZD: MPEG2.5
+ {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",
+ "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s",
+ "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s",
+ "forbidden"},
+ {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
+ "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
+ "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
+ "forbidden"},
+ {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
+ "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
+ "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
+ "forbidden"}},
+ };
+ // VBR support added by E.B
+ private final double[] h_vbr_time_per_frame = {-1, 384, 1152, 1152};
+ public short checksum;
+ public int framesize;
+ public int nSlots;
+ private int h_layer, h_protection_bit, h_bitrate_index,
+ h_padding_bit, h_mode_extension;
+ private int h_version;
+ private int h_mode;
+ private int h_sample_frequency;
+ private int h_number_of_subbands, h_intensity_stereo_bound;
+ private boolean h_vbr;
+ private int h_vbr_frames;
+ private int h_vbr_bytes;
+ private byte syncmode = Bitstream.INITIAL_SYNC;
+ private Crc16 crc;
+
+ Header() {
+ }
+
+ /**
+ * Returns total ms.
+ *
+ * @param streamsize
+ * @return total milliseconds
+ */
+ public float total_ms(int streamsize) {
+ return (max_number_of_frames(streamsize) * ms_per_frame());
+ }
+
+ public String toString() {
+ StringBuilder buffer = new StringBuilder(200);
+ buffer.append("Layer ");
+ buffer.append(layer_string());
+ buffer.append(" frame ");
+ buffer.append(mode_string());
+ buffer.append(' ');
+ buffer.append(version_string());
+ if (!checksums())
+ buffer.append(" no");
+ buffer.append(" checksums");
+ buffer.append(' ');
+ buffer.append(sample_frequency_string());
+ buffer.append(',');
+ buffer.append(' ');
+ buffer.append(bitrate_string());
+
+ return buffer.toString();
+ }
+
+ // Functions to query header contents:
+
+ /**
+ * Read a 32-bit header from the bitstream.
+ */
+ void read_header(Bitstream stream, Crc16[] crcp) throws BitstreamException {
+ int headerstring;
+ int channel_bitrate;
+ boolean sync = false;
+ do {
+ headerstring = stream.syncHeader(syncmode);
+ if (syncmode == Bitstream.INITIAL_SYNC) {
+ h_version = ((headerstring >>> 19) & 1);
+ if (((headerstring >>> 20) & 1) == 0) // SZD: MPEG2.5 detection
+ if (h_version == MPEG2_LSF)
+ h_version = MPEG25_LSF;
+ else
+ throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);
+ if ((h_sample_frequency = ((headerstring >>> 10) & 3)) == 3) {
+ throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);
+ }
+ }
+ h_layer = 4 - (headerstring >>> 17) & 3;
+ h_protection_bit = (headerstring >>> 16) & 1;
+ h_bitrate_index = (headerstring >>> 12) & 0xF;
+ h_padding_bit = (headerstring >>> 9) & 1;
+ h_mode = ((headerstring >>> 6) & 3);
+ h_mode_extension = (headerstring >>> 4) & 3;
+ if (h_mode == JOINT_STEREO)
+ h_intensity_stereo_bound = (h_mode_extension << 2) + 4;
+ else
+ h_intensity_stereo_bound = 0; // should never be used
+ // calculate number of subbands:
+ if (h_layer == 1)
+ h_number_of_subbands = 32;
+ else {
+ channel_bitrate = h_bitrate_index;
+ // calculate bitrate per channel:
+ if (h_mode != SINGLE_CHANNEL)
+ if (channel_bitrate == 4)
+ channel_bitrate = 1;
+ else
+ channel_bitrate -= 4;
+ if ((channel_bitrate == 1) || (channel_bitrate == 2))
+ if (h_sample_frequency == THIRTYTWO)
+ h_number_of_subbands = 12;
+ else
+ h_number_of_subbands = 8;
+ else if ((h_sample_frequency == FOURTYEIGHT) || ((channel_bitrate >= 3) && (channel_bitrate <= 5)))
+ h_number_of_subbands = 27;
+ else
+ h_number_of_subbands = 30;
+ }
+ if (h_intensity_stereo_bound > h_number_of_subbands)
+ h_intensity_stereo_bound = h_number_of_subbands;
+ // calculate framesize and nSlots
+ calculate_framesize();
+ // read framedata:
+ int framesizeloaded = stream.read_frame_data(framesize);
+ if ((framesize >= 0) && (framesizeloaded != framesize)) {
+ // Data loaded does not match to expected framesize,
+ // it might be an ID3v1 TAG. (Fix 11/17/04).
+ throw stream.newBitstreamException(Bitstream.INVALIDFRAME);
+ }
+ if (stream.isSyncCurrentPosition(syncmode)) {
+ if (syncmode == Bitstream.INITIAL_SYNC) {
+ syncmode = Bitstream.STRICT_SYNC;
+ stream.set_syncword(headerstring & 0xFFF80CC0);
+ }
+ sync = true;
+ } else {
+ stream.unreadFrame();
+ }
+ }
+ while (!sync);
+ stream.parse_frame();
+ if (h_protection_bit == 0) {
+ // frame contains a crc checksum
+ checksum = (short) stream.get_bits(16);
+ if (crc == null)
+ crc = new Crc16();
+ crc.add_bits(headerstring, 16);
+ crcp[0] = crc;
+ } else
+ crcp[0] = null;
+ }
+
+ /**
+ * Parse frame to extract optionnal VBR frame.
+ *
+ * @param firstframe
+ * @author E.B (javalayer@javazoom.net)
+ */
+ void parseVBR(byte[] firstframe) throws BitstreamException {
+ // Trying Xing header.
+ String xing = "Xing";
+ byte[] tmp = new byte[4];
+ int offset = 0;
+ // Compute "Xing" offset depending on MPEG version and channels.
+ if (h_version == MPEG1) {
+ if (h_mode == SINGLE_CHANNEL) offset = 21 - 4;
+ else offset = 36 - 4;
+ } else {
+ if (h_mode == SINGLE_CHANNEL) offset = 13 - 4;
+ else offset = 21 - 4;
+ }
+ byte[] h_vbr_toc;
+ try {
+ System.arraycopy(firstframe, offset, tmp, 0, 4);
+ // Is "Xing" ?
+ if (xing.equals(new String(tmp))) {
+ //Yes.
+ h_vbr = true;
+ h_vbr_frames = -1;
+ h_vbr_bytes = -1;
+ h_vbr_toc = new byte[100];
+
+ int length = 4;
+ // Read flags.
+ byte[] flags = new byte[4];
+ System.arraycopy(firstframe, offset + length, flags, 0, flags.length);
+ length += flags.length;
+ // Read number of frames (if available).
+ if ((flags[3] & (byte) (1)) != 0) {
+ System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
+ h_vbr_frames = (tmp[0] << 24) & 0xFF000000 | (tmp[1] << 16) & 0x00FF0000 | (tmp[2] << 8) & 0x0000FF00 | tmp[3] & 0x000000FF;
+ length += 4;
+ }
+ // Read size (if available).
+ if ((flags[3] & (byte) (1 << 1)) != 0) {
+ System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
+ h_vbr_bytes = (tmp[0] << 24) & 0xFF000000 | (tmp[1] << 16) & 0x00FF0000 | (tmp[2] << 8) & 0x0000FF00 | tmp[3] & 0x000000FF;
+ length += 4;
+ }
+ // Read TOC (if available).
+ if ((flags[3] & (byte) (1 << 2)) != 0) {
+ System.arraycopy(firstframe, offset + length, h_vbr_toc, 0, h_vbr_toc.length);
+ length += h_vbr_toc.length;
+ }
+ // Read scale (if available).
+ if ((flags[3] & (byte) (1 << 3)) != 0) {
+ System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new BitstreamException("XingVBRHeader Corrupted", e);
+ }
+
+ // Trying VBRI header.
+ String vbri = "VBRI";
+ offset = 36 - 4;
+ try {
+ System.arraycopy(firstframe, offset, tmp, 0, 4);
+ // Is "VBRI" ?
+ if (vbri.equals(new String(tmp))) {
+ //Yes.
+ h_vbr = true;
+ h_vbr_frames = -1;
+ h_vbr_bytes = -1;
+ // Bytes.
+ int length = 4 + 6;
+ System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
+ h_vbr_bytes = (tmp[0] << 24) & 0xFF000000 | (tmp[1] << 16) & 0x00FF0000 | (tmp[2] << 8) & 0x0000FF00 | tmp[3] & 0x000000FF;
+ length += 4;
+ // Frames.
+ System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);
+ h_vbr_frames = (tmp[0] << 24) & 0xFF000000 | (tmp[1] << 16) & 0x00FF0000 | (tmp[2] << 8) & 0x0000FF00 | tmp[3] & 0x000000FF;
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new BitstreamException("VBRIVBRHeader Corrupted", e);
+ }
+ }
+
+ /**
+ * Returns version.
+ */
+ public int version() {
+ return h_version;
+ }
+
+ /**
+ * Returns Layer ID.
+ */
+ public int layer() {
+ return h_layer;
+ }
+
+ /**
+ * Returns bitrate index.
+ */
+ public int bitrate_index() {
+ return h_bitrate_index;
+ }
+
+ /**
+ * Returns Sample Frequency.
+ */
+ public int sample_frequency() {
+ return h_sample_frequency;
+ }
+
+ /**
+ * Returns Frequency.
+ */
+ public int frequency() {
+ return frequencies[h_version][h_sample_frequency];
+ }
+
+ /**
+ * Returns Mode.
+ */
+ public int mode() {
+ return h_mode;
+ }
+
+ /**
+ * Returns Protection bit.
+ */
+ public boolean checksums() {
+ return h_protection_bit == 0;
+ }
+
+ // Seeking and layer III stuff
+
+ /**
+ * Returns Checksum flag.
+ * Compares computed checksum with stream checksum.
+ */
+ public boolean checksum_ok() {
+ return (checksum == crc.checksum());
+ }
+
+ /**
+ * Returns Slots.
+ */
+ public int slots() {
+ return nSlots;
+ }
+
+ // E.B -> private to public
+
+ /**
+ * Returns Mode Extension.
+ */
+ public int mode_extension() {
+ return h_mode_extension;
+ }
+
+ /**
+ * Calculate Frame size.
+ * Calculates framesize in bytes excluding header size.
+ */
+ public void calculate_framesize() {
+
+ if (h_layer == 1) {
+ framesize = (12 * bitrates[h_version][0][h_bitrate_index]) /
+ frequencies[h_version][h_sample_frequency];
+ if (h_padding_bit != 0) framesize++;
+ framesize <<= 2; // one slot is 4 bytes long
+ nSlots = 0;
+ } else {
+ framesize = (144 * bitrates[h_version][h_layer - 1][h_bitrate_index]) /
+ frequencies[h_version][h_sample_frequency];
+ if (h_version == MPEG2_LSF || h_version == MPEG25_LSF) framesize >>= 1; // SZD
+ if (h_padding_bit != 0) framesize++;
+ // Layer III slots
+ if (h_layer == 3) {
+ if (h_version == MPEG1) {
+ nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 17 : 32) // side info size
+ - ((h_protection_bit != 0) ? 0 : 2) // CRC size
+ - 4; // header size
+ } else { // MPEG-2 LSF, SZD: MPEG-2.5 LSF
+ nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 9 : 17) // side info size
+ - ((h_protection_bit != 0) ? 0 : 2) // CRC size
+ - 4; // header size
+ }
+ } else {
+ nSlots = 0;
+ }
+ }
+ framesize -= 4; // subtract header size
+ }
+
+ /**
+ * Returns the maximum number of frames in the stream.
+ *
+ * @param streamsize
+ * @return number of frames
+ */
+ public int max_number_of_frames(int streamsize) // E.B
+ {
+ if (h_vbr) return h_vbr_frames;
+ else {
+ if ((framesize + 4 - h_padding_bit) == 0) return 0;
+ else return (streamsize / (framesize + 4 - h_padding_bit));
+ }
+ }
+
+ /**
+ * Returns ms/frame.
+ *
+ * @return milliseconds per frame
+ */
+ public float ms_per_frame() // E.B
+ {
+ if (h_vbr) {
+ double tpf = h_vbr_time_per_frame[layer()] / frequency();
+ if ((h_version == MPEG2_LSF) || (h_version == MPEG25_LSF)) tpf /= 2;
+ return ((float) (tpf * 1000));
+ } else {
+ float[][] ms_per_frame_array = {{8.707483f, 8.0f, 12.0f},
+ {26.12245f, 24.0f, 36.0f},
+ {26.12245f, 24.0f, 36.0f}};
+ return (ms_per_frame_array[h_layer - 1][h_sample_frequency]);
+ }
+ }
+
+ // functions which return header informations as strings:
+
+ /**
+ * Return Layer version.
+ */
+ public String layer_string() {
+ switch (h_layer) {
+ case 1:
+ return "I";
+ case 2:
+ return "II";
+ case 3:
+ return "III";
+ }
+ return null;
+ }
+
+ /**
+ * Return Bitrate.
+ *
+ * @return bitrate in bps
+ */
+ public String bitrate_string() {
+ if (h_vbr) {
+ return bitrate() / 1000 + " kb/s";
+ } else return bitrate_str[h_version][h_layer - 1][h_bitrate_index];
+ }
+
+ /**
+ * Return Bitrate.
+ *
+ * @return bitrate in bps and average bitrate for VBR header
+ */
+ public int bitrate() {
+ if (h_vbr) {
+ return ((int) ((h_vbr_bytes * 8) / (ms_per_frame() * h_vbr_frames))) * 1000;
+ } else return bitrates[h_version][h_layer - 1][h_bitrate_index];
+ }
+
+ /**
+ * Returns Frequency
+ *
+ * @return frequency string in kHz
+ */
+ public String sample_frequency_string() {
+ switch (h_sample_frequency) {
+ case THIRTYTWO:
+ if (h_version == MPEG1)
+ return "32 kHz";
+ else if (h_version == MPEG2_LSF)
+ return "16 kHz";
+ else // SZD
+ return "8 kHz";
+ case FOURTYFOUR_POINT_ONE:
+ if (h_version == MPEG1)
+ return "44.1 kHz";
+ else if (h_version == MPEG2_LSF)
+ return "22.05 kHz";
+ else // SZD
+ return "11.025 kHz";
+ case FOURTYEIGHT:
+ if (h_version == MPEG1)
+ return "48 kHz";
+ else if (h_version == MPEG2_LSF)
+ return "24 kHz";
+ else // SZD
+ return "12 kHz";
+ }
+ return (null);
+ }
+
+ /**
+ * Returns Mode.
+ */
+ public String mode_string() {
+ switch (h_mode) {
+ case STEREO:
+ return "Stereo";
+ case JOINT_STEREO:
+ return "Joint stereo";
+ case DUAL_CHANNEL:
+ return "Dual channel";
+ case SINGLE_CHANNEL:
+ return "Single channel";
+ }
+ return null;
+ }
+
+ /**
+ * Returns Version.
+ *
+ * @return MPEG-1 or MPEG-2 LSF or MPEG-2.5 LSF
+ */
+ public String version_string() {
+ switch (h_version) {
+ case MPEG1:
+ return "MPEG-1";
+ case MPEG2_LSF:
+ return "MPEG-2 LSF";
+ case MPEG25_LSF: // SZD
+ return "MPEG-2.5 LSF";
+ }
+ return (null);
+ }
+
+ /**
+ * Returns the number of subbands in the current frame.
+ *
+ * @return number of subbands
+ */
+ public int number_of_subbands() {
+ return h_number_of_subbands;
+ }
+
+ /**
+ * Returns Intensity Stereo.
+ * (Layer II joint stereo only).
+ * Returns the number of subbands which are in stereo mode,
+ * subbands above that limit are in intensity stereo mode.
+ *
+ * @return intensity
+ */
+ public int intensity_stereo_bound() {
+ return h_intensity_stereo_bound;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/decoder/JavaLayerErrors.java b/server/src/main/java/coloryr/allmusic/core/decoder/JavaLayerErrors.java
new file mode 100644
index 00000000..42a81bdf
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/decoder/JavaLayerErrors.java
@@ -0,0 +1,39 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package coloryr.allmusic.core.decoder;
+
+/**
+ * Exception erorr codes for components of the JavaLayer API.
+ */
+public interface JavaLayerErrors {
+ /**
+ * The first bitstream error code. See the {@link DecoderErrors DecoderErrors}
+ * interface for other bitstream error codes.
+ */
+ int BITSTREAM_ERROR = 0x100;
+
+ /**
+ * The first decoder error code. See the {@link DecoderErrors DecoderErrors}
+ * interface for other decoder error codes.
+ */
+ int DECODER_ERROR = 0x200;
+
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/decoder/JavaLayerException.java b/server/src/main/java/coloryr/allmusic/core/decoder/JavaLayerException.java
new file mode 100644
index 00000000..d624c3e8
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/decoder/JavaLayerException.java
@@ -0,0 +1,61 @@
+/*
+ * 11/19/04 1.0 moved to LGPL.
+ * 12/12/99 Initial version. mdm@techie.com
+ *-----------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *----------------------------------------------------------------------
+ */
+
+package coloryr.allmusic.core.decoder;
+
+import java.io.PrintStream;
+
+
+/**
+ * The JavaLayerException is the base class for all API-level
+ * exceptions thrown by JavaLayer. To facilitate conversion and
+ * common handling of exceptions from other domains, the class
+ * can delegate some functionality to a contained Throwable instance.
+ *
+ *
+ * @author MDM
+ */
+public class JavaLayerException extends Exception {
+
+ private Throwable exception;
+
+ public JavaLayerException(String msg) {
+ super(msg);
+ }
+
+ public JavaLayerException(String msg, Throwable t) {
+ super(msg);
+ exception = t;
+ }
+
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+ public void printStackTrace(PrintStream ps) {
+ if (this.exception == null) {
+ super.printStackTrace(ps);
+ } else {
+ exception.printStackTrace();
+ }
+ }
+
+
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/enums/EncryptType.java b/server/src/main/java/coloryr/allmusic/core/enums/EncryptType.java
new file mode 100644
index 00000000..305bb5e2
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/enums/EncryptType.java
@@ -0,0 +1,5 @@
+package coloryr.allmusic.core.enums;
+
+public enum EncryptType {
+ WEAPI, EAPI, API
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/enums/HudPos.java b/server/src/main/java/coloryr/allmusic/core/enums/HudPos.java
new file mode 100644
index 00000000..026127b4
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/enums/HudPos.java
@@ -0,0 +1,5 @@
+package coloryr.allmusic.core.enums;
+
+public enum HudPos {
+ info, list, lyric, pic
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/hud/DataSql.java b/server/src/main/java/coloryr/allmusic/core/hud/DataSql.java
new file mode 100644
index 00000000..b61a6556
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/hud/DataSql.java
@@ -0,0 +1,255 @@
+package coloryr.allmusic.core.hud;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.hud.PosObj;
+import coloryr.allmusic.core.objs.hud.SaveObj;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.text.MessageFormat;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Semaphore;
+
+public class DataSql {
+ private static final Queue tasks = new ConcurrentLinkedQueue<>();
+ private static final Semaphore semaphore = new Semaphore(0);
+ /**
+ * 创建表用
+ */
+ private static final String table = "CREATE TABLE \"allmusic\" (\n" +
+ " \"id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n" +
+ " \"name\" TEXT(20),\n" +
+ " \"info_x\" integer(6),\n" +
+ " \"info_y\" integer(6),\n" +
+ " \"info_enable\" integer(1),\n" +
+ " \"lyric_x\" integer(6),\n" +
+ " \"lyric_y\" integer(6),\n" +
+ " \"lyric_enable\" integer(1),\n" +
+ " \"list_x\" integer(6),\n" +
+ " \"list_y\" integer(6),\n" +
+ " \"list_enable\" integer(1),\n" +
+ " \"pic_x\" integer(6),\n" +
+ " \"pic_y\" integer(6),\n" +
+ " \"pic_size\" integer(6),\n" +
+ " \"pic_enable\" integer(1),\n" +
+ " \"pic_rotate\" integer(1),\n" +
+ " \"pic_rotate_speed\" integer(6)\n" +
+ ");";
+ /**
+ * 数据库文件
+ */
+ public static File sqlFile;
+ private static boolean isRun;
+ /**
+ * 数据库链接对象
+ */
+ private static Connection connection;
+
+ /**
+ * 初始化数据库
+ */
+ public static void init() {
+ try {
+ AllMusic.log.info("正在初始化数据库");
+ if (connection != null)
+ connection.close();
+ Class.forName("org.sqlite.JDBC");
+ connection = DriverManager.getConnection("jdbc:sqlite:" + sqlFile.getPath());
+ Statement stat = connection.createStatement();
+ ResultSet set = stat.executeQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='allmusic';");
+ if (!set.next()) {
+ set.close();
+ stat.execute(table);
+ }
+ stat.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 检查玩家是否在数据库
+ *
+ * @param name 用户名
+ * @return 结果
+ */
+ public static boolean check(String name) {
+ try {
+ boolean have = false;
+ if (connection.isReadOnly() || connection.isClosed()) {
+ init();
+ }
+ Statement stat = connection.createStatement();
+ ResultSet set = stat.executeQuery("SELECT allmusic.id FROM allmusic WHERE allmusic.name ='" + name + "'");
+ if (set.next()) {
+ have = true;
+ }
+ set.close();
+ stat.close();
+ return have;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ /**
+ * 更新玩家Hud数据
+ *
+ * @param name 用户名
+ * @param hud Hud数据
+ */
+ private static void update(String name, SaveObj hud) {
+ String sql = "";
+ try {
+ if (connection.isReadOnly() || connection.isClosed()) {
+ init();
+ }
+ Statement stat = connection.createStatement();
+ sql = MessageFormat.format("UPDATE allmusic SET info_x={0},info_y={1},info_enable={2},lyric_x={3},lyric_y={4},lyric_enable={5},list_x={6},list_y={7}, list_enable={8},pic_x={9},pic_y={10},pic_enable={11},pic_size={12},pic_rotate={13},pic_rotate_speed={14} WHERE name=@name",
+ hud.Info.x, hud.Info.y, hud.EnableInfo ? 1 : 0,
+ hud.Lyric.x, hud.Lyric.y, hud.EnableLyric ? 1 : 0,
+ hud.List.x, hud.List.y, hud.EnableList ? 1 : 0,
+ hud.Pic.x, hud.Pic.y, hud.EnablePic ? 1 : 0,
+ hud.PicSize, hud.EnablePicRotate ? 1: 0,
+ hud.PicRotateSpeed);
+ sql = sql.replace("@name", "'" + name + "'");
+ stat.execute(sql);
+ stat.close();
+ } catch (Exception e) {
+ AllMusic.log.info(sql);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 添加用户Hud数据
+ *
+ * @param name 用户名
+ * @param hud 数据
+ */
+ public static void addUser(String name, SaveObj hud) {
+ String sql = "";
+ try {
+ if (connection.isReadOnly() || connection.isClosed()) {
+ init();
+ }
+ if (check(name)) {
+ update(name, hud);
+ } else {
+ Statement stat = connection.createStatement();
+ sql = MessageFormat.format("INSERT INTO allmusic (name,info_x,info_y," +
+ "info_enable,lyric_x,lyric_y,lyric_enable,list_x,list_y,list_enable," +
+ "pic_x,pic_y,pic_enable,pic_size,pic_rotate,pic_rotate_speed)" +
+ "VALUES (@name,{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14})",
+ hud.Info.x, hud.Info.y, hud.EnableInfo ? 1 : 0,
+ hud.Lyric.x, hud.Lyric.y, hud.EnableLyric ? 1 : 0,
+ hud.List.x, hud.List.y, hud.EnableList ? 1 : 0,
+ hud.Pic.x, hud.Pic.y, hud.EnablePic ? 1 : 0,
+ hud.PicSize, hud.EnablePicRotate ? 1: 0,
+ hud.PicRotateSpeed);
+ sql = sql.replace("@name", "'" + name + "'");
+ stat.execute(sql);
+ stat.close();
+ }
+ } catch (Exception e) {
+ AllMusic.log.info(sql);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 读取所有数据
+ */
+ private static void readAll() {
+ try {
+ AllMusic.log.info("正在读取数据库所有内容");
+ if (connection.isReadOnly() || connection.isClosed()) {
+ init();
+ }
+ Statement stat = connection.createStatement();
+ ResultSet set = stat.executeQuery("SELECT name,info_x,info_y,info_enable,lyric_x,lyric_y,lyric_enable,list_x,list_y,list_enable,pic_x,pic_y,pic_enable,pic_size,pic_rotate,pic_rotate_speed FROM allmusic");
+ while (set.next()) {
+ String name = set.getString(1);
+ SaveObj obj = new SaveObj();
+ PosObj pos1 = new PosObj();
+ pos1.x = set.getInt(2);
+ pos1.y = set.getInt(3);
+ obj.Info = pos1;
+ obj.EnableInfo = set.getInt(4) == 1;
+ PosObj pos2 = new PosObj();
+ pos2.x = set.getInt(5);
+ pos2.y = set.getInt(6);
+ obj.Lyric = pos2;
+ obj.EnableLyric = set.getInt(7) == 1;
+ PosObj pos3 = new PosObj();
+ pos3.x = set.getInt(8);
+ pos3.y = set.getInt(9);
+ obj.List = pos3;
+ obj.EnableList = set.getInt(10) == 1;
+ PosObj pos4 = new PosObj();
+ pos4.x = set.getInt(11);
+ pos4.y = set.getInt(12);
+ obj.Pic = pos4;
+ obj.EnablePic = set.getInt(13) == 1;
+ obj.PicSize = set.getInt(14);
+ obj.EnablePicRotate = set.getInt(15) == 1;
+ obj.PicRotateSpeed = set.getInt(16);
+ HudUtils.add(name, obj);
+ }
+ stat.close();
+ } catch (Exception e) {
+ AllMusic.log.warning("数据库读取错误,请删除关闭服务器删除数据库,在启动服务器");
+ e.printStackTrace();
+ }
+ }
+
+ public static void task(Runnable runnable) {
+ tasks.add(runnable);
+ semaphore.release();
+ }
+
+ /**
+ * 启用Hud数据库
+ */
+ public static void start() {
+ init();
+ readAll();
+ Thread thread = new Thread(DataSql::run);
+ isRun = true;
+ thread.start();
+ }
+
+ /**
+ * 停止数据库
+ */
+ public static void stop() {
+ isRun = false;
+ semaphore.release();
+ HudUtils.save();
+ }
+
+ private static void run() {
+ Runnable runnable;
+ while (isRun) {
+ try {
+ semaphore.acquire();
+ if (!isRun)
+ return;
+ do {
+ runnable = tasks.poll();
+ if (runnable != null) {
+ runnable.run();
+ }
+ }
+ while (runnable != null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/hud/HudUtils.java b/server/src/main/java/coloryr/allmusic/core/hud/HudUtils.java
new file mode 100644
index 00000000..d4c3131f
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/hud/HudUtils.java
@@ -0,0 +1,348 @@
+package coloryr.allmusic.core.hud;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.enums.HudPos;
+import coloryr.allmusic.core.music.play.LyricSave;
+import coloryr.allmusic.core.music.play.PlayMusic;
+import coloryr.allmusic.core.objs.hud.PosObj;
+import coloryr.allmusic.core.objs.hud.SaveObj;
+import coloryr.allmusic.core.objs.music.SongInfoObj;
+import coloryr.allmusic.core.utils.Function;
+import com.google.gson.Gson;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class HudUtils {
+ private static final Map huds = new ConcurrentHashMap<>();
+
+ public static SaveObj get(String name) {
+ if (!huds.containsKey(name)) {
+ SaveObj obj = AllMusic.getConfig().DefaultHud.copy();
+ huds.put(name, obj);
+ DataSql.task(() -> DataSql.addUser(name, obj));
+ return obj;
+ }
+ return huds.get(name);
+ }
+
+ public static void add(String name, SaveObj hud) {
+ huds.put(name, hud);
+ }
+
+ public static void addAndSave(String name, SaveObj hud) {
+ huds.put(name, hud);
+ DataSql.task(() -> DataSql.addUser(name, hud));
+ }
+
+ public static void save() {
+ for (Map.Entry item : huds.entrySet()) {
+ DataSql.addUser(item.getKey(), item.getValue());
+ }
+ }
+
+ /**
+ * 设置玩家Hud位置
+ *
+ * @param player 用户名
+ * @param pos 位置
+ * @param x x
+ * @param y y
+ * @return 位置数据
+ */
+ public static PosObj setHudPos(String player, String pos, String x, String y) {
+ SaveObj obj = get(player);
+ if (obj == null)
+ obj = AllMusic.getConfig().DefaultHud.copy();
+ HudPos pos1 = HudPos.valueOf(pos);
+ PosObj posOBJ = new PosObj(0, 0);
+ if (!Function.isInteger(x) && !Function.isInteger(y))
+ return null;
+ int x1 = Integer.parseInt(x);
+ int y1 = Integer.parseInt(y);
+
+ switch (pos1) {
+ case lyric:
+ posOBJ = obj.Lyric;
+ break;
+ case list:
+ posOBJ = obj.List;
+ break;
+ case info:
+ posOBJ = obj.Info;
+ break;
+ case pic:
+ posOBJ = obj.Pic;
+ }
+ posOBJ.x = x1;
+ posOBJ.y = y1;
+
+ addAndSave(player, obj);
+ AllMusic.save();
+ HudUtils.sendHudPos(player);
+ return posOBJ;
+ }
+
+ /**
+ * 更新Hud的List数据
+ */
+ public static void sendHudListData() {
+ String info;
+ if (PlayMusic.getSize() == 0) {
+ info = AllMusic.getMessage().Hud.NoList;
+ } else {
+ String now;
+ StringBuilder list = new StringBuilder();
+ for (SongInfoObj info1 : PlayMusic.getList()) {
+ if (info1 == null)
+ continue;
+ now = info1.getInfo();
+ if (now.length() > AllMusic.getConfig().MessageLimitSize)
+ now = now.substring(0, AllMusic.getConfig().MessageLimitSize - 1) + "...";
+ list.append(now).append("\n");
+ }
+ info = AllMusic.getMessage().Hud.List
+ .replace("%Size%", String.valueOf(PlayMusic.getList().size()))
+ .replace("%List%", list.toString());
+ }
+
+ AllMusic.side.sendHudList(info);
+ }
+
+ /**
+ * 时间转换
+ *
+ * @param time 时间
+ * @return 结果
+ */
+ private static String tranTime(int time) {
+ int m = time / 60;
+ int s = time - m * 60;
+ return (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
+ }
+
+ /**
+ * 更新Hud的信息数据
+ */
+ public static void sendHudNowData() {
+ String info;
+ if (PlayMusic.nowPlayMusic == null) {
+ info = AllMusic.getMessage().Hud.NoMusic;
+ } else {
+ info = AllMusic.getMessage().Hud.Music
+ .replace("%Name%", PlayMusic.nowPlayMusic.getName())
+ .replace("%AllTime%", tranTime(PlayMusic.musicAllTime))
+ .replace("%NowTime%", tranTime(PlayMusic.musicNowTime / 1000))
+ .replace("%Author%", PlayMusic.nowPlayMusic.getAuthor())
+ .replace("%Alia%", PlayMusic.nowPlayMusic.getAlia())
+ .replace("%Al%", PlayMusic.nowPlayMusic.getAl())
+ .replace("%Player%", PlayMusic.nowPlayMusic.getCall());
+ }
+
+ AllMusic.side.sendHudInfo(info);
+ }
+
+ /**
+ * 更新Hud的歌词数据
+ */
+ public static void sendHudLyricData() {
+ String info;
+ LyricSave obj = PlayMusic.lyric;
+ if (obj == null) {
+ info = AllMusic.getMessage().Hud.NoLyric;
+ } else {
+ String lyric = obj.getLyric();
+ String tLyric = obj.getTlyric();
+ String kLyric = obj.getKly();
+ if (!AllMusic.getConfig().KtvMode) {
+ info = AllMusic.getMessage().Hud.Lyric
+ .replace("%Lyric%", lyric == null ? "" : lyric)
+ .replace("%Tlyric%", tLyric != null ? tLyric : "");
+ } else {
+ info = AllMusic.getMessage().Hud.Ktv
+ .replace("%Lyric%", lyric != null ? lyric : "")
+ .replace("%KLyric%", kLyric != null ? kLyric : "")
+ .replace("%Tlyric%", tLyric != null ? tLyric : "");
+ }
+ }
+
+ AllMusic.side.sendHudLyric(info);
+ }
+
+ /**
+ * 更新Hud的开启关闭数据
+ *
+ * @param player 用户名
+ * @param pos 输入数据
+ * @return 设置结果
+ */
+ public static boolean setHudEnable(String player, String pos) {
+ SaveObj obj = get(player);
+ boolean res = false;
+ if (obj == null) {
+ obj = AllMusic.getConfig().DefaultHud.copy();
+ res = obj.EnableInfo && obj.EnableList && obj.EnableLyric;
+ } else {
+ if (pos == null) {
+ if (obj.EnableInfo && obj.EnableList && obj.EnableLyric) {
+ obj.EnableInfo = false;
+ obj.EnableList = false;
+ obj.EnableLyric = false;
+ obj.EnablePic = false;
+ } else {
+ obj.EnableInfo = true;
+ obj.EnableList = true;
+ obj.EnableLyric = true;
+ obj.EnablePic = true;
+ res = true;
+ }
+ } else {
+ HudPos pos1 = HudPos.valueOf(pos);
+ switch (pos1) {
+ case info:
+ obj.EnableInfo = !obj.EnableInfo;
+ break;
+ case list:
+ obj.EnableList = !obj.EnableList;
+ break;
+ case lyric:
+ obj.EnableLyric = !obj.EnableLyric;
+ break;
+ case pic:
+ obj.EnablePic = !obj.EnablePic;
+ break;
+ }
+ }
+ }
+ clearHud(player);
+ addAndSave(player, obj);
+ AllMusic.save();
+ HudUtils.sendHudPos(player);
+ if (pos == null) {
+ return res;
+ } else {
+ HudPos pos1 = HudPos.valueOf(pos);
+ switch (pos1) {
+ case info:
+ return obj.EnableInfo;
+ case list:
+ return obj.EnableList;
+ case lyric:
+ return obj.EnableLyric;
+ case pic:
+ return obj.EnablePic;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 清空Hud数据
+ */
+ public static void clearHud() {
+ AllMusic.side.clearHud();
+ }
+
+ /**
+ * 清空Hud数
+ *
+ * @param player 用户名
+ */
+ public static void clearHud(String player) {
+ AllMusic.side.clearHud(player);
+ }
+
+ /**
+ * 发送Hud位置信息
+ *
+ * @param player 用户名
+ */
+ public static void sendHudPos(String player) {
+ AllMusic.side.runTask(() -> {
+ try {
+ SaveObj obj = get(player);
+ if (obj == null) {
+ obj = AllMusic.getConfig().DefaultHud.copy();
+ addAndSave(player, obj);
+ AllMusic.save();
+ }
+ String data = new Gson().toJson(obj);
+ AllMusic.side.send(data, player);
+ } catch (Exception e1) {
+ AllMusic.log.warning("§d[AllMusic]§c数据发送发生错误");
+ e1.printStackTrace();
+ }
+ });
+ }
+
+ /**
+ * 重置Hud位置
+ *
+ * @param player 用户名
+ */
+ public static void reset(String player) {
+ SaveObj obj = AllMusic.getConfig().DefaultHud.copy();
+ clearHud(player);
+ addAndSave(player, obj);
+ HudUtils.sendHudPos(player);
+ }
+
+ /**
+ * 设置Hud的图片大小
+ *
+ * @param player 用户名
+ * @param size 大小
+ * @return 结果
+ */
+ public static boolean setPicSize(String player, String size) {
+ SaveObj obj = get(player);
+ if (obj == null)
+ obj = AllMusic.getConfig().DefaultHud.copy();
+ if (!Function.isInteger(size))
+ return false;
+
+ obj.PicSize = Integer.parseInt(size);
+
+ addAndSave(player, obj);
+ HudUtils.sendHudPos(player);
+ return true;
+ }
+
+ /**
+ * 图片旋转开关
+ * @param player 用户名
+ * @param open 开关
+ * @return 结果
+ */
+ public static boolean setPicRotate(String player, String open) {
+ SaveObj obj = get(player);
+ if (obj == null)
+ obj = AllMusic.getConfig().DefaultHud.copy();
+
+ obj.EnablePicRotate = Boolean.parseBoolean(open);
+
+ addAndSave(player, obj);
+ HudUtils.sendHudPos(player);
+ return obj.EnablePicRotate;
+ }
+
+ /**
+ * 图片旋转速度设置
+ * @param player 用户名
+ * @param size 大小
+ * @return 结果
+ */
+ public static boolean setPicRotateSpeed(String player, String size){
+ SaveObj obj = get(player);
+ if (obj == null)
+ obj = AllMusic.getConfig().DefaultHud.copy();
+ if (!Function.isInteger(size))
+ return false;
+
+ obj.PicRotateSpeed = Integer.parseInt(size);
+
+ addAndSave(player, obj);
+ HudUtils.sendHudPos(player);
+ return true;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/music/api/APIMain.java b/server/src/main/java/coloryr/allmusic/core/music/api/APIMain.java
new file mode 100644
index 00000000..f9057b23
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/api/APIMain.java
@@ -0,0 +1,342 @@
+package coloryr.allmusic.core.music.api;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.enums.EncryptType;
+import coloryr.allmusic.core.music.play.LyricDo;
+import coloryr.allmusic.core.music.play.LyricSave;
+import coloryr.allmusic.core.music.play.PlayMusic;
+import coloryr.allmusic.core.objs.HttpResObj;
+import coloryr.allmusic.core.objs.SearchMusicObj;
+import coloryr.allmusic.core.objs.api.music.info.InfoObj;
+import coloryr.allmusic.core.objs.api.music.list.DataObj;
+import coloryr.allmusic.core.objs.api.music.lyric.WLyricObj;
+import coloryr.allmusic.core.objs.api.music.search.SearchDataObj;
+import coloryr.allmusic.core.objs.api.music.search.songs;
+import coloryr.allmusic.core.objs.api.music.trialinfo.TrialInfoObj;
+import coloryr.allmusic.core.objs.api.program.info.PrInfoObj;
+import coloryr.allmusic.core.objs.music.SearchPageObj;
+import coloryr.allmusic.core.objs.music.SongInfoObj;
+import coloryr.allmusic.core.utils.Logs;
+import com.google.gson.JsonObject;
+import okhttp3.Cookie;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class APIMain {
+
+ public int PlayNow = 0;
+ public boolean isUpdata;
+
+ public APIMain() {
+ AllMusic.log.info("§d[AllMusic]§e正在初始化网络爬虫");
+ HttpClientUtil.init();
+ HttpResObj res = HttpClientUtil.get("https://music.163.com", "");
+ if (res == null || !res.ok) {
+ AllMusic.log.info("§d[AllMusic]§c初始化网络爬虫连接失败");
+ }
+ }
+
+ /**
+ * 获取手机验证码
+ *
+ * @param sender 发送者
+ */
+ public void sendCode(Object sender) {
+ JsonObject params = new JsonObject();
+ params.addProperty("ctcode", "86");
+ params.addProperty("cellphone", AllMusic.getConfig().LoginUser);
+ HttpResObj res = HttpClientUtil.post("https://music.163.com/api/sms/captcha/sent", params, EncryptType.WEAPI, null);
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§d已发送验证码\n" + res.data);
+ }
+
+ /**
+ * 登录
+ *
+ * @param sender 发送者
+ * @param code 手机验证码
+ */
+ public void login(Object sender, String code) {
+ JsonObject params = new JsonObject();
+ params.addProperty("rememberLogin", "true");
+ if (AllMusic.cookie.cookieStore.containsKey("music.163.com")) {
+ List cookies = AllMusic.cookie.cookieStore.get("music.163.com");
+ for (Cookie item : cookies) {
+ if (item.name().equalsIgnoreCase("os")) {
+ cookies.remove(item);
+ break;
+ }
+ }
+ for (Cookie item : cookies) {
+ if (item.name().equalsIgnoreCase("appver")) {
+ cookies.remove(item);
+ break;
+ }
+ }
+ List cookies1 = new CopyOnWriteArrayList<>();
+ cookies1.addAll(cookies);
+ cookies1.add(new Cookie.Builder().name("os").value("pc").domain("music.163.com").build());
+ cookies1.add(new Cookie.Builder().name("appver").value("2.10.6").domain("music.163.com").build());
+ AllMusic.cookie.cookieStore.put("music.163.com", cookies1);
+ AllMusic.saveCookie();
+ }
+ params.addProperty("countrycode", "86");
+ params.addProperty("phone", AllMusic.getConfig().LoginUser);
+ params.addProperty("captcha", code);
+ HttpResObj res = HttpClientUtil.post("https://music.163.com/eapi/w/login/cellphone", params, EncryptType.WEAPI, null);
+ if (res == null || !res.ok) {
+ if (sender == null)
+ AllMusic.log.info("§d[AllMusic]§c登录失败");
+ else
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§c登录失败");
+ return;
+ }
+ if (res.data.contains("200")) {
+ if (sender == null)
+ AllMusic.log.info("§d[AllMusic]§d已登录");
+ else
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§d已登录");
+ } else {
+ if (sender == null)
+ AllMusic.log.info("§d[AllMusic]§c登录失败:账号或密码错误\n" + res.data);
+ else
+ AllMusic.side.sendMessage(sender, "§d[AllMusic]§c登录失败:账号或密码错误\n" + res.data);
+ }
+ }
+
+ /**
+ * 获取音乐详情
+ *
+ * @param id 音乐ID
+ * @param player 用户名
+ * @param isList 是否是空闲列表
+ * @return 结果
+ */
+ private SongInfoObj getMusicDetail(String id, String player, boolean isList) {
+ JsonObject params = new JsonObject();
+ params.addProperty("c", "[{\"id\":" + id + "}]");
+
+ HttpResObj res = HttpClientUtil.post("https://music.163.com/api/v3/song/detail", params, EncryptType.WEAPI, null);
+ if (res != null && res.ok) {
+ InfoObj temp = AllMusic.gson.fromJson(res.data, InfoObj.class);
+ if (temp.isOk()) {
+ params = new JsonObject();
+ params.addProperty("ids", "[" + id + "]");
+ params.addProperty("br", "320000");
+ res = HttpClientUtil.post("https://music.163.com/weapi/song/enhance/player/url", params, EncryptType.WEAPI, null);
+ if (res == null || !res.ok) {
+ AllMusic.log.warning("§d[AllMusic]§c版权检索失败");
+ return null;
+ }
+ TrialInfoObj obj = AllMusic.gson.fromJson(res.data, TrialInfoObj.class);
+ return new SongInfoObj(temp.getAuthor(), temp.getName(),
+ id, temp.getAlia(), player, temp.getAl(), isList, temp.getLength(),
+ temp.getPicUrl(), obj.isTrial(), obj.getFreeTrialInfo());
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 获取音乐数据
+ *
+ * @param id 音乐ID
+ * @param player 用户名
+ * @param isList 是否是空闲列表
+ * @return 结果
+ */
+ public SongInfoObj getMusic(String id, String player, boolean isList) {
+ SongInfoObj info = getMusicDetail(id, player, isList);
+ if (info != null)
+ return info;
+ JsonObject params = new JsonObject();
+ params.addProperty("id", id);
+ HttpResObj res = HttpClientUtil.post("https://music.163.com/api/dj/program/detail", params, EncryptType.WEAPI, null);
+ if (res != null && res.ok) {
+ PrInfoObj temp = AllMusic.gson.fromJson(res.data, PrInfoObj.class);
+ if (temp.isOk()) {
+ return new SongInfoObj(temp.getAuthor(), temp.getName(),
+ temp.getId(), temp.getAlia(), player, "电台", isList, temp.getLength(),
+ null, false, null);
+ } else {
+ AllMusic.log.warning("§d[AllMusic]§c歌曲信息获取为空");
+ }
+ }
+ return info;
+ }
+
+ /**
+ * 获取播放链接
+ *
+ * @param id 音乐ID
+ * @return 结果
+ */
+ public String getPlayUrl(String id) {
+ JsonObject params = new JsonObject();
+ params.addProperty("ids", "[" + id + "]");
+ params.addProperty("br", AllMusic.getConfig().MusicBR);
+ HttpResObj res = HttpClientUtil.post("https://music.163.com/weapi/song/enhance/player/url", params, EncryptType.WEAPI, null);
+ if (res != null && res.ok) {
+ try {
+ TrialInfoObj obj = AllMusic.gson.fromJson(res.data, TrialInfoObj.class);
+ return obj.getUrl();
+ } catch (Exception e) {
+ Logs.logWrite(res.data);
+ AllMusic.log.warning("§d[AllMusic]§c播放连接解析错误");
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 添加空闲歌单
+ *
+ * @param id 歌单id
+ * @param sender 发送者
+ */
+ public void setList(String id, Object sender) {
+ final Thread thread = new Thread(() -> {
+ JsonObject params = new JsonObject();
+ params.addProperty("id", id);
+ params.addProperty("n", 100000);
+ params.addProperty("s", 8);
+ HttpResObj res = HttpClientUtil.post("https://music.163.com/api/v6/playlist/detail", params, EncryptType.API, null);
+ if (res != null && res.ok)
+ try {
+ isUpdata = true;
+ DataObj obj = AllMusic.gson.fromJson(res.data, DataObj.class);
+ AllMusic.getConfig().PlayList.addAll(obj.getPlaylist());
+ AllMusic.save();
+ AllMusic.side.sendMessaget(sender, AllMusic.getMessage().MusicPlay.ListMusic.Get.replace("%ListName%", obj.getName()));
+ } catch (Exception e) {
+ AllMusic.log.warning("§d[AllMusic]§c歌曲列表获取错误");
+ e.printStackTrace();
+ }
+ isUpdata = false;
+ }, "AllMusic_setList");
+ thread.start();
+ }
+
+ /**
+ * 获取歌词
+ *
+ * @param id 歌曲id
+ * @return 结果
+ */
+ public LyricSave getLyric(String id) {
+ LyricSave lyric = new LyricSave();
+ JsonObject params = new JsonObject();
+ params.addProperty("id", id);
+ 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);
+ HttpResObj res = HttpClientUtil.post("https://interface3.music.163.com/eapi/song/lyric/v1",
+ params, EncryptType.EAPI, "/api/song/lyric/v1");
+ if (res != null && res.ok) {
+ try {
+ WLyricObj obj = AllMusic.gson.fromJson(res.data, WLyricObj.class);
+ LyricDo temp = new LyricDo();
+ for (int times = 0; times < 3; times++) {
+ if (temp.check(obj)) {
+ AllMusic.log.warning("§d[AllMusic]§c歌词解析错误,正在进行第" + times + "重试");
+ } else {
+ if (temp.isHave) {
+ lyric.setHaveLyric(AllMusic.getConfig().SendLyric);
+ lyric.setLyric(temp.getTemp());
+ if (temp.isHaveK) {
+ lyric.setKlyric(temp.getKLyric());
+ }
+ }
+ return lyric;
+ }
+ Thread.sleep(1000);
+ }
+ AllMusic.log.warning("§d[AllMusic]§c歌词解析失败");
+ } catch (Exception e) {
+ AllMusic.log.warning("§d[AllMusic]§c歌词解析错误");
+ e.printStackTrace();
+ }
+ }
+ return lyric;
+ }
+
+ /**
+ * 搜歌
+ *
+ * @param name 关键字
+ * @param isDefault 是否是默认方式
+ * @return 结果
+ */
+ public SearchPageObj search(String[] name, boolean isDefault) {
+ List resData = new ArrayList<>();
+ int maxpage;
+
+ StringBuilder name1 = new StringBuilder();
+ for (int a = isDefault ? 0 : 1; a < name.length; a++) {
+ name1.append(name[a]).append(" ");
+ }
+ String MusicName = name1.toString();
+ MusicName = MusicName.substring(0, MusicName.length() - 1);
+
+ JsonObject params = new JsonObject();
+ params.addProperty("s", MusicName);
+ params.addProperty("type", 1);
+ params.addProperty("limit", 30);
+ params.addProperty("offset", 0);
+
+ HttpResObj res = HttpClientUtil.post("https://music.163.com/weapi/search/get", params, EncryptType.WEAPI, null);
+ if (res != null && res.ok) {
+ SearchDataObj obj = AllMusic.gson.fromJson(res.data, SearchDataObj.class);
+ if (obj != null && obj.isOk()) {
+ List res1 = obj.getResult();
+ SearchMusicObj item;
+ for (songs temp : res1) {
+ item = new SearchMusicObj(String.valueOf(temp.getId()), temp.getName(), temp.getArtists(), temp.getAlbum());
+ resData.add(item);
+ }
+ maxpage = res1.size() / 10;
+ return new SearchPageObj(resData, maxpage);
+ } else {
+ AllMusic.log.warning("§d[AllMusic]§c歌曲搜索出现错误");
+
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 获取空闲歌单的一首歌
+ *
+ * @return 结果
+ */
+ public String getListMusic() {
+ if (PlayMusic.error >= 10)
+ return null;
+ if (!isUpdata && AllMusic.getConfig().PlayList.size() != 0) {
+ String ID;
+ if (AllMusic.getConfig().PlayListRandom) {
+ if (AllMusic.getConfig().PlayList.size() == 0)
+ return null;
+ else if (AllMusic.getConfig().PlayList.size() == 1)
+ return AllMusic.getConfig().PlayList.get(0);
+ ID = AllMusic.getConfig().PlayList.get(new Random().nextInt(AllMusic.getConfig().PlayList.size()));
+ } else {
+ ID = AllMusic.getConfig().PlayList.get(PlayNow);
+ if (PlayNow == AllMusic.getConfig().PlayList.size() - 1)
+ PlayNow = 0;
+ else
+ PlayNow++;
+ }
+ return ID;
+ }
+ return null;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/music/api/CryptoUtil.java b/server/src/main/java/coloryr/allmusic/core/music/api/CryptoUtil.java
new file mode 100644
index 00000000..2e7bb5d7
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/api/CryptoUtil.java
@@ -0,0 +1,137 @@
+package coloryr.allmusic.core.music.api;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.api.EncResObj;
+import com.google.gson.JsonObject;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+
+public class CryptoUtil {
+
+ private static final String presetKey = "0CoJUm6Qyw8W8jud";
+ private static final String iv = "0102030405060708";
+ private static final String base62 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
+ private static final String eapiKey = "e82ckenh8dichen8";
+
+ private static String createSecretKey(int size) {
+ StringBuilder key = new StringBuilder();
+ for (int i = 0; i < size; i++) {
+ double index = Math.floor(Math.random() * base62.length());
+ key.append(base62.charAt((int) index));
+ }
+ return key.toString();
+ }
+
+ public static String byteArrToHex(byte[] bytes) {
+ char[] hexChars = new char[bytes.length * 2];
+ for (int j = 0; j < bytes.length; j++) {
+ int v = bytes[j] & 0xFF;
+ hexChars[j * 2] = hexArray[v >>> 4];
+ hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+ }
+ return new String(hexChars);
+ }
+
+ private static String aesEncrypt(String content, String key, String iv) {
+ String result = null;
+ if (content == null || key == null)
+ return result;
+ try {
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
+ byte[] keys = key.getBytes(StandardCharsets.UTF_8);
+ byte[] ivs = iv.getBytes(StandardCharsets.UTF_8);
+ cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keys, "AES"),
+ new IvParameterSpec(ivs));
+ bytes = cipher.doFinal(bytes);
+ result = Base64.getEncoder().encodeToString(bytes);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ private static String aesEncrypt(String content, String key) {
+ String result = null;
+ if (content == null || key == null)
+ return result;
+ try {
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+ byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
+ byte[] keys = key.getBytes(StandardCharsets.UTF_8);
+ cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keys, "AES"));
+ bytes = cipher.doFinal(bytes);
+ result = byteArrToHex(bytes).toUpperCase();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ private static String zFill(String str) {
+ StringBuilder strBuilder = new StringBuilder(str);
+ while (strBuilder.length() < 256) {
+ strBuilder.insert(0, "0");
+ }
+ str = strBuilder.toString();
+ return str;
+ }
+
+ private static String rsaEncrypt(String text) {
+ text = new StringBuffer(text).reverse().toString();
+
+ BigInteger biText = new BigInteger(strToHex(text), 16);
+ BigInteger biEx = new BigInteger("010001", 16);
+ BigInteger biMod = new BigInteger("00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7", 16);
+ BigInteger biRet = biText.modPow(biEx, biMod);
+
+ return zFill(biRet.toString(16));
+ }
+
+ private static String strToHex(String s) {
+ StringBuilder str = new StringBuilder();
+ for (int i = 0; i < s.length(); i++) {
+ int ch = s.charAt(i);
+ String s4 = Integer.toHexString(ch);
+ str.append(s4);
+ }
+ return str.toString();
+ }
+
+ public static EncResObj weapiEncrypt(String content) {
+ String key = createSecretKey(16);
+ String encText = aesEncrypt(aesEncrypt(content, presetKey, iv), key, iv);
+ String encSecKey = rsaEncrypt(key);
+ return new EncResObj(encText, encSecKey);
+ }
+
+ public static EncResObj eapi(String url, JsonObject object) {
+ String text = AllMusic.gson.toJson(object);
+ String message = "nobody" + url + "use" + text + "md5forencrypt";
+ String digest = getMd5(message);
+ String data = url + "-36cd479b6b5-" + text + "-36cd479b6b5-" + digest;
+ return new EncResObj(aesEncrypt(data, eapiKey), "");
+ }
+
+ public static String getMd5(String plainText) {
+ byte[] secretBytes;
+ try {
+ MessageDigest digest = MessageDigest.getInstance("md5");
+ digest.update(plainText.getBytes(StandardCharsets.UTF_8));
+ secretBytes = digest.digest();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("没有这个md5算法!");
+ }
+ return byteArrToHex(secretBytes);
+ }
+}
\ No newline at end of file
diff --git a/server/src/main/java/coloryr/allmusic/core/music/api/HttpClientUtil.java b/server/src/main/java/coloryr/allmusic/core/music/api/HttpClientUtil.java
new file mode 100644
index 00000000..d2eda7dd
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/api/HttpClientUtil.java
@@ -0,0 +1,171 @@
+package coloryr.allmusic.core.music.api;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.enums.EncryptType;
+import coloryr.allmusic.core.objs.HttpResObj;
+import coloryr.allmusic.core.objs.api.EncResObj;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import okhttp3.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class HttpClientUtil {
+
+ private static final int CONNECT_TIMEOUT = 5;
+ private static final int READ_TIMEOUT = 7;
+ private static OkHttpClient client;
+
+ public static void init() {
+ try {
+ synchronized (OkHttpClient.class) {
+ client = new OkHttpClient.Builder().cookieJar(new MyCookieJar())
+ .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
+ .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
+ .build();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static HttpResObj get(String path, String data) {
+ try {
+ data = URLEncoder.encode(data, "UTF-8");
+ Request request = new Request.Builder().url(path + data)
+ .addHeader("referer", "https://music.163.com")
+ .addHeader("content-type", "application/json;charset=UTF-8")
+ .addHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 Edg/91.0.864.41")
+ .get()
+ .build();
+ Response response = client.newCall(request).execute();
+ int httpCode = response.code();
+ ResponseBody body = response.body();
+ if (body == null) {
+ AllMusic.log.warning("§d[AllMusic]§c获取网页错误");
+ return null;
+ }
+ InputStream inputStream = body.byteStream();
+ boolean ok = httpCode == 200;
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[4096];
+ int length;
+ while ((length = inputStream.read(buffer)) != -1) {
+ result.write(buffer, 0, length);
+ }
+ String data1 = result.toString(StandardCharsets.UTF_8.name());
+ if (!ok) {
+ AllMusic.log.warning("§d[AllMusic]§c服务器返回错误:" + data1);
+ }
+ return new HttpResObj(data1, ok);
+ } catch (Exception e) {
+ AllMusic.log.warning("§d[AllMusic]§c获取网页错误");
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static HttpResObj post(String url, JsonObject data, EncryptType type, String ourl) {
+ try {
+ RequestBody formBody;
+ Request.Builder request = new Request.Builder();
+ request = request.addHeader("Content-Type", "application/x-www-form-urlencoded");
+ request = request.addHeader("Referer", "https://music.163.com");
+ EncResObj res;
+ List cookies = new ArrayList<>();
+ if (AllMusic.cookie.cookieStore.containsKey("music.163.com")) {
+ cookies = AllMusic.cookie.cookieStore.get("music.163.com");
+ }
+ if (type == EncryptType.WEAPI) {
+ request = request.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/13.10586");
+ String csrfToken = "";
+ for (Cookie item : cookies) {
+ if (item.name().equalsIgnoreCase("__csrf")) {
+ csrfToken = item.value();
+ }
+ }
+ data.addProperty("csrf_token", csrfToken);
+ res = CryptoUtil.weapiEncrypt(AllMusic.gson.toJson(data));
+ url = url.replaceFirst("\\w*api", "weapi");
+ request = request.url(url);
+ formBody = new FormBody.Builder()
+ .add("params", res.params)
+ .add("encSecKey", res.encSecKey)
+ .build();
+ } else if (type == EncryptType.EAPI) {
+ request = request.addHeader("User-Agent", "Mozilla/5.0 (Linux; Android 9; PCT-AL10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.311 Mobile Safari/537.36");
+ JsonObject header = new JsonObject();
+ header.addProperty("appver", "8.0.0");
+ header.addProperty("versioncode", "140");
+ header.addProperty("buildver", new Date().toString().substring(0, 10));
+ header.addProperty("resolution", "1920x1080");
+ header.addProperty("os", "android");
+ String requestId = "0000" + (new Date() + "_" + Math.floor(Math.random() * 1000));
+ header.addProperty("requestId", requestId);
+ for (Cookie item : cookies) {
+ if (item.name().equalsIgnoreCase("MUSIC_U")) {
+ header.addProperty("MUSIC_U", item.value());
+ } else if (item.name().equalsIgnoreCase("MUSIC_A")) {
+ header.addProperty("MUSIC_A", item.value());
+ } else if (item.name().equalsIgnoreCase("channel")) {
+ header.addProperty("channel", item.value());
+ } else if (item.name().equalsIgnoreCase("mobilename")) {
+ header.addProperty("mobilename", item.value());
+ } else if (item.name().equalsIgnoreCase("osver")) {
+ header.addProperty("osver", item.value());
+ } else if (item.name().equalsIgnoreCase("__csrf")) {
+ header.addProperty("__csrf", item.value());
+ }
+ }
+
+ data.add("header", header);
+ res = CryptoUtil.eapi(ourl, data);
+ url = url.replaceFirst("\\w*api", "eapi");
+ request = request.url(url);
+ formBody = new FormBody.Builder()
+ .add("params", res.params)
+ .build();
+ } else {
+ request = request.url(url);
+ FormBody.Builder builder = new FormBody.Builder();
+ for (Map.Entry item : data.entrySet()) {
+ builder = builder.add(item.getKey(), item.getValue().getAsString());
+ }
+ formBody = builder.build();
+ }
+ request = request.post(formBody);
+ Response response = client.newCall(request.build()).execute();
+ int httpCode = response.code();
+ ResponseBody body = response.body();
+ if (body == null) {
+ AllMusic.log.warning("§d[AllMusic]§c获取网页错误");
+ return null;
+ }
+ InputStream inputStream = body.byteStream();
+ boolean ok = httpCode == 200;
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[4096];
+ int length;
+ while ((length = inputStream.read(buffer)) != -1) {
+ result.write(buffer, 0, length);
+ }
+ String data1 = result.toString(StandardCharsets.UTF_8.name());
+ if (!ok) {
+ AllMusic.log.warning("§d[AllMusic]§c服务器返回错误:" + data1);
+ }
+ return new HttpResObj(data1, ok);
+ } catch (Exception e) {
+ AllMusic.log.warning("§d[AllMusic]§c获取网页错误");
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/music/api/MyCookieJar.java b/server/src/main/java/coloryr/allmusic/core/music/api/MyCookieJar.java
new file mode 100644
index 00000000..b9ebaa26
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/api/MyCookieJar.java
@@ -0,0 +1,38 @@
+package coloryr.allmusic.core.music.api;
+
+import coloryr.allmusic.core.AllMusic;
+import okhttp3.Cookie;
+import okhttp3.CookieJar;
+import okhttp3.HttpUrl;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class MyCookieJar implements CookieJar {
+ @Override
+ public void saveFromResponse(HttpUrl httpUrl, @NotNull List list) {
+ if (AllMusic.cookie.cookieStore.containsKey(httpUrl.host())) {
+ List cookies = AllMusic.cookie.cookieStore.get(httpUrl.host());
+ for (Cookie item : list) {
+ for (Cookie item1 : cookies) {
+ if (item.name().equalsIgnoreCase(item1.name())) {
+ cookies.remove(item1);
+ break;
+ }
+ }
+ cookies.add(item);
+ }
+ AllMusic.cookie.cookieStore.put(httpUrl.host(), cookies);
+ } else {
+ AllMusic.cookie.cookieStore.put(httpUrl.host(), list);
+ }
+ AllMusic.saveCookie();
+ }
+
+ @Override
+ public @NotNull List loadForRequest(HttpUrl httpUrl) {
+ List cookies = AllMusic.cookie.cookieStore.get(httpUrl.host());
+ return cookies != null ? cookies : new CopyOnWriteArrayList<>();
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/music/play/LyricDo.java b/server/src/main/java/coloryr/allmusic/core/music/play/LyricDo.java
new file mode 100644
index 00000000..67b293bc
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/play/LyricDo.java
@@ -0,0 +1,171 @@
+package coloryr.allmusic.core.music.play;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.api.music.lyric.WLyricObj;
+import coloryr.allmusic.core.objs.music.LyricItemObj;
+import coloryr.allmusic.core.utils.Function;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class LyricDo {
+ private static final Pattern p = Pattern.compile("\\(([0-9]+),[0-9]+.[0-9]\\)");
+ private final Map temp = new LinkedHashMap<>();
+ public boolean isHave = false;
+ public boolean isHaveK = false;
+ public Map kly = new LinkedHashMap<>();
+
+ public Map getTemp() {
+ return temp;
+ }
+
+ public Map getKLyric() {
+ return kly;
+ }
+
+ /**
+ * 检查歌词
+ *
+ * @param obj 歌词
+ * @return 结果
+ */
+ public boolean check(WLyricObj obj) {
+ String[] lyric;
+
+ boolean haveT = false;
+ if (!obj.isOk())
+ return true;
+ else if (obj.isNone())
+ return false;
+ lyric = obj.getLyric().split("\n");
+
+ Map temp = getTime(Arrays.asList(lyric));
+ Map temp1 = new HashMap<>();
+
+ if (obj.getTlyric() != null) {
+ List tlyric = Arrays.asList(obj.getTlyric().split("\n"));
+ haveT = true;
+ temp1 = getTime(tlyric);
+ }
+
+ String temp2 = obj.getYrc() == null ? obj.getKlyric() : obj.getYrc();
+
+ if (temp2 != null && !temp2.isEmpty()) {
+ String[] klyric = temp2.split("\n");
+ for (String item : klyric) {
+ Map temp4 = getKTime(item, obj.getVersion());
+ if (temp4 != null) {
+ kly.putAll(temp4);
+ }
+ }
+ isHaveK = true;
+ }
+
+ for (Map.Entry item : temp.entrySet()) {
+ this.temp.put(item.getKey(), new LyricItemObj(item.getValue(),
+ haveT ? temp1.get(item.getKey()) : null));
+ }
+
+
+ isHave = true;
+ return false;
+ }
+
+ /**
+ * 将歌词转换成时间 字
+ *
+ * @param lyric 歌词
+ * @return 结果
+ */
+ private Map getTime(List lyric) {
+ Map res = new LinkedHashMap<>();
+ String min;
+ String sec;
+ String mil;
+ int time;
+ int milt;
+ for (String s : lyric) {
+ if (!s.startsWith("["))
+ continue;
+ String temp = Function.getString(s, "[", "]");
+ if (!temp.contains(".") || !temp.contains(":"))
+ continue;
+ if (Function.countChar(temp, ':') > 1) {
+ String[] a = s.split(":");
+ min = a[0].substring(1);
+ sec = a[1];
+ mil = a[2];
+ } else {
+ min = Function.getString(s, "[", ":");
+ sec = Function.getString(s, ":", ".");
+ mil = Function.getString(s, ".", "]");
+ }
+ if (!Function.isInteger(min))
+ continue;
+ if (!Function.isInteger(sec))
+ continue;
+ if (!Function.isInteger(mil))
+ continue;
+ if (min.isEmpty() || sec.isEmpty() || mil.isEmpty())
+ continue;
+ milt = Integer.parseInt(mil);
+ if (mil.length() == 3) {
+ milt /= 10;
+ }
+ time = Integer.parseInt(min) * 60 * 1000 + Integer.parseInt(sec) * 1000 + milt * 10;
+ if (time > 0 && time + AllMusic.getConfig().Delay > 0)
+ time += AllMusic.getConfig().Delay / 10 * 10;
+ res.put(time, Function.getString(s, "]", null));
+ }
+ return res;
+ }
+
+ private Map getKTime(String lyric, boolean yrc) {
+ Map res = new LinkedHashMap<>();
+ if (!lyric.startsWith("[") || !lyric.contains("]("))
+ return null;
+
+ String[] datas = lyric.split("\\(([0-9]+),[0-9]+.[0-9]\\)");
+ Matcher m = p.matcher(lyric);
+ List temp1111 = new ArrayList<>();
+ while (m.find()) {
+ temp1111.add(m.group()
+ .replace("(", "")
+ .replace(")", ""));
+ }
+ if (datas.length == 1)
+ return null;
+
+ String temp = Function.getString(lyric, "[", "]");
+ String[] temp11 = temp.split(",");
+ int now = Integer.parseInt(temp11[0]) / 10 * 10;
+ for (int a = 1; a < datas.length; a++) {
+ String data = datas[a];
+ String temp3 = temp1111.get(a - 1);
+ String[] temp8 = temp3.split(",");
+ int temp5;
+ if (yrc) {
+ temp5 = (Integer.parseInt(temp8[0]) / 10 * 10);
+ if (temp5 > 0 && temp5 + AllMusic.getConfig().KDelay > 0)
+ temp5 += (AllMusic.getConfig().KDelay / 10 * 10);
+ res.put(temp5, data);
+ } else {
+ try {
+ temp5 = (Integer.parseInt(temp8[1]) / 10 * 10);
+ } catch (Exception e) {
+ AllMusic.log.warning("不支持的Ktv歌词");
+ AllMusic.log.warning("请带上音乐ID联系开发者");
+ return null;
+ }
+
+ if (temp5 > 0 && temp5 + AllMusic.getConfig().KDelay > 0)
+ temp5 += (AllMusic.getConfig().KDelay / 10 * 10);
+ res.put(now, data);
+ now += temp5;
+ }
+ }
+
+ return res;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/music/play/LyricSave.java b/server/src/main/java/coloryr/allmusic/core/music/play/LyricSave.java
new file mode 100644
index 00000000..f53dc76b
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/play/LyricSave.java
@@ -0,0 +1,110 @@
+package coloryr.allmusic.core.music.play;
+
+import coloryr.allmusic.core.objs.music.LyricItemObj;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+public class LyricSave {
+ public int lastIndex = 0;
+ protected boolean haveLyric;
+ protected String lly;
+ protected String kly;
+ protected String tly;
+ private Map lyric;
+ private Map klyric;
+ private LyricItemObj now;
+ private int last;
+ private String kNow;
+
+ public LyricSave() {
+ haveLyric = false;
+ lyric = new HashMap<>();
+ }
+
+ public void setKlyric(Map klyric) {
+ this.klyric = klyric;
+ }
+
+ public boolean isHaveLyric() {
+ return haveLyric;
+ }
+
+ public void setHaveLyric(boolean haveLyric) {
+ this.haveLyric = haveLyric;
+ }
+
+ public String getLyric() {
+ return lly;
+ }
+
+ public void setLyric(Map lyric) {
+ this.lyric = lyric;
+ }
+
+ public String getTlyric() {
+ return tly;
+ }
+
+ public String getKly() {
+ return kly;
+ }
+
+ public boolean kUpdate() {
+ if (lastIndex >= now.lyric.length()) {
+ kly = now.lyric;
+ lly = "";
+ } else if (kNow != null) {
+ int index = now.lyric.toLowerCase(Locale.ROOT).indexOf(kNow, lastIndex);
+ if (index != -1) {
+ lastIndex = index + kNow.length();
+
+ kly = now.lyric.substring(0, lastIndex);
+ lly = now.lyric.substring(lastIndex);
+ return true;
+ }
+ } else {
+ kly = "";
+ }
+
+ return false;
+ }
+
+ public boolean ktv(int time) {
+ if (last == time || klyric == null)
+ return false;
+
+ String temp = klyric.get(time);
+ if (temp != null) {
+ kNow = temp.toLowerCase(Locale.ROOT);
+ last = time;
+ return kUpdate();
+ }
+
+ return false;
+ }
+
+ public boolean checkTime(int playNow, boolean ktv) {
+ if (lyric == null)
+ return false;
+
+ boolean res = false;
+ LyricItemObj temp = lyric.get(playNow);
+ if (temp != null) {
+ now = temp;
+ lly = now.lyric;
+ tly = now.tlyric;
+ kly = null;
+ lastIndex = 0;
+ kUpdate();
+ return true;
+ }
+
+ if (ktv && now != null) {
+ res = ktv(playNow);
+ }
+
+ return res;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/music/play/MusicSearch.java b/server/src/main/java/coloryr/allmusic/core/music/play/MusicSearch.java
new file mode 100644
index 00000000..9b4e206b
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/play/MusicSearch.java
@@ -0,0 +1,51 @@
+package coloryr.allmusic.core.music.play;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.command.CommandEX;
+import coloryr.allmusic.core.objs.music.MusicObj;
+import coloryr.allmusic.core.objs.music.SearchPageObj;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+public class MusicSearch {
+ private static final Queue tasks = new ConcurrentLinkedQueue<>();
+ private static boolean isRun;
+
+ private static void task() {
+ while (isRun) {
+ try {
+ MusicObj obj = tasks.poll();
+ if (obj != null) {
+ SearchPageObj search = AllMusic.getMusicApi().search(obj.args, obj.isDefault);
+ if (search == null)
+ AllMusic.side.sendMessaget(obj.sender, AllMusic.getMessage().Search
+ .CantSearch.replace("%Music%", obj.isDefault ? obj.args[0] : obj.args[1]));
+ else {
+ AllMusic.side.sendMessaget(obj.sender, AllMusic.getMessage().Search.Res);
+ AllMusic.addSearch(obj.name, search);
+ AllMusic.side.runTask(() -> CommandEX.showSearch(obj.sender, search));
+ }
+ }
+ Thread.sleep(100);
+ } catch (Exception e) {
+ AllMusic.log.warning("搜歌出现问题");
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static void start() {
+ Thread taskT = new Thread(MusicSearch::task, "AllMusic_search");
+ isRun = true;
+ taskT.start();
+ }
+
+ public static void stop() {
+ isRun = false;
+ }
+
+ public static void addSearch(MusicObj obj) {
+ tasks.add(obj);
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/music/play/PlayGo.java b/server/src/main/java/coloryr/allmusic/core/music/play/PlayGo.java
new file mode 100644
index 00000000..0ceadd3a
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/play/PlayGo.java
@@ -0,0 +1,230 @@
+package coloryr.allmusic.core.music.play;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.hud.HudUtils;
+import coloryr.allmusic.core.objs.music.MusicObj;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class PlayGo {
+ /**
+ * 播放链接
+ */
+ public static String url;
+ /**
+ * 倒数计数器
+ */
+ private static int count = 0;
+ private static boolean isRun;
+ /**
+ * 歌曲更新计数器
+ */
+ private static int times = 0;
+ private static ScheduledExecutorService service;
+ private static ScheduledExecutorService service1;
+ private static ScheduledExecutorService service2;
+
+ /**
+ * 启动歌曲工作
+ */
+ public static void start() {
+ Thread taskT = new Thread(PlayGo::task, "AllMusic_Play");
+ isRun = true;
+ taskT.start();
+
+ service2 = Executors.newSingleThreadScheduledExecutor();
+ service2.scheduleAtFixedRate(PlayGo::time3, 0, 10, TimeUnit.SECONDS);
+ }
+
+ /**
+ * 停止歌曲工作
+ */
+ public static void stop() {
+ closeTimer();
+ isRun = false;
+ PlayMusic.musicLessTime = 0;
+ }
+
+ private static void closeTimer() {
+ if (service != null) {
+ service.shutdown();
+ service = null;
+ }
+ if (service1 != null) {
+ service1.shutdown();
+ service1 = null;
+ }
+ if (service2 != null) {
+ service2.shutdown();
+ service2 = null;
+ }
+ }
+
+ private static void startTimer() {
+ service = Executors.newSingleThreadScheduledExecutor();
+ service.scheduleAtFixedRate(PlayGo::time1, 0, 10, TimeUnit.MILLISECONDS);
+ if (PlayMusic.lyric != null && PlayMusic.lyric.isHaveLyric()) {
+ service1 = Executors.newSingleThreadScheduledExecutor();
+ service1.scheduleAtFixedRate(PlayGo::time2, 0, 2, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ /**
+ * 清空歌曲数据
+ */
+ private static void clear() {
+ closeTimer();
+ PlayMusic.musicNowTime = 0;
+ PlayMusic.musicAllTime = 0;
+ PlayMusic.musicLessTime = 0;
+ PlayMusic.lyric = null;
+ PlayMusic.nowPlayMusic = null;
+ AllMusic.side.updateInfo();
+ HudUtils.clearHud();
+ }
+
+ private static void time1() {
+ PlayMusic.musicNowTime += 10;
+ count++;
+ if (count == 100) {
+ PlayMusic.musicLessTime--;
+ count = 0;
+ }
+ }
+
+ private static void time2() {
+ try {
+ if (PlayMusic.lyric == null)
+ return;
+ boolean res = PlayMusic.lyric
+ .checkTime(PlayMusic.musicNowTime, AllMusic.getConfig().KtvMode);
+ if (res) {
+ times = 0;
+ HudUtils.sendHudLyricData();
+ AllMusic.side.updateLyric();
+ } else {
+ times++;
+ if (times == 500 && PlayMusic.lyric != null) {
+ times = 0;
+ HudUtils.sendHudLyricData();
+ AllMusic.side.updateLyric();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void time3() {
+ AllMusic.side.ping();
+ }
+
+ private static void task() {
+ while (isRun) {
+ try {
+ if (PlayMusic.getSize() == 0) {
+ HudUtils.sendHudNowData();
+ HudUtils.sendHudLyricData();
+ HudUtils.sendHudListData();
+ if (AllMusic.side.needPlay()) {
+ String ID = AllMusic.getMusicApi().getListMusic();
+ if (ID != null) {
+ MusicObj obj = new MusicObj();
+ obj.sender = ID;
+ obj.name = "空闲列表";
+ obj.isDefault = true;
+ PlayMusic.addMusic(null, ID, "空闲列表", true);
+ }
+ }
+ Thread.sleep(50);
+ } else {
+ AllMusic.side.sendHudUtilsAll();
+ PlayMusic.nowPlayMusic = PlayMusic.remove(0);
+ if (AllMusic.side.onMusicPlay(PlayMusic.nowPlayMusic)) {
+ AllMusic.side.bqt(AllMusic.getMessage().MusicPlay.Cancel);
+ continue;
+ }
+
+ url = PlayMusic.nowPlayMusic.getPlayerUrl() == null ?
+ AllMusic.getMusicApi().getPlayUrl(PlayMusic.nowPlayMusic.getID()) :
+ PlayMusic.nowPlayMusic.getPlayerUrl();
+ if (url == null) {
+ String data = AllMusic.getMessage().MusicPlay.NoCanPlay;
+ AllMusic.side.bqt(data.replace("%MusicID%", PlayMusic.nowPlayMusic.getID()));
+ PlayMusic.nowPlayMusic = null;
+ continue;
+ }
+
+ if (PlayMusic.nowPlayMusic.getPlayerUrl() == null)
+ PlayMusic.lyric = AllMusic.getMusicApi().getLyric(PlayMusic.nowPlayMusic.getID());
+ else
+ PlayMusic.lyric = new LyricSave();
+
+ if (PlayMusic.nowPlayMusic.getLength() != 0) {
+ PlayMusic.musicAllTime = PlayMusic.musicLessTime = (PlayMusic.nowPlayMusic.getLength() / 1000) + 3;
+ if (!AllMusic.getConfig().MutePlayMessage) {
+ String info = AllMusic.getMessage().MusicPlay.Play;
+ info = info.replace("%MusicName%", PlayMusic.nowPlayMusic.getName())
+ .replace("%MusicAuthor%", PlayMusic.nowPlayMusic.getAuthor())
+ .replace("%MusicAl%", PlayMusic.nowPlayMusic.getAl())
+ .replace("%MusicAlia%", PlayMusic.nowPlayMusic.getAlia())
+ .replace("%PlayerName%", PlayMusic.nowPlayMusic.getCall());
+ if (AllMusic.getConfig().ShowInBar)
+ AllMusic.side.sendBar(info);
+ else
+ AllMusic.side.bqt(info);
+ }
+ startTimer();
+ AllMusic.side.sendMusic(url);
+ if (!PlayMusic.nowPlayMusic.isUrl() && PlayMusic.nowPlayMusic.getPicUrl() != null) {
+ AllMusic.side.sendPic(PlayMusic.nowPlayMusic.getPicUrl());
+ }
+ if (PlayMusic.nowPlayMusic.isTrial()) {
+ AllMusic.side.bqt(AllMusic.getMessage().MusicPlay.Trail);
+ PlayMusic.musicLessTime = PlayMusic.nowPlayMusic.getTrialInfo().getEnd();
+ PlayMusic.musicNowTime = PlayMusic.nowPlayMusic.getTrialInfo().getStart();
+ }
+
+ AllMusic.side.updateInfo();
+
+ while (PlayMusic.musicLessTime > 0) {
+ HudUtils.sendHudNowData();
+ HudUtils.sendHudListData();
+ if (!AllMusic.side.needPlay()) {
+ PlayMusic.musicLessTime = 1;
+ }
+ if (PlayMusic.voteTime > 0) {
+ PlayMusic.voteTime--;
+ if (PlayMusic.voteTime == 0) {
+ AllMusic.clearVote();
+ AllMusic.side.bqt(AllMusic.getMessage().Vote.TimeOut);
+ } else {
+ int players = AllMusic.side.getAllPlayer();
+ if (AllMusic.getVoteCount() >= AllMusic.getConfig().MinVote
+ || (players <= AllMusic.getConfig().MinVote
+ && players <= AllMusic.getVoteCount())) {
+ AllMusic.side.bqt(AllMusic.getMessage().Vote.Do);
+ AllMusic.clearVote();
+ PlayMusic.voteTime = 0;
+ break;
+ }
+ }
+ }
+ Thread.sleep(1000);
+ }
+ AllMusic.side.sendStop();
+ } else {
+ String data = AllMusic.getMessage().MusicPlay.NoCanPlay;
+ AllMusic.side.bqt(data.replace("%MusicID%", PlayMusic.nowPlayMusic.getID()));
+ }
+ clear();
+ }
+ } catch (InterruptedException e) {
+ AllMusic.log.warning("§c歌曲播放出现错误");
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/music/play/PlayMusic.java b/server/src/main/java/coloryr/allmusic/core/music/play/PlayMusic.java
new file mode 100644
index 00000000..aec4624f
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/play/PlayMusic.java
@@ -0,0 +1,263 @@
+package coloryr.allmusic.core.music.play;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.decoder.Bitstream;
+import coloryr.allmusic.core.decoder.Header;
+import coloryr.allmusic.core.objs.music.MusicObj;
+import coloryr.allmusic.core.objs.music.SongInfoObj;
+import coloryr.allmusic.core.utils.Logs;
+
+import java.io.BufferedInputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class PlayMusic {
+
+ /**
+ * 播放列表
+ */
+ private static final List playList = new CopyOnWriteArrayList<>();
+ private static final Queue tasks = new ConcurrentLinkedQueue<>();
+ /**
+ * 投票时间
+ */
+ public static int voteTime = 0;
+ /**
+ * 总歌曲长度
+ */
+ public static int musicAllTime = 0;
+ /**
+ * 剩余歌曲长度
+ */
+ public static int musicLessTime = 0;
+ /**
+ * 歌曲现在位置
+ */
+ public static int musicNowTime = 0;
+ /**
+ * 当前歌曲信息
+ */
+ public static SongInfoObj nowPlayMusic;
+ /**
+ * 当前歌词信息
+ */
+ public static LyricSave lyric;
+ /**
+ * 错误次数
+ */
+ public static int error;
+ private static boolean isRun;
+
+ /**
+ * 停止歌曲逻辑
+ */
+ public static void stop() {
+ PlayMusic.clear();
+ isRun = false;
+ }
+
+ /**
+ * 开始歌曲逻辑
+ */
+ public static void start() {
+ Thread addT = new Thread(PlayMusic::task, "AllMusic_list");
+ isRun = true;
+ addT.start();
+ }
+
+ /**
+ * 添加点歌任务
+ *
+ * @param obj 歌曲
+ */
+ public static void addTask(MusicObj obj) {
+ tasks.add(obj);
+ }
+
+ private static void task() {
+ while (isRun) {
+ try {
+ MusicObj obj = tasks.poll();
+ if (obj != null) {
+ if (obj.isUrl) {
+ addUrl(obj.url);
+ } else {
+ addMusic(obj.sender, obj.id, obj.name, obj.isDefault);
+ }
+ }
+ Thread.sleep(10);
+ } catch (Exception e) {
+ AllMusic.log.warning("歌曲处理出现问题");
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * 添加歌曲
+ *
+ * @param sender 发送者
+ * @param id 歌曲ID
+ * @param player 用户名
+ * @param isList 是否是空闲歌单
+ */
+ public static void addMusic(Object sender, String id, String player, boolean isList) {
+ if (isHave(id))
+ return;
+ if (sender != null) {
+ String text = AllMusic.getMessage().MusicPlay.CheckMusic;
+ text = text.replace("%MusicID%", id);
+ AllMusic.side.sendMessaget(sender, text);
+ }
+ Logs.logWrite("玩家:" + player + " 点歌:" + id);
+ try {
+ SongInfoObj info = AllMusic.getMusicApi().getMusic(id, player, isList);
+ if (info == null) {
+ if (sender != null) {
+ String data = AllMusic.getMessage().MusicPlay.NoCanPlay;
+ AllMusic.side.sendMessaget(sender, data.replace("%MusicID%", id));
+ }
+ return;
+ }
+ if (info.getLength() / 1000 > AllMusic.getConfig().MaxMusicTime) {
+ AllMusic.side.sendMessaget(sender, AllMusic.getMessage().AddMusic.TimeOut);
+ return;
+ }
+ playList.add(info);
+ if (!AllMusic.getConfig().MuteAddMessage) {
+ String data = AllMusic.getMessage().MusicPlay.AddMusic;
+ data = data.replace("%MusicName%", info.getName())
+ .replace("%MusicAuthor%", info.getAuthor())
+ .replace("%MusicAl%", info.getAl())
+ .replace("%MusicAlia%", info.getAlia());
+ if (AllMusic.getConfig().ShowInBar) {
+ AllMusic.side.sendBar(data);
+ } else {
+ AllMusic.side.bqt(data);
+ }
+ }
+ if (AllMusic.getConfig().PlayListSwitch
+ && (PlayMusic.nowPlayMusic != null && PlayMusic.nowPlayMusic.isList())) {
+ PlayMusic.musicLessTime = 1;
+ if (!isList)
+ AllMusic.side.bqt(AllMusic.getMessage().MusicPlay.Switch);
+ }
+ error = 0;
+ } catch (Exception e) {
+ if (isList) {
+ error++;
+ }
+ AllMusic.log.warning("§d[AllMusic]§c歌曲信息解析错误");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 获取播放列表长度
+ *
+ * @return 长度
+ */
+ public static int getSize() {
+ return playList.size();
+ }
+
+ /**
+ * 获取当前播放列表
+ *
+ * @return 播放列表
+ */
+ public static List getList() {
+ return new ArrayList<>(playList);
+ }
+
+ /**
+ * 清理播放列表
+ */
+ public static void clear() {
+ playList.clear();
+ }
+
+ /**
+ * 从播放列表删除
+ *
+ * @param index 标号
+ * @return 结果
+ */
+ public static SongInfoObj remove(int index) {
+ return playList.remove(index);
+ }
+
+ /**
+ * 获取播放列表所有信息
+ *
+ * @return 信息
+ */
+ public static String getAllList() {
+ StringBuilder list = new StringBuilder();
+ String a;
+ SongInfoObj info;
+ for (int i = 0; i < playList.size(); i++) {
+ info = playList.get(i);
+ a = AllMusic.getMessage().MusicPlay.ListMusic.Item;
+ a = a.replace("%index%", "" + (i + 1))
+ .replace("%MusicName%", info.getName())
+ .replace("%MusicAuthor%", info.getAuthor())
+ .replace("%MusicAl%", info.getAl())
+ .replace("%MusicAlia%", info.getAlia());
+ list.append(a).append("\n");
+ }
+ String temp = list.toString();
+ if (temp.isEmpty())
+ return "";
+ return temp.substring(0, temp.length() - 1);
+ }
+
+ /**
+ * 是否在播放列表中
+ *
+ * @param id 音乐ID
+ * @return 结果
+ */
+ public static boolean isHave(String id) {
+ if (nowPlayMusic != null && nowPlayMusic.getID().equalsIgnoreCase(id))
+ return true;
+ for (SongInfoObj item : playList) {
+ if (item.getID().equalsIgnoreCase(id))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 添加Url歌曲
+ *
+ * @param url 链接
+ */
+ private static void addUrl(String url) {
+ try {
+ URL urlfile = new URL(url);
+ URLConnection con = urlfile.openConnection();
+ int b = con.getContentLength();// 得到音乐文件的总长度
+ BufferedInputStream bis = new BufferedInputStream(con.getInputStream());
+ Bitstream bt = new Bitstream(bis);
+ Header h = bt.readFrame();
+ int le = 6000000;
+ if (h == null) {
+ AllMusic.side.bqt("§d[AllMusic]§c未知音乐类型");
+ } else {
+ le = (int) h.total_ms(b);
+ }
+ SongInfoObj info = new SongInfoObj(AllMusic.getMessage().Custom.Info, url, le);
+ playList.add(info);
+ } catch (Exception e) {
+ AllMusic.log.warning("§d[AllMusic]§c歌曲信息解析错误");
+ e.printStackTrace();
+ }
+ }
+}
+
diff --git a/server/src/main/java/coloryr/allmusic/core/music/play/TopLyricSave.java b/server/src/main/java/coloryr/allmusic/core/music/play/TopLyricSave.java
new file mode 100644
index 00000000..553a86f3
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/music/play/TopLyricSave.java
@@ -0,0 +1,28 @@
+package coloryr.allmusic.core.music.play;
+
+public class TopLyricSave extends LyricSave {
+
+ public void setTlyric(String data) {
+ tly = data;
+ }
+
+ public void setLyric(String data) {
+ lly = data;
+ }
+
+ public void setKly(String data) {
+ kly = data;
+ }
+
+ public void setHaveK(boolean data) {
+ if (!data) {
+ kly = null;
+ }
+ }
+
+ public void setHaveT(boolean data) {
+ if (!data) {
+ tly = null;
+ }
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/objs/ConfigObj.java b/server/src/main/java/coloryr/allmusic/core/objs/ConfigObj.java
new file mode 100644
index 00000000..7df3e2da
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/objs/ConfigObj.java
@@ -0,0 +1,248 @@
+package coloryr.allmusic.core.objs;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.config.EconomyObj;
+import coloryr.allmusic.core.objs.config.FunConfigObj;
+import coloryr.allmusic.core.objs.hud.SaveObj;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 配置文件对象
+ */
+public class ConfigObj {
+ /**
+ * 最大歌曲数
+ */
+ public int MaxList;
+ /**
+ * 最小通过投票数
+ */
+ public int MinVote;
+ /**
+ * 歌曲延迟
+ */
+ public int Delay;
+ /**
+ * 搜歌花费
+ */
+ public int SearchCost;
+ /**
+ * 点歌花费
+ */
+ public int AddMusicCost;
+ /**
+ * 默认添加歌曲方式
+ */
+ public int DefaultAddMusic;
+ /**
+ * 消息限制长度
+ */
+ public int MessageLimitSize;
+ /**
+ * 最长音乐长度
+ */
+ public int MaxMusicTime;
+ /**
+ * KTV模式歌词加时
+ */
+ public int KDelay;
+
+ /**
+ * 管理员ID列表
+ */
+ public List Admin;
+ /**
+ * 不参与点歌的服务器列表
+ */
+ public List NoMusicServer;
+ /**
+ * 不参与点歌的玩家列表
+ */
+ public List NoMusicPlayer;
+ /**
+ * 禁止点歌ID列表
+ */
+ public List BanMusic;
+ /**
+ * 空闲歌单列表
+ */
+ public List PlayList;
+
+ /**
+ * 玩家点歌后是否直接从空闲歌单切换至玩家歌曲
+ */
+ public boolean PlayListSwitch;
+ /**
+ * 空闲歌单随机播放
+ */
+ public boolean PlayListRandom;
+ /**
+ * 显示歌词
+ */
+ public boolean SendLyric;
+ /**
+ * 指令需要权限
+ */
+ public boolean NeedPermission;
+ /**
+ * 开启花钱点歌
+ */
+ public boolean UseCost;
+ /**
+ * 顶层模式,用于和BC交换数据
+ */
+ public boolean TopPAPI;
+ /**
+ * 开启信息长度限制
+ */
+ public boolean MessageLimit;
+ /**
+ * 不发送播放信息
+ */
+ public boolean MutePlayMessage;
+ /**
+ * 不发送点歌信息
+ */
+ public boolean MuteAddMessage;
+ /**
+ * 将信息限制在bar处
+ */
+ public boolean ShowInBar;
+ /**
+ * K歌歌词
+ */
+ public boolean KtvMode;
+
+ /**
+ * 登录的用户
+ */
+ public String LoginUser;
+ /**
+ * 歌曲音质
+ */
+ public String MusicBR;
+ /**
+ * 配置文件版本号
+ */
+ public String Version;
+
+ /**
+ * 默认的Hud配置
+ */
+ public SaveObj DefaultHud;
+ /**
+ * 经济插件挂钩
+ */
+ public EconomyObj Economy;
+ /**
+ * 娱乐选项
+ */
+ public FunConfigObj FunConfig;
+
+ public static ConfigObj makeDefault(){
+ return new ConfigObj(){{
+ MaxList = 10;
+ MinVote = 3;
+ Delay = 0;
+ Admin = new ArrayList() {{
+ this.add("CONSOLE");
+ }};
+ NoMusicServer = new ArrayList<>();
+ NoMusicPlayer = new ArrayList<>();
+ BanMusic = new ArrayList<>();
+ PlayList = new ArrayList<>();
+ PlayListSwitch = true;
+ PlayListRandom = true;
+ SendLyric = true;
+ NeedPermission = false;
+ DefaultHud = new SaveObj();
+
+ UseCost = false;
+ SearchCost = 20;
+ MutePlayMessage = false;
+ MuteAddMessage = false;
+ ShowInBar = false;
+ AddMusicCost = 10;
+
+ DefaultAddMusic = 0;
+ LoginUser = "";
+
+ MusicBR = "320000";
+
+ MaxMusicTime = 600;
+
+ TopPAPI = false;
+ MessageLimit = false;
+ MessageLimitSize = 40;
+
+ Economy = new EconomyObj();
+ FunConfig = new FunConfigObj();
+
+ KtvMode = true;
+ KDelay = 0;
+
+ Version = AllMusic.version;
+ }};
+ }
+
+ public void addBanID(String ID) {
+ if (!BanMusic.contains(ID))
+ BanMusic.add(ID);
+ AllMusic.save();
+ }
+
+ public void AddNoMusicPlayer(String ID) {
+ if (!NoMusicPlayer.contains(ID))
+ NoMusicPlayer.add(ID);
+ AllMusic.save();
+ }
+
+ public void RemoveNoMusicPlayer(String ID) {
+ NoMusicPlayer.remove(ID);
+ AllMusic.save();
+ }
+
+ public boolean check() {
+ boolean saveConfig = false;
+ if (PlayList == null) {
+ saveConfig = true;
+ PlayList = new ArrayList<>();
+ }
+ if (Admin == null) {
+ saveConfig = true;
+ Admin = new ArrayList<>();
+ }
+ if (BanMusic == null) {
+ saveConfig = true;
+ BanMusic = new ArrayList<>();
+ }
+ if (DefaultHud == null) {
+ saveConfig = true;
+ DefaultHud = new SaveObj();
+ }
+ if (NoMusicPlayer == null) {
+ saveConfig = true;
+ NoMusicPlayer = new ArrayList<>();
+ }
+ if (NoMusicServer == null) {
+ saveConfig = true;
+ NoMusicServer = new ArrayList<>();
+ }
+ if (Economy == null) {
+ saveConfig = true;
+ Economy = new EconomyObj();
+ } else if (Economy.check()) {
+ saveConfig = true;
+ Economy = new EconomyObj();
+ }
+
+ if (FunConfig == null) {
+ saveConfig = true;
+ FunConfig = new FunConfigObj();
+ }
+
+ return saveConfig;
+ }
+}
\ No newline at end of file
diff --git a/server/src/main/java/coloryr/allmusic/core/objs/CookieObj.java b/server/src/main/java/coloryr/allmusic/core/objs/CookieObj.java
new file mode 100644
index 00000000..28d69bbd
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/objs/CookieObj.java
@@ -0,0 +1,10 @@
+package coloryr.allmusic.core.objs;
+
+import okhttp3.Cookie;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class CookieObj {
+ public HashMap> cookieStore = new HashMap<>();
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/objs/HttpResObj.java b/server/src/main/java/coloryr/allmusic/core/objs/HttpResObj.java
new file mode 100644
index 00000000..103a44f7
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/objs/HttpResObj.java
@@ -0,0 +1,11 @@
+package coloryr.allmusic.core.objs;
+
+public class HttpResObj {
+ public final String data;
+ public final boolean ok;
+
+ public HttpResObj(String data, boolean ok) {
+ this.data = data;
+ this.ok = ok;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/objs/MessageObj.java b/server/src/main/java/coloryr/allmusic/core/objs/MessageObj.java
new file mode 100644
index 00000000..aebc1ca2
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/objs/MessageObj.java
@@ -0,0 +1,108 @@
+package coloryr.allmusic.core.objs;
+
+import coloryr.allmusic.core.AllMusic;
+import coloryr.allmusic.core.objs.message.SearchObj;
+import coloryr.allmusic.core.objs.message.*;
+
+public class MessageObj {
+ public MusicPlayObj MusicPlay;
+ public AddMusicObj AddMusic;
+ public PageObj Page;
+ public LyricObj Lyric;
+ public VoteObj Vote;
+ public SearchObj Search;
+ public HudObj Hud;
+ public HudListObj HudList;
+ public CommandObj Command;
+ public CustomObj Custom;
+ public PAPIObj PAPI;
+ public CostObj Cost;
+ public ClickObj Click;
+ public HelpObj Help;
+ public FunObj Fun;
+ public String Version;
+
+ public MessageObj() {
+ MusicPlay = new MusicPlayObj();
+ AddMusic = new AddMusicObj();
+ Page = new PageObj();
+ Lyric = new LyricObj();
+ Vote = new VoteObj();
+ Search = new SearchObj();
+ Hud = new HudObj();
+ Command = new CommandObj();
+ HudList = new HudListObj();
+ Custom = new CustomObj();
+ PAPI = new PAPIObj();
+ Cost = new CostObj();
+ Click = new ClickObj();
+ Help = new HelpObj();
+ Fun = new FunObj();
+ Version = AllMusic.configVersion;
+ }
+
+ public boolean check() {
+ boolean saveConfig = false;
+ if (MusicPlay == null || MusicPlay.check()) {
+ saveConfig = true;
+ MusicPlay = new MusicPlayObj();
+ }
+ if (AddMusic == null || AddMusic.check()) {
+ saveConfig = true;
+ AddMusic = new AddMusicObj();
+ }
+ if (Page == null || Page.check()) {
+ saveConfig = true;
+ Page = new PageObj();
+ }
+ if (Lyric == null || Lyric.check()) {
+ saveConfig = true;
+ Lyric = new LyricObj();
+ }
+ if (Vote == null || Vote.check()) {
+ saveConfig = true;
+ Vote = new VoteObj();
+ }
+ if (Search == null || Search.check()) {
+ saveConfig = true;
+ Search = new SearchObj();
+ }
+ if (Hud == null || Hud.check()) {
+ saveConfig = true;
+ Hud = new HudObj();
+ }
+ if (HudList == null || HudList.check()) {
+ saveConfig = true;
+ HudList = new HudListObj();
+ }
+ if (Command == null || Command.check()) {
+ saveConfig = true;
+ Command = new CommandObj();
+ }
+ if (Custom == null || Custom.check()) {
+ saveConfig = true;
+ Custom = new CustomObj();
+ }
+ if (PAPI == null || PAPI.check()) {
+ saveConfig = true;
+ PAPI = new PAPIObj();
+ }
+ if (Cost == null || Cost.check()) {
+ saveConfig = true;
+ Cost = new CostObj();
+ }
+ if (Click == null || Click.check()) {
+ saveConfig = true;
+ Click = new ClickObj();
+ }
+ if (Help == null || Help.check()) {
+ saveConfig = true;
+ Help = new HelpObj();
+ }
+ if (Fun == null || Fun.check()) {
+ saveConfig = true;
+ Fun = new FunObj();
+ }
+ return saveConfig;
+ }
+}
\ No newline at end of file
diff --git a/server/src/main/java/coloryr/allmusic/core/objs/SearchMusicObj.java b/server/src/main/java/coloryr/allmusic/core/objs/SearchMusicObj.java
new file mode 100644
index 00000000..e0d70963
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/objs/SearchMusicObj.java
@@ -0,0 +1,15 @@
+package coloryr.allmusic.core.objs;
+
+public class SearchMusicObj {
+ public final String id;
+ public final String name;
+ public final String author;
+ public final String al;
+
+ public SearchMusicObj(String ID, String Name, String Author, String Al) {
+ this.id = ID;
+ this.name = Name;
+ this.author = Author;
+ this.al = Al;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/objs/api/EncResObj.java b/server/src/main/java/coloryr/allmusic/core/objs/api/EncResObj.java
new file mode 100644
index 00000000..7409dad0
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/objs/api/EncResObj.java
@@ -0,0 +1,11 @@
+package coloryr.allmusic.core.objs.api;
+
+public class EncResObj {
+ public String params;
+ public String encSecKey;
+
+ public EncResObj(String params, String encSecKey) {
+ this.encSecKey = encSecKey;
+ this.params = params;
+ }
+}
diff --git a/server/src/main/java/coloryr/allmusic/core/objs/api/music/info/InfoObj.java b/server/src/main/java/coloryr/allmusic/core/objs/api/music/info/InfoObj.java
new file mode 100644
index 00000000..67ad7a31
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/objs/api/music/info/InfoObj.java
@@ -0,0 +1,127 @@
+package coloryr.allmusic.core.objs.api.music.info;
+
+import java.util.List;
+
+public class InfoObj {
+ private List songs;
+
+ public boolean isOk() {
+ return (songs != null && songs.size() != 0);
+ }
+
+ public String getName() {
+ if (songs == null || songs.size() == 0)
+ return "";
+ return songs.get(0).getName();
+ }
+
+ public String getAuthor() {
+ StringBuilder Author = new StringBuilder();
+ if (songs.size() == 0)
+ return "";
+ for (ar ar : songs.get(0).getAr()) {
+ Author.append(ar.getName()).append(",");
+ }
+ if (Author.length() != 0) {
+ Author = new StringBuilder(Author.substring(0, Author.length() - 1));
+ }
+ return Author.toString();
+ }
+
+ public String getAlia() {
+ StringBuilder Alia = new StringBuilder();
+ for (String alia : songs.get(0).getAlia()) {
+ Alia.append(alia).append(",");
+ }
+ if (Alia.length() != 0) {
+ Alia = new StringBuilder(Alia.substring(0, Alia.length() - 1));
+ }
+ return Alia.toString();
+ }
+
+ public String getAl() {
+ return songs.get(0).getAl();
+ }
+
+ public int getLength() {
+ if (songs == null)
+ return 0;
+ return songs.get(0).getLength();
+ }
+
+ public String getPicUrl() {
+ if (songs == null)
+ return null;
+ return songs.get(0).getPicUrl();
+ }
+}
+
+class Songs {
+ private String name;
+ private List ar;
+ private List alia;
+ private al al;
+ private h l;
+ private h m;
+ private h h;
+
+ public int getLength() {
+ if (l != null)
+ return l.getLength();
+ if (m != null)
+ return m.getLength();
+ if (h != null)
+ return h.getLength();
+ return 0;
+ }
+
+ public String getName() {
+ return name == null ? "" : name;
+ }
+
+ public List getAr() {
+ return ar;
+ }
+
+ public List getAlia() {
+ return alia;
+ }
+
+ public String getAl() {
+ return al.getName() == null ? "" : al.getName();
+ }
+
+ public String getPicUrl() {
+ return al.getPicUrl();
+ }
+}
+
+class ar {
+ private String name;
+
+ public String getName() {
+ return name == null ? "" : name;
+ }
+}
+
+class al {
+ private String name;
+ private String picUrl;
+
+ public String getName() {
+ return name == null ? "" : name;
+ }
+
+ public String getPicUrl() {
+ return picUrl == null ? "" : picUrl;
+ }
+}
+
+class h {
+ private int br;
+ private int size;
+
+ public int getLength() {
+ return size / br * 8000;
+ }
+}
\ No newline at end of file
diff --git a/server/src/main/java/coloryr/allmusic/core/objs/api/music/info/PlayObj.java b/server/src/main/java/coloryr/allmusic/core/objs/api/music/info/PlayObj.java
new file mode 100644
index 00000000..3901e43f
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/objs/api/music/info/PlayObj.java
@@ -0,0 +1,30 @@
+package coloryr.allmusic.core.objs.api.music.info;
+
+import java.util.List;
+
+public class PlayObj {
+ private List data;
+ private int code;
+
+ public String getData() {
+ if (data == null)
+ return null;
+ if (data.size() == 0)
+ return null;
+ obj obj = data.get(0);
+ return obj.getUrl();
+ }
+
+ public int getCode() {
+ return code;
+ }
+}
+
+class obj {
+ private String url;
+
+ public String getUrl() {
+ return url;
+ }
+}
+
diff --git a/server/src/main/java/coloryr/allmusic/core/objs/api/music/list/DataObj.java b/server/src/main/java/coloryr/allmusic/core/objs/api/music/list/DataObj.java
new file mode 100644
index 00000000..4620e9ca
--- /dev/null
+++ b/server/src/main/java/coloryr/allmusic/core/objs/api/music/list/DataObj.java
@@ -0,0 +1,41 @@
+package coloryr.allmusic.core.objs.api.music.list;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DataObj {
+ private playlist playlist;
+
+ public List getPlaylist() {
+ List list = new ArrayList<>();
+ for (track item : playlist.getTracks()) {
+ list.add(item.getId());
+ }
+ return list;
+ }
+
+ public String getName() {
+ return playlist.getName();
+ }
+}
+
+class track {
+ private int id;
+
+ public String getId() {
+ return String.valueOf(id);
+ }
+}
+
+class playlist {
+ private List