post version 0, zero debugging yet
technically I'm vibecoding this and I'm the LLM here
This commit is contained in:
parent
92d36ddc7e
commit
c0b4d8692b
125
patchodon.py
125
patchodon.py
|
|
@ -3,9 +3,118 @@
|
|||
import sys, os
|
||||
import argparse
|
||||
import requests
|
||||
import hashlib
|
||||
import time
|
||||
|
||||
# NOTES: html2text: html2text
|
||||
# the replies are listed by context, should be link-listed to avoid issues,
|
||||
# should specify next hash to provide some kind of a filter
|
||||
# visibility public+unlisted, all unlisted, all private, all direct
|
||||
|
||||
VERSION = "0.1.0"
|
||||
|
||||
DPASTE_URL = "https://dpaste.com"
|
||||
|
||||
STATUS_LENGTH_LIMIT = 400
|
||||
|
||||
|
||||
def trace(x):
|
||||
sys.stderr.write(sys.argv[0] + ": " + x + "\n")
|
||||
|
||||
|
||||
def api_token(args):
|
||||
if args.debug_api_token:
|
||||
return args.debug_api_token
|
||||
if args.env_api_token:
|
||||
return os.environ["PATCHODON_API_TOKEN"]
|
||||
raise ("API token not specified")
|
||||
|
||||
|
||||
def do_post_status(args, body, parent=None, optional=None):
|
||||
if len(body) > STATUS_LENGTH_LIMIT:
|
||||
raise ("required status body too long")
|
||||
|
||||
if not args.instance_url:
|
||||
raise ("mastodon instance not specified")
|
||||
|
||||
token = api_token(args)
|
||||
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
st = body + (
|
||||
"\n" + optional[0 : (STATUS_LENGTH_LIMIT - len(body) - 1)]
|
||||
if optional
|
||||
else ""
|
||||
)
|
||||
data = {status: st, visibility: "unlisted"}
|
||||
if parent:
|
||||
data["in_reply_to_id"] = parent
|
||||
|
||||
r = requests.post(
|
||||
args.instance_url + "/api/v1/statuses", data=data, headers=headers
|
||||
)
|
||||
if r.status_code != 200:
|
||||
raise ("mastodon status posting failed ({r.status_code})")
|
||||
|
||||
return r.json.id
|
||||
|
||||
|
||||
def do_pastebin_file(file):
|
||||
# DPASTE API USE RULES:
|
||||
# - user-agent must be set properly
|
||||
# - 1 second between requests
|
||||
trace(f"pasting {file}...")
|
||||
r = requests.post(
|
||||
DPASTE_URL + "/api/v2/",
|
||||
data={
|
||||
"contents": open(file, "r").read(),
|
||||
"syntax": "diff",
|
||||
"title": os.path.basename(file),
|
||||
"expiry_days": 30,
|
||||
},
|
||||
headers={"User-agent": f"patchodon v{VERSION}"},
|
||||
)
|
||||
if r.status_code != 201:
|
||||
raise (f"dpaste POST failed for `{file}'")
|
||||
sleep(1.1)
|
||||
return r.headers["location"] + ".txt"
|
||||
|
||||
|
||||
def split_off_diff(s):
|
||||
return s.split("\ndiff --git ")[0]
|
||||
|
||||
|
||||
def do_post(args):
|
||||
files = args.patchfile
|
||||
if not files:
|
||||
trace("reading patchfile series from stdin")
|
||||
files = sys.stdin.readlines().map(lambda x: x.rstrip(chars="\n"))
|
||||
n_patches = len(files)
|
||||
hashes = files.map(lambda x: hashlib.sha1(open(x, "r").read()).hexdigest())
|
||||
short_hashes = hashes.map(lambda x: x[0:8])
|
||||
full_hash = hashlib.sha1(hashes.join(" ")).hexdigest()
|
||||
paste_raw_urls = map(do_pastebin_file, files)
|
||||
trace("posting the header...")
|
||||
parent_post_id, url = do_post_status(
|
||||
args,
|
||||
args.subject
|
||||
+ f"\n[patchodon hash {full_hash} shorts {short_hashes.join(' ')}]",
|
||||
)
|
||||
for fn, pst, hsh, series in zip(
|
||||
files, paste_raw_urls, hashes, range(n_patches)
|
||||
):
|
||||
trace(f"posting patch {series+1}/{n_patches}...")
|
||||
parent_post_id, _ = do_post_status(
|
||||
args,
|
||||
f"[patchodon {series+1}/{n_patches} {hsh}\n{pst}\n",
|
||||
parent=parent_post_id,
|
||||
optional=split_off_diff(open(fn, "r").read()),
|
||||
)
|
||||
print(url)
|
||||
|
||||
|
||||
def do_get(args):
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(
|
||||
|
|
@ -38,7 +147,13 @@ def main():
|
|||
"-i", "--instance-url", help="mastodon instance URL to post to"
|
||||
)
|
||||
post.add_argument(
|
||||
"-r", "--recipient", help="recipient to tag in the initial post"
|
||||
"-s",
|
||||
"--subject",
|
||||
default="",
|
||||
help=(
|
||||
"start of the initial post (e.g. to @tag someone and name the"
|
||||
" project and topic)"
|
||||
),
|
||||
)
|
||||
post.add_argument(
|
||||
"patchfile",
|
||||
|
|
@ -93,7 +208,13 @@ def main():
|
|||
),
|
||||
)
|
||||
args = ap.parse_args()
|
||||
print(args)
|
||||
|
||||
if args.command == "post":
|
||||
do_post(args)
|
||||
elif args.command == "get":
|
||||
do_get(args)
|
||||
else:
|
||||
raise ("fatal: args borked")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Reference in a new issue