social media crossposting tool. 3rd time's the charm
mastodon misskey crossposting bluesky
1import grapheme 2from cross.fragments import Fragment, LinkFragment 3from dataclasses import replace 4 5 6def canonical_label(label: str | None, href: str): 7 if not label or label == href: 8 return True 9 10 split = href.split("://", 1) 11 if len(split) > 1: 12 if split[1] == label: 13 return True 14 15 return False 16 17 18class FragmentSplitter: 19 def __init__(self, climit: int, urllen: int): 20 self.climit: int = climit 21 self.urllen: int = urllen 22 23 def normalize_link(self, label: str, url: str) -> str: 24 return label 25 26 def tally_lenght(self, post: tuple[str, list[Fragment]]): 27 return grapheme.length(post[0]) 28 29 def url_normalize( 30 self, text: str, fragments: list[Fragment] 31 ) -> tuple[str, list[Fragment]]: 32 if self.urllen == -1: 33 return text, fragments 34 btext = text.encode('utf-8') 35 36 nbytes = bytearray() 37 nfragments: list[Fragment] = [] 38 39 fragments = [fg for fg in fragments] 40 fragments.sort(key=lambda x: x.start) 41 42 last_index = 0 43 44 for fg in fragments: 45 if last_index < fg.start: 46 nbytes.extend(btext[last_index:fg.start]) 47 48 label_bytes = btext[fg.start:fg.end] 49 label = label_bytes.decode('utf-8') 50 51 nlabel = label 52 if isinstance(fg, LinkFragment): 53 nlabel = self.normalize_link(nlabel, fg.url) 54 55 nlabel_bytes = nlabel.encode('utf-8') 56 57 nstart = len(nbytes) 58 nbytes.extend(nlabel_bytes) 59 nend = len(nbytes) 60 61 nfg = replace(fg, start=nstart, end=nend) 62 nfragments.append(nfg) 63 64 last_index = fg.end 65 66 if last_index < len(btext): 67 nbytes.extend(btext[last_index:]) 68 69 return nbytes.decode('utf-8'), nfragments 70 71 def split( 72 self, text: str, fragments: list[Fragment] 73 ) -> list[tuple[str, list[Fragment]]]: 74 text, fragments = self.url_normalize(text, fragments) 75 if self.tally_lenght((text, fragments)) <= self.climit: 76 return [(text, fragments)]