forked from claw/flaskpaste
fpaste: add --all flag and expiry countdown to list
This commit is contained in:
48
fpaste
48
fpaste
@@ -10,6 +10,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
import ssl
|
import ssl
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
import urllib.error
|
import urllib.error
|
||||||
import urllib.request
|
import urllib.request
|
||||||
from datetime import UTC, datetime, timedelta
|
from datetime import UTC, datetime, timedelta
|
||||||
@@ -336,6 +337,28 @@ def format_timestamp(ts: int | float) -> str:
|
|||||||
return dt.strftime("%Y-%m-%d %H:%M")
|
return dt.strftime("%Y-%m-%d %H:%M")
|
||||||
|
|
||||||
|
|
||||||
|
def format_time_remaining(expires_at: int | float | None) -> str:
|
||||||
|
"""Format time remaining until expiry."""
|
||||||
|
if not expires_at:
|
||||||
|
return ""
|
||||||
|
now = time.time()
|
||||||
|
remaining = expires_at - now
|
||||||
|
if remaining <= 0:
|
||||||
|
return "expired"
|
||||||
|
if remaining < 60:
|
||||||
|
return f"{int(remaining)}s"
|
||||||
|
if remaining < 3600:
|
||||||
|
return f"{int(remaining / 60)}m"
|
||||||
|
if remaining < 86400:
|
||||||
|
hours = int(remaining / 3600)
|
||||||
|
return f"{hours}h"
|
||||||
|
days = int(remaining / 86400)
|
||||||
|
if days >= 365:
|
||||||
|
years = days // 365
|
||||||
|
return f"{years}y"
|
||||||
|
return f"{days}d"
|
||||||
|
|
||||||
|
|
||||||
def parse_date(date_str: str) -> int:
|
def parse_date(date_str: str) -> int:
|
||||||
"""Parse date string to Unix timestamp."""
|
"""Parse date string to Unix timestamp."""
|
||||||
if not date_str:
|
if not date_str:
|
||||||
@@ -359,22 +382,27 @@ def get_extension_for_mime(mime_type: str) -> str:
|
|||||||
return MIME_EXTENSIONS.get(mime_type, ".bin")
|
return MIME_EXTENSIONS.get(mime_type, ".bin")
|
||||||
|
|
||||||
|
|
||||||
def format_paste_row(paste: dict[str, Any]) -> str:
|
def format_paste_row(paste: dict[str, Any], show_owner: bool = False) -> str:
|
||||||
"""Format a paste as a table row."""
|
"""Format a paste as a table row."""
|
||||||
paste_id = paste["id"]
|
paste_id = paste["id"]
|
||||||
mime_type = paste.get("mime_type", "unknown")[:16]
|
mime_type = paste.get("mime_type", "unknown")[:16]
|
||||||
size = format_size(paste.get("size", 0))
|
size = format_size(paste.get("size", 0))
|
||||||
created = format_timestamp(paste.get("created_at", 0))
|
created = format_timestamp(paste.get("created_at", 0))
|
||||||
|
|
||||||
|
# Time remaining until expiry
|
||||||
|
expires = format_time_remaining(paste.get("expires_at"))
|
||||||
|
|
||||||
flags = []
|
flags = []
|
||||||
if paste.get("burn_after_read"):
|
if paste.get("burn_after_read"):
|
||||||
flags.append("burn")
|
flags.append("burn")
|
||||||
if paste.get("password_protected"):
|
if paste.get("password_protected"):
|
||||||
flags.append("pass")
|
flags.append("pass")
|
||||||
if paste.get("expires_at"):
|
|
||||||
flags.append("exp")
|
|
||||||
|
|
||||||
return f"{paste_id:<12} {mime_type:<16} {size:>6} {created:<16} {' '.join(flags)}"
|
flags_str = " ".join(flags)
|
||||||
|
row = f"{paste_id:<12} {mime_type:<16} {size:>6} {created:<16} {expires:<8} {flags_str}"
|
||||||
|
if show_owner and paste.get("owner"):
|
||||||
|
row += f" {paste['owner'][:12]}"
|
||||||
|
return row
|
||||||
|
|
||||||
|
|
||||||
def print_paste_list(
|
def print_paste_list(
|
||||||
@@ -392,9 +420,14 @@ def print_paste_list(
|
|||||||
print("no pastes found")
|
print("no pastes found")
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"{'ID':<12} {'TYPE':<16} {'SIZE':>6} {'CREATED':<16} FLAGS")
|
# Check if owner data is present (admin view)
|
||||||
|
show_owner = any(paste.get("owner") for paste in pastes)
|
||||||
|
header = f"{'ID':<12} {'TYPE':<16} {'SIZE':>6} {'CREATED':<16} {'EXPIRES':<8} FLAGS"
|
||||||
|
if show_owner:
|
||||||
|
header += " OWNER"
|
||||||
|
print(header)
|
||||||
for paste in pastes:
|
for paste in pastes:
|
||||||
print(format_paste_row(paste))
|
print(format_paste_row(paste, show_owner=show_owner))
|
||||||
print(f"\n{summary}")
|
print(f"\n{summary}")
|
||||||
|
|
||||||
|
|
||||||
@@ -653,6 +686,8 @@ def cmd_list(args: argparse.Namespace, config: dict[str, Any]) -> None:
|
|||||||
require_auth(config)
|
require_auth(config)
|
||||||
|
|
||||||
params = []
|
params = []
|
||||||
|
if getattr(args, "all", False):
|
||||||
|
params.append("all=1")
|
||||||
if args.limit:
|
if args.limit:
|
||||||
params.append(f"limit={args.limit}")
|
params.append(f"limit={args.limit}")
|
||||||
if args.offset:
|
if args.offset:
|
||||||
@@ -1258,6 +1293,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
|
|
||||||
# list
|
# list
|
||||||
p_list = subparsers.add_parser("list", aliases=["ls"], help="list your pastes")
|
p_list = subparsers.add_parser("list", aliases=["ls"], help="list your pastes")
|
||||||
|
p_list.add_argument("-a", "--all", action="store_true", help="list all pastes (admin only)")
|
||||||
p_list.add_argument("-l", "--limit", type=int, metavar="N", help="max pastes (default: 50)")
|
p_list.add_argument("-l", "--limit", type=int, metavar="N", help="max pastes (default: 50)")
|
||||||
p_list.add_argument("-o", "--offset", type=int, metavar="N", help="skip first N pastes")
|
p_list.add_argument("-o", "--offset", type=int, metavar="N", help="skip first N pastes")
|
||||||
p_list.add_argument("--json", action="store_true", help="output as JSON")
|
p_list.add_argument("--json", action="store_true", help="output as JSON")
|
||||||
|
|||||||
Reference in New Issue
Block a user