Skip to content

Commit

Permalink
ad get-m3u8-from-device
Browse files Browse the repository at this point in the history
thanks BƎΛTS and NPGamma
  • Loading branch information
zhaarey committed May 29, 2024
1 parent 603fc4a commit 2a4e557
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)`
Expand Down
86 changes: 86 additions & 0 deletions agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 47 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 2a4e557

Please sign in to comment.