-
-
Notifications
You must be signed in to change notification settings - Fork 36
/
types.go
395 lines (336 loc) · 9.63 KB
/
types.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
package types
import (
"encoding/json"
"fmt"
"sort"
"strings"
"github.com/bakito/adguardhome-sync/pkg/versions"
)
const (
// DefaultAPIPath default api path
DefaultAPIPath = "/control"
)
// Config application configuration struct
type Config struct {
Origin AdGuardInstance `json:"origin" yaml:"origin"`
Replica AdGuardInstance `json:"replica,omitempty" yaml:"replica,omitempty"`
Replicas []AdGuardInstance `json:"replicas,omitempty" yaml:"replicas,omitempty"`
Cron string `json:"cron,omitempty" yaml:"cron,omitempty"`
RunOnStart bool `json:"runOnStart,omitempty" yaml:"runOnStart,omitempty"`
API API `json:"api,omitempty" yaml:"api,omitempty"`
Features Features `json:"features,omitempty" yaml:"features,omitempty"`
}
// API configuration
type API struct {
Port int `json:"port,omitempty" yaml:"port,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
Password string `json:"password,omitempty" yaml:"password,omitempty"`
DarkMode bool `json:"darkMode,omitempty" yaml:"darkMode,omitempty"`
}
// UniqueReplicas get unique replication instances
func (cfg *Config) UniqueReplicas() []AdGuardInstance {
dedup := make(map[string]AdGuardInstance)
if cfg.Replica.URL != "" {
dedup[cfg.Replica.Key()] = cfg.Replica
}
for _, replica := range cfg.Replicas {
if replica.URL != "" {
dedup[replica.Key()] = replica
}
}
var r []AdGuardInstance
for _, replica := range dedup {
if replica.APIPath == "" {
replica.APIPath = DefaultAPIPath
}
r = append(r, replica)
}
return r
}
// AdGuardInstance AdguardHome config instance
type AdGuardInstance struct {
URL string `json:"url" yaml:"url"`
APIPath string `json:"apiPath,omitempty" yaml:"apiPath,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
Password string `json:"password,omitempty" yaml:"password,omitempty"`
InsecureSkipVerify bool `json:"insecureSkipVerify" yaml:"insecureSkipVerify"`
AutoSetup bool `json:"autoSetup" yaml:"autoSetup"`
InterfaceName string `json:"interfaceName" yaml:"interfaceName"`
}
// Key AdGuardInstance key
func (i *AdGuardInstance) Key() string {
return fmt.Sprintf("%s#%s", i.URL, i.APIPath)
}
// Protection API struct
type Protection struct {
ProtectionEnabled bool `json:"protection_enabled"`
}
// Status API struct
type Status struct {
Protection
DNSAddresses []string `json:"dns_addresses"`
DNSPort int `json:"dns_port"`
HTTPPort int `json:"http_port"`
DhcpAvailable bool `json:"dhcp_available"`
Running bool `json:"running"`
Version string `json:"version"`
Language string `json:"language"`
}
// RewriteEntries list of RewriteEntry
type RewriteEntries []RewriteEntry
// Merge RewriteEntries
func (rwe *RewriteEntries) Merge(other *RewriteEntries) (RewriteEntries, RewriteEntries, RewriteEntries) {
current := make(map[string]RewriteEntry)
var adds RewriteEntries
var removes RewriteEntries
var duplicates RewriteEntries
processed := make(map[string]bool)
for _, rr := range *rwe {
if _, ok := processed[rr.Key()]; !ok {
current[rr.Key()] = rr
processed[rr.Key()] = true
} else {
// remove duplicate
removes = append(removes, rr)
}
}
for _, rr := range *other {
if _, ok := current[rr.Key()]; ok {
delete(current, rr.Key())
} else {
if _, ok := processed[rr.Key()]; !ok {
adds = append(adds, rr)
processed[rr.Key()] = true
} else {
// skip duplicate
duplicates = append(duplicates, rr)
}
}
}
for _, rr := range current {
removes = append(removes, rr)
}
return adds, removes, duplicates
}
// RewriteEntry API struct
type RewriteEntry struct {
Domain string `json:"domain"`
Answer string `json:"answer"`
}
// Key RewriteEntry key
func (re *RewriteEntry) Key() string {
return fmt.Sprintf("%s#%s", re.Domain, re.Answer)
}
// Filters list of Filter
type Filters []Filter
// Merge merge Filters
func (f Filters) Merge(other Filters) (Filters, Filters, Filters) {
current := make(map[string]Filter)
var adds Filters
var updates Filters
var removes Filters
for _, f := range f {
current[f.URL] = f
}
for i := range other {
rr := other[i]
if c, ok := current[rr.URL]; ok {
if !c.Equals(&rr) {
updates = append(updates, rr)
}
delete(current, rr.URL)
} else {
adds = append(adds, rr)
}
}
for _, rr := range current {
removes = append(removes, rr)
}
return adds, updates, removes
}
// Filter API struct
type Filter struct {
ID int `json:"id"`
Enabled bool `json:"enabled"`
URL string `json:"url"` // needed for add
Name string `json:"name"` // needed for add
RulesCount int `json:"rules_count"`
Whitelist bool `json:"whitelist"` // needed for add
}
// Equals Filter equal check
func (f *Filter) Equals(o *Filter) bool {
return f.Enabled == o.Enabled && f.URL == o.URL && f.Name == o.Name
}
// FilterUpdate API struct
type FilterUpdate struct {
URL string `json:"url"`
Data Filter `json:"data"`
Whitelist bool `json:"whitelist"`
}
// FilteringStatus API struct
type FilteringStatus struct {
FilteringConfig
Filters Filters `json:"filters"`
WhitelistFilters Filters `json:"whitelist_filters"`
UserRules UserRules `json:"user_rules"`
}
// UserRules API struct
type UserRules []string
// String toString of Users
func (ur UserRules) String() string {
return strings.Join(ur, "\n")
}
// ToPayload return the version specific payload for user rules
func (ur UserRules) ToPayload(version string) interface{} {
if versions.IsNewerThan(version, versions.LastStringCustomRules) {
return &UserRulesRequest{Rules: ur}
}
return ur.String()
}
// UserRulesRequest API struct
type UserRulesRequest struct {
Rules UserRules
}
// String toString of Users
func (ur UserRulesRequest) String() string {
return ur.Rules.String()
}
// EnableConfig API struct
type EnableConfig struct {
Enabled bool `json:"enabled"`
}
// IntervalConfig API struct
type IntervalConfig struct {
Interval float64 `json:"interval"`
}
// FilteringConfig API struct
type FilteringConfig struct {
EnableConfig
IntervalConfig
}
// QueryLogConfig API struct
type QueryLogConfig struct {
EnableConfig
IntervalConfig
AnonymizeClientIP bool `json:"anonymize_client_ip"`
}
// Equals QueryLogConfig equal check
func (qlc *QueryLogConfig) Equals(o *QueryLogConfig) bool {
return qlc.Enabled == o.Enabled && qlc.AnonymizeClientIP == o.AnonymizeClientIP && qlc.Interval == o.Interval
}
// RefreshFilter API struct
type RefreshFilter struct {
Whitelist bool `json:"whitelist"`
}
// Services API struct
type Services []string
// Sort sort Services
func (s Services) Sort() {
sort.Strings(s)
}
// Equals Services equal check
func (s Services) Equals(o Services) bool {
s.Sort()
o.Sort()
return equals(s, o)
}
// Clients API struct
type Clients struct {
Clients []Client `json:"clients"`
AutoClients []struct {
IP string `json:"ip"`
Name string `json:"name"`
Source string `json:"source"`
WhoisInfo struct{} `json:"whois_info"`
} `json:"auto_clients"`
SupportedTags []string `json:"supported_tags"`
}
// Client API struct
type Client struct {
Ids []string `json:"ids,omitempty"`
Tags []string `json:"tags,omitempty"`
BlockedServices []string `json:"blocked_services,omitempty"`
Upstreams []string `json:"upstreams,omitempty"`
UseGlobalSettings bool `json:"use_global_settings"`
UseGlobalBlockedServices bool `json:"use_global_blocked_services"`
Name string `json:"name"`
FilteringEnabled bool `json:"filtering_enabled"`
ParentalEnabled bool `json:"parental_enabled"`
SafesearchEnabled bool `json:"safesearch_enabled"`
SafebrowsingEnabled bool `json:"safebrowsing_enabled"`
Disallowed bool `json:"disallowed"`
DisallowedRule string `json:"disallowed_rule"`
}
// Sort sort clients
func (cl *Client) Sort() {
sort.Strings(cl.Ids)
sort.Strings(cl.Tags)
sort.Strings(cl.BlockedServices)
sort.Strings(cl.Upstreams)
}
// Equals Clients equal check
func (cl *Client) Equals(o *Client) bool {
cl.Sort()
o.Sort()
a, _ := json.Marshal(cl)
b, _ := json.Marshal(o)
return string(a) == string(b)
}
// Merge merge Clients
func (clients *Clients) Merge(other *Clients) ([]Client, []Client, []Client) {
current := make(map[string]Client)
for _, client := range clients.Clients {
current[client.Name] = client
}
expected := make(map[string]Client)
for _, client := range other.Clients {
expected[client.Name] = client
}
var adds []Client
var removes []Client
var updates []Client
for _, cl := range expected {
if oc, ok := current[cl.Name]; ok {
if !cl.Equals(&oc) {
updates = append(updates, cl)
}
delete(current, cl.Name)
} else {
adds = append(adds, cl)
}
}
for _, rr := range current {
removes = append(removes, rr)
}
return adds, updates, removes
}
// ClientUpdate API struct
type ClientUpdate struct {
Name string `json:"name"`
Data Client `json:"data"`
}
func equals(a []string, b []string) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
// InstallConfig AdguardHome install config
type InstallConfig struct {
Web InstallPort `json:"web"`
DNS InstallPort `json:"dns"`
Username string `json:"username"`
Password string `json:"password"`
}
// InstallPort AdguardHome install config port
type InstallPort struct {
IP string `json:"ip"`
Port int `json:"port"`
Status string `json:"status"`
CanAutofix bool `json:"can_autofix"`
}