diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index 6d7cdd557..a9dff442a 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -121,7 +121,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, userRankRepo := rank.NewUserRankRepo(dataData, configService) userActiveActivityRepo := activity.NewUserActiveActivityRepo(dataData, activityRepo, userRankRepo, configService) emailRepo := export.NewEmailRepo(dataData) - emailService := export2.NewEmailService(configService, emailRepo, siteInfoRepo) + emailService := export2.NewEmailService(configService, emailRepo, siteInfoCommonService) userRoleRelRepo := role.NewUserRoleRelRepo(dataData) roleRepo := role.NewRoleRepo(dataData) roleService := role2.NewRoleService(roleRepo) diff --git a/internal/base/constant/site_info.go b/internal/base/constant/site_info.go index d3c4e52a8..2e386743d 100644 --- a/internal/base/constant/site_info.go +++ b/internal/base/constant/site_info.go @@ -9,12 +9,12 @@ const ( ) const ( - // PermaLinkQuestionIDAndTitle /questions/10010000000000001/post-title - PermaLinkQuestionIDAndTitle = iota + 1 - // PermaLinkQuestionID /questions/10010000000000001 - PermaLinkQuestionID - // PermaLinkQuestionIDAndTitleByShortID /questions/11/post-title - PermaLinkQuestionIDAndTitleByShortID - // PermaLinkQuestionIDByShortID /questions/11 - PermaLinkQuestionIDByShortID + // PermalinkQuestionIDAndTitle /questions/10010000000000001/post-title + PermalinkQuestionIDAndTitle = iota + 1 + // PermalinkQuestionID /questions/10010000000000001 + PermalinkQuestionID + // PermalinkQuestionIDAndTitleByShortID /questions/11/post-title + PermalinkQuestionIDAndTitleByShortID + // PermalinkQuestionIDByShortID /questions/11 + PermalinkQuestionIDByShortID ) diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index 71da96d40..5fbeb7d09 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -116,7 +116,7 @@ func (tc *TemplateController) Index(ctx *gin.Context) { siteInfo.Canonical = siteInfo.General.SiteUrl UrlUseTitle := false - if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionIDAndTitle { + if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle { UrlUseTitle = true } siteInfo.Title = "" @@ -149,7 +149,7 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) { } UrlUseTitle := false - if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionIDAndTitle { + if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle { UrlUseTitle = true } siteInfo.Title = fmt.Sprintf("Questions - %s", siteInfo.General.Name) @@ -196,7 +196,7 @@ func (tc *TemplateController) QuestionInfoeRdirect(ctx *gin.Context, siteInfo *s } url = fmt.Sprintf("%s/questions/%s", siteInfo.General.SiteUrl, questionID) - if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionID || siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionIDByShortID { + if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionID || siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDByShortID { if len(ctx.Request.URL.Query()) > 0 { url = fmt.Sprintf("%s?%s", url, ctx.Request.URL.RawQuery) } @@ -299,7 +299,7 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) { return } siteInfo.Canonical = fmt.Sprintf("%s/questions/%s/%s", siteInfo.General.SiteUrl, id, encodeTitle) - if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionID { + if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionID { siteInfo.Canonical = fmt.Sprintf("%s/questions/%s", siteInfo.General.SiteUrl, id) } jsonLD := &schema.QAPageJsonLD{} @@ -414,7 +414,7 @@ func (tc *TemplateController) TagInfo(ctx *gin.Context) { siteInfo.Keywords = taginifo.DisplayName UrlUseTitle := false - if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionIDAndTitle { + if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle { UrlUseTitle = true } siteInfo.Title = fmt.Sprintf("'%s' Questions - %s", taginifo.DisplayName, siteInfo.General.Name) diff --git a/internal/controller/template_render/question.go b/internal/controller/template_render/question.go index 5629245d3..32416cf4a 100644 --- a/internal/controller/template_render/question.go +++ b/internal/controller/template_render/question.go @@ -44,8 +44,8 @@ func (t *TemplateRenderController) Sitemap(ctx *gin.Context) { "xmlHeader": template.HTML(``), "list": questions, "general": general, - "hastitle": siteInfo.PermaLink == constant.PermaLinkQuestionIDAndTitle || - siteInfo.PermaLink == constant.PermaLinkQuestionIDAndTitleByShortID, + "hastitle": siteInfo.Permalink == constant.PermalinkQuestionIDAndTitle || + siteInfo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID, }, ) return @@ -93,8 +93,8 @@ func (t *TemplateRenderController) SitemapPage(ctx *gin.Context, page int) error "xmlHeader": template.HTML(``), "list": questions, "general": general, - "hastitle": siteInfo.PermaLink == constant.PermaLinkQuestionIDAndTitle || - siteInfo.PermaLink == constant.PermaLinkQuestionIDAndTitleByShortID, + "hastitle": siteInfo.Permalink == constant.PermalinkQuestionIDAndTitle || + siteInfo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID, }, ) return nil diff --git a/internal/schema/email_template.go b/internal/schema/email_template.go index 1d54d92f7..7edf6285d 100644 --- a/internal/schema/email_template.go +++ b/internal/schema/email_template.go @@ -34,6 +34,25 @@ func (r *EmailCodeContent) FromJSONString(data string) error { return json.Unmarshal([]byte(data), &r) } +type RegisterTemplateData struct { + SiteName string + RegisterUrl string +} + +type PassResetTemplateData struct { + SiteName string + PassResetUrl string +} + +type ChangeEmailTemplateData struct { + SiteName string + ChangeEmailUrl string +} + +type TestTemplateData struct { + SiteName string +} + type NewAnswerTemplateRawData struct { AnswerUserDisplayName string QuestionTitle string diff --git a/internal/schema/siteinfo_schema.go b/internal/schema/siteinfo_schema.go index e21e8ff46..4c15ff16c 100644 --- a/internal/schema/siteinfo_schema.go +++ b/internal/schema/siteinfo_schema.go @@ -118,13 +118,13 @@ type SiteThemeReq struct { } type SiteSeoReq struct { - PermaLink int `validate:"required,lte=4,gte=0" form:"permalink" json:"permalink"` + Permalink int `validate:"required,lte=4,gte=0" form:"permalink" json:"permalink"` Robots string `validate:"required" form:"robots" json:"robots"` } func (s *SiteSeoResp) IsShortLink() bool { - return s.PermaLink == constant.PermaLinkQuestionIDAndTitleByShortID || - s.PermaLink == constant.PermaLinkQuestionIDByShortID + return s.Permalink == constant.PermalinkQuestionIDAndTitleByShortID || + s.Permalink == constant.PermalinkQuestionIDByShortID } // SiteGeneralResp site general response diff --git a/internal/service/export/email_service.go b/internal/service/export/email_service.go index 0f0985f5d..8ff276eb5 100644 --- a/internal/service/export/email_service.go +++ b/internal/service/export/email_service.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "encoding/json" "fmt" + "github.com/answerdev/answer/pkg/display" "mime" "os" "strings" @@ -13,7 +14,6 @@ import ( "github.com/answerdev/answer/internal/base/handler" "github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/base/translator" - "github.com/answerdev/answer/internal/entity" "github.com/answerdev/answer/internal/schema" "github.com/answerdev/answer/internal/service/config" "github.com/answerdev/answer/internal/service/siteinfo_common" @@ -25,9 +25,9 @@ import ( // EmailService kit service type EmailService struct { - configService *config.ConfigService - emailRepo EmailRepo - siteInfoRepo siteinfo_common.SiteInfoRepo + configService *config.ConfigService + emailRepo EmailRepo + siteInfoService siteinfo_common.SiteInfoCommonService } // EmailRepo email repository @@ -37,11 +37,15 @@ type EmailRepo interface { } // NewEmailService email service -func NewEmailService(configService *config.ConfigService, emailRepo EmailRepo, siteInfoRepo siteinfo_common.SiteInfoRepo) *EmailService { +func NewEmailService( + configService *config.ConfigService, + emailRepo EmailRepo, + siteInfoService siteinfo_common.SiteInfoCommonService, +) *EmailService { return &EmailService{ - configService: configService, - emailRepo: emailRepo, - siteInfoRepo: siteInfoRepo, + configService: configService, + emailRepo: emailRepo, + siteInfoService: siteInfoService, } } @@ -61,25 +65,6 @@ func (e *EmailConfig) IsSSL() bool { return e.Encryption == "SSL" } -type RegisterTemplateData struct { - SiteName string - RegisterUrl string -} - -type PassResetTemplateData struct { - SiteName string - PassResetUrl string -} - -type ChangeEmailTemplateData struct { - SiteName string - ChangeEmailUrl string -} - -type TestTemplateData struct { - SiteName string -} - // SaveCode save code func (es *EmailService) SaveCode(ctx context.Context, code, codeContent string) { err := es.emailRepo.SetCode(ctx, code, codeContent, 10*time.Minute) @@ -150,29 +135,12 @@ func (es *EmailService) VerifyUrlExpired(ctx context.Context, code string) (cont return content } -func (es *EmailService) getSiteGeneral(ctx context.Context) (resp schema.SiteGeneralResp, err error) { - var ( - siteType = "general" - siteInfo *entity.SiteInfo - exist bool - ) - resp = schema.SiteGeneralResp{} - - siteInfo, exist, err = es.siteInfoRepo.GetByType(ctx, siteType) - if !exist { - return - } - - _ = json.Unmarshal([]byte(siteInfo.Content), &resp) - return -} - func (es *EmailService) RegisterTemplate(ctx context.Context, registerUrl string) (title, body string, err error) { - siteInfo, err := es.getSiteGeneral(ctx) + siteInfo, err := es.siteInfoService.GetSiteGeneral(ctx) if err != nil { return } - templateData := RegisterTemplateData{ + templateData := &schema.RegisterTemplateData{ SiteName: siteInfo.Name, RegisterUrl: registerUrl, } @@ -184,12 +152,12 @@ func (es *EmailService) RegisterTemplate(ctx context.Context, registerUrl string } func (es *EmailService) PassResetTemplate(ctx context.Context, passResetUrl string) (title, body string, err error) { - siteInfo, err := es.getSiteGeneral(ctx) + siteInfo, err := es.siteInfoService.GetSiteGeneral(ctx) if err != nil { return } - templateData := PassResetTemplateData{SiteName: siteInfo.Name, PassResetUrl: passResetUrl} + templateData := &schema.PassResetTemplateData{SiteName: siteInfo.Name, PassResetUrl: passResetUrl} lang := handler.GetLangByCtx(ctx) title = translator.TrWithData(lang, constant.EmailTplKeyPassResetTitle, templateData) @@ -198,11 +166,11 @@ func (es *EmailService) PassResetTemplate(ctx context.Context, passResetUrl stri } func (es *EmailService) ChangeEmailTemplate(ctx context.Context, changeEmailUrl string) (title, body string, err error) { - siteInfo, err := es.getSiteGeneral(ctx) + siteInfo, err := es.siteInfoService.GetSiteGeneral(ctx) if err != nil { return } - templateData := ChangeEmailTemplateData{ + templateData := &schema.ChangeEmailTemplateData{ SiteName: siteInfo.Name, ChangeEmailUrl: changeEmailUrl, } @@ -215,11 +183,11 @@ func (es *EmailService) ChangeEmailTemplate(ctx context.Context, changeEmailUrl // TestTemplate send test email template parse func (es *EmailService) TestTemplate(ctx context.Context) (title, body string, err error) { - siteInfo, err := es.getSiteGeneral(ctx) + siteInfo, err := es.siteInfoService.GetSiteGeneral(ctx) if err != nil { return } - templateData := TestTemplateData{SiteName: siteInfo.Name} + templateData := &schema.TestTemplateData{SiteName: siteInfo.Name} lang := handler.GetLangByCtx(ctx) title = translator.TrWithData(lang, constant.EmailTplKeyTestTitle, templateData) @@ -230,7 +198,11 @@ func (es *EmailService) TestTemplate(ctx context.Context) (title, body string, e // NewAnswerTemplate new answer template func (es *EmailService) NewAnswerTemplate(ctx context.Context, raw *schema.NewAnswerTemplateRawData) ( title, body string, err error) { - siteInfo, err := es.getSiteGeneral(ctx) + siteInfo, err := es.siteInfoService.GetSiteGeneral(ctx) + if err != nil { + return + } + seoInfo, err := es.siteInfoService.GetSiteSeo(ctx) if err != nil { return } @@ -238,7 +210,7 @@ func (es *EmailService) NewAnswerTemplate(ctx context.Context, raw *schema.NewAn SiteName: siteInfo.Name, DisplayName: raw.AnswerUserDisplayName, QuestionTitle: raw.QuestionTitle, - AnswerUrl: fmt.Sprintf("%s/questions/%s/%s", siteInfo.SiteUrl, raw.QuestionID, raw.AnswerID), + AnswerUrl: display.AnswerURL(seoInfo.Permalink, siteInfo.SiteUrl, raw.QuestionID, raw.QuestionTitle, raw.AnswerID), AnswerSummary: raw.AnswerSummary, UnsubscribeUrl: fmt.Sprintf("%s/users/unsubscribe?code=%s", siteInfo.SiteUrl, raw.UnsubscribeCode), } @@ -252,7 +224,11 @@ func (es *EmailService) NewAnswerTemplate(ctx context.Context, raw *schema.NewAn // NewInviteAnswerTemplate new invite answer template func (es *EmailService) NewInviteAnswerTemplate(ctx context.Context, raw *schema.NewInviteAnswerTemplateRawData) ( title, body string, err error) { - siteInfo, err := es.getSiteGeneral(ctx) + siteInfo, err := es.siteInfoService.GetSiteGeneral(ctx) + if err != nil { + return + } + seoInfo, err := es.siteInfoService.GetSiteSeo(ctx) if err != nil { return } @@ -260,7 +236,7 @@ func (es *EmailService) NewInviteAnswerTemplate(ctx context.Context, raw *schema SiteName: siteInfo.Name, DisplayName: raw.InviterDisplayName, QuestionTitle: raw.QuestionTitle, - InviteUrl: fmt.Sprintf("%s/questions/%s", siteInfo.SiteUrl, raw.QuestionID), + InviteUrl: display.QuestionURL(seoInfo.Permalink, siteInfo.SiteUrl, raw.QuestionID, raw.QuestionTitle), UnsubscribeUrl: fmt.Sprintf("%s/users/unsubscribe?code=%s", siteInfo.SiteUrl, raw.UnsubscribeCode), } @@ -273,7 +249,11 @@ func (es *EmailService) NewInviteAnswerTemplate(ctx context.Context, raw *schema // NewCommentTemplate new comment template func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewCommentTemplateRawData) ( title, body string, err error) { - siteInfo, err := es.getSiteGeneral(ctx) + siteInfo, err := es.siteInfoService.GetSiteGeneral(ctx) + if err != nil { + return + } + seoInfo, err := es.siteInfoService.GetSiteSeo(ctx) if err != nil { return } @@ -284,13 +264,8 @@ func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewC CommentSummary: raw.CommentSummary, UnsubscribeUrl: fmt.Sprintf("%s/users/unsubscribe?code=%s", siteInfo.SiteUrl, raw.UnsubscribeCode), } - if len(raw.AnswerID) > 0 { - templateData.CommentUrl = fmt.Sprintf("%s/questions/%s/%s?commentId=%s", siteInfo.SiteUrl, raw.QuestionID, - raw.AnswerID, raw.CommentID) - } else { - templateData.CommentUrl = fmt.Sprintf("%s/questions/%s?commentId=%s", siteInfo.SiteUrl, - raw.QuestionID, raw.CommentID) - } + templateData.CommentUrl = display.CommentURL(seoInfo.Permalink, + siteInfo.SiteUrl, raw.QuestionID, raw.QuestionTitle, raw.AnswerID, raw.CommentID) lang := handler.GetLangByCtx(ctx) title = translator.TrWithData(lang, constant.EmailTplKeyNewCommentTitle, templateData) @@ -301,7 +276,11 @@ func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewC // NewQuestionTemplate new question template func (es *EmailService) NewQuestionTemplate(ctx context.Context, raw *schema.NewQuestionTemplateRawData) ( title, body string, err error) { - siteInfo, err := es.getSiteGeneral(ctx) + siteInfo, err := es.siteInfoService.GetSiteGeneral(ctx) + if err != nil { + return + } + seoInfo, err := es.siteInfoService.GetSiteSeo(ctx) if err != nil { return } @@ -311,7 +290,8 @@ func (es *EmailService) NewQuestionTemplate(ctx context.Context, raw *schema.New Tags: strings.Join(raw.Tags, ", "), UnsubscribeUrl: fmt.Sprintf("%s/users/unsubscribe?code=%s", siteInfo.SiteUrl, raw.UnsubscribeCode), } - templateData.QuestionUrl = fmt.Sprintf("%s/questions/%s", siteInfo.SiteUrl, raw.QuestionID) + templateData.QuestionUrl = display.QuestionURL( + seoInfo.Permalink, siteInfo.SiteUrl, raw.QuestionID, raw.QuestionTitle) lang := handler.GetLangByCtx(ctx) title = translator.TrWithData(lang, constant.EmailTplKeyNewQuestionTitle, templateData) diff --git a/pkg/display/url.go b/pkg/display/url.go new file mode 100644 index 000000000..43290129e --- /dev/null +++ b/pkg/display/url.go @@ -0,0 +1,41 @@ +package display + +import ( + "github.com/answerdev/answer/internal/base/constant" + "github.com/answerdev/answer/pkg/htmltext" + "github.com/answerdev/answer/pkg/uid" +) + +// QuestionURL get question url +func QuestionURL(permalink int, siteUrl, questionID, title string) string { + u := siteUrl + "/questions" + if permalink == constant.PermalinkQuestionIDAndTitle || permalink == constant.PermalinkQuestionID { + questionID = uid.DeShortID(questionID) + } else { + questionID = uid.EnShortID(questionID) + } + u += "/" + questionID + if permalink == constant.PermalinkQuestionIDAndTitle || permalink == constant.PermalinkQuestionIDAndTitleByShortID { + u += "/" + htmltext.UrlTitle(title) + } + return u +} + +// AnswerURL get answer url +func AnswerURL(permalink int, siteUrl, questionID, title, answerID string) string { + if permalink == constant.PermalinkQuestionIDAndTitle || + permalink == constant.PermalinkQuestionID { + answerID = uid.DeShortID(answerID) + } else { + answerID = uid.EnShortID(answerID) + } + return QuestionURL(permalink, siteUrl, questionID, title) + "/" + answerID +} + +// CommentURL get comment url +func CommentURL(permalink int, siteUrl, questionID, title, answerID, commentID string) string { + if len(answerID) > 0 { + return AnswerURL(permalink, siteUrl, questionID, answerID, title) + "?commentId=" + commentID + } + return QuestionURL(permalink, siteUrl, questionID, title) + "?commentId=" + commentID +}