Files

124 lines
4.3 KiB
Go

// Summer_Time_Configuration.html has THREE DST modes (Disable, Recurring,
// NonRecurring), each with its own full set of fields, ALL present in the
// DOM simultaneously (JS shows/hides based on the selected mode) -- same
// shape of problem as PortConfiguration.html's duplicate Link Speed fields,
// except here several labels collide WITHIN one table (Month/Hours/Minutes/
// Offset each appear once in the NonRecurring block and once in the
// Recurring block). Rather than lean on generic xepage.go parsing and its
// document-order last-wins behavior, this reads/writes via hardcoded field
// names extracted directly with regex -- unambiguous regardless of DOM
// order.
//
// Only Disable and Recurring are supported; NonRecurring is rejected
// outright rather than guessed at (it uses a different, absolute-date field
// set: Month/Date/Year/Hours/Minutes, v_3_1_1..v_3_10_1).
//
// Confirmed live before this was wired into a resource: submitting mode +
// only the Recurring block's fields (omitting the NonRecurring block
// entirely) was accepted with no err_flag and no FILTER_MISSING -- unlike
// PortConfiguration.html, this page does NOT require hidden hold_all_fields.
package client
import (
"fmt"
"regexp"
"strconv"
)
const (
dstConfigPath = "/Summer_Time_Configuration.html"
dstModeField = "v_1_1_1"
dstStartWeekField = "v_3_12_1"
dstStartDayField = "v_3_13_1"
dstStartMonthField = "v_3_14_1"
dstStartHourField = "v_3_15_1"
dstStartMinuteField = "v_3_399_1"
dstEndWeekField = "v_3_16_1"
dstEndDayField = "v_3_17_1"
dstEndMonthField = "v_3_18_1"
dstEndHourField = "v_3_19_1"
dstEndMinuteField = "v_3_498_1"
dstOffsetField = "v_3_20_1"
dstOffsetAcronymField = "v_3_21_1"
DSTModeDisable = "Disable"
DSTModeRecurring = "Recurring"
)
type DSTConfig struct {
Mode string
StartWeek int
StartDay string
StartMonth string
StartHour int
StartMinute int
EndWeek int
EndDay string
EndMonth string
EndHour int
EndMinute int
OffsetMinutes int
OffsetAcronym string
}
func extractHiddenFieldValue(html, name string) string {
re := regexp.MustCompile(`(?i)NAME=` + regexp.QuoteMeta(name) + `\b[^>]*VALUE="([^"]*)"`)
m := re.FindStringSubmatch(html)
if m == nil {
return ""
}
return m[1]
}
func (c *Client) ReadDSTConfig() (DSTConfig, error) {
html, err := c.Fetch(dstConfigPath)
if err != nil {
return DSTConfig{}, err
}
atoi := func(name string) int {
n, _ := strconv.Atoi(extractHiddenFieldValue(html, name))
return n
}
return DSTConfig{
Mode: extractHiddenFieldValue(html, dstModeField),
StartWeek: atoi(dstStartWeekField),
StartDay: extractHiddenFieldValue(html, dstStartDayField),
StartMonth: extractHiddenFieldValue(html, dstStartMonthField),
StartHour: atoi(dstStartHourField),
StartMinute: atoi(dstStartMinuteField),
EndWeek: atoi(dstEndWeekField),
EndDay: extractHiddenFieldValue(html, dstEndDayField),
EndMonth: extractHiddenFieldValue(html, dstEndMonthField),
EndHour: atoi(dstEndHourField),
EndMinute: atoi(dstEndMinuteField),
OffsetMinutes: atoi(dstOffsetField),
OffsetAcronym: extractHiddenFieldValue(html, dstOffsetAcronymField),
}, nil
}
func (c *Client) SetDSTConfig(desired DSTConfig) error {
if desired.Mode != DSTModeDisable && desired.Mode != DSTModeRecurring {
return fmt.Errorf("unsupported Daylight Saving Time mode %q -- this resource only supports %q and %q (NonRecurring is not supported)", desired.Mode, DSTModeDisable, DSTModeRecurring)
}
fields := map[string]string{
dstModeField: desired.Mode,
dstStartWeekField: strconv.Itoa(desired.StartWeek),
dstStartDayField: desired.StartDay,
dstStartMonthField: desired.StartMonth,
dstStartHourField: strconv.Itoa(desired.StartHour),
dstStartMinuteField: strconv.Itoa(desired.StartMinute),
dstEndWeekField: strconv.Itoa(desired.EndWeek),
dstEndDayField: desired.EndDay,
dstEndMonthField: desired.EndMonth,
dstEndHourField: strconv.Itoa(desired.EndHour),
dstEndMinuteField: strconv.Itoa(desired.EndMinute),
dstOffsetField: strconv.Itoa(desired.OffsetMinutes),
dstOffsetAcronymField: desired.OffsetAcronym,
}
_, err := c.SubmitForm(dstConfigPath, fields)
return err
}