123 lines
3.8 KiB
Bash
123 lines
3.8 KiB
Bash
|
#!/bin/bash
|
||
|
# shellcheck disable=SC2154,SC2034
|
||
|
# beatsaber-ntfy, a bash script (with jq, bc, and curl) to push notifications to a ntfy.sh server on beatsaber leaderboard statistics updates
|
||
|
# Global configuration
|
||
|
INTERVAL=3600
|
||
|
# Set to empty string to disable
|
||
|
SCORESABER_DIR="./scoresaber-players/"
|
||
|
BEATLEADER_DIR="./beatleader-players/"
|
||
|
|
||
|
# Variables taken from SS/BL API
|
||
|
PLAYER_STATS_VARS="name country pp rank countryRank banned inactive"
|
||
|
# Settings stored per player
|
||
|
SETTINGS_VARS="NTFY_URL COUNTRY_THRESHOLD RANK_THRESHOLD PP_THRESHOLD"
|
||
|
|
||
|
stats_routine() {
|
||
|
( if [[ -n "$SCORESABER_DIR" ]]; then
|
||
|
cd "$SCORESABER_DIR" || exit 1
|
||
|
for PLAYER in *; do
|
||
|
update_player_stats "$PLAYER" "ScoreSaber" "https://scoresaber.com/api/player/$PLAYER/basic" "https://scoresaber.com/u/$PLAYER"
|
||
|
done
|
||
|
fi )
|
||
|
( if [[ -n "$BEATLEADER_DIR" ]]; then
|
||
|
cd "$BEATLEADER_DIR" || exit 1
|
||
|
for PLAYER in *; do
|
||
|
update_player_stats "$PLAYER" "BeatLeader" "https://api.beatleader.xyz/player/$PLAYER" "https://beatleader.xyz/u/$PLAYER"
|
||
|
done
|
||
|
fi )
|
||
|
}
|
||
|
|
||
|
update_player_stats() {
|
||
|
# Name arguments
|
||
|
PLAYER=$1
|
||
|
TITLE=$2
|
||
|
API_URL=$3
|
||
|
PROFILE_URL=$4
|
||
|
# If the API fails, don't continue
|
||
|
echo "Fetching stats for $PLAYER on $TITLE"
|
||
|
if ! UPDATED_STATS="$(curl -s --fail-with-body "$API_URL")"; then
|
||
|
echo "Failed to gather stats for $PLAYER on $TITLE due to:"
|
||
|
echo "$UPDATED_STATS"
|
||
|
return
|
||
|
fi
|
||
|
# Get the old playerdata
|
||
|
# shellcheck disable=SC1090
|
||
|
source "$PLAYER"
|
||
|
|
||
|
# Set the new playerdata
|
||
|
for VAR in $PLAYER_STATS_VARS; do
|
||
|
declare "UPD_${VAR}=$(echo "$UPDATED_STATS" | jq -r ".$VAR")"
|
||
|
done
|
||
|
|
||
|
# If there are no known stats, update them without sending a notification
|
||
|
if [[ -z "$rank" ]]; then
|
||
|
INIT_STATS=true
|
||
|
else
|
||
|
INIT_STATS=false
|
||
|
fi
|
||
|
|
||
|
# Calculate stat differences
|
||
|
RANK_DIFF=$(( rank - UPD_rank ))
|
||
|
COUNTRYRANK_DIFF=$(( countryRank - UPD_countryRank ))
|
||
|
PP_DIFF=$(bc <<< "$UPD_pp - $pp")
|
||
|
|
||
|
# Check if criteria for notification are met
|
||
|
SEND_NOTIF=false
|
||
|
if [[ ${RANK_DIFF#-} -gt ${RANK_THRESHOLD} ]]; then SEND_NOTIF=true; fi
|
||
|
if [[ ${COUNTRYRANK_DIFF#-} -gt ${COUNTRYRANK_THRESHOLD} ]]; then SEND_NOTIF=true; fi
|
||
|
if [[ 1 -eq "$(bc <<< "${PP_DIFF#-} > ${PP_THRESHOLD}")" ]]; then SEND_NOTIF=true; fi
|
||
|
if [[ $inactive != "$UPD_inactive" ]]; then SEND_NOTIF=true; fi
|
||
|
if [[ $banned != "$UPD_banned" ]]; then SEND_NOTIF=true; fi
|
||
|
|
||
|
if ! $SEND_NOTIF; then
|
||
|
return
|
||
|
fi
|
||
|
|
||
|
# Add "+" to stats that increased
|
||
|
if [[ ${RANK_DIFF} -gt 0 ]]; then RANK_DIFF="+$RANK_DIFF"; fi
|
||
|
if [[ ${COUNTRYRANK_DIFF} -gt 0 ]]; then COUNTRYRANK_DIFF="+$COUNTRYRANK_DIFF"; fi
|
||
|
if [[ 1 -eq "$(bc <<< "${PP_DIFF} > 0")" ]]; then PP_DIFF="+$PP_DIFF"; fi
|
||
|
|
||
|
# Create the notification text
|
||
|
NOTIF="Global: $rank > $UPD_rank ($RANK_DIFF)
|
||
|
Country ($UPD_country): $countryRank > $UPD_countryRank ($COUNTRYRANK_DIFF)
|
||
|
PP: $pp > $UPD_pp ($PP_DIFF)"
|
||
|
if [[ $inactive != "$UPD_inactive" ]]; then
|
||
|
NOTIF="$NOTIF
|
||
|
Inactive status has changed: $inactive > $UPD_inactive"
|
||
|
fi
|
||
|
if [[ $banned != "$UPD_banned" ]]; then
|
||
|
NOTIF="$NOTIF
|
||
|
Banned status has changed: $banned > $UPD_banned"
|
||
|
fi
|
||
|
|
||
|
# Send the notification
|
||
|
if ! $INIT_STATS; then
|
||
|
echo "${UPD_name}'s $TITLE stats have changed, sending notification"
|
||
|
if ! NOTIF_RESPONSE=$(curl -s --fail-with-body -X POST -H "Title: $UPD_name's $TITLE Stats" -H "Click: $PROFILE_URL" -d "$NOTIF" "$NTFY_URL"); then
|
||
|
echo "Failed to send notification:"
|
||
|
echo "$NOTIF_RESPONSE"
|
||
|
# If we can't notify the user, don't update the stats file.
|
||
|
# Ensures notifications are accurate after ntfy server is fixed.
|
||
|
return
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
# Recreate the player file
|
||
|
NEW_PLAYER=""
|
||
|
for VAR in $SETTINGS_VARS; do
|
||
|
NEW_PLAYER="$NEW_PLAYER
|
||
|
$VAR=$(eval "echo \$$VAR")"
|
||
|
done
|
||
|
for VAR in $PLAYER_STATS_VARS; do
|
||
|
NEW_PLAYER="$NEW_PLAYER
|
||
|
$VAR=\"$(eval "echo \"\$UPD_$VAR\"")\""
|
||
|
done
|
||
|
echo "${NEW_PLAYER:1}" > "$PLAYER"
|
||
|
}
|
||
|
|
||
|
while true; do
|
||
|
stats_routine
|
||
|
sleep "$INTERVAL"
|
||
|
done
|