package main import ( "encoding/json" "errors" "fmt" "regexp" "strconv" "strings" ) type loadTupContent struct { Title string VideoID string Interval float64 Secs []float64 Caps []string Scrsecs []float64 Scrcaps []string } func parse_json_floats(part []byte) ([]float64, error) { secsStrings := make([]string, 0) err := json.Unmarshal(part, &secsStrings) if err != nil { return nil, err } ret := make([]float64, 0, len(secsStrings)) for _, sec := range secsStrings { ff, err := strconv.ParseFloat(sec, 64) if err != nil { return nil, err } ret = append(ret, ff) } return ret, nil } func NewLoadTupContent(content []byte) (*loadTupContent, error) { var err error rx := regexp.MustCompile(`videoIdMain = "([^"]+)";var interval = (\d+);var secs = (.+?);var caps = (.+?);var scrsecs = (.+?);var scrcaps = (.+?);`) parts := rx.FindStringSubmatch(string(content)) if parts == nil { return nil, errors.New("Missing video properties in HTML page") } if len(parts) != 7 { return nil, fmt.Errorf("expected len(parts)=7, got %d", len(parts)) } ltc := loadTupContent{} ltc.VideoID = parts[1] ltc.Interval, err = strconv.ParseFloat(parts[2], 64) if err != nil { return nil, err } ltc.Secs, err = parse_json_floats([]byte(parts[3])) if err != nil { return nil, err } err = json.Unmarshal([]byte(parts[4]), <c.Caps) if err != nil { return nil, err } ltc.Scrsecs, err = parse_json_floats([]byte(parts[5])) if err != nil { return nil, err } err = json.Unmarshal([]byte(parts[6]), <c.Scrcaps) if err != nil { return nil, err } // Parse the page title rx = regexp.MustCompile(`(?ms)

(.+?)

`) parts = rx.FindStringSubmatch(string(content)) if parts == nil { return nil, errors.New("Missing title in HTML page") } if len(parts) != 2 { return nil, fmt.Errorf("expected len(parts)=2, got %d", len(parts)) } ltc.Title = strings.TrimSpace(parts[1]) return <c, nil } func (ltc *loadTupContent) Validate() error { if len(ltc.Secs) != len(ltc.Caps) { return fmt.Errorf("secs/caps length mismatch") } if len(ltc.Scrsecs) != len(ltc.Scrcaps) { return fmt.Errorf("scrsecs/scrcaps length mismatch") } if len(ltc.VideoID) == 0 { return errors.New("unexpected blank video ID") } if ltc.Interval != 100.0 { return errors.New("unsupported non-100 duration field") } return nil }