social media crossposting tool. 3rd time's the charm
mastodon misskey crossposting bluesky
1from typing import Any, override 2import cross.fragments as f 3from util.splitter import FragmentSplitter, canonical_label 4 5LINK = 'app.bsky.richtext.facet#link' 6TAG = 'app.bsky.richtext.facet#tag' 7MENTION = "app.bsky.richtext.facet#mention" 8 9class BskySplitter(FragmentSplitter): 10 def __init__(self): 11 super().__init__(300, 30) 12 13 @override 14 def normalize_link(self, label: str, url: str) -> str: 15 if canonical_label(label, url): 16 nlabel = url.split("://", 1)[1] 17 if len(nlabel) <= self.urllen: 18 return nlabel 19 return nlabel[: self.urllen - 1] + "" 20 return label 21 22# TODO handle extending overlapping fragments somehow 23def parse_facets( 24 text: str, 25 facets: list[dict[str, Any]] | None 26) -> tuple[str, list[f.Fragment]]: 27 if not facets: 28 return text, [] 29 30 btext = text.encode("utf-8") 31 nbytes = bytearray() 32 last_original_byte_index = 0 33 fragments: list[f.Fragment] = [] 34 35 for facet in facets: 36 original_start: int = facet['index']['byteStart'] 37 original_end: int = facet['index']['byteEnd'] 38 39 if last_original_byte_index < original_start: 40 nbytes.extend(btext[last_original_byte_index:original_start]) 41 42 fdict = {feat['$type']: feat for feat in facet.get('features', [])} 43 44 original_label_bytes = btext[original_start:original_end] 45 original_label_str = original_label_bytes.decode("utf-8") 46 47 nlabel_bytes = original_label_bytes 48 49 if LINK in fdict: 50 url: str = fdict.pop(LINK)['uri'] 51 label = original_label_str 52 53 split = url.split("://", 1) 54 full_url = False 55 if len(split) > 1: 56 if split[1].startswith(label): 57 full_url = True 58 if label.endswith("...") and split[1].startswith(label[:-3]): 59 full_url = True 60 61 if full_url: 62 nlabel_bytes = url.encode("utf-8") 63 64 nstart = len(nbytes) 65 nbytes.extend(nlabel_bytes) 66 nend = len(nbytes) 67 68 fragments.append(f.LinkFragment(start=nstart, end=nend, url=url)) 69 else: 70 nstart = len(nbytes) 71 nbytes.extend(nlabel_bytes) 72 nend = len(nbytes) 73 74 if TAG in fdict: 75 tag: str = fdict.pop(TAG)['tag'] 76 fragments.append(f.TagFragment(start=nstart, end=nend, tag=tag)) 77 78 if MENTION in fdict: 79 did: str = fdict.pop(MENTION)['did'] 80 fragments.append(f.MentionFragment(start=nstart, end=nend, uri=did)) 81 82 last_original_byte_index = original_end 83 84 if last_original_byte_index < len(btext): 85 nbytes.extend(btext[last_original_byte_index:]) 86 87 return nbytes.decode("utf-8"), fragments