// Package notifyrender owns the subject/body templates used by both the // legacy sender (internal/sender) and the worker-driven notification // producer (internal/notifier). It is a leaf package so the notifier package // can pre-render notification content for the worker without importing the // sender package, which would otherwise create an import cycle (sender's // tests already import notifier to drive the legacy loop). package notifyrender import ( "bytes" "strings" "time" "github.com/russross/blackfriday/v2" "rocketgit.ru/rsmon/worker/app/models" ) const ( stateDown = "down" stateUp = "up" stateTest = "test" stateExp = "exp" ) // GetContent pre-renders subject + bodies for one Message using the same // templates the legacy sender used to apply at delivery time. The result is // what the worker binary consumes directly so it does not need access to // Message/Event rows, workdays, or NotificationDayStart logic on the data plane. // // Returns the four bodies (subject, text, markdown, html). The caller is // responsible for passing them through to the worker task payload. func GetContent(message *models.Message, tn time.Time) (bytes.Buffer, bytes.Buffer, bytes.Buffer, bytes.Buffer) { var subject, textBody, markdownBody, htmlBody bytes.Buffer if message.Kind == stateTest { subject.WriteString("тестовое сообщение от rsmon.ru") textBody.WriteString("тестовое сообщение от rsmon.ru") markdownBody.WriteString("#### тестовое сообщение от rsmon.ru") htmlBody.WriteString("

тестовое сообщение от rsmon.ru

") return subject, textBody, markdownBody, htmlBody } if message.Kind == stateExp { if len(message.Events) > 0 { panic("exp message with events") } if message.Check == nil { panic("exp message with no check") } return TextExpires(message.Check) } if message.Check != nil { panic("up/down message with check") } if len(message.Events) == 1 { event := message.Events[0] switch message.Kind { case stateDown: return TextDownOne(&event) case stateUp: return TextUpOne(&event) default: panic("bad message kind " + message.Kind) } } switch message.Kind { case stateDown: subject.WriteString(GetDownMany(len(message.Events))) case stateUp: subject.WriteString(GetUpMany(len(message.Events))) default: panic("bad message kind" + message.Kind) } names := []string{} for _, evt := range message.Events { //nolint:gocritic // range copy is acceptable here names = append(names, evt.Monitor.GetLabel()) } subject.WriteString(": ") subject.WriteString(strings.Join(names, ", ")) asciiTable, markdownTable := RenderEventsTable(message, tn) textBody.WriteString(subject.String() + "\n") textBody.WriteString(asciiTable) markdownBody.WriteString("###### " + subject.String() + "\n\n") markdownBody.WriteString(markdownTable) htmlTable := blackfriday.Run([]byte(markdownTable)) htmlBody.WriteString("

Изменения статусов по мониторам:

") htmlBody.Write(htmlTable) return subject, textBody, markdownBody, htmlBody }