luci-app-adblock-fast: initial commit
[project/luci.git] / applications / luci-app-adblock-fast / htdocs / luci-static / resources / view / adblock-fast / overview.js
1 // Copyright 2023 MOSSDeF, Stan Grishin <stangri@melmac.ca>
2 // This code wouldn't have been possible without help from:
3 // - [@stokito](https://github.com/stokito)
4 // - [@vsviridov](https://github.com/vsviridov)
5
6 "use strict";
7 "require form";
8 "require uci";
9 "require view";
10 "require adblock-fast.status as adb";
11
12 var pkg = {
13 get Name() {
14 return "adblock-fast";
15 },
16 get URL() {
17 return "https://docs.openwrt.melmac.net/" + pkg.Name + "/";
18 },
19 humanFileSize: function (bytes, si = false, dp = 2) {
20 return `%${si ? 1000 : 1024}.${dp ?? 0}mB`.format(bytes);
21 },
22 };
23
24 return view.extend({
25 load: function () {
26 return Promise.all([
27 L.resolveDefault(adb.getFileUrlFilesizes(pkg.Name), {}),
28 L.resolveDefault(adb.getPlatformSupport(pkg.Name), {}),
29 uci.load(pkg.Name),
30 uci.load("dhcp"),
31 ]);
32 },
33
34 render: function (data) {
35 var reply = {
36 sizes: (data[0] && data[0][pkg.Name] && data[0][pkg.Name]["sizes"]) || [],
37 platform: (data[1] && data[1][pkg.Name]) || {
38 ipset_installed: false,
39 nft_installed: false,
40 dnsmasq_installed: false,
41 unbound_installed: false,
42 dnsmasq_ipset_support: false,
43 dnsmasq_nftset_support: false,
44 leds: [],
45 },
46 };
47 var status, m, s1, s2, s3, o;
48
49 status = new adb.status();
50 m = new form.Map(pkg.Name, _("AdBlock-Fast - Configuration"));
51 s1 = m.section(form.NamedSection, "config", pkg.Name);
52 s1.tab("tab_basic", _("Basic Configuration"));
53 s1.tab("tab_advanced", _("Advanced Configuration"));
54
55 var text = _(
56 "DNS resolution option, see the %sREADME%s for details."
57 ).format(
58 '<a href="' + pkg.URL + '#dns-resolver-option" target="_blank">',
59 "</a>"
60 );
61 if (!reply.platform.dnsmasq_installed) {
62 text +=
63 "<br />" +
64 _("Please note that %s is not supported on this system.").format(
65 "<i>dnsmasq.addnhosts</i>"
66 );
67 text +=
68 "<br />" +
69 _("Please note that %s is not supported on this system.").format(
70 "<i>dnsmasq.conf</i>"
71 );
72 text +=
73 "<br />" +
74 _("Please note that %s is not supported on this system.").format(
75 "<i>dnsmasq.ipset</i>"
76 );
77 text +=
78 "<br />" +
79 _("Please note that %s is not supported on this system.").format(
80 "<i>dnsmasq.servers</i>"
81 );
82 } else {
83 if (!reply.platform.dnsmasq_ipset_support) {
84 text +=
85 "<br />" +
86 _("Please note that %s is not supported on this system.").format(
87 "<i>dnsmasq.ipset</i>"
88 );
89 }
90 if (!reply.platform.dnsmasq_nftset_support) {
91 text +=
92 "<br />" +
93 _("Please note that %s is not supported on this system.").format(
94 "<i>dnsmasq.nftset</i>"
95 );
96 }
97 }
98 if (!reply.platform.unbound_installed) {
99 text =
100 text +
101 "<br />" +
102 _("Please note that %s is not supported on this system.").format(
103 "<i>unbound.adb_list</i>"
104 );
105 }
106
107 o = s1.taboption(
108 "tab_basic",
109 form.ListValue,
110 "dns",
111 _("DNS Service"),
112 text
113 );
114 if (reply.platform.dnsmasq_installed) {
115 o.value("dnsmasq.addnhosts", _("dnsmasq additional hosts"));
116 o.value("dnsmasq.conf", _("dnsmasq config"));
117 if (reply.platform.dnsmasq_ipset_support) {
118 o.value("dnsmasq.ipset", _("dnsmasq ipset"));
119 }
120 if (reply.platform.dnsmasq_nftset_support) {
121 o.value("dnsmasq.nftset", _("dnsmasq nft set"));
122 }
123 o.value("dnsmasq.servers", _("dnsmasq servers file"));
124 }
125 if (reply.platform.unbound_installed) {
126 o.value("unbound.adb_list", _("unbound adblock list"));
127 }
128 o.default = ("dnsmasq.servers", _("dnsmasq servers file"));
129
130 o = s1.taboption(
131 "tab_basic",
132 form.Value,
133 "dnsmasq_config_file_url",
134 _("Dnsmasq Config File URL"),
135 _(
136 "URL to the external dnsmasq config file, see the %sREADME%s for details."
137 ).format(
138 '<a href="' + pkg.URL + '#dnsmasq_config_file_url" target="_blank">',
139 "</a>"
140 )
141 );
142 o.depends("dns", "dnsmasq.conf");
143
144 o = s1.taboption(
145 "tab_basic",
146 form.ListValue,
147 "dnsmasq_instance",
148 _("Use AdBlocking on the dnsmasq instance(s)"),
149 _(
150 "You can limit the AdBlocking to a specific dnsmasq instance(s) (%smore information%s)."
151 ).format(
152 '<a href="' + pkg.URL + "#dnsmasq_instance" + '" target="_blank">',
153 "</a>"
154 )
155 );
156 o.value("*", _("AdBlock on all instances"));
157 var sections = uci.sections("dhcp", "dnsmasq");
158 sections.forEach((element) => {
159 var description;
160 var key;
161 if (element[".name"] === uci.resolveSID("dhcp", element[".name"])) {
162 key = element[".index"];
163 description = "dnsmasq[" + element[".index"] + "]";
164 } else {
165 key = element[".name"];
166 description = element[".name"];
167 }
168 o.value(key, _("AdBlock on %s only").format(description));
169 });
170 o.value("-", _("No AdBlock on dnsmasq"));
171 o.default = "*";
172 o.depends("dns", "dnsmasq.addnhosts");
173 o.depends("dns", "dnsmasq.servers");
174 o.retain = true;
175
176 o = s1.taboption(
177 "tab_basic",
178 form.ListValue,
179 "force_dns",
180 _("Force Router DNS"),
181 _("Forces Router DNS use on local devices, also known as DNS Hijacking.")
182 );
183 o.value("0", _("Let local devices use their own DNS servers if set"));
184 o.value("1", _("Force Router DNS server to all local devices"));
185 o.default = ("1", _("Force Router DNS server to all local devices"));
186
187 o = s1.taboption(
188 "tab_basic",
189 form.ListValue,
190 "verbosity",
191 _("Output Verbosity Setting"),
192 _("Controls system log and console output verbosity.")
193 );
194 o.value("0", _("Suppress output"));
195 o.value("1", _("Some output"));
196 o.value("2", _("Verbose output"));
197 o.default = ("2", _("Verbose output"));
198
199 if (reply.platform.leds.length) {
200 o = s1.taboption(
201 "tab_basic",
202 form.ListValue,
203 "led",
204 _("LED to indicate status"),
205 _(
206 "Pick the LED not already used in %sSystem LED Configuration%s."
207 ).format('<a href="' + L.url("admin", "system", "leds") + '">', "</a>")
208 );
209 o.value("", _("none"));
210 reply.platform.leds.forEach((element) => {
211 o.value(element);
212 });
213 }
214 o = s1.taboption(
215 "tab_advanced",
216 form.ListValue,
217 "config_update_enabled",
218 _("Automatic Config Update"),
219 _("Perform config update before downloading the block/allow-lists.")
220 );
221 o.value("0", _("Disable"));
222 o.value("1", _("Enable"));
223 o.default = ("0", _("Disable"));
224
225 o = s1.taboption(
226 "tab_advanced",
227 form.ListValue,
228 "ipv6_enabled",
229 _("IPv6 Support"),
230 _("Add IPv6 entries to block-list.")
231 );
232 o.value("", _("Do not add IPv6 entries"));
233 o.value("1", _("Add IPv6 entries"));
234 o.depends("dns", "dnsmasq.addnhosts");
235 o.depends("dns", "dnsmasq.nftset");
236 o.default = ("", _("Do not add IPv6 entries"));
237 o.rmempty = true;
238 o.retain = true;
239
240 o = s1.taboption(
241 "tab_advanced",
242 form.Value,
243 "download_timeout",
244 _("Download time-out (in seconds)"),
245 _("Stop the download if it is stalled for set number of seconds.")
246 );
247 o.default = "20";
248 o.datatype = "range(1,60)";
249
250 o = s1.taboption(
251 "tab_advanced",
252 form.Value,
253 "curl_max_file_size",
254 _("Curl maximum file size (in bytes)"),
255 _(
256 "If curl is installed and detected, it would not download files bigger than this."
257 )
258 );
259 o.default = "";
260 o.datatype = "uinteger";
261 o.rmempty = true;
262
263 o = s1.taboption(
264 "tab_advanced",
265 form.Value,
266 "curl_retry",
267 _("Curl download retry"),
268 _(
269 "If curl is installed and detected, it would retry download this many times on timeout/fail."
270 )
271 );
272 o.default = "3";
273 o.datatype = "range(0,30)";
274
275 o = s1.taboption(
276 "tab_advanced",
277 form.ListValue,
278 "parallel_downloads",
279 _("Simultaneous processing"),
280 _(
281 "Launch all lists downloads and processing simultaneously, reducing service start time."
282 )
283 );
284 o.value("0", _("Do not use simultaneous processing"));
285 o.value("1", _("Use simultaneous processing"));
286 o.default = ("1", _("Use simultaneous processing"));
287
288 o = s1.taboption(
289 "tab_advanced",
290 form.ListValue,
291 "compressed_cache",
292 _("Store compressed cache file on router"),
293 _(
294 "Attempt to create a compressed cache of block-list in the persistent memory."
295 )
296 );
297 o.value("0", _("Do not store compressed cache"));
298 o.value("1", _("Store compressed cache"));
299 o.default = ("0", _("Do not store compressed cache"));
300
301 o = s1.taboption(
302 "tab_advanced",
303 form.Value,
304 "compressed_cache_dir",
305 _("Directory for compressed cache file"),
306 _(
307 "Directory for compressed cache file of block-list in the persistent memory."
308 )
309 );
310 o.datatype = "string";
311 o.rmempty = true;
312 o.default = "/etc";
313 o.depends("compressed_cache", "1");
314 o.retain = true;
315
316 o = s1.taboption(
317 "tab_advanced",
318 form.ListValue,
319 "debug",
320 _("Enable Debugging"),
321 _("Enables debug output to /tmp/adblock-fast.log.")
322 );
323 o.value("0", _("Disable Debugging"));
324 o.value("1", _("Enable Debugging"));
325 o.default = ("0", _("Disable Debugging"));
326
327 s2 = m.section(
328 form.NamedSection,
329 "config",
330 "adblock-fast",
331 _("AdBlock-Fast - Allowed and Blocked Domains")
332 );
333 o.addremove = true;
334 o.rmempty = true;
335 o = s2.option(
336 form.DynamicList,
337 "allowed_domain",
338 _("Allowed Domains"),
339 _("Individual domains to be allowed.")
340 );
341
342 o.addremove = true;
343 o = s2.option(
344 form.DynamicList,
345 "blocked_domain",
346 _("Blocked Domains"),
347 _("Individual domains to be blocked.")
348 );
349 o.addremove = true;
350
351 s3 = m.section(
352 form.GridSection,
353 "file_url",
354 _("AdBlock-Fast - Allowed and Blocked Lists URLs"),
355 _("URLs to file(s) containing lists to be allowed or blocked.")
356 );
357 s3.rowcolors = true;
358 s3.sortable = true;
359 s3.anonymous = true;
360 s3.addremove = true;
361 o = s3.option(form.DummyValue, "_size", "Size");
362 o.modalonly = false;
363 o.cfgvalue = function (section_id) {
364 let url = uci.get(pkg.Name, section_id, "url");
365 let ret = _("Unknown");
366 reply.sizes.forEach((element) => {
367 if (element.url === url) {
368 ret = element.size === 0 ? ret : pkg.humanFileSize(element.size);
369 }
370 });
371 return _("Size: %s").format(ret);
372 };
373 o = s3.option(form.Flag, "enabled", _("Enable"));
374 o.editable = true;
375 o.default = "1";
376 o = s3.option(form.ListValue, "action", _("Action"));
377 o.value("allow", _("Allow"));
378 o.value("block", _("Block"));
379 o.default = "block";
380 o = s3.option(form.Value, "url", _("URL"));
381 o.optional = false;
382
383 return Promise.all([status.render(), m.render()]);
384 },
385 });