fix(email): fix all incorrect url in email.

This commit is contained in:
LinkinStars 2023-10-08 17:58:52 +08:00
parent a920e5c2c1
commit ee5613099f
8 changed files with 127 additions and 87 deletions

View File

@ -121,7 +121,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
userRankRepo := rank.NewUserRankRepo(dataData, configService) userRankRepo := rank.NewUserRankRepo(dataData, configService)
userActiveActivityRepo := activity.NewUserActiveActivityRepo(dataData, activityRepo, userRankRepo, configService) userActiveActivityRepo := activity.NewUserActiveActivityRepo(dataData, activityRepo, userRankRepo, configService)
emailRepo := export.NewEmailRepo(dataData) emailRepo := export.NewEmailRepo(dataData)
emailService := export2.NewEmailService(configService, emailRepo, siteInfoRepo) emailService := export2.NewEmailService(configService, emailRepo, siteInfoCommonService)
userRoleRelRepo := role.NewUserRoleRelRepo(dataData) userRoleRelRepo := role.NewUserRoleRelRepo(dataData)
roleRepo := role.NewRoleRepo(dataData) roleRepo := role.NewRoleRepo(dataData)
roleService := role2.NewRoleService(roleRepo) roleService := role2.NewRoleService(roleRepo)

View File

@ -9,12 +9,12 @@ const (
) )
const ( const (
// PermaLinkQuestionIDAndTitle /questions/10010000000000001/post-title // PermalinkQuestionIDAndTitle /questions/10010000000000001/post-title
PermaLinkQuestionIDAndTitle = iota + 1 PermalinkQuestionIDAndTitle = iota + 1
// PermaLinkQuestionID /questions/10010000000000001 // PermalinkQuestionID /questions/10010000000000001
PermaLinkQuestionID PermalinkQuestionID
// PermaLinkQuestionIDAndTitleByShortID /questions/11/post-title // PermalinkQuestionIDAndTitleByShortID /questions/11/post-title
PermaLinkQuestionIDAndTitleByShortID PermalinkQuestionIDAndTitleByShortID
// PermaLinkQuestionIDByShortID /questions/11 // PermalinkQuestionIDByShortID /questions/11
PermaLinkQuestionIDByShortID PermalinkQuestionIDByShortID
) )

View File

@ -116,7 +116,7 @@ func (tc *TemplateController) Index(ctx *gin.Context) {
siteInfo.Canonical = siteInfo.General.SiteUrl siteInfo.Canonical = siteInfo.General.SiteUrl
UrlUseTitle := false UrlUseTitle := false
if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionIDAndTitle { if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle {
UrlUseTitle = true UrlUseTitle = true
} }
siteInfo.Title = "" siteInfo.Title = ""
@ -149,7 +149,7 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) {
} }
UrlUseTitle := false UrlUseTitle := false
if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionIDAndTitle { if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle {
UrlUseTitle = true UrlUseTitle = true
} }
siteInfo.Title = fmt.Sprintf("Questions - %s", siteInfo.General.Name) 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) 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 { if len(ctx.Request.URL.Query()) > 0 {
url = fmt.Sprintf("%s?%s", url, ctx.Request.URL.RawQuery) url = fmt.Sprintf("%s?%s", url, ctx.Request.URL.RawQuery)
} }
@ -299,7 +299,7 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
return return
} }
siteInfo.Canonical = fmt.Sprintf("%s/questions/%s/%s", siteInfo.General.SiteUrl, id, encodeTitle) 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) siteInfo.Canonical = fmt.Sprintf("%s/questions/%s", siteInfo.General.SiteUrl, id)
} }
jsonLD := &schema.QAPageJsonLD{} jsonLD := &schema.QAPageJsonLD{}
@ -414,7 +414,7 @@ func (tc *TemplateController) TagInfo(ctx *gin.Context) {
siteInfo.Keywords = taginifo.DisplayName siteInfo.Keywords = taginifo.DisplayName
UrlUseTitle := false UrlUseTitle := false
if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionIDAndTitle { if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle {
UrlUseTitle = true UrlUseTitle = true
} }
siteInfo.Title = fmt.Sprintf("'%s' Questions - %s", taginifo.DisplayName, siteInfo.General.Name) siteInfo.Title = fmt.Sprintf("'%s' Questions - %s", taginifo.DisplayName, siteInfo.General.Name)

View File

@ -44,8 +44,8 @@ func (t *TemplateRenderController) Sitemap(ctx *gin.Context) {
"xmlHeader": template.HTML(`<?xml version="1.0" encoding="UTF-8"?>`), "xmlHeader": template.HTML(`<?xml version="1.0" encoding="UTF-8"?>`),
"list": questions, "list": questions,
"general": general, "general": general,
"hastitle": siteInfo.PermaLink == constant.PermaLinkQuestionIDAndTitle || "hastitle": siteInfo.Permalink == constant.PermalinkQuestionIDAndTitle ||
siteInfo.PermaLink == constant.PermaLinkQuestionIDAndTitleByShortID, siteInfo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID,
}, },
) )
return return
@ -93,8 +93,8 @@ func (t *TemplateRenderController) SitemapPage(ctx *gin.Context, page int) error
"xmlHeader": template.HTML(`<?xml version="1.0" encoding="UTF-8"?>`), "xmlHeader": template.HTML(`<?xml version="1.0" encoding="UTF-8"?>`),
"list": questions, "list": questions,
"general": general, "general": general,
"hastitle": siteInfo.PermaLink == constant.PermaLinkQuestionIDAndTitle || "hastitle": siteInfo.Permalink == constant.PermalinkQuestionIDAndTitle ||
siteInfo.PermaLink == constant.PermaLinkQuestionIDAndTitleByShortID, siteInfo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID,
}, },
) )
return nil return nil

