fpaste: add batch delete and --all with confirmation
This commit is contained in:
87
fpaste
87
fpaste
@@ -635,26 +635,73 @@ def cmd_get(args: argparse.Namespace, config: dict[str, Any]) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def cmd_delete(args: argparse.Namespace, config: dict[str, Any]) -> None:
|
def cmd_delete(args: argparse.Namespace, config: dict[str, Any]) -> None:
|
||||||
"""Delete a paste."""
|
"""Delete paste(s)."""
|
||||||
require_auth(config)
|
require_auth(config)
|
||||||
|
|
||||||
paste_id = args.id.split("/")[-1]
|
delete_all = getattr(args, "all", False)
|
||||||
url = f"{config['server'].rstrip('/')}/{paste_id}"
|
confirm_count = getattr(args, "confirm", None)
|
||||||
|
paste_ids = [pid.split("/")[-1] for pid in (args.ids or [])]
|
||||||
|
|
||||||
status, _, _ = request(
|
# Validate arguments
|
||||||
url, method="DELETE", headers=auth_headers(config), ssl_context=config.get("ssl_context")
|
if delete_all and paste_ids:
|
||||||
)
|
die("cannot specify both --all and paste IDs")
|
||||||
|
if not delete_all and not paste_ids:
|
||||||
|
die("specify paste ID(s) or use --all")
|
||||||
|
|
||||||
if status == 200:
|
if delete_all:
|
||||||
print(f"deleted: {paste_id}")
|
# Fetch all pastes to get count and IDs
|
||||||
elif status == 404:
|
url = f"{config['server'].rstrip('/')}/pastes?all=1&limit=1000"
|
||||||
die(f"not found: {paste_id}")
|
status, body, _ = request(
|
||||||
elif status == 403:
|
url, headers=auth_headers(config), ssl_context=config.get("ssl_context")
|
||||||
die("permission denied (not owner)")
|
)
|
||||||
elif status == 401:
|
if status == 401:
|
||||||
die("authentication failed")
|
die("authentication failed")
|
||||||
else:
|
if status != 200:
|
||||||
die(f"delete failed ({status})")
|
die(f"failed to list pastes ({status})")
|
||||||
|
|
||||||
|
data = json.loads(body)
|
||||||
|
pastes = data.get("pastes", [])
|
||||||
|
total = len(pastes)
|
||||||
|
|
||||||
|
if total == 0:
|
||||||
|
print("no pastes to delete")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Require confirmation with expected count
|
||||||
|
if confirm_count is None:
|
||||||
|
die(f"--all requires --confirm {total} (found {total} pastes)")
|
||||||
|
if confirm_count != total:
|
||||||
|
die(f"confirmation mismatch: expected {confirm_count}, found {total}")
|
||||||
|
|
||||||
|
paste_ids = [p["id"] for p in pastes]
|
||||||
|
|
||||||
|
# Delete pastes
|
||||||
|
deleted = 0
|
||||||
|
failed = 0
|
||||||
|
for paste_id in paste_ids:
|
||||||
|
url = f"{config['server'].rstrip('/')}/{paste_id}"
|
||||||
|
status, _, _ = request(
|
||||||
|
url,
|
||||||
|
method="DELETE",
|
||||||
|
headers=auth_headers(config),
|
||||||
|
ssl_context=config.get("ssl_context"),
|
||||||
|
)
|
||||||
|
if status == 200:
|
||||||
|
print(f"deleted: {paste_id}")
|
||||||
|
deleted += 1
|
||||||
|
elif status == 404:
|
||||||
|
print(f"not found: {paste_id}", file=sys.stderr)
|
||||||
|
failed += 1
|
||||||
|
elif status == 403:
|
||||||
|
print(f"permission denied: {paste_id}", file=sys.stderr)
|
||||||
|
failed += 1
|
||||||
|
else:
|
||||||
|
print(f"failed ({status}): {paste_id}", file=sys.stderr)
|
||||||
|
failed += 1
|
||||||
|
|
||||||
|
# Summary for batch operations
|
||||||
|
if len(paste_ids) > 1:
|
||||||
|
print(f"\n{deleted} deleted, {failed} failed")
|
||||||
|
|
||||||
|
|
||||||
def cmd_info(args: argparse.Namespace, config: dict[str, Any]) -> None:
|
def cmd_info(args: argparse.Namespace, config: dict[str, Any]) -> None:
|
||||||
@@ -1285,8 +1332,12 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
p_get.add_argument("-m", "--meta", action="store_true", help="show metadata only")
|
p_get.add_argument("-m", "--meta", action="store_true", help="show metadata only")
|
||||||
|
|
||||||
# delete
|
# delete
|
||||||
p_delete = subparsers.add_parser("delete", aliases=["d", "rm"], help="delete paste")
|
p_delete = subparsers.add_parser("delete", aliases=["d", "rm"], help="delete paste(s)")
|
||||||
p_delete.add_argument("id", help="paste ID or URL")
|
p_delete.add_argument("ids", nargs="*", metavar="ID", help="paste ID(s) or URL(s)")
|
||||||
|
p_delete.add_argument("-a", "--all", action="store_true", help="delete all pastes (admin)")
|
||||||
|
p_delete.add_argument(
|
||||||
|
"-c", "--confirm", type=int, metavar="N", help="confirm expected delete count"
|
||||||
|
)
|
||||||
|
|
||||||
# info
|
# info
|
||||||
subparsers.add_parser("info", aliases=["i"], help="show server info")
|
subparsers.add_parser("info", aliases=["i"], help="show server info")
|
||||||
|
|||||||
Reference in New Issue
Block a user