ad get-m3u8-from-device

thanks BƎΛTS and NPGamma
pull/22/head
zhaarey 4 months ago
parent 603fc4acdd
commit 2a4e557acb
  1. 1
      README.md
  2. 86
      agent.js
  3. 1
      config.yaml
  4. 47
      main.go

@ -9,6 +9,7 @@
6. main_select 支持手动填写m3u8,输入#号,比如#1 #2,支持txt读取m3u8,输入txt文件名 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) 自动生成 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数据库. 8. main 支持check 可以填入文本地址 或API数据库.
9. 新增get-m3u8-from-device 改为true 且设置端口`adb forward tcp:20020 tcp:20020`即从模拟器获取m3u8
本项目仅支持ALAC和Atmos 本项目仅支持ALAC和Atmos
- `alac (audio-alac-stereo)` - `alac (audio-alac-stereo)`

@ -100,6 +100,92 @@ setTimeout(() => {
} }
await s.close(); 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({ Socket.listen({
family: "ipv4", family: "ipv4",

@ -8,3 +8,4 @@ alac-save-folder: AM-DL downloads
atmos-save-folder: AM-DL-Atmos downloads atmos-save-folder: AM-DL-Atmos downloads
check: "" check: ""
force-api: false force-api: false
get-m3u8-from-device: false

@ -47,6 +47,7 @@ type Config struct {
AtmosSaveFolder string `yaml:"atmos-save-folder"` AtmosSaveFolder string `yaml:"atmos-save-folder"`
ForceApi bool `yaml:"force-api"` ForceApi bool `yaml:"force-api"`
Check string `yaml:"check"` Check string `yaml:"check"`
GetM3u8FromDevice bool `yaml:"get-m3u8-from-device"`
} }
var config Config 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 != "" { if txtpath != "" {
file, err := os.Open(txtpath) file, err := os.Open(txtpath)
if err != nil { if err != nil {

Loading…
Cancel
Save