diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2273a10 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module github.com/idec-net/lessmore-node + +go 1.16 + +replace github.com/idec-net/lessmore-node/node => ./node + +require ( + github.com/idec-net/lessmore-node/node v0.0.0-00010101000000-000000000000 + github.com/sirupsen/logrus v1.8.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..3aede04 --- /dev/null +++ b/go.sum @@ -0,0 +1,36 @@ +gitea.difrex.ru/Umbrella/fetcher v0.0.0-20200723122826-e8bbdd12256b h1:K0vLl90b8k+JaCcxoaqbKOfK0LpyTMHQg4a0ggI6HI0= +gitea.difrex.ru/Umbrella/fetcher v0.0.0-20200723122826-e8bbdd12256b/go.mod h1:rcNfqAtzWqj1MsvxDuqTuqTNiJ7r6f1reQvsuUaiHYY= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/idec-net/go-idec v0.0.0-20181106151523-61a006246343/go.mod h1:XUvr43ZLN/4bTZT7TEhJA/rsfFLQxnggX6iU5TGXgIY= +github.com/idec-net/go-idec v0.0.0-20190316125931-ba6681d1b33b h1:QnpZjlk1jtZwZzT8HKMSfFio+L/6QG16uz3zCbPTkLw= +github.com/idec-net/go-idec v0.0.0-20190316125931-ba6681d1b33b/go.mod h1:ST2XOvFc7oRd1FCiZPwYf78F43SV9D3r1S+J4OQMsUo= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/jarcoal/httpmock.v1 v1.0.0-20190304095222-3b6b0a8dbc05 h1:u9qyM/i6c8jhNxsMfz4qdKtZumvEhHWYu5jEeOn1SOA= +gopkg.in/jarcoal/httpmock.v1 v1.0.0-20190304095222-3b6b0a8dbc05/go.mod h1:d3R+NllX3X5e0zlG1Rful3uLvsGC/Q3OHut5464DEQw= diff --git a/main.go b/main.go index df4cd80..d3ab7a5 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,7 @@ import ( "flag" "os" - "gitea.difrex.ru/Umbrella/lessmore/node" + "github.com/idec-net/lessmore-node/node" log "github.com/sirupsen/logrus" ) @@ -22,8 +22,8 @@ var ( func init() { flag.StringVar(&listen, "listen", "127.0.0.1:15582", "Address to listen") flag.StringVar(&es, "es", "http://127.0.0.1:9200", "ES host") - flag.StringVar(&esMessagesIndex, "esindex", "idec3", "ES index") - flag.StringVar(&esMessagesType, "estype", "post", "ES index type") + flag.StringVar(&esMessagesIndex, "esindex", "", "ES index") + flag.StringVar(&esMessagesType, "estype", "", "ES index type") flag.StringVar(&add, "add", "", "User to add") flag.StringVar(&email, "email", "", "User email address") flag.BoolVar(&debug, "debug", false, "Debug output") diff --git a/node/api.go b/node/api.go index 244e08d..3af2103 100644 --- a/node/api.go +++ b/node/api.go @@ -230,6 +230,10 @@ func Serve(listen string, es ESConf) { // Point methods r.HandleFunc("/u/point", es.UPointHandler).Methods("POST") + // Simple and clean SSR UI + ssr := newSSR("./templates", es) + r.HandleFunc("/ssr", ssr.ssrRootHandler) + http.Handle("/", r) srv := http.Server{ diff --git a/node/elastic.go b/node/elastic.go index 25f608a..ed253eb 100644 --- a/node/elastic.go +++ b/node/elastic.go @@ -7,6 +7,7 @@ import ( "net/http" "strconv" "strings" + "time" "fmt" @@ -136,12 +137,6 @@ func (es ESConf) GetEchoMessageHashes(echo string) []string { // GetLimitedEchoMessageHashes ... func (es ESConf) GetLimitedEchoMessageHashes(echo string, offset int, limit int) []string { var hashes []string - var searchURI string - if es.Index != "" && es.Type != "" { - searchURI = strings.Join([]string{es.Host, es.Index, es.Type, "_search"}, "/") - } else { - searchURI = strings.Join([]string{es.Host, "search"}, "/") - } // Check offset var order string @@ -158,7 +153,7 @@ func (es ESConf) GetLimitedEchoMessageHashes(echo string, offset int, limit int) {"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)) + req, err := http.NewRequest("POST", es.searchURI(), bytes.NewBuffer(searchQ)) if err != nil { log.Error(err.Error()) return hashes @@ -375,15 +370,57 @@ func (es ESConf) GetXC(echoes string) []string { return counts } -// GetListTXT ... -func (es ESConf) GetListTXT() []byte { - var searchURI string - if es.Index != "" && es.Type != "" { - searchURI = strings.Join([]string{es.Host, es.Index, "_search"}, "/") - } else { - searchURI = strings.Join([]string{es.Host, "search"}, "/") +func (es ESConf) GetLatestPosts(sum int) []i2es.ESDoc { + query := fmt.Sprintf(`{"sort": [{"date": {"order": "desc"}}, {"_score": {"order": "desc" }}], "size": %d}`, sum) + req, err := http.NewRequest("POST", es.searchURI(), bytes.NewBuffer([]byte(query))) + if err != nil { + log.Error(err.Error()) + return nil } - searchQ := []byte(`{ + req.Header.Add("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + log.Error(err.Error()) + return nil + } + + defer resp.Body.Close() + + var esr ESSearchResp + err = json.NewDecoder(resp.Body).Decode(&esr) + if err != nil { + log.Error(err.Error()) + return nil + } + + var posts []i2es.ESDoc + for _, hit := range esr.Hits.Hits { + hit.Source.Date = parseTime(hit.Source.Date) + hit.Source.Message = strings.Trim(hit.Source.Message, "\n") + posts = append(posts, hit.Source) + } + + return posts +} + +func parseTime(t string) string { + i, err := strconv.ParseInt(t, 10, 64) + if err != nil { + return "" + } + ts := time.Unix(i, 0) + return ts.Format(time.UnixDate) +} + +type echo struct { + Name string + Docs int64 +} + +func (es ESConf) GetEchoesList() []echo { + searchQ := []byte(`{ "size": 0, "aggs": { "uniqueEcho": { @@ -399,12 +436,11 @@ func (es ESConf) GetListTXT() []byte { } } }`) - log.Print("Search URI: ", searchURI) - req, err := http.NewRequest("POST", searchURI, bytes.NewBuffer(searchQ)) + req, err := http.NewRequest("POST", es.searchURI(), bytes.NewBuffer(searchQ)) if err != nil { log.Error(err.Error()) - return []byte("") + return nil } req.Header.Add("Content-Type", "application/json") @@ -412,7 +448,7 @@ func (es ESConf) GetListTXT() []byte { resp, err := client.Do(req) if err != nil { log.Error(err.Error()) - return []byte("") + return nil } defer resp.Body.Close() @@ -421,15 +457,26 @@ func (es ESConf) GetListTXT() []byte { err = json.NewDecoder(resp.Body).Decode(&esr) if err != nil { log.Error(err.Error()) - return []byte("") + return nil } - log.Infof("%+v", esr) - var echoes []string + var echoes []echo for _, bucket := range esr.EchoAgg["echo"].Buckets { - echoes = append(echoes, fmt.Sprintf("%s:%d:", bucket.Key, bucket.DocCount)) + echoes = append(echoes, echo{bucket.Key, int64(bucket.DocCount)}) } - log.Print("Getting ", len(echoes), " echoes") - return []byte(strings.Join(echoes, "\n")) + return echoes +} + +// GetListTXT ... +func (es ESConf) GetListTXT() []byte { + var listTXT []string + echoes := es.GetEchoesList() + for _, echo := range echoes { + listTXT = append(listTXT, fmt.Sprintf("%s:%d:(TODO) description support", echo.Name, echo.Docs)) + } + // Add new line to be more compatible with fetchers + listTXT[len(listTXT)-1] = listTXT[len(listTXT)-1] + "\n" + + return []byte(strings.Join(listTXT, "\n")) } diff --git a/node/go.mod b/node/go.mod new file mode 100644 index 0000000..8f2f76d --- /dev/null +++ b/node/go.mod @@ -0,0 +1,13 @@ +module github.com/idec-net/lessmore-node/node + +go 1.16 + +require ( + gitea.difrex.ru/Umbrella/fetcher v0.0.0-20200723122826-e8bbdd12256b + github.com/google/uuid v1.2.0 // indirect + github.com/gorilla/mux v1.8.0 + github.com/idec-net/go-idec v0.0.0-20190316125931-ba6681d1b33b + github.com/sirupsen/logrus v1.8.1 + golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 + golang.org/x/sys v0.0.0-20210324051608-47abb6519492 // indirect +) diff --git a/node/go.sum b/node/go.sum new file mode 100644 index 0000000..22a2149 --- /dev/null +++ b/node/go.sum @@ -0,0 +1,38 @@ +gitea.difrex.ru/Umbrella/fetcher v0.0.0-20200723122826-e8bbdd12256b h1:K0vLl90b8k+JaCcxoaqbKOfK0LpyTMHQg4a0ggI6HI0= +gitea.difrex.ru/Umbrella/fetcher v0.0.0-20200723122826-e8bbdd12256b/go.mod h1:rcNfqAtzWqj1MsvxDuqTuqTNiJ7r6f1reQvsuUaiHYY= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/idec-net/go-idec v0.0.0-20181106151523-61a006246343/go.mod h1:XUvr43ZLN/4bTZT7TEhJA/rsfFLQxnggX6iU5TGXgIY= +github.com/idec-net/go-idec v0.0.0-20190316125931-ba6681d1b33b h1:QnpZjlk1jtZwZzT8HKMSfFio+L/6QG16uz3zCbPTkLw= +github.com/idec-net/go-idec v0.0.0-20190316125931-ba6681d1b33b/go.mod h1:ST2XOvFc7oRd1FCiZPwYf78F43SV9D3r1S+J4OQMsUo= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/jarcoal/httpmock.v1 v1.0.0-20190304095222-3b6b0a8dbc05 h1:u9qyM/i6c8jhNxsMfz4qdKtZumvEhHWYu5jEeOn1SOA= +gopkg.in/jarcoal/httpmock.v1 v1.0.0-20190304095222-3b6b0a8dbc05/go.mod h1:d3R+NllX3X5e0zlG1Rful3uLvsGC/Q3OHut5464DEQw= diff --git a/node/ssr.go b/node/ssr.go new file mode 100644 index 0000000..eea1dab --- /dev/null +++ b/node/ssr.go @@ -0,0 +1,67 @@ +package node + +import ( + "html/template" + "net/http" + "os" + + "gitea.difrex.ru/Umbrella/fetcher/i2es" + log "github.com/sirupsen/logrus" +) + +type ssr struct { + es ESConf + templatesDir string +} + +func newSSR(templatesDir string, es ESConf) *ssr { + return &ssr{ + es: es, + templatesDir: templatesDir, + } +} + +func (s *ssr) templatePath(name string) string { + return s.templatesDir + string(os.PathSeparator) + name +} + +func (s *ssr) getTemplate(name string) (*template.Template, error) { + t := template.New("root.html") + + tpl, err := t.ParseFiles( + s.templatePath(name+".html"), + s.templatePath("style.html"), + s.templatePath("echoes.html"), + s.templatePath("post.html"), + s.templatePath("latest_posts.html"), + s.templatePath("header.html"), + s.templatePath("footer.html"), + ) + if err != nil { + return nil, err + } + + return tpl, nil +} + +func (s *ssr) ssrRootHandler(w http.ResponseWriter, r *http.Request) { + LogRequest(r) + + tpl, err := s.getTemplate("root") + if err != nil { + log.Error(err) + return + } + + var root struct { + Echoes []echo + CurrentPage string + Posts []i2es.ESDoc + } + root.Echoes = s.es.GetEchoesList() + root.Posts = s.es.GetLatestPosts(100) + + if err := tpl.Execute(w, root); err != nil { + log.Error(err) + } +} diff --git a/node/structs.go b/node/structs.go index 27a79d6..ebeaaf2 100644 --- a/node/structs.go +++ b/node/structs.go @@ -1,6 +1,10 @@ package node -import "gitea.difrex.ru/Umbrella/fetcher/i2es" +import ( + "strings" + + "gitea.difrex.ru/Umbrella/fetcher/i2es" +) // PointRequest with message type PointRequest struct { @@ -11,6 +15,16 @@ type PointRequest struct { // ESConf ... type ESConf i2es.ESConf +// searchURI returns an ElasticSearch search URL string +func (es ESConf) searchURI() (searchURI string) { + if es.Index != "" && es.Type != "" { + searchURI = strings.Join([]string{es.Host, es.Index, es.Type, "_search"}, "/") + } else { + searchURI = strings.Join([]string{es.Host, "search"}, "/") + } + return +} + // Bucket ... type Bucket struct { Key string `json:"key"` diff --git a/templates/echoes.html b/templates/echoes.html new file mode 100644 index 0000000..7f63f53 --- /dev/null +++ b/templates/echoes.html @@ -0,0 +1,22 @@ +{{ define "echoes" }} + +