253 lines
6.4 KiB
Go
253 lines
6.4 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"gitea.dwysokinski.me/twhelp/dcbot/internal/domain"
|
|
"gitea.dwysokinski.me/twhelp/dcbot/internal/twhelp"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
//counterfeiter:generate -o internal/mock/group_repository.gen.go . GroupRepository
|
|
type GroupRepository interface {
|
|
Create(ctx context.Context, params domain.CreateGroupParams) (domain.Group, error)
|
|
Update(ctx context.Context, id, serverID string, params domain.UpdateGroupParams) (domain.Group, error)
|
|
List(ctx context.Context, params domain.ListGroupsParams) ([]domain.Group, error)
|
|
Get(ctx context.Context, id, serverID string) (domain.Group, error)
|
|
Delete(ctx context.Context, id, serverID string) error
|
|
DeleteMany(ctx context.Context, id ...string) error
|
|
}
|
|
|
|
type Group struct {
|
|
repo GroupRepository
|
|
client TWHelpClient
|
|
logger *zap.Logger
|
|
maxGroupsPerServer int
|
|
}
|
|
|
|
func NewGroup(repo GroupRepository, client TWHelpClient, logger *zap.Logger, maxGroupsPerServer int) *Group {
|
|
return &Group{
|
|
repo: repo,
|
|
client: client,
|
|
logger: logger,
|
|
maxGroupsPerServer: maxGroupsPerServer,
|
|
}
|
|
}
|
|
|
|
func (g *Group) Create(ctx context.Context, params domain.CreateGroupParams) (domain.Group, error) {
|
|
groups, err := g.repo.List(ctx, domain.ListGroupsParams{
|
|
ServerIDs: []string{params.ServerID()},
|
|
})
|
|
if err != nil {
|
|
return domain.Group{}, fmt.Errorf("GroupRepository.List: %w", err)
|
|
}
|
|
|
|
if len(groups) >= g.maxGroupsPerServer {
|
|
return domain.Group{}, domain.GroupLimitReachedError{
|
|
Current: len(groups),
|
|
Limit: g.maxGroupsPerServer,
|
|
}
|
|
}
|
|
|
|
if err = g.checkTWServer(ctx, params.VersionCode(), params.ServerKey()); err != nil {
|
|
return domain.Group{}, err
|
|
}
|
|
|
|
group, err := g.repo.Create(ctx, params)
|
|
if err != nil {
|
|
return domain.Group{}, fmt.Errorf("GroupRepository.Create: %w", err)
|
|
}
|
|
|
|
return group, nil
|
|
}
|
|
|
|
func (g *Group) checkTWServer(ctx context.Context, versionCode, serverKey string) error {
|
|
server, err := g.client.GetServer(ctx, versionCode, serverKey)
|
|
if err != nil {
|
|
var apiErr twhelp.APIError
|
|
if !errors.As(err, &apiErr) {
|
|
return fmt.Errorf("TWHelpClient.GetServer: %w", err)
|
|
}
|
|
return domain.ServerDoesNotExistError{
|
|
VersionCode: versionCode,
|
|
Key: serverKey,
|
|
}
|
|
}
|
|
|
|
if !server.Open {
|
|
return domain.ServerIsClosedError{
|
|
VersionCode: versionCode,
|
|
Key: serverKey,
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (g *Group) SetChannelGains(ctx context.Context, id, serverID, channel string) (domain.Group, error) {
|
|
return g.update(ctx, id, serverID, domain.UpdateGroupParams{
|
|
ChannelGains: domain.NullString{
|
|
String: channel,
|
|
Valid: true,
|
|
},
|
|
})
|
|
}
|
|
|
|
func (g *Group) SetChannelLosses(ctx context.Context, id, serverID, channel string) (domain.Group, error) {
|
|
return g.update(ctx, id, serverID, domain.UpdateGroupParams{
|
|
ChannelLosses: domain.NullString{
|
|
String: channel,
|
|
Valid: true,
|
|
},
|
|
})
|
|
}
|
|
|
|
func (g *Group) SetInternals(ctx context.Context, id, serverID string, internals bool) (domain.Group, error) {
|
|
return g.update(ctx, id, serverID, domain.UpdateGroupParams{
|
|
Internals: domain.NullBool{
|
|
Bool: internals,
|
|
Valid: true,
|
|
},
|
|
})
|
|
}
|
|
|
|
func (g *Group) SetBarbarians(ctx context.Context, id, serverID string, barbarians bool) (domain.Group, error) {
|
|
return g.update(ctx, id, serverID, domain.UpdateGroupParams{
|
|
Barbarians: domain.NullBool{
|
|
Bool: barbarians,
|
|
Valid: true,
|
|
},
|
|
})
|
|
}
|
|
|
|
func (g *Group) update(ctx context.Context, id, serverID string, params domain.UpdateGroupParams) (domain.Group, error) {
|
|
group, err := g.repo.Update(ctx, id, serverID, params)
|
|
if err != nil {
|
|
return domain.Group{}, fmt.Errorf("GroupRepository.Update: %w", err)
|
|
}
|
|
return group, nil
|
|
}
|
|
|
|
func (g *Group) List(ctx context.Context, params domain.ListGroupsParams) ([]domain.Group, error) {
|
|
groups, err := g.repo.List(ctx, params)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("GroupRepository.List: %w", err)
|
|
}
|
|
return groups, nil
|
|
}
|
|
|
|
func (g *Group) Get(ctx context.Context, id, serverID string) (domain.Group, error) {
|
|
group, err := g.repo.Get(ctx, id, serverID)
|
|
if err != nil {
|
|
return domain.Group{}, fmt.Errorf("GroupRepository.Get: %w", err)
|
|
}
|
|
return group, nil
|
|
}
|
|
|
|
func (g *Group) Delete(ctx context.Context, id, serverID string) error {
|
|
if err := g.repo.Delete(ctx, id, serverID); err != nil {
|
|
return fmt.Errorf("GroupRepository.Delete: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (g *Group) CleanUp(ctx context.Context) error {
|
|
if err := g.deleteAllWithDisabledNotifications(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := g.deleteAllWithClosedTWServers(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (g *Group) deleteAllWithDisabledNotifications(ctx context.Context) error {
|
|
groups, err := g.repo.List(ctx, domain.ListGroupsParams{
|
|
EnabledNotifications: domain.NullBool{
|
|
Bool: false,
|
|
Valid: true,
|
|
},
|
|
CreatedAtLTE: time.Now().Add(-24 * time.Hour),
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("GroupRepository.List: %w", err)
|
|
}
|
|
|
|
ids := make([]string, 0, len(groups))
|
|
for _, group := range groups {
|
|
ids = append(ids, group.ID)
|
|
}
|
|
|
|
if err = g.repo.DeleteMany(ctx, ids...); err != nil {
|
|
return fmt.Errorf("GroupRepository.DeleteMany: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (g *Group) deleteAllWithClosedTWServers(ctx context.Context) error {
|
|
versions, err := g.client.ListVersions(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("TWHelpClient.ListVersions: %w", err)
|
|
}
|
|
|
|
for _, v := range versions {
|
|
servers, err := g.client.ListServers(ctx, v.Code, twhelp.ListServersQueryParams{
|
|
Open: twhelp.NullBool{
|
|
Bool: false,
|
|
Valid: true,
|
|
},
|
|
})
|
|
if err != nil {
|
|
g.logger.Warn("failed to fetch closed servers", zap.Error(err), zap.String("versionCode", v.Code))
|
|
continue
|
|
}
|
|
|
|
if len(servers) == 0 {
|
|
continue
|
|
}
|
|
|
|
params := domain.ListGroupsParams{
|
|
VersionCode: domain.NullString{
|
|
String: v.Code,
|
|
Valid: true,
|
|
},
|
|
ServerKeys: make([]string, 0, len(servers)),
|
|
}
|
|
for _, s := range servers {
|
|
params.ServerKeys = append(params.ServerKeys, s.Key)
|
|
}
|
|
|
|
groups, err := g.repo.List(ctx, params)
|
|
if err != nil {
|
|
g.logger.Warn("failed to list groups", zap.Error(err), zap.String("versionCode", v.Code))
|
|
continue
|
|
}
|
|
|
|
if len(groups) == 0 {
|
|
continue
|
|
}
|
|
|
|
ids := make([]string, 0, len(groups))
|
|
for _, group := range groups {
|
|
ids = append(ids, group.ID)
|
|
}
|
|
|
|
if err = g.repo.DeleteMany(ctx, ids...); err != nil {
|
|
g.logger.Warn(
|
|
"failed to delete groups",
|
|
zap.Error(err),
|
|
zap.String("versionCode", v.Code),
|
|
)
|
|
continue
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|