Minor formatting fixes
This commit is contained in:
parent
709668d811
commit
40ae9cdb31
4
init.go
4
init.go
|
@ -186,7 +186,7 @@ func initImporter(app *App) *subimporter.Importer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// initMessengers initializes various messaging backends.
|
// initMessengers initializes various messaging backends.
|
||||||
func initMessengers(r *manager.Manager) messenger.Messenger {
|
func initMessengers(m *manager.Manager) messenger.Messenger {
|
||||||
// Load SMTP configurations for the default e-mail Messenger.
|
// Load SMTP configurations for the default e-mail Messenger.
|
||||||
var (
|
var (
|
||||||
mapKeys = ko.MapKeys("smtp")
|
mapKeys = ko.MapKeys("smtp")
|
||||||
|
@ -215,7 +215,7 @@ func initMessengers(r *manager.Manager) messenger.Messenger {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lo.Fatalf("error loading e-mail messenger: %v", err)
|
lo.Fatalf("error loading e-mail messenger: %v", err)
|
||||||
}
|
}
|
||||||
if err := r.AddMessenger(msgr); err != nil {
|
if err := m.AddMessenger(msgr); err != nil {
|
||||||
lo.Printf("error registering messenger %s", err)
|
lo.Printf("error registering messenger %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,6 @@ func (m *Manager) AddMessenger(msg messenger.Messenger) error {
|
||||||
return fmt.Errorf("messenger '%s' is already loaded", id)
|
return fmt.Errorf("messenger '%s' is already loaded", id)
|
||||||
}
|
}
|
||||||
m.messengers[id] = msg
|
m.messengers[id] = msg
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +131,6 @@ func (m *Manager) GetMessengerNames() []string {
|
||||||
for n := range m.messengers {
|
for n := range m.messengers {
|
||||||
names = append(names, n)
|
names = append(names, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,9 +194,7 @@ func (m *Manager) Run(tick time.Duration) {
|
||||||
delete(m.msgErrorCounts, e.camp.ID)
|
delete(m.msgErrorCounts, e.camp.ID)
|
||||||
|
|
||||||
// Notify admins.
|
// Notify admins.
|
||||||
m.sendNotif(e.camp,
|
m.sendNotif(e.camp, models.CampaignStatusPaused, "Too many errors")
|
||||||
models.CampaignStatusPaused,
|
|
||||||
"Too many errors")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,6 +252,34 @@ func (m *Manager) SpawnWorkers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TemplateFuncs returns the template functions to be applied into
|
||||||
|
// compiled campaign templates.
|
||||||
|
func (m *Manager) TemplateFuncs(c *models.Campaign) template.FuncMap {
|
||||||
|
return template.FuncMap{
|
||||||
|
"TrackLink": func(url string, msg *Message) string {
|
||||||
|
return m.trackLink(url, msg.Campaign.UUID, msg.Subscriber.UUID)
|
||||||
|
},
|
||||||
|
"TrackView": func(msg *Message) template.HTML {
|
||||||
|
return template.HTML(fmt.Sprintf(`<img src="%s" alt="" />`,
|
||||||
|
fmt.Sprintf(m.cfg.ViewTrackURL, msg.Campaign.UUID, msg.Subscriber.UUID)))
|
||||||
|
},
|
||||||
|
"UnsubscribeURL": func(msg *Message) string {
|
||||||
|
return msg.unsubURL
|
||||||
|
},
|
||||||
|
"OptinURL": func(msg *Message) string {
|
||||||
|
// Add list IDs.
|
||||||
|
// TODO: Show private lists list on optin e-mail
|
||||||
|
return fmt.Sprintf(m.cfg.OptinURL, msg.Subscriber.UUID, "")
|
||||||
|
},
|
||||||
|
"Date": func(layout string) string {
|
||||||
|
if layout == "" {
|
||||||
|
layout = time.ANSIC
|
||||||
|
}
|
||||||
|
return time.Now().Format(layout)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// addCampaign adds a campaign to the process queue.
|
// addCampaign adds a campaign to the process queue.
|
||||||
func (m *Manager) addCampaign(c *models.Campaign) error {
|
func (m *Manager) addCampaign(c *models.Campaign) error {
|
||||||
// Validate messenger.
|
// Validate messenger.
|
||||||
|
@ -281,7 +305,6 @@ func (m *Manager) getPendingCampaignIDs() []int64 {
|
||||||
for _, c := range m.camps {
|
for _, c := range m.camps {
|
||||||
ids = append(ids, int64(c.ID))
|
ids = append(ids, int64(c.ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,17 +381,6 @@ func (m *Manager) exhaustCampaign(c *models.Campaign, status string) (*models.Ca
|
||||||
return cm, nil
|
return cm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render takes a Message, executes its pre-compiled Campaign.Tpl
|
|
||||||
// and applies the resultant bytes to Message.body to be used in messages.
|
|
||||||
func (m *Message) Render() error {
|
|
||||||
out := bytes.Buffer{}
|
|
||||||
if err := m.Campaign.Tpl.ExecuteTemplate(&out, models.BaseTpl, m); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
m.Body = out.Bytes()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// trackLink register a URL and return its UUID to be used in message templates
|
// trackLink register a URL and return its UUID to be used in message templates
|
||||||
// for tracking links.
|
// for tracking links.
|
||||||
func (m *Manager) trackLink(url, campUUID, subUUID string) string {
|
func (m *Manager) trackLink(url, campUUID, subUUID string) string {
|
||||||
|
@ -412,30 +424,13 @@ func (m *Manager) sendNotif(c *models.Campaign, status, reason string) error {
|
||||||
return m.notifCB(subject, data)
|
return m.notifCB(subject, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TemplateFuncs returns the template functions to be applied into
|
// Render takes a Message, executes its pre-compiled Campaign.Tpl
|
||||||
// compiled campaign templates.
|
// and applies the resultant bytes to Message.body to be used in messages.
|
||||||
func (m *Manager) TemplateFuncs(c *models.Campaign) template.FuncMap {
|
func (m *Message) Render() error {
|
||||||
return template.FuncMap{
|
out := bytes.Buffer{}
|
||||||
"TrackLink": func(url string, msg *Message) string {
|
if err := m.Campaign.Tpl.ExecuteTemplate(&out, models.BaseTpl, m); err != nil {
|
||||||
return m.trackLink(url, msg.Campaign.UUID, msg.Subscriber.UUID)
|
return err
|
||||||
},
|
|
||||||
"TrackView": func(msg *Message) template.HTML {
|
|
||||||
return template.HTML(fmt.Sprintf(`<img src="%s" alt="" />`,
|
|
||||||
fmt.Sprintf(m.cfg.ViewTrackURL, msg.Campaign.UUID, msg.Subscriber.UUID)))
|
|
||||||
},
|
|
||||||
"UnsubscribeURL": func(msg *Message) string {
|
|
||||||
return msg.unsubURL
|
|
||||||
},
|
|
||||||
"OptinURL": func(msg *Message) string {
|
|
||||||
// Add list IDs.
|
|
||||||
// TODO: Show private lists list on optin e-mail
|
|
||||||
return fmt.Sprintf(m.cfg.OptinURL, msg.Subscriber.UUID, "")
|
|
||||||
},
|
|
||||||
"Date": func(layout string) string {
|
|
||||||
if layout == "" {
|
|
||||||
layout = time.ANSIC
|
|
||||||
}
|
|
||||||
return time.Now().Format(layout)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
m.Body = out.Bytes()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
"github.com/lib/pq"
|
|
||||||
|
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
|
"github.com/gofrs/uuid"
|
||||||
"github.com/knadh/listmonk/models"
|
"github.com/knadh/listmonk/models"
|
||||||
|
"github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -34,7 +33,10 @@ const (
|
||||||
|
|
||||||
// commitBatchSize is the number of inserts to commit in a single SQL transaction.
|
// commitBatchSize is the number of inserts to commit in a single SQL transaction.
|
||||||
commitBatchSize = 10000
|
commitBatchSize = 10000
|
||||||
|
)
|
||||||
|
|
||||||
|
// Various import statuses.
|
||||||
|
const (
|
||||||
StatusNone = "none"
|
StatusNone = "none"
|
||||||
StatusImporting = "importing"
|
StatusImporting = "importing"
|
||||||
StatusStopping = "stopping"
|
StatusStopping = "stopping"
|
||||||
|
@ -113,7 +115,6 @@ func New(upsert *sql.Stmt, blacklist *sql.Stmt, updateListDate *sql.Stmt,
|
||||||
notifCB: notifCB,
|
notifCB: notifCB,
|
||||||
status: Status{Status: StatusNone, logBuf: bytes.NewBuffer(nil)},
|
status: Status{Status: StatusNone, logBuf: bytes.NewBuffer(nil)},
|
||||||
}
|
}
|
||||||
|
|
||||||
return &im
|
return &im
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +163,6 @@ func (im *Importer) GetLogs() []byte {
|
||||||
if im.status.logBuf == nil {
|
if im.status.logBuf == nil {
|
||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return im.status.logBuf.Bytes()
|
return im.status.logBuf.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +213,6 @@ func (im *Importer) sendNotif(status string) error {
|
||||||
strings.Title(status),
|
strings.Title(status),
|
||||||
s.Name)
|
s.Name)
|
||||||
)
|
)
|
||||||
|
|
||||||
return im.notifCB(subject, out)
|
return im.notifCB(subject, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,7 +525,6 @@ func (s *Session) LoadCSV(srcPath string, delim rune) error {
|
||||||
|
|
||||||
close(s.subQueue)
|
close(s.subQueue)
|
||||||
failed = false
|
failed = false
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,7 +556,6 @@ func (s *Session) mapCSVHeaders(csvHdrs []string, knownHdrs map[string]bool) map
|
||||||
s.log.Printf("ignoring unknown header '%s'", h)
|
s.log.Printf("ignoring unknown header '%s'", h)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
hdrKeys[h] = i
|
hdrKeys[h] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,5 +598,4 @@ func countLines(r io.Reader) (int, error) {
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
28
media.go
28
media.go
|
@ -1,10 +1,13 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
"github.com/knadh/listmonk/internal/media"
|
"github.com/knadh/listmonk/internal/media"
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
|
@ -146,3 +149,28 @@ func handleDeleteMedia(c echo.Context) error {
|
||||||
app.media.Delete(thumbPrefix + m.Filename)
|
app.media.Delete(thumbPrefix + m.Filename)
|
||||||
return c.JSON(http.StatusOK, okResp{true})
|
return c.JSON(http.StatusOK, okResp{true})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createThumbnail reads the file object and returns a smaller image
|
||||||
|
func createThumbnail(file *multipart.FileHeader) (*bytes.Reader, error) {
|
||||||
|
src, err := file.Open()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
img, err := imaging.Decode(src)
|
||||||
|
if err != nil {
|
||||||
|
return nil, echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
|
fmt.Sprintf("Error decoding image: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode the image into a byte slice as PNG.
|
||||||
|
var (
|
||||||
|
thumb = imaging.Resize(img, thumbnailSize, 0, imaging.Lanczos)
|
||||||
|
out bytes.Buffer
|
||||||
|
)
|
||||||
|
if err := imaging.Encode(&out, thumb, imaging.PNG); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bytes.NewReader(out.Bytes()), nil
|
||||||
|
}
|
||||||
|
|
34
utils.go
34
utils.go
|
@ -4,15 +4,10 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"mime/multipart"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/disintegration/imaging"
|
|
||||||
"github.com/labstack/echo"
|
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,28 +47,6 @@ func generateFileName(fName string) string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
// createThumbnail reads the file object and returns a smaller image
|
|
||||||
func createThumbnail(file *multipart.FileHeader) (*bytes.Reader, error) {
|
|
||||||
src, err := file.Open()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer src.Close()
|
|
||||||
img, err := imaging.Decode(src)
|
|
||||||
if err != nil {
|
|
||||||
return nil, echo.NewHTTPError(http.StatusInternalServerError,
|
|
||||||
fmt.Sprintf("Error decoding image: %v", err))
|
|
||||||
}
|
|
||||||
t := imaging.Resize(img, thumbnailSize, 0, imaging.Lanczos)
|
|
||||||
// Encode the image into a byte slice as PNG.
|
|
||||||
var buf bytes.Buffer
|
|
||||||
err = imaging.Encode(&buf, t, imaging.PNG)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return bytes.NewReader(buf.Bytes()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given an error, pqErrMsg will try to return pq error details
|
// Given an error, pqErrMsg will try to return pq error details
|
||||||
// if it's a pq error.
|
// if it's a pq error.
|
||||||
func pqErrMsg(err error) string {
|
func pqErrMsg(err error) string {
|
||||||
|
@ -82,7 +55,6 @@ func pqErrMsg(err error) string {
|
||||||
return fmt.Sprintf("%s. %s", err, err.Detail)
|
return fmt.Sprintf("%s. %s", err, err.Detail)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return err.Error()
|
return err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +75,6 @@ func normalizeTags(tags []string) []string {
|
||||||
out = append(out, string(rep))
|
out = append(out, string(rep))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +89,6 @@ func makeMsgTpl(pageTitle, heading, msg string) msgTpl {
|
||||||
err.Title = pageTitle
|
err.Title = pageTitle
|
||||||
err.MessageTitle = heading
|
err.MessageTitle = heading
|
||||||
err.Message = msg
|
err.Message = msg
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +97,6 @@ func makeMsgTpl(pageTitle, heading, msg string) msgTpl {
|
||||||
// resultant values.
|
// resultant values.
|
||||||
func parseStringIDs(s []string) ([]int64, error) {
|
func parseStringIDs(s []string) ([]int64, error) {
|
||||||
vals := make([]int64, 0, len(s))
|
vals := make([]int64, 0, len(s))
|
||||||
|
|
||||||
for _, v := range s {
|
for _, v := range s {
|
||||||
i, err := strconv.ParseInt(v, 10, 64)
|
i, err := strconv.ParseInt(v, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -147,12 +116,11 @@ func parseStringIDs(s []string) ([]int64, error) {
|
||||||
// generateRandomString generates a cryptographically random, alphanumeric string of length n.
|
// generateRandomString generates a cryptographically random, alphanumeric string of length n.
|
||||||
func generateRandomString(n int) (string, error) {
|
func generateRandomString(n int) (string, error) {
|
||||||
const dictionary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
const dictionary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
var bytes = make([]byte, n)
|
var bytes = make([]byte, n)
|
||||||
|
|
||||||
if _, err := rand.Read(bytes); err != nil {
|
if _, err := rand.Read(bytes); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range bytes {
|
for k, v := range bytes {
|
||||||
bytes[k] = dictionary[v%byte(len(dictionary))]
|
bytes[k] = dictionary[v%byte(len(dictionary))]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue