-
-
Save malesfth/d5fb2eb36aab4e726727c14ba32f9f8b to your computer and use it in GitHub Desktop.
// Parameters: | |
// {"url":"https://pihole","token": "x"} | |
// Optional key in parameters: "theme": system|light|dark | |
let piholeURL = "" // set the URL here for debug | |
let apiToken = "" // set the api token here for debug | |
let wTheme = "" // set the theme for debug | |
if (config.runsInWidget) { | |
const widgetParams = (args.widgetParameter != null ? JSON.parse(args.widgetParameter) : null) | |
if (widgetParams==null) { | |
throw new Error("Please long press the widget and add the parameters.") | |
} else if (!widgetParams.hasOwnProperty("url") || !widgetParams.hasOwnProperty("token")) { | |
throw new Error("Wrong parameters.") | |
} | |
piholeURL = widgetParams.url | |
apiToken = widgetParams.token | |
if (widgetParams.hasOwnProperty("theme")) { | |
wTheme = widgetParams.theme | |
} | |
} | |
let wBackground = new LinearGradient() | |
let wColor = new Color("#ffffff") | |
setTheme() | |
let piholeStats = await getStats() | |
let wSize = config.widgetFamily || "large" //set size of widget for debug | |
let widget = await createWidget() || null | |
if (!config.runsInWidget) { | |
if (wSize=="large") { await widget.presentLarge() } | |
else if (wSize=="medium") { await widget.presentMedium() } | |
else { await widget.presentSmall() } | |
} | |
Script.setWidget(widget) | |
Script.complete() | |
async function createWidget() { | |
let w = new ListWidget() | |
w.backgroundGradient = wBackground | |
w.addSpacer() | |
w.setPadding(5, 15, 0, (wSize=="small" ? 0 : 10)) | |
let state = (piholeStats!=null ? (piholeStats.status=="enabled" ? true : false) : null) | |
let icn = null | |
if (state==true) { | |
icn = SFSymbol.named((state ? "checkmark.shield.fill" : "xmark.shield.fill")) | |
} else { | |
icn = SFSymbol.named("xmark.circle.fill") | |
state = false | |
} | |
let topStack = w.addStack() | |
topStack.layoutHorizontally() | |
topStack.setPadding(5, 0, 0, 10) | |
let content = topStack.addImage(icn.image) | |
content.tintColor = (state ? Color.green() : Color.red()) | |
content.imageSize = new Size(16,16) | |
topStack.addSpacer(5) | |
content = topStack.addText("Pi-hole") | |
content.font = Font.blackSystemFont(16) | |
content.textColor = wColor | |
if (state==true && wSize != "small") { | |
topStack.addSpacer() | |
topStack.addText(" ") // same line with distance to title | |
addUpdateItem(topStack, (piholeStats.core_current==piholeStats.core_latest ? true : false), "Pi" + ((wSize=="small") ? "" : "-hole")) | |
topStack.addText(" ") | |
addUpdateItem(topStack, (piholeStats.web_current==piholeStats.web_latest ? true : false), "WebUI") | |
topStack.addText(" ") | |
addUpdateItem(topStack, (piholeStats.FTL_current==piholeStats.FTL_latest ? true : false), "FTL") | |
} | |
w.addSpacer(8) | |
if (piholeStats==null) { | |
content = w.addText("No connection") | |
content.font = Font.thinSystemFont(14) | |
content.textColor = wColor | |
w.addSpacer() | |
return w | |
} | |
w.url = piholeURL + "/admin/" | |
addItem(w, "Total Queries", piholeStats.dns_queries_all_types) | |
layoutStack = w.addStack() | |
layoutStack.setPadding(5, 0, 0, 10) | |
layoutStack.centerAlignContent() | |
addItem(w, "Queries Blocked", piholeStats.ads_blocked_today) | |
layoutStack = w.addStack() | |
layoutStack.setPadding(5, 0, 0, 10) | |
layoutStack.centerAlignContent() | |
addItem(w, "Percent Blocked", Number.parseFloat(piholeStats.ads_percentage_today).toFixed(1).replace(".", ",") + "%") | |
layoutStack = w.addStack() | |
layoutStack.setPadding(5, 0, 0, 10) | |
layoutStack.centerAlignContent() | |
addItem(w, "Domains on Blocklist", piholeStats.domains_being_blocked) | |
if (wSize=="large") { | |
addItem(w, "Unique Domains", piholeStats.unique_domains) | |
layoutStack = w.addStack() | |
layoutStack.setPadding(5, 0, 0, 10) | |
addItem(w, "Cached Queries", piholeStats.queries_cached) | |
layoutStack = w.addStack() | |
layoutStack.setPadding(5, 0, 0, 10) | |
addItem(w, "Queries Forwarded", piholeStats.queries_forwarded) | |
layoutStack = w.addStack() | |
layoutStack.setPadding(5, 0, 0, 10) | |
addItem(w, "Clients Seen / Unique", piholeStats.clients_ever_seen + " / " + piholeStats.unique_clients) | |
} | |
w.addSpacer() | |
return w | |
} | |
function addItem(w, strHeadline, strData) { | |
let fontSizeHeadline = 12 | |
let fontSizeString = 9 | |
switch (wSize) { | |
case "large": | |
fontSizeHeadline = 18 | |
fontSizeString = 14 | |
break; | |
case "medium": | |
fontSizeHeadline = 14 | |
fontSizeString = 11 | |
break; | |
} | |
let layoutStack = w.addStack() | |
layoutStack.setPadding(3, 0, 0, 10) | |
layoutStack.centerAlignContent() | |
content = layoutStack.addText(strHeadline) | |
content.font = Font.mediumSystemFont(fontSizeHeadline) | |
content.textColor = wColor | |
layoutStack.addSpacer() | |
content = layoutStack.addText(strData.toString()) | |
content.font = Font.mediumSystemFont(fontSizeString) | |
content.textColor = wColor | |
} | |
function addUpdateItem(stack, status, text) { | |
let icn = SFSymbol.named((status ? "checkmark.circle.fill" : "exclamationmark.triangle.fill")) | |
let content = stack.addImage(icn.image) | |
content.tintColor = (status ? Color.green() : Color.red()) | |
content.imageSize = new Size(14,14) | |
content = stack.addText(((wSize!="small") ? " " : "" ) + text) | |
content.font = Font.semiboldMonospacedSystemFont(12) | |
content.textColor = wColor | |
} | |
function setTheme() { | |
if (wTheme=="system") { | |
if (Device.isUsingDarkAppearance()) { | |
wTheme = "dark" | |
} else { | |
wTheme = "light" | |
} | |
} | |
wBackground.locations = [0, 1] | |
if (wTheme=="dark") { | |
wBackground.colors = [ | |
new Color("#384d54"), | |
new Color("#384d54") | |
] | |
wColor = new Color("#ffffff") | |
} else { | |
wBackground.colors = [ | |
new Color("#ffffffe6"), //ffffffe6 | |
new Color("#ffffffe6") | |
] | |
wColor = new Color("#000000") | |
} | |
} | |
async function getStats() { | |
try { | |
let req = new Request(piholeURL + "/admin/api.php?versions&summary&auth="+apiToken) | |
let json = await req.loadJSON() | |
if (json.length === 0) { return null } | |
return json | |
} catch(err) { | |
console.error(err) | |
return null | |
} | |
} |
I've changed the following line in function addItem:
content = layoutStack.addText(strData)
to
content = layoutStack.addText(strData.toLocaleString('de'))
Thanks @JoeGit42
… now is running!
… with a little cosmetic error: percent blocked % shows several digits after the decimal point.
Please display again to one digit after the decimal point.
I've also observed this issue.
I changed line
addItem(w, "Percent Blocked", piholeStats.ads_percentage_today + "%")
to
addItem(w, "Percent Blocked", piholeStats.ads_percentage_today.toFixed(1).replace(".", ",") + "%")
This is the current version I use:
// Parameters:
// {"url":"https://pihole","apikey":"123abc"}
// Optional key in parameters: "theme": system|light|dark
let piholeURL = "" //set the URL here for debug http://
let piholeAPIkey = "" // set the API-key here for debug
let wTheme = "" // set the theme for debug
if (config.runsInWidget) {
const widgetParams = (args.widgetParameter != null ? JSON.parse(args.widgetParameter) : null)
if (widgetParams==null) {
throw new Error("Please long press the widget and add the parameters.")
} else if (!widgetParams.hasOwnProperty("url") && !widgetParams.hasOwnProperty("apikey")) {
throw new Error("Wrong parameters.")
}
piholeURL = widgetParams.url
piholeAPIkey = widgetParams.apikey
if (widgetParams.hasOwnProperty("theme")) {
wTheme = widgetParams.theme
}
}
let wBackground = new LinearGradient()
let wColor = new Color("#ffffff")
setTheme()
let piholeStats = await getStats()
let adminPage = await getAdminPage()
let isLatestVer = getUpdateStats(adminPage)
let wSize = config.widgetFamily || "large" //set size of widget for debug
let widget = await createWidget() || null
if (!config.runsInWidget) {
if (wSize=="large") { await widget.presentLarge() }
else if (wSize=="medium") { await widget.presentMedium() }
else { await widget.presentSmall() }
}
Script.setWidget(widget)
Script.complete()
async function createWidget() {
let w = new ListWidget()
w.backgroundGradient = wBackground
w.addSpacer()
w.setPadding(5, 15, 0, (wSize=="small" ? 0 : 10))
let state = (piholeStats!=null ? (piholeStats.status=="enabled" ? true : false) : null)
let icn = null
if (state==true) {
icn = SFSymbol.named((state ? "checkmark.shield.fill" : "xmark.shield.fill"))
} else {
icn = SFSymbol.named("xmark.circle.fill")
state = false
}
let topStack = w.addStack()
topStack.layoutHorizontally()
topStack.setPadding(5, 0, 0, 10)
let content = topStack.addImage(icn.image)
content.tintColor = (state ? Color.green() : Color.red())
content.imageSize = new Size(16,16)
topStack.addSpacer(5)
content = topStack.addText("Pi-hole")
content.font = Font.blackSystemFont(16)
content.textColor = wColor
// added version status
if (wSize=="small") {
topStack = w.addStack() // new line
topStack.layoutHorizontally()
} else { // medium or large
topStack.addSpacer()
topStack.addText(" ") // same line with distance to title
}
addUpdateItem(topStack, isLatestVer[0], "Pi" + ((wSize=="small") ? "" : "-hole"))
topStack.addText(" ")
addUpdateItem(topStack, isLatestVer[1], "WebUI")
topStack.addText(" ")
addUpdateItem(topStack, isLatestVer[2], "FTL")
w.addSpacer(8)
if (piholeStats==null) {
content = w.addText("No connection")
content.font = Font.thinSystemFont(14)
content.textColor = wColor
w.addSpacer()
return w
}
w.url = piholeURL + "/admin/"
addItem(w, "Total Queries", piholeStats.dns_queries_all_types)
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
layoutStack.centerAlignContent()
addItem(w, "Queries Blocked", piholeStats.ads_blocked_today)
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
layoutStack.centerAlignContent()
addItem(w, "Percent Blocked", piholeStats.ads_percentage_today.toFixed(1).replace(".", ",") + "%")
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
layoutStack.centerAlignContent()
addItem(w, "Domains on Blocklist", piholeStats.domains_being_blocked)
if (wSize=="large") {
addItem(w, "Unique Domains", piholeStats.unique_domains)
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
addItem(w, "Cached Queries", piholeStats.queries_cached)
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
addItem(w, "Queries Forwarded", piholeStats.queries_forwarded)
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
addItem(w, "Clients Seen / Unique", piholeStats.clients_ever_seen + " / " + piholeStats.unique_clients)
}
w.addSpacer()
return w
}
function addItem(w, strHeadline, numData) {
let fontSizeHeadline = 12
let fontSizeString = 9
switch (wSize) {
case "large":
fontSizeHeadline = 18
fontSizeString = 14
break;
case "medium":
fontSizeHeadline = 14
fontSizeString = 11
break;
}
let layoutStack = w.addStack()
layoutStack.setPadding(3, 0, 0, 10)
layoutStack.centerAlignContent()
content = layoutStack.addText(strHeadline)
content.font = Font.mediumSystemFont(fontSizeHeadline)
content.textColor = wColor
layoutStack.addSpacer()
content = layoutStack.addText(numData.toLocaleString('de'))
content.font = Font.mediumSystemFont(fontSizeString)
content.textColor = wColor
}
function addUpdateItem(stack, status, text) {
let icn = SFSymbol.named((status ? "checkmark.circle.fill" : "exclamationmark.triangle.fill"))
let content = stack.addImage(icn.image)
content.tintColor = (status ? Color.green() : Color.red())
content.imageSize = new Size(14,14)
content = stack.addText(((wSize!="small") ? " " : "" ) + text)
content.font = Font.semiboldMonospacedSystemFont(12)
content.textColor = wColor
}
function getUpdateStats (webPage) {
// check how adminPage has to be parsed to get necessary updates
var recognition = ["pi-hole/releases/v", "FTL/releases/v", "AdminLTE/releases/v"]; // order has to be the same as on website
var updStr = "pdate avail"
let i
let pos, posUpdate
let page = webPage
let numCharRec2Upd = 300 // the maximum number of characters between the identifier and the update info
var isLatestVersion = new Array();
for (i=0; i<recognition.length; i++) {
isLatestVersion[i] = true
pos = page.indexOf(recognition[i])
if (pos >= 0) {
page = page.substring(pos + recognition[i].length)
posUpdate = page.indexOf(updStr)
if (posUpdate >= 0) {
if ((i+1) < recognition.length) {
pos = page.indexOf(recognition[i+1])
if (posUpdate < pos) { // Update between two version info
isLatestVersion[i] = false
}
} else if ( posUpdate <= numCharRec2Upd ) { // Update not far away from last version info
isLatestVersion[i] = false
}
}
}
}
return isLatestVersion
}
function setTheme() {
if (wTheme=="system") {
if (Device.isUsingDarkAppearance()) {
wTheme = "dark"
} else {
wTheme = "light"
}
}
wBackground.locations = [0, 1]
if (wTheme=="dark") {
wBackground.colors = [
new Color("#384d54"),
new Color("#384d54")
]
wColor = new Color("#ffffff")
} else {
wBackground.colors = [
new Color("#ffffffe6"), //ffffffe6
new Color("#ffffffe6")
]
wColor = new Color("#000000")
}
}
async function getStats() {
try {
let req = new Request(piholeURL + "/admin/api.php?summary")
let json = await req.loadJSON()
return json
} catch {
return null
}
}
async function getAdminPage() {
try {
let req = new Request(piholeURL + "/admin/")
let adminHTMLPage = await req.loadString()
return adminHTMLPage
} catch {
return null
}
}
Yeah! That works great indeed. Thanks @JoeGit42
only when I run it in scriptable it still gives me the following error:
2022-01-09 14:29:39: Error on line 192:13: TypeError: null is not an object (evaluating 'page.indexOf')
doesn’t really matter since the widget is working but would like to understand why it does that.
Ahh, found it. Just needed to add the pihole URL to the debug section in the script
@JoeGit42
Thanks for %-Fix … now is Okay!
At Line 110 I placed the following
addItem(w, "Percent Blocked", piholeStats.ads_percentage_today + "%")
that solves the issue for me.
Or this if you want a comma as a decimal separator
addItem(w, "Percent Blocked", piholeStats.ads_percentage_today.replace(".", ",") + "%")
@marked80
I’am use your second part - this help!
Big Thanks for the fastest Bugfix!
You can use the replace function for the other numbers too using this from line 100 till 117
addItem(w, "Total Queries", piholeStats.dns_queries_all_types.replace(",", "."))
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
layoutStack.centerAlignContent()
addItem(w, "Queries Blocked", piholeStats.ads_blocked_today.replace(",", "."))
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
layoutStack.centerAlignContent()
addItem(w, "Percent Blocked", piholeStats.ads_percentage_today.replace(".", ",") + "%")
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
layoutStack.centerAlignContent()
addItem(w, "Domains on Blocklist", piholeStats.domains_being_blocked.replaceAll(",", "."))
@Token2K You are welcome! 👍🏼
Hi all,
I have a problem to get a connection:
my code:
let piholeURL = "{“url“:“http://192.168.178.18“,“apikey“:“1234abcd“}" //set the URL here for debug http:// let wTheme = "system" // set the theme for debug
Parameters:
http://192.168.178.18“,“apikey“:“1234abcd“}
When I run it in scriptable it still gives me the following error:
In the widget it shows me the following error:
Can you help me? Any idea?
Thx a lot!
I also have not been able to fix it unfortunately.
It looks like the pihole stats values are not fetched anymore so that is why the error pops up.
It wants to convert the data to a string value but there is no data variable present at that point so it tries to convert null to string.
Does anyone know if the parameters have been changed for pi-hole?
I looked at the information of pi-hole but it still mentions the same parameters.
Hey there 👋
just updated the code. Because of changes of Pi-hole, you must use now the api token. You can create this one in the settings area.
Please update the parameters of your widget with the code inside:
{"url":"…","token":""}
Hey there 👋
just updated the code. Because of changes of Pi-hole, you must use now the api token. You can create this one in the settings area.
Please update the parameters of your widget with the code inside: {"url":"…","token":""}
Yes!! This works great. Just replaced the comma’s and dots again (in Europe that is the used decimal setting)
Yeah, perfect! Thanks a lot. One question: does the update feature work? It always shows me green, even though there is a new update… any idea?
Yeah, perfect! Thanks a lot. One question: does the update feature work? It always shows me green, even though there is a new update… any idea?
Fixed!
Just replaced the comma’s and dots again (in Europe that is the used decimal setting)
@marked80
How did you replaced them?
Just replaced the comma’s and dots again (in Europe that is the used decimal setting)
@marked80
How did you replaced them?
With a .replace function.
Below is the modified script:
// Parameters:
// {"url":"https://pihole","token": "x"}
// Optional key in parameters: "theme": system|light|dark
let piholeURL = "http://192.xxx.x.x" // set the URL here for debug
let apiToken = "xxxxxxx" // set the api token here for debug
let wTheme = "" // set the theme for debug
if (config.runsInWidget) {
const widgetParams = (args.widgetParameter != null ? JSON.parse(args.widgetParameter) : null)
if (widgetParams==null) {
throw new Error("Please long press the widget and add the parameters.")
} else if (!widgetParams.hasOwnProperty("url")) {
throw new Error("Wrong parameters.")
}
piholeURL = widgetParams.url
apiToken = widgetParams.token
if (widgetParams.hasOwnProperty("theme")) {
wTheme = widgetParams.theme
}
}
let wBackground = new LinearGradient()
let wColor = new Color("#ffffff")
setTheme()
let piholeStats = await getStats()
let adminPage = await getAdminPage()
let isLatestVersion = await getUpdateStats(adminPage)
let wSize = config.widgetFamily || "large" //set size of widget for debug
let widget = await createWidget() || null
if (!config.runsInWidget) {
if (wSize=="large") { await widget.presentLarge() }
else if (wSize=="medium") { await widget.presentMedium() }
else { await widget.presentSmall() }
}
Script.setWidget(widget)
Script.complete()
async function createWidget() {
let w = new ListWidget()
w.backgroundGradient = wBackground
w.addSpacer()
w.setPadding(5, 15, 0, (wSize=="small" ? 0 : 10))
let state = (piholeStats!=null ? (piholeStats.status=="enabled" ? true : false) : null)
let icn = null
if (state==true) {
icn = SFSymbol.named((state ? "checkmark.shield.fill" : "xmark.shield.fill"))
} else {
icn = SFSymbol.named("xmark.circle.fill")
state = false
}
let topStack = w.addStack()
topStack.layoutHorizontally()
topStack.setPadding(5, 0, 0, 10)
let content = topStack.addImage(icn.image)
content.tintColor = (state ? Color.green() : Color.red())
content.imageSize = new Size(16,16)
topStack.addSpacer(5)
content = topStack.addText("Pi-hole")
content.font = Font.blackSystemFont(16)
content.textColor = wColor
if (state==true && wSize != "small") {
topStack.addSpacer()
topStack.addText(" ") // same line with distance to title
addUpdateItem(topStack, isLatestVersion[0], "Pi" + ((wSize=="small") ? "" : "-hole"))
topStack.addText(" ")
addUpdateItem(topStack, isLatestVersion[2], "WebUI")
topStack.addText(" ")
addUpdateItem(topStack, isLatestVersion[1], "FTL")
}
w.addSpacer(8)
if (piholeStats==null) {
content = w.addText("No connection")
content.font = Font.thinSystemFont(14)
content.textColor = wColor
w.addSpacer()
return w
}
w.url = piholeURL + "/admin/"
addItem(w, "Total Queries", piholeStats.dns_queries_all_types.replace(",", "."))
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
layoutStack.centerAlignContent()
addItem(w, "Queries Blocked", piholeStats.ads_blocked_today.replace(",", "."))
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
layoutStack.centerAlignContent()
addItem(w, "Percent Blocked", Number.parseFloat(piholeStats.ads_percentage_today).toFixed(1).replace(".", ",") + "%")
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
layoutStack.centerAlignContent()
addItem(w, "Domains on Blocklist", piholeStats.domains_being_blocked.replace(",", "."))
if (wSize=="large") {
addItem(w, "Unique Domains", piholeStats.unique_domains)
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
addItem(w, "Cached Queries", piholeStats.queries_cached.replace(",", "."))
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
addItem(w, "Queries Forwarded", piholeStats.queries_forwarded.replace(",", "."))
layoutStack = w.addStack()
layoutStack.setPadding(5, 0, 0, 10)
addItem(w, "Clients Seen / Unique", piholeStats.clients_ever_seen + " / " + piholeStats.unique_clients)
}
w.addSpacer()
return w
}
function addItem(w, strHeadline, strData) {
let fontSizeHeadline = 12
let fontSizeString = 9
switch (wSize) {
case "large":
fontSizeHeadline = 18
fontSizeString = 14
break;
case "medium":
fontSizeHeadline = 14
fontSizeString = 11
break;
}
let layoutStack = w.addStack()
layoutStack.setPadding(3, 0, 0, 10)
layoutStack.centerAlignContent()
content = layoutStack.addText(strHeadline)
content.font = Font.mediumSystemFont(fontSizeHeadline)
content.textColor = wColor
layoutStack.addSpacer()
content = layoutStack.addText(strData.toString())
content.font = Font.mediumSystemFont(fontSizeString)
content.textColor = wColor
}
function addUpdateItem(stack, status, text) {
let icn = SFSymbol.named((status ? "checkmark.circle.fill" : "exclamationmark.triangle.fill"))
let content = stack.addImage(icn.image)
content.tintColor = (status ? Color.green() : Color.red())
content.imageSize = new Size(14,14)
content = stack.addText(((wSize!="small") ? " " : "" ) + text)
content.font = Font.semiboldMonospacedSystemFont(12)
content.textColor = wColor
}
function setTheme() {
if (wTheme=="system") {
if (Device.isUsingDarkAppearance()) {
wTheme = "dark"
} else {
wTheme = "light"
}
}
wBackground.locations = [0, 1]
if (wTheme=="dark") {
wBackground.colors = [
new Color("#384d54"),
new Color("#384d54")
]
wColor = new Color("#ffffff")
} else {
wBackground.colors = [
new Color("#ffffffe6"), //ffffffe6
new Color("#ffffffe6")
]
wColor = new Color("#000000")
}
}
async function getUpdateStats (webPage) {
let latestVersions = [true, true, true]
try {
let view = new WebView()
await view.loadHTML(webPage);
let data = await view.evaluateJavaScript(`
let retoure = [true, true, true]
let a = Array.from(document.querySelectorAll('div.version-info div ul li'))
for (let i=0; i<a.length; i++) {
let el = a[i]
if (el.getElementsByTagName('a').length == 2) {
retoure[i] = false
}
}
completion(retoure)`, true)
latestVersions = data
} catch(e) {
console.log("Cannot get update stats: " + e)
}
return latestVersions
}
async function getStats() {
try {
let req = new Request(piholeURL + "/admin/api.php?summary&auth="+apiToken)
let json = await req.loadJSON()
if (json.length === 0) { json == null }
return json
} catch(err) {
console.error(err)
return null
}
}
async function getAdminPage() {
try {
let req = new Request(piholeURL + "/admin/")
let adminHTMLPage = await req.loadString()
return adminHTMLPage
} catch(err) {
console.log(err)
return null
}
}
THX
Yep, same errors here “null is not an object” and after the last pihole update also the “expected value is type string”. Any idea how to fix them?