package hub import ( "bytes" "encoding/json" "fmt" "net/http" "runtime" "time" "github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/pkg/txt" ) var FeedbackURL = ServiceURL + "/%s/feedback" type Feedback struct { Category string `json:"Category"` Subject string `json:"Subject"` Message string `json:"Message"` UserName string `json:"UserName"` UserEmail string `json:"UserEmail"` UserAgent string `json:"UserAgent"` ApiKey string `json:"ApiKey"` ClientVersion string `json:"ClientVersion"` ClientSerial string `json:"ClientSerial"` ClientOS string `json:"ClientOS"` ClientArch string `json:"ClientArch"` ClientCPU int `json:"ClientCPU"` } // NewFeedback creates a new hub feedback instance. func NewFeedback(version, serial string) *Feedback { return &Feedback{ ClientVersion: version, ClientSerial: serial, ClientOS: runtime.GOOS, ClientArch: runtime.GOARCH, ClientCPU: runtime.NumCPU(), } } func (c *Config) SendFeedback(f form.Feedback) (err error) { feedback := NewFeedback(c.Version, c.Serial) feedback.Category = f.Category feedback.Subject = txt.TrimLen(f.Message, 50) feedback.Message = f.Message feedback.UserName = f.UserName feedback.UserEmail = f.UserEmail feedback.UserAgent = f.UserAgent feedback.ApiKey = c.Key client := &http.Client{Timeout: 60 * time.Second} url := fmt.Sprintf(FeedbackURL, c.Key) method := http.MethodPost var req *http.Request log.Debugf("sending feedback to %s", ApiHost()) if j, err := json.Marshal(feedback); err != nil { return err } else if req, err = http.NewRequest(method, url, bytes.NewReader(j)); err != nil { return err } req.Header.Add("Accept-Language", f.UserLocales) req.Header.Add("Content-Type", "application/json") var r *http.Response for i := 0; i < 3; i++ { r, err = client.Do(req) if err == nil { break } } if err != nil { return err } else if r.StatusCode >= 400 { err = fmt.Errorf("sending feedback to %s failed (error %d)", ApiHost(), r.StatusCode) return err } err = json.NewDecoder(r.Body).Decode(c) if err != nil { return err } return nil }