mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-19 22:17:29 +02:00
feat(discord): add opt-in mobile rich presence with track artwork
This commit is contained in:
1 parent
bbe2caa754
commit
0b2cf0e4e5
40 files changed
+1839
-18
No files matched your search
@@ -6,6 +6,10 @@ set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
OUTPUT_DIR="$PROJECT_DIR/build/app/outputs/flutter-apk"
|
||||
AUDIT_FLAGS=()
|
||||
if [[ -f "$PROJECT_DIR/third_party/spotiflac_discord/sdk/discord_partner_sdk.aar" ]]; then
|
||||
AUDIT_FLAGS+=(--discord-sdk)
|
||||
fi
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
BUILD_GIT_COMMIT="$(git rev-parse --short=8 HEAD)"
|
||||
@@ -28,7 +32,7 @@ for target in armeabi-v7a arm64-v8a universal; do
|
||||
exit 1
|
||||
fi
|
||||
python3 scripts/check_backend_apk.py "$OUTPUT_DIR/$apk" \
|
||||
--backend rust --abis "$abis"
|
||||
--backend rust --abis "$abis" "${AUDIT_FLAGS[@]}"
|
||||
done
|
||||
|
||||
echo "Built Android release APKs in $OUTPUT_DIR"
|
||||
@@ -15,7 +15,7 @@ ABI_LAYOUT = {
|
||||
"armeabi-v7a": (1, 40),
|
||||
}
|
||||
CORE_LIBRARIES = ("libapp.so", "libflutter.so")
|
||||
REMOVED_LIBRARIES = ("libspotiflac_discord.so", "libdiscord_partner_sdk.so")
|
||||
DISCORD_LIBRARIES = ("libspotiflac_discord.so", "libdiscord_partner_sdk.so")
|
||||
|
||||
|
||||
class AuditError(Exception):
|
||||
@@ -107,7 +107,7 @@ def check_backend_markers(
|
||||
raise AuditError("Go APK contains forbidden libspotiflac_mobile.so")
|
||||
|
||||
|
||||
def audit(path: Path, backend: str, abis: Sequence[str]) -> str:
|
||||
def audit(path: Path, backend: str, abis: Sequence[str], discord_sdk: bool = False) -> str:
|
||||
if not path.is_file():
|
||||
raise AuditError("APK is not a regular file: " + str(path))
|
||||
digest = artifact_sha256(path)
|
||||
@@ -116,8 +116,8 @@ def audit(path: Path, backend: str, abis: Sequence[str]) -> str:
|
||||
infos = zf.infolist()
|
||||
names = [info.filename for info in infos]
|
||||
for name in names:
|
||||
if name.rsplit("/", 1)[-1] in REMOVED_LIBRARIES:
|
||||
raise AuditError("APK contains removed SDK library: " + name)
|
||||
if not discord_sdk and name.rsplit("/", 1)[-1] == "libdiscord_partner_sdk.so":
|
||||
raise AuditError("APK unexpectedly contains Discord SDK library: " + name)
|
||||
if "assets/flutter_assets/kernel_blob.bin" in names:
|
||||
raise AuditError("debug APK contains assets/flutter_assets/kernel_blob.bin")
|
||||
check_abi_directories(names, abis)
|
||||
@@ -128,6 +128,8 @@ def audit(path: Path, backend: str, abis: Sequence[str]) -> str:
|
||||
libraries = CORE_LIBRARIES + (backend_library,)
|
||||
if backend == "rust":
|
||||
libraries += ("libjnidispatch.so",)
|
||||
if discord_sdk:
|
||||
libraries += DISCORD_LIBRARIES
|
||||
for abi in abis:
|
||||
for library in libraries:
|
||||
entry_path = f"lib/{abi}/{library}"
|
||||
@@ -144,6 +146,7 @@ def make_parser() -> argparse.ArgumentParser:
|
||||
parser.add_argument("apk", type=Path, help="release APK to audit")
|
||||
parser.add_argument("--backend", choices=("rust", "go"), required=True)
|
||||
parser.add_argument("--abis", required=True, metavar="ABI[,ABI...]", help="expected APK ABIs")
|
||||
parser.add_argument("--discord-sdk", action="store_true", help="require Discord SDK and bridge in every ABI")
|
||||
return parser
|
||||
|
||||
|
||||
@@ -151,7 +154,7 @@ def main(argv: Sequence[str] = None) -> int:
|
||||
args = make_parser().parse_args(argv)
|
||||
try:
|
||||
abis = parse_abis(args.abis)
|
||||
digest = audit(args.apk, args.backend, abis)
|
||||
digest = audit(args.apk, args.backend, abis, args.discord_sdk)
|
||||
except (AuditError, OSError) as exc:
|
||||
print("error: " + str(exc), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# SDK binaries are downloaded from the application's Discord Developer Portal,
|
||||
# not mirrored in this repository. No client secret or bot token is needed.
|
||||
sdk_source="${1:-${DISCORD_SOCIAL_SDK_DIR:-}}"
|
||||
if [[ -z "$sdk_source" ]]; then
|
||||
echo "Usage: bash scripts/setup_discord_sdk.sh /path/to/discord_social_sdk" >&2
|
||||
exit 1
|
||||
fi
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
sdk_target="$repo_root/third_party/spotiflac_discord/sdk"
|
||||
for sdk_file in include/discordpp.h lib/release/discord_partner_sdk.aar lib/release/discord_partner_sdk.xcframework/Info.plist; do
|
||||
if [[ ! -f "$sdk_source/$sdk_file" ]]; then
|
||||
echo "Missing SDK file: $sdk_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
mkdir -p "$sdk_target/android"
|
||||
cp "$sdk_source/lib/release/discord_partner_sdk.aar" "$sdk_target/"
|
||||
unzip -oq "$sdk_target/discord_partner_sdk.aar" -d "$sdk_target/android"
|
||||
mkdir -p "$repo_root/third_party/spotiflac_discord/ios/Frameworks"
|
||||
cp -R "$sdk_source/lib/release/discord_partner_sdk.xcframework" "$repo_root/third_party/spotiflac_discord/ios/Frameworks/"
|
||||
cp "$sdk_source/License-Notices.txt" "$sdk_target/"
|
||||
mkdir -p "$sdk_target/notices"
|
||||
cp "$sdk_source/License-Notices.txt" "$sdk_target/notices/Discord-License-Notices.txt"
|
||||
cp "$sdk_source/License-Notices.txt" "$repo_root/third_party/spotiflac_discord/ios/Frameworks/Discord-License-Notices.txt"
|
||||
cp "$repo_root/third_party/spotiflac_discord/ios/DiscordSimulator.xcconfig" "$repo_root/third_party/spotiflac_discord/ios/Frameworks/"
|
||||
echo "Discord SDK staged. Run flutter pub get and rebuild both platforms."
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Verify native backend payloads and reject removed SDKs in release APKs."""
|
||||
"""Verify native backend payloads and optional Discord SDKs in release APKs."""
|
||||
|
||||
import struct
|
||||
import tempfile
|
||||
@@ -24,11 +24,11 @@ class BackendApkAuditTest(unittest.TestCase):
|
||||
):
|
||||
self.entries[f"lib/{abi}/{library}"] = bytes(header)
|
||||
|
||||
def audit(self, abis=("arm64-v8a", "armeabi-v7a")):
|
||||
def audit(self, abis=("arm64-v8a", "armeabi-v7a"), discord_sdk=False):
|
||||
with zipfile.ZipFile(self.apk, "w") as zf:
|
||||
for name, data in self.entries.items():
|
||||
zf.writestr(name, data)
|
||||
return checker.audit(self.apk, "rust", abis)
|
||||
return checker.audit(self.apk, "rust", abis, discord_sdk)
|
||||
|
||||
def test_universal_passes(self):
|
||||
self.assertEqual(len(self.audit()), 64)
|
||||
@@ -57,15 +57,22 @@ class BackendApkAuditTest(unittest.TestCase):
|
||||
with self.assertRaisesRegex(checker.AuditError, "ELF class"):
|
||||
self.audit()
|
||||
|
||||
def test_removed_sdk_cannot_leak_from_build_cache(self):
|
||||
def test_disabled_sdk_cannot_leak_from_build_cache(self):
|
||||
for abi in checker.ABI_LAYOUT:
|
||||
for library in checker.REMOVED_LIBRARIES:
|
||||
with self.subTest(abi=abi, library=library):
|
||||
path = f"lib/{abi}/{library}"
|
||||
self.entries[path] = self.entries[f"lib/{abi}/libapp.so"]
|
||||
with self.assertRaisesRegex(checker.AuditError, "removed SDK"):
|
||||
self.audit()
|
||||
del self.entries[path]
|
||||
path = f"lib/{abi}/libdiscord_partner_sdk.so"
|
||||
self.entries[path] = self.entries[f"lib/{abi}/libapp.so"]
|
||||
with self.assertRaisesRegex(checker.AuditError, "unexpectedly contains Discord"):
|
||||
self.audit()
|
||||
del self.entries[path]
|
||||
|
||||
def test_enabled_sdk_requires_both_libraries_for_each_abi(self):
|
||||
for abi in checker.ABI_LAYOUT:
|
||||
for library in checker.DISCORD_LIBRARIES:
|
||||
self.entries[f"lib/{abi}/{library}"] = self.entries[f"lib/{abi}/libapp.so"]
|
||||
self.assertEqual(len(self.audit(discord_sdk=True)), 64)
|
||||
del self.entries["lib/armeabi-v7a/libdiscord_partner_sdk.so"]
|
||||
with self.assertRaisesRegex(checker.AuditError, "missing APK entry"):
|
||||
self.audit(discord_sdk=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in new issue
Block a user