mirror of
https://github.com/tiennm99/miti99bot.git
synced 2026-08-06 16:24:48 +00:00
refactor(modules): allow hyphens in module names
Relax module name regex to accept hyphens, preparing for hyphenated loldle variants (loldle-emoji, loldle-quote, etc.) ported from upstream JS sources. Storage prefix delimiter ':' remains rejected. Telegram command names use separate stricter regex (commandNameRe) and are unaffected.
This commit is contained in:
@@ -2,15 +2,21 @@ package modules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
|
||||
"github.com/tiennm99/miti99bot-go/internal/storage"
|
||||
)
|
||||
|
||||
// moduleNameRe enforces the same alphabet as command names so KV prefix
|
||||
// isolation is preserved (no ":" in module names → no prefix collision) and
|
||||
// the cron route's path segment regex matches.
|
||||
var moduleNameRe = commandNameRe // alias kept for symmetry; one regex serves both
|
||||
// moduleNameRe is intentionally looser than commandNameRe — it allows hyphen
|
||||
// so modules can keep their JS-source names verbatim (e.g. "loldle-emoji").
|
||||
// The crucial constraint is "no `:`" so the storage Prefixed wrapper's `:`
|
||||
// delimiter cannot be subverted; everything else is style.
|
||||
//
|
||||
// Telegram command names still need the stricter [a-z0-9_]{1,32} alphabet
|
||||
// (commandNameRe in validate.go). Cron route segments use their own regex in
|
||||
// internal/server/router.go and stay strict for log-injection safety.
|
||||
var moduleNameRe = regexp.MustCompile(`^[a-z0-9_-]{1,32}$`)
|
||||
|
||||
// Registry holds the resolved set of modules selected by the MODULES env var.
|
||||
// It is built once at startup; Build fails fast on validation or conflict.
|
||||
|
||||
@@ -210,7 +210,10 @@ func TestDispatchScheduled_PassesPrefixedDeps(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBuild_RejectsInvalidModuleName(t *testing.T) {
|
||||
for _, name := range []string{"BadName", "with-dash", "a:b", ""} {
|
||||
// `-` is intentionally allowed (loldle-emoji and friends carry hyphenated
|
||||
// names from the JS source). `:` must stay rejected — it's the storage
|
||||
// prefix delimiter and a hyphen-allowing regex must not let it through.
|
||||
for _, name := range []string{"BadName", "a:b", "", "with space", "with.dot", "with/slash"} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
_, err := Build([]string{name}, map[string]Factory{}, newProvider(), nil)
|
||||
if err == nil {
|
||||
@@ -220,6 +223,19 @@ func TestBuild_RejectsInvalidModuleName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuild_AcceptsHyphenatedModuleName(t *testing.T) {
|
||||
factories := map[string]Factory{
|
||||
"loldle-emoji": factory("loldle-emoji", []Command{noopCmd("emoji_cmd")}, nil),
|
||||
}
|
||||
reg, err := Build([]string{"loldle-emoji"}, factories, newProvider(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("hyphenated name should be allowed: %v", err)
|
||||
}
|
||||
if len(reg.Modules) != 1 || reg.Modules[0].Name != "loldle-emoji" {
|
||||
t.Errorf("module not registered correctly: %+v", reg.Modules)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuild_RejectsDuplicateModuleInEnv(t *testing.T) {
|
||||
factories := map[string]Factory{
|
||||
"alpha": factory("alpha", []Command{noopCmd("a1")}, nil),
|
||||
|
||||
Reference in New Issue
Block a user