Skip to content

Commit

Permalink
feat: brainery report command (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
namnhce authored Jun 23, 2023
1 parent e3e03c7 commit 9bab603
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 63 deletions.
29 changes: 29 additions & 0 deletions pkg/adapter/fortress/fortress.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,32 @@ func (f *Fortress) CreateBraineryPost(post *model.CreateBraineryLogRequest) erro

return nil
}

func (f *Fortress) GetBraineryReport(view string) (report *model.BraineryMetric, err error) {
req, err := f.makeReq("/api/v1/brainery-logs/metrics", http.MethodGet, nil)
if err != nil {
return nil, err
}

q := req.URL.Query()
q.Add("view", view)
req.URL.RawQuery = q.Encode()

resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("invalid call, code %v", resp.StatusCode)
}

var braineryMetricResp model.BraineryMetricResponse

if err := json.NewDecoder(resp.Body).Decode(&braineryMetricResp); err != nil {
return nil, fmt.Errorf("invalid decoded, error %v", err.Error())
}

return &braineryMetricResp.Data, nil
}
1 change: 1 addition & 0 deletions pkg/adapter/fortress/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ type FortressAdapter interface {
UpsertRollupRecord(record *model.EngagementsRollupRecord) error

CreateBraineryPost(post *model.CreateBraineryLogRequest) error
GetBraineryReport(view string) (*model.BraineryMetric, error)
}
6 changes: 4 additions & 2 deletions pkg/discord/command/brainery/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ func (e *Brainery) Execute(message *model.DiscordMessage) error {
switch message.ContentArgs[1] {
case "post":
return e.Post(message)
case "report":
return e.Report(message)
default:
return e.DefaultCommand(message)
}

return nil
}

func (e *Brainery) Name() string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,22 @@ import (
"strings"
"time"

"github.com/dwarvesf/fortress-discord/pkg/config"
"github.com/dwarvesf/fortress-discord/pkg/constant"
"github.com/dwarvesf/fortress-discord/pkg/discord/service"
"github.com/dwarvesf/fortress-discord/pkg/discord/service/brainery"
"github.com/dwarvesf/fortress-discord/pkg/discord/view"
"github.com/dwarvesf/fortress-discord/pkg/logger"
"github.com/dwarvesf/fortress-discord/pkg/model"
)

type Brainery struct {
L logger.Logger
svc service.Servicer
view view.Viewer
cfg *config.Config
}

func New(l logger.Logger, svc service.Servicer, view view.Viewer, cfg *config.Config) Commander {
return &Brainery{
L: l,
svc: svc,
view: view,
cfg: cfg,
}
}

