From aa15dc793bd973d5351fc4a51ce59ad65e28c07b Mon Sep 17 00:00:00 2001
From: Sergey <83376337+freak12techno@users.noreply.github.com>
Date: Sun, 12 May 2024 02:21:03 +0300
Subject: [PATCH] feat: move templates manager to class (#85)
* feat: move templates manager to class
* chore: fixed linting
* chore: added tests for templates manager
* chore: fixed linting
---
pkg/reporters/telegram/add_mute.go | 13 ++-
pkg/reporters/telegram/help.go | 13 ++-
pkg/reporters/telegram/list_mutes.go | 12 ++-
pkg/reporters/telegram/list_proposals.go | 12 ++-
pkg/reporters/telegram/params.go | 17 +---
pkg/reporters/telegram/tally.go | 17 +---
pkg/reporters/telegram/telegram.go | 88 ++++--------------
pkg/templates/manager.go | 5 ++
pkg/templates/telegram.go | 88 ++++++++++++++++++
pkg/templates/telegram_test.go | 108 +++++++++++++++++++++++
templates/telegram/help.html | 2 +-
11 files changed, 247 insertions(+), 128 deletions(-)
create mode 100644 pkg/templates/manager.go
create mode 100644 pkg/templates/telegram.go
create mode 100644 pkg/templates/telegram_test.go
diff --git a/pkg/reporters/telegram/add_mute.go b/pkg/reporters/telegram/add_mute.go
index d097178..f453158 100644
--- a/pkg/reporters/telegram/add_mute.go
+++ b/pkg/reporters/telegram/add_mute.go
@@ -1,8 +1,6 @@
package telegram
import (
- "bytes"
-
tele "gopkg.in/telebot.v3"
)
@@ -19,12 +17,11 @@ func (reporter *Reporter) HandleAddMute(c tele.Context) error {
reporter.MutesManager.AddMute(mute)
- template, _ := reporter.GetTemplate("mute_added")
- var buffer bytes.Buffer
- if err := template.Execute(&buffer, mute); err != nil {
- reporter.Logger.Error().Err(err).Msg("Error rendering mute_added template")
- return err
+ templateRendered, renderErr := reporter.TemplatesManager.Render("mute_added", mute)
+ if renderErr != nil {
+ reporter.Logger.Error().Err(renderErr).Msg("Error rendering template")
+ return reporter.BotReply(c, "Error rendering template")
}
- return reporter.BotReply(c, buffer.String())
+ return reporter.BotReply(c, templateRendered)
}
diff --git a/pkg/reporters/telegram/help.go b/pkg/reporters/telegram/help.go
index 394f520..a11023b 100644
--- a/pkg/reporters/telegram/help.go
+++ b/pkg/reporters/telegram/help.go
@@ -1,8 +1,6 @@
package telegram
import (
- "bytes"
-
tele "gopkg.in/telebot.v3"
)
@@ -12,12 +10,11 @@ func (reporter *Reporter) HandleHelp(c tele.Context) error {
Str("text", c.Text()).
Msg("Got help query")
- template, _ := reporter.GetTemplate("help")
- var buffer bytes.Buffer
- if err := template.Execute(&buffer, reporter.Version); err != nil {
- reporter.Logger.Error().Err(err).Msg("Error rendering help template")
- return err
+ template, err := reporter.TemplatesManager.Render("help", reporter.Version)
+ if err != nil {
+ reporter.Logger.Error().Err(err).Msg("Error rendering template")
+ return reporter.BotReply(c, "Error rendering template")
}
- return reporter.BotReply(c, buffer.String())
+ return reporter.BotReply(c, template)
}
diff --git a/pkg/reporters/telegram/list_mutes.go b/pkg/reporters/telegram/list_mutes.go
index 54e1f21..467c79a 100644
--- a/pkg/reporters/telegram/list_mutes.go
+++ b/pkg/reporters/telegram/list_mutes.go
@@ -1,7 +1,6 @@
package telegram
import (
- "bytes"
mutes "main/pkg/mutes"
"main/pkg/utils"
@@ -18,12 +17,11 @@ func (reporter *Reporter) HandleListMutes(c tele.Context) error {
return !m.IsExpired()
})
- template, _ := reporter.GetTemplate("mutes")
- var buffer bytes.Buffer
- if err := template.Execute(&buffer, filteredMutes); err != nil {
- reporter.Logger.Error().Err(err).Msg("Error rendering votes template")
- return err
+ template, err := reporter.TemplatesManager.Render("mutes", filteredMutes)
+ if err != nil {
+ reporter.Logger.Error().Err(err).Msg("Error rendering template")
+ return reporter.BotReply(c, "Error rendering template")
}
- return reporter.BotReply(c, buffer.String())
+ return reporter.BotReply(c, template)
}
diff --git a/pkg/reporters/telegram/list_proposals.go b/pkg/reporters/telegram/list_proposals.go
index 8c8a47a..1674641 100644
--- a/pkg/reporters/telegram/list_proposals.go
+++ b/pkg/reporters/telegram/list_proposals.go
@@ -1,7 +1,6 @@
package telegram
import (
- "bytes"
statePkg "main/pkg/state"
tele "gopkg.in/telebot.v3"
@@ -16,12 +15,11 @@ func (reporter *Reporter) HandleProposals(c tele.Context) error {
state := reporter.StateGenerator.GetState(statePkg.NewState())
renderedState := state.ToRenderedState()
- template, _ := reporter.GetTemplate("proposals")
- var buffer bytes.Buffer
- if err := template.Execute(&buffer, renderedState); err != nil {
- reporter.Logger.Error().Err(err).Msg("Error rendering proposals template")
- return err
+ template, err := reporter.TemplatesManager.Render("proposals", renderedState)
+ if err != nil {
+ reporter.Logger.Error().Err(err).Msg("Error rendering template")
+ return reporter.BotReply(c, "Error rendering template")
}
- return reporter.BotReply(c, buffer.String())
+ return reporter.BotReply(c, template)
}
diff --git a/pkg/reporters/telegram/params.go b/pkg/reporters/telegram/params.go
index 9f415ee..966cb2f 100644
--- a/pkg/reporters/telegram/params.go
+++ b/pkg/reporters/telegram/params.go
@@ -1,7 +1,6 @@
package telegram
import (
- "bytes"
"fmt"
tele "gopkg.in/telebot.v3"
@@ -18,19 +17,11 @@ func (reporter *Reporter) HandleParams(c tele.Context) error {
return reporter.BotReply(c, fmt.Sprintf("Error getting chain params: %s", err))
}
- template, err := reporter.GetTemplate("params")
+ template, err := reporter.TemplatesManager.Render("params", params)
if err != nil {
- reporter.Logger.Error().
- Err(err).
- Msg("Error rendering params template")
- return reporter.BotReply(c, "Error rendering params template")
+ reporter.Logger.Error().Err(err).Msg("Error rendering template")
+ return reporter.BotReply(c, "Error rendering template")
}
- var buffer bytes.Buffer
- if err := template.Execute(&buffer, params); err != nil {
- reporter.Logger.Error().Err(err).Msg("Error rendering params template")
- return err
- }
-
- return reporter.BotReply(c, buffer.String())
+ return reporter.BotReply(c, template)
}
diff --git a/pkg/reporters/telegram/tally.go b/pkg/reporters/telegram/tally.go
index 38e19a1..3c46521 100644
--- a/pkg/reporters/telegram/tally.go
+++ b/pkg/reporters/telegram/tally.go
@@ -1,7 +1,6 @@
package telegram
import (
- "bytes"
"fmt"
tele "gopkg.in/telebot.v3"
@@ -22,19 +21,11 @@ func (reporter *Reporter) HandleTally(c tele.Context) error {
return reporter.BotReply(c, fmt.Sprintf("Error getting tallies info: %s", err))
}
- template, err := reporter.GetTemplate("tally")
+ template, err := reporter.TemplatesManager.Render("tally", tallies)
if err != nil {
- reporter.Logger.Error().
- Err(err).
- Msg("Error rendering tallies template")
- return reporter.BotReply(c, "Error rendering tallies template")
+ reporter.Logger.Error().Err(err).Msg("Error rendering template")
+ return reporter.BotReply(c, "Error rendering template")
}
- var buffer bytes.Buffer
- if err := template.Execute(&buffer, tallies); err != nil {
- reporter.Logger.Error().Err(err).Msg("Error rendering votes template")
- return err
- }
-
- return reporter.BotReply(c, buffer.String())
+ return reporter.BotReply(c, template)
}
diff --git a/pkg/reporters/telegram/telegram.go b/pkg/reporters/telegram/telegram.go
index b81d100..ddfa405 100644
--- a/pkg/reporters/telegram/telegram.go
+++ b/pkg/reporters/telegram/telegram.go
@@ -1,38 +1,34 @@
package telegram
import (
- "bytes"
"fmt"
- "html/template"
"main/pkg/data"
mutes "main/pkg/mutes"
"main/pkg/report/entry"
"main/pkg/state"
- "main/pkg/utils"
+ "main/pkg/templates"
"strings"
"time"
"main/pkg/reporters"
"main/pkg/types"
- "main/templates"
"github.com/rs/zerolog"
tele "gopkg.in/telebot.v3"
)
type Reporter struct {
- TelegramToken string
- TelegramChat int64
- MutesManager *mutes.Manager
- StateGenerator *state.Generator
- DataManager *data.Manager
+ TelegramToken string
+ TelegramChat int64
+ MutesManager *mutes.Manager
+ StateGenerator *state.Generator
+ DataManager *data.Manager
+ TemplatesManager templates.Manager
TelegramBot *tele.Bot
Logger zerolog.Logger
- Templates map[string]*template.Template
- Version string
- Timezone *time.Location
+ Version string
}
const (
@@ -49,15 +45,14 @@ func NewTelegramReporter(
timezone *time.Location,
) *Reporter {
return &Reporter{
- TelegramToken: config.TelegramToken,
- TelegramChat: config.TelegramChat,
- MutesManager: mutesManager,
- StateGenerator: stateGenerator,
- DataManager: dataManager,
- Logger: logger.With().Str("component", "telegram_reporter").Logger(),
- Templates: make(map[string]*template.Template, 0),
- Version: version,
- Timezone: timezone,
+ TelegramToken: config.TelegramToken,
+ TelegramChat: config.TelegramChat,
+ MutesManager: mutesManager,
+ StateGenerator: stateGenerator,
+ DataManager: dataManager,
+ Logger: logger.With().Str("component", "telegram_reporter").Logger(),
+ TemplatesManager: templates.NewTelegramTemplatesManager(logger, timezone),
+ Version: version,
}
}
@@ -95,45 +90,8 @@ func (reporter *Reporter) Enabled() bool {
return reporter.TelegramToken != "" && reporter.TelegramChat != 0
}
-func (reporter *Reporter) GetTemplate(tmlpType string) (*template.Template, error) {
- if cachedTemplate, ok := reporter.Templates[tmlpType]; ok {
- reporter.Logger.Trace().Str("type", tmlpType).Msg("Using cached template")
- return cachedTemplate, nil
- }
-
- reporter.Logger.Trace().Str("type", tmlpType).Msg("Loading template")
-
- filename := tmlpType + ".html"
-
- t, err := template.New(filename).Funcs(template.FuncMap{
- "SerializeLink": reporter.SerializeLink,
- "SerializeDate": reporter.SerializeDate,
- "FormatDuration": utils.FormatDuration,
- }).ParseFS(templates.TemplatesFs, "telegram/"+filename)
- if err != nil {
- return nil, err
- }
-
- reporter.Templates[tmlpType] = t
-
- return t, nil
-}
-
func (reporter *Reporter) SerializeReportEntry(e entry.ReportEntry) (string, error) {
- parsedTemplate, err := reporter.GetTemplate(e.Name())
- if err != nil {
- reporter.Logger.Error().Err(err).Str("type", e.Name()).Msg("Error loading template")
- return "", err
- }
-
- var buffer bytes.Buffer
- err = parsedTemplate.Execute(&buffer, e)
- if err != nil {
- reporter.Logger.Error().Err(err).Str("type", e.Name()).Msg("Error rendering template")
- return "", err
- }
-
- return buffer.String(), nil
+ return reporter.TemplatesManager.Render(e.Name(), e)
}
func (reporter *Reporter) SendReport(report reporters.Report) error {
@@ -247,15 +205,3 @@ func ParseMuteOptions(query string, c tele.Context) (*mutes.Mute, string) {
return mute, ""
}
-
-func (reporter *Reporter) SerializeLink(link types.Link) template.HTML {
- if link.Href != "" {
- return template.HTML(fmt.Sprintf("%s", link.Href, link.Name))
- }
-
- return template.HTML(link.Name)
-}
-
-func (reporter *Reporter) SerializeDate(date time.Time) string {
- return date.In(reporter.Timezone).Format(time.RFC1123)
-}
diff --git a/pkg/templates/manager.go b/pkg/templates/manager.go
new file mode 100644
index 0000000..1952026
--- /dev/null
+++ b/pkg/templates/manager.go
@@ -0,0 +1,5 @@
+package templates
+
+type Manager interface {
+ Render(templateName string, data interface{}) (string, error)
+}
diff --git a/pkg/templates/telegram.go b/pkg/templates/telegram.go
new file mode 100644
index 0000000..594b0a0
--- /dev/null
+++ b/pkg/templates/telegram.go
@@ -0,0 +1,88 @@
+package templates
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "main/pkg/types"
+ "main/pkg/utils"
+ "main/templates"
+ "time"
+
+ "github.com/rs/zerolog"
+)
+
+type TelegramTemplatesManager struct {
+ Templates map[string]*template.Template
+ Logger zerolog.Logger
+ Timezone *time.Location
+}
+
+func NewTelegramTemplatesManager(
+ logger *zerolog.Logger,
+ timezone *time.Location,
+) *TelegramTemplatesManager {
+ return &TelegramTemplatesManager{
+ Templates: map[string]*template.Template{},
+ Logger: logger.With().Str("component", "telegram_templates_manager").Logger(),
+ Timezone: timezone,
+ }
+}
+
+func (m *TelegramTemplatesManager) Render(templateName string, data interface{}) (string, error) {
+ templateToRender, err := m.GetTemplate(templateName)
+ if err != nil {
+ m.Logger.Error().
+ Err(err).
+ Str("name", templateName).
+ Msg("Error getting template")
+ return "", err
+ }
+
+ var buffer bytes.Buffer
+ if err := templateToRender.Execute(&buffer, data); err != nil {
+ m.Logger.Error().
+ Err(err).
+ Str("name", templateName).
+ Msg("Error rendering template")
+ return "", err
+ }
+
+ return buffer.String(), nil
+}
+
+func (m *TelegramTemplatesManager) GetTemplate(templateName string) (*template.Template, error) {
+ if cachedTemplate, ok := m.Templates[templateName]; ok {
+ m.Logger.Trace().Str("type", templateName).Msg("Using cached template")
+ return cachedTemplate, nil
+ }
+
+ m.Logger.Trace().Str("type", templateName).Msg("Loading template")
+
+ filename := templateName + ".html"
+
+ t, err := template.New(filename).Funcs(template.FuncMap{
+ "SerializeLink": m.SerializeLink,
+ "SerializeDate": m.SerializeDate,
+ "FormatDuration": utils.FormatDuration,
+ }).ParseFS(templates.TemplatesFs, "telegram/"+filename)
+ if err != nil {
+ return nil, err
+ }
+
+ m.Templates[templateName] = t
+
+ return t, nil
+}
+
+func (m *TelegramTemplatesManager) SerializeLink(link types.Link) template.HTML {
+ if link.Href != "" {
+ return template.HTML(fmt.Sprintf("%s", link.Href, link.Name))
+ }
+
+ return template.HTML(link.Name)
+}
+
+func (m *TelegramTemplatesManager) SerializeDate(date time.Time) string {
+ return date.In(m.Timezone).Format(time.RFC1123)
+}
diff --git a/pkg/templates/telegram_test.go b/pkg/templates/telegram_test.go
new file mode 100644
index 0000000..62e8de5
--- /dev/null
+++ b/pkg/templates/telegram_test.go
@@ -0,0 +1,108 @@
+package templates
+
+import (
+ templatePkg "html/template"
+ loggerPkg "main/pkg/logger"
+ "main/pkg/types"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestTelegramGetTemplateNotExisting(t *testing.T) {
+ t.Parallel()
+
+ logger := loggerPkg.GetNopLogger()
+ timezone, _ := time.LoadLocation("Europe/Moscow")
+ manager := NewTelegramTemplatesManager(logger, timezone)
+
+ template, err := manager.GetTemplate("not-existing")
+ require.Error(t, err)
+ assert.Nil(t, template)
+}
+
+func TestTelegramGetTemplateExistingAndCached(t *testing.T) {
+ t.Parallel()
+
+ logger := loggerPkg.GetNopLogger()
+ timezone, _ := time.LoadLocation("Europe/Moscow")
+ manager := NewTelegramTemplatesManager(logger, timezone)
+
+ template, err := manager.GetTemplate("help")
+ require.NoError(t, err)
+ assert.NotNil(t, template)
+
+ // this time it should be loaded from cache
+ template2, err2 := manager.GetTemplate("help")
+ require.NoError(t, err2)
+ assert.NotNil(t, template2)
+}
+
+func TestTelegramRenderTemplateError(t *testing.T) {
+ t.Parallel()
+
+ logger := loggerPkg.GetNopLogger()
+ timezone, _ := time.LoadLocation("Europe/Moscow")
+ manager := NewTelegramTemplatesManager(logger, timezone)
+
+ template, err := manager.Render("not-existing", nil)
+ require.Error(t, err)
+ assert.Empty(t, template)
+}
+
+func TestTelegramRenderTemplateRenderError(t *testing.T) {
+ t.Parallel()
+
+ logger := loggerPkg.GetNopLogger()
+ timezone, _ := time.LoadLocation("Europe/Moscow")
+ manager := NewTelegramTemplatesManager(logger, timezone)
+
+ value := map[string]interface{}{}
+
+ template, err := manager.Render("voted", value)
+ require.Error(t, err)
+ assert.Empty(t, template)
+}
+
+func TestTelegramRenderTemplateRenderSuccess(t *testing.T) {
+ t.Parallel()
+
+ logger := loggerPkg.GetNopLogger()
+ timezone, _ := time.LoadLocation("Europe/Moscow")
+ manager := NewTelegramTemplatesManager(logger, timezone)
+
+ template, err := manager.Render("help", "1.0.0")
+ require.NoError(t, err)
+ assert.NotEmpty(t, template)
+}
+
+func TestTelegramRenderSerializeLink(t *testing.T) {
+ t.Parallel()
+
+ logger := loggerPkg.GetNopLogger()
+ timezone, _ := time.LoadLocation("Europe/Moscow")
+ manager := NewTelegramTemplatesManager(logger, timezone)
+
+ assert.Equal(t, templatePkg.HTML("test"), manager.SerializeLink(types.Link{Name: "test"}))
+ assert.Equal(
+ t,
+ templatePkg.HTML("test"),
+ manager.SerializeLink(types.Link{Name: "test", Href: "href"}),
+ )
+}
+
+func TestTelegramRenderSerializeDate(t *testing.T) {
+ t.Parallel()
+
+ logger := loggerPkg.GetNopLogger()
+ timezone, _ := time.LoadLocation("Europe/Moscow")
+ manager := NewTelegramTemplatesManager(logger, timezone)
+
+ dateStr := manager.SerializeDate(
+ time.Date(2000, 1, 1, 0, 0, 0, 0, timezone),
+ )
+ assert.Equal(t, "Sat, 01 Jan 2000 00:00:00 MSK", dateStr)
+}
diff --git a/templates/telegram/help.html b/templates/telegram/help.html
index 041d3c1..6f1ddd9 100644
--- a/templates/telegram/help.html
+++ b/templates/telegram/help.html
@@ -6,5 +6,5 @@
- /proposals_mutes - display the active proposals mutes list
- /help - display this command
-Created by 🐹 QuokkaStake with ❤️.
+Created by 🐹 Quokka Stake with ❤️.
If you like what we're doing, consider staking with us!