package storage import ( "context" "log" "net/url" "strings" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) type MongodbStorage struct { Db *mongo.Client } func (m MongodbStorage) CreateUser(user *User) (primitive.ObjectID, error) { ctx := context.TODO() store := NewStore[User](&m, "users") return store.InsertOne(ctx, user) } func (m MongodbStorage) GetUserByID(id primitive.ObjectID) (*User, error) { ctx := context.TODO() store := NewStore[User](&m, "users") return store.GetById(ctx, id) } func (m MongodbStorage) GetUser(filter *bson.D) (*User, error) { ctx := context.TODO() store := NewStore[User](&m, "users") return store.GetOne(ctx, filter) } func (m MongodbStorage) GetUsers(filter *bson.D) ([]*User, error) { ctx := context.TODO() store := NewStore[User](&m, "users") return store.GetMany(ctx, filter) } func (m MongodbStorage) UpdateUser(user *User) error { ctx := context.TODO() store := NewStore[User](&m, "users") return store.ReplaceByID(ctx, user.Id, user) } func (m MongodbStorage) DeleteUser(id primitive.ObjectID) error { ctx := context.TODO() store := NewStore[User](&m, "users") return store.DeleteByID(ctx, id) } func (m MongodbStorage) CreateSession(s *Session) (primitive.ObjectID, error) { ctx := context.TODO() store := NewStore[Session](&m, "sessions") return store.InsertOne(ctx, s) } func (m MongodbStorage) GetSessionByToken(token string) (*Session, error) { ctx := context.TODO() store := NewStore[Session](&m, "sessions") return store.GetOne(ctx, &bson.D{{Key: "token", Value: token}}) } func (m MongodbStorage) GetUserSessions(user *User) ([]*Session, error) { ctx := context.TODO() store := NewStore[Session](&m, "sessions") return store.GetMany(ctx, &bson.D{{Key: "userid", Value: user.Id}}) } func (m MongodbStorage) DeleteSession(id primitive.ObjectID) error { ctx := context.TODO() store := NewStore[Session](&m, "sessions") return store.DeleteByID(ctx, id) } func (m MongodbStorage) CreateBookmark(bookmark *Bookmark) (primitive.ObjectID, error) { ctx := context.TODO() store := NewStore[Bookmark](&m, "bookmarks") return store.InsertOne(ctx, bookmark) } func (m MongodbStorage) GetBookmarkByID(id primitive.ObjectID) (*Bookmark, error) { ctx := context.TODO() store := NewStore[Bookmark](&m, "bookmarks") return store.GetById(ctx, id) } func (m MongodbStorage) GetBookmark(filter *bson.D) (*Bookmark, error) { ctx := context.TODO() store := NewStore[Bookmark](&m, "bookmarks") return store.GetOne(ctx, filter) } func (m MongodbStorage) GetBookmarks(filter *bson.D) ([]*Bookmark, error) { ctx := context.TODO() store := NewStore[Bookmark](&m, "bookmarks") return store.GetMany(ctx, filter) } func (m MongodbStorage) GetRandomBookmarks(count int, filter *bson.D) ([]*Bookmark, error) { passedFilter := getFilter(filter) ctx := context.TODO() store := NewStore[Bookmark](&m, "bookmarks") bookmarks := []*Bookmark{} cur, err := store.Coll.Aggregate(ctx, bson.A{ bson.D{{Key: "$match", Value: passedFilter}}, bson.D{{Key: "$sample", Value: bson.D{bson.E{Key: "size", Value: count}}}}, }) if err != nil { log.Println("Cant aggregate random bookmakrs: ", err) return bookmarks, err } cur.All(ctx, &bookmarks) return bookmarks, err } func (m MongodbStorage) GetLastBookmarks(count int, filter *bson.D) ([]*Bookmark, error) { passedFilter := getFilter(filter) ctx := context.TODO() store := NewStore[Bookmark](&m, "bookmarks") bookmarks := []*Bookmark{} opts := options.Find().SetSort(bson.D{{Key: "created", Value: -1}}).SetLimit(int64(count)) cur, err := store.Coll.Find(ctx, passedFilter, opts) if err != nil { log.Println("Cant find last bookmakrs: ", err) return bookmarks, err } cur.All(ctx, &bookmarks) return bookmarks, err } func (m MongodbStorage) GetUserBookmarks(user *User, filter *bson.D) ([]*Bookmark, error) { passedFilter := getFilter(filter) f := bson.D{{Key: "userid", Value: user.Id}} f = append(f, passedFilter...) ctx := context.TODO() store := NewStore[Bookmark](&m, "bookmarks") return store.GetMany(ctx, &f) } func (m MongodbStorage) CreateFolder(folder *Folder) (primitive.ObjectID, error) { store := NewStore[Folder](&m, "folders") return store.InsertOne(context.TODO(), folder) } func (m MongodbStorage) GetFolderByID(id primitive.ObjectID) (*Folder, error) { store := NewStore[Folder](&m, "folders") return store.GetById(context.TODO(), id) } func (m MongodbStorage) GetFolder(filter *bson.D) (*Folder, error) { store := NewStore[Folder](&m, "folders") return store.GetOne(context.TODO(), filter) } func (m MongodbStorage) GetFolders(filter *bson.D) ([]*Folder, error) { store := NewStore[Folder](&m, "folders") return store.GetMany(context.TODO(), filter) } func (m MongodbStorage) GetChildrenFolders(id primitive.ObjectID) ([]*Folder, error) { store := NewStore[Folder](&m, "folders") return store.GetMany(context.TODO(), &bson.D{{Key: "parentid", Value: id}}) } func (m MongodbStorage) GetChildrenBookmarks(id primitive.ObjectID) ([]*Bookmark, error) { store := NewStore[Bookmark](&m, "bookmarks") return store.GetMany(context.TODO(), &bson.D{{Key: "folderid", Value: id}}) } func (m MongodbStorage) Collection(col string) *mongo.Collection { return m.Db.Database("nash").Collection(col) } func getFilter(f *bson.D) bson.D { if f == nil { return bson.D{} } return *f } func QueryFilter(q *url.Values) bson.D { filter := bson.D{} for k, v := range *q { var f bson.E q := strings.Split(k, "_") if len(q) == 1 { // If param is like "name" or "url" we're using exact matching f = bson.E{Key: k, Value: v[0]} } else { if q[1] == "like" { // If it's like "name_like", we're using regex f = bson.E{Key: q[0], Value: bson.D{{Key: "$regex", Value: v[0]}}} } } filter = append(filter, f) // Applying query filters to user filter } return filter }