-
Notifications
You must be signed in to change notification settings - Fork 13
/
subscribe.go
98 lines (87 loc) · 2.23 KB
/
subscribe.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
package main
import (
"context"
"encoding/base64"
"io/ioutil"
"net/http"
"strings"
"sync/atomic"
"time"
)
var nekoXSubscriptionDomain = "nekogramx-public-proxy-v1.seyana.moe"
var nekoXSubscriptionDohs = []string{
"https://1.1.1.1/dns-query",
"https://1.0.0.1/dns-query",
"https://101.101.101.101/dns-query",
"https://8.8.8.8/resolve",
"https://8.8.4.4/resolve",
"https://[2606:4700:4700::1111]/dns-query",
}
var _subscribeGood int32 = 0
var _subscribeBad int32 = 0
func getNekoXString() string {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
in := make(chan string, len(nekoXSubscriptionDohs))
out := make(chan string, 0)
for i := 0; i < 10; i++ {
go getNekoXStringWorker(ctx, in, out, cancel)
}
go func() {
for _, doh := range nekoXSubscriptionDohs {
in <- doh
}
}()
return <-out
}
func getNekoXStringWorker(ctx context.Context, in, out chan string, cancel context.CancelFunc) {
for {
select {
case <-ctx.Done():
return
case doh := <-in:
ret := getTXTUsingDoH(ctx, doh)
if _, err := base64.RawURLEncoding.DecodeString(ret); err != nil || ret == "" {
// fmt.Println(err, ret, doh)
if atomic.AddInt32(&_subscribeBad, 1) == int32(len(nekoXSubscriptionDohs)) {
cancel()
out <- ""
return
}
continue
}
if atomic.AddInt32(&_subscribeGood, 1) == 1 {
cancel()
out <- ret
}
}
}
}
func getTXTUsingDoH(ctx context.Context, doh string) string {
dohURL := doh + "?name=" + nekoXSubscriptionDomain + "&type=TXT"
req, _ := http.NewRequestWithContext(ctx, "GET", dohURL, nil)
req.Header.Set("accept", "application/dns-json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return ""
}
data, _ := ioutil.ReadAll(resp.Body)
data2 := strings.ReplaceAll(string(data), "\\\"", "")
data2 = strings.ReplaceAll(data2, " ", "")
return between(data2, "#NekoXStart#", "#NekoXEnd#")
}
func between(value string, a string, b string) string {
// Get substring between two strings.
posFirst := strings.Index(value, a)
if posFirst == -1 {
return ""
}
posLast := strings.Index(value, b)
if posLast == -1 {
return ""
}
posFirstAdjusted := posFirst + len(a)
if posFirstAdjusted >= posLast {
return ""
}
return value[posFirstAdjusted:posLast]
}