mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-09-27 03:28:14 -05:00
feat(scrape): harden preflight and cron config for Documents archives
Preflight probes skip forbidden channels when seeded archives exist. Cron installer passes container config path and supports --config override. Compose and docs align with append-only ~/Documents scrape workflow.
This commit is contained in:
@@ -645,26 +645,16 @@ resolve_target_channels() {
|
||||
fi
|
||||
}
|
||||
|
||||
preflight_target() {
|
||||
local target_json=$1
|
||||
local defaults_json=$2
|
||||
local target_name output_dir
|
||||
local probe_channel_id probe_dir probe_output
|
||||
local -a channel_ids
|
||||
preflight_probe_channel() {
|
||||
local probe_channel_id=$1
|
||||
local output_dir=$2
|
||||
local probe_dir probe_output probe_log
|
||||
local -a probe_command after_id probe_destination
|
||||
local probe_status=0
|
||||
|
||||
target_name=$(jq -r '.name' <<<"$target_json")
|
||||
output_dir=$(jq -r '.output_dir' <<<"$target_json")
|
||||
bootstrap_channel_map_from_archives "$output_dir"
|
||||
|
||||
mapfile -t channel_ids < <(resolve_target_channels "$target_json" "$defaults_json")
|
||||
if (( ${#channel_ids[@]} == 0 )); then
|
||||
die "Target '$target_name' resolved no channels during preflight."
|
||||
fi
|
||||
|
||||
probe_channel_id="${channel_ids[0]}"
|
||||
probe_dir=$(mktemp -d "${TMPDIR:-/tmp}/dce-preflight.${probe_channel_id}.XXXXXX")
|
||||
probe_output="$probe_dir/probe.json"
|
||||
local -a probe_command after_id probe_destination
|
||||
probe_log=$(mktemp "${TMPDIR:-/tmp}/dce-preflight-log.${probe_channel_id}.XXXXXX")
|
||||
|
||||
probe_destination=$(resolve_destination_path "$output_dir" "$probe_channel_id")
|
||||
after_id=""
|
||||
@@ -683,13 +673,75 @@ preflight_target() {
|
||||
probe_command+=(--after "$after_id")
|
||||
fi
|
||||
|
||||
if ! "${probe_command[@]}"; then
|
||||
set +e
|
||||
"${probe_command[@]}" >"$probe_log" 2>&1
|
||||
probe_status=$?
|
||||
set -e
|
||||
|
||||
if (( probe_status == 0 )); then
|
||||
rm -f "$probe_log"
|
||||
rm -rf "$probe_dir"
|
||||
die "Target '$target_name' failed authenticated preflight on channel '$probe_channel_id'."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if is_skippable_channel_export_failure "$probe_log"; then
|
||||
log "Preflight probe skipped channel $probe_channel_id (forbidden or inaccessible)."
|
||||
cat "$probe_log" >&2
|
||||
rm -f "$probe_log"
|
||||
rm -rf "$probe_dir"
|
||||
return 2
|
||||
fi
|
||||
|
||||
cat "$probe_log" >&2
|
||||
rm -f "$probe_log"
|
||||
rm -rf "$probe_dir"
|
||||
log "Preflight ok for target '$target_name': ${#channel_ids[@]} channel(s) resolved for $output_dir."
|
||||
return 1
|
||||
}
|
||||
|
||||
preflight_target() {
|
||||
local target_json=$1
|
||||
local defaults_json=$2
|
||||
local target_name output_dir
|
||||
local probe_channel_id
|
||||
local -a channel_ids seeded_channel_ids
|
||||
local probe_status=0
|
||||
local skipped_channels=0
|
||||
local probed_channels=0
|
||||
|
||||
target_name=$(jq -r '.name' <<<"$target_json")
|
||||
output_dir=$(jq -r '.output_dir' <<<"$target_json")
|
||||
bootstrap_channel_map_from_archives "$output_dir"
|
||||
|
||||
mapfile -t channel_ids < <(resolve_target_channels "$target_json" "$defaults_json")
|
||||
if (( ${#channel_ids[@]} == 0 )); then
|
||||
die "Target '$target_name' resolved no channels during preflight."
|
||||
fi
|
||||
|
||||
for probe_channel_id in "${channel_ids[@]}"; do
|
||||
probed_channels=$((probed_channels + 1))
|
||||
preflight_probe_channel "$probe_channel_id" "$output_dir" || probe_status=$?
|
||||
case "$probe_status" in
|
||||
0)
|
||||
log "Preflight ok for target '$target_name': ${#channel_ids[@]} channel(s) resolved for $output_dir."
|
||||
return 0
|
||||
;;
|
||||
2)
|
||||
skipped_channels=$((skipped_channels + 1))
|
||||
probe_status=0
|
||||
;;
|
||||
*)
|
||||
die "Target '$target_name' failed authenticated preflight on channel '$probe_channel_id'."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
mapfile -t seeded_channel_ids < <(load_archive_seed_channel_ids "$output_dir" | sort -u)
|
||||
if (( skipped_channels == probed_channels && ${#seeded_channel_ids[@]} > 0 )); then
|
||||
log "Preflight ok for target '$target_name' with warning: all ${#channel_ids[@]} resolved channel(s) are inaccessible, but ${#seeded_channel_ids[@]} seeded archive(s) exist under $output_dir."
|
||||
return 0
|
||||
fi
|
||||
|
||||
die "Target '$target_name' failed preflight: every resolved channel is inaccessible and no seeded archives exist under $output_dir."
|
||||
}
|
||||
|
||||
scrape_target() {
|
||||
|
||||
@@ -45,6 +45,7 @@ Options:
|
||||
--cron EXPR Use an explicit five-field cron expression instead of --interval/--at.
|
||||
--job-name NAME Marker name for the installed cron block. Default: discord-scrape
|
||||
--log-file PATH Cron log file. Default: $LOG_FILE
|
||||
--config PATH Scrape targets JSON. Default: $CONFIG_FILE
|
||||
--env-file PATH Compose env file. Default: $ENV_FILE
|
||||
--skip-preflight Install the cron job without running the authenticated container preflight.
|
||||
--dry-run Print the cron block instead of installing it.
|
||||
@@ -130,6 +131,22 @@ append_target_args() {
|
||||
done
|
||||
}
|
||||
|
||||
container_config_path() {
|
||||
local config_path=$1
|
||||
|
||||
if [[ "$config_path" == "$REPO_ROOT/config/"* ]]; then
|
||||
printf '/config/%s\n' "$(basename "$config_path")"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$config_path" == config/* ]]; then
|
||||
printf '/config/%s\n' "${config_path#config/}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf '%s\n' "$config_path"
|
||||
}
|
||||
|
||||
ensure_target_directories() {
|
||||
local selected_targets_json archive_root output_dir
|
||||
|
||||
@@ -182,6 +199,7 @@ run_preflight() {
|
||||
--env-file "$ENV_FILE"
|
||||
--compose-file "$COMPOSE_FILE"
|
||||
preflight
|
||||
--config "$(container_config_path "$CONFIG_FILE")"
|
||||
)
|
||||
append_target_args preflight_args
|
||||
"${preflight_args[@]}"
|
||||
@@ -230,6 +248,11 @@ main() {
|
||||
LOG_FILE=$2
|
||||
shift 2
|
||||
;;
|
||||
--config)
|
||||
[[ $# -ge 2 ]] || die "Missing value for --config."
|
||||
CONFIG_FILE=$2
|
||||
shift 2
|
||||
;;
|
||||
--env-file)
|
||||
[[ $# -ge 2 ]] || die "Missing value for --env-file."
|
||||
ENV_FILE=$2
|
||||
@@ -315,6 +338,7 @@ main() {
|
||||
--env-file "$ENV_FILE"
|
||||
--compose-file "$COMPOSE_FILE"
|
||||
scrape
|
||||
--config "$(container_config_path "$CONFIG_FILE")"
|
||||
)
|
||||
append_target_args scrape_args
|
||||
scrape_command=$(printf '%q ' "${scrape_args[@]}")
|
||||
|
||||
Reference in New Issue
Block a user