// StalkHandle return n most recent lines of chat for user func StalkHandle(w http.ResponseWriter, r *http.Request) { type Error struct { Error string `json:"error"` } w.Header().Set("Content-type", "application/json") vars := mux.Vars(r) if _, ok := vars["limit"]; !ok { vars["limit"] = "3" } limit, err := strconv.ParseUint(vars["limit"], 10, 32) if err != nil { d, _ := json.Marshal(Error{err.Error()}) http.Error(w, string(d), http.StatusBadRequest) return } if limit > uint64(common.GetConfig().Server.MaxStalkLines) { limit = uint64(common.GetConfig().Server.MaxStalkLines) } else if limit < 1 { limit = 3 } buf := make([]string, limit) index := limit search, err := common.NewNickSearch(common.GetConfig().LogPath+"/"+vars["channel"], vars["nick"]) if err != nil { d, _ := json.Marshal(Error{err.Error()}) http.Error(w, string(d), http.StatusNotFound) return } ScanLogs: for { rs, err := search.Next() if err == io.EOF { break } else if err != nil { d, _ := json.Marshal(Error{err.Error()}) http.Error(w, string(d), http.StatusInternalServerError) return } data, err := readLogFile(common.GetConfig().LogPath + "/" + vars["channel"] + "/" + rs.Month() + "/" + rs.Day()) if err != nil { d, _ := json.Marshal(Error{err.Error()}) http.Error(w, string(d), http.StatusInternalServerError) return } lines := [][]byte{} r := bufio.NewReaderSize(bytes.NewReader(data), len(data)) filter := nickFilter(rs.Nick()) for { line, err := r.ReadSlice('\n') if err != nil { if err != io.EOF { log.Printf("error reading bytes %s", err) } break } if filter(line) { lines = append(lines, line[0:len(line)-1]) } } for i := len(lines) - 1; i >= 0; i-- { index-- buf[index] = string(lines[i]) if index == 0 { break ScanLogs } } } if index == limit { d, _ := json.Marshal(Error{"User not found"}) http.Error(w, string(d), http.StatusInternalServerError) return } type Line struct { Timestamp int64 `json:"timestamp"` Text string `json:"text"` } data := struct { Nick string `json:"nick"` Lines []Line `json:"lines"` }{ Lines: []Line{}, } for i := int(index); i < len(buf); i++ { t, err := time.Parse("2006-01-02 15:04:05 MST", buf[i][1:24]) if err != nil { continue } ci := strings.Index(buf[i][LogLinePrefixLength:], ":") data.Nick = buf[i][LogLinePrefixLength : LogLinePrefixLength+ci] data.Lines = append(data.Lines, Line{ Timestamp: t.Unix(), Text: buf[i][ci+LogLinePrefixLength+2:], }) } d, _ := json.Marshal(data) w.Write(d) }