/
templateserver.go
92 lines (80 loc) · 2.73 KB
/
templateserver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
*
* Copyright 2023 puzzlegotemplateserver authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package templateserver
import (
"bytes"
"context"
"encoding/json"
"errors"
"text/template"
"time"
"github.com/dvaumoron/partrenderer"
pb "github.com/dvaumoron/puzzletemplateservice"
"github.com/uptrace/opentelemetry-go-extra/otelzap"
"go.uber.org/zap"
)
const TemplateKey = "puzzleTemplate"
var errInternal = errors.New("internal service error")
// server is used to implement puzzletemplateservice.TemplateServer
type server struct {
pb.UnimplementedTemplateServer
renderer partrenderer.PartRenderer
messages map[string]map[string]string
logger *otelzap.Logger
}
func New(componentsPath string, viewsPath string, sourceFormat string, messages map[string]map[string]string, logger *otelzap.Logger) pb.TemplateServer {
renderer := load(componentsPath, viewsPath, sourceFormat, logger)
return server{renderer: renderer, messages: messages, logger: logger}
}
func (s server) Render(ctx context.Context, request *pb.RenderRequest) (*pb.Rendered, error) {
logger := s.logger.Ctx(ctx)
var data map[string]any
err := json.Unmarshal(request.Data, &data)
if err != nil {
logger.Error("Failed during JSON parsing", zap.Error(err))
return nil, errInternal
}
data["Messages"] = s.messages[asString(data["lang"])]
var content bytes.Buffer
if err = s.renderer.ExecuteTemplate(&content, request.TemplateName, data); err != nil {
logger.Error("Failed during go template call", zap.Error(err))
return nil, errInternal
}
return &pb.Rendered{Content: content.Bytes()}, nil
}
func load(componentsPath string, viewsPath string, sourceFormat string, logger *otelzap.Logger) partrenderer.PartRenderer {
customFuncs := template.FuncMap{"date": func(value string, targetFormat string) string {
if sourceFormat == targetFormat {
return value
}
date, err := time.Parse(sourceFormat, value)
if err != nil {
return value
}
return date.Format(targetFormat)
}}
renderer, err := partrenderer.MakePartRenderer(componentsPath, viewsPath, partrenderer.WithFuncs(customFuncs))
if err != nil {
logger.Fatal("Failed to load templates", zap.Error(err))
}
return renderer
}
func asString(value any) string {
s, _ := value.(string)
return s
}