package main import ( "encoding/json" "errors" "fmt" "time" "github.com/xujiajun/nutsdb" ) func ReadUser(username string) (*UserData, error) { data, err := DbRead(bucketUsers, []byte(username)) if err != nil { return nil, err } var user UserData err = json.Unmarshal(data, &user) return &user, err } func SaveUser(user *UserData) error { data, err := json.Marshal(user) if err != nil { return err } if user.Username == "" { return errors.New("user empty") } err = DbSave(bucketUsers, user.Username, data) return err } func AddUserToAnime(username string, userId, animeId int64, progress int, updated time.Time) (*AnimeUser, error) { var anime AnimeUser err := db.Update( func(tx *nutsdb.Tx) error { keyBytes := Int64ToByte(animeId) e, err := tx.Get(bucketAnime, keyBytes) var users []WatchUser if err != nil { users = make([]WatchUser, 0) } else { // parse user list users, err = parseWatchUserList(e.Value) if err != nil { return err } } // check if user already part for _, u := range users { if u.MalID == userId { // early terminate anime = AnimeUser{ Anime: animeId, Users: users, } return err } } // add user users = append(users, WatchUser{ Username: username, MalID: userId, Progress: progress, Updated: updated, }) anime = AnimeUser{ Anime: animeId, Users: users, } newData, err := json.Marshal(users) if err != nil { return err } return tx.Put(bucketAnime, keyBytes, newData, nutsdb.Persistent) }) return &anime, err } func DeleteUserFromAnime(username string, userId, animeId int64) (*AnimeUser, error) { var anime AnimeUser err := db.Update( func(tx *nutsdb.Tx) error { keyBytes := Int64ToByte(animeId) e, err := tx.Get(bucketAnime, keyBytes) var users []WatchUser if err != nil { users = make([]WatchUser, 0) } else { // parse user list users, err = parseWatchUserList(e.Value) if err != nil { return err } } // check if user already part for i, u := range users { // early terminate if u.MalID == userId { // delete user from list users[i] = users[len(users)-1] users = users[:len(users)-1] // check if anime needs recycling anime = AnimeUser{ Anime: animeId, Users: users, } if len(users) == 0 { return DeleteAnime(tx, keyBytes) } newData, err := json.Marshal(users) if err != nil { return err } return tx.Put(bucketAnime, keyBytes, newData, nutsdb.Persistent) } } return fmt.Errorf("%s %d schaut nicht %d", username, userId, animeId) }) return &anime, err } func DeleteUserFromAnimes(userId int64) error { return db.Update( func(tx *nutsdb.Tx) error { entries, err := tx.GetAll(bucketAnime) if err != nil { return err } // iterate entries for _, e := range entries { // parse user list users, err := parseWatchUserList(e.Value) if err != nil { return err } // check if user is part for i, u := range users { if u.MalID == userId { // delete user from list users[i] = users[len(users)-1] users = users[:len(users)-1] // check if anime needs recycling if len(users) == 0 { err = DeleteAnime(tx, e.Key) if err != nil { return err } } else { newData, err := json.Marshal(users) if err != nil { return err } err = tx.Put(bucketAnime, e.Key, newData, nutsdb.Persistent) if err != nil { return err } } break } } } return nil }) } func DeleteAnime(tx *nutsdb.Tx, keyBytes []byte) error { tx.Delete(bucketChat, keyBytes) return tx.Delete(bucketAnime, keyBytes) } func UpdateUserAnimeProgress(animeId, userId int64, progress int, updated time.Time) error { return db.Update( func(tx *nutsdb.Tx) error { keyBytes := Int64ToByte(animeId) e, err := tx.Get(bucketAnime, keyBytes) if err != nil { return err } // parse user list users, err := parseWatchUserList(e.Value) if err != nil { return err } // find user for i, u := range users { // early terminate if u.MalID == userId { users[i].Progress = progress users[i].Updated = updated newData, err := json.Marshal(users) if err != nil { return err } return tx.Put(bucketAnime, keyBytes, newData, nutsdb.Persistent) } } return fmt.Errorf("%d schaut nicht %d", userId, animeId) }) } func ReadRegisteredUsers() ([]UserData, error) { var users []UserData err := db.View( func(tx *nutsdb.Tx) error { entries, err := tx.GetAll(bucketUsers) if err != nil { return err } users = make([]UserData, 0) // iterate entries for _, e := range entries { // parse user var user UserData err := json.Unmarshal(e.Value, &user) if err != nil { return err } users = append(users, user) } return nil }) return users, err } func ReadAnimeUsers() ([]AnimeUser, error) { var animes []AnimeUser err := db.View( func(tx *nutsdb.Tx) error { entries, err := tx.GetAll(bucketAnime) if err != nil { return err } animes = make([]AnimeUser, 0) // iterate entries for _, e := range entries { // decode anime list animeId, err := BytesToInt64(e.Key) if err != nil { return err } // parse user list users, err := parseWatchUserList(e.Value) if err != nil { return err } anime := AnimeUser{ Anime: animeId, Users: users, } animes = append(animes, anime) } return nil }) return animes, err } func ReadAppointments() ([]Appointment, error) { var appoints []Appointment err := db.View( func(tx *nutsdb.Tx) error { entries, err := tx.GetAll(bucketAppoint) if err != nil { return err } appoints = make([]Appointment, 0) // iterate entries for _, e := range entries { // decode appointment list animeId, date, err := BytesToInt64AndDate(e.Key) if err != nil { return err } // parse user list appointmentUsers, err := parseAppointmentUserList(e.Value) if err != nil { return err } appointment := Appointment{ Anime: animeId, Time: date, Users: appointmentUsers, } appoints = append(appoints, appointment) } return nil }) return appoints, err } func ReadChat(animeId int64) (string, error) { data, err := DbRead(bucketChat, Int64ToByte(animeId)) return string(data), err } func SaveChat(animeId int64, username, newMessage string) (string, error) { var chat string err := db.Update( func(tx *nutsdb.Tx) error { keyBytes := Int64ToByte(animeId) e, err := tx.Get(bucketChat, keyBytes) if err != nil { chat = "" } else { chat = string(e.Value) } // add to chat message chat = AddToChat(chat, newMessage, username) return tx.Put(bucketChat, keyBytes, []byte(chat), nutsdb.Persistent) }) return chat, err } func DbClean() error { return db.Update( func(tx *nutsdb.Tx) error { return db.Merge() }) } func DbSave(bucket, key string, val []byte) error { return db.Update( func(tx *nutsdb.Tx) error { keyBytes := []byte(key) return tx.Put(bucket, keyBytes, val, nutsdb.Persistent) }) } func DbRead(bucket string, keyBytes []byte) ([]byte, error) { var val []byte err := db.View( func(tx *nutsdb.Tx) error { e, err := tx.Get(bucket, keyBytes) if err != nil { return err } val = make([]byte, len(e.Value)) copy(val, e.Value) return err }) return val, err } func DbDelete(bucket, key string) error { return db.Update( func(tx *nutsdb.Tx) error { keyBytes := []byte(key) return tx.Delete(bucket, keyBytes) }) } func parseWatchUserList(data []byte) ([]WatchUser, error) { var users []WatchUser err := json.Unmarshal(data, &users) return users, err } func parseAppointmentUserList(data []byte) ([]string, error) { var users []string err := json.Unmarshal(data, &users) return users, err }