repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

pico / feeds
Eric Bower · 29 Aug 24

api.go

  1package feeds
  2
  3import (
  4	"fmt"
  5	"net/http"
  6	"net/url"
  7	"time"
  8
  9	"github.com/picosh/pico/db/postgres"
 10	"github.com/picosh/pico/shared"
 11	"github.com/picosh/pico/shared/storage"
 12)
 13
 14func createStaticRoutes() []shared.Route {
 15	return []shared.Route{
 16		shared.NewRoute("GET", "/main.css", shared.ServeFile("main.css", "text/css")),
 17		shared.NewRoute("GET", "/card.png", shared.ServeFile("card.png", "image/png")),
 18		shared.NewRoute("GET", "/favicon-16x16.png", shared.ServeFile("favicon-16x16.png", "image/png")),
 19		shared.NewRoute("GET", "/favicon-32x32.png", shared.ServeFile("favicon-32x32.png", "image/png")),
 20		shared.NewRoute("GET", "/apple-touch-icon.png", shared.ServeFile("apple-touch-icon.png", "image/png")),
 21		shared.NewRoute("GET", "/favicon.ico", shared.ServeFile("favicon.ico", "image/x-icon")),
 22		shared.NewRoute("GET", "/robots.txt", shared.ServeFile("robots.txt", "text/plain")),
 23	}
 24}
 25
 26func keepAliveHandler(w http.ResponseWriter, r *http.Request) {
 27	dbpool := shared.GetDB(r)
 28	logger := shared.GetLogger(r)
 29	postID, _ := url.PathUnescape(shared.GetField(r, 0))
 30
 31	post, err := dbpool.FindPost(postID)
 32	if err != nil {
 33		logger.Info("post not found")
 34		http.Error(w, "post not found", http.StatusNotFound)
 35		return
 36	}
 37
 38	now := time.Now()
 39	expiresAt := now.AddDate(0, 3, 0)
 40	post.ExpiresAt = &expiresAt
 41	_, err = dbpool.UpdatePost(post)
 42	if err != nil {
 43		logger.Error("could not update post", "err", err.Error())
 44		http.Error(w, "server error", 500)
 45		return
 46	}
 47
 48	w.Header().Add("Content-Type", "text/plain")
 49
 50	txt := fmt.Sprintf(
 51		"Success! This feed will stay active until %s or by clicking the link in your digest email again",
 52		time.Now(),
 53	)
 54	_, err = w.Write([]byte(txt))
 55	if err != nil {
 56		logger.Error("could not write to writer", "err", err.Error())
 57		http.Error(w, "server error", 500)
 58	}
 59}
 60
 61func createMainRoutes(staticRoutes []shared.Route) []shared.Route {
 62	routes := []shared.Route{
 63		shared.NewRoute("GET", "/", shared.CreatePageHandler("html/marketing.page.tmpl")),
 64		shared.NewRoute("GET", "/keep-alive/(.+)", keepAliveHandler),
 65	}
 66
 67	routes = append(
 68		routes,
 69		staticRoutes...,
 70	)
 71
 72	return routes
 73}
 74
 75func StartApiServer() {
 76	cfg := NewConfigSite()
 77	db := postgres.NewDB(cfg.DbURL, cfg.Logger)
 78	defer db.Close()
 79	logger := cfg.Logger
 80
 81	var st storage.StorageServe
 82	var err error
 83	if cfg.MinioURL == "" {
 84		st, err = storage.NewStorageFS(cfg.StorageDir)
 85	} else {
 86		st, err = storage.NewStorageMinio(cfg.MinioURL, cfg.MinioUser, cfg.MinioPass)
 87	}
 88
 89	if err != nil {
 90		logger.Error(err.Error())
 91	}
 92
 93	// cron daily digest
 94	fetcher := NewFetcher(db, cfg)
 95	go fetcher.Loop()
 96
 97	staticRoutes := createStaticRoutes()
 98
 99	if cfg.Debug {
100		staticRoutes = shared.CreatePProfRoutes(staticRoutes)
101	}
102
103	mainRoutes := createMainRoutes(staticRoutes)
104
105	apiConfig := &shared.ApiConfig{
106		Cfg:     cfg,
107		Dbpool:  db,
108		Storage: st,
109	}
110	handler := shared.CreateServe(mainRoutes, []shared.Route{}, apiConfig)
111	router := http.HandlerFunc(handler)
112
113	portStr := fmt.Sprintf(":%s", cfg.Port)
114	logger.Info(
115		"Starting server on port",
116		"port", cfg.Port,
117		"domain", cfg.Domain,
118	)
119
120	logger.Error(http.ListenAndServe(portStr, router).Error())
121}