38 Commits
Author SHA1 Message Date
Vitaly Gashkov 4264727c33 1.3.5 2026-02-08 14:01:29 +05:00
Vitaly Gashkov c6ec34ca8b chore: add formatter 2026-02-08 14:01:20 +05:00
Vitaly Gashkov 3297dce797 fix: search tv app id instead of hardcoding 2026-02-08 14:00:56 +05:00
vitalygashkovandgithub-actions[bot] ae1e4c97d7 Apply automatic changes 2026-01-13 14:54:29 +00:00
Vitaly Gashkov f5d2233d68 Merge branch 'main' of https://github.com/vitalygashkov/crunchys 2026-01-13 19:51:36 +05:00
Vitaly Gashkov 196a1cad1d fix: update crunchyroll tv app id 2026-01-13 19:51:30 +05:00
vitalygashkovandgithub-actions[bot] 00408ad8e8 Apply automatic changes 2025-11-22 06:18:19 +00:00
vitalygashkovandgithub-actions[bot] 4e5a0d1561 Apply automatic changes 2025-11-04 14:52:19 +00:00
Vitaly Gashkov cbdde54471 1.3.4 2025-11-04 19:49:27 +05:00
Vitaly Gashkov 777eb4ee2b fix: update tv app id 2025-11-04 19:48:37 +05:00
Vitaly Gashkov b2c672dfa6 1.3.3 2025-10-25 12:14:11 +05:00
Vitaly Gashkov 828f4fa1d5 fix: correct checking for downloaded apk 2025-10-25 12:13:35 +05:00
Vitaly Gashkov 8275aff35e 1.3.2 2025-10-25 12:09:17 +05:00
Vitaly Gashkov 1d8596b8c9 chore: update deps 2025-10-25 12:09:12 +05:00
Vitaly Gashkov 8658934ebe Merge branch 'main' of https://github.com/vitalygashkov/crunchys 2025-10-25 12:04:16 +05:00
Vitaly Gashkov 96e77102e3 fix: skip process if downloaded apk not found 2025-10-25 12:03:59 +05:00
vitalygashkovandgithub-actions[bot] 673c276c9a Apply automatic changes 2025-10-11 06:17:25 +00:00
vitalygashkovandgithub-actions[bot] ed80f46a45 Apply automatic changes 2025-10-04 06:17:15 +00:00
vitalygashkovandgithub-actions[bot] e8468cafe9 Apply automatic changes 2025-09-27 06:17:10 +00:00
Vitaly Gashkov 50d84b208c 1.3.1 2025-09-20 22:19:07 +05:00
Vitaly Gashkov 3ed2207eaa chore: update tv credentials 2025-09-20 22:17:18 +05:00
Vitaly Gashkov 980278acb9 Merge branch 'main' of https://github.com/vitalygashkov/crunchys 2025-09-20 22:17:01 +05:00
Vitaly Gashkov 485d330af2 fix: update source for tv apk 2025-09-20 22:16:34 +05:00
vitalygashkovandgithub-actions[bot] 50f77e0e7a Apply automatic changes 2025-09-13 06:16:25 +00:00
Vitaly Gashkov 00ba683170 chore: update tv credentials manually 2025-09-06 22:04:12 +05:00
Vitaly Gashkov d979333e13 update workflow 2025-09-01 13:03:24 +05:00
Vitaly Gashkov 1908ba60f5 update workflow 2025-09-01 12:59:48 +05:00
Vitaly Gashkov 45ab0a6085 update workflow 2025-09-01 12:54:30 +05:00
Vitaly Gashkov 17e9adf3b2 update workflow 2025-09-01 12:48:03 +05:00
Vitaly Gashkov 99d07dc063 update workflow 2025-09-01 12:46:35 +05:00
Vitaly Gashkov c7a72f06a2 update workflow 2025-09-01 12:44:19 +05:00
Vitaly Gashkov 2ac5d94eb8 update workflow 2025-09-01 12:38:24 +05:00
Vitaly Gashkov f2db789e75 update workflow 2025-09-01 12:36:22 +05:00
Vitaly Gashkov a00b53007f update workflow 2025-09-01 12:34:13 +05:00
Vitaly Gashkov 38ac098adb update workflow 2025-09-01 12:29:22 +05:00
Vitaly Gashkov 5240fe25d5 fix 2 2025-09-01 12:22:58 +05:00
Vitaly Gashkov 50267e58a6 fix 2025-09-01 12:21:10 +05:00
Vitaly Gashkov 06e004b173 update gitignore 2025-08-26 19:10:31 +05:00
8 changed files with 236 additions and 63 deletions
+11 -29
View File
@@ -3,56 +3,38 @@ name: Extract
on:
workflow_dispatch:
schedule:
- cron: '0 4 * * 1' # Runs every Monday at 04:00 UTC
- cron: '0 6 * * 6' # Runs every Saturday at 06:00 UTC
jobs:
extract:
runs-on: ubuntu-latest
permissions:
# Give the default GITHUB_TOKEN write permission to commit and push the
# added or changed files to the repository.
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
# JADX requires Java 11 or higher to run
- name: Set up JDK 17
uses: actions/setup-java@v4
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
java-version: '17'
node-version: 22
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
# Download and install the latest version of JADX
- name: Install JADX
run: |
# Fetch the latest version tag from the JADX GitHub repository
JADX_VERSION=$(curl -s "https://api.github.com/repos/skylot/jadx/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+')
echo "Installing JADX version ${JADX_VERSION}..."
# Download the release zip file
curl -Lo jadx.zip "https://github.com/skylot/jadx/releases/download/v${JADX_VERSION}/jadx-${JADX_VERSION}.zip"
# Unzip the archive
unzip -q jadx.zip -d jadx-dist
# Add the JADX bin directory to the GitHub Actions path
# This makes the 'jadx' command available in subsequent steps
echo "$(pwd)/jadx-dist/jadx-${JADX_VERSION}/bin" >> $GITHUB_PATH
# Clean up the downloaded zip file
echo "$(pwd)/jadx-dist/bin" >> $GITHUB_PATH
rm jadx.zip
shell: bash
# Verify that JADX was installed correctly
- name: Verify JADX installation
run: jadx --version
- name: Install dependencies
run: npm install
# Verify that JADX was installed correctly
- name: Extract app credentials
run: node . --target mobile --output ./credentials.mobile.json && node . --target tv --output ./credentials.tv.json
run: npm run extract:mobile && npm run extract:tv
# Commit all changed files back to the repository
- uses: stefanzweifel/git-auto-commit-action@v5
+2
View File
@@ -1,5 +1,7 @@
/node_modules
.DS_Store
/jadx-dist
/jadx.zip
/crunchyroll
crunchyroll.apk
crunchyroll.xapk
+11
View File
@@ -0,0 +1,11 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"printWidth": 100,
"singleQuote": true,
"jsxSingleQuote": false,
"trailingComma": "all",
"tabWidth": 2,
"useTabs": false,
"semi": true,
"ignorePatterns": []
}
+5 -5
View File
@@ -1,7 +1,7 @@
{
"version": "3.89.2 (952)",
"id": "n0q2nxl37zig0dqn0aio",
"secret": "P0j3he4N8UG8W2w0-PvDadjGuv62fN2d",
"encoded": "bjBxMm54bDM3emlnMGRxbjBhaW86UDBqM2hlNE44VUc4VzJ3MC1QdkRhZGpHdXY2MmZOMmQ=",
"authorization": "Basic bjBxMm54bDM3emlnMGRxbjBhaW86UDBqM2hlNE44VUc4VzJ3MC1QdkRhZGpHdXY2MmZOMmQ="
"version": "3.97.3 (1023)",
"id": "t5u2txnuq8td1z0hodzt",
"secret": "4qEyXRs-WUeFwWPp4Dc5QyWu0YFtYP7O",
"encoded": "dDV1MnR4bnVxOHRkMXowaG9kenQ6NHFFeVhScy1XVWVGd1dQcDREYzVReVd1MFlGdFlQN08=",
"authorization": "Basic dDV1MnR4bnVxOHRkMXowaG9kenQ6NHFFeVhScy1XVWVGd1dQcDREYzVReVd1MFlGdFlQN08="
}
+5 -5
View File
@@ -1,7 +1,7 @@
{
"version": "3.42.1 (22267)",
"id": "bmbrkxyx3d7u6jsfyla4",
"secret": "AIN4D5VE_cp0wVzfNoP0YqHUrYFp9hSg",
"encoded": "Ym1icmt4eXgzZDd1NmpzZnlsYTQ6QUlONEQ1VkVfY3Awd1Z6Zk5vUDBZcUhVcllGcDloU2c=",
"authorization": "Basic Ym1icmt4eXgzZDd1NmpzZnlsYTQ6QUlONEQ1VkVfY3Awd1Z6Zk5vUDBZcUhVcllGcDloU2c="
"version": "3.54.5 (22304)",
"id": "ea9cmqltlqyzyan1vdy4",
"secret": "-_YCpAD5gsxCiOHZzRLgICR8gOWXilQR",
"encoded": "ZWE5Y21xbHRscXl6eWFuMXZkeTQ6LV9ZQ3BBRDVnc3hDaU9IWnpSTGdJQ1I4Z09XWGlsUVI=",
"authorization": "Basic ZWE5Y21xbHRscXl6eWFuMXZkeTQ6LV9ZQ3BBRDVnc3hDaU9IWnpSTGdJQ1I4Z09XWGlsUVI="
}
+34 -9
View File
@@ -15,14 +15,23 @@ const downloadMobileApk = async () => {
};
const downloadTvApk = async () => {
const searchParams = new URLSearchParams();
searchParams.append('query', 'crunchyroll');
searchParams.append('cdn', 'web');
searchParams.append('q', 'bXlDUFU9YXJtNjQtdjhhLGFybWVhYmktdjdhLGFybWVhYmkmbGVhbmJhY2s9MA');
searchParams.append('aab', '1');
const searchUrl = `https://ws2-cache.aptoide.com/api/7/apps/search?${searchParams.toString()}`;
const searchResults = await fetch(searchUrl).then((r) => r.json());
const id = searchResults.datalist?.list?.[0]?.id;
if (!id) {
console.error('Unable to find ID for TV APK');
return;
}
const source = 'https://webservices.aptoide.com/webservices/3/getApkInfo';
const formData = new FormData();
formData.append('identif', 'id:71305225');
formData.append('mode', 'json');
const response = await fetch(source, {
method: 'POST',
body: formData,
});
const body = new FormData();
body.append('identif', `id:${id}`);
body.append('mode', 'json');
const response = await fetch(source, { method: 'POST', body });
const json = await response.json();
const url = json.apk.path;
const filepath = join(process.cwd(), 'crunchyroll.apk');
@@ -74,7 +83,15 @@ const parseCredentials = async (decompiledDir) => {
if (id && secret) return { id, secret };
}
const constantsPath = join(decompiledDir, 'sources', 'com', 'crunchyroll', 'api', 'util', 'Constants.java');
const constantsPath = join(
decompiledDir,
'sources',
'com',
'crunchyroll',
'api',
'util',
'Constants.java',
);
const constants = await readFile(constantsPath, 'utf8');
return {
id: constants.split(' PROD_CLIENT_ID = "')[1].split('"')[0],
@@ -100,6 +117,11 @@ const extract = async ({ target = 'mobile', output, cleanup = false } = {}) => {
console.log('Downloading APK...');
const apkPath = target === 'tv' ? await downloadTvApk() : await downloadMobileApk();
if (!existsSync(apkPath)) {
console.error('Unable to find APK (possibly a download error)');
return;
}
console.log('Decompiling APK...');
const decompiledDir = decompileApk(apkPath);
@@ -122,7 +144,10 @@ const extract = async ({ target = 'mobile', output, cleanup = false } = {}) => {
console.log(`Authorization: ${authorization}`);
if (output) {
await writeFile(output, JSON.stringify({ version, id, secret, encoded, authorization }, null, 2));
await writeFile(
output,
JSON.stringify({ version, id, secret, encoded, authorization }, null, 2),
);
}
return { version, id, secret, encoded, authorization };
+163 -11
View File
@@ -1,12 +1,12 @@
{
"name": "crextractor",
"version": "1.3.0",
"version": "1.3.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "crextractor",
"version": "1.3.0",
"version": "1.3.5",
"funding": [
{
"type": "individual",
@@ -15,18 +15,131 @@
],
"license": "MIT",
"dependencies": {
"molnia": "^0.1.5"
"molnia": "^0.1.7"
},
"bin": {
"crextractor": "bin/cli.js"
},
"devDependencies": {
"typescript": "^5.9.2"
"oxfmt": "^0.28.0",
"typescript": "^5.9.3"
},
"engines": {
"node": ">=20"
"node": ">=22"
}
},
"node_modules/@oxfmt/darwin-arm64": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/@oxfmt/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
"integrity": "sha512-jmUfF7cNJPw57bEK7sMIqrYRgn4LH428tSgtgLTCtjuGuu1ShREyrkeB7y8HtkXRfhBs4lVY+HMLhqElJvZ6ww==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@oxfmt/darwin-x64": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/@oxfmt/darwin-x64/-/darwin-x64-0.28.0.tgz",
"integrity": "sha512-S6vlV8S7jbjzJOSjfVg2CimUC0r7/aHDLdUm/3+/B/SU/s1jV7ivqWkMv1/8EB43d1BBwT9JQ60ZMTkBqeXSFA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@oxfmt/linux-arm64-gnu": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/@oxfmt/linux-arm64-gnu/-/linux-arm64-gnu-0.28.0.tgz",
"integrity": "sha512-TfJkMZjePbLiskmxFXVAbGI/OZtD+y+fwS0wyW8O6DWG0ARTf0AipY9zGwGoOdpFuXOJceXvN4SHGLbYNDMY4Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@oxfmt/linux-arm64-musl": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/@oxfmt/linux-arm64-musl/-/linux-arm64-musl-0.28.0.tgz",
"integrity": "sha512-7fyQUdW203v4WWGr1T3jwTz4L7KX9y5DeATryQ6fLT6QQp9GEuct8/k0lYhd+ys42iTV/IkJF20e3YkfSOOILg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@oxfmt/linux-x64-gnu": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/@oxfmt/linux-x64-gnu/-/linux-x64-gnu-0.28.0.tgz",
"integrity": "sha512-sRKqAvEonuz0qr1X1ncUZceOBJerKzkO2gZIZmosvy/JmqyffpIFL3OE2tqacFkeDhrC+dNYQpusO8zsfHo3pw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@oxfmt/linux-x64-musl": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/@oxfmt/linux-x64-musl/-/linux-x64-musl-0.28.0.tgz",
"integrity": "sha512-fW6czbXutX/tdQe8j4nSIgkUox9RXqjyxwyWXUDItpoDkoXllq17qbD7GVc0whrEhYQC6hFE1UEAcDypLJoSzw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@oxfmt/win32-arm64": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/@oxfmt/win32-arm64/-/win32-arm64-0.28.0.tgz",
"integrity": "sha512-D/HDeQBAQRjTbD9OLV6kRDcStrIfO+JsUODDCdGmhRfNX8LPCx95GpfyybpZfn3wVF8Jq/yjPXV1xLkQ+s7RcA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@oxfmt/win32-x64": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/@oxfmt/win32-x64/-/win32-x64-0.28.0.tgz",
"integrity": "sha512-4+S2j4OxOIyo8dz5osm5dZuL0yVmxXvtmNdHB5xyGwAWVvyWNvf7tCaQD7w2fdSsAXQLOvK7KFQrHFe33nJUCA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/fastq": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
@@ -37,9 +150,9 @@
}
},
"node_modules/molnia": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/molnia/-/molnia-0.1.5.tgz",
"integrity": "sha512-Kb3bhlvNVWJ9Z8tGZGkhmChpXQY8OLFPkxXFvLJb+foLwfH7JyyJl+DbKuUKAIK1vnxs5sBFuQb3wxOIwWBpiA==",
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/molnia/-/molnia-0.1.7.tgz",
"integrity": "sha512-wCezzcu2sRybrJb9ltrBEWwzO9NU2DRgxZw5Gr1g2QrnwrNo+olE3cAiD3Q1Y76rCde1qXBUmEuZ13aKXew+AQ==",
"funding": [
{
"type": "individual",
@@ -58,6 +171,35 @@
"node": ">=20"
}
},
"node_modules/oxfmt": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.28.0.tgz",
"integrity": "sha512-3+hhBqPE6Kp22KfJmnstrZbl+KdOVSEu1V0ABaFIg1rYLtrMgrupx9znnHgHLqKxAVHebjTdiCJDk30CXOt6cw==",
"dev": true,
"license": "MIT",
"dependencies": {
"tinypool": "2.1.0"
},
"bin": {
"oxfmt": "bin/oxfmt"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"funding": {
"url": "https://github.com/sponsors/Boshen"
},
"optionalDependencies": {
"@oxfmt/darwin-arm64": "0.28.0",
"@oxfmt/darwin-x64": "0.28.0",
"@oxfmt/linux-arm64-gnu": "0.28.0",
"@oxfmt/linux-arm64-musl": "0.28.0",
"@oxfmt/linux-x64-gnu": "0.28.0",
"@oxfmt/linux-x64-musl": "0.28.0",
"@oxfmt/win32-arm64": "0.28.0",
"@oxfmt/win32-x64": "0.28.0"
}
},
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
@@ -68,10 +210,20 @@
"node": ">=0.10.0"
}
},
"node_modules/tinypool": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz",
"integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^20.0.0 || >=22.0.0"
}
},
"node_modules/typescript": {
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
+5 -4
View File
@@ -1,6 +1,6 @@
{
"name": "crextractor",
"version": "1.3.0",
"version": "1.3.5",
"description": "Utility for extracting credentials from the Crunchyroll Android app",
"main": "crextractor.js",
"bin": {
@@ -32,12 +32,13 @@
}
],
"engines": {
"node": ">=20"
"node": ">=22"
},
"dependencies": {
"molnia": "^0.1.5"
"molnia": "^0.1.7"
},
"devDependencies": {
"typescript": "^5.9.2"
"oxfmt": "^0.28.0",
"typescript": "^5.9.3"
}
}