aboutsummaryrefslogblamecommitdiffstats
path: root/web/web.go
blob: 794a3d701a241313e7cbe54e1bc97f2a3f95d89f (plain) (tree)


































































































































                                                                                       
package web

import (
	"encoding/json"
	"github.com/abbot/go-http-auth"
	"log"
	"neko/config"
	"neko/models/feed"
	"neko/models/item"
	"net/http"
	"strconv"
)

func indexHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "static/ui.html")
}

func streamHandler(w http.ResponseWriter, r *http.Request) {

	max_id := 0
	if r.FormValue("max_id") != "" {
		max_id, _ = strconv.Atoi(r.FormValue("max_id"))
	}

	feed_id := int64(0)
	if r.FormValue("feed_url") != "" {
		feed_url := r.FormValue("feed_url")
		var f feed.Feed
		f.ByUrl(feed_url)
		feed_id = f.Id
	}

	unread_only := true
	if r.FormValue("read_filter") != "" {
		unread_only = false
	}

	var items []*item.Item
	items, err := item.Filter(int64(max_id), feed_id, unread_only)
	if err != nil {
		log.Println(err)
	}

	w.Header().Set("Content-Type", "application/json")
	js, _ := json.Marshal(items)
	w.Write(js)
}

func itemHandler(w http.ResponseWriter, r *http.Request) {
	var i item.Item
	err := json.NewDecoder(r.Body).Decode(&i)
	if err != nil {
		log.Println(err)
	} else {
		i.Save()
	}
	defer r.Body.Close()
}

func feedHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		feeds, err := feed.All()
		if err != nil {
			log.Println(err)
		}

		js, err := json.Marshal(feeds)
		if err != nil {
			log.Println(err)
		}
		w.Write(js)
		return
	}

	var f feed.Feed
	err := json.NewDecoder(r.Body).Decode(&f)
	if err != nil {
		log.Println(err)
	}

	switch r.Method {
	case "POST":
		feed.NewFeed(f.Url)
	case "PUT":
		f.Update()
	case "DELETE":
		feed_id, err := strconv.Atoi(r.URL.Path[len("/feed/"):])
		if err != nil {
			log.Println(err)
			return
		}
		f.Id = int64(feed_id)
		f.Delete()
	}
}

func Secret(user, realm string) string {
	if user == config.Config.Username {
		return config.Config.DigestPassword
	}
	return ""
}

func AuthWrap(a *auth.DigestAuth, wrapped http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if username, authinfo := a.CheckAuth(r); username == "" {
			a.RequireAuth(w, r)
		} else {
			_ = &auth.AuthenticatedRequest{Request: *r, Username: username}
			if authinfo != nil {
				w.Header().Set(a.Headers.V().AuthInfo, *authinfo)
			}
			wrapped(w, r)
		}
	}
}

func Serve() {
	authenticator := auth.NewDigestAuthenticator(config.Config.Realm, Secret)
	authenticator.PlainTextSecrets = true

	fs := http.FileServer(http.Dir("static"))
	http.Handle("/static/", http.StripPrefix("/static/", fs))

	http.HandleFunc("/stream/", AuthWrap(authenticator, streamHandler))
	http.HandleFunc("/item/", AuthWrap(authenticator, itemHandler))
	http.HandleFunc("/feed/", AuthWrap(authenticator, feedHandler))
	http.HandleFunc("/", AuthWrap(authenticator, indexHandler))

	log.Fatal(http.ListenAndServe(config.Config.WebServer, nil))
}