-
Notifications
You must be signed in to change notification settings - Fork 582
Expand file tree
/
Copy pathbuild-ipa-local.sh
More file actions
executable file
·85 lines (71 loc) · 3.19 KB
/
Copy pathbuild-ipa-local.sh
File metadata and controls
executable file
·85 lines (71 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env bash
# Local IPA build — mirror of .github/workflows/main.yml. Produces an IPA
# you can sign with Sideloadly/AltStore/TrollStore.
#
# Pipeline:
# 1. Build EeveeSwiftProtobuf.framework from apple/swift-protobuf source
# (renamed module — see Tools/SwiftProtobufBuild/).
# 2. theos `make package FINALPACKAGE=1` — produces .deb with
# EeveeSpotify.dylib + EeveeSpotify.bundle + framework.
# 3. Build zxPluginsInject.dylib — sideload compat shim (keychain redirect,
# group containers, CloudKit stub). LC-injected via ipapatch in step 6.
# 4. cyan inject deb-contents (dylib + framework + bundle) into vanilla IPA.
# 5. ipapatch LC-inject zxPluginsInject into main exec + every appex.
# 6. Strip Watch.app if it survived cyan -du.
#
# Requires: theos, cyan (pyzule-rw), ipapatch, dpkg, ldid, plutil.
set -euo pipefail
VANILLA_IPA="${1:-}"
[ -n "$VANILLA_IPA" ] && [ -f "$VANILLA_IPA" ] || {
echo "usage: $0 <path/to/Spotify-vanilla.ipa>" >&2
exit 1
}
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$REPO_DIR"
[ -n "${THEOS:-}" ] || { [ -d "$HOME/theos" ] && export THEOS="$HOME/theos" || { echo "THEOS not set"; exit 1; }; }
VERSION=$(grep -E '^Version:' control | awk '{print $2}')
SPOT_VERSION=$(unzip -p "$VANILLA_IPA" 'Payload/Spotify.app/Info.plist' \
| plutil -extract CFBundleShortVersionString raw - 2>/dev/null || echo "unknown")
OUT_DIR="Outputs/IPAS"
OUT_IPA="$OUT_DIR/EeveeSpotify-${VERSION}-${SPOT_VERSION}.ipa"
mkdir -p "$OUT_DIR"
color() { printf '\033[1;32m==> %s\033[0m\n' "$*"; }
color "1/6 EeveeSwiftProtobuf.framework"
chmod +x Tools/SwiftProtobufBuild/build-eeveeswiftprotobuf.sh
Tools/SwiftProtobufBuild/build-eeveeswiftprotobuf.sh
color "2/6 theos make package"
THEOS_PACKAGE_SCHEME=rootless make package FINALPACKAGE=1
DEB_FILE=$(ls -t packages/com.eevee.spotify_*.deb 2>/dev/null | head -1)
[ -n "$DEB_FILE" ] || { echo "deb not produced"; exit 1; }
color "3/6 zxPluginsInject.dylib"
chmod +x Tools/build-zxpi.sh
Tools/build-zxpi.sh >/dev/null
color "4/6 extract deb"
DEB_EXTRACT="$REPO_DIR/Outputs/deb-extract"
rm -rf "$DEB_EXTRACT"; mkdir -p "$DEB_EXTRACT"
dpkg-deb -R "$DEB_FILE" "$DEB_EXTRACT"
DYLIB_SRC=$(find "$DEB_EXTRACT" -name 'EeveeSpotify.dylib' | head -1)
BUNDLE_SRC=$(find "$DEB_EXTRACT" -type d -name 'EeveeSpotify.bundle' | head -1)
FRAMEWORK_SRC=$(find "$DEB_EXTRACT" -type d -name 'EeveeSwiftProtobuf.framework' | head -1)
[ -n "$DYLIB_SRC" ] || { echo "dylib not in deb"; exit 1; }
color "5/6 cyan inject"
INJECT=("$DYLIB_SRC")
[ -n "$FRAMEWORK_SRC" ] && INJECT+=("$FRAMEWORK_SRC")
[ -n "$BUNDLE_SRC" ] && INJECT+=("$BUNDLE_SRC")
rm -f "$OUT_IPA"
cyan -i "$VANILLA_IPA" -o "$OUT_IPA" -f "${INJECT[@]}" -c 9 -m 15.0 -du
color "6/6 ipapatch LC-inject zxPluginsInject"
ipapatch --input "$OUT_IPA" --inplace --noconfirm --dylib packages/zxPluginsInject.dylib
# Belt-and-suspenders: cyan -du strips appex/Watch but verify.
cd "$OUT_DIR"
rm -rf Payload
unzip -q "$(basename "$OUT_IPA")"
if [ -d "Payload/Spotify.app/Watch" ]; then
rm -rf Payload/Spotify.app/Watch
zip -qry "$(basename "$OUT_IPA")" Payload
fi
rm -rf Payload
cd - >/dev/null
color "Done"
ls -lh "$OUT_IPA"
echo "Sign with Sideloadly / AltStore / TrollStore."