package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "local/storage" "local/truckstop/broker" "local/truckstop/config" "local/truckstop/message" "log" "regexp" "strings" "sync" "time" ) var stateFinder = regexp.MustCompile(`[ ^>][A-Z][A-Z][ $<]`) func main() { lock := &sync.Mutex{} go func() { c := time.NewTicker(time.Minute) for range c.C { if !config.Get().EmailerEnabled { continue } lock.Lock() if err := email(); err != nil { log.Print(err) } lock.Unlock() } }() if err := _main(); err != nil { panic(err) } lock.Lock() } func email() error { ch, err := config.Get().Emailer.ReadIMAP() if err != nil { return err } states := map[config.State]struct{}{} var state config.State for email := range ch { if len(states) > 0 { continue } if !strings.Contains(email.Header.Get("From"), config.Get().Client) { continue } b, _ := ioutil.ReadAll(email.Body) candidates := stateFinder.FindAll(b, -1) for _, candidate := range candidates { s := fmt.Sprintf(`"%s"`, bytes.TrimSpace(candidate)) err := json.Unmarshal([]byte(s), &state) if err != nil { } else { states[state] = struct{}{} } } } if len(states) == 0 { return nil } conf := *config.Get() conf.States = []config.State{} for k := range states { conf.States = append(conf.States, k) } log.Printf("%+v, %+v", states, conf) config.Set(conf) return nil } func _main() error { for { if err := config.Refresh(); err != nil { return err } if err := once(); err != nil { return err } if config.Get().Once { break } time.Sleep(config.Get().Interval.Get()) } return nil } func once() error { alljobs, err := getJobs() if err != nil { return err } newjobs, err := dropStaleJobs(alljobs) if err != nil { return err } jobs, err := dropBanlistJobs(newjobs) if err != nil { return err } for i := range jobs { if err := sendJob(jobs[i]); err != nil { return err } if err := config.Get().DB().Set(jobs[i].ID, []byte(`sent`)); err != nil { return err } } return nil } func getJobs() ([]broker.Job, error) { states := config.Get().States ntg := broker.NewNTGVision() if config.Get().Brokers.NTG.Mock { ntg = ntg.WithMock() } brokers := []broker.Broker{ntg} jobs := []broker.Job{} for _, broker := range brokers { somejobs, err := broker.Search(states) if err != nil { return nil, err } jobs = append(jobs, somejobs...) } return jobs, nil } func dropStaleJobs(jobs []broker.Job) ([]broker.Job, error) { db := config.Get().DB() for i := len(jobs) - 1; i >= 0; i-- { if _, err := db.Get(jobs[i].ID); err == storage.ErrNotFound { } else if err != nil { return nil, err } else { jobs = append(jobs[:i], jobs[i+1:]...) } } return jobs, nil } func dropBanlistJobs(jobs []broker.Job) ([]broker.Job, error) { // TODO return jobs, nil } func sendJob(job broker.Job) error { sender := message.NewMatrix() return sender.Send(job.FormatMultilineText()) }