Files
miti99bot/internal/modules/monkeyd/crawl_args.go
T
tiennm99 0ddc6b3ccc feat(monkeyd): accept an optional font size argument
/monkeyd_crawl <url> [font_size] sets the body text size in points, half points
included, bounded to 6-24. Omitting it sends no size at all so the crawler's
default applies, rather than defining a second default here that could drift.
The document caption reports the size used.

Also advance the submodule to the lower 10pt default: on the 90x160mm phone
page that fits about 43 characters per line instead of 36.
2026-07-30 00:16:57 +07:00

71 lines
1.9 KiB
Go

package monkeyd
import (
"errors"
"fmt"
"math"
"strconv"
"strings"
)
// Font size bounds for the optional argument. The body font drives the heading
// and title sizes too, and the default page is only 78mm wide between margins,
// so the useful range is narrow: at 6pt a line holds about 72 characters, at
// 24pt about 18.
const (
minFontSize = 6.0
maxFontSize = 24.0
)
var errTooManyArgs = errors.New("too many arguments")
// crawlArgs is a validated /monkeyd_crawl invocation.
type crawlArgs struct {
// NovelURL is normalised and known to be on an allowed host.
NovelURL string
// FontSize is the requested body font size in points, or 0 to leave the
// crawler's default in place.
FontSize float64
}
// parseCrawlArgs validates the text after the command: a novel URL, optionally
// followed by a body font size.
func parseCrawlArgs(arg string) (crawlArgs, error) {
fields := strings.Fields(arg)
if len(fields) == 0 {
return crawlArgs{}, errNotAURL
}
if len(fields) > 2 {
return crawlArgs{}, errTooManyArgs
}
novelURL, err := normalizeNovelURL(fields[0])
if err != nil {
return crawlArgs{}, err
}
parsed := crawlArgs{NovelURL: novelURL}
if len(fields) == 2 {
if parsed.FontSize, err = parseFontSize(fields[1]); err != nil {
return crawlArgs{}, err
}
}
return parsed, nil
}
// parseFontSize accepts a font size in points, including half points, and
// rejects anything outside the readable range.
func parseFontSize(raw string) (float64, error) {
size, err := strconv.ParseFloat(raw, 64)
// ParseFloat accepts "NaN" and "Inf", neither of which is a font size, and
// both would reach the renderer as a silently broken layout.
if err != nil || math.IsNaN(size) || math.IsInf(size, 0) {
return 0, fmt.Errorf("font size %q is not a number", raw)
}
if size < minFontSize || size > maxFontSize {
return 0, fmt.Errorf("font size must be between %g and %g points", minFontSize, maxFontSize)
}
return size, nil
}