gostart/handlers.go

407 lines
10 KiB
Go
Raw Normal View History

2022-11-29 19:55:00 -07:00
package main
import (
2022-12-05 15:45:39 -07:00
"bytes"
2022-11-29 19:55:00 -07:00
"context"
"encoding/json"
"fmt"
2022-12-05 15:45:39 -07:00
"image"
"image/color"
"image/png"
2024-05-11 14:24:49 -06:00
"log"
2022-11-29 19:55:00 -07:00
"net/http"
"strconv"
2022-12-05 15:45:39 -07:00
"unicode"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"golang.org/x/image/font"
"golang.org/x/image/font/basicfont"
"golang.org/x/image/math/fixed"
"suah.dev/gostart/data"
2022-11-29 19:55:00 -07:00
)
2022-12-02 20:53:05 -07:00
// TODO: make this more generic.
2022-12-05 19:43:38 -07:00
type ctxKey string
func (c ctxKey) String() string {
return string(c)
}
const ownerKey = ctxKey("ownerid")
2022-11-29 19:55:00 -07:00
func OwnerCtx(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
owner, err := app.getOwner(r)
if err != nil {
http.Error(w, err.Error(), http.StatusUnauthorized)
return
}
ownerID := int64(owner.ID)
2022-12-05 19:43:38 -07:00
ctx := context.WithValue(r.Context(), ownerKey, ownerID)
2022-11-29 19:55:00 -07:00
next.ServeHTTP(w, r.WithContext(ctx))
})
}
2022-12-05 20:45:42 -07:00
func IconCacher(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=604800")
next.ServeHTTP(w, r)
})
}
2022-12-02 20:53:05 -07:00
func iconGET(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
2022-12-24 05:50:23 -07:00
/*
ownerID, ok := ctx.Value(ownerKey).(int64)
if !ok {
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
return
}
*/
2022-12-02 20:53:05 -07:00
linkID, err := strconv.Atoi(chi.URLParam(r, "linkID"))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
2022-12-05 15:45:39 -07:00
return
}
link, err := app.queries.GetLinkByID(ctx, int64(linkID))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
2022-12-02 20:53:05 -07:00
}
2022-12-24 05:50:23 -07:00
icon, err := app.queries.GetIconByLinkID(ctx, int64(linkID))
2022-12-05 15:45:39 -07:00
if err != nil {
size := 24
img := image.NewRGBA(image.Rect(0, 0, size, size))
2022-12-21 19:27:32 -07:00
co := color.RGBA{A: 255}
2022-12-05 15:45:39 -07:00
point := fixed.Point26_6{
2022-12-21 19:27:32 -07:00
X: fixed.I(size/2 - basicfont.Face7x13.Width),
Y: fixed.I(size / 2),
2022-12-05 15:45:39 -07:00
}
d := &font.Drawer{
Dst: img,
Src: image.NewUniform(co),
Face: basicfont.Face7x13,
Dot: point,
}
r := []rune(link.Name)
l := string(unicode.ToUpper(r[0]))
d.DrawString(l)
buf := new(bytes.Buffer)
if err := png.Encode(buf, img); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else {
icon.Data = buf.Bytes()
icon.ContentType = "image/png"
}
}
2022-12-02 20:53:05 -07:00
w.Header().Add("Content-type", icon.ContentType)
w.WriteHeader(200)
2022-12-05 19:43:38 -07:00
_, _ = w.Write(icon.Data)
2022-12-02 20:53:05 -07:00
}
2022-11-29 19:55:00 -07:00
func watchitemGET(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-11-29 19:55:00 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-11-29 19:55:00 -07:00
return
}
2023-04-23 19:12:26 -06:00
watches := app.watches.forID(ownerID)
2022-11-29 19:55:00 -07:00
wJson, err := json.Marshal(watches)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Add("Content-type", "application/json")
w.WriteHeader(200)
_, err = w.Write(wJson)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
2022-12-02 20:53:05 -07:00
func watchitemDELETE(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-12-02 20:53:05 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-12-02 20:53:05 -07:00
return
}
watchID, err := strconv.Atoi(chi.URLParam(r, "watchID"))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
2024-05-11 14:24:49 -06:00
err = app.queries.DeleteWatchItem(ctx, data.DeleteWatchItemParams{ID: int64(watchID), OwnerID: ownerID})
2022-12-02 20:53:05 -07:00
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
2023-06-07 11:57:17 -06:00
app.removeWatch(watchID)
2022-12-02 20:53:05 -07:00
}
func watchitemPOST(w http.ResponseWriter, r *http.Request) {
d := &data.AddWatchItemParams{}
if err := render.Decode(r, d); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-12-02 20:53:05 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-12-02 20:53:05 -07:00
return
}
d.OwnerID = ownerID
2024-05-11 14:24:49 -06:00
_, err := app.queries.AddWatchItem(ctx, *d)
2022-12-02 20:53:05 -07:00
if err != nil {
2022-12-05 19:43:38 -07:00
http.Error(w, err.Error(), http.StatusUnprocessableEntity)
2022-12-02 20:53:05 -07:00
return
}
}
2022-11-29 19:55:00 -07:00
func pullrequestsPOST(w http.ResponseWriter, r *http.Request) {
2022-12-02 20:53:05 -07:00
d := &data.AddPullRequestParams{}
if err := render.Decode(r, d); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-12-02 20:53:05 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-12-02 20:53:05 -07:00
return
}
d.OwnerID = ownerID
2024-05-11 14:24:49 -06:00
_, err := app.queries.AddPullRequest(ctx, *d)
2022-12-02 20:53:05 -07:00
if err != nil {
2022-12-05 19:43:38 -07:00
http.Error(w, err.Error(), http.StatusUnprocessableEntity)
2022-12-02 20:53:05 -07:00
return
}
2022-11-29 19:55:00 -07:00
}
func pullrequestsDELETE(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-11-29 19:55:00 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-11-29 19:55:00 -07:00
return
}
prID, err := strconv.Atoi(chi.URLParam(r, "prID"))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
2024-05-11 14:24:49 -06:00
err = app.queries.DeletePullRequest(ctx, data.DeletePullRequestParams{ID: int64(prID), OwnerID: ownerID})
2022-11-29 19:55:00 -07:00
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func pullrequestsGET(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-11-29 19:55:00 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-11-29 19:55:00 -07:00
return
}
2024-05-11 14:24:49 -06:00
prs, err := app.queries.GetAllPullRequests(ctx, ownerID)
2022-11-29 19:55:00 -07:00
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
prJson, err := json.Marshal(prs)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Add("Content-type", "application/json")
w.WriteHeader(200)
_, err = w.Write(prJson)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func linksGET(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-11-29 19:55:00 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-11-29 19:55:00 -07:00
return
}
owner, err := app.queries.GetOwner(ctx, ownerID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
2024-05-11 14:24:49 -06:00
links, err := app.queries.GetAllLinksForOwner(ctx, ownerID)
2022-11-29 19:55:00 -07:00
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
filteredLinks := []data.Link{}
for _, l := range links {
if !owner.ShowShared && l.OwnerID != ownerID {
continue
}
filteredLinks = append(filteredLinks, l)
}
linksJson, err := json.Marshal(filteredLinks)
2022-11-29 19:55:00 -07:00
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Add("Content-type", "application/json")
w.WriteHeader(200)
_, err = w.Write(linksJson)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func linksPOST(w http.ResponseWriter, r *http.Request) {
d := &data.AddLinkParams{}
if err := render.Decode(r, d); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-11-29 19:55:00 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-11-29 19:55:00 -07:00
return
}
d.OwnerID = ownerID
2024-05-11 14:24:49 -06:00
_, err := app.queries.AddLink(ctx, *d)
2022-11-29 19:55:00 -07:00
if err != nil {
2022-12-05 19:43:38 -07:00
http.Error(w, err.Error(), http.StatusInternalServerError)
2022-11-29 19:55:00 -07:00
return
}
}
func prignoreGET(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ownerID, ok := ctx.Value(ownerKey).(int64)
if !ok {
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
return
}
2024-05-11 14:24:49 -06:00
prIgnores, err := app.queries.GetAllPullRequestIgnores(ctx, ownerID)
if err != nil {
2024-05-11 14:24:49 -06:00
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
prJson, err := json.Marshal(prIgnores)
if err != nil {
2024-05-11 14:24:49 -06:00
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Add("Content-type", "application/json")
w.WriteHeader(200)
_, err = w.Write(prJson)
if err != nil {
2024-05-11 14:24:49 -06:00
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func prignoreDELETE(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ownerID, ok := ctx.Value(ownerKey).(int64)
if !ok {
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
return
}
ignoreID, err := strconv.Atoi(chi.URLParam(r, "ignoreID"))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
2024-05-11 14:24:49 -06:00
err = app.queries.DeleteIgnore(ctx, data.DeleteIgnoreParams{ID: int64(ignoreID), OwnerID: ownerID})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
2022-12-04 19:03:59 -07:00
func prignorePOST(w http.ResponseWriter, r *http.Request) {
d := &data.AddPullRequestIgnoreParams{}
if err := render.Decode(r, d); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-12-04 19:03:59 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-12-04 19:03:59 -07:00
return
}
d.OwnerID = ownerID
2024-05-11 14:24:49 -06:00
_, err := app.queries.AddPullRequestIgnore(ctx, *d)
2022-12-04 19:03:59 -07:00
if err != nil {
2022-12-05 19:43:38 -07:00
http.Error(w, err.Error(), http.StatusInternalServerError)
2022-12-04 19:03:59 -07:00
return
}
}
2022-12-02 20:53:05 -07:00
func linkDELETE(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
2022-12-05 19:43:38 -07:00
ownerID, ok := ctx.Value(ownerKey).(int64)
2022-12-02 20:53:05 -07:00
if !ok {
2022-12-05 19:43:38 -07:00
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
2022-12-02 20:53:05 -07:00
return
}
linkID, err := strconv.Atoi(chi.URLParam(r, "linkID"))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
2024-05-11 14:24:49 -06:00
err = app.queries.DeleteLink(ctx, data.DeleteLinkParams{ID: int64(linkID), OwnerID: ownerID})
2022-12-02 20:53:05 -07:00
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func linkGET(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ownerID, ok := ctx.Value(ownerKey).(int64)
if !ok {
http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
return
}
linkID, err := strconv.Atoi(chi.URLParam(r, "linkID"))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
link, err := app.queries.IncrementLink(ctx, data.IncrementLinkParams{ID: int64(linkID), OwnerID: ownerID})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
fmt.Fprintf(w, "%s", link.Url)
}