diff --git a/node/api.go b/node/api.go index 7fd645d..4b8e770 100644 --- a/node/api.go +++ b/node/api.go @@ -27,7 +27,7 @@ func (es ESConf) ListTXTHandler(w http.ResponseWriter, r *http.Request) { // XFeaturesHandler list supported features func XFeaturesHandler(w http.ResponseWriter, r *http.Request) { - features := []string{"list.txt", "x/features"} + features := []string{"list.txt", "u/e"} LogRequest(r) @@ -54,6 +54,27 @@ func (es ESConf) EHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte(strings.Join(messages, "\n"))) } +// UEHandler /u/e/ schema +func (es ESConf) UEHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + e := vars["echoes"] + + log.Print("/u/e/ vars: ", e) + + LogRequest(r) + + ch := make(chan []string) + // Get echolist + go func() { + ch <- es.GetUEchoMessageHashes(e) + }() + + messages := <-ch + + w.WriteHeader(200) + w.Write([]byte(strings.Join(messages, "\n"))) +} + // MHandler /m/ schema func (es ESConf) MHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -83,6 +104,9 @@ func Serve(listen string, es ESConf) { r.HandleFunc("/e/{echo}", es.EHandler) r.HandleFunc("/m/{msgid}", es.MHandler) + // Extensions + r.HandleFunc("/u/e/{echoes:[a-z0-9-_/.:]+}", es.UEHandler) + http.Handle("/", r) srv := http.Server{ diff --git a/node/elastic.go b/node/elastic.go index 4cf0fcc..a878d5d 100644 --- a/node/elastic.go +++ b/node/elastic.go @@ -105,6 +105,122 @@ func (es ESConf) GetEchoMessageHashes(echo string) []string { return hashes } +// GetLimitedEchoMessageHashes ... +func (es ESConf) GetLimitedEchoMessageHashes(echo string, offset int, limit int) []string { + var hashes []string + + // Check offset + var order string + if offset <= 0 { + order = "desc" + } else { + order = "asc" + } + + l := strconv.Itoa(limit) + + searchURI := strings.Join([]string{es.Host, es.Index, es.Type, "_search"}, "/") + searchQ := []byte(strings.Join([]string{ + `{"sort": [ + {"date":{ "order": "`, order, `" }},{ "_score":{ "order": "`, order, `" }}], + "query": {"query_string" : {"fields": ["msgid", "echo"], "query":"`, echo, `"}}, "size":`, l, `}`}, "")) + + req, err := http.NewRequest("POST", searchURI, bytes.NewBuffer(searchQ)) + client := &http.Client{} + resp, err := client.Do(req) + + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return hashes + } + + esresp, err := gabs.ParseJSON(body) + if err != nil { + panic(err) + } + + hits, _ := esresp.Path("hits.hits").Data().([]interface{}) + for _, hit := range hits { + h := make(map[string]interface{}) + h = hit.(map[string]interface{}) + source := make(map[string]interface{}) + source = h["_source"].(map[string]interface{}) + hashes = append(hashes, source["msgid"].(string)) + } + + return hashes +} + +// GetUEchoMessageHashes ... +func (es ESConf) GetUEchoMessageHashes(echoes string) []string { + var echohashes []string + // First get echoes list + el := strings.Split(echoes, "/") + + // Check offset and limit + var offset int + var limit int + withOL := false + if strings.Contains(el[len(el)-1], ":") { + oflim := strings.Split(el[len(el)-1], ":") + o, err := strconv.Atoi(oflim[0]) + l, err := strconv.Atoi(oflim[1]) + if err != nil { + log.Print(err) + } else { + offset = o + limit = l + withOL = true + } + } + + eh := make(map[string][]string) + var curEcho string + for i, echo := range el { + if echo == "" { + continue + } + + if !strings.Contains(echo, ":") { + curEcho = echo + } + + if withOL { + recEcho := es.GetLimitedEchoMessageHashes(curEcho, offset, limit) + eh[curEcho] = make([]string, len(curEcho)) + eh[curEcho] = append(eh[curEcho], recEcho...) + + } else { + recEcho := es.GetEchoMessageHashes(curEcho) + eh[curEcho] = make([]string, len(recEcho)) + eh[curEcho] = append(eh[curEcho], recEcho...) + } + if i == len(el) { + break + } + } + + // Make standard output: + // echo.name + // Some20SimbolsHash333 + for k, v := range eh { + echohashes = append(echohashes, k) + if k == "" { + continue + } + for _, e := range v { + if e == "" { + continue + } + echohashes = append(echohashes, e) + } + } + + return echohashes +} + // GetListTXT ... func (es ESConf) GetListTXT() []byte { searchURI := strings.Join([]string{es.Host, es.Index, es.Type, "_search"}, "/")