2017-02-12 13:19:02 +03:00
|
|
|
package node
|
|
|
|
|
|
|
|
import (
|
2018-11-04 16:11:37 +03:00
|
|
|
"fmt"
|
2018-11-06 08:23:15 +03:00
|
|
|
"io/ioutil"
|
2017-02-12 13:19:02 +03:00
|
|
|
"net/http"
|
2017-02-13 14:31:18 +03:00
|
|
|
"strings"
|
2018-11-04 12:05:23 +03:00
|
|
|
|
|
|
|
"github.com/gorilla/mux"
|
2018-11-12 15:06:39 +03:00
|
|
|
log "github.com/sirupsen/logrus"
|
2017-02-12 13:19:02 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// ListTXTHandler ...
|
|
|
|
func (es ESConf) ListTXTHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
2017-02-13 14:31:18 +03:00
|
|
|
LogRequest(r)
|
|
|
|
|
2017-02-13 10:24:21 +03:00
|
|
|
ch := make(chan []byte)
|
2017-02-12 13:19:02 +03:00
|
|
|
// Get echolist
|
2017-02-13 10:24:21 +03:00
|
|
|
go func() {
|
|
|
|
ch <- es.GetListTXT()
|
|
|
|
}()
|
|
|
|
|
|
|
|
echoes := <-ch
|
2017-02-12 13:19:02 +03:00
|
|
|
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write(echoes)
|
|
|
|
}
|
|
|
|
|
2018-11-06 15:53:33 +03:00
|
|
|
func (ed ESConf) BlacklistTXT(w http.ResponseWriter, r *http.Request) {
|
|
|
|
LogRequest(r)
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write([]byte(`KNMUXRTMJA6XWHMB22CD
|
|
|
|
6AKO6DEWYF7EHXWMI2BY
|
|
|
|
qcYj9ceDYjoxt2z6qhzN
|
|
|
|
k1zaEUu1Tg0g97osDeS7
|
|
|
|
j8s7ZMdTzmHzsRJna3xb
|
|
|
|
vuMNfQWe8xonMFPZtOxP
|
|
|
|
bcp6izdkdCj9AXUOP2aT
|
|
|
|
0dIDXSJTLtR8N2KnLTl1
|
|
|
|
2QzNqUiyuoPcPn0l74KP
|
|
|
|
`))
|
|
|
|
}
|
|
|
|
|
2017-02-13 14:31:18 +03:00
|
|
|
// XFeaturesHandler list supported features
|
|
|
|
func XFeaturesHandler(w http.ResponseWriter, r *http.Request) {
|
2018-11-04 16:11:37 +03:00
|
|
|
features := []string{"list.txt", "u/e", "u/m", "x/c"}
|
2017-02-13 14:31:18 +03:00
|
|
|
|
|
|
|
LogRequest(r)
|
|
|
|
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write([]byte(strings.Join(features, "\n")))
|
|
|
|
}
|
|
|
|
|
|
|
|
// EHandler /e/ schema
|
|
|
|
func (es ESConf) EHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
vars := mux.Vars(r)
|
|
|
|
echo := vars["echo"]
|
|
|
|
|
|
|
|
LogRequest(r)
|
|
|
|
|
|
|
|
ch := make(chan []string)
|
|
|
|
// Get echolist
|
|
|
|
go func() {
|
|
|
|
ch <- es.GetEchoMessageHashes(echo)
|
|
|
|
}()
|
|
|
|
|
|
|
|
messages := <-ch
|
|
|
|
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write([]byte(strings.Join(messages, "\n")))
|
|
|
|
}
|
|
|
|
|
2017-02-14 00:05:12 +03:00
|
|
|
// 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)
|
|
|
|
|
|
|
|
// Get echolist
|
2021-04-09 22:04:49 +03:00
|
|
|
messages := es.GetUEchoMessageHashes(e)
|
2017-02-14 00:05:12 +03:00
|
|
|
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write([]byte(strings.Join(messages, "\n")))
|
|
|
|
}
|
|
|
|
|
2018-11-04 12:05:23 +03:00
|
|
|
// UMHandler /u/m/ schema
|
|
|
|
func (es ESConf) UMHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
vars := mux.Vars(r)
|
|
|
|
e := vars["ids"]
|
|
|
|
|
2018-11-06 12:38:38 +03:00
|
|
|
log.Print("/u/m/ vars: ", e)
|
2018-11-04 12:05:23 +03:00
|
|
|
|
|
|
|
LogRequest(r)
|
|
|
|
|
|
|
|
ch := make(chan []string)
|
|
|
|
// Get echolist
|
|
|
|
go func() {
|
|
|
|
ch <- es.GetUMMessages(e)
|
|
|
|
}()
|
|
|
|
|
|
|
|
messages := <-ch
|
|
|
|
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write([]byte(strings.Join(messages, "\n")))
|
|
|
|
}
|
|
|
|
|
2017-02-13 14:56:35 +03:00
|
|
|
// MHandler /m/ schema
|
|
|
|
func (es ESConf) MHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
vars := mux.Vars(r)
|
|
|
|
msgid := vars["msgid"]
|
|
|
|
|
|
|
|
LogRequest(r)
|
|
|
|
|
|
|
|
ch := make(chan []byte)
|
|
|
|
// Get echolist
|
|
|
|
go func() {
|
|
|
|
ch <- es.GetPlainTextMessage(msgid)
|
|
|
|
}()
|
|
|
|
|
|
|
|
message := <-ch
|
|
|
|
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write(message)
|
|
|
|
}
|
|
|
|
|
2018-11-04 12:05:23 +03:00
|
|
|
// XCHandler /x/c schema
|
|
|
|
func (es ESConf) XCHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
vars := mux.Vars(r)
|
|
|
|
echoes := vars["echoes"]
|
|
|
|
|
|
|
|
LogRequest(r)
|
|
|
|
|
|
|
|
ch := make(chan []string)
|
|
|
|
// Get echolist
|
|
|
|
go func() {
|
|
|
|
ch <- es.GetXC(echoes)
|
|
|
|
}()
|
|
|
|
|
|
|
|
counts := <-ch
|
|
|
|
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write([]byte(strings.Join(counts, "\n")))
|
|
|
|
}
|
|
|
|
|
2018-11-04 16:11:37 +03:00
|
|
|
// UPointHandler /u/point scheme
|
|
|
|
func (es ESConf) UPointHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var req PointRequest
|
|
|
|
LogRequest(r)
|
|
|
|
|
2018-11-06 08:23:15 +03:00
|
|
|
// Log request
|
2018-11-06 08:41:04 +03:00
|
|
|
content, err := ioutil.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("Fail to parse POST body: ", err.Error())
|
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write([]byte(fmt.Sprintf("error: %s", err.Error())))
|
|
|
|
return
|
|
|
|
}
|
2018-11-06 08:23:15 +03:00
|
|
|
log.Debugf("Point request is: ", string(content))
|
|
|
|
|
|
|
|
// Get plain POST variables
|
|
|
|
if err := r.ParseForm(); err != nil {
|
|
|
|
log.Error("Fail to parse POST args: ", err.Error())
|
2018-11-06 12:38:38 +03:00
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write([]byte(fmt.Sprintf("error: %s", err.Error())))
|
|
|
|
return
|
2018-11-04 16:11:37 +03:00
|
|
|
}
|
2018-11-06 08:23:15 +03:00
|
|
|
pauth := r.Form.Get("pauth")
|
|
|
|
tmsg := r.Form.Get("tmsg")
|
2018-11-06 08:41:04 +03:00
|
|
|
if pauth == "" && tmsg == "" {
|
|
|
|
log.Debug("Trying parse body request")
|
|
|
|
pauth, tmsg = parsePointBody(string(content))
|
|
|
|
}
|
2018-11-06 08:23:15 +03:00
|
|
|
|
|
|
|
req.Pauth = pauth
|
|
|
|
req.Tmsg = tmsg
|
2018-11-04 16:11:37 +03:00
|
|
|
|
2018-11-06 08:23:15 +03:00
|
|
|
log.Debugf("pauth: %s\ntmsg: %s", pauth, tmsg)
|
|
|
|
|
|
|
|
if pauth == "" {
|
|
|
|
w.WriteHeader(403)
|
2018-11-06 13:57:27 +03:00
|
|
|
w.Write([]byte("auth error"))
|
2018-11-06 08:23:15 +03:00
|
|
|
return
|
|
|
|
}
|
2018-11-04 16:11:37 +03:00
|
|
|
// Authorization check
|
2018-11-05 18:24:46 +03:00
|
|
|
user, ok := es.checkAuth(req)
|
|
|
|
if !ok {
|
2018-11-04 16:11:37 +03:00
|
|
|
w.WriteHeader(403)
|
2018-11-06 13:57:27 +03:00
|
|
|
w.Write([]byte("auth error"))
|
2018-11-04 16:11:37 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Proccess point message
|
2018-11-06 08:23:15 +03:00
|
|
|
if err := es.PointMessage(req, user); err != nil {
|
2018-11-06 12:38:38 +03:00
|
|
|
log.Error("Fail to parse point message: ", err.Error())
|
2018-11-04 16:11:37 +03:00
|
|
|
w.WriteHeader(500)
|
2018-11-06 08:23:15 +03:00
|
|
|
w.Write([]byte(fmt.Sprintf("error: %s", err.Error())))
|
2018-11-04 16:11:37 +03:00
|
|
|
return
|
|
|
|
}
|
2018-11-05 18:24:46 +03:00
|
|
|
|
|
|
|
w.WriteHeader(200)
|
2018-11-06 13:57:27 +03:00
|
|
|
w.Write([]byte("msg ok"))
|
2018-11-04 16:11:37 +03:00
|
|
|
}
|
|
|
|
|
2021-04-02 17:11:12 +03:00
|
|
|
type ServeOpts struct {
|
|
|
|
Listen string
|
|
|
|
TemplatesDir string
|
|
|
|
ServeStatic bool
|
|
|
|
StaticDir string
|
|
|
|
ES ESConf
|
|
|
|
}
|
|
|
|
|
2017-02-12 13:19:02 +03:00
|
|
|
// Serve ...
|
2021-04-02 17:11:12 +03:00
|
|
|
func Serve(opts *ServeOpts) {
|
2017-02-12 13:19:02 +03:00
|
|
|
r := mux.NewRouter()
|
2021-04-02 17:11:12 +03:00
|
|
|
r.HandleFunc("/list.txt", opts.ES.ListTXTHandler).Methods("GET")
|
|
|
|
r.HandleFunc("/blacklist.txt", opts.ES.BlacklistTXT).Methods("GET")
|
2018-11-04 12:05:23 +03:00
|
|
|
r.HandleFunc("/x/features", XFeaturesHandler).Methods("GET")
|
2017-02-13 14:31:18 +03:00
|
|
|
|
|
|
|
// Standart schemas
|
2021-04-02 17:11:12 +03:00
|
|
|
r.HandleFunc("/e/{echo}", opts.ES.EHandler).Methods("GET")
|
|
|
|
r.HandleFunc("/m/{msgid}", opts.ES.MHandler).Methods("GET")
|
2017-02-13 14:31:18 +03:00
|
|
|
|
2017-02-14 00:05:12 +03:00
|
|
|
// Extensions
|
2021-04-02 17:11:12 +03:00
|
|
|
r.HandleFunc("/u/e/{echoes:[a-z0-9-_/.:]+}", opts.ES.UEHandler).Methods("GET")
|
|
|
|
r.HandleFunc("/u/m/{ids:[a-zA-Z0-9-_/.:]+}", opts.ES.UMHandler).Methods("GET")
|
|
|
|
r.HandleFunc("/x/c/{echoes:[a-zA-Z0-9-_/.:]+}", opts.ES.XCHandler).Methods("GET")
|
2017-02-14 00:05:12 +03:00
|
|
|
|
2018-11-04 16:11:37 +03:00
|
|
|
// Point methods
|
2021-04-02 17:11:12 +03:00
|
|
|
r.HandleFunc("/u/point", opts.ES.UPointHandler).Methods("POST")
|
2018-11-04 16:11:37 +03:00
|
|
|
|
2021-03-25 18:11:00 +03:00
|
|
|
// Simple and clean SSR UI
|
2021-04-02 17:11:12 +03:00
|
|
|
ssr := newSSR(opts.TemplatesDir, opts.ES)
|
2021-03-25 18:25:40 +03:00
|
|
|
r.HandleFunc("/", ssr.ssrRootHandler)
|
2021-04-02 18:03:28 +03:00
|
|
|
// Forum
|
2021-04-02 17:11:12 +03:00
|
|
|
r.HandleFunc("/forum/page/{page:[0-9]+}", ssr.ssrForumHandler)
|
2021-04-02 18:03:28 +03:00
|
|
|
// Echo
|
2021-03-30 19:47:25 +03:00
|
|
|
r.HandleFunc("/echo/{echo:[a-z0-9-_.]+}/page/{page:[0-9]+}", ssr.echoViewHandler)
|
2021-04-02 18:03:28 +03:00
|
|
|
// Thread
|
2021-03-30 19:47:25 +03:00
|
|
|
r.HandleFunc("/thread/{topicid:[a-z0-9-]+}", ssr.threadViewHandler)
|
2021-04-02 18:03:28 +03:00
|
|
|
// Single message
|
2021-03-30 19:47:25 +03:00
|
|
|
r.HandleFunc("/msg/{msgid:[a-zA-Z0-9]{20}}", ssr.singleMessageHandler)
|
2021-04-02 18:03:28 +03:00
|
|
|
// Search
|
2021-03-30 19:47:25 +03:00
|
|
|
r.HandleFunc("/find", ssr.searchHandler).Methods(http.MethodGet)
|
2021-04-02 18:03:28 +03:00
|
|
|
// Docs
|
|
|
|
// formatting
|
|
|
|
r.HandleFunc("/docs/formatting", ssr.docsFormattingHandler)
|
2021-03-25 18:11:00 +03:00
|
|
|
|
2021-04-02 17:11:12 +03:00
|
|
|
if opts.ServeStatic {
|
|
|
|
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(opts.StaticDir))))
|
|
|
|
}
|
|
|
|
|
2017-02-13 14:31:18 +03:00
|
|
|
http.Handle("/", r)
|
2017-02-12 13:19:02 +03:00
|
|
|
|
|
|
|
srv := http.Server{
|
2021-03-25 18:25:40 +03:00
|
|
|
Handler: r,
|
2021-04-02 17:11:12 +03:00
|
|
|
Addr: opts.Listen,
|
2021-03-25 18:25:40 +03:00
|
|
|
// WriteTimeout: 15 * time.Second,
|
|
|
|
// ReadTimeout: 15 * time.Second,
|
2017-02-12 13:19:02 +03:00
|
|
|
}
|
|
|
|
|
2021-04-02 17:11:12 +03:00
|
|
|
log.Print("Listening IDEC API on ", opts.Listen)
|
2017-02-12 13:19:02 +03:00
|
|
|
log.Fatal(srv.ListenAndServe())
|
|
|
|
}
|