View File

@ -34,6 +34,25 @@ func (r *EmailCodeContent) FromJSONString(data string) error {
return json.Unmarshal([]byte(data), &r) 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 { type NewAnswerTemplateRawData struct {
AnswerUserDisplayName string AnswerUserDisplayName string
QuestionTitle string QuestionTitle string

View File

@ -118,13 +118,13 @@ type SiteThemeReq struct {
} }
type SiteSeoReq 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"` Robots string `validate:"required" form:"robots" json:"robots"`
} }
func (s *SiteSeoResp) IsShortLink() bool { func (s *SiteSeoResp) IsShortLink() bool {
return s.PermaLink == constant.PermaLinkQuestionIDAndTitleByShortID || return s.Permalink == constant.PermalinkQuestionIDAndTitleByShortID ||
s.PermaLink == constant.PermaLinkQuestionIDByShortID s.Permalink == constant.PermalinkQuestionIDByShortID
} }
// SiteGeneralResp site general response // SiteGeneralResp site general response

View File

@ -4,6 +4,7 @@ import (
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/answerdev/answer/pkg/display"
"mime" "mime"
"os" "os"
"strings" "strings"
@ -13,7 +14,6 @@ import (
"github.com/answerdev/answer/internal/base/handler" "github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/base/translator" "github.com/answerdev/answer/internal/base/translator"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/internal/schema" "github.com/answerdev/answer/internal/schema"
"github.com/answerdev/answer/internal/service/config" "github.com/answerdev/answer/internal/service/config"
"github.com/answerdev/answer/internal/service/siteinfo_common" "github.com/answerdev/answer/internal/service/siteinfo_common"
@ -25,9 +25,9 @@ import (
// EmailService kit service // EmailService kit service
type EmailService struct { type EmailService struct {
configService *config.ConfigService configService *config.ConfigService
emailRepo EmailRepo emailRepo EmailRepo
siteInfoRepo siteinfo_common.SiteInfoRepo siteInfoService siteinfo_common.SiteInfoCommonService
} }
// EmailRepo email repository // EmailRepo email repository
@ -37,11 +37,15 @@ type EmailRepo interface {
} }
// NewEmailService email service // 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{ return &EmailService{
configService: configService, configService: configService,
emailRepo: emailRepo, emailRepo: emailRepo,
siteInfoRepo: siteInfoRepo, siteInfoService: siteInfoService,
} }
} }
@ -61,25 +65,6 @@ func (e *EmailConfig) IsSSL() bool {
return e.Encryption == "SSL" 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 // SaveCode save code
func (es *EmailService) SaveCode(ctx context.Context, code, codeContent string) { func (es *EmailService) SaveCode(ctx context.Context, code, codeContent string) {
err := es.emailRepo.SetCode(ctx, code, codeContent, 10*time.Minute) 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 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) { 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 { if err != nil {
return return
} }
templateData := RegisterTemplateData{ templateData := &schema.RegisterTemplateData{
SiteName: siteInfo.Name, SiteName: siteInfo.Name,
RegisterUrl: registerUrl, 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) { 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 { if err != nil {
return return
} }
templateData := PassResetTemplateData{SiteName: siteInfo.Name, PassResetUrl: passResetUrl} templateData := &schema.PassResetTemplateData{SiteName: siteInfo.Name, PassResetUrl: passResetUrl}
lang := handler.GetLangByCtx(ctx) lang := handler.GetLangByCtx(ctx)
title = translator.TrWithData(lang, constant.EmailTplKeyPassResetTitle, templateData) 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) { 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 { if err != nil {
return return
} }
templateData := ChangeEmailTemplateData{ templateData := &schema.ChangeEmailTemplateData{
SiteName: siteInfo.Name, SiteName: siteInfo.Name,
ChangeEmailUrl: changeEmailUrl, ChangeEmailUrl: changeEmailUrl,
} }
@ -215,11 +183,11 @@ func (es *EmailService) ChangeEmailTemplate(ctx context.Context, changeEmailUrl
// TestTemplate send test email template parse // TestTemplate send test email template parse
func (es *EmailService) TestTemplate(ctx context.Context) (title, body string, err error) { 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 { if err != nil {
return return
} }
templateData := TestTemplateData{SiteName: siteInfo.Name} templateData := &schema.TestTemplateData{SiteName: siteInfo.Name}
lang := handler.GetLangByCtx(ctx) lang := handler.GetLangByCtx(ctx)
title = translator.TrWithData(lang, constant.EmailTplKeyTestTitle, templateData) 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 // NewAnswerTemplate new answer template
func (es *EmailService) NewAnswerTemplate(ctx context.Context, raw *schema.NewAnswerTemplateRawData) ( func (es *EmailService) NewAnswerTemplate(ctx context.Context, raw *schema.NewAnswerTemplateRawData) (
title, body string, err error) { 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 { if err != nil {
return return
} }
@ -238,7 +210,7 @@ func (es *EmailService) NewAnswerTemplate(ctx context.Context, raw *schema.NewAn
SiteName: siteInfo.Name, SiteName: siteInfo.Name,
DisplayName: raw.AnswerUserDisplayName, DisplayName: raw.AnswerUserDisplayName,
QuestionTitle: raw.QuestionTitle, 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, AnswerSummary: raw.AnswerSummary,
UnsubscribeUrl: fmt.Sprintf("%s/users/unsubscribe?code=%s", siteInfo.SiteUrl, raw.UnsubscribeCode), 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 // NewInviteAnswerTemplate new invite answer template
func (es *EmailService) NewInviteAnswerTemplate(ctx context.Context, raw *schema.NewInviteAnswerTemplateRawData) ( func (es *EmailService) NewInviteAnswerTemplate(ctx context.Context, raw *schema.NewInviteAnswerTemplateRawData) (
title, body string, err error) { 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 { if err != nil {
return return
} }
@ -260,7 +236,7 @@ func (es *EmailService) NewInviteAnswerTemplate(ctx context.Context, raw *schema
SiteName: siteInfo.Name, SiteName: siteInfo.Name,
DisplayName: raw.InviterDisplayName, DisplayName: raw.InviterDisplayName,
QuestionTitle: raw.QuestionTitle, 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), 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 // NewCommentTemplate new comment template
func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewCommentTemplateRawData) ( func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewCommentTemplateRawData) (
title, body string, err error) { 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 { if err != nil {
return return
} }
@ -284,13 +264,8 @@ func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewC
CommentSummary: raw.CommentSummary, CommentSummary: raw.CommentSummary,
UnsubscribeUrl: fmt.Sprintf("%s/users/unsubscribe?code=%s", siteInfo.SiteUrl, raw.UnsubscribeCode), UnsubscribeUrl: fmt.Sprintf("%s/users/unsubscribe?code=%s", siteInfo.SiteUrl, raw.UnsubscribeCode),
} }
if len(raw.AnswerID) > 0 { templateData.CommentUrl = display.CommentURL(seoInfo.Permalink,
templateData.CommentUrl = fmt.Sprintf("%s/questions/%s/%s?commentId=%s", siteInfo.SiteUrl, raw.QuestionID, siteInfo.SiteUrl, raw.QuestionID, raw.QuestionTitle, raw.AnswerID, raw.CommentID)
raw.AnswerID, raw.CommentID)
} else {
templateData.CommentUrl = fmt.Sprintf("%s/questions/%s?commentId=%s", siteInfo.SiteUrl,
raw.QuestionID, raw.CommentID)
}
lang := handler.GetLangByCtx(ctx) lang := handler.GetLangByCtx(ctx)
title = translator.TrWithData(lang, constant.EmailTplKeyNewCommentTitle, templateData) 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 // NewQuestionTemplate new question template
func (es *EmailService) NewQuestionTemplate(ctx context.Context, raw *schema.NewQuestionTemplateRawData) ( func (es *EmailService) NewQuestionTemplate(ctx context.Context, raw *schema.NewQuestionTemplateRawData) (
title, body string, err error) { 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 { if err != nil {
return return
} }
@ -311,7 +290,8 @@ func (es *EmailService) NewQuestionTemplate(ctx context.Context, raw *schema.New
Tags: strings.Join(raw.Tags, ", "), Tags: strings.Join(raw.Tags, ", "),
UnsubscribeUrl: fmt.Sprintf("%s/users/unsubscribe?code=%s", siteInfo.SiteUrl, raw.UnsubscribeCode), 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) lang := handler.GetLangByCtx(ctx)
title = translator.TrWithData(lang, constant.EmailTplKeyNewQuestionTitle, templateData) title = translator.TrWithData(lang, constant.EmailTplKeyNewQuestionTitle, templateData)

41
pkg/display/url.go Normal file
View File

@ -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
}