mirror of
https://github.com/ultrasn0w/huso.git
synced 2025-12-14 18:49:53 +01:00
Appointment feature
This commit is contained in:
89
nuss.go
89
nuss.go
@@ -79,6 +79,51 @@ func AddUserToAnime(username string, userId, animeId int64, progress int, update
|
|||||||
return &anime, err
|
return &anime, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddUserToAppointment(username string, animeId int64, meeting time.Time) (*Appointment, error) {
|
||||||
|
var appoint Appointment
|
||||||
|
err := db.Update(
|
||||||
|
func(tx *nutsdb.Tx) error {
|
||||||
|
keyBytes := Int64AndDateToBytes(animeId, meeting)
|
||||||
|
e, err := tx.Get(bucketAppoint, keyBytes)
|
||||||
|
var users []string
|
||||||
|
if err != nil {
|
||||||
|
users = make([]string, 0)
|
||||||
|
} else {
|
||||||
|
// parse user list
|
||||||
|
users, err = parseAppointmentUserList(e.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check if user already part
|
||||||
|
for _, u := range users {
|
||||||
|
if u == username {
|
||||||
|
// early terminate
|
||||||
|
appoint = Appointment{
|
||||||
|
Anime: animeId,
|
||||||
|
Time: meeting,
|
||||||
|
Users: users,
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add user
|
||||||
|
users = append(users, username)
|
||||||
|
appoint = Appointment{
|
||||||
|
Anime: animeId,
|
||||||
|
Time: meeting,
|
||||||
|
Users: users,
|
||||||
|
}
|
||||||
|
newData, err := json.Marshal(users)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.Put(bucketAppoint, keyBytes, newData, nutsdb.Persistent)
|
||||||
|
})
|
||||||
|
return &appoint, err
|
||||||
|
}
|
||||||
|
|
||||||
func DeleteUserFromAnime(username string, userId, animeId int64) (*AnimeUser, error) {
|
func DeleteUserFromAnime(username string, userId, animeId int64) (*AnimeUser, error) {
|
||||||
var anime AnimeUser
|
var anime AnimeUser
|
||||||
err := db.Update(
|
err := db.Update(
|
||||||
@@ -167,6 +212,50 @@ func DeleteUserFromAnimes(userId int64) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeleteUserFromAppointment(username string, animeId int64, meeting time.Time) (*Appointment, error) {
|
||||||
|
var appoint Appointment
|
||||||
|
err := db.Update(
|
||||||
|
func(tx *nutsdb.Tx) error {
|
||||||
|
keyBytes := Int64AndDateToBytes(animeId, meeting)
|
||||||
|
e, err := tx.Get(bucketAppoint, keyBytes)
|
||||||
|
var users []string
|
||||||
|
if err != nil {
|
||||||
|
users = make([]string, 0)
|
||||||
|
} else {
|
||||||
|
// parse user list
|
||||||
|
users, err = parseAppointmentUserList(e.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check if user already part
|
||||||
|
for i, u := range users {
|
||||||
|
// early terminate
|
||||||
|
if u == username {
|
||||||
|
// delete user from list
|
||||||
|
users[i] = users[len(users)-1]
|
||||||
|
users = users[:len(users)-1]
|
||||||
|
// check if appointment needs recycling
|
||||||
|
appoint = Appointment{
|
||||||
|
Anime: animeId,
|
||||||
|
Time: meeting,
|
||||||
|
Users: users,
|
||||||
|
}
|
||||||
|
if len(users) == 0 {
|
||||||
|
return tx.Delete(bucketAppoint, keyBytes)
|
||||||
|
}
|
||||||
|
newData, err := json.Marshal(users)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.Put(bucketAppoint, keyBytes, newData, nutsdb.Persistent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s schaut nicht %d um %s", username, animeId, meeting.Format(time.RFC3339))
|
||||||
|
})
|
||||||
|
return &appoint, err
|
||||||
|
}
|
||||||
|
|
||||||
func DeleteAnime(tx *nutsdb.Tx, keyBytes []byte) error {
|
func DeleteAnime(tx *nutsdb.Tx, keyBytes []byte) error {
|
||||||
tx.Delete(bucketChat, keyBytes)
|
tx.Delete(bucketChat, keyBytes)
|
||||||
return tx.Delete(bucketAnime, keyBytes)
|
return tx.Delete(bucketAnime, keyBytes)
|
||||||
|
|||||||
101
ober.go
101
ober.go
@@ -6,6 +6,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/fasthttp/router"
|
"github.com/fasthttp/router"
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
@@ -26,9 +27,11 @@ func RunWebserv() {
|
|||||||
r.GET("/api/user/{user?}", Headers(UserGet))
|
r.GET("/api/user/{user?}", Headers(UserGet))
|
||||||
r.GET("/api/watch/{user?}", Headers(WatchGet))
|
r.GET("/api/watch/{user?}", Headers(WatchGet))
|
||||||
r.GET("/api/watchext/{user?}", Headers(WatchExtendedGet))
|
r.GET("/api/watchext/{user?}", Headers(WatchExtendedGet))
|
||||||
|
r.POST("/api/appointment/{user}", Headers(AppointmentPost))
|
||||||
r.POST("/api/chat/{id}/{user}", Headers(ChatPost))
|
r.POST("/api/chat/{id}/{user}", Headers(ChatPost))
|
||||||
r.POST("/api/register", Headers(Register))
|
r.POST("/api/register", Headers(Register))
|
||||||
r.POST("/api/watch/{user}", Headers(WatchPost))
|
r.POST("/api/watch/{user}", Headers(WatchPost))
|
||||||
|
r.DELETE("/api/appointment/{user}", Headers(AppointmentDelete))
|
||||||
r.DELETE("/api/register", Headers(UnRegister))
|
r.DELETE("/api/register", Headers(UnRegister))
|
||||||
r.DELETE("/api/watch/{user}", Headers(WatchDelete))
|
r.DELETE("/api/watch/{user}", Headers(WatchDelete))
|
||||||
log.Fatal(fasthttp.ListenAndServe(":"+strconv.Itoa(*webServerPort), r.Handler))
|
log.Fatal(fasthttp.ListenAndServe(":"+strconv.Itoa(*webServerPort), r.Handler))
|
||||||
@@ -395,6 +398,10 @@ func Register(ctx *fasthttp.RequestCtx) {
|
|||||||
ctx.SetStatusCode(fasthttp.StatusOK)
|
ctx.SetStatusCode(fasthttp.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AppointmentPost(ctx *fasthttp.RequestCtx) {
|
||||||
|
processUpdateAppointmentReq(ctx, true)
|
||||||
|
}
|
||||||
|
|
||||||
func ChatPost(ctx *fasthttp.RequestCtx) {
|
func ChatPost(ctx *fasthttp.RequestCtx) {
|
||||||
auth := ctx.Request.Header.Peek("X-HUSO-AUTH")
|
auth := ctx.Request.Header.Peek("X-HUSO-AUTH")
|
||||||
if ctx.UserValue("id") == nil || ctx.UserValue("user") == nil || auth == nil || string(auth) == "" || !strings.Contains(string(ctx.Request.Header.ContentType()), "text/plain") {
|
if ctx.UserValue("id") == nil || ctx.UserValue("user") == nil || auth == nil || string(auth) == "" || !strings.Contains(string(ctx.Request.Header.ContentType()), "text/plain") {
|
||||||
@@ -445,6 +452,10 @@ func WatchPost(ctx *fasthttp.RequestCtx) {
|
|||||||
processUpdateReq(ctx, true)
|
processUpdateReq(ctx, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AppointmentDelete(ctx *fasthttp.RequestCtx) {
|
||||||
|
processUpdateAppointmentReq(ctx, false)
|
||||||
|
}
|
||||||
|
|
||||||
func UnRegister(ctx *fasthttp.RequestCtx) {
|
func UnRegister(ctx *fasthttp.RequestCtx) {
|
||||||
if !strings.Contains(string(ctx.Request.Header.ContentType()), "application/json") {
|
if !strings.Contains(string(ctx.Request.Header.ContentType()), "application/json") {
|
||||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||||
@@ -597,9 +608,15 @@ func processUpdateReq(ctx *fasthttp.RequestCtx, update bool) {
|
|||||||
ctx.SetStatusCode(fasthttp.StatusConflict)
|
ctx.SetStatusCode(fasthttp.StatusConflict)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// anime is already dropped big baka user
|
||||||
|
if listState == malApiStatusD {
|
||||||
|
ctx.WriteString("Du hast schon gedropped bro")
|
||||||
|
ctx.SetStatusCode(fasthttp.StatusConflict)
|
||||||
|
return
|
||||||
|
}
|
||||||
animeData, err = AddUserToAnime(username, userId, anime.Anime, progress, updated)
|
animeData, err = AddUserToAnime(username, userId, anime.Anime, progress, updated)
|
||||||
} else {
|
} else {
|
||||||
// anime exitsts => delete
|
// anime exists => delete
|
||||||
animeData, err = DeleteUserFromAnime(username, userId, anime.Anime)
|
animeData, err = DeleteUserFromAnime(username, userId, anime.Anime)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -622,6 +639,88 @@ func processUpdateReq(ctx *fasthttp.RequestCtx, update bool) {
|
|||||||
ctx.SetContentType("application/json; charset=utf-8")
|
ctx.SetContentType("application/json; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func processUpdateAppointmentReq(ctx *fasthttp.RequestCtx, update bool) {
|
||||||
|
auth := ctx.Request.Header.Peek("X-HUSO-AUTH")
|
||||||
|
if ctx.UserValue("user") == nil || auth == nil || string(auth) == "" || !strings.Contains(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 appoints []Appointment
|
||||||
|
err := json.Unmarshal(body, &appoints)
|
||||||
|
if err != nil || len(appoints) == 0 {
|
||||||
|
ctx.WriteString(err.Error())
|
||||||
|
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate sent appointments
|
||||||
|
for i, appointment := range appoints {
|
||||||
|
var appData *Appointment
|
||||||
|
var found bool
|
||||||
|
|
||||||
|
if update {
|
||||||
|
// kann sich (noch) nicht in der Vergagenheit verabreden
|
||||||
|
if appointment.Time.Before(time.Now()) {
|
||||||
|
ctx.WriteString("kann sich (noch) nicht in der Vergagenheit verabreden")
|
||||||
|
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// check if user is a troll
|
||||||
|
found, err = CheckAnimeExistInDbAndUserWatches(appointment.Anime, userId)
|
||||||
|
if err != nil {
|
||||||
|
addErrorToCtx(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
ctx.WriteString("Anime gibts net oder du schaust net")
|
||||||
|
ctx.SetStatusCode(fasthttp.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// save appointment and get list
|
||||||
|
appData, err = AddUserToAppointment(username, appointment.Anime, appointment.Time)
|
||||||
|
} else {
|
||||||
|
found, err = CheckAnimeExistInDb(appointment.Anime)
|
||||||
|
if err != nil {
|
||||||
|
addErrorToCtx(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
ctx.WriteString("Anime gibts net")
|
||||||
|
ctx.SetStatusCode(fasthttp.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// anime exists => delete
|
||||||
|
appData, err = DeleteUserFromAppointment(username, appointment.Anime, appointment.Time)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
addErrorToCtx(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
appoints[i].Users = appData.Users
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(appoints)
|
||||||
|
if err != nil {
|
||||||
|
addErrorToCtx(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = writeResponseBody(ctx, data)
|
||||||
|
if err != nil {
|
||||||
|
addErrorToCtx(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.SetContentType("application/json; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
func writeResponseBody(ctx *fasthttp.RequestCtx, bytes []byte) error {
|
func writeResponseBody(ctx *fasthttp.RequestCtx, bytes []byte) error {
|
||||||
_, err := ctx.Write(bytes)
|
_, err := ctx.Write(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
18
schaffer.go
18
schaffer.go
@@ -232,3 +232,21 @@ func CheckAnimeExistInDb(animeId int64) (bool, error) {
|
|||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckAnimeExistInDbAndUserWatches(animeId, userId int64) (bool, error) {
|
||||||
|
dbAnime, err := ReadAnimeUsers()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
for _, a := range dbAnime {
|
||||||
|
if a.Anime == animeId {
|
||||||
|
for _, u := range a.Users {
|
||||||
|
if u.MalID == userId {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user