package main import ( "encoding/json" "fmt" "log" "strconv" "strings" "github.com/fasthttp/router" "github.com/valyala/fasthttp" "github.com/xujiajun/nutsdb" ) func RunWebserv() { r := router.New() r.GET("/", Start) r.GET("/api/season", Season) r.GET("/api/watch/{user?}", WatchGet) r.POST("/api/register", Register) r.POST("/api/watch/{user}", WatchPost) r.DELETE("/api/watch/{user}", WatchDelete) log.Fatal(fasthttp.ListenAndServe(":"+strconv.Itoa(*webServerPort), r.Handler)) } func Start(ctx *fasthttp.RequestCtx) { season, err := GetSeasonCache() if err != nil { addErrorToCtx(ctx, err) return } WriteIndex(ctx, season) ctx.SetContentType("text/html; charset=utf-8") ctx.SetStatusCode(fasthttp.StatusOK) } func Season(ctx *fasthttp.RequestCtx) { data, err := cache.Get(seasonApiJikan) if err != nil { addErrorToCtx(ctx, err) return } err = writeResponseBody(ctx, data) if err != nil { addErrorToCtx(ctx, err) return } } func WatchGet(ctx *fasthttp.RequestCtx) { usrVal := ctx.UserValue("user") var userId int64 if usrVal != nil { // check user exists user, err := ReadUser(fmt.Sprintf("%s", usrVal)) if err != nil { ctx.WriteString("Dich gibts nicht") ctx.SetStatusCode(fasthttp.StatusNotFound) return } userId = user.MalID } animes, err := ReadAnimes() if err != nil { // check if no anime were inserted if err != nutsdb.ErrBucketEmpty { addErrorToCtx(ctx, err) return } animes = make([]Anime, 0) } // apply single user logic if usrVal != nil { filteredAnimes := make([]Anime, 0) for _, a := range animes { for _, u := range a.Users { if u.MalID == userId { filteredAnimes = append(filteredAnimes, a) break } } } animes = filteredAnimes } bytes, err := json.Marshal(animes) if err != nil { addErrorToCtx(ctx, err) return } _, err = ctx.Write(bytes) if err != nil { addErrorToCtx(ctx, err) return } ctx.SetContentType("application/json; charset=utf-8") ctx.SetStatusCode(fasthttp.StatusOK) } func Register(ctx *fasthttp.RequestCtx) { if string(ctx.Request.Header.ContentType()) != "application/json" { ctx.SetStatusCode(fasthttp.StatusBadRequest) return } body := ctx.PostBody() var register RegisterData err := json.Unmarshal(body, ®ister) if err != nil { ctx.WriteString(err.Error()) ctx.SetStatusCode(fasthttp.StatusBadRequest) return } if register.MalID == 0 || register.Username == "" || register.Secret == "" || register.Sauce == "" { ctx.WriteString("Sprich JSON du Hurensohn") ctx.SetStatusCode(fasthttp.StatusBadRequest) return } calcSauce := Sauce(register.MalID, register.Username) if calcSauce != strings.ToLower(register.Sauce) { ctx.WriteString("Möge die Sauce mit dir sein") ctx.SetStatusCode(fasthttp.StatusBadRequest) return } // check user exists _, err = ReadUser(register.Username) if err == nil { ctx.WriteString("Nicht drängeln") ctx.SetStatusCode(fasthttp.StatusConflict) return } // check user legit userData, _, err := GetUserData(register.Username) if err != nil { ctx.WriteString(err.Error()) ctx.SetStatusCode(fasthttp.StatusExpectationFailed) return } if userData.Data.MalID != register.MalID { ctx.WriteString("Dich gibts nicht auf MAL") ctx.SetStatusCode(fasthttp.StatusExpectationFailed) return } // REGISTER user := UserData{ Username: register.Username, MalID: register.MalID, Secret: register.Secret, } err = SaveUser(&user) if err != nil { addErrorToCtx(ctx, err) return } ctx.SetBody(body) ctx.SetStatusCode(fasthttp.StatusOK) } func WatchPost(ctx *fasthttp.RequestCtx) { auth := ctx.Request.Header.Peek("X-HUSO-AUTH") if ctx.UserValue("user") == nil || auth == nil || string(auth) == "" || string(ctx.Request.Header.ContentType()) != "application/json" { ctx.SetStatusCode(fasthttp.StatusBadRequest) return } username := fmt.Sprintf("%s", ctx.UserValue("user")) legit, userId := GheddoAuth(username, string(auth)) if !legit { ctx.SetStatusCode(fasthttp.StatusUnauthorized) return } body := ctx.PostBody() var animes []Anime err := json.Unmarshal(body, &animes) if err != nil || len(animes) == 0 { ctx.WriteString(err.Error()) ctx.SetStatusCode(fasthttp.StatusBadRequest) return } // iterate sent animes for _, anime := range animes { // check if anime is in season _, err = SearchSeason(anime.Anime) if err == nil { // anime exitsts => save animeData, err := AddUserToAnime(username, userId, anime.Anime) if err != nil { addErrorToCtx(ctx, err) return } anime.Users = animeData.Users fmt.Printf("%+v\n", anime) } // TODO detail, _, err := GetAnimeDetailData(anime.Anime) if err != nil { ctx.WriteString(err.Error()) ctx.SetStatusCode(fasthttp.StatusNotFound) return } fmt.Printf("%+v\n", detail) data, err := json.Marshal(animes) if err != nil { addErrorToCtx(ctx, err) return } err = writeResponseBody(ctx, data) if err != nil { addErrorToCtx(ctx, err) return } } } func WatchDelete(ctx *fasthttp.RequestCtx) { auth := ctx.Request.Header.Peek("X-HUSO-AUTH") if ctx.UserValue("user") == nil || auth == nil || string(auth) == "" || string(ctx.Request.Header.ContentType()) != "application/json" { ctx.SetStatusCode(fasthttp.StatusBadRequest) return } username := fmt.Sprintf("%s", ctx.UserValue("user")) legit, userId := GheddoAuth(username, string(auth)) if !legit { ctx.SetStatusCode(fasthttp.StatusUnauthorized) return } // TODO fmt.Printf("%+v\n", userId) } func GheddoAuth(username, auth string) (bool, int64) { user, err := ReadUser(username) if err != nil { return false, 0 } return user.Secret == auth, user.MalID } func writeResponseBody(ctx *fasthttp.RequestCtx, bytes []byte) error { _, err := ctx.Write(bytes) if err != nil { return err } ctx.SetContentType("application/json; charset=utf-8") ctx.SetStatusCode(fasthttp.StatusOK) return err } func addErrorToCtx(ctx *fasthttp.RequestCtx, err error) { ctx.WriteString(err.Error()) ctx.SetStatusCode(fasthttp.StatusInternalServerError) }