Files
routeros-geoip/generator.go
Steven Polley b1ed8f75ec mondern slopify hand crafted code for the greater good.
(move from user specified blocklist download URLs to simply country codes with multiple providers available.)
2026-05-01 17:18:50 -06:00

56 lines
1.7 KiB
Go

package main
import (
"fmt"
"os"
"strings"
"time"
)
// CountryData holds the resolved CIDR blocks for a single country.
type CountryData struct {
Code string // ISO 3166-1 alpha-2 country code
Name string // Display name for RouterOS comments
CIDRs []string // IPv4 CIDR blocks
}
// GenerateRSC produces a RouterOS .rsc script file that populates an address list.
// The filename includes today's date, e.g. "CountryIPBlocks-2026-05-01.rsc".
// Returns the generated filename.
func GenerateRSC(countries []CountryData, listName string) (string, error) {
now := time.Now()
datedName := fmt.Sprintf("%s-%s", listName, now.Format("2006-01-02"))
filename := fmt.Sprintf("%s.rsc", datedName)
var b strings.Builder
// Header with metadata
b.WriteString(fmt.Sprintf("# RouterOS GeoIP Address List: %s\n", datedName))
b.WriteString(fmt.Sprintf("# Generated: %s\n", now.UTC().Format(time.RFC3339)))
b.WriteString(fmt.Sprintf("# Countries: %d\n", len(countries)))
totalCIDRs := 0
for _, c := range countries {
totalCIDRs += len(c.CIDRs)
}
b.WriteString(fmt.Sprintf("# Total entries: %d\n", totalCIDRs))
b.WriteString("#\n")
// Each run creates a uniquely-named list (e.g. CountryIPBlocks-2026-05-01).
// Workflow: import this file, then atomically swap your firewall rules to
// reference the new list, then remove the old dated list.
b.WriteString("/ip firewall address-list\n")
for _, country := range countries {
for _, cidr := range country.CIDRs {
b.WriteString(fmt.Sprintf("add address=%s comment=\"%s\" list=%s\n", cidr, country.Name, datedName))
}
}
if err := os.WriteFile(filename, []byte(b.String()), os.ModePerm); err != nil {
return "", fmt.Errorf("failed to write file %q: %v", filename, err)
}
return filename, nil
}