This commit is contained in:
daru
2022-04-15 01:26:18 +02:00
parent 9dfe6424c8
commit ea49d83475
6 changed files with 160 additions and 45 deletions

View File

@@ -27,7 +27,7 @@ const (
malApiStatusD = "dropped" malApiStatusD = "dropped"
bucketUsers = "users" bucketUsers = "users"
bucketAnime = "anime" bucketAnime = "anime"
bucketmedia = "media" bucketMedia = "media"
) )
var ( var (

View File

@@ -2,15 +2,26 @@ package main
import "time" import "time"
type Anime struct {
Anime int64 `json:"anime"`
Users []WatchUser `json:"users"`
}
type WatchUser struct {
Username string `json:"username"`
MalID int64 `json:"malId"`
Progress int `json:"progress"`
}
type UserData struct { type UserData struct {
Username string `json:"username"` Username string `json:"username"`
MalId int `json:"malId"` MalID int64 `json:"malId"`
Secret string `json:"secret"` Secret string `json:"secret"`
} }
type RegisterData struct { type RegisterData struct {
Username string `json:"username"` Username string `json:"username"`
MalId int `json:"malId"` MalID int64 `json:"malId"`
Secret string `json:"secret"` Secret string `json:"secret"`
Sauce string `json:"sauce"` Sauce string `json:"sauce"`
} }
@@ -18,7 +29,7 @@ type RegisterData struct {
type AnimeListMal struct { type AnimeListMal struct {
Data []struct { Data []struct {
Node struct { Node struct {
ID int `json:"id"` ID int64 `json:"id"`
Title string `json:"title"` Title string `json:"title"`
MainPicture struct { MainPicture struct {
Medium string `json:"medium"` Medium string `json:"medium"`
@@ -33,7 +44,7 @@ type AnimeListMal struct {
type UserJikan struct { type UserJikan struct {
Data struct { Data struct {
MalID int `json:"mal_id"` MalID int64 `json:"mal_id"`
Username string `json:"username"` Username string `json:"username"`
URL string `json:"url"` URL string `json:"url"`
Images struct { Images struct {
@@ -45,8 +56,8 @@ type UserJikan struct {
} `json:"webp"` } `json:"webp"`
} `json:"images"` } `json:"images"`
LastOnline time.Time `json:"last_online"` LastOnline time.Time `json:"last_online"`
Gender interface{} `json:"gender"` Gender string `json:"gender"`
Birthday interface{} `json:"birthday"` Birthday time.Time `json:"birthday"`
Location string `json:"location"` Location string `json:"location"`
Joined time.Time `json:"joined"` Joined time.Time `json:"joined"`
} `json:"data"` } `json:"data"`
@@ -55,7 +66,7 @@ type UserJikan struct {
type SeasonMal struct { type SeasonMal struct {
Data []struct { Data []struct {
Node struct { Node struct {
ID int `json:"id"` ID int64 `json:"id"`
Title string `json:"title"` Title string `json:"title"`
MainPicture struct { MainPicture struct {
Medium string `json:"medium"` Medium string `json:"medium"`
@@ -84,7 +95,7 @@ type SeasonJikan struct {
} `json:"items"` } `json:"items"`
} `json:"pagination"` } `json:"pagination"`
Data []struct { Data []struct {
MalID int `json:"mal_id"` MalID int64 `json:"mal_id"`
URL string `json:"url"` URL string `json:"url"`
Images struct { Images struct {
Jpg struct { Jpg struct {
@@ -121,7 +132,7 @@ type SeasonJikan struct {
Airing bool `json:"airing"` Airing bool `json:"airing"`
Aired struct { Aired struct {
From time.Time `json:"from"` From time.Time `json:"from"`
To interface{} `json:"to"` To time.Time `json:"to"`
Prop struct { Prop struct {
From struct { From struct {
Day int `json:"day"` Day int `json:"day"`
@@ -129,9 +140,9 @@ type SeasonJikan struct {
Year int `json:"year"` Year int `json:"year"`
} `json:"from"` } `json:"from"`
To struct { To struct {
Day interface{} `json:"day"` Day int `json:"day"`
Month interface{} `json:"month"` Month int `json:"month"`
Year interface{} `json:"year"` Year int `json:"year"`
} `json:"to"` } `json:"to"`
} `json:"prop"` } `json:"prop"`
String string `json:"string"` String string `json:"string"`
@@ -145,7 +156,7 @@ type SeasonJikan struct {
Members int `json:"members"` Members int `json:"members"`
Favorites int `json:"favorites"` Favorites int `json:"favorites"`
Synopsis string `json:"synopsis"` Synopsis string `json:"synopsis"`
Background interface{} `json:"background"` Background string `json:"background"`
Season string `json:"season"` Season string `json:"season"`
Year int `json:"year"` Year int `json:"year"`
Broadcast struct { Broadcast struct {
@@ -160,7 +171,12 @@ type SeasonJikan struct {
Name string `json:"name"` Name string `json:"name"`
URL string `json:"url"` URL string `json:"url"`
} `json:"producers"` } `json:"producers"`
Licensors []interface{} `json:"licensors"` Licensors []struct {
MalID int `json:"mal_id"`
Type string `json:"type"`
Name string `json:"name"`
URL string `json:"url"`
} `json:"licensors"`
Studios []struct { Studios []struct {
MalID int `json:"mal_id"` MalID int `json:"mal_id"`
Type string `json:"type"` Type string `json:"type"`
@@ -180,6 +196,11 @@ type SeasonJikan struct {
Name string `json:"name"` Name string `json:"name"`
URL string `json:"url"` URL string `json:"url"`
} `json:"themes"` } `json:"themes"`
Demographics []interface{} `json:"demographics"` Demographics []struct {
MalID int `json:"mal_id"`
Type string `json:"type"`
Name string `json:"name"`
URL string `json:"url"`
} `json:"demographics"`
} `json:"data"` } `json:"data"`
} }

44
nuss.go
View File

@@ -1,8 +1,10 @@
package main package main
import ( import (
"encoding/binary"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"github.com/xujiajun/nutsdb" "github.com/xujiajun/nutsdb"
) )
@@ -29,21 +31,52 @@ func SaveUser(user *UserData) error {
return err return err
} }
func ReadAnimes() ([]Anime, error) {
var animes []Anime
err := db.View(
func(tx *nutsdb.Tx) error {
entries, err := tx.GetAll(bucketAnime)
if err != nil {
return err
}
animes = make([]Anime, len(entries))
// iterate entries
for _, entry := range entries {
// decode anime list
malId, c := binary.Varint(entry.Key)
if c <= 0 {
return fmt.Errorf("int64 decode error: %s %s", entry.Key, entry.Value)
}
// parse user list
var users []WatchUser
err = json.Unmarshal(entry.Value, &users)
if err != nil {
return err
}
anime := Anime{
Anime: malId,
Users: users,
}
animes = append(animes, anime)
}
return nil
})
return animes, err
}
func DbClean() error { func DbClean() error {
err := db.Update( return db.Update(
func(tx *nutsdb.Tx) error { func(tx *nutsdb.Tx) error {
return db.Merge() return db.Merge()
}) })
return err
} }
func DbSave(bucket, key string, val []byte) error { func DbSave(bucket, key string, val []byte) error {
err := db.Update( return db.Update(
func(tx *nutsdb.Tx) error { func(tx *nutsdb.Tx) error {
keyBytes := []byte(key) keyBytes := []byte(key)
return tx.Put(bucket, keyBytes, val, nutsdb.Persistent) return tx.Put(bucket, keyBytes, val, nutsdb.Persistent)
}) })
return err
} }
func DbRead(bucket, key string) ([]byte, error) { func DbRead(bucket, key string) ([]byte, error) {
@@ -63,10 +96,9 @@ func DbRead(bucket, key string) ([]byte, error) {
} }
func DbDelete(bucket, key string, val []byte) error { func DbDelete(bucket, key string, val []byte) error {
err := db.Update( return db.Update(
func(tx *nutsdb.Tx) error { func(tx *nutsdb.Tx) error {
keyBytes := []byte(key) keyBytes := []byte(key)
return tx.Delete(bucket, keyBytes) return tx.Delete(bucket, keyBytes)
}) })
return err
} }

72
ober.go
View File

@@ -10,13 +10,18 @@ import (
"github.com/fasthttp/router" "github.com/fasthttp/router"
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
"github.com/xujiajun/nutsdb"
) )
func RunWebserv() { func RunWebserv() {
r := router.New() r := router.New()
r.GET("/", Start) r.GET("/", Start)
r.GET("/api/season", Season) r.GET("/api/season", Season)
r.GET("/api/watch/{user?}", WatchGet)
r.POST("/api/register", Register) r.POST("/api/register", Register)
r.POST("/api/watch/{user}", WatchPost)
r.PATCH("/api/watch/{user}", Start)
r.DELETE("/api/watch/{user}", Start)
log.Fatal(fasthttp.ListenAndServe(":"+strconv.Itoa(*webServerPort), r.Handler)) log.Fatal(fasthttp.ListenAndServe(":"+strconv.Itoa(*webServerPort), r.Handler))
} }
@@ -62,6 +67,58 @@ func Season(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusOK) ctx.SetStatusCode(fasthttp.StatusOK)
} }
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) { func Register(ctx *fasthttp.RequestCtx) {
if string(ctx.Request.Header.ContentType()) != "application/json" { if string(ctx.Request.Header.ContentType()) != "application/json" {
ctx.SetStatusCode(fasthttp.StatusBadRequest) ctx.SetStatusCode(fasthttp.StatusBadRequest)
@@ -75,12 +132,13 @@ func Register(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusBadRequest) ctx.SetStatusCode(fasthttp.StatusBadRequest)
return return
} }
if register.MalId == 0 || register.Username == "" || register.Secret == "" || register.Sauce == "" { if register.MalID == 0 || register.Username == "" || register.Secret == "" || register.Sauce == "" {
ctx.WriteString("Sprich JSON du Hurensohn") ctx.WriteString("Sprich JSON du Hurensohn")
ctx.SetStatusCode(fasthttp.StatusBadRequest) ctx.SetStatusCode(fasthttp.StatusBadRequest)
return return
} }
calcSauce := fmt.Sprintf("%x", sha512.Sum512([]byte(registerSecret+strconv.Itoa(register.MalId)+register.Username)))
calcSauce := fmt.Sprintf("%x", sha512.Sum512([]byte(registerSecret+strconv.FormatInt(register.MalID, 10)+register.Username)))
if calcSauce != strings.ToLower(register.Sauce) { if calcSauce != strings.ToLower(register.Sauce) {
ctx.WriteString("Möge die Sauce mit dir sein") ctx.WriteString("Möge die Sauce mit dir sein")
ctx.SetStatusCode(fasthttp.StatusBadRequest) ctx.SetStatusCode(fasthttp.StatusBadRequest)
@@ -100,15 +158,15 @@ func Register(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusExpectationFailed) ctx.SetStatusCode(fasthttp.StatusExpectationFailed)
return return
} }
if userData.Data.MalID != register.MalId { if userData.Data.MalID != register.MalID {
ctx.WriteString("Dich gibts net auf MAL") ctx.WriteString("Dich gibts nicht auf MAL")
ctx.SetStatusCode(fasthttp.StatusExpectationFailed) ctx.SetStatusCode(fasthttp.StatusExpectationFailed)
return return
} }
// REGISTER // REGISTER
user := UserData{ user := UserData{
Username: register.Username, Username: register.Username,
MalId: register.MalId, MalID: register.MalID,
Secret: register.Secret, Secret: register.Secret,
} }
err = SaveUser(&user) err = SaveUser(&user)
@@ -121,6 +179,10 @@ func Register(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusOK) ctx.SetStatusCode(fasthttp.StatusOK)
} }
func WatchPost(ctx *fasthttp.RequestCtx) {
//
}
func addErrorToCtx(ctx *fasthttp.RequestCtx, err error) { func addErrorToCtx(ctx *fasthttp.RequestCtx, err error) {
ctx.WriteString(err.Error()) ctx.WriteString(err.Error())
ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.SetStatusCode(fasthttp.StatusInternalServerError)

View File

@@ -31,7 +31,7 @@ body { background-color: #1a1a1a; color: #fff; }
{% for _, anime := range season.Data %} {% for _, anime := range season.Data %}
<tr> <tr>
<td><strong>{%s anime.Title %}</strong></td> <td><strong>{%s anime.Title %}</strong></td>
<td>{%d anime.MalID %}</td> <td>{%dl anime.MalID %}</td>
<td>{%s anime.Aired.String %}</td> <td>{%s anime.Aired.String %}</td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@@ -37,7 +37,7 @@ func StreamIndex(qw422016 *qt422016.Writer, season *SeasonJikan) {
//line season.qtpl:33 //line season.qtpl:33
qw422016.N().S(`</strong></td> <td>`) qw422016.N().S(`</strong></td> <td>`)
//line season.qtpl:34 //line season.qtpl:34
qw422016.N().D(anime.MalID) qw422016.N().DL(anime.MalID)
//line season.qtpl:34 //line season.qtpl:34
qw422016.N().S(`</td> <td>`) qw422016.N().S(`</td> <td>`)
//line season.qtpl:35 //line season.qtpl:35