var (
discordIDRegexPattern = `<@(\d+)>`
tagRegexPattern = `#(\w+)`
icyRewardRegexPattern = ` (\d+)`
urlRegexPattern = `((?:https?://)[^\s]+)`
githubRegexPattern = `gh:(\w+)`
descriptionRegexPattern = `d:"(.*?)"`
const (
discordChannelIDRegexPattern = `<#(\d+)>`
discordIDRegexPattern = `<@(\d+)>`
tagRegexPattern = `#(\w+)`
icyRewardRegexPattern = ` (\d+)`
urlRegexPattern = `((?:https?://)[^\s]+)`
githubRegexPattern = `gh:(\w+)`
descriptionRegexPattern = `d:"(.*?)"`
defaultBraineryReward = "0"
)

const defaultBraineryReward = "0"

func (e *Brainery) Post(message *model.DiscordMessage) error {
targetChannelID := constant.DiscordBraineryChannel
if e.cfg.Env == "dev" {
Expand Down
38 changes: 38 additions & 0 deletions pkg/discord/command/brainery/brainery_report.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package brainery

import (
"strings"

"github.com/dwarvesf/fortress-discord/pkg/model"
)

func (e *Brainery) Report(message *model.DiscordMessage) error {
rawFormattedContent := formatString(message.RawContent)
args := strings.Split(rawFormattedContent, " ")
targetChannelID := message.ChannelId

reportView := "weekly"
if len(args) > 1 {
reportView = args[2]
}

if !(reportView == "weekly" || reportView == "monthly") {
return e.view.Error().Raise(message, "Report view should be weekly or monthly")
}

extractChannelID := extractPattern(rawFormattedContent, discordChannelIDRegexPattern)
if len(extractChannelID) > 1 {
return e.view.Error().Raise(message, "There is more than one target channel in your message.")
}

if len(extractChannelID) == 1 {
targetChannelID = extractChannelID[0]
}

result, err := e.svc.Brainery().Report(reportView)
if err != nil {
return e.view.Error().Raise(message, err.Error())
}

return e.view.Brainery().Report(message, reportView, result, targetChannelID)
}
21 changes: 21 additions & 0 deletions pkg/discord/command/brainery/interface.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
package brainery

import (
"github.com/dwarvesf/fortress-discord/pkg/config"
"github.com/dwarvesf/fortress-discord/pkg/discord/base"
"github.com/dwarvesf/fortress-discord/pkg/discord/service"
"github.com/dwarvesf/fortress-discord/pkg/discord/view"
"github.com/dwarvesf/fortress-discord/pkg/logger"
"github.com/dwarvesf/fortress-discord/pkg/model"
)

type Brainery struct {
L logger.Logger
svc service.Servicer
view view.Viewer
cfg *config.Config
}

func New(l logger.Logger, svc service.Servicer, view view.Viewer, cfg *config.Config) Commander {
return &Brainery{
L: l,
svc: svc,
view: view,
cfg: cfg,
}
}

type Commander interface {
base.TextCommander

Post(message *model.DiscordMessage) error
Report(message *model.DiscordMessage) error
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,9 @@ import (
"github.com/PuerkitoBio/goquery"
"github.com/shopspring/decimal"

"github.com/dwarvesf/fortress-discord/pkg/adapter"
"github.com/dwarvesf/fortress-discord/pkg/logger"
"github.com/dwarvesf/fortress-discord/pkg/model"
)

type Brainery struct {
adapter adapter.IAdapter
l logger.Logger
}

func New(adapter adapter.IAdapter, l logger.Logger) Service {
return &Brainery{
adapter: adapter,
l: l,
}
}

type PostInput struct {
URL string
Author string
Reward string
Description string
PublishedAt *time.Time
Tags []string
Github string
DiscordID string
}

func (e *Brainery) Post(in *PostInput) (*model.Brainery, error) {
title, err := getTitle(in.URL)
if err != nil {
Expand Down
14 changes: 14 additions & 0 deletions pkg/discord/service/brainery/brainery_report.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package brainery

import (
"github.com/dwarvesf/fortress-discord/pkg/model"
)

func (e *Brainery) Report(view string) (*model.BraineryMetric, error) {
data, err := e.adapter.Fortress().GetBraineryReport(view)
if err != nil {
return nil, err
}

return data, nil
}
32 changes: 31 additions & 1 deletion pkg/discord/service/brainery/interface.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,37 @@
package brainery

import "github.com/dwarvesf/fortress-discord/pkg/model"
import (
"time"

"github.com/dwarvesf/fortress-discord/pkg/adapter"
"github.com/dwarvesf/fortress-discord/pkg/logger"
"github.com/dwarvesf/fortress-discord/pkg/model"
)

type Brainery struct {
adapter adapter.IAdapter
l logger.Logger
}

func New(adapter adapter.IAdapter, l logger.Logger) Service {
return &Brainery{
adapter: adapter,
l: l,
}
}

type PostInput struct {
URL string
Author string
Reward string
Description string
PublishedAt *time.Time
Tags []string
Github string
DiscordID string
}

type Service interface {
Post(in *PostInput) (*model.Brainery, error)
Report(view string) (*model.BraineryMetric, error)
}
88 changes: 82 additions & 6 deletions pkg/discord/view/brainery/brainery.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package brainery

import (
"fmt"
"github.com/bwmarrin/discordgo"
"strings"

"github.com/bwmarrin/discordgo"
"github.com/shopspring/decimal"

"github.com/dwarvesf/fortress-discord/pkg/discord/view/base"
"github.com/dwarvesf/fortress-discord/pkg/model"
)
Expand All @@ -19,22 +21,24 @@ func New(ses *discordgo.Session) Viewer {
}
}

func (h *Brainery) Help(message *model.DiscordMessage) error {
func (v *Brainery) Help(message *model.DiscordMessage) error {
content := []string{
"**?brainery post**・publish new brainery article.",
"*Example:* `?brainery post <url> @n #tag1 #tag2 gh:namnhce`",
"**?brainery report**・get brainery report by week/month.",
"*Example:* `?brainery report weekly`",
}

msg := &discordgo.MessageEmbed{
Title: "**Welcome to Fortress Discord bot**",
Description: strings.Join(content, "\n"),
}

return base.SendEmbededMessage(h.ses, message, msg)
return base.SendEmbededMessage(v.ses, message, msg)
}

func (h *Brainery) Post(original *model.DiscordMessage, content *model.Brainery, channelID string) error {
author, err := h.ses.GuildMember(original.GuildId, content.DiscordID)
func (v *Brainery) Post(original *model.DiscordMessage, content *model.Brainery, channelID string) error {
author, err := v.ses.GuildMember(original.GuildId, content.DiscordID)
if err != nil {
return err
}
Expand Down Expand Up @@ -82,5 +86,77 @@ func (h *Brainery) Post(original *model.DiscordMessage, content *model.Brainery,
},
}

return base.SendEmbededMessageWithChannel(h.ses, original, msg, channelID)
return base.SendEmbededMessageWithChannel(v.ses, original, msg, channelID)
}

func (v *Brainery) Report(original *model.DiscordMessage, view string, braineryMetric *model.BraineryMetric, channelID string) error {
var messageEmbed []*discordgo.MessageEmbedField
totalICY := decimal.NewFromInt(0)
latestPost := "This is where we keep track of our **top 10** latest Brainery notes:\n\n"
if braineryMetric.LatestPosts != nil {
for _, post := range braineryMetric.LatestPosts {
latestPost += fmt.Sprintf("• [%s](%s)\n", post.Title, post.URL)
}
}

contributors := ""
if len(braineryMetric.Contributors) > 0 {
for _, itm := range braineryMetric.Contributors {
totalICY = totalICY.Add(itm.Reward)
contributors += fmt.Sprintf("• <@%v> - [%s](%s)\n", itm.DiscordID, itm.Title, itm.URL)
}
}

if len(contributors) > 0 {
latestPost += "**\nContributors**\n"
latestPost += contributors
}

newContributor := ""
if len(braineryMetric.NewContributors) > 0 {
for _, itm := range braineryMetric.NewContributors {
totalICY = totalICY.Add(itm.Reward)
newContributor += fmt.Sprintf("• <@%v> - [%s](%s)\n", itm.DiscordID, itm.Title, itm.URL)
}
}

if len(newContributor) > 0 {
latestPost += "\n**New Contributors**\n"
latestPost += newContributor
}

if totalICY.GreaterThan(decimal.NewFromInt(0)) {
embedField := &discordgo.MessageEmbedField{
Name: "Total ICY Given Out",
Value: totalICY.String() + " ICY 🧊",
Inline: false,
}

messageEmbed = append(messageEmbed, embedField)
}

tags := ""
if len(braineryMetric.Tags) > 0 {
for _, tag := range braineryMetric.Tags {
tags += fmt.Sprintf("#%v ", tag)
}
}

if len(tags) > 0 {
embedField := &discordgo.MessageEmbedField{
Name: "Tags",
Value: tags,
Inline: false,
}

messageEmbed = append(messageEmbed, embedField)
}

msg := &discordgo.MessageEmbed{
Title: fmt.Sprintf("BRAINERY %s REPORT ", strings.ToTitle(view)),
Fields: messageEmbed,
Description: latestPost,
}

return base.SendEmbededMessageWithChannel(v.ses, original, msg, channelID)
}
1 change: 1 addition & 0 deletions pkg/discord/view/brainery/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import "github.com/dwarvesf/fortress-discord/pkg/model"
type Viewer interface {
Help(message *model.DiscordMessage) error
Post(original *model.DiscordMessage, content *model.Brainery, channelID string) error
Report(original *model.DiscordMessage, view string, braineryMetric *model.BraineryMetric, channelID string) error
}
Loading

0 comments on commit 9bab603

Please sign in to comment.