eleven / ocho Public

Clone
git clone https://amadan.net/eleven/ocho

Plain git — no account needed to clone.

Download

Download this file

1package client
2
3import (
4 "fmt"
5 "net/url"
6 "strings"
7)
8
9// invitePrefix is the versioned fingerprint every minted link carries
10// (web/static/invite.js buildInviteFragment). Older links are bare T.
11const invitePrefix = "e1."
12
13// InviteLink is a parsed /join/... link: where to join, the secret T (never
14// sent to the server), and the inviter's suggested pre-fill name (rides in the
15// fragment for the same reason — the server must not see it).
16type InviteLink struct {
17 Base string // scheme://host origin
18 T string // the invite secret (base64url)
19 Name string // suggested name ("" when the link carries none)
20}
21
22// ParseInviteLink parses a full invite link — https://host/join/<label>#<frag>
23// — mirroring web/static/invite.js parseInviteFragment: the fragment is
24// "e1.<T>" or "e1.<T>~<urlencoded name>" (bare T on older links).
25func ParseInviteLink(link string) (InviteLink, error) {
26 u, err := url.Parse(strings.TrimSpace(link))
27 if err != nil || u.Scheme == "" || u.Host == "" {
28 return InviteLink{}, fmt.Errorf("client: that doesn't look like an invite link (expected https://…/join/…#…)")
29 }
30 frag := u.Fragment
31 if frag == "" {
32 return InviteLink{}, fmt.Errorf("client: the link is missing its #secret — copy the whole invite link")
33 }
34 frag = strings.TrimPrefix(frag, invitePrefix)
35 t, name := frag, ""
36 if i := strings.Index(frag, "~"); i >= 0 {
37 t = frag[:i]
38 if n, err := url.QueryUnescape(frag[i+1:]); err == nil {
39 name = n
40 }
41 }
42 if t == "" {
43 return InviteLink{}, fmt.Errorf("client: the link is missing its #secret — copy the whole invite link")
44 }
45 return InviteLink{Base: u.Scheme + "://" + u.Host, T: t, Name: name}, nil
46}
47