package main import ( "encoding/json" "log" "net/http" "strings" "time" ) type Attendee struct { AttendeeId int64 UserId int64 `json:"-"` Name string Date time.Time `json:"-"` } type PopularAttendee struct { Name string Popularity int64 } type AttendeeList struct { Attendees *[]*Attendee `json:"attendees"` } type PopularAttendeeList struct { PopularAttendees *[]*PopularAttendee `json:"popularattendees"` } func (a *Attendee) Write(w http.ResponseWriter) error { enc := json.NewEncoder(w) return enc.Encode(a) } func (a *Attendee) Read(json_str string) error { dec := json.NewDecoder(strings.NewReader(json_str)) return dec.Decode(a) } func (al *AttendeeList) Write(w http.ResponseWriter) error { enc := json.NewEncoder(w) return enc.Encode(al) } func (pa *PopularAttendee) Write(w http.ResponseWriter) error { enc := json.NewEncoder(w) return enc.Encode(pa) } func (pal *PopularAttendeeList) Write(w http.ResponseWriter) error { enc := json.NewEncoder(w) return enc.Encode(pal) } type AttendeeExistsError struct{} func (aeu AttendeeExistsError) Error() string { return "Attendee exists" } func GetAttendees(userid int64, date time.Time) (*[]*Attendee, error) { var attendees []*Attendee _, err := DB.Select(&attendees, "SELECT * from attendees WHERE UserId=? AND Date=?", userid, date) if err != nil { return nil, err } return &attendees, nil } func GetPopularAttendees() (*[]*PopularAttendee, error) { var attendees []*Attendee var attendeeMap map[string]int64 popularAttendees := make([]*PopularAttendee, 0) _, err := DB.Select(&attendees, "SELECT * from attendees") if err != nil { return nil, err } for i := range attendees { attendeeMap[attendees[i].Name] += 1 } for name, count := range attendeeMap { var popularAttendee PopularAttendee popularAttendee.Name = name popularAttendee.Popularity = count popularAttendees = append(popularAttendees, &popularAttendee) } return &popularAttendees, nil } func InsertAttendee(a *Attendee) error { transaction, err := DB.Begin() if err != nil { return err } existing, err := transaction.SelectInt("SELECT count(*) from users where Name=?", a.Name) if err != nil { transaction.Rollback() return err } if existing > 0 { transaction.Rollback() return AttendeeExistsError{} } err = transaction.Insert(a) if err != nil { transaction.Rollback() return err } err = transaction.Commit() if err != nil { transaction.Rollback() return err } return nil } func AttendeeHandler(w http.ResponseWriter, r *http.Request) { user, err := GetUserFromSession(r) if err != nil { WriteError(w, 1 /*Not Signed In*/) return } today := time.Now().Truncate(time.Hour * 24) if r.Method == "POST" { attendee_json := r.PostFormValue("attendee") if attendee_json == "" { WriteError(w, 3 /*Invalid Request*/) return } var attendee Attendee err := attendee.Read(attendee_json) if err != nil { WriteError(w, 3 /*Invalid Request*/) return } attendee.AttendeeId = -1 attendee.UserId = user.UserId attendee.Date = today err = InsertAttendee(&attendee) if err != nil { if _, ok := err.(AttendeeExistsError); ok { WriteError(w, 5 /*Attendee Exists*/) } else { WriteError(w, 999 /*Internal Error*/) log.Print(err) } return } w.WriteHeader(201 /*Created*/) err = attendee.Write(w) if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } } else if r.Method == "GET" { var al AttendeeList attendees, err := GetAttendees(user.UserId, today) if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } al.Attendees = attendees err = (&al).Write(w) if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } } else { /* No PUT or DELETE */ WriteError(w, 3 /*Invalid Request*/) return } } func PopularAttendeeHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { var pal PopularAttendeeList attendees, err := GetPopularAttendees() if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } pal.PopularAttendees = attendees err = (&pal).Write(w) if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return } } else { /* No POST, PUT, or DELETE */ WriteError(w, 3 /*Invalid Request*/) return } }