Initial commit

Based on JMusicBot by jagrosh (https://github.com/jagrosh/MusicBot),
via the maintained fork by arif-banai (https://github.com/arif-banai/MusicBot).
See NOTICE for attribution. Licensed under Apache 2.0.

YouTube-side changes had broken playback entirely. Fixes:

- Apply the remote signature cipher independently of OAuth. Deciphering and
  authentication are unrelated, but the cipher was only configured when OAuth
  was enabled, so the default install fell back to the bundled extractor and
  failed with "Must find sig function from script: /s/player/<id>/...".
  Now always applied, and configurable via playback.youtube.remoteCipher.url.

- Add the ANDROID client and order the client list by reliability. ANDROID is
  currently the only client YouTube reliably streams to anonymously. WEB moves
  last, as YouTube answers it with SABR-only responses carrying no playable
  format ("No supported audio streams available, available types:").

- Detect sign-in failures across the whole exception graph. The existing hint
  could never fire: it matched the aggregate AllClientsFailedException message
  rather than the per-client reasons, and compared against an ASCII apostrophe
  while YouTube sends U+2019.

- Track youtube-source past 1.18.2, which predates the TV client User-Agent fix
  and the contentLength recovery fix.

Measured on previously failing tracks: 5/5 playing, stable across repeat runs
(was 1/5). No OAuth required. Adds 17 tests; 676 unit + 48 integration pass.
This commit is contained in:
purnell569 committed 2026-09-11 13:47:20 +09:30
commit 0941987234
295 files changed
+58207

No files matched your search

+71
View File
@@ -0,0 +1,71 @@
#!/bin/sh
# This will have this script check for a new version of JMusicBot every
# startup (and download it if the latest version isn't currently downloaded)
DOWNLOAD=true
# This will cause the script to run in a loop so that the bot auto-restarts
# when you use the shutdown command
LOOP=true
# JVM options for running JMusicBot
# --enable-native-access=ALL-UNNAMED: Required for Java 22+ to load native libraries (jdave, udpqueue)
JAVA_OPTS="${JAVA_OPTS:---enable-native-access=ALL-UNNAMED}"
download() {
if [ $DOWNLOAD = true ]; then
# First, check if the latest release is a pre-release
LATEST_RELEASE=$(curl -s https://api.github.com/repos/arif-banai/MusicBot/releases/latest)
IS_PRERELEASE=$(echo "$LATEST_RELEASE" | grep -o '"prerelease":[^,}]*' | head -1 | grep -o 'true')
if [ "$IS_PRERELEASE" = "true" ]; then
# Latest is a pre-release, so get all releases and find the first non-prerelease
ALL_RELEASES=$(curl -s https://api.github.com/repos/arif-banai/MusicBot/releases?per_page=10)
# Find the first release block that has "prerelease": false, then extract JAR URL from it
# This handles the JSON structure where assets are nested
URL=$(echo "$ALL_RELEASES" | awk '
BEGIN { in_non_prerelease = 0; found = 0 }
/"prerelease":\s*false/ { in_non_prerelease = 1 }
/"prerelease":\s*true/ { in_non_prerelease = 0 }
in_non_prerelease && /"browser_download_url".*\.jar/ && !found {
match($0, /"browser_download_url":\s*"([^"]+\.jar)"/, arr)
if (arr[1] != "") {
print arr[1]
found = 1
exit
}
}
')
else
# Latest is not a pre-release, use it
URL=$(echo "$LATEST_RELEASE" | grep -i "browser_download_url.*\.jar" | sed 's/.*\(http.*\)"/\1/')
fi
FILENAME=$(echo $URL | sed 's/.*\/\([^\/]*\)/\1/')
if [ -f $FILENAME ]; then
echo "Latest version already downloaded (${FILENAME})"
else
curl -L $URL -o $FILENAME
fi
fi
}
run() {
# JVM flags for optimal audio performance (set -Xms/-Xmx via JAVA_OPTS if desired):
# -XX:+UseZGC: Sub-millisecond GC pauses (generational mode is default in JDK 24+)
# -XX:+AlwaysPreTouch: Pre-allocate memory at startup to avoid page faults
# shellcheck disable=SC2086
java -XX:+UseZGC \
-XX:+AlwaysPreTouch \
-Dnogui=true \
$JAVA_OPTS \
-jar $(ls -t JMusicBot* | head -1)
}
while
download
run
$LOOP
do
continue
done