mirror of
https://github.com/keven1024/015.git
synced 2026-05-26 07:08:02 +00:00
feat(worker): integrate GeoIP functionality into email notifications and enhance email template with region information
This commit is contained in:
3
go.work
3
go.work
@@ -2,6 +2,9 @@ go 1.25.5
|
||||
|
||||
use (
|
||||
./backend
|
||||
./pkg/geoip
|
||||
./pkg/i18n
|
||||
./pkg/mail
|
||||
./pkg/models
|
||||
./pkg/services
|
||||
./pkg/utils
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"dev": "concurrently -n front,backend,worker -c blue,green,yellow 'pnpm:dev:front' 'pnpm:dev:backend' 'pnpm:dev:worker'",
|
||||
"dev:front": "cd front && pnpm run dev",
|
||||
"dev:backend": "cd backend && air",
|
||||
"dev:worker": "cd worker && air",
|
||||
"dev:worker": "pnpm gen:mail && cd worker && air",
|
||||
"lint": "concurrently -n front,backend,worker -c blue,green,yellow 'pnpm:lint:front' 'pnpm:lint:backend' 'pnpm:lint:worker'",
|
||||
"lint:front": "cd front && pnpm nuxt typecheck",
|
||||
"lint:backend": "cd backend && golangci-lint run",
|
||||
@@ -20,7 +20,8 @@
|
||||
"up-deps:backend": "cd backend && go get -u",
|
||||
"up-deps:worker": "cd worker && go get -u",
|
||||
"up-deps:models": "cd pkg/models && go get -u",
|
||||
"up-deps:utils": "cd pkg/utils && go get -u"
|
||||
"up-deps:utils": "cd pkg/utils && go get -u",
|
||||
"gen:mail": "cd pkg/mail && pnpm export"
|
||||
},
|
||||
"workspaces": [
|
||||
"front"
|
||||
@@ -41,7 +42,7 @@
|
||||
"concurrently": "^9.2.1",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.5.2",
|
||||
"prettier": "^3.8.1"
|
||||
"prettier": "^3.8.3"
|
||||
},
|
||||
"packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017"
|
||||
}
|
||||
|
||||
@@ -3,8 +3,11 @@ module pkg/geoip
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/enescakir/emoji v1.0.0 // indirect
|
||||
github.com/oschwald/geoip2-golang/v2 v2.1.0 // indirect
|
||||
github.com/oschwald/maxminddb-golang/v2 v2.1.1 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
github.com/enescakir/emoji v1.0.0
|
||||
github.com/oschwald/geoip2-golang/v2 v2.1.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/oschwald/maxminddb-golang/v2 v2.1.1 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/enescakir/emoji v1.0.0 h1:W+HsNql8swfCQFtioDGDHCHri8nudlK1n5p2rHCJoog=
|
||||
github.com/enescakir/emoji v1.0.0/go.mod h1:Bt1EKuLnKDTYpLALApstIkAjdDrS/8IAgTkKp+WKFD0=
|
||||
github.com/oschwald/geoip2-golang/v2 v2.1.0 h1:DjnLhNJu9WHwTrmoiQFvgmyJoczhdnm7LB23UBI2Amo=
|
||||
github.com/oschwald/geoip2-golang/v2 v2.1.0/go.mod h1:qdVmcPgrTJ4q2eP9tHq/yldMTdp2VMr33uVdFbHBiBc=
|
||||
github.com/oschwald/maxminddb-golang/v2 v2.1.1 h1:lA8FH0oOrM4u7mLvowq8IT6a3Q/qEnqRzLQn9eH5ojc=
|
||||
github.com/oschwald/maxminddb-golang/v2 v2.1.1/go.mod h1:PLdx6PR+siSIoXqqy7C7r3SB3KZnhxWr1Dp6g0Hacl8=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
5136
pnpm-lock.yaml
generated
5136
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
packages:
|
||||
# all packages in direct subdirs of packages/
|
||||
- 'front'
|
||||
# - '*'
|
||||
# all packages in direct subdirs of packages/
|
||||
- 'front'
|
||||
- 'pkg/*'
|
||||
# - '*'
|
||||
|
||||
@@ -6,6 +6,7 @@ require (
|
||||
github.com/go-resty/resty/v2 v2.16.5
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/hibiken/asynq v0.26.0
|
||||
github.com/mocktools/go-smtp-mock/v2 v2.5.4
|
||||
github.com/openai/openai-go/v3 v3.30.0
|
||||
github.com/samber/lo v1.53.0
|
||||
github.com/spf13/cast v1.10.0
|
||||
@@ -18,7 +19,6 @@ require (
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/mocktools/go-smtp-mock/v2 v2.5.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/redis/go-redis/v9 v9.18.0 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
|
||||
@@ -40,6 +40,8 @@ github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM=
|
||||
github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
|
||||
@@ -2,7 +2,9 @@ package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"pkg/i18n"
|
||||
pkgmail "pkg/mail"
|
||||
"pkg/models"
|
||||
u "pkg/utils"
|
||||
"strings"
|
||||
@@ -44,8 +46,9 @@ func SendWebhook(webhook models.NotifyWebhook) error {
|
||||
type EmailTemplateData struct {
|
||||
Locale string
|
||||
IP string
|
||||
ShareType models.ShareType
|
||||
Region string
|
||||
FileName string
|
||||
ShareType models.ShareType
|
||||
}
|
||||
|
||||
func SendEmail(to string, emailTemplateData EmailTemplateData, options ...mail.Option) error {
|
||||
@@ -63,16 +66,27 @@ func SendEmail(to string, emailTemplateData EmailTemplateData, options ...mail.O
|
||||
if username == "" {
|
||||
return fmt.Errorf("smtp.username is required")
|
||||
}
|
||||
port := lo.Ternary(cast.ToInt(smtp["port"]) != 0, cast.ToInt(smtp["port"]), mail.DefaultPortSSL)
|
||||
|
||||
templateData := map[string]any{
|
||||
"IP": emailTemplateData.IP,
|
||||
"SiteURL": u.GetEnv("site.url"),
|
||||
"ShareType": i18n.T(emailTemplateData.Locale, lo.Ternary(emailTemplateData.ShareType == models.ShareTypeText, "share_type_text", "share_type_file")),
|
||||
"FileName": emailTemplateData.FileName,
|
||||
port := mail.DefaultPortSSL
|
||||
if smtpPort := cast.ToInt(smtp["port"]); smtpPort != 0 {
|
||||
port = smtpPort
|
||||
}
|
||||
|
||||
p, err := url.Parse(u.GetEnv("site.url"))
|
||||
subject := i18n.TWithData(emailTemplateData.Locale, "notify_email_subject", map[string]any{
|
||||
"SiteURL": p.Host,
|
||||
})
|
||||
htmlBody, err := pkgmail.RenderMailTemplate("pull-notify", map[string]string{
|
||||
"EMAIL-TITLE": subject,
|
||||
"EMAIL-INTRO": i18n.T(emailTemplateData.Locale, "notify_email_intro"),
|
||||
"EMAIL-FILEICON": lo.Ternary(emailTemplateData.ShareType == models.ShareTypeText, "spiral_notepad", "file_folder"),
|
||||
"EMAIL-FILENAME": emailTemplateData.FileName,
|
||||
"EMAIL-IP": emailTemplateData.IP,
|
||||
"EMAIL-REGION": emailTemplateData.Region,
|
||||
"EMAIL-LABEL-REGION": i18n.T(emailTemplateData.Locale, "notify_email_label_region"),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
subject := i18n.TWithData(emailTemplateData.Locale, "notify_email_subject", templateData)
|
||||
body := i18n.TWithData(emailTemplateData.Locale, "notify_email_body", templateData)
|
||||
message := mail.NewMsg()
|
||||
if err := message.From(username); err != nil {
|
||||
return err
|
||||
@@ -81,7 +95,7 @@ func SendEmail(to string, emailTemplateData EmailTemplateData, options ...mail.O
|
||||
return err
|
||||
}
|
||||
message.Subject(subject)
|
||||
message.SetBodyString(mail.TypeTextPlain, body)
|
||||
message.SetBodyString(mail.TypeTextHTML, htmlBody)
|
||||
|
||||
options = append([]mail.Option{
|
||||
mail.WithPort(port),
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"pkg/geoip"
|
||||
"pkg/models"
|
||||
u "pkg/utils"
|
||||
"worker/internal/services"
|
||||
@@ -77,12 +78,18 @@ func ShareNotify(ctx context.Context, task *asynq.Task) error {
|
||||
successCount++
|
||||
}
|
||||
|
||||
region := "-"
|
||||
if info := geoip.GetIpGeoInfo(payload.IP); info != nil {
|
||||
region = info.Emoji + " " + info.Country.Country.Names.English
|
||||
}
|
||||
|
||||
for _, email := range shareInfo.NotifyEmails {
|
||||
if err := services.SendEmail(email, services.EmailTemplateData{
|
||||
Locale: shareInfo.Locale,
|
||||
ShareType: shareInfo.Type,
|
||||
FileName: shareInfo.FileName,
|
||||
FileName: lo.Ternary(shareInfo.Type == models.ShareTypeFile, shareInfo.FileName, lo.Substring(shareInfo.Data, 0, 7)+"..."),
|
||||
IP: payload.IP,
|
||||
Region: region,
|
||||
ShareType: shareInfo.Type,
|
||||
}); err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"pkg/geoip"
|
||||
"pkg/i18n"
|
||||
"pkg/utils"
|
||||
"worker/internal/tasks"
|
||||
@@ -26,6 +27,9 @@ func main() {
|
||||
if err := i18n.Init(); err != nil {
|
||||
log.Fatalf("failed to init i18n: %v", err)
|
||||
}
|
||||
if err := geoip.Init(); err != nil {
|
||||
log.Fatalf("failed to init geoip: %v", err)
|
||||
}
|
||||
|
||||
srv := asynq.NewServer(
|
||||
utils.RedisURI2AsynqOpt(utils.GetEnv("redis.url")),
|
||||
|
||||
Reference in New Issue
Block a user