-
Notifications
You must be signed in to change notification settings - Fork 17
/
handle.go
102 lines (90 loc) · 2.48 KB
/
handle.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package lnurl
import (
"errors"
"io"
"net/url"
"strings"
"github.com/tidwall/gjson"
)
// HandleLNURL takes a bech32-encoded lnurl and either gets its parameters from the query-
// string or calls the URL to get the parameters.
// Returns a different struct for each of the lnurl subprotocols, the .LNURLKind() method of
// which should be checked next to see how the wallet is going to proceed.
func HandleLNURL(rawlnurl string) (string, LNURLParams, error) {
var err error
var rawurl string
if name, domain, ok := ParseInternetIdentifier(rawlnurl); ok {
isOnion := strings.Index(domain, ".onion") == len(domain)-6
rawurl = domain + "/.well-known/lnurlp/" + name
if isOnion {
rawurl = "http://" + rawurl
} else {
rawurl = "https://" + rawurl
}
} else if strings.HasPrefix(rawlnurl, "http") {
rawurl = rawlnurl
} else if strings.HasPrefix(rawlnurl, "lnurlp://") ||
strings.HasPrefix(rawlnurl, "lnurlw://") ||
strings.HasPrefix(rawlnurl, "lnurla://") ||
strings.HasPrefix(rawlnurl, "keyauth://") {
scheme := "https:"
if strings.Contains(rawlnurl, ".onion/") || strings.HasSuffix(rawlnurl, ".onion") {
scheme = "http:"
}
location := strings.SplitN(rawlnurl, ":", 2)[1]
rawurl = scheme + location
} else {
lnurl, ok := FindLNURLInText(rawlnurl)
if !ok {
return "", nil,
errors.New("invalid bech32-encoded lnurl: " + rawlnurl)
}
rawurl, err = LNURLDecode(lnurl)
if err != nil {
return "", nil, err
}
}
parsed, err := url.Parse(rawurl)
if err != nil {
return rawurl, nil, err
}
query := parsed.Query()
switch query.Get("tag") {
case "login":
value, err := HandleAuth(rawurl, parsed, query)
return rawurl, value, err
case "withdrawRequest":
if value, ok := HandleFastWithdraw(query); ok {
return rawurl, value, nil
}
}
resp, err := actualClient.Get(rawurl)
if err != nil {
return rawurl, nil, err
}
b, err := io.ReadAll(resp.Body)
if err != nil {
return rawurl, nil, err
}
j := gjson.ParseBytes(b)
if j.Get("status").String() == "ERROR" {
return rawurl, nil, LNURLErrorResponse{
URL: parsed,
Reason: j.Get("reason").String(),
Status: "ERROR",
}
}
switch j.Get("tag").String() {
case "withdrawRequest":
value, err := HandleWithdraw(b)
return rawurl, value, err
case "payRequest":
value, err := HandlePay(b)
return rawurl, value, err
case "channelRequest":
value, err := HandleChannel(b)
return rawurl, value, err
default:
return rawurl, nil, errors.New("unknown response tag " + j.String())
}
}