feat: add a new command - monitor list
All checks were successful
continuous-integration/drone/pr Build is passing
All checks were successful
continuous-integration/drone/pr Build is passing
This commit is contained in:
parent
de19857b34
commit
6f20736671
1
go.mod
1
go.mod
|
@ -5,6 +5,7 @@ go 1.19
|
|||
require (
|
||||
github.com/bwmarrin/discordgo v0.26.1
|
||||
github.com/cenkalti/backoff/v4 v4.1.3
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/ory/dockertest/v3 v3.9.1
|
||||
|
|
3
go.sum
3
go.sum
|
@ -49,7 +49,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
|
|
|
@ -20,6 +20,7 @@ type GroupService interface {
|
|||
|
||||
type MonitorService interface {
|
||||
Create(ctx context.Context, groupID, serverID, tribeTag string) (domain.Monitor, error)
|
||||
List(ctx context.Context, groupID, serverID string) ([]domain.MonitorWithTribe, error)
|
||||
Execute(ctx context.Context) ([]domain.EnnoblementNotification, error)
|
||||
Delete(ctx context.Context, id, serverID string) error
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package discord
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gitea.dwysokinski.me/twhelp/dcbot/internal/domain"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
|
@ -57,6 +59,19 @@ func (c *monitorCommand) create(s *discordgo.Session) error {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "list",
|
||||
Description: "Lists all monitors associated with a particular group",
|
||||
Type: discordgo.ApplicationCommandOptionSubCommand,
|
||||
Options: []*discordgo.ApplicationCommandOption{
|
||||
{
|
||||
Name: "group",
|
||||
Description: "Group ID",
|
||||
Type: discordgo.ApplicationCommandOptionString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "delete",
|
||||
Description: "Deletes a monitor",
|
||||
|
@ -90,6 +105,9 @@ func (c *monitorCommand) handle(s *discordgo.Session, i *discordgo.InteractionCr
|
|||
case "create":
|
||||
c.handleCreate(s, i)
|
||||
return
|
||||
case "list":
|
||||
c.handleList(s, i)
|
||||
return
|
||||
case "delete":
|
||||
c.handleDelete(s, i)
|
||||
return
|
||||
|
@ -133,6 +151,36 @@ func (c *monitorCommand) handleCreate(s *discordgo.Session, i *discordgo.Interac
|
|||
})
|
||||
}
|
||||
|
||||
func (c *monitorCommand) handleList(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
ctx := context.Background()
|
||||
|
||||
group := i.ApplicationCommandData().Options[0].Options[0].StringValue()
|
||||
monitors, err := c.svc.List(ctx, group, i.GuildID)
|
||||
if err != nil {
|
||||
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: messageFromError(err),
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Embeds: []*discordgo.MessageEmbed{
|
||||
{
|
||||
Type: discordgo.EmbedTypeRich,
|
||||
Title: "Monitor list",
|
||||
Description: buildMonitorListDescription(monitors),
|
||||
Timestamp: formatTimestamp(time.Now()),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (c *monitorCommand) handleDelete(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
ctx := context.Background()
|
||||
|
||||
|
@ -154,3 +202,11 @@ func (c *monitorCommand) handleDelete(s *discordgo.Session, i *discordgo.Interac
|
|||
},
|
||||
})
|
||||
}
|
||||
|
||||
func buildMonitorListDescription(monitors []domain.MonitorWithTribe) string {
|
||||
description := "**ID** - **Tribe**"
|
||||
for i, m := range monitors {
|
||||
description += fmt.Sprintf("\n%d. %s - %s", i+1, m.ID, buildLink(m.Tribe.Tag, m.Tribe.ProfileURL))
|
||||
}
|
||||
return description
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@ type Monitor struct {
|
|||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type MonitorWithTribe struct {
|
||||
Monitor
|
||||
Tribe TribeMeta
|
||||
}
|
||||
|
||||
type CreateMonitorParams struct {
|
||||
tribeID int64
|
||||
groupID string
|
||||
|
|
|
@ -103,6 +103,74 @@ func (m *Monitor) Create(ctx context.Context, groupID, serverID, tribeTag string
|
|||
return monitor, nil
|
||||
}
|
||||
|
||||
type getTribeResult struct {
|
||||
monitor domain.Monitor
|
||||
tribe twhelp.Tribe
|
||||
err error
|
||||
}
|
||||
|
||||
func (m *Monitor) List(ctx context.Context, groupID, serverID string) ([]domain.MonitorWithTribe, error) {
|
||||
group, err := m.groupSvc.Get(ctx, groupID, serverID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GroupService.Get: %w", err)
|
||||
}
|
||||
|
||||
monitors, err := m.repo.List(ctx, group.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("MonitorRepository.Delete: %w", err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
ch := make(chan getTribeResult)
|
||||
|
||||
for _, monitor := range monitors {
|
||||
wg.Add(1)
|
||||
go func(monitor domain.Monitor) {
|
||||
res := getTribeResult{
|
||||
monitor: monitor,
|
||||
}
|
||||
res.tribe, res.err = m.client.GetTribeByID(
|
||||
ctx,
|
||||
group.VersionCode,
|
||||
group.ServerKey,
|
||||
monitor.TribeID,
|
||||
)
|
||||
ch <- res
|
||||
}(monitor)
|
||||
}
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
var firstErr error
|
||||
results := make([]domain.MonitorWithTribe, 0, len(monitors))
|
||||
for res := range ch {
|
||||
wg.Done()
|
||||
|
||||
if res.err != nil && firstErr == nil {
|
||||
firstErr = fmt.Errorf("couldn't load tribe (monitorID=%s): %w", res.monitor.ID, res.err)
|
||||
continue
|
||||
}
|
||||
|
||||
results = append(results, domain.MonitorWithTribe{
|
||||
Monitor: res.monitor,
|
||||
Tribe: domain.TribeMeta{
|
||||
ID: res.tribe.ID,
|
||||
Name: res.tribe.Name,
|
||||
Tag: res.tribe.Tag,
|
||||
ProfileURL: res.tribe.ProfileURL,
|
||||
},
|
||||
})
|
||||
}
|
||||
if firstErr != nil {
|
||||
return nil, firstErr
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (m *Monitor) Delete(ctx context.Context, id, serverID string) error {
|
||||
monitor, err := m.repo.Get(ctx, id)
|
||||
if err != nil {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"gitea.dwysokinski.me/twhelp/dcbot/internal/service"
|
||||
"gitea.dwysokinski.me/twhelp/dcbot/internal/service/internal/mock"
|
||||
"gitea.dwysokinski.me/twhelp/dcbot/internal/twhelp"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -195,6 +196,71 @@ func TestMonitor_Create(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestMonitor_List(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
groupID := uuid.NewString()
|
||||
groupSvc := &mock.FakeGroupReader{}
|
||||
groupSvc.GetCalls(func(ctx context.Context, groupID, serverID string) (domain.Group, error) {
|
||||
return domain.Group{
|
||||
ID: groupID,
|
||||
ServerID: serverID,
|
||||
ChannelGains: "",
|
||||
ChannelLosses: "",
|
||||
ServerKey: "pl151",
|
||||
VersionCode: "pl",
|
||||
CreatedAt: time.Now(),
|
||||
}, nil
|
||||
})
|
||||
|
||||
repo := &mock.FakeMonitorRepository{}
|
||||
monitors := []domain.Monitor{
|
||||
{
|
||||
ID: uuid.NewString(),
|
||||
TribeID: 124,
|
||||
GroupID: groupID,
|
||||
CreatedAt: time.Now(),
|
||||
},
|
||||
{
|
||||
ID: uuid.NewString(),
|
||||
TribeID: 125,
|
||||
GroupID: groupID,
|
||||
CreatedAt: time.Now(),
|
||||
},
|
||||
}
|
||||
repo.ListReturns(monitors, nil)
|
||||
|
||||
client := &mock.FakeTWHelpClient{}
|
||||
client.GetTribeByIDCalls(func(ctx context.Context, _ string, _ string, id int64) (twhelp.Tribe, error) {
|
||||
return twhelp.Tribe{
|
||||
ID: id,
|
||||
Tag: uuid.NewString(),
|
||||
Name: uuid.NewString(),
|
||||
ProfileURL: uuid.NewString(),
|
||||
DeletedAt: time.Time{},
|
||||
}, nil
|
||||
})
|
||||
|
||||
res, err := service.NewMonitor(repo, groupSvc, client, 10).
|
||||
List(context.Background(), groupID, uuid.NewString())
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, res, len(monitors))
|
||||
for _, m1 := range monitors {
|
||||
var exist bool
|
||||
for _, m2 := range res {
|
||||
if cmp.Equal(m1, m2.Monitor) && m1.TribeID == m2.Tribe.ID {
|
||||
exist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, exist)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestMonitor_Execute(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
type TWHelpClient interface {
|
||||
ListVersions(ctx context.Context) ([]twhelp.Version, error)
|
||||
GetServer(ctx context.Context, version, server string) (twhelp.Server, error)
|
||||
GetTribeByID(ctx context.Context, version, server string, id int64) (twhelp.Tribe, error)
|
||||
GetTribeByTag(ctx context.Context, version, server, tag string) (twhelp.Tribe, error)
|
||||
ListEnnoblements(
|
||||
ctx context.Context,
|
||||
|
|
|
@ -17,6 +17,7 @@ const (
|
|||
|
||||
endpointListVersions = "/api/v1/versions"
|
||||
endpointGetServer = "/api/v1/versions/%s/servers/%s"
|
||||
endpointGetTribeByID = "/api/v1/versions/%s/servers/%s/tribes/%d"
|
||||
endpointGetTribeByTag = "/api/v1/versions/%s/servers/%s/tribes/tag/%s"
|
||||
endpointListEnnoblements = "/api/v1/versions/%s/servers/%s/ennoblements"
|
||||
)
|
||||
|
@ -71,6 +72,14 @@ func (c *Client) GetServer(ctx context.Context, version, server string) (Server,
|
|||
return resp.Data, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetTribeByID(ctx context.Context, version, server string, id int64) (Tribe, error) {
|
||||
var resp getTribeResp
|
||||
if err := c.getJSON(ctx, fmt.Sprintf(endpointGetTribeByID, version, server, id), &resp); err != nil {
|
||||
return Tribe{}, err
|
||||
}
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetTribeByTag(ctx context.Context, version, server, tag string) (Tribe, error) {
|
||||
var resp getTribeResp
|
||||
if err := c.getJSON(ctx, fmt.Sprintf(endpointGetTribeByTag, version, server, tag), &resp); err != nil {
|
||||
|
|
Loading…
Reference in New Issue
Block a user