Панель видит моды Build 42 и названия больших сборок
CI / test (push) Successful in 23s
Release / release (push) Successful in 29s

В Build 42 mod.info лежит не в корне мода, а в папке версии: common, 42,
42.16. Сканер смотрел только в корень, и такие моды выглядели нескачанными
с неизвестным Mod ID — включить их через панель было нельзя. На реальной
мастерской находилось 237 модов из 399.

Названия из мастерской фронтенд запрашивал одним списком, а эндпоинт не
принимает больше двухсот идентификаторов за раз. У сборки на 284 пакета
запрос падал целиком, ошибка молча проглатывалась, и вместо названий
оставались одни номера. Теперь запрос идёт партиями, а полная неудача
больше не остаётся незамеченной.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-07 17:38:23 +03:00
co-authored by Claude Opus 5
parent 5d9bedaad2
commit 6d27fd049d
5 changed files with 148 additions and 6 deletions
+60
View File
@@ -75,3 +75,63 @@ func writeModInfo(t *testing.T, dir, content string) {
t.Fatal(err)
}
}
// В Build 42 mod.info лежит не в корне мода, а в папке версии. Мод из такой
// раскладки должен находиться, иначе панель считает его нескачанным.
func TestScanInstalledModsBuild42Layout(t *testing.T) {
root := t.TempDir()
content := filepath.Join(root, "server", "steamapps", "workshop", "content", pzAppID)
writeModInfo(t, filepath.Join(content, "111", "mods", "Wipes", "common"),
"name=Cleaning Wipes\nid=dustinguished_cleaning_wipes\n")
// Мод с несколькими версиями: берём самую свежую, а не common.
mod := filepath.Join(content, "222", "mods", "NewMusicG90s")
writeModInfo(t, filepath.Join(mod, "common"), "name=Mixtape (common)\nid=NewMusicG90s\n")
writeModInfo(t, filepath.Join(mod, "42"), "name=Mixtape (42)\nid=NewMusicG90s\n")
writeModInfo(t, filepath.Join(mod, "42.16"), "name=Mixtape (42.16)\nid=NewMusicG90s\n")
mods := ScanInstalledMods([]string{filepath.Join(root, "server")}, "")
byID := make(map[string]InstalledMod, len(mods))
for _, m := range mods {
byID[m.ModID] = m
}
if len(byID) != 2 {
t.Fatalf("найдено %d модов, ожидалось 2: %v", len(byID), byID)
}
if got := byID["dustinguished_cleaning_wipes"]; got.Name != "Cleaning Wipes" || got.WorkshopID != "111" {
t.Errorf("мод из common разобран неверно: %+v", got)
}
if got := byID["NewMusicG90s"]; got.Name != "Mixtape (42.16)" {
t.Errorf("взята не самая свежая версия: %+v", got)
}
// Dir указывает на папку мода, а не на папку версии: так его удобнее найти.
if got := byID["NewMusicG90s"]; filepath.Base(got.Dir) != "NewMusicG90s" {
t.Errorf("Dir указывает не на папку мода: %+v", got)
}
}
// Корневой mod.info главнее версий: так раскладывают моды Build 41.
func TestModInfoPathPrefersRoot(t *testing.T) {
mod := t.TempDir()
writeModInfo(t, mod, "name=Root\nid=Root\n")
writeModInfo(t, filepath.Join(mod, "42"), "name=Version\nid=Version\n")
path, ok := modInfoPath(mod)
if !ok {
t.Fatal("mod.info не найден")
}
if filepath.Dir(path) != mod {
t.Errorf("взят mod.info из папки версии: %s", path)
}
}
func TestModInfoPathWithoutModInfo(t *testing.T) {
mod := t.TempDir()
if err := os.MkdirAll(filepath.Join(mod, "media"), 0o755); err != nil {
t.Fatal(err)
}
if _, ok := modInfoPath(mod); ok {
t.Error("mod.info найден там, где его нет")
}
}