Moves msdls_v3.py from repo root into scripts/check-new-releases/, alongside a new Go tool, documented as Method 1 (Python brute-force range scan, can write results to a catalog-shaped JSON) and Method 2 (Go auto-discovery via page-scrape + bounded adjacent-ID probe, no range-guessing needed). Only Windows 11 is checked -- 8.1 is fully frozen and Windows 10 is past end-of-life, so neither will produce a new consumer ISO again. Fixed msdls_v3.py's release-name extraction: it checked EditionName/ ReleaseName/FriendlyName, none of which exist in the real API response -- the actual field is ProductDisplayName, confirmed live. Also added the vlscppe session-permit call to setup_session(), which was skipped entirely; higher-risk gap for this script's brute-force range-scan usage pattern than for a single lookup. Both tools' live runs surfaced a real catalog gap: product IDs 3322/3323/3325/3326 (Home/Pro China variants of the 25H2 "V2" refresh) exist on Microsoft's side but weren't in our catalog. Added them to cli/catalog.go, products.json, validContributeProducts, and sitemap.xml, and renamed 3321/3324 from our own guessed "(Updated Oct)" label to Microsoft's actual name for this refresh, "(V2)" (their internal name is "Windows 11 25H2__V2"; cleaned up the double-underscore for user-facing display). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
3.3 KiB
Go
111 lines
3.3 KiB
Go
package main
|
|
|
|
import "strings"
|
|
|
|
type Product struct {
|
|
ID string
|
|
Name string
|
|
}
|
|
|
|
type EvalProduct struct {
|
|
Slug string
|
|
Name string
|
|
EvalURL string
|
|
}
|
|
|
|
var consumerProducts = []Product{
|
|
{"52", "Windows 8.1 (9600.17415)"},
|
|
{"2378", "Windows 10 22H2 Home China (19045.2006)"},
|
|
{"2618", "Windows 10 22H2 v1 (19045.2965)"},
|
|
{"3113", "Windows 11 24H2 (26100.1742)"},
|
|
{"3114", "Windows 11 24H2 Home China (26100.1742)"},
|
|
{"3115", "Windows 11 24H2 Pro China (26100.1742)"},
|
|
{"3131", "Windows 11 Arm64 24H2 (26100.1742)"},
|
|
{"3132", "Windows 11 Arm64 24H2 Home China (26100.1742)"},
|
|
{"3133", "Windows 11 Arm64 24H2 Pro China (26100.1742)"},
|
|
{"3262", "Windows 11 25H2 (26200.6584)"},
|
|
{"3263", "Windows 11 25H2 Home China (26200.6584)"},
|
|
{"3264", "Windows 11 25H2 Pro China (26200.6584)"},
|
|
{"3265", "Windows 11 Arm64 25H2 (26200.6584)"},
|
|
{"3266", "Windows 11 Arm64 25H2 Home China (26200.6584)"},
|
|
{"3267", "Windows 11 Arm64 25H2 Pro China (26200.6584)"},
|
|
{"3321", "Windows 11 25H2 (V2)"},
|
|
{"3322", "Windows 11 25H2 Home China (V2)"},
|
|
{"3323", "Windows 11 25H2 Pro China (V2)"},
|
|
{"3324", "Windows 11 Arm64 25H2 (V2)"},
|
|
{"3325", "Windows 11 Arm64 25H2 Home China (V2)"},
|
|
{"3326", "Windows 11 Arm64 25H2 Pro China (V2)"},
|
|
}
|
|
|
|
var evalProducts = []EvalProduct{
|
|
{"server-2025", "Windows Server 2025", "https://www.microsoft.com/en-us/evalcenter/download-windows-server-2025"},
|
|
{"server-2022", "Windows Server 2022", "https://www.microsoft.com/en-us/evalcenter/download-windows-server-2022"},
|
|
{"server-2019", "Windows Server 2019", "https://www.microsoft.com/en-us/evalcenter/download-windows-server-2019"},
|
|
{"server-2016", "Windows Server 2016", "https://www.microsoft.com/en-us/evalcenter/download-windows-server-2016"},
|
|
{"win11-ent", "Windows 11 Enterprise", "https://www.microsoft.com/en-us/evalcenter/download-windows-11-enterprise"},
|
|
}
|
|
|
|
func findProductByID(id string) (Product, bool) {
|
|
for _, p := range consumerProducts {
|
|
if p.ID == id {
|
|
return p, true
|
|
}
|
|
}
|
|
return Product{}, false
|
|
}
|
|
|
|
func searchProducts(query string) []Product {
|
|
words := strings.Fields(strings.ToLower(query))
|
|
if len(words) == 0 {
|
|
return consumerProducts
|
|
}
|
|
var results []Product
|
|
for _, p := range consumerProducts {
|
|
name := strings.ToLower(p.Name)
|
|
match := true
|
|
for _, w := range words {
|
|
if !containsWordStart(name, w) {
|
|
match = false
|
|
break
|
|
}
|
|
}
|
|
if match {
|
|
results = append(results, p)
|
|
}
|
|
}
|
|
return results
|
|
}
|
|
|
|
// containsWordStart reports whether s contains substr starting at a word
|
|
// boundary: the start of s, or right after a non-alphanumeric character.
|
|
// Plain strings.Contains would let a query word match a digit fragment
|
|
// buried inside an unrelated number -- e.g. "10" matching inside a build
|
|
// number like "26100.1742" -- which made "windows 10" incorrectly return
|
|
// Windows 11 24H2 results.
|
|
func containsWordStart(s, substr string) bool {
|
|
from := 0
|
|
for {
|
|
i := strings.Index(s[from:], substr)
|
|
if i < 0 {
|
|
return false
|
|
}
|
|
pos := from + i
|
|
if pos == 0 || !isAlphanumeric(s[pos-1]) {
|
|
return true
|
|
}
|
|
from = pos + 1
|
|
}
|
|
}
|
|
|
|
func isAlphanumeric(b byte) bool {
|
|
return (b >= 'a' && b <= 'z') || (b >= '0' && b <= '9')
|
|
}
|
|
|
|
func findEvalProduct(slug string) (EvalProduct, bool) {
|
|
for _, p := range evalProducts {
|
|
if p.Slug == slug {
|
|
return p, true
|
|
}
|
|
}
|
|
return EvalProduct{}, false
|
|
}
|