mirror of
https://github.com/ultrasn0w/huso.git
synced 2025-12-13 14:09:52 +01:00
518 lines
12 KiB
Go
518 lines
12 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, bool, error) {
|
|
var appoint Appointment
|
|
fresh := false
|
|
err := db.Update(
|
|
func(tx *nutsdb.Tx) error {
|
|
keyBytes := Int64AndDateToBytes(animeId, meeting)
|
|
e, err := tx.Get(bucketAppoint, keyBytes)
|
|
var users []string
|
|
if err != nil {
|
|
fresh = true
|
|
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, fresh, 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 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)
|
|
}
|
|
|
|
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
|
|
}
|