Files
huso/nuss.go
2022-05-28 14:07:10 +02:00

455 lines
10 KiB
Go

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 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(
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 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 {
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
}