From a8e008de0702f76733c79ae784357469b4bb496c Mon Sep 17 00:00:00 2001
From: sy-records <52o@qq52o.cn>
Date: Tue, 15 Oct 2024 19:20:04 +0800
Subject: [PATCH 1/3] feat: Support related and hot questions template
---
cmd/wire_gen.go | 2 +-
internal/controller/template_controller.go | 68 ++++++++++++++++------
ui/template/hot-question.html | 42 +++++++++++++
ui/template/question-detail.html | 10 +++-
ui/template/question.html | 4 +-
ui/template/related-question.html | 42 +++++++++++++
6 files changed, 146 insertions(+), 22 deletions(-)
create mode 100644 ui/template/hot-question.html
create mode 100644 ui/template/related-question.html
diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go
index 978ab23b3..d8e6c744b 100644
--- a/cmd/wire_gen.go
+++ b/cmd/wire_gen.go
@@ -277,7 +277,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
avatarMiddleware := middleware.NewAvatarMiddleware(serviceConf, uploaderService)
shortIDMiddleware := middleware.NewShortIDMiddleware(siteInfoCommonService)
templateRenderController := templaterender.NewTemplateRenderController(questionService, userService, tagService, answerService, commentService, siteInfoCommonService, questionRepo)
- templateController := controller.NewTemplateController(templateRenderController, siteInfoCommonService, eventQueueService, userService)
+ templateController := controller.NewTemplateController(templateRenderController, siteInfoCommonService, eventQueueService, userService, questionService)
templateRouter := router.NewTemplateRouter(templateController, templateRenderController, siteInfoController, authUserMiddleware)
connectorController := controller.NewConnectorController(siteInfoCommonService, emailService, userExternalLoginService)
userCenterLoginService := user_external_login2.NewUserCenterLoginService(userRepo, userCommon, userExternalLoginRepo, userActiveActivityRepo, siteInfoCommonService)
diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go
index 56a38f006..5a63e6de1 100644
--- a/internal/controller/template_controller.go
+++ b/internal/controller/template_controller.go
@@ -22,6 +22,7 @@ package controller
import (
"encoding/json"
"fmt"
+ "github.com/apache/incubator-answer/internal/base/middleware"
"github.com/apache/incubator-answer/internal/service/content"
"github.com/apache/incubator-answer/internal/service/event_queue"
"github.com/apache/incubator-answer/plugin"
@@ -58,6 +59,7 @@ type TemplateController struct {
siteInfoService siteinfo_common.SiteInfoCommonService
eventQueueService event_queue.EventQueueService
userService *content.UserService
+ questionService *content.QuestionService
}
// NewTemplateController new controller
@@ -66,6 +68,7 @@ func NewTemplateController(
siteInfoService siteinfo_common.SiteInfoCommonService,
eventQueueService event_queue.EventQueueService,
userService *content.UserService,
+ questionService *content.QuestionService,
) *TemplateController {
script, css := GetStyle()
return &TemplateController{
@@ -75,6 +78,7 @@ func NewTemplateController(
siteInfoService: siteInfoService,
eventQueueService: eventQueueService,
userService: userService,
+ questionService: questionService,
}
}
func GetStyle() (script []string, css string) {
@@ -146,6 +150,14 @@ func (tc *TemplateController) Index(ctx *gin.Context) {
return
}
+ hotQuestionReq := &schema.QuestionPageReq{
+ Page: 1,
+ PageSize: 6,
+ OrderCond: "hot",
+ InDays: 7,
+ }
+ hotQuestion, _, _ := tc.templateRenderController.Index(ctx, hotQuestionReq)
+
siteInfo := tc.SiteInfo(ctx)
siteInfo.Canonical = siteInfo.General.SiteUrl
@@ -156,10 +168,11 @@ func (tc *TemplateController) Index(ctx *gin.Context) {
}
siteInfo.Title = ""
tc.html(ctx, http.StatusOK, "question.html", siteInfo, gin.H{
- "data": data,
- "useTitle": UrlUseTitle,
- "page": templaterender.Paginator(page, req.PageSize, count),
- "path": "questions",
+ "data": data,
+ "useTitle": UrlUseTitle,
+ "page": templaterender.Paginator(page, req.PageSize, count),
+ "path": "questions",
+ "hotQuestion": hotQuestion,
})
}
@@ -177,6 +190,15 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) {
tc.Page404(ctx)
return
}
+
+ hotQuestionReq := &schema.QuestionPageReq{
+ Page: 1,
+ PageSize: 6,
+ OrderCond: "hot",
+ InDays: 7,
+ }
+ hotQuestion, _, _ := tc.templateRenderController.Index(ctx, hotQuestionReq)
+
siteInfo := tc.SiteInfo(ctx)
siteInfo.Canonical = fmt.Sprintf("%s/questions", siteInfo.General.SiteUrl)
if page > 1 {
@@ -190,13 +212,14 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) {
}
siteInfo.Title = fmt.Sprintf("%s - %s", translator.Tr(handler.GetLang(ctx), constant.QuestionsTitleTrKey), siteInfo.General.Name)
tc.html(ctx, http.StatusOK, "question.html", siteInfo, gin.H{
- "data": data,
- "useTitle": UrlUseTitle,
- "page": templaterender.Paginator(page, req.PageSize, count),
+ "data": data,
+ "useTitle": UrlUseTitle,
+ "page": templaterender.Paginator(page, req.PageSize, count),
+ "hotQuestion": hotQuestion,
})
}
-func (tc *TemplateController) QuestionInfoeRdirect(ctx *gin.Context, siteInfo *schema.TemplateSiteInfoResp, correctTitle bool) (jump bool, url string) {
+func (tc *TemplateController) QuestionInfoRedirect(ctx *gin.Context, siteInfo *schema.TemplateSiteInfoResp, correctTitle bool) (jump bool, url string) {
questionID := ctx.Param("id")
title := ctx.Param("title")
answerID := uid.DeShortID(title)
@@ -316,7 +339,7 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
}
siteInfo := tc.SiteInfo(ctx)
- jump, jumpurl := tc.QuestionInfoeRdirect(ctx, siteInfo, correctTitle)
+ jump, jumpurl := tc.QuestionInfoRedirect(ctx, siteInfo, correctTitle)
if jump {
ctx.Redirect(http.StatusFound, jumpurl)
return
@@ -337,7 +360,6 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
}
// comments
-
objectIDs := []string{uid.DeShortID(id)}
for _, answer := range answers {
answerID := uid.DeShortID(answer.ID)
@@ -348,6 +370,17 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
tc.Page404(ctx)
return
}
+
+ UrlUseTitle := false
+ if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle ||
+ siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID {
+ UrlUseTitle = true
+ }
+
+ //related question
+ userID := middleware.GetLoginUserIDFromContext(ctx)
+ relatedQuestion, _, _ := tc.questionService.SimilarQuestion(ctx, id, userID)
+
siteInfo.Canonical = fmt.Sprintf("%s/questions/%s/%s", siteInfo.General.SiteUrl, id, encodeTitle)
if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionID || siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDByShortID {
siteInfo.Canonical = fmt.Sprintf("%s/questions/%s", siteInfo.General.SiteUrl, id)
@@ -389,7 +422,6 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
item.Author.URL = fmt.Sprintf("%s/users/%s", siteInfo.General.SiteUrl, answer.UserInfo.Username)
answerList = append(answerList, item)
}
-
}
jsonLD.MainEntity.SuggestedAnswer = answerList
jsonLDStr, err := json.Marshal(jsonLD)
@@ -405,12 +437,14 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
siteInfo.Keywords = strings.Replace(strings.Trim(fmt.Sprint(tags), "[]"), " ", ",", -1)
siteInfo.Title = fmt.Sprintf("%s - %s", detail.Title, siteInfo.General.Name)
tc.html(ctx, http.StatusOK, "question-detail.html", siteInfo, gin.H{
- "id": id,
- "answerid": answerid,
- "detail": detail,
- "answers": answers,
- "comments": comments,
- "noindex": detail.Show == entity.QuestionHide,
+ "id": id,
+ "answerid": answerid,
+ "detail": detail,
+ "answers": answers,
+ "comments": comments,
+ "noindex": detail.Show == entity.QuestionHide,
+ "useTitle": UrlUseTitle,
+ "relatedQuestion": relatedQuestion,
})
}
diff --git a/ui/template/hot-question.html b/ui/template/hot-question.html
new file mode 100644
index 000000000..239819267
--- /dev/null
+++ b/ui/template/hot-question.html
@@ -0,0 +1,42 @@
+
+{{define "hot-question"}}
+
+{{end}}
diff --git a/ui/template/question-detail.html b/ui/template/question-detail.html
index 2134a04f5..d0e6933d9 100644
--- a/ui/template/question-detail.html
+++ b/ui/template/question-detail.html
@@ -24,7 +24,11 @@
@@ -116,7 +120,7 @@
{{.detail.AnswerCount}} Answers
{{range .answers}}
-
+
{{formatLinkNofollow .HTML}}
@@ -192,8 +196,8 @@
{{.detail.AnswerCount}} Answers
{{end}}
-
-
+
+ {{template "related-question" .}}
diff --git a/ui/template/question.html b/ui/template/question.html
index 40c645edc..058645e5b 100644
--- a/ui/template/question.html
+++ b/ui/template/question.html
@@ -94,7 +94,9 @@
-
+
+ {{template "hot-question" .}}
+
{{template "footer" .}}
diff --git a/ui/template/related-question.html b/ui/template/related-question.html
new file mode 100644
index 000000000..c93ccc8da
--- /dev/null
+++ b/ui/template/related-question.html
@@ -0,0 +1,42 @@
+
+{{define "related-question"}}
+
+{{end}}
From 916dba3f063b95ab8297c63630750b2d08988046 Mon Sep 17 00:00:00 2001
From: Luffy <52o@qq52o.cn>
Date: Fri, 18 Oct 2024 10:12:59 +0800
Subject: [PATCH 2/3] feat(pager): Show 404 when page is out of range (#1135)
close #1133
---
internal/base/pager/pagination.go | 12 ++++++++++++
internal/controller/question_controller.go | 4 ++++
internal/controller/tag_controller.go | 5 +++++
internal/controller/template_controller.go | 10 +++++++---
internal/service/tag/tag_service.go | 1 -
ui/src/services/client/question.ts | 5 ++---
ui/src/services/common.ts | 10 +++++-----
7 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/internal/base/pager/pagination.go b/internal/base/pager/pagination.go
index 5411e6850..36849fed5 100644
--- a/internal/base/pager/pagination.go
+++ b/internal/base/pager/pagination.go
@@ -62,3 +62,15 @@ func ValPageAndPageSize(page, pageSize int) (int, int) {
}
return page, pageSize
}
+
+// ValPageOutOfRange validate page out of range
+func ValPageOutOfRange(total int64, page, pageSize int) bool {
+ if total <= 0 {
+ return false
+ }
+ if pageSize <= 0 {
+ return true
+ }
+ totalPages := (total + int64(pageSize) - 1) / int64(pageSize)
+ return page < 1 || page > int(totalPages)
+}
diff --git a/internal/controller/question_controller.go b/internal/controller/question_controller.go
index 8f3498556..310a8201c 100644
--- a/internal/controller/question_controller.go
+++ b/internal/controller/question_controller.go
@@ -337,6 +337,10 @@ func (qc *QuestionController) QuestionPage(ctx *gin.Context) {
handler.HandleResponse(ctx, err, nil)
return
}
+ if pager.ValPageOutOfRange(total, req.Page, req.PageSize) {
+ handler.HandleResponse(ctx, errors.NotFound(reason.RequestFormatError), nil)
+ return
+ }
handler.HandleResponse(ctx, nil, pager.NewPageModel(total, questions))
}
diff --git a/internal/controller/tag_controller.go b/internal/controller/tag_controller.go
index 5f5cf5fbd..1e98b480c 100644
--- a/internal/controller/tag_controller.go
+++ b/internal/controller/tag_controller.go
@@ -22,6 +22,7 @@ package controller
import (
"github.com/apache/incubator-answer/internal/base/handler"
"github.com/apache/incubator-answer/internal/base/middleware"
+ "github.com/apache/incubator-answer/internal/base/pager"
"github.com/apache/incubator-answer/internal/base/reason"
"github.com/apache/incubator-answer/internal/schema"
"github.com/apache/incubator-answer/internal/service/permission"
@@ -269,6 +270,10 @@ func (tc *TagController) GetTagWithPage(ctx *gin.Context) {
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
resp, err := tc.tagService.GetTagWithPage(ctx, req)
+ if pager.ValPageOutOfRange(resp.Count, req.Page, req.PageSize) {
+ handler.HandleResponse(ctx, errors.NotFound(reason.RequestFormatError), nil)
+ return
+ }
handler.HandleResponse(ctx, err, resp)
}
diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go
index 5a63e6de1..c3a2ff0af 100644
--- a/internal/controller/template_controller.go
+++ b/internal/controller/template_controller.go
@@ -23,6 +23,7 @@ import (
"encoding/json"
"fmt"
"github.com/apache/incubator-answer/internal/base/middleware"
+ "github.com/apache/incubator-answer/internal/base/pager"
"github.com/apache/incubator-answer/internal/service/content"
"github.com/apache/incubator-answer/internal/service/event_queue"
"github.com/apache/incubator-answer/plugin"
@@ -145,7 +146,7 @@ func (tc *TemplateController) Index(ctx *gin.Context) {
var page = req.Page
data, count, err := tc.templateRenderController.Index(ctx, req)
- if err != nil {
+ if err != nil || (len(data) == 0 && pager.ValPageOutOfRange(count, page, req.PageSize)) {
tc.Page404(ctx)
return
}
@@ -186,7 +187,7 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) {
}
var page = req.Page
data, count, err := tc.templateRenderController.Index(ctx, req)
- if err != nil {
+ if err != nil || (len(data) == 0 && pager.ValPageOutOfRange(count, page, req.PageSize)) {
tc.Page404(ctx)
return
}
@@ -454,8 +455,11 @@ func (tc *TemplateController) TagList(ctx *gin.Context) {
if handler.BindAndCheck(ctx, req) {
return
}
+ if req.PageSize == 0 {
+ req.PageSize = constant.DefaultPageSize
+ }
data, err := tc.templateRenderController.TagList(ctx, req)
- if err != nil {
+ if err != nil || pager.ValPageOutOfRange(data.Count, req.Page, req.PageSize) {
tc.Page404(ctx)
return
}
diff --git a/internal/service/tag/tag_service.go b/internal/service/tag/tag_service.go
index 018641634..e5fcf597a 100644
--- a/internal/service/tag/tag_service.go
+++ b/internal/service/tag/tag_service.go
@@ -432,7 +432,6 @@ func (ts *TagService) GetTagWithPage(ctx context.Context, req *schema.GetTagWith
}
item.GetExcerpt()
resp = append(resp, item)
-
}
return pager.NewPageModel(total, resp), nil
}
diff --git a/ui/src/services/client/question.ts b/ui/src/services/client/question.ts
index b62fbf1a7..169ccf3d3 100644
--- a/ui/src/services/client/question.ts
+++ b/ui/src/services/client/question.ts
@@ -25,9 +25,8 @@ import type * as Type from '@/common/interface';
export const useQuestionList = (params: Type.QueryQuestionsReq) => {
const apiUrl = `/answer/api/v1/question/page?${qs.stringify(params)}`;
- const { data, error } = useSWR(
- [apiUrl],
- request.instance.get,
+ const { data, error } = useSWR(apiUrl, (url) =>
+ request.get(url, { allow404: true }),
);
return {
data,
diff --git a/ui/src/services/common.ts b/ui/src/services/common.ts
index ad0d99e03..cfc1d9cd2 100644
--- a/ui/src/services/common.ts
+++ b/ui/src/services/common.ts
@@ -35,11 +35,11 @@ export const queryQuestionByTitle = (title: string) => {
};
export const useQueryTags = (params) => {
- const { data, error, mutate } = useSWR(
- `/answer/api/v1/tags/page?${qs.stringify(params, {
- skipNulls: true,
- })}`,
- request.instance.get,
+ const apiUrl = `/answer/api/v1/tags/page?${qs.stringify(params, {
+ skipNulls: true,
+ })}`;
+ const { data, error, mutate } = useSWR(apiUrl, (url) =>
+ request.get(url, { allow404: true }),
);
return {
data,
From 23cc755aa8ba7d536c8c5db36022264efc5b2201 Mon Sep 17 00:00:00 2001
From: LinkinStars
Date: Fri, 18 Oct 2024 15:55:31 +0800
Subject: [PATCH 3/3] feat(question): add question linking feature for closing
question
---
cmd/wire_gen.go | 2 +-
internal/service/content/question_service.go | 4 +
internal/service/question_common/question.go | 76 ++++++++++++
plugin/importer.go | 124 +++++++++----------
4 files changed, 143 insertions(+), 63 deletions(-)
diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go
index d8e6c744b..801c5a776 100644
--- a/cmd/wire_gen.go
+++ b/cmd/wire_gen.go
@@ -177,7 +177,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
answerCommon := answercommon.NewAnswerCommon(answerRepo)
metaRepo := meta.NewMetaRepo(dataData)
metaCommonService := metacommon.NewMetaCommonService(metaRepo)
- questionCommon := questioncommon.NewQuestionCommon(questionRepo, answerRepo, voteRepo, followRepo, tagCommonService, userCommon, collectionCommon, answerCommon, metaCommonService, configService, activityQueueService, revisionRepo, dataData)
+ questionCommon := questioncommon.NewQuestionCommon(questionRepo, answerRepo, voteRepo, followRepo, tagCommonService, userCommon, collectionCommon, answerCommon, metaCommonService, configService, activityQueueService, revisionRepo, siteInfoCommonService, dataData)
eventQueueService := event_queue.NewEventQueueService()
userService := content.NewUserService(userRepo, userActiveActivityRepo, activityRepo, emailService, authService, siteInfoCommonService, userRoleRelService, userCommon, userExternalLoginService, userNotificationConfigRepo, userNotificationConfigService, questionCommon, eventQueueService)
captchaRepo := captcha.NewCaptchaRepo(dataData)
diff --git a/internal/service/content/question_service.go b/internal/service/content/question_service.go
index 7cfd39a09..51f0da9b5 100644
--- a/internal/service/content/question_service.go
+++ b/internal/service/content/question_service.go
@@ -174,6 +174,9 @@ func (qs *QuestionService) CloseQuestion(ctx context.Context, req *schema.CloseQ
if err != nil {
return err
}
+ if cf.Key == constant.ReasonADuplicate {
+ qs.questioncommon.AddQuestionLinkForCloseReason(ctx, questionInfo, req.CloseMsg)
+ }
qs.activityQueueService.Send(ctx, &schema.ActivityMsg{
UserID: req.UserID,
@@ -199,6 +202,7 @@ func (qs *QuestionService) ReopenQuestion(ctx context.Context, req *schema.Reope
if err != nil {
return err
}
+ qs.questioncommon.RemoveQuestionLinkForReopen(ctx, questionInfo)
qs.activityQueueService.Send(ctx, &schema.ActivityMsg{
UserID: req.UserID,
ObjectID: questionInfo.ID,
diff --git a/internal/service/question_common/question.go b/internal/service/question_common/question.go
index 63c8f5a2a..13df33896 100644
--- a/internal/service/question_common/question.go
+++ b/internal/service/question_common/question.go
@@ -23,6 +23,7 @@ import (
"context"
"encoding/json"
"fmt"
+ "github.com/apache/incubator-answer/internal/service/siteinfo_common"
"math"
"strings"
"time"
@@ -98,6 +99,7 @@ type QuestionCommon struct {
configService *config.ConfigService
activityQueueService activity_queue.ActivityQueueService
revisionRepo revision.RevisionRepo
+ siteInfoService siteinfo_common.SiteInfoCommonService
data *data.Data
}
@@ -113,6 +115,7 @@ func NewQuestionCommon(questionRepo QuestionRepo,
configService *config.ConfigService,
activityQueueService activity_queue.ActivityQueueService,
revisionRepo revision.RevisionRepo,
+ siteInfoService siteinfo_common.SiteInfoCommonService,
data *data.Data,
) *QuestionCommon {
return &QuestionCommon{
@@ -128,6 +131,7 @@ func NewQuestionCommon(questionRepo QuestionRepo,
configService: configService,
activityQueueService: activityQueueService,
revisionRepo: revisionRepo,
+ siteInfoService: siteInfoService,
data: data,
}
}
@@ -795,3 +799,75 @@ func (qs *QuestionCommon) UpdateQuestionLink(ctx context.Context, questionID, an
return parsedText, nil
}
+
+// AddQuestionLinkForCloseReason When the reason about close question is a question link, add the link to the question
+func (qs *QuestionCommon) AddQuestionLinkForCloseReason(ctx context.Context,
+ questionInfo *entity.Question, closeMsg string) {
+ questionID := qs.tryToGetQuestionIDFromMsg(ctx, closeMsg)
+ if len(questionID) == 0 {
+ return
+ }
+
+ linkedQuestion, exist, err := qs.questionRepo.GetQuestion(ctx, questionID)
+ if err != nil {
+ log.Errorf("get question error %s", err)
+ return
+ }
+ if !exist {
+ return
+ }
+ err = qs.questionRepo.LinkQuestion(ctx, &entity.QuestionLink{
+ FromQuestionID: questionInfo.ID,
+ ToQuestionID: linkedQuestion.ID,
+ Status: entity.QuestionLinkStatusAvailable,
+ })
+ if err != nil {
+ log.Errorf("link question error %s", err)
+ }
+}
+
+func (qs *QuestionCommon) RemoveQuestionLinkForReopen(ctx context.Context, questionInfo *entity.Question) {
+ questionInfo.ID = uid.DeShortID(questionInfo.ID)
+ metaInfo, err := qs.metaCommonService.GetMetaByObjectIdAndKey(ctx, questionInfo.ID, entity.QuestionCloseReasonKey)
+ if err != nil {
+ return
+ }
+
+ closeMsgMeta := &schema.CloseQuestionMeta{}
+ _ = json.Unmarshal([]byte(metaInfo.Value), closeMsgMeta)
+
+ linkedQuestionID := qs.tryToGetQuestionIDFromMsg(ctx, closeMsgMeta.CloseMsg)
+ if len(linkedQuestionID) == 0 {
+ return
+ }
+ err = qs.questionRepo.RemoveQuestionLink(ctx, &entity.QuestionLink{
+ FromQuestionID: questionInfo.ID,
+ ToQuestionID: linkedQuestionID,
+ })
+ if err != nil {
+ log.Errorf("remove question link error %s", err)
+ }
+}
+
+func (qs *QuestionCommon) tryToGetQuestionIDFromMsg(ctx context.Context, closeMsg string) (questionID string) {
+ siteGeneral, err := qs.siteInfoService.GetSiteGeneral(ctx)
+ if err != nil {
+ log.Errorf("get site general error %s", err)
+ return
+ }
+ if !strings.HasPrefix(closeMsg, siteGeneral.SiteUrl) {
+ return
+ }
+ // get question id from url
+ // the url may like: https://xxx.com/questions/D1401/xxx
+ // the D1401 is question id
+ questionID = strings.TrimPrefix(closeMsg, siteGeneral.SiteUrl)
+ questionID = strings.TrimPrefix(questionID, "/questions/")
+ t := strings.Split(questionID, "/")
+ if len(t) < 1 {
+ return ""
+ }
+ questionID = t[0]
+ questionID = uid.DeShortID(questionID)
+ return questionID
+}
diff --git a/plugin/importer.go b/plugin/importer.go
index 3893d54a1..bfd7d36a5 100644
--- a/plugin/importer.go
+++ b/plugin/importer.go
@@ -1,62 +1,62 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package plugin
-
-import (
- "context"
-)
-
-type QuestionImporterInfo struct {
- Title string `json:"title"`
- Content string `json:"content"`
- Tags []string `json:"tags"`
- UserEmail string `json:"user_email"`
-}
-
-type Importer interface {
- Base
- RegisterImporterFunc(ctx context.Context, importer ImporterFunc)
-}
-
-type ImporterFunc interface {
- AddQuestion(ctx context.Context, questionInfo QuestionImporterInfo) (err error)
-}
-
-var (
- // CallImporter is a function that calls all registered parsers
- CallImporter,
- registerImporter = MakePlugin[Importer](false)
-)
-
-func ImporterEnabled() (enabled bool) {
- _ = CallImporter(func(fn Importer) error {
- enabled = true
- return nil
- })
- return
-}
-func GetImporter() (ip Importer, ok bool) {
- _ = CallImporter(func(fn Importer) error {
- ip = fn
- ok = true
- return nil
- })
- return
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package plugin
+
+import (
+ "context"
+)
+
+type QuestionImporterInfo struct {
+ Title string `json:"title"`
+ Content string `json:"content"`
+ Tags []string `json:"tags"`
+ UserEmail string `json:"user_email"`
+}
+
+type Importer interface {
+ Base
+ RegisterImporterFunc(ctx context.Context, importer ImporterFunc)
+}
+
+type ImporterFunc interface {
+ AddQuestion(ctx context.Context, questionInfo QuestionImporterInfo) (err error)
+}
+
+var (
+ // CallImporter is a function that calls all registered parsers
+ CallImporter,
+ registerImporter = MakePlugin[Importer](false)
+)
+
+func ImporterEnabled() (enabled bool) {
+ _ = CallImporter(func(fn Importer) error {
+ enabled = true
+ return nil
+ })
+ return
+}
+func GetImporter() (ip Importer, ok bool) {
+ _ = CallImporter(func(fn Importer) error {
+ ip = fn
+ ok = true
+ return nil
+ })
+ return
+}