package bundb import ( "context" "database/sql" "errors" "fmt" "gitea.dwysokinski.me/twhelp/dcbot/internal/bundb/internal/model" "gitea.dwysokinski.me/twhelp/dcbot/internal/domain" "github.com/google/uuid" "github.com/uptrace/bun" ) type Group struct { db *bun.DB } func NewGroup(db *bun.DB) *Group { return &Group{db: db} } func (g *Group) Create(ctx context.Context, params domain.CreateGroupParams) (domain.Group, error) { group := model.Group{ ServerID: params.ServerID(), VersionCode: params.VersionCode(), ChannelGains: params.ChannelGains(), ChannelLosses: params.ChannelLosses(), ServerKey: params.ServerKey(), } if _, err := g.db.NewInsert(). Model(&group). Returning("*"). Exec(ctx); err != nil { return domain.Group{}, fmt.Errorf("something went wrong while inserting group into the db: %w", err) } return group.ToDomain(), nil } func (g *Group) Update(ctx context.Context, id, serverID string, params domain.UpdateGroupParams) (domain.Group, error) { if params.IsZero() { return domain.Group{}, domain.ErrNothingToUpdate } if _, err := uuid.Parse(id); err != nil { return domain.Group{}, domain.GroupNotFoundError{ID: id} } var group model.Group res, err := g.db.NewUpdate(). Model(&group). Returning("*"). Where("id = ?", id). Where("server_id = ?", serverID). Apply(updateGroupsParamsApplier{params}.apply). Exec(ctx) if err != nil && !errors.Is(err, sql.ErrNoRows) { return domain.Group{}, fmt.Errorf("couldn't update group (id=%s,serverID=%s): %w", id, serverID, err) } if affected, _ := res.RowsAffected(); affected == 0 { return domain.Group{}, domain.GroupNotFoundError{ID: id} } return group.ToDomain(), nil } func (g *Group) List(ctx context.Context, params domain.ListGroupsParams) ([]domain.Group, error) { var groups []model.Group if err := g.db.NewSelect(). Model(&groups). Order("created_at ASC"). Apply(listGroupsParamsApplier{params}.apply). Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) { return nil, fmt.Errorf("couldn't select groups from the db: %w", err) } result := make([]domain.Group, 0, len(groups)) for _, version := range groups { result = append(result, version.ToDomain()) } return result, nil } func (g *Group) Delete(ctx context.Context, id, serverID string) error { if _, err := uuid.Parse(id); err != nil { return domain.GroupNotFoundError{ID: id} } res, err := g.db.NewDelete(). Model(&model.Group{}). Returning("NULL"). Where("id = ?", id). Where("server_id = ?", serverID). Exec(ctx) if err != nil && !errors.Is(err, sql.ErrNoRows) { return fmt.Errorf("couldn't delete group (id=%s,serverID=%s): %w", id, serverID, err) } if affected, _ := res.RowsAffected(); affected == 0 { return domain.GroupNotFoundError{ID: id} } return nil } type updateGroupsParamsApplier struct { params domain.UpdateGroupParams } func (u updateGroupsParamsApplier) apply(q *bun.UpdateQuery) *bun.UpdateQuery { if u.params.ChannelGains.Valid { if u.params.ChannelGains.String != "" { q = q.Set("channel_gains = ?", u.params.ChannelGains.String) } else { q = q.Set("channel_gains = NULL") } } if u.params.ChannelLosses.Valid { if u.params.ChannelLosses.String != "" { q = q.Set("channel_losses = ?", u.params.ChannelLosses.String) } else { q = q.Set("channel_losses = NULL") } } return q } type listGroupsParamsApplier struct { params domain.ListGroupsParams } func (l listGroupsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { if l.params.ServerIDs != nil { q = q.Where("server_id IN (?)", bun.In(l.params.ServerIDs)) } return q }