mirror of
https://github.com/ultrasn0w/huso.git
synced 2025-12-13 10:39:52 +01:00
Compare commits
8 Commits
7e939800cd
...
f7c331c945
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7c331c945 | ||
|
|
97f94e5e2f | ||
|
|
5b029ee835 | ||
|
|
d9ab365ae4 | ||
|
|
864aa5695a | ||
|
|
231cecedd8 | ||
|
|
a079fbf9db | ||
|
|
b2b6c97282 |
45
README.md
45
README.md
@@ -215,7 +215,8 @@ _[]AnimeUserExtended_ (GET)
|
||||
"updated": "2022-05-15T20:44:35Z"
|
||||
}
|
||||
],
|
||||
"data": { --SEE ANIME GET (Anime object)-- }
|
||||
"data": { --SEE ANIME GET (Anime object)-- },
|
||||
"appointments": { --SEE APPOINTMENT GET (Appointment list)-- }
|
||||
},
|
||||
{
|
||||
"anime": 40356,
|
||||
@@ -227,7 +228,8 @@ _[]AnimeUserExtended_ (GET)
|
||||
"updated": "2022-04-25T18:11:27Z"
|
||||
}
|
||||
],
|
||||
"data": { --SEE ANIME GET (Anime object)-- }
|
||||
"data": { --SEE ANIME GET (Anime object)-- },
|
||||
"appointments": { --SEE APPOINTMENT GET (Appointment list)-- }
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -248,7 +250,44 @@ _[]AnimeUser_ (POST/DELETE)
|
||||
| GET | /api/chat/{id} | Chat für Anime holen | Plaintext chat | {id} = MAL Anime id | | |
|
||||
| POST | /api/chat/{id}/{user} | Chat für Anime senden | Plaintext chat mit neuer Nachricht | {id} = MAL Anime id; {user} = MAL username | X-HUSO-AUTH | Neue Nachricht in plaintext |
|
||||
|
||||
### Appointment [WIP]
|
||||
### Appointment
|
||||
| Method | Route | Description | Response | Parameter | Header | POST-Body |
|
||||
| - | - | - | - | - | - | - |
|
||||
| GET | /api/appointment | Appointments holen | []Appointment | | | |
|
||||
| POST | /api/appointment/{user} | Appointment schicken | []Appointment JSON | {user} = MAL username | X-HUSO-AUTH | []Appointment JSON |
|
||||
| DELETE | /api/appointment/{user} | Von Appointments austragen | []Appointment JSON | {user} = MAL username | X-HUSO-AUTH | []Appointment JSON |
|
||||
|
||||
|
||||
**Verwendung des JSON von GET und POST/DELETE unterscheiden sich. Bei POST/DELETE muss nur das Datum und der zu verändernde Anime angegeben werden und sonst nichts.**
|
||||
|
||||
_[]Appointment_ (GET)
|
||||
```json
|
||||
[
|
||||
{
|
||||
"anime": 40356,
|
||||
"date": "2022-05-30T20:51:51Z",
|
||||
"users": [
|
||||
"TESTUSERNAME",
|
||||
"TESTUSERNAME2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"anime": 50265,
|
||||
"date": "2022-05-31T20:51:51Z",
|
||||
"users": [
|
||||
"TESTUSERNAME"
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
_[]Appointment_ (POST/DELETE)
|
||||
```json
|
||||
[
|
||||
{
|
||||
"anime": 50265,
|
||||
"date": "2022-05-31T22:51:51Z",
|
||||
"users": []
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
2
go.mod
2
go.mod
@@ -15,7 +15,7 @@ require (
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/bwmarrin/snowflake v0.3.0 // indirect
|
||||
github.com/klauspost/compress v1.15.4 // indirect
|
||||
github.com/klauspost/compress v1.15.5 // indirect
|
||||
github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
|
||||
|
||||
6
go.sum
6
go.sum
@@ -18,8 +18,8 @@ github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.4 h1:1kn4/7MepF/CHmYub99/nNX8az0IJjfSOU/jbnTVfqQ=
|
||||
github.com/klauspost/compress v1.15.4/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.5 h1:qyCLMz2JCrKADihKOh9FxnW3houKeNsp2h5OEz0QSEA=
|
||||
github.com/klauspost/compress v1.15.5/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 h1:sfTahD3f2BSjx9U3R4K09PkNuZZWthT7g6vzTIXNWkM=
|
||||
@@ -59,8 +59,6 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220519141025-dcacdad47464 h1:MpIuURY70f0iKp/oooEFtB2oENcHITo/z1b6u41pKCw=
|
||||
golang.org/x/sys v0.0.0-20220519141025-dcacdad47464/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
||||
2
huso.go
2
huso.go
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
husoVersion = "1.1"
|
||||
husoVersion = "1.2"
|
||||
registerSecret = "綾波レイ"
|
||||
seasonApiJikan = "seasons/now"
|
||||
seasonStrJikan = "seasons/"
|
||||
|
||||
150
nuss.go
150
nuss.go
@@ -79,6 +79,51 @@ func AddUserToAnime(username string, userId, animeId int64, progress int, update
|
||||
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) {
|
||||
var anime AnimeUser
|
||||
err := db.Update(
|
||||
@@ -167,7 +212,112 @@ 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 DeleteUserFromAppointmens(username string) error {
|
||||
return db.Update(
|
||||
func(tx *nutsdb.Tx) error {
|
||||
entries, err := tx.GetAll(bucketAppoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// iterate entries
|
||||
for _, e := range entries {
|
||||
// parse user list
|
||||
users, err := parseAppointmentUserList(e.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check if user already part
|
||||
for i, u := range users {
|
||||
if u == username {
|
||||
// delete user from list
|
||||
users[i] = users[len(users)-1]
|
||||
users = users[:len(users)-1]
|
||||
// check if appointment needs recycling
|
||||
if len(users) == 0 {
|
||||
err = tx.Delete(bucketAppoint, e.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
newData, err := json.Marshal(users)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Put(bucketAppoint, e.Key, newData, nutsdb.Persistent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteAnime(tx *nutsdb.Tx, keyBytes []byte) error {
|
||||
// clear appointments
|
||||
appoints, err := tx.GetAll(bucketAppoint)
|
||||
if err == nil {
|
||||
animeId, err := BytesToInt64(keyBytes)
|
||||
if err == nil {
|
||||
for _, e := range appoints {
|
||||
// decode appointment list
|
||||
dbAnimeId, _, err := BytesToInt64AndDate(e.Key)
|
||||
if err == nil && dbAnimeId == animeId {
|
||||
tx.Delete(bucketAppoint, e.Key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tx.Delete(bucketChat, keyBytes)
|
||||
return tx.Delete(bucketAnime, keyBytes)
|
||||
}
|
||||
|
||||
148
ober.go
148
ober.go
@@ -6,6 +6,7 @@ import (
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fasthttp/router"
|
||||
"github.com/valyala/fasthttp"
|
||||
@@ -26,9 +27,11 @@ func RunWebserv() {
|
||||
r.GET("/api/user/{user?}", Headers(UserGet))
|
||||
r.GET("/api/watch/{user?}", Headers(WatchGet))
|
||||
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/register", Headers(Register))
|
||||
r.POST("/api/watch/{user}", Headers(WatchPost))
|
||||
r.DELETE("/api/appointment/{user}", Headers(AppointmentDelete))
|
||||
r.DELETE("/api/register", Headers(UnRegister))
|
||||
r.DELETE("/api/watch/{user}", Headers(WatchDelete))
|
||||
log.Fatal(fasthttp.ListenAndServe(":"+strconv.Itoa(*webServerPort), r.Handler))
|
||||
@@ -153,7 +156,30 @@ func AnimeSearchGet(ctx *fasthttp.RequestCtx) {
|
||||
}
|
||||
|
||||
func AppointmentGet(ctx *fasthttp.RequestCtx) {
|
||||
ctx.SetStatusCode(fasthttp.StatusNotImplemented)
|
||||
appoints, err := ReadAppointments()
|
||||
// check if no appointments exists
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found") || err == nutsdb.ErrBucketEmpty {
|
||||
appoints = make([]Appointment, 0)
|
||||
} else {
|
||||
addErrorToCtx(ctx, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
bytes, err := json.Marshal(appoints)
|
||||
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 ChatGet(ctx *fasthttp.RequestCtx) {
|
||||
@@ -290,10 +316,16 @@ func WatchExtendedGet(ctx *fasthttp.RequestCtx) {
|
||||
addErrorToCtx(ctx, err)
|
||||
return
|
||||
}
|
||||
apps, err := SearchAppointments(a.Anime)
|
||||
if err != nil {
|
||||
addErrorToCtx(ctx, err)
|
||||
return
|
||||
}
|
||||
animeUsersExtended = append(animeUsersExtended, AnimeUserExtended{
|
||||
Anime: a.Anime,
|
||||
Users: a.Users,
|
||||
Data: *data,
|
||||
Anime: a.Anime,
|
||||
Users: a.Users,
|
||||
Data: *data,
|
||||
Appointments: apps,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -372,6 +404,10 @@ func Register(ctx *fasthttp.RequestCtx) {
|
||||
ctx.SetStatusCode(fasthttp.StatusOK)
|
||||
}
|
||||
|
||||
func AppointmentPost(ctx *fasthttp.RequestCtx) {
|
||||
processUpdateAppointmentReq(ctx, true)
|
||||
}
|
||||
|
||||
func ChatPost(ctx *fasthttp.RequestCtx) {
|
||||
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") {
|
||||
@@ -422,6 +458,10 @@ func WatchPost(ctx *fasthttp.RequestCtx) {
|
||||
processUpdateReq(ctx, true)
|
||||
}
|
||||
|
||||
func AppointmentDelete(ctx *fasthttp.RequestCtx) {
|
||||
processUpdateAppointmentReq(ctx, false)
|
||||
}
|
||||
|
||||
func UnRegister(ctx *fasthttp.RequestCtx) {
|
||||
if !strings.Contains(string(ctx.Request.Header.ContentType()), "application/json") {
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
@@ -450,8 +490,14 @@ func UnRegister(ctx *fasthttp.RequestCtx) {
|
||||
err = DeleteUserFromAnimes(register.MalID)
|
||||
if err != nil {
|
||||
if err != nutsdb.ErrBucketEmpty {
|
||||
ctx.WriteString(err.Error())
|
||||
ctx.SetStatusCode(fasthttp.StatusNotFound)
|
||||
addErrorToCtx(ctx, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
err = DeleteUserFromAppointmens(register.Username)
|
||||
if err != nil {
|
||||
if err != nutsdb.ErrBucketEmpty {
|
||||
addErrorToCtx(ctx, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -574,9 +620,15 @@ func processUpdateReq(ctx *fasthttp.RequestCtx, update bool) {
|
||||
ctx.SetStatusCode(fasthttp.StatusConflict)
|
||||
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)
|
||||
} else {
|
||||
// anime exitsts => delete
|
||||
// anime exists => delete
|
||||
animeData, err = DeleteUserFromAnime(username, userId, anime.Anime)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -599,6 +651,88 @@ func processUpdateReq(ctx *fasthttp.RequestCtx, update bool) {
|
||||
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 {
|
||||
_, err := ctx.Write(bytes)
|
||||
if err != nil {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gookit/color"
|
||||
@@ -17,6 +18,34 @@ func Arbeiten() {
|
||||
}
|
||||
|
||||
func Arbeit() {
|
||||
// check appointments
|
||||
appoints, err := ReadAppointments()
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "not found") && err != nutsdb.ErrBucketEmpty {
|
||||
color.Errorln(err.Error())
|
||||
logOut.WriteError(err)
|
||||
}
|
||||
} else {
|
||||
cleared := 0
|
||||
for _, a := range appoints {
|
||||
if a.Time.Before(time.Now()) {
|
||||
// appointment expired
|
||||
keyBytes := Int64AndDateToBytes(a.Anime, a.Time)
|
||||
err = DbDelete(bucketAppoint, string(keyBytes))
|
||||
if err != nil {
|
||||
color.Errorln(err.Error())
|
||||
logOut.WriteError(err)
|
||||
} else {
|
||||
cleared++
|
||||
}
|
||||
}
|
||||
}
|
||||
if cleared > 0 {
|
||||
color.Infof("Cleared %d expired appointments\n", cleared)
|
||||
logOut.WriteLine(fmt.Sprintf("♻️ Cleared %d expired appointments", cleared))
|
||||
}
|
||||
}
|
||||
|
||||
// refresh animelist of users
|
||||
animesUsers, err := ReadAnimeUsers()
|
||||
if err != nil {
|
||||
@@ -36,11 +65,6 @@ func Arbeit() {
|
||||
logOut.WriteError(err)
|
||||
continue
|
||||
}
|
||||
if newProgress == u.Progress {
|
||||
continue
|
||||
}
|
||||
color.Infof("%s progress von %d: %d -> %d\n", u.Username, a.Anime, u.Progress, newProgress)
|
||||
logOut.WriteLine(fmt.Sprintf("📜 %s progress von %d: %d -> %d", u.Username, a.Anime, u.Progress, newProgress))
|
||||
// check if user set anime as completed
|
||||
if listState == malApiStatusC {
|
||||
color.Infof("%s finished %d\n", u.Username, a.Anime)
|
||||
@@ -53,6 +77,23 @@ func Arbeit() {
|
||||
}
|
||||
continue
|
||||
}
|
||||
// check if user set anime as dropped
|
||||
if listState == malApiStatusD {
|
||||
color.Infof("%s dropped %d\n", u.Username, a.Anime)
|
||||
logOut.WriteLine(fmt.Sprintf("📜 %s dropped %d !", u.Username, a.Anime))
|
||||
// delete user from anime
|
||||
_, err = DeleteUserFromAnime(u.Username, u.MalID, a.Anime)
|
||||
if err != nil {
|
||||
color.Errorln(err.Error())
|
||||
logOut.WriteError(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if newProgress == u.Progress {
|
||||
continue
|
||||
}
|
||||
color.Infof("%s progress von %d: %d -> %d\n", u.Username, a.Anime, u.Progress, newProgress)
|
||||
logOut.WriteLine(fmt.Sprintf("📜 %s progress von %d: %d -> %d", u.Username, a.Anime, u.Progress, newProgress))
|
||||
// update db
|
||||
err = UpdateUserAnimeProgress(a.Anime, u.MalID, newProgress, updated)
|
||||
if err != nil {
|
||||
|
||||
48
schaffer.go
48
schaffer.go
@@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xujiajun/nutsdb"
|
||||
)
|
||||
|
||||
func JikanConvert(jik *SeasonAnimeJikan) Anime {
|
||||
@@ -160,6 +162,24 @@ func SearchAnime(animeId int64) (*Anime, error) {
|
||||
return anime, err
|
||||
}
|
||||
|
||||
func SearchAppointments(animeId int64) ([]Appointment, error) {
|
||||
appointments, err := ReadAppointments()
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found") || err == nutsdb.ErrBucketEmpty {
|
||||
return make([]Appointment, 0), nil
|
||||
} else {
|
||||
return appointments, err
|
||||
}
|
||||
}
|
||||
result := make([]Appointment, 0)
|
||||
for _, a := range appointments {
|
||||
if animeId == a.Anime {
|
||||
result = append(result, a)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func FetchProgress(animeId, userId int64, username string, progress int) (int, time.Time, string, error) {
|
||||
// check watching first
|
||||
newProgress, updated, err := fetchProgressOnState(animeId, userId, progress, username, malApiStatusW)
|
||||
@@ -185,7 +205,15 @@ func FetchProgress(animeId, userId int64, username string, progress int) (int, t
|
||||
if newProgress != -1 {
|
||||
return newProgress, updated, malApiStatusC, err
|
||||
}
|
||||
// has no progress or dropped
|
||||
// check dropped
|
||||
newProgress, updated, err = fetchProgressOnState(animeId, userId, progress, username, malApiStatusD)
|
||||
if err != nil {
|
||||
return newProgress, updated, "", err
|
||||
}
|
||||
if newProgress != -1 {
|
||||
return newProgress, updated, malApiStatusD, err
|
||||
}
|
||||
// has no progress or PTW
|
||||
return 0, updated, "", nil
|
||||
}
|
||||
|
||||
@@ -224,3 +252,21 @@ func CheckAnimeExistInDb(animeId int64) (bool, error) {
|
||||
}
|
||||
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