ad get-m3u8-from-device
thanks BƎΛTS and NPGamma
This commit is contained in:
parent
603fc4acdd
commit
2a4e557acb
@ -9,6 +9,7 @@
|
||||
6. main_select 支持手动填写m3u8,输入#号,比如#1 #2,支持txt读取m3u8,输入txt文件名
|
||||
7. main 支持使用 go run main.go "txt文件地址" txt文件名需要指定格式 例如 cn_1707581102_THE BOOK 3.txt 建议使用这个[Reqable 脚本代码](https://telegra.ph/Reqable-For-Apple-Music-05-01) 自动生成
|
||||
8. main 支持check 可以填入文本地址 或API数据库.
|
||||
9. 新增get-m3u8-from-device 改为true 且设置端口`adb forward tcp:20020 tcp:20020`即从模拟器获取m3u8
|
||||
|
||||
本项目仅支持ALAC和Atmos
|
||||
- `alac (audio-alac-stereo)`
|
||||
|
86
agent.js
86
agent.js
@ -100,6 +100,92 @@ setTimeout(() => {
|
||||
}
|
||||
await s.close();
|
||||
}
|
||||
global.getM3U8 = function(adamID) {
|
||||
var C3282k = Java.use("c.a.a.e.o.k");
|
||||
var m7125s = C3282k.a().s();
|
||||
var PurchaseRequest$PurchaseRequestPtr = Java.use("com.apple.android.storeservices.javanative.account.PurchaseRequest$PurchaseRequestPtr");
|
||||
|
||||
var c3249t = Java.cast(m7125s, Java.use("c.a.a.e.k.t"));
|
||||
var create = PurchaseRequest$PurchaseRequestPtr.create(c3249t.n.value);
|
||||
create.get().setProcessDialogActions(true);
|
||||
create.get().setURLBagKey("subDownload");
|
||||
create.get().setBuyParameters(`salableAdamId=${adamID}&price=0&pricingParameters=SUBS&productType=S`);
|
||||
create.get().run();
|
||||
var response = create.get().getResponse();
|
||||
if (response.get().getError().get() == null) {
|
||||
var item = response.get().getItems().get(0);
|
||||
var assets = item.get().getAssets();
|
||||
var size = assets.size();
|
||||
return assets.get(size - 1).get().getURL();
|
||||
} else {
|
||||
return response.get().getError().get().errorCode();
|
||||
}
|
||||
};
|
||||
|
||||
function performJavaOperations(adamID) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Java.performNow(function () {
|
||||
const url = getM3U8(adamID);
|
||||
resolve(url);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function handleM3U8Connection(s) {
|
||||
console.log("New M3U8 connection!");
|
||||
try {
|
||||
const byteArrayToString = byteArray => {
|
||||
let result = '';
|
||||
for (let i = 0; i < byteArray.length; ++i) {
|
||||
result += String.fromCharCode(byteArray[i]);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const adamSize = (await s.input.readAll(1)).unwrap().readU8();
|
||||
if (adamSize !== 0) {
|
||||
const adam = await s.input.readAll(adamSize);
|
||||
const byteArray = new Uint8Array(adam);
|
||||
let adamID = "";
|
||||
for (let i = 0; i < byteArray.length; i++) {
|
||||
adamID += String.fromCharCode(byteArray[i]);
|
||||
}
|
||||
console.log("adamID:", adamID);
|
||||
let m3u8Url;
|
||||
performJavaOperations(adamID)
|
||||
.then(async (url) => {
|
||||
m3u8Url = url;
|
||||
console.log("M3U8 URL: ", m3u8Url);
|
||||
const m3u8Array = stringToByteArray(m3u8Url + "\n");
|
||||
// console.log("M3U8 ARRAY:", m3u8Array);
|
||||
await s.output.writeAll(m3u8Array);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error performing Java operations:", error);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error handling M3U8 connection:", err);
|
||||
}
|
||||
await s.close();
|
||||
}
|
||||
|
||||
const stringToByteArray = str => {
|
||||
const byteArray = [];
|
||||
for (let i = 0; i < str.length; ++i) {
|
||||
byteArray.push(str.charCodeAt(i));
|
||||
}
|
||||
return byteArray;
|
||||
};
|
||||
|
||||
Socket.listen({
|
||||
family: "ipv4",
|
||||
port: 20020,
|
||||
}).then(async function (listener) {
|
||||
while (true) {
|
||||
handleM3U8Connection(await listener.accept());
|
||||
}
|
||||
}).catch(console.log);
|
||||
|
||||
Socket.listen({
|
||||
family: "ipv4",
|
||||
|
@ -8,3 +8,4 @@ alac-save-folder: AM-DL downloads
|
||||
atmos-save-folder: AM-DL-Atmos downloads
|
||||
check: ""
|
||||
force-api: false
|
||||
get-m3u8-from-device: false
|
||||
|
47
main.go
47
main.go
@ -47,6 +47,7 @@ type Config struct {
|
||||
AtmosSaveFolder string `yaml:"atmos-save-folder"`
|
||||
ForceApi bool `yaml:"force-api"`
|
||||
Check string `yaml:"check"`
|
||||
GetM3u8FromDevice bool `yaml:"get-m3u8-from-device"`
|
||||
}
|
||||
|
||||
var config Config
|
||||
@ -1259,6 +1260,52 @@ func rip(albumId string, token string, storefront string, userToken string) erro
|
||||
}
|
||||
}
|
||||
}
|
||||
if config.GetM3u8FromDevice{
|
||||
adamID := track.ID
|
||||
conn, err := net.Dial("tcp", "127.0.0.1:20020")
|
||||
if err != nil {
|
||||
fmt.Println("Error connecting to device:", err)
|
||||
continue
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
fmt.Println("Connected to device")
|
||||
|
||||
// Send the length of adamID and the adamID itself
|
||||
adamIDBuffer := []byte(adamID)
|
||||
lengthBuffer := []byte{byte(len(adamIDBuffer))}
|
||||
|
||||
// Write length and adamID to the connection
|
||||
_, err = conn.Write(lengthBuffer)
|
||||
if err != nil {
|
||||
fmt.Println("Error writing length to device:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = conn.Write(adamIDBuffer)
|
||||
if err != nil {
|
||||
fmt.Println("Error writing adamID to device:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Read the response (URL) from the device
|
||||
response, err := bufio.NewReader(conn).ReadBytes('\n')
|
||||
if err != nil {
|
||||
fmt.Println("Error reading response from device:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Trim any newline characters from the response
|
||||
|
||||
response = bytes.TrimSpace(response)
|
||||
if len(response) > 0 {
|
||||
fmt.Println("Received URL:", string(response))
|
||||
manifest.Attributes.ExtendedAssetUrls.EnhancedHls = string(response)
|
||||
} else {
|
||||
fmt.Println("Received an empty response")
|
||||
continue
|
||||
}
|
||||
}
|
||||
if txtpath != "" {
|
||||
file, err := os.Open(txtpath)
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user