From ea0ff1cb7adc46f9a0cbef9c8fa7592fcecf8ea9 Mon Sep 17 00:00:00 2001 From: James Kwon <96548424+hongil0316@users.noreply.github.com> Date: Tue, 31 Dec 2024 17:53:18 -0500 Subject: [PATCH] Add NoOp DiscordService Implemnetation for staging/dev environments --- gateways/discord/discord.go | 57 ++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/gateways/discord/discord.go b/gateways/discord/discord.go index b1aa854..abb5bbc 100644 --- a/gateways/discord/discord.go +++ b/gateways/discord/discord.go @@ -4,25 +4,37 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/rs/zerolog/log" "net/http" "registry-backend/config" ) +// DiscordService defines the interface for interacting with Discord notifications. type DiscordService interface { SendSecurityCouncilMessage(msg string, private bool) error } -type DripDiscordService struct { +// Ensure discordService struct implements DiscordService interface +var _ DiscordService = (*discordService)(nil) + +// discordService struct holds the configuration and webhook URLs. +type discordService struct { securityDiscordChannelWebhook string securityDiscordPrivateChannelWebhook string config *config.Config } -func NewDiscordService(config *config.Config) *DripDiscordService { - return &DripDiscordService{ - config: config, - securityDiscordChannelWebhook: config.DiscordSecurityChannelWebhook, - securityDiscordPrivateChannelWebhook: config.DiscordSecurityPrivateChannelWebhook, +// NewDiscordService creates a new Discord service using the provided config or returns a no-op implementation if the config is missing. +func NewDiscordService(cfg *config.Config) DiscordService { + if cfg == nil || cfg.DiscordSecurityChannelWebhook == "" { + log.Info().Msg("No Discord configuration found, using no-op implementation") + return &discordNoop{} + } + + return &discordService{ + config: cfg, + securityDiscordChannelWebhook: cfg.DiscordSecurityChannelWebhook, + securityDiscordPrivateChannelWebhook: cfg.DiscordSecurityPrivateChannelWebhook, } } @@ -30,19 +42,21 @@ type discordRequestBody struct { Content string `json:"content"` } -func (s *DripDiscordService) SendSecurityCouncilMessage(msg string, private bool) error { - if s.config.DripEnv == "prod" { - webhookURL := s.securityDiscordChannelWebhook - if private { - webhookURL = s.securityDiscordPrivateChannelWebhook - } - return sendDiscordNotification(msg, webhookURL) - } else { - println("Skipping sending message to Discord in non-prod environment. " + msg) +// SendSecurityCouncilMessage sends a message to the appropriate Discord channel. +func (s *discordService) SendSecurityCouncilMessage(msg string, private bool) error { + if s.config.DripEnv != "prod" { + log.Info().Msgf("Skipping Discord message in non-prod environment: %s", msg) + return nil } - return nil + + webhookURL := s.securityDiscordChannelWebhook + if private { + webhookURL = s.securityDiscordPrivateChannelWebhook + } + return sendDiscordNotification(msg, webhookURL) } +// sendDiscordNotification sends the message to the provided Discord webhook URL. func sendDiscordNotification(msg string, discordWebhookURL string) error { if discordWebhookURL == "" { return fmt.Errorf("no Discord webhook URL provided, skipping sending message to Discord") @@ -69,9 +83,18 @@ func sendDiscordNotification(msg string, discordWebhookURL string) error { defer resp.Body.Close() if resp.StatusCode >= 400 { - // You can handle or log the HTTP error status code here return fmt.Errorf("request to Discord returned error status: %d", resp.StatusCode) } return nil } + +// discordNoop is a no-op implementation of the DiscordService interface. +// It does nothing and is used when no valid config is provided. +type discordNoop struct{} + +// SendSecurityCouncilMessage is a no-op implementation that simply returns nil. +func (s *discordNoop) SendSecurityCouncilMessage(msg string, private bool) error { + log.Info().Msgf("No-op: Skipping Discord message: %s (private: %v)", msg, private) + return nil +}