170 lines
4.4 KiB
Bash
170 lines
4.4 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}"
|
|
GUILD_NAME=""
|
|
ASSUME_YES=0
|
|
|
|
if [[ -f "$ENV_FILE" ]]; then
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
source "$ENV_FILE"
|
|
set +a
|
|
fi
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $(basename "$0") <guild name> [--yes]
|
|
|
|
Permanently deletes a guild and its related character-database records.
|
|
The worldserver must be stopped before running this script.
|
|
|
|
Options:
|
|
--yes Skip the interactive confirmation
|
|
-h, --help Show this help
|
|
|
|
Examples:
|
|
docker compose stop ac-worldserver
|
|
./delete-guild.sh "Название гильдии"
|
|
./delete-guild.sh "Название гильдии" --yes
|
|
docker compose start ac-worldserver
|
|
EOF
|
|
}
|
|
|
|
log() {
|
|
printf '[delete-guild] %s\n' "$*"
|
|
}
|
|
|
|
while (($#)); do
|
|
case "$1" in
|
|
--yes)
|
|
ASSUME_YES=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
-*)
|
|
printf 'Unknown option: %s\n\n' "$1" >&2
|
|
usage >&2
|
|
exit 1
|
|
;;
|
|
*)
|
|
if [[ -n "$GUILD_NAME" ]]; then
|
|
printf 'Only one guild name may be specified\n\n' >&2
|
|
usage >&2
|
|
exit 1
|
|
fi
|
|
GUILD_NAME="$1"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$GUILD_NAME" ]]; then
|
|
usage >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$GUILD_NAME" == *$'\n'* || "$GUILD_NAME" == *$'\r'* || "$GUILD_NAME" == *$'\t'* ]]; then
|
|
printf 'Guild name must not contain control characters\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
cd "$ROOT_DIR"
|
|
|
|
RUNNING_SERVICES="$(docker compose ps --status running --services)"
|
|
|
|
if grep -qx 'ac-worldserver' <<<"$RUNNING_SERVICES"; then
|
|
printf 'ac-worldserver is running. Stop it first:\n docker compose stop ac-worldserver\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! grep -qx 'ac-database' <<<"$RUNNING_SERVICES"; then
|
|
printf 'ac-database is not running. Start it first:\n docker compose up -d ac-database\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
export ACORE_DELETE_GUILD_NAME="$GUILD_NAME"
|
|
SQL_GUILD_NAME="$(python3 <<'PY'
|
|
import os
|
|
|
|
value = os.environ["ACORE_DELETE_GUILD_NAME"]
|
|
print("'" + value.replace("\\", "\\\\").replace("'", "\\'") + "'")
|
|
PY
|
|
)"
|
|
|
|
GUILD_ROW="$(
|
|
docker compose exec -T ac-database bash -lc \
|
|
'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" --batch --skip-column-names acore_characters' \
|
|
<<<"SELECT guildid, name, leaderguid FROM guild WHERE name = ${SQL_GUILD_NAME} LIMIT 1;"
|
|
)"
|
|
|
|
if [[ -z "$GUILD_ROW" ]]; then
|
|
printf 'Guild not found: %s\n' "$GUILD_NAME" >&2
|
|
exit 1
|
|
fi
|
|
|
|
IFS=$'\t' read -r GUILD_ID FOUND_NAME LEADER_GUID <<<"$GUILD_ROW"
|
|
log "found guild id=${GUILD_ID}, name=${FOUND_NAME}, leader=${LEADER_GUID}"
|
|
|
|
if ((ASSUME_YES == 0)); then
|
|
printf 'This permanently deletes the guild and all items in its bank.\n'
|
|
printf 'Type the guild name to confirm: '
|
|
read -r CONFIRMATION
|
|
if [[ "$CONFIRMATION" != "$FOUND_NAME" ]]; then
|
|
printf 'Confirmation did not match; nothing was deleted.\n' >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
SQL=$(cat <<EOF
|
|
START TRANSACTION;
|
|
|
|
SET @guild_id := ${GUILD_ID};
|
|
|
|
CREATE TEMPORARY TABLE delete_guild_members (
|
|
guid INT UNSIGNED NOT NULL PRIMARY KEY
|
|
) ENGINE=MEMORY
|
|
SELECT guid FROM guild_member WHERE guildid = @guild_id;
|
|
|
|
CREATE TEMPORARY TABLE delete_guild_bank_items (
|
|
item_guid INT UNSIGNED NOT NULL PRIMARY KEY
|
|
) ENGINE=MEMORY
|
|
SELECT item_guid FROM guild_bank_item WHERE guildid = @guild_id;
|
|
|
|
DELETE item_instance
|
|
FROM item_instance
|
|
INNER JOIN delete_guild_bank_items
|
|
ON delete_guild_bank_items.item_guid = item_instance.guid;
|
|
|
|
DELETE guild_member_withdraw
|
|
FROM guild_member_withdraw
|
|
INNER JOIN delete_guild_members
|
|
ON delete_guild_members.guid = guild_member_withdraw.guid;
|
|
|
|
DELETE FROM guild_bank_eventlog WHERE guildid = @guild_id;
|
|
DELETE FROM guild_eventlog WHERE guildid = @guild_id;
|
|
DELETE FROM guild_bank_right WHERE guildid = @guild_id;
|
|
DELETE FROM guild_bank_item WHERE guildid = @guild_id;
|
|
DELETE FROM guild_bank_tab WHERE guildid = @guild_id;
|
|
DELETE FROM guild_rank WHERE guildid = @guild_id;
|
|
DELETE FROM guild_member WHERE guildid = @guild_id;
|
|
DELETE FROM guild WHERE guildid = @guild_id;
|
|
|
|
SET @deleted := ROW_COUNT();
|
|
COMMIT;
|
|
|
|
SELECT @guild_id AS guildid, @deleted AS deleted;
|
|
EOF
|
|
)
|
|
|
|
log "deleting guild ${FOUND_NAME} (${GUILD_ID})"
|
|
docker compose exec -T ac-database bash -lc \
|
|
'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" --show-warnings acore_characters' <<<"$SQL"
|
|
|
|
log "guild deleted"
|