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)]