-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
StartedContext + changes to PathsToBytes and Template sending
- Added the error and started templates which are both new txt based templates (01/02/2023 - 10:35:17) - Renamed Context.HTML to Context.Execute as it now can call either Template.HTML or Template.Text (01/02/2023 - 10:35:51) - Added Text as a new TemplateBufferContentType (01/02/2023 - 10:36:17) - Moved all implementations of email.Context to contexts.go (01/02/2023 - 10:42:28) - Template.Template is now the new parsedType which can store a reference to both a parsed HTML template and a parsed text template (01/02/2023 - 12:00:28) - parsedTemplate.Execute will call the execute method of the set parsed template (01/02/2023 - 12:01:05) - Renamed Template.HTML to Execute and it now can also execute text templates along with HTML templates (01/02/2023 - 12:15:17) - Added the Template.SendAsyncAndConsume method for use cases where we want to send an email asynchronously and continue doing other stuff (01/02/2023 - 13:33:07) - The StartedContext and ErrorContext will probably need to exist within the main package so that we can pass a ScoutState instance to them (01/02/2023 - 14:51:22) - Added new interfaces for reading and writing to PathsToBytes. These are PathsToBytesInterface, PathsToBytesReader, PathsToBytesWriter, and PathsToBytesReadWriter. This is so I could create another type similar to the existing PathsToBytes that writes to a zip archive for email sending in StartedContext and ErrorContext (01/02/2023 - 15:55:12) - Added the ScoutState.LoadFrom and ScoutState.SaveTo methods which can be given a PathsToBytesReader and a PathsToBytesWriter respectively to load/save a ScoutState to (01/02/2023 - 15:56:37) - StartedContext should now be finished and ready for implementation in the Scout procedure #8 (01/02/2023 - 16:34:37) - Added a check to Part.Encoder which stops zip attachment from being re-archived (01/02/2023 - 16:35:28)
- Loading branch information
1 parent
2f75ab7
commit b8ca9e1
Showing
10 changed files
with
630 additions
and
316 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package email | ||
|
||
import ( | ||
"fmt" | ||
"github.com/andygello555/game-scout/db/models" | ||
"github.com/andygello555/gotils/v2/numbers" | ||
"github.com/deckarep/golang-set/v2" | ||
"github.com/volatiletech/null/v9" | ||
"html/template" | ||
"reflect" | ||
"strconv" | ||
"time" | ||
"unicode" | ||
) | ||
|
||
// Context will be implemented by structures that are used to fill out a Template in Template.Execute. | ||
type Context interface { | ||
// Path returns the TemplatePath that this Context is for. | ||
Path() TemplatePath | ||
// Template returns an un-executed Template that this Context can be used for. | ||
Template() *Template | ||
// Funcs returns the functions that should be bound to the template.Template before parsing the HTML/Text template | ||
// located in at the TemplatePath. | ||
Funcs() template.FuncMap | ||
// Execute executes the Context via Template.Execute. | ||
Execute() *Template | ||
// AdditionalParts returns any additional Part to add onto an Email. | ||
AdditionalParts() []Part | ||
} | ||
|
||
// MeasureContext is a Context that contains the data required to fill out the Measure HTML template. | ||
type MeasureContext struct { | ||
Start time.Time | ||
End time.Time | ||
TrendingDevs []*models.TrendingDev | ||
TopSteamApps []*models.SteamApp | ||
DevelopersBeingDeleted []*models.TrendingDev | ||
EnabledDevelopers int64 | ||
Config Config | ||
} | ||
|
||
func (m *MeasureContext) Path() TemplatePath { return Measure } | ||
func (m *MeasureContext) Execute() *Template { return m.Template().Execute() } | ||
func (m *MeasureContext) AdditionalParts() []Part { return []Part{} } | ||
func (m *MeasureContext) Template() *Template { return NewParsedTemplate(HTML, m).Template(m) } | ||
func (m *MeasureContext) Funcs() template.FuncMap { | ||
return map[string]any{ | ||
"intRange": func(start, end, step int) []int { | ||
return numbers.Range(start, end, step) | ||
}, | ||
"contains": func(set []string, elem string) bool { | ||
return mapset.NewThreadUnsafeSet(set...).Contains(elem) | ||
}, | ||
"timePretty": func(t time.Time) string { | ||
loc, _ := time.LoadLocation("Europe/London") | ||
t = t.In(loc) | ||
return numbers.Ordinal(t.Day()) + t.Format(" January 2006 at 3pm") | ||
}, | ||
"datePretty": func(t time.Time) string { | ||
return t.Format("02/01/2006") | ||
}, | ||
"percentage": func(f null.Float64) string { | ||
perc := f.Float64 | ||
if !f.IsValid() { | ||
perc = 1.0 | ||
} | ||
return fmt.Sprintf("%.2f%%", perc*100.0) | ||
}, | ||
"percentageF64": func(f float64) string { | ||
return fmt.Sprintf("%.2f%%", f*100.0) | ||
}, | ||
"cap": func(s string) string { | ||
r := []rune(s) | ||
return string(append([]rune{unicode.ToUpper(r[0])}, r[1:]...)) | ||
}, | ||
"yesno": func(b bool) string { | ||
return map[bool]string{ | ||
true: "yes", | ||
false: "no", | ||
}[b] | ||
}, | ||
"inc": func(i int) int { | ||
return i + 1 | ||
}, | ||
"dec": func(i int) int { | ||
return i - 1 | ||
}, | ||
"div": func(a, b int) int { | ||
return a / b | ||
}, | ||
"ord": func(num int) string { | ||
return numbers.OrdinalOnly(num) | ||
}, | ||
"date": func(date time.Time) time.Time { | ||
year, month, day := date.Date() | ||
return time.Date(year, month, day, 0, 0, 0, 0, time.UTC) | ||
}, | ||
"duration": func(duration models.NullDuration) time.Duration { | ||
return time.Duration(duration.Int64) | ||
}, | ||
"timeSub": func(t1 time.Time, t2 time.Time) time.Duration { | ||
return t1.Sub(t2) | ||
}, | ||
"days": func(d time.Duration) int { | ||
return int(d.Hours() / 24) | ||
}, | ||
"lastIndex": func(a any) int { | ||
return reflect.ValueOf(a).Len() - 1 | ||
}, | ||
"trunc": func(s string, max int) string { | ||
lastSpaceIx := -1 | ||
sLen := 0 | ||
for i, r := range s { | ||
if unicode.IsSpace(r) { | ||
lastSpaceIx = i | ||
} | ||
sLen++ | ||
if sLen >= max { | ||
if lastSpaceIx != -1 { | ||
return s[:lastSpaceIx] + "..." | ||
} | ||
// If here, string is longer than max, but has no spaces | ||
} | ||
} | ||
return s | ||
}, | ||
"float": func(f float64) string { | ||
return strconv.FormatFloat(f, 'G', 12, 64) | ||
}, | ||
} | ||
} | ||
|
||
type ErrorContext struct { | ||
} | ||
|
||
func (e *ErrorContext) Path() TemplatePath { return Error } | ||
func (e *ErrorContext) Execute() *Template { return e.Template().Execute() } | ||
func (e *ErrorContext) AdditionalParts() []Part { return []Part{} } | ||
func (e *ErrorContext) Template() *Template { return NewParsedTemplate(Text, e).Template(e) } | ||
func (e *ErrorContext) Funcs() template.FuncMap { | ||
//TODO implement me | ||
panic("implement me") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.