add visibility and dpaste expirations

This commit is contained in:
Mirek Kratochvil 2025-10-13 21:29:09 +02:00
parent 9b6b4e6c61
commit daf737fa08

View file

@ -54,7 +54,22 @@ def auth_headers(args):
return {"Authorization": f"Bearer {token}"} return {"Authorization": f"Bearer {token}"}
def do_post_status(args, body, parent=None, optional=None): def post_visibility(args, is_head):
"""
choose the status visibility based on args and head-ness
"""
if args.direct:
return "direct"
if args.private:
return "private"
if args.public:
return "public" if is_head else "unlisted"
if args.all_public:
return "public"
return "public" if is_head else "unlisted"
def do_post_status(args, body, is_head, parent=None, optional=None):
""" """
POST a new status with body, optionally in reply-to `parent` post ID, and POST a new status with body, optionally in reply-to `parent` post ID, and
with attached `optional` contents to body. with attached `optional` contents to body.
@ -67,7 +82,7 @@ def do_post_status(args, body, parent=None, optional=None):
if optional if optional
else "" else ""
) )
data = {"status": st, "visibility": "direct"} # TODO parametrize direct data = {"status": st, "visibility": post_visibility(args, is_head)}
# visibility options: public head+unlisted, all unlisted, all private, all direct # visibility options: public head+unlisted, all unlisted, all private, all direct
if parent: if parent:
data["in_reply_to_id"] = parent data["in_reply_to_id"] = parent
@ -86,29 +101,33 @@ def do_post_status(args, body, parent=None, optional=None):
return (rj["id"], rj["url"]) return (rj["id"], rj["url"])
def do_pastebin_file(file): def do_pastebin_file(args):
""" """
Send the `file` to dpaste, returning URL for the raw file. Send the `file` to dpaste, returning URL for the raw file.
""" """
# DPASTE API USE RULES:
# - user-agent must be set properly def f(file):
# - 1 second between requests # DPASTE API USE RULES:
trace(f"sending `{file}' to dpaste...") # - user-agent must be set properly
r = requests.post( # - 1 second between requests
DPASTE_URL + "/api/v2/", trace(f"sending `{file}' to dpaste...")
data={ r = requests.post(
"content": Path(file).read_text(), DPASTE_URL + "/api/v2/",
"syntax": "diff", data={
"title": os.path.basename(file), "content": Path(file).read_text(),
"expiry_days": 1, # TODO remove after testing "syntax": "diff",
}, "title": os.path.basename(file),
headers={"User-agent": f"patchodon v{__version__}"}, "expiry_days": args.paste_expire_days,
timeout=300, # TODO passthrough args },
) headers={"User-agent": f"patchodon v{__version__}"},
time.sleep(1.1) timeout=args.timeout,
if r.status_code != 201: )
raise RuntimeError("dpaste POST failed for `{file}'") time.sleep(1.1)
return r.headers["location"] + ".txt" if r.status_code != 201:
raise RuntimeError("dpaste POST failed for `{file}'")
return r.headers["location"] + ".txt"
return f
def split_off_diff(s): def split_off_diff(s):
@ -150,12 +169,13 @@ def do_post(args):
) )
short_hashes = mapl(lambda x: x[0:8], hashes) short_hashes = mapl(lambda x: x[0:8], hashes)
full_hash = hashlib.sha1(" ".join(hashes).encode()).hexdigest() full_hash = hashlib.sha1(" ".join(hashes).encode()).hexdigest()
paste_raw_urls = mapl(do_pastebin_file, files) paste_raw_urls = mapl(do_pastebin_file(args), files)
trace("posting the header...") trace("posting the header...")
parent_post_id, url = do_post_status( parent_post_id, url = do_post_status(
args, args,
f"{mayline(args.recipient)}{mayline(args.subject)}" f"{mayline(args.recipient)}{mayline(args.subject)}"
f"[patchodon: {full_hash} / {' '.join(short_hashes)}]", f"[patchodon: {full_hash} / {' '.join(short_hashes)}]",
True,
) )
for fn, pst, hsh, series in zip( for fn, pst, hsh, series in zip(
files, paste_raw_urls, hashes, range(n_patches) files, paste_raw_urls, hashes, range(n_patches)
@ -166,6 +186,7 @@ def do_post(args):
f"{mayline(args.recipient)}" f"{mayline(args.recipient)}"
f"[patchodon {series+1}/{n_patches} {hsh}]\n" f"[patchodon {series+1}/{n_patches} {hsh}]\n"
f"{pst}\n", f"{pst}\n",
False,
parent=parent_post_id, parent=parent_post_id,
optional=split_off_diff(Path(fn).read_text()), optional=split_off_diff(Path(fn).read_text()),
) )
@ -384,6 +405,12 @@ def main():
" target project and patch topic" " target project and patch topic"
), ),
) )
post.add_argument(
"-x",
"--paste-expire-days",
default=14,
help="how many days should dpaste.com hold the patches (default: 14)",
)
post.add_argument( post.add_argument(
"patchfile", "patchfile",
nargs="*", nargs="*",
@ -393,6 +420,31 @@ def main():
" into patchodon)" " into patchodon)"
), ),
) )
visibility = post.add_mutually_exclusive_group()
visibility.add_argument(
"--public",
action="store_true",
help=(
"post head status publicly, patches unlisted (this is the default)"
),
)
visibility.add_argument(
"--all-public",
action="store_true",
help="post head status and all patches publicly",
)
visibility.add_argument(
"--private",
action="store_true",
help=(
"post statuses as private (visible by followers and recipient only)"
),
)
visibility.add_argument(
"--direct",
action="store_true",
help="post statuses as direct (visible only by the tagged recipients)",
)
get = cmds.add_parser("get") get = cmds.add_parser("get")
get.add_argument( get.add_argument(