diff --git a/docs/custom-api.md b/docs/custom-api.md index a32f296..3f603d8 100644 --- a/docs/custom-api.md +++ b/docs/custom-api.md @@ -238,7 +238,7 @@ Output:
90
``` -Other operations include `add`, `mul`, and `div`. +Other operations include `add`, `mul`, `div` and `mod`.
@@ -415,6 +415,14 @@ The following functions are available on the `JSON` object: - `Array(key string) []JSON`: Returns the value of the key as an array of `JSON` objects. - `Exists(key string) bool`: Returns true if the key exists in the JSON object. +The following functions are available on the `Options` object: + +- `StringOr(key string, default string) string`: Returns the value of the key as a string, or the default value if the key does not exist. +- `IntOr(key string, default int) int`: Returns the value of the key as an integer, or the default value if the key does not exist. +- `FloatOr(key string, default float) float`: Returns the value of the key as a float, or the default value if the key does not exist. +- `BoolOr(key string, default bool) bool`: Returns the value of the key as a boolean, or the default value if the key does not exist. +- `JSON(key string) JSON`: Returns the value of the key as a stringified `JSON` object, or throws an error if the key does not exist. + The following helper functions provided by Glance are available: - `toFloat(i int) float`: Converts an integer to a float. @@ -431,6 +439,7 @@ The following helper functions provided by Glance are available: - `sub(a, b float) float`: Subtracts two numbers. - `mul(a, b float) float`: Multiplies two numbers. - `div(a, b float) float`: Divides two numbers. +- `mod(a, b int) int`: Remainder after dividing a by b (a % b). - `formatApproxNumber(n int) string`: Formats a number to be more human-readable, e.g. 1000 -> 1k. - `formatNumber(n float|int) string`: Formats a number with commas, e.g. 1000 -> 1,000. - `trimPrefix(prefix string, str string) string`: Trims the prefix from a string. diff --git a/internal/glance/diagnose.go b/internal/glance/diagnose.go index 1ee1bc3..2839a23 100644 --- a/internal/glance/diagnose.go +++ b/internal/glance/diagnose.go @@ -12,7 +12,7 @@ import ( "time" ) -const httpTestRequestTimeout = 10 * time.Second +const httpTestRequestTimeout = 15 * time.Second var diagnosticSteps = []diagnosticStep{ { @@ -75,7 +75,9 @@ var diagnosticSteps = []diagnosticStep{ { name: "fetch data from Reddit API", fn: func() (string, error) { - return testHttpRequest("GET", "https://www.reddit.com/search.json", 200) + return testHttpRequestWithHeaders("GET", "https://www.reddit.com/search.json", map[string]string{ + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0", + }, 200) }, }, { @@ -165,7 +167,7 @@ func testHttpRequestWithHeaders(method, url string, headers map[string]string, e request.Header.Add(key, value) } - response, err := http.DefaultClient.Do(request) + response, err := defaultHTTPClient.Do(request) if err != nil { return "", err } diff --git a/internal/glance/static/js/page.js b/internal/glance/static/js/page.js index 5ee6d16..56e9c2e 100644 --- a/internal/glance/static/js/page.js +++ b/internal/glance/static/js/page.js @@ -661,7 +661,7 @@ function setupTruncatedElementTitles() { for (let i = 0; i < elements.length; i++) { const element = elements[i]; - if (element.getAttribute("title") === null) element.title = element.textContent; + if (element.getAttribute("title") === null) element.title = element.innerText; } } diff --git a/internal/glance/widget-custom-api.go b/internal/glance/widget-custom-api.go index 3d94eb6..3c2ca75 100644 --- a/internal/glance/widget-custom-api.go +++ b/internal/glance/widget-custom-api.go @@ -108,6 +108,20 @@ func (o *customAPIOptions) BoolOr(key string, defaultValue bool) bool { return customAPIGetOptionOrDefault(*o, key, defaultValue) } +func (o *customAPIOptions) JSON(key string) string { + value, exists := (*o)[key] + if !exists { + panic(fmt.Sprintf("key %q does not exist in options", key)) + } + + encoded, err := json.Marshal(value) + if err != nil { + panic(fmt.Sprintf("marshaling %s: %v", key, err)) + } + + return string(encoded) +} + func customAPIGetOptionOrDefault[T any](o customAPIOptions, key string, defaultValue T) T { if value, exists := o[key]; exists { if typedValue, ok := value.(T); ok { @@ -479,6 +493,12 @@ var customAPITemplateFuncs = func() template.FuncMap { "div": func(a, b any) any { return doMathOpWithAny(a, b, "div") }, + "mod": func(a, b int) int { + if b == 0 { + return 0 + } + return a % b + }, "now": func() time.Time { return time.Now() }, diff --git a/internal/glance/widget-utils.go b/internal/glance/widget-utils.go index fa2fad5..6d752e5 100644 --- a/internal/glance/widget-utils.go +++ b/internal/glance/widget-utils.go @@ -26,6 +26,7 @@ const defaultClientTimeout = 5 * time.Second var defaultHTTPClient = &http.Client{ Transport: &http.Transport{ MaxIdleConnsPerHost: 10, + Proxy: http.ProxyFromEnvironment, }, Timeout: defaultClientTimeout, } @@ -34,6 +35,7 @@ var defaultInsecureHTTPClient = &http.Client{ Timeout: defaultClientTimeout, Transport: &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + Proxy: http.ProxyFromEnvironment, }, }