From 666ab706a66f7c39c8bb758c0abc2c08c15d4967 Mon Sep 17 00:00:00 2001 From: Dinesht04 Date: Thu, 13 Nov 2025 02:22:58 +0530 Subject: [PATCH 01/25] feat(ui): add min values for inputs and context-based keyboards for inputs --- ui/src/components/SchemaForm/components/Input.tsx | 15 +++++++++++++++ ui/src/components/SchemaForm/index.tsx | 3 +++ ui/src/components/SchemaForm/types.ts | 10 ++++++++++ ui/src/pages/Admin/Privileges/index.tsx | 2 ++ ui/src/pages/Admin/Write/index.tsx | 10 ++++++++++ 5 files changed, 40 insertions(+) diff --git a/ui/src/components/SchemaForm/components/Input.tsx b/ui/src/components/SchemaForm/components/Input.tsx index 1a3fe319b..c0fd084ca 100644 --- a/ui/src/components/SchemaForm/components/Input.tsx +++ b/ui/src/components/SchemaForm/components/Input.tsx @@ -29,6 +29,17 @@ interface Props { onChange?: (fd: Type.FormDataType) => void; formData: Type.FormDataType; readOnly: boolean; + minValue?: number; + inputMode?: + | 'text' + | 'search' + | 'none' + | 'tel' + | 'url' + | 'email' + | 'numeric' + | 'decimal' + | undefined; } const Index: FC = ({ type = 'text', @@ -37,6 +48,8 @@ const Index: FC = ({ onChange, formData, readOnly = false, + minValue = 0, + inputMode = 'text', }) => { const fieldObject = formData[fieldName]; const handleChange = (evt: React.ChangeEvent) => { @@ -60,6 +73,8 @@ const Index: FC = ({ placeholder={placeholder} type={type} value={fieldObject?.value || ''} + min={minValue} + inputMode={inputMode} onChange={handleChange} disabled={readOnly} isInvalid={fieldObject?.isInvalid} diff --git a/ui/src/components/SchemaForm/index.tsx b/ui/src/components/SchemaForm/index.tsx index 421e0b1e1..23b193b48 100644 --- a/ui/src/components/SchemaForm/index.tsx +++ b/ui/src/components/SchemaForm/index.tsx @@ -368,6 +368,9 @@ const SchemaForm: ForwardRefRenderFunction = ( {widget === 'input' ? ( { } return true; }, + inputType: 'number', + inputMode: 'numeric', }, }; }); diff --git a/ui/src/pages/Admin/Write/index.tsx b/ui/src/pages/Admin/Write/index.tsx index 86d44d6d9..fee2d28cc 100644 --- a/ui/src/pages/Admin/Write/index.tsx +++ b/ui/src/pages/Admin/Write/index.tsx @@ -261,6 +261,8 @@ const Index: FC = () => { {t('min_tags.label')} { @@ -302,6 +304,8 @@ const Index: FC = () => { {t('min_content.label')} { @@ -344,6 +348,8 @@ const Index: FC = () => { {t('image_size.label')} { @@ -366,6 +372,8 @@ const Index: FC = () => { {t('attachment_size.label')} { @@ -388,6 +396,8 @@ const Index: FC = () => { {t('image_megapixels.label')} { From 157dbfd08a1474534fe3548ef02243bf421ba020 Mon Sep 17 00:00:00 2001 From: Dinesht04 Date: Fri, 14 Nov 2025 02:28:46 +0530 Subject: [PATCH 02/25] feat(ui): add types, logic and defaults for min, max value of input component of form --- ui/src/components/SchemaForm/components/Input.tsx | 9 ++++++--- ui/src/components/SchemaForm/index.tsx | 9 +++++++++ ui/src/components/SchemaForm/types.ts | 2 ++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ui/src/components/SchemaForm/components/Input.tsx b/ui/src/components/SchemaForm/components/Input.tsx index c0fd084ca..3a2c0397d 100644 --- a/ui/src/components/SchemaForm/components/Input.tsx +++ b/ui/src/components/SchemaForm/components/Input.tsx @@ -29,7 +29,8 @@ interface Props { onChange?: (fd: Type.FormDataType) => void; formData: Type.FormDataType; readOnly: boolean; - minValue?: number; + min?: number; + max?: number; inputMode?: | 'text' | 'search' @@ -48,7 +49,8 @@ const Index: FC = ({ onChange, formData, readOnly = false, - minValue = 0, + min = 0, + max = 65355, inputMode = 'text', }) => { const fieldObject = formData[fieldName]; @@ -73,7 +75,8 @@ const Index: FC = ({ placeholder={placeholder} type={type} value={fieldObject?.value || ''} - min={minValue} + min={min} + max={max} inputMode={inputMode} onChange={handleChange} disabled={readOnly} diff --git a/ui/src/components/SchemaForm/index.tsx b/ui/src/components/SchemaForm/index.tsx index 23b193b48..5bde2fdc8 100644 --- a/ui/src/components/SchemaForm/index.tsx +++ b/ui/src/components/SchemaForm/index.tsx @@ -260,6 +260,8 @@ const SchemaForm: ForwardRefRenderFunction = ( enum: enumValues = [], enumNames = [], max_length = 0, + max = 65355, + min = 0, } = properties[key]; const { 'ui:widget': widget = 'input', 'ui:options': uiOpt } = uiSchema?.[key] || {}; @@ -374,6 +376,8 @@ const SchemaForm: ForwardRefRenderFunction = ( placeholder={ uiOpt && 'placeholder' in uiOpt ? uiOpt.placeholder : '' } + min={min} + max={max} fieldName={key} onChange={onChange} formData={formData} @@ -408,9 +412,14 @@ const SchemaForm: ForwardRefRenderFunction = ( type={ uiOpt && 'inputType' in uiOpt ? uiOpt.inputType : 'text' } + inputMode={ + uiOpt && 'inputMode' in uiOpt ? uiOpt.inputMode : 'text' + } placeholder={ uiOpt && 'placeholder' in uiOpt ? uiOpt.placeholder : '' } + min={min} + max={max} fieldName={key} onChange={onChange} formData={formData} diff --git a/ui/src/components/SchemaForm/types.ts b/ui/src/components/SchemaForm/types.ts index eaedf902a..55cf8e99d 100644 --- a/ui/src/components/SchemaForm/types.ts +++ b/ui/src/components/SchemaForm/types.ts @@ -49,6 +49,8 @@ export interface JSONSchema { description?: string; enum?: Array; enumNames?: string[]; + min?: number; + max?: number; default?: string | boolean | number | any[]; max_length?: number; }; From 54e602c5e6ad9a8c49187eadc4d480fbd7892a97 Mon Sep 17 00:00:00 2001 From: Dinesht04 Date: Wed, 19 Nov 2025 15:28:58 +0530 Subject: [PATCH 03/25] fix(ui): refactor number input props (min,max) --- ui/src/components/SchemaForm/components/Input.tsx | 9 ++++++--- ui/src/components/SchemaForm/index.tsx | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ui/src/components/SchemaForm/components/Input.tsx b/ui/src/components/SchemaForm/components/Input.tsx index 3a2c0397d..d84d7d55a 100644 --- a/ui/src/components/SchemaForm/components/Input.tsx +++ b/ui/src/components/SchemaForm/components/Input.tsx @@ -50,10 +50,14 @@ const Index: FC = ({ formData, readOnly = false, min = 0, - max = 65355, + max, inputMode = 'text', }) => { const fieldObject = formData[fieldName]; + const numberInputProps = + type === 'number' + ? { min, ...(max != null && max > 0 ? { max } : {}) } + : {}; const handleChange = (evt: React.ChangeEvent) => { const { name, value } = evt.currentTarget; const state = { @@ -75,8 +79,7 @@ const Index: FC = ({ placeholder={placeholder} type={type} value={fieldObject?.value || ''} - min={min} - max={max} + {...numberInputProps} inputMode={inputMode} onChange={handleChange} disabled={readOnly} diff --git a/ui/src/components/SchemaForm/index.tsx b/ui/src/components/SchemaForm/index.tsx index 5bde2fdc8..171b5f675 100644 --- a/ui/src/components/SchemaForm/index.tsx +++ b/ui/src/components/SchemaForm/index.tsx @@ -260,7 +260,7 @@ const SchemaForm: ForwardRefRenderFunction = ( enum: enumValues = [], enumNames = [], max_length = 0, - max = 65355, + max, min = 0, } = properties[key]; const { 'ui:widget': widget = 'input', 'ui:options': uiOpt } = From 9a7eb0f450d31042c8badf080354754a8704e429 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Thu, 20 Nov 2025 17:42:35 +0800 Subject: [PATCH 04/25] fix(service): set default language to "en_US" if invalid language is provided --- internal/service/siteinfo/siteinfo_service.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/internal/service/siteinfo/siteinfo_service.go b/internal/service/siteinfo/siteinfo_service.go index a0f4891c4..92b3e0c71 100644 --- a/internal/service/siteinfo/siteinfo_service.go +++ b/internal/service/siteinfo/siteinfo_service.go @@ -40,7 +40,6 @@ import ( tagcommon "github.com/apache/answer/internal/service/tag_common" "github.com/apache/answer/plugin" "github.com/jinzhu/copier" - "github.com/segmentfault/pacman/errors" "github.com/segmentfault/pacman/log" ) @@ -159,10 +158,9 @@ func (s *SiteInfoService) SaveSiteGeneral(ctx context.Context, req schema.SiteGe } func (s *SiteInfoService) SaveSiteInterface(ctx context.Context, req schema.SiteInterfaceReq) (err error) { - // check language + // If the language is invalid, set it to the default language "en_US" if !translator.CheckLanguageIsValid(req.Language) { - err = errors.BadRequest(reason.LangNotFound) - return + req.Language = "en_US" } content, _ := json.Marshal(req) From 09b6b34b0540b1aa6f344b20df8507f56e6fb406 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Thu, 20 Nov 2025 17:50:57 +0800 Subject: [PATCH 05/25] fix(comment): decode CommentID using DeShortID for consistency --- internal/controller/comment_controller.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/controller/comment_controller.go b/internal/controller/comment_controller.go index 5b807d935..65fbedf04 100644 --- a/internal/controller/comment_controller.go +++ b/internal/controller/comment_controller.go @@ -246,6 +246,7 @@ func (cc *CommentController) GetCommentWithPage(ctx *gin.Context) { return } req.ObjectID = uid.DeShortID(req.ObjectID) + req.CommentID = uid.DeShortID(req.CommentID) req.UserID = middleware.GetLoginUserIDFromContext(ctx) canList, err := cc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{ permission.CommentEdit, From a15dd41550c282a4de44259c69a57dd52eeb0e9c Mon Sep 17 00:00:00 2001 From: ferhat elmas Date: Sat, 22 Nov 2025 12:43:55 +0100 Subject: [PATCH 06/25] refactor(internal): compile regex once while clearing text Regex and Replacer can be reused. No need to recreate for each invocation. Signed-off-by: ferhat elmas --- pkg/htmltext/htmltext.go | 48 ++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/pkg/htmltext/htmltext.go b/pkg/htmltext/htmltext.go index 49049109d..0b84cda49 100644 --- a/pkg/htmltext/htmltext.go +++ b/pkg/htmltext/htmltext.go @@ -34,38 +34,34 @@ import ( "github.com/mozillazg/go-pinyin" ) +var ( + reCode = regexp.MustCompile(`(?ism)<(pre)>.*<\/pre>`) + reCodeReplace = "{code...}" + reLink = regexp.MustCompile(`(?ism)(.*)?<\/a>`) + reLinkReplace = " [$1] " + reSpace = regexp.MustCompile(` +`) + reSpaceReplace = " " + + spaceReplacer = strings.NewReplacer( + "\n", " ", + "\r", " ", + "\t", " ", + ) +) + // ClearText clear HTML, get the clear text -func ClearText(html string) (text string) { - if len(html) == 0 { - text = html - return +func ClearText(html string) string { + if html == "" { + return html } - var ( - re *regexp.Regexp - codeReg = `(?ism)<(pre)>.*<\/pre>` - codeRepl = "{code...}" - linkReg = `(?ism)(.*)?<\/a>` - linkRepl = " [$1] " - spaceReg = ` +` - spaceRepl = " " - ) - re = regexp.MustCompile(codeReg) - html = re.ReplaceAllString(html, codeRepl) + html = reCode.ReplaceAllString(html, reCodeReplace) + html = reLink.ReplaceAllString(html, reLinkReplace) - re = regexp.MustCompile(linkReg) - html = re.ReplaceAllString(html, linkRepl) - - text = strings.NewReplacer( - "\n", " ", - "\r", " ", - "\t", " ", - ).Replace(strip.StripTags(html)) + text := spaceReplacer.Replace(strip.StripTags(html)) // replace multiple spaces to one space - re = regexp.MustCompile(spaceReg) - text = strings.TrimSpace(re.ReplaceAllString(text, spaceRepl)) - return + return strings.TrimSpace(reSpace.ReplaceAllString(text, reSpaceReplace)) } func UrlTitle(title string) (text string) { From ce053ccfa6620cc4c8263ba3b54dfcd988a1e6e9 Mon Sep 17 00:00:00 2001 From: ferhat elmas Date: Tue, 25 Nov 2025 00:34:24 +0100 Subject: [PATCH 07/25] fix: multi byte run boundary for cut long title Signed-off-by: ferhat elmas --- pkg/htmltext/htmltext.go | 12 +++++++++--- pkg/htmltext/htmltext_test.go | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/pkg/htmltext/htmltext.go b/pkg/htmltext/htmltext.go index 0b84cda49..707c20a80 100644 --- a/pkg/htmltext/htmltext.go +++ b/pkg/htmltext/htmltext.go @@ -96,10 +96,16 @@ func convertChinese(content string) string { } func cutLongTitle(title string) string { - if len(title) > 150 { - return title[0:150] + maxBytes := 150 + if len(title) <= maxBytes { + return title } - return title + + truncated := title[:maxBytes] + for len(truncated) > 0 && !utf8.ValidString(truncated) { + truncated = truncated[:len(truncated)-1] + } + return truncated } // FetchExcerpt return the excerpt from the HTML string diff --git a/pkg/htmltext/htmltext_test.go b/pkg/htmltext/htmltext_test.go index d549d8874..63866eb28 100644 --- a/pkg/htmltext/htmltext_test.go +++ b/pkg/htmltext/htmltext_test.go @@ -21,6 +21,7 @@ package htmltext import ( "fmt" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -178,6 +179,27 @@ func TestFetchRangedExcerpt(t *testing.T) { assert.Equal(t, expected, actual) } +func TestCutLongTitle(t *testing.T) { + // Short title, no cutting needed + short := "hello" + assert.Equal(t, short, cutLongTitle(short)) + + // Exactly max bytes, no cutting needed + exact150 := strings.Repeat("a", 150) + assert.Equal(t, 150, len(cutLongTitle(exact150))) + + // Just over max bytes, should be cut + exact151 := strings.Repeat("a", 151) + assert.Equal(t, 150, len(cutLongTitle(exact151))) + + // Multi-byte rune at boundary gets removed properly + asciiPart := strings.Repeat("a", 149) // 149 bytes + multiByteChar := "中" // 3 bytes - will span bytes 149-151 + title := asciiPart + multiByteChar // 152 bytes total + + assert.Equal(t, asciiPart, cutLongTitle(title)) +} + func TestFetchMatchedExcerpt(t *testing.T) { var ( expected, From 0777291e80c804cb836b5059d7e0fad5f2b7fe79 Mon Sep 17 00:00:00 2001 From: ferhat elmas Date: Wed, 26 Nov 2025 01:00:42 +0100 Subject: [PATCH 08/25] fix(ui): null pointer access if get branding fails Signed-off-by: ferhat elmas --- internal/router/ui.go | 6 ++-- internal/router/ui_test.go | 59 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 internal/router/ui_test.go diff --git a/internal/router/ui.go b/internal/router/ui.go index 0b5ee3f96..14f71f5fc 100644 --- a/internal/router/ui.go +++ b/internal/router/ui.go @@ -22,7 +22,6 @@ package router import ( "embed" "fmt" - "github.com/apache/answer/plugin" "io/fs" "net/http" "os" @@ -31,6 +30,7 @@ import ( "github.com/apache/answer/internal/controller" "github.com/apache/answer/internal/service/siteinfo_common" "github.com/apache/answer/pkg/htmltext" + "github.com/apache/answer/plugin" "github.com/apache/answer/ui" "github.com/gin-gonic/gin" "github.com/segmentfault/pacman/log" @@ -111,10 +111,10 @@ func (a *UIRouter) Register(r *gin.Engine, baseURLPath string) { if err != nil { log.Error(err) } - if branding.Favicon != "" { + if branding != nil && branding.Favicon != "" { c.String(http.StatusOK, htmltext.GetPicByUrl(branding.Favicon)) return - } else if branding.SquareIcon != "" { + } else if branding != nil && branding.SquareIcon != "" { c.String(http.StatusOK, htmltext.GetPicByUrl(branding.SquareIcon)) return } else { diff --git a/internal/router/ui_test.go b/internal/router/ui_test.go new file mode 100644 index 000000000..645529338 --- /dev/null +++ b/internal/router/ui_test.go @@ -0,0 +1,59 @@ +/* + * 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 router + +import ( + "errors" + "net/http" + "net/http/httptest" + "testing" + + "github.com/apache/answer/internal/service/mock" + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" +) + +func TestUIRouter_FaviconWithNilBranding(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockSiteInfoService := mock.NewMockSiteInfoCommonService(ctrl) + + // Simulate a database error + mockSiteInfoService.EXPECT(). + GetSiteBranding(gomock.Any()). + Return(nil, errors.New("database connection failed")) + + router := &UIRouter{ + siteInfoService: mockSiteInfoService, + } + + gin.SetMode(gin.TestMode) + r := gin.New() + router.Register(r, "") + + req := httptest.NewRequest(http.MethodGet, "/favicon.ico", nil) + w := httptest.NewRecorder() + + r.ServeHTTP(w, req) + + assert.Equal(t, http.StatusOK, w.Code) +} From bc629db13266dfcd9560da38b39d71a615a1664f Mon Sep 17 00:00:00 2001 From: ferhat elmas Date: Thu, 27 Nov 2025 22:05:14 +0100 Subject: [PATCH 09/25] chore(deps): bump mockgen to 0.6.0 for go1.25 support Signed-off-by: ferhat elmas --- Makefile | 4 ++-- README.md | 2 +- cmd/wire_gen.go | 8 ++++---- docs/docs.go | 32 +++++++++++++++++++++++--------- docs/swagger.json | 32 +++++++++++++++++++++++--------- docs/swagger.yaml | 28 +++++++++++++++++++--------- go.mod | 14 +++++++------- go.sum | 36 ++++++++++++++++++------------------ 8 files changed, 97 insertions(+), 59 deletions(-) diff --git a/Makefile b/Makefile index 6e9679a89..8ab23cce3 100644 --- a/Makefile +++ b/Makefile @@ -23,10 +23,10 @@ universal: generate generate: @$(GO) get github.com/swaggo/swag/cmd/swag@v1.16.3 @$(GO) get github.com/google/wire/cmd/wire@v0.5.0 - @$(GO) get go.uber.org/mock/mockgen@v0.5.0 + @$(GO) get go.uber.org/mock/mockgen@v0.6.0 @$(GO) install github.com/swaggo/swag/cmd/swag@v1.16.3 @$(GO) install github.com/google/wire/cmd/wire@v0.5.0 - @$(GO) install go.uber.org/mock/mockgen@v0.5.0 + @$(GO) install go.uber.org/mock/mockgen@v0.6.0 @$(GO) generate ./... @$(GO) mod tidy diff --git a/README.md b/README.md index 8d201500e..362365496 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ You can also check out the [plugins here](https://answer.apache.org/plugins). - Golang >= 1.23 - Node.js >= 20 - pnpm >= 9 -- [mockgen](https://github.com/uber-go/mock?tab=readme-ov-file#installation) >= 1.6.0 +- [mockgen](https://github.com/uber-go/mock?tab=readme-ov-file#installation) >= 0.6.0 - [wire](https://github.com/google/wire/) >= 0.5.0 ### Build diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index bda555bca..aae1c6af6 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -192,22 +192,22 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, objService := object_info.NewObjService(answerRepo, questionRepo, commentCommonRepo, tagCommonRepo, tagCommonService) notificationQueueService := notice_queue.NewNotificationQueueService() externalNotificationQueueService := notice_queue.NewNewQuestionNotificationQueueService() + reviewRepo := review.NewReviewRepo(dataData) + reviewService := review2.NewReviewService(reviewRepo, objService, userCommon, userRepo, questionRepo, answerRepo, userRoleRelService, externalNotificationQueueService, tagCommonService, questionCommon, notificationQueueService, siteInfoCommonService, commentCommonRepo) + commentService := comment2.NewCommentService(commentRepo, commentCommonRepo, userCommon, objService, voteRepo, emailService, userRepo, notificationQueueService, externalNotificationQueueService, activityQueueService, eventQueueService, reviewService) rolePowerRelRepo := role.NewRolePowerRelRepo(dataData) rolePowerRelService := role2.NewRolePowerRelService(rolePowerRelRepo, userRoleRelService) rankService := rank2.NewRankService(userCommon, userRankRepo, objService, userRoleRelService, rolePowerRelService, configService) limitRepo := limit.NewRateLimitRepo(dataData) rateLimitMiddleware := middleware.NewRateLimitMiddleware(limitRepo) + commentController := controller.NewCommentController(commentService, rankService, captchaService, rateLimitMiddleware) reportRepo := report.NewReportRepo(dataData, uniqueIDRepo) tagService := tag2.NewTagService(tagRepo, tagCommonService, revisionService, followRepo, siteInfoCommonService, activityQueueService) answerActivityRepo := activity.NewAnswerActivityRepo(dataData, activityRepo, userRankRepo, notificationQueueService) answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, configService) externalNotificationService := notification.NewExternalNotificationService(dataData, userNotificationConfigRepo, followRepo, emailService, userRepo, externalNotificationQueueService, userExternalLoginRepo, siteInfoCommonService) - reviewRepo := review.NewReviewRepo(dataData) - reviewService := review2.NewReviewService(reviewRepo, objService, userCommon, userRepo, questionRepo, answerRepo, userRoleRelService, externalNotificationQueueService, tagCommonService, questionCommon, notificationQueueService, siteInfoCommonService, commentCommonRepo) questionService := content.NewQuestionService(activityRepo, questionRepo, answerRepo, tagCommonService, tagService, questionCommon, userCommon, userRepo, userRoleRelService, revisionService, metaCommonService, collectionCommon, answerActivityService, emailService, notificationQueueService, externalNotificationQueueService, activityQueueService, siteInfoCommonService, externalNotificationService, reviewService, configService, eventQueueService, reviewRepo) answerService := content.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService, notificationQueueService, externalNotificationQueueService, activityQueueService, reviewService, eventQueueService) - commentService := comment2.NewCommentService(commentRepo, commentCommonRepo, userCommon, objService, voteRepo, emailService, userRepo, notificationQueueService, externalNotificationQueueService, activityQueueService, eventQueueService, reviewService) - commentController := controller.NewCommentController(commentService, rankService, captchaService, rateLimitMiddleware) reportHandle := report_handle.NewReportHandle(questionService, answerService, commentService) reportService := report2.NewReportService(reportRepo, objService, userCommon, answerRepo, questionRepo, commentCommonRepo, reportHandle, configService, eventQueueService) reportController := controller.NewReportController(reportService, rankService, captchaService) diff --git a/docs/docs.go b/docs/docs.go index 263e6775e..c87313917 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -9780,8 +9780,6 @@ const docTemplate = `{ "schema.QuestionAdd": { "type": "object", "required": [ - "content", - "tags", "title" ], "properties": { @@ -9796,7 +9794,7 @@ const docTemplate = `{ "description": "content", "type": "string", "maxLength": 65535, - "minLength": 6 + "minLength": 0 }, "tags": { "description": "tags", @@ -9817,8 +9815,6 @@ const docTemplate = `{ "type": "object", "required": [ "answer_content", - "content", - "tags", "title" ], "properties": { @@ -9838,7 +9834,7 @@ const docTemplate = `{ "description": "content", "type": "string", "maxLength": 65535, - "minLength": 6 + "minLength": 0 }, "mention_username_list": { "type": "array", @@ -10119,9 +10115,7 @@ const docTemplate = `{ "schema.QuestionUpdate": { "type": "object", "required": [ - "content", "id", - "tags", "title" ], "properties": { @@ -10136,7 +10130,7 @@ const docTemplate = `{ "description": "content", "type": "string", "maxLength": 65535, - "minLength": 6 + "minLength": 0 }, "edit_summary": { "description": "edit summary", @@ -11047,6 +11041,16 @@ const docTemplate = `{ "max_image_size": { "type": "integer" }, + "min_content": { + "type": "integer", + "maximum": 65535, + "minimum": 0 + }, + "min_tags": { + "type": "integer", + "maximum": 5, + "minimum": 0 + }, "recommend_tags": { "type": "array", "items": { @@ -11091,6 +11095,16 @@ const docTemplate = `{ "max_image_size": { "type": "integer" }, + "min_content": { + "type": "integer", + "maximum": 65535, + "minimum": 0 + }, + "min_tags": { + "type": "integer", + "maximum": 5, + "minimum": 0 + }, "recommend_tags": { "type": "array", "items": { diff --git a/docs/swagger.json b/docs/swagger.json index 8cc85e263..9f89cb157 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -9753,8 +9753,6 @@ "schema.QuestionAdd": { "type": "object", "required": [ - "content", - "tags", "title" ], "properties": { @@ -9769,7 +9767,7 @@ "description": "content", "type": "string", "maxLength": 65535, - "minLength": 6 + "minLength": 0 }, "tags": { "description": "tags", @@ -9790,8 +9788,6 @@ "type": "object", "required": [ "answer_content", - "content", - "tags", "title" ], "properties": { @@ -9811,7 +9807,7 @@ "description": "content", "type": "string", "maxLength": 65535, - "minLength": 6 + "minLength": 0 }, "mention_username_list": { "type": "array", @@ -10092,9 +10088,7 @@ "schema.QuestionUpdate": { "type": "object", "required": [ - "content", "id", - "tags", "title" ], "properties": { @@ -10109,7 +10103,7 @@ "description": "content", "type": "string", "maxLength": 65535, - "minLength": 6 + "minLength": 0 }, "edit_summary": { "description": "edit summary", @@ -11020,6 +11014,16 @@ "max_image_size": { "type": "integer" }, + "min_content": { + "type": "integer", + "maximum": 65535, + "minimum": 0 + }, + "min_tags": { + "type": "integer", + "maximum": 5, + "minimum": 0 + }, "recommend_tags": { "type": "array", "items": { @@ -11064,6 +11068,16 @@ "max_image_size": { "type": "integer" }, + "min_content": { + "type": "integer", + "maximum": 65535, + "minimum": 0 + }, + "min_tags": { + "type": "integer", + "maximum": 5, + "minimum": 0 + }, "recommend_tags": { "type": "array", "items": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 9cdf248e1..d2dd076cf 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1589,7 +1589,7 @@ definitions: content: description: content maxLength: 65535 - minLength: 6 + minLength: 0 type: string tags: description: tags @@ -1602,8 +1602,6 @@ definitions: minLength: 6 type: string required: - - content - - tags - title type: object schema.QuestionAddByAnswer: @@ -1620,7 +1618,7 @@ definitions: content: description: content maxLength: 65535 - minLength: 6 + minLength: 0 type: string mention_username_list: items: @@ -1638,8 +1636,6 @@ definitions: type: string required: - answer_content - - content - - tags - title type: object schema.QuestionInfoResp: @@ -1826,7 +1822,7 @@ definitions: content: description: content maxLength: 65535 - minLength: 6 + minLength: 0 type: string edit_summary: description: edit summary @@ -1849,9 +1845,7 @@ definitions: minLength: 6 type: string required: - - content - id - - tags - title type: object schema.QuestionUpdateInviteUser: @@ -2453,6 +2447,14 @@ definitions: type: integer max_image_size: type: integer + min_content: + maximum: 65535 + minimum: 0 + type: integer + min_tags: + maximum: 5 + minimum: 0 + type: integer recommend_tags: items: $ref: '#/definitions/schema.SiteWriteTag' @@ -2482,6 +2484,14 @@ definitions: type: integer max_image_size: type: integer + min_content: + maximum: 65535 + minimum: 0 + type: integer + min_tags: + maximum: 5 + minimum: 0 + type: integer recommend_tags: items: $ref: '#/definitions/schema.SiteWriteTag' diff --git a/go.mod b/go.mod index 417688120..969d9ebbc 100644 --- a/go.mod +++ b/go.mod @@ -56,12 +56,12 @@ require ( github.com/swaggo/swag v1.16.3 github.com/tidwall/gjson v1.17.3 github.com/yuin/goldmark v1.7.4 - go.uber.org/mock v0.5.0 - golang.org/x/crypto v0.36.0 + go.uber.org/mock v0.6.0 + golang.org/x/crypto v0.41.0 golang.org/x/image v0.20.0 - golang.org/x/net v0.38.0 - golang.org/x/term v0.30.0 - golang.org/x/text v0.23.0 + golang.org/x/net v0.43.0 + golang.org/x/term v0.34.0 + golang.org/x/text v0.28.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.33.0 @@ -161,8 +161,8 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.10.0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/tools v0.25.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/tools v0.36.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index b45d881fe..35db004db 100644 --- a/go.sum +++ b/go.sum @@ -654,8 +654,8 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= -go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -685,8 +685,8 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= @@ -703,8 +703,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -731,8 +731,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -743,8 +743,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -779,14 +779,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -795,8 +795,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -820,8 +820,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= -golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From fc2a1d8afeb86602215d831c2767c2a1a56f30a2 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Fri, 28 Nov 2025 10:49:10 +0800 Subject: [PATCH 10/25] fix(answer): update QuestionID handling in answer update process --- internal/controller/answer_controller.go | 1 - internal/schema/answer_schema.go | 1 - internal/service/content/answer_service.go | 19 +++++++++---------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/internal/controller/answer_controller.go b/internal/controller/answer_controller.go index 7c5aca1db..0e43121c5 100644 --- a/internal/controller/answer_controller.go +++ b/internal/controller/answer_controller.go @@ -318,7 +318,6 @@ func (ac *AnswerController) UpdateAnswer(ctx *gin.Context) { handler.HandleResponse(ctx, err, nil) return } - req.QuestionID = uid.DeShortID(req.QuestionID) linkUrlLimitUser := canList[2] isAdmin := middleware.GetUserIsAdminModerator(ctx) if !isAdmin || !linkUrlLimitUser { diff --git a/internal/schema/answer_schema.go b/internal/schema/answer_schema.go index 015e26ac5..9ac4bcad7 100644 --- a/internal/schema/answer_schema.go +++ b/internal/schema/answer_schema.go @@ -78,7 +78,6 @@ type GetAnswerInfoResp struct { type AnswerUpdateReq struct { ID string `json:"id"` - QuestionID string `json:"question_id"` Title string `json:"title"` Content string `validate:"required,notblank,gte=6,lte=65535" json:"content"` EditSummary string `validate:"omitempty" json:"edit_summary"` diff --git a/internal/service/content/answer_service.go b/internal/service/content/answer_service.go index b9d45b522..982bbf88a 100644 --- a/internal/service/content/answer_service.go +++ b/internal/service/content/answer_service.go @@ -346,24 +346,23 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq return "", errors.BadRequest(reason.AnswerCannotUpdate) } - questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, req.QuestionID) + answerInfo, exist, err := as.answerRepo.GetByID(ctx, req.ID) if err != nil { return "", err } if !exist { - return "", errors.BadRequest(reason.QuestionNotFound) + return "", errors.BadRequest(reason.AnswerNotFound) + } + if answerInfo.Status == entity.AnswerStatusDeleted { + return "", errors.BadRequest(reason.AnswerCannotUpdate) } - answerInfo, exist, err := as.answerRepo.GetByID(ctx, req.ID) + questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, answerInfo.QuestionID) if err != nil { return "", err } if !exist { - return "", errors.BadRequest(reason.AnswerNotFound) - } - - if answerInfo.Status == entity.AnswerStatusDeleted { - return "", errors.BadRequest(reason.AnswerCannotUpdate) + return "", errors.BadRequest(reason.QuestionNotFound) } //If the content is the same, ignore it @@ -374,7 +373,7 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq insertData := &entity.Answer{} insertData.ID = req.ID insertData.UserID = answerInfo.UserID - insertData.QuestionID = req.QuestionID + insertData.QuestionID = questionInfo.ID insertData.OriginalText = req.Content insertData.ParsedText = req.HTML insertData.UpdatedAt = time.Now() @@ -403,7 +402,7 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq if err = as.answerRepo.UpdateAnswer(ctx, insertData, []string{"original_text", "parsed_text", "updated_at", "last_edit_user_id"}); err != nil { return "", err } - err = as.questionCommon.UpdatePostTime(ctx, req.QuestionID) + err = as.questionCommon.UpdatePostTime(ctx, questionInfo.ID) if err != nil { return insertData.ID, err } From f723d120d924dcf7e65b969ce18f8111cac40343 Mon Sep 17 00:00:00 2001 From: ferhat elmas Date: Fri, 28 Nov 2025 23:11:57 +0100 Subject: [PATCH 11/25] feat: add golangci-lint into lint target * replace empty interface with any * run fmt via golangci-lint related to #1432 Signed-off-by: ferhat elmas --- .gitignore | 2 +- .golangci.yaml | 30 +++++++++++++++++++ Makefile | 17 +++++++++-- docs/docs.go | 7 ++--- docs/swagger.json | 7 ++--- docs/swagger.yaml | 6 ++-- internal/base/handler/handler.go | 6 ++-- internal/base/handler/response.go | 4 +-- internal/base/pager/pager.go | 2 +- internal/base/pager/pagination.go | 6 ++-- internal/base/server/http_funcmap.go | 6 ++-- internal/base/translator/provider.go | 8 ++--- internal/base/validator/validator.go | 4 +-- internal/install/install_from_env.go | 2 +- internal/migrations/init.go | 10 +++---- internal/migrations/init_data.go | 2 +- internal/migrations/v25.go | 2 +- internal/migrations/v6.go | 2 +- internal/repo/meta/meta_repo.go | 2 +- .../plugin_config/plugin_user_config_repo.go | 2 +- internal/repo/revision/revision_repo.go | 2 +- internal/repo/role/user_role_rel_repo.go | 2 +- internal/repo/search_common/search_repo.go | 26 ++++++++-------- internal/repo/user/user_repo.go | 2 +- internal/schema/question_schema.go | 28 ++++++++--------- internal/schema/revision_schema.go | 2 +- internal/schema/siteinfo_schema.go | 14 ++++----- internal/schema/user_schema.go | 2 +- internal/service/question_common/question.go | 2 +- internal/service/siteinfo/siteinfo_service.go | 2 +- .../siteinfo_common/siteinfo_service.go | 4 +-- pkg/converter/str.go | 2 +- 32 files changed, 125 insertions(+), 90 deletions(-) create mode 100644 .golangci.yaml diff --git a/.gitignore b/.gitignore index 1fc116a74..257ef31d6 100644 --- a/.gitignore +++ b/.gitignore @@ -28,7 +28,7 @@ vendor/ /answer-data/ /answer /new_answer - +build/tools/ dist/ # Lint setup generated file diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 000000000..af00efc3b --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,30 @@ +# 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. + +version: "2" +linters: + default: none + +formatters: + enable: + - gofmt + settings: + gofmt: + simplify: true + rewrite-rules: + - pattern: 'interface{}' + replacement: 'any' diff --git a/Makefile b/Makefile index 8ab23cce3..fd3f044fa 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,15 @@ Revision=$(shell git rev-parse --short HEAD 2>/dev/null || echo "") GO_FLAGS=-ldflags="-X github.com/apache/answer/cmd.Version=$(VERSION) -X 'github.com/apache/answer/cmd.Revision=$(Revision)' -X 'github.com/apache/answer/cmd.Time=`date +%s`' -extldflags -static" GO=$(GO_ENV) "$(shell which go)" +GOLANGCI_VERSION ?= v2.6.2 +TOOLS_BIN := $(shell mkdir -p build/tools && realpath build/tools) + +GOLANGCI = $(TOOLS_BIN)/golangci-lint-$(GOLANGCI_VERSION) +$(GOLANGCI): + rm -f $(TOOLS_BIN)/golangci-lint* + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOLANGCI_VERSION)/install.sh | sh -s -- -b $(TOOLS_BIN) $(GOLANGCI_VERSION) + mv $(TOOLS_BIN)/golangci-lint $(TOOLS_BIN)/golangci-lint-$(GOLANGCI_VERSION) + build: generate @$(GO) build $(GO_FLAGS) -o $(BIN) $(DIR_SRC) @@ -50,8 +59,12 @@ install-ui-packages: ui: @cd ui && pnpm pre-install && pnpm build && cd - -lint: generate +lint: generate $(GOLANGCI) + @bash ./script/check-asf-header.sh + $(GOLANGCI) run + +lint-fix: generate $(GOLANGCI) @bash ./script/check-asf-header.sh - @gofmt -w -l . + $(GOLANGCI) run --fix all: clean build diff --git a/docs/docs.go b/docs/docs.go index c87313917..5e9d5b39d 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -8080,9 +8080,6 @@ const docTemplate = `{ "id": { "type": "string" }, - "question_id": { - "type": "string" - }, "title": { "type": "string" } @@ -10920,7 +10917,7 @@ const docTemplate = `{ }, "theme_config": { "type": "object", - "additionalProperties": true + "additionalProperties": {} } } }, @@ -10935,7 +10932,7 @@ const docTemplate = `{ }, "theme_config": { "type": "object", - "additionalProperties": true + "additionalProperties": {} }, "theme_options": { "type": "array", diff --git a/docs/swagger.json b/docs/swagger.json index 9f89cb157..e0f6378e4 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -8053,9 +8053,6 @@ "id": { "type": "string" }, - "question_id": { - "type": "string" - }, "title": { "type": "string" } @@ -10893,7 +10890,7 @@ }, "theme_config": { "type": "object", - "additionalProperties": true + "additionalProperties": {} } } }, @@ -10908,7 +10905,7 @@ }, "theme_config": { "type": "object", - "additionalProperties": true + "additionalProperties": {} }, "theme_options": { "type": "array", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index d2dd076cf..e0244083b 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -399,8 +399,6 @@ definitions: type: string id: type: string - question_id: - type: string title: type: string required: @@ -2364,7 +2362,7 @@ definitions: maxLength: 255 type: string theme_config: - additionalProperties: true + additionalProperties: {} type: object required: - theme @@ -2376,7 +2374,7 @@ definitions: theme: type: string theme_config: - additionalProperties: true + additionalProperties: {} type: object theme_options: items: diff --git a/internal/base/handler/handler.go b/internal/base/handler/handler.go index 7670feea7..5a4961a3e 100644 --- a/internal/base/handler/handler.go +++ b/internal/base/handler/handler.go @@ -31,7 +31,7 @@ import ( ) // HandleResponse Handle response body -func HandleResponse(ctx *gin.Context, err error, data interface{}) { +func HandleResponse(ctx *gin.Context, err error, data any) { lang := GetLang(ctx) // no error if err == nil { @@ -61,7 +61,7 @@ func HandleResponse(ctx *gin.Context, err error, data interface{}) { } // BindAndCheck bind request and check -func BindAndCheck(ctx *gin.Context, data interface{}) bool { +func BindAndCheck(ctx *gin.Context, data any) bool { lang := GetLang(ctx) ctx.Set(constant.AcceptLanguageFlag, lang) if err := ctx.ShouldBind(data); err != nil { @@ -79,7 +79,7 @@ func BindAndCheck(ctx *gin.Context, data interface{}) bool { } // BindAndCheckReturnErr bind request and check -func BindAndCheckReturnErr(ctx *gin.Context, data interface{}) (errFields []*validator.FormErrorField) { +func BindAndCheckReturnErr(ctx *gin.Context, data any) (errFields []*validator.FormErrorField) { lang := GetLang(ctx) if err := ctx.ShouldBind(data); err != nil { log.Errorf("http_handle BindAndCheck fail, %s", err.Error()) diff --git a/internal/base/handler/response.go b/internal/base/handler/response.go index 827e0b362..51be8a8a1 100644 --- a/internal/base/handler/response.go +++ b/internal/base/handler/response.go @@ -34,7 +34,7 @@ type RespBody struct { // response message Message string `json:"msg"` // response data - Data interface{} `json:"data"` + Data any `json:"data"` } // TrMsg translate the reason cause as a message @@ -63,7 +63,7 @@ func NewRespBodyFromError(e *errors.Error) *RespBody { } // NewRespBodyData new response body with data -func NewRespBodyData(code int, reason string, data interface{}) *RespBody { +func NewRespBodyData(code int, reason string, data any) *RespBody { return &RespBody{ Code: code, Reason: reason, diff --git a/internal/base/pager/pager.go b/internal/base/pager/pager.go index d7a4caa14..b14d99bfa 100644 --- a/internal/base/pager/pager.go +++ b/internal/base/pager/pager.go @@ -27,7 +27,7 @@ import ( ) // Help xorm page helper -func Help(page, pageSize int, rowsSlicePtr interface{}, rowElement interface{}, session *xorm.Session) (total int64, err error) { +func Help(page, pageSize int, rowsSlicePtr any, rowElement any, session *xorm.Session) (total int64, err error) { page, pageSize = ValPageAndPageSize(page, pageSize) sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr)) diff --git a/internal/base/pager/pagination.go b/internal/base/pager/pagination.go index 36849fed5..1b09e1f21 100644 --- a/internal/base/pager/pagination.go +++ b/internal/base/pager/pagination.go @@ -25,8 +25,8 @@ import ( // PageModel page model type PageModel struct { - Count int64 `json:"count"` - List interface{} `json:"list"` + Count int64 `json:"count"` + List any `json:"list"` } // PageCond page condition @@ -36,7 +36,7 @@ type PageCond struct { } // NewPageModel new page model -func NewPageModel(totalRecords int64, records interface{}) *PageModel { +func NewPageModel(totalRecords int64, records any) *PageModel { sliceValue := reflect.Indirect(reflect.ValueOf(records)) if sliceValue.Kind() != reflect.Slice { panic("not a slice") diff --git a/internal/base/server/http_funcmap.go b/internal/base/server/http_funcmap.go index 9d8e98f96..8f6cac5fc 100644 --- a/internal/base/server/http_funcmap.go +++ b/internal/base/server/http_funcmap.go @@ -64,7 +64,7 @@ var funcMap = template.FuncMap{ "formatLinkNofollow": func(data string) template.HTML { return template.HTML(FormatLinkNofollow(data)) }, - "translator": func(la i18n.Language, data string, params ...interface{}) string { + "translator": func(la i18n.Language, data string, params ...any) string { trans := translator.GlobalTrans.Tr(la, data) if len(params) > 0 && len(params)%2 == 0 { @@ -128,8 +128,8 @@ var funcMap = template.FuncMap{ trans = translator.GlobalTrans.Tr(la, "ui.dates.long_date_with_year") return day.Format(timestamp, trans, tz) }, - "wrapComments": func(comments []*schema.GetCommentResp, la i18n.Language, tz string) map[string]interface{} { - return map[string]interface{}{ + "wrapComments": func(comments []*schema.GetCommentResp, la i18n.Language, tz string) map[string]any { + return map[string]any{ "comments": comments, "language": la, "timezone": tz, diff --git a/internal/base/translator/provider.go b/internal/base/translator/provider.go index 9838d185d..47212e84f 100644 --- a/internal/base/translator/provider.go +++ b/internal/base/translator/provider.go @@ -76,14 +76,14 @@ func NewTranslator(c *I18n) (tr i18n.Translator, err error) { // parse the backend translation originalTr := struct { - Backend map[string]map[string]interface{} `yaml:"backend"` - UI map[string]interface{} `yaml:"ui"` - Plugin map[string]interface{} `yaml:"plugin"` + Backend map[string]map[string]any `yaml:"backend"` + UI map[string]any `yaml:"ui"` + Plugin map[string]any `yaml:"plugin"` }{} if err = yaml.Unmarshal(buf, &originalTr); err != nil { return nil, err } - translation := make(map[string]interface{}, 0) + translation := make(map[string]any, 0) for k, v := range originalTr.Backend { translation[k] = v } diff --git a/internal/base/validator/validator.go b/internal/base/validator/validator.go index 70c7be2e9..22761c521 100644 --- a/internal/base/validator/validator.go +++ b/internal/base/validator/validator.go @@ -187,7 +187,7 @@ func GetValidatorByLang(lang i18n.Language) *MyValidator { } // Check / -func (m *MyValidator) Check(value interface{}) (errFields []*FormErrorField, err error) { +func (m *MyValidator) Check(value any) (errFields []*FormErrorField, err error) { defer func() { if len(errFields) == 0 { return @@ -261,7 +261,7 @@ type Checker interface { Check() (errField []*FormErrorField, err error) } -func getObjectTagByFieldName(obj interface{}, fieldName string) (tag string) { +func getObjectTagByFieldName(obj any, fieldName string) (tag string) { defer func() { if err := recover(); err != nil { log.Error(err) diff --git a/internal/install/install_from_env.go b/internal/install/install_from_env.go index a6b668bab..c05d2aaba 100644 --- a/internal/install/install_from_env.go +++ b/internal/install/install_from_env.go @@ -133,7 +133,7 @@ func initBaseInfo(env *Env) (err error) { return requestAPI(req, "POST", "/installation/base-info", InitBaseInfo) } -func requestAPI(req interface{}, method, url string, handlerFunc gin.HandlerFunc) error { +func requestAPI(req any, method, url string, handlerFunc gin.HandlerFunc) error { w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) body, _ := json.Marshal(req) diff --git a/internal/migrations/init.go b/internal/migrations/init.go index 392ecb2c6..184c986b9 100644 --- a/internal/migrations/init.go +++ b/internal/migrations/init.go @@ -208,7 +208,7 @@ func (m *Mentor) initSiteInfoGeneralData() { } func (m *Mentor) initSiteInfoLoginConfig() { - loginConfig := map[string]interface{}{ + loginConfig := map[string]any{ "allow_new_registrations": true, "allow_email_registrations": true, "allow_password_login": true, @@ -223,7 +223,7 @@ func (m *Mentor) initSiteInfoLoginConfig() { } func (m *Mentor) initSiteInfoLegalConfig() { - legalConfig := map[string]interface{}{ + legalConfig := map[string]any{ "external_content_display": m.userData.ExternalContentDisplay, } legalConfigDataBytes, _ := json.Marshal(legalConfig) @@ -244,7 +244,7 @@ func (m *Mentor) initSiteInfoThemeConfig() { } func (m *Mentor) initSiteInfoSEOConfig() { - seoData := map[string]interface{}{ + seoData := map[string]any{ "permalink": constant.PermalinkQuestionID, "robots": defaultSEORobotTxt + m.userData.SiteURL + "/sitemap.xml", } @@ -276,7 +276,7 @@ func (m *Mentor) initSiteInfoUsersConfig() { } func (m *Mentor) initSiteInfoPrivilegeRank() { - privilegeRankData := map[string]interface{}{ + privilegeRankData := map[string]any{ "level": schema.PrivilegeLevel2, } privilegeRankDataBytes, _ := json.Marshal(privilegeRankData) @@ -288,7 +288,7 @@ func (m *Mentor) initSiteInfoPrivilegeRank() { } func (m *Mentor) initSiteInfoWrite() { - writeData := map[string]interface{}{ + writeData := map[string]any{ "min_content": 6, "restrict_answer": true, "min_tags": 1, diff --git a/internal/migrations/init_data.go b/internal/migrations/init_data.go index 96151625d..356a915a7 100644 --- a/internal/migrations/init_data.go +++ b/internal/migrations/init_data.go @@ -43,7 +43,7 @@ Sitemap: ` ) var ( - tables = []interface{}{ + tables = []any{ &entity.Activity{}, &entity.Answer{}, &entity.Collection{}, diff --git a/internal/migrations/v25.go b/internal/migrations/v25.go index 560a852ac..228c2ef26 100644 --- a/internal/migrations/v25.go +++ b/internal/migrations/v25.go @@ -39,7 +39,7 @@ func addFileRecord(ctx context.Context, x *xorm.Engine) error { if err != nil { return fmt.Errorf("get legal config failed: %w", err) } - legalConfig := make(map[string]interface{}) + legalConfig := make(map[string]any) if exist { if err := json.Unmarshal([]byte(legalInfo.Content), &legalConfig); err != nil { return fmt.Errorf("unmarshal legal config failed: %w", err) diff --git a/internal/migrations/v6.go b/internal/migrations/v6.go index 9171ad47a..88fb58497 100644 --- a/internal/migrations/v6.go +++ b/internal/migrations/v6.go @@ -45,7 +45,7 @@ func addNewAnswerNotification(ctx context.Context, x *xorm.Engine) error { } } - m := make(map[string]interface{}) + m := make(map[string]any) _ = json.Unmarshal([]byte(cond.Value), &m) m["new_answer_title"] = "[{{.SiteName}}] {{.DisplayName}} answered your question" m["new_answer_body"] = "{{.QuestionTitle}}

\n\n{{.DisplayName}}:
\n
{{.AnswerSummary}}

\nView it on {{.SiteName}}

\n\nYou are receiving this because you authored the thread. Unsubscribe" diff --git a/internal/repo/meta/meta_repo.go b/internal/repo/meta/meta_repo.go index 767bd04c7..9680fb419 100644 --- a/internal/repo/meta/meta_repo.go +++ b/internal/repo/meta/meta_repo.go @@ -72,7 +72,7 @@ func (mr *metaRepo) UpdateMeta(ctx context.Context, meta *entity.Meta) (err erro // AddOrUpdateMetaByObjectIdAndKey if exist record with same objectID and key, update it. Or create a new one func (mr *metaRepo) AddOrUpdateMetaByObjectIdAndKey(ctx context.Context, objectId, key string, f func(*entity.Meta, bool) (*entity.Meta, error)) error { - _, err := mr.data.DB.Transaction(func(session *xorm.Session) (interface{}, error) { + _, err := mr.data.DB.Transaction(func(session *xorm.Session) (any, error) { session = session.Context(ctx) // 1. acquire meta entity with target object id and key diff --git a/internal/repo/plugin_config/plugin_user_config_repo.go b/internal/repo/plugin_config/plugin_user_config_repo.go index 19d6af5f9..83da8e758 100644 --- a/internal/repo/plugin_config/plugin_user_config_repo.go +++ b/internal/repo/plugin_config/plugin_user_config_repo.go @@ -44,7 +44,7 @@ func NewPluginUserConfigRepo(data *data.Data) plugin_common.PluginUserConfigRepo func (ur *pluginUserConfigRepo) SaveUserPluginConfig(ctx context.Context, userID string, pluginSlugName, configValue string) (err error) { - _, err = ur.data.DB.Transaction(func(session *xorm.Session) (interface{}, error) { + _, err = ur.data.DB.Transaction(func(session *xorm.Session) (any, error) { session = session.Context(ctx) old := &entity.PluginUserConfig{ UserID: userID, diff --git a/internal/repo/revision/revision_repo.go b/internal/repo/revision/revision_repo.go index 09ba1aacd..8b9e08400 100644 --- a/internal/repo/revision/revision_repo.go +++ b/internal/repo/revision/revision_repo.go @@ -64,7 +64,7 @@ func (rr *revisionRepo) AddRevision(ctx context.Context, revision *entity.Revisi if !rr.allowRecord(revision.ObjectType) { return nil } - _, err = rr.data.DB.Transaction(func(session *xorm.Session) (interface{}, error) { + _, err = rr.data.DB.Transaction(func(session *xorm.Session) (any, error) { session = session.Context(ctx) _, err = session.Insert(revision) if err != nil { diff --git a/internal/repo/role/user_role_rel_repo.go b/internal/repo/role/user_role_rel_repo.go index 7bd14ecea..1925339c0 100644 --- a/internal/repo/role/user_role_rel_repo.go +++ b/internal/repo/role/user_role_rel_repo.go @@ -45,7 +45,7 @@ func NewUserRoleRelRepo(data *data.Data) role.UserRoleRelRepo { // SaveUserRoleRel save user role rel func (ur *userRoleRelRepo) SaveUserRoleRel(ctx context.Context, userID string, roleID int) (err error) { - _, err = ur.data.DB.Transaction(func(session *xorm.Session) (interface{}, error) { + _, err = ur.data.DB.Transaction(func(session *xorm.Session) (any, error) { session = session.Context(ctx) item := &entity.UserRoleRel{UserID: userID} exist, err := session.Get(item) diff --git a/internal/repo/search_common/search_repo.go b/internal/repo/search_common/search_repo.go index 314c51878..806517234 100644 --- a/internal/repo/search_common/search_repo.go +++ b/internal/repo/search_common/search_repo.go @@ -107,8 +107,8 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagIDs ub *builder.Builder qfs = qFields afs = aFields - argsQ = []interface{}{} - argsA = []interface{}{} + argsQ = []any{} + argsA = []any{} ) if order == "relevance" { @@ -212,8 +212,8 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagIDs return } - queryArgs := []interface{}{} - countArgs := []interface{}{} + queryArgs := []any{} + countArgs := []any{} queryArgs = append(queryArgs, querySQL) queryArgs = append(queryArgs, argsQ...) @@ -246,7 +246,7 @@ func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, tagID words = filterWords(words) var ( qfs = qFields - args = []interface{}{} + args = []any{} ) if order == "relevance" { if len(words) > 0 { @@ -313,8 +313,8 @@ func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, tagID args = append(args, answers) } - queryArgs := []interface{}{} - countArgs := []interface{}{} + queryArgs := []any{} + countArgs := []any{} countSQL, _, err := builder.MySQL().Select("count(*) total").From(b, "c").ToSQL() if err != nil { @@ -358,7 +358,7 @@ func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, tagIDs var ( afs = aFields - args = []interface{}{} + args = []any{} ) if order == "relevance" { if len(words) > 0 { @@ -409,8 +409,8 @@ func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, tagIDs args = append(args, questionID) } - queryArgs := []interface{}{} - countArgs := []interface{}{} + queryArgs := []any{} + countArgs := []any{} countSQL, _, err := builder.MySQL().Select("count(*) total").From(b, "c").ToSQL() if err != nil { @@ -575,9 +575,9 @@ func (sr *searchRepo) parseResult(ctx context.Context, res []map[string][]byte, return resultList, nil } -func addRelevanceField(searchFields, words, fields []string) (res []string, args []interface{}) { +func addRelevanceField(searchFields, words, fields []string) (res []string, args []any) { relevanceRes := []string{} - args = []interface{}{} + args = []any{} for _, searchField := range searchFields { var ( @@ -585,7 +585,7 @@ func addRelevanceField(searchFields, words, fields []string) (res []string, args replacement = "REPLACE(%s, ?, '')" replaceField = searchField replaced string - argsField = []interface{}{} + argsField = []any{} ) res = fields diff --git a/internal/repo/user/user_repo.go b/internal/repo/user/user_repo.go index a85cd79a1..1533cc5e8 100644 --- a/internal/repo/user/user_repo.go +++ b/internal/repo/user/user_repo.go @@ -51,7 +51,7 @@ func NewUserRepo(data *data.Data) usercommon.UserRepo { // AddUser add user func (ur *userRepo) AddUser(ctx context.Context, user *entity.User) (err error) { - _, err = ur.data.DB.Transaction(func(session *xorm.Session) (interface{}, error) { + _, err = ur.data.DB.Transaction(func(session *xorm.Session) (any, error) { session = session.Context(ctx) userInfo := &entity.User{} exist, err := session.Where("username = ?", user.Username).Get(userInfo) diff --git a/internal/schema/question_schema.go b/internal/schema/question_schema.go index 84b97b830..133208286 100644 --- a/internal/schema/question_schema.go +++ b/internal/schema/question_schema.go @@ -330,24 +330,24 @@ type UserAnswerInfo struct { CreateTime int `json:"create_time"` UpdateTime int `json:"update_time"` QuestionInfo struct { - Title string `json:"title"` - UrlTitle string `json:"url_title"` - Tags []interface{} `json:"tags"` + Title string `json:"title"` + UrlTitle string `json:"url_title"` + Tags []any `json:"tags"` } `json:"question_info"` } type UserQuestionInfo struct { - ID string `json:"question_id"` - Title string `json:"title"` - UrlTitle string `json:"url_title"` - VoteCount int `json:"vote_count"` - Tags []interface{} `json:"tags"` - ViewCount int `json:"view_count"` - AnswerCount int `json:"answer_count"` - CollectionCount int `json:"collection_count"` - CreatedAt int64 `json:"created_at"` - AcceptedAnswerID string `json:"accepted_answer_id"` - Status string `json:"status"` + ID string `json:"question_id"` + Title string `json:"title"` + UrlTitle string `json:"url_title"` + VoteCount int `json:"vote_count"` + Tags []any `json:"tags"` + ViewCount int `json:"view_count"` + AnswerCount int `json:"answer_count"` + CollectionCount int `json:"collection_count"` + CreatedAt int64 `json:"created_at"` + AcceptedAnswerID string `json:"accepted_answer_id"` + Status string `json:"status"` } const ( diff --git a/internal/schema/revision_schema.go b/internal/schema/revision_schema.go index 946d11653..b3ac0aadd 100644 --- a/internal/schema/revision_schema.go +++ b/internal/schema/revision_schema.go @@ -97,7 +97,7 @@ type GetRevisionResp struct { Title string `json:"title"` UrlTitle string `json:"url_title"` Content string `json:"-"` - ContentParsed interface{} `json:"content"` + ContentParsed any `json:"content"` Status int `json:"status"` CreatedAt time.Time `json:"-"` CreatedAtParsed int64 `json:"create_at"` diff --git a/internal/schema/siteinfo_schema.go b/internal/schema/siteinfo_schema.go index 76f66cb07..0e43bb420 100644 --- a/internal/schema/siteinfo_schema.go +++ b/internal/schema/siteinfo_schema.go @@ -178,9 +178,9 @@ type SiteCustomCssHTMLReq struct { // SiteThemeReq site theme config type SiteThemeReq struct { - Theme string `validate:"required,gt=0,lte=255" json:"theme"` - ThemeConfig map[string]interface{} `validate:"omitempty" json:"theme_config"` - ColorScheme string `validate:"omitempty,gt=0,lte=100" json:"color_scheme"` + Theme string `validate:"required,gt=0,lte=255" json:"theme"` + ThemeConfig map[string]any `validate:"omitempty" json:"theme_config"` + ColorScheme string `validate:"omitempty,gt=0,lte=100" json:"color_scheme"` } type SiteSeoReq struct { @@ -213,10 +213,10 @@ type SiteUsersResp SiteUsersReq // SiteThemeResp site theme response type SiteThemeResp struct { - ThemeOptions []*ThemeOption `json:"theme_options"` - Theme string `json:"theme"` - ThemeConfig map[string]interface{} `json:"theme_config"` - ColorScheme string `json:"color_scheme"` + ThemeOptions []*ThemeOption `json:"theme_options"` + Theme string `json:"theme"` + ThemeConfig map[string]any `json:"theme_config"` + ColorScheme string `json:"color_scheme"` } func (s *SiteThemeResp) TrTheme(ctx context.Context) { diff --git a/internal/schema/user_schema.go b/internal/schema/user_schema.go index 7ba8817a8..d209c8f58 100644 --- a/internal/schema/user_schema.go +++ b/internal/schema/user_schema.go @@ -200,7 +200,7 @@ func (r *GetOtherUserInfoByUsernameResp) ConvertFromUserEntityWithLang(ctx conte r.SuspendedUntil = userInfo.SuspendedUntil.Unix() trans := translator.GlobalTrans.Tr(lang, "ui.dates.long_date_with_time") suspendedUntilFormatted := day.Format(userInfo.SuspendedUntil.Unix(), trans, "UTC") - r.StatusMsg = translator.TrWithData(lang, reason.UserStatusSuspendedUntil, map[string]interface{}{ + r.StatusMsg = translator.TrWithData(lang, reason.UserStatusSuspendedUntil, map[string]any{ "SuspendedUntil": suspendedUntilFormatted, }) } diff --git a/internal/service/question_common/question.go b/internal/service/question_common/question.go index feb5626ed..333806445 100644 --- a/internal/service/question_common/question.go +++ b/internal/service/question_common/question.go @@ -622,7 +622,7 @@ func (qs *QuestionCommon) SitemapCron(ctx context.Context) { } } -func (qs *QuestionCommon) SetCache(ctx context.Context, cachekey string, info interface{}) error { +func (qs *QuestionCommon) SetCache(ctx context.Context, cachekey string, info any) error { infoStr, err := json.Marshal(info) if err != nil { return errors.InternalServer(reason.UnknownError).WithError(err).WithStack() diff --git a/internal/service/siteinfo/siteinfo_service.go b/internal/service/siteinfo/siteinfo_service.go index 92b3e0c71..cf43d68d5 100644 --- a/internal/service/siteinfo/siteinfo_service.go +++ b/internal/service/siteinfo/siteinfo_service.go @@ -183,7 +183,7 @@ func (s *SiteInfoService) SaveSiteBranding(ctx context.Context, req *schema.Site } // SaveSiteWrite save site configuration about write -func (s *SiteInfoService) SaveSiteWrite(ctx context.Context, req *schema.SiteWriteReq) (resp interface{}, err error) { +func (s *SiteInfoService) SaveSiteWrite(ctx context.Context, req *schema.SiteWriteReq) (resp any, err error) { recommendTags, reservedTags := make([]string, 0), make([]string, 0) recommendTagMapping, reservedTagMapping := make(map[string]bool), make(map[string]bool) for _, tag := range req.ReservedTags { diff --git a/internal/service/siteinfo_common/siteinfo_service.go b/internal/service/siteinfo_common/siteinfo_service.go index ef4869cc4..fda117229 100644 --- a/internal/service/siteinfo_common/siteinfo_service.go +++ b/internal/service/siteinfo_common/siteinfo_service.go @@ -56,7 +56,7 @@ type SiteInfoCommonService interface { GetSiteCustomCssHTML(ctx context.Context) (resp *schema.SiteCustomCssHTMLResp, err error) GetSiteTheme(ctx context.Context) (resp *schema.SiteThemeResp, err error) GetSiteSeo(ctx context.Context) (resp *schema.SiteSeoResp, err error) - GetSiteInfoByType(ctx context.Context, siteType string, resp interface{}) (err error) + GetSiteInfoByType(ctx context.Context, siteType string, resp any) (err error) IsBrandingFileUsed(ctx context.Context, filePath string) bool } @@ -224,7 +224,7 @@ func (s *siteInfoCommonService) EnableShortID(ctx context.Context) (enabled bool return siteSeo.IsShortLink() } -func (s *siteInfoCommonService) GetSiteInfoByType(ctx context.Context, siteType string, resp interface{}) (err error) { +func (s *siteInfoCommonService) GetSiteInfoByType(ctx context.Context, siteType string, resp any) (err error) { siteInfo, exist, err := s.siteInfoRepo.GetByType(ctx, siteType) if err != nil { return err diff --git a/pkg/converter/str.go b/pkg/converter/str.go index 40c147fdc..5164609ca 100644 --- a/pkg/converter/str.go +++ b/pkg/converter/str.go @@ -47,7 +47,7 @@ func IntToString(data int64) string { // InterfaceToString converts data to string // It will be used in template render -func InterfaceToString(data interface{}) string { +func InterfaceToString(data any) string { switch t := data.(type) { case int: i := data.(int) From 9540ef60050fb6e2598d8d72ab23514f6e6d4f93 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Mon, 1 Dec 2025 11:30:42 +0800 Subject: [PATCH 12/25] refactor(goimports): add goimports to golangci-lint configuration #1432 --- .golangci.yaml | 1 + internal/base/handler/handler.go | 3 ++- internal/base/middleware/accept_language.go | 3 ++- internal/base/middleware/rate_limit.go | 1 + internal/cli/config.go | 1 + internal/cli/i18n.go | 7 ++++--- internal/controller/template_render/comment.go | 1 + internal/controller/user_plugin_controller.go | 3 ++- internal/entity/badge_entity.go | 3 ++- internal/entity/config_entity.go | 1 + internal/migrations/v1.go | 1 + internal/migrations/v13.go | 1 + internal/migrations/v14.go | 1 + internal/migrations/v15.go | 1 + internal/migrations/v16.go | 1 + internal/migrations/v17.go | 1 + internal/migrations/v18.go | 1 + internal/migrations/v19.go | 1 + internal/migrations/v2.go | 1 + internal/migrations/v21.go | 1 + internal/migrations/v22.go | 1 + internal/migrations/v24.go | 1 + internal/repo/activity/answer_repo.go | 3 ++- internal/repo/activity/user_active_repo.go | 1 + internal/repo/activity_common/vote.go | 1 + internal/repo/auth/auth.go | 1 + internal/repo/badge/badge_event_rule.go | 3 ++- internal/repo/badge/badge_repo.go | 1 + internal/repo/badge_award/badge_award_repo.go | 1 + internal/repo/badge_group/badge_group_repo.go | 1 + internal/repo/collection/collection_repo.go | 1 + internal/repo/export/email_repo.go | 3 ++- internal/repo/limit/limit.go | 3 ++- internal/repo/meta/meta_repo.go | 2 +- internal/repo/plugin_config/plugin_user_config_repo.go | 1 + internal/repo/search_sync/search_sync.go | 1 + .../user_notification_config_repo.go | 1 + internal/schema/email_template.go | 1 + internal/schema/notification_schema.go | 3 ++- internal/schema/user_notification_schema.go | 1 + internal/service/activity/activity.go | 2 +- internal/service/activity/answer_activity_service.go | 1 + internal/service/badge/badge_award_service.go | 1 + internal/service/badge/badge_event_handler.go | 1 + internal/service/badge/badge_group_service.go | 1 + internal/service/badge/badge_service.go | 3 ++- internal/service/content/question_hottest_service.go | 5 +++-- internal/service/content/vote_service.go | 3 ++- internal/service/export/email_service.go | 3 ++- internal/service/meta/meta_service.go | 3 ++- internal/service/notification/notification_service.go | 1 + internal/service/permission/answer_permission.go | 1 + internal/service/permission/question_permission.go | 1 + internal/service/provider.go | 2 +- internal/service/report/report_service.go | 1 + internal/service/search_parser/search_parser.go | 3 ++- .../user_notification_config_service.go | 1 + pkg/converter/str.go | 3 ++- pkg/day/day_test.go | 3 ++- pkg/gravatar/gravatar_test.go | 3 ++- 60 files changed, 82 insertions(+), 25 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index af00efc3b..263f63f70 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -22,6 +22,7 @@ linters: formatters: enable: - gofmt + - goimports settings: gofmt: simplify: true diff --git a/internal/base/handler/handler.go b/internal/base/handler/handler.go index 5a4961a3e..b545b5e01 100644 --- a/internal/base/handler/handler.go +++ b/internal/base/handler/handler.go @@ -21,13 +21,14 @@ package handler import ( "errors" + "net/http" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/reason" "github.com/apache/answer/internal/base/validator" "github.com/gin-gonic/gin" myErrors "github.com/segmentfault/pacman/errors" "github.com/segmentfault/pacman/log" - "net/http" ) // HandleResponse Handle response body diff --git a/internal/base/middleware/accept_language.go b/internal/base/middleware/accept_language.go index 7a8ee391a..ca8a1f903 100644 --- a/internal/base/middleware/accept_language.go +++ b/internal/base/middleware/accept_language.go @@ -20,13 +20,14 @@ package middleware import ( + "strings" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/handler" "github.com/apache/answer/internal/base/translator" "github.com/gin-gonic/gin" "github.com/segmentfault/pacman/i18n" "golang.org/x/text/language" - "strings" ) // ExtractAndSetAcceptLanguage extract accept language from header and set to context diff --git a/internal/base/middleware/rate_limit.go b/internal/base/middleware/rate_limit.go index 29b961757..d376a6d50 100644 --- a/internal/base/middleware/rate_limit.go +++ b/internal/base/middleware/rate_limit.go @@ -22,6 +22,7 @@ package middleware import ( "encoding/json" "fmt" + "github.com/apache/answer/internal/base/handler" "github.com/apache/answer/internal/base/reason" "github.com/apache/answer/internal/repo/limit" diff --git a/internal/cli/config.go b/internal/cli/config.go index 93cb8eab2..ecb62a13c 100644 --- a/internal/cli/config.go +++ b/internal/cli/config.go @@ -23,6 +23,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/entity" diff --git a/internal/cli/i18n.go b/internal/cli/i18n.go index faef0f28a..819ebd753 100644 --- a/internal/cli/i18n.go +++ b/internal/cli/i18n.go @@ -21,13 +21,14 @@ package cli import ( "fmt" + "os" + "path/filepath" + "strings" + "github.com/apache/answer/i18n" "github.com/apache/answer/pkg/dir" "github.com/apache/answer/pkg/writer" "gopkg.in/yaml.v3" - "os" - "path/filepath" - "strings" ) type YamlPluginContent struct { diff --git a/internal/controller/template_render/comment.go b/internal/controller/template_render/comment.go index 67efd2129..2862ad8dd 100644 --- a/internal/controller/template_render/comment.go +++ b/internal/controller/template_render/comment.go @@ -21,6 +21,7 @@ package templaterender import ( "context" + "github.com/apache/answer/internal/base/pager" "github.com/apache/answer/internal/schema" ) diff --git a/internal/controller/user_plugin_controller.go b/internal/controller/user_plugin_controller.go index 310215253..1c4c041c5 100644 --- a/internal/controller/user_plugin_controller.go +++ b/internal/controller/user_plugin_controller.go @@ -21,10 +21,11 @@ package controller import ( "encoding/json" + "net/http" + "github.com/apache/answer/internal/base/middleware" "github.com/apache/answer/internal/base/reason" "github.com/segmentfault/pacman/errors" - "net/http" "github.com/apache/answer/internal/base/handler" "github.com/apache/answer/internal/schema" diff --git a/internal/entity/badge_entity.go b/internal/entity/badge_entity.go index a370e2750..367bb7456 100644 --- a/internal/entity/badge_entity.go +++ b/internal/entity/badge_entity.go @@ -20,8 +20,9 @@ package entity import ( - "github.com/tidwall/gjson" "time" + + "github.com/tidwall/gjson" ) type BadgeLevel int diff --git a/internal/entity/config_entity.go b/internal/entity/config_entity.go index 95a02be48..d39af7b2d 100644 --- a/internal/entity/config_entity.go +++ b/internal/entity/config_entity.go @@ -21,6 +21,7 @@ package entity import ( "encoding/json" + "github.com/segmentfault/pacman/log" "github.com/apache/answer/pkg/converter" diff --git a/internal/migrations/v1.go b/internal/migrations/v1.go index c5e731a0e..688732fa7 100644 --- a/internal/migrations/v1.go +++ b/internal/migrations/v1.go @@ -21,6 +21,7 @@ package migrations import ( "context" + "xorm.io/xorm" ) diff --git a/internal/migrations/v13.go b/internal/migrations/v13.go index 30bfbb542..57d248482 100644 --- a/internal/migrations/v13.go +++ b/internal/migrations/v13.go @@ -24,6 +24,7 @@ import ( "encoding/json" "fmt" "time" + "xorm.io/builder" "github.com/apache/answer/internal/base/constant" diff --git a/internal/migrations/v14.go b/internal/migrations/v14.go index ee3a3d0d6..5e125c98e 100644 --- a/internal/migrations/v14.go +++ b/internal/migrations/v14.go @@ -22,6 +22,7 @@ package migrations import ( "context" "time" + "xorm.io/xorm/schemas" "xorm.io/xorm" diff --git a/internal/migrations/v15.go b/internal/migrations/v15.go index 5195c105a..5858d0097 100644 --- a/internal/migrations/v15.go +++ b/internal/migrations/v15.go @@ -21,6 +21,7 @@ package migrations import ( "context" + "github.com/apache/answer/internal/entity" "xorm.io/xorm" ) diff --git a/internal/migrations/v16.go b/internal/migrations/v16.go index 11643600c..11ae36843 100644 --- a/internal/migrations/v16.go +++ b/internal/migrations/v16.go @@ -21,6 +21,7 @@ package migrations import ( "context" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/entity" "github.com/segmentfault/pacman/log" diff --git a/internal/migrations/v17.go b/internal/migrations/v17.go index 655e547a2..3fa2c7b31 100644 --- a/internal/migrations/v17.go +++ b/internal/migrations/v17.go @@ -22,6 +22,7 @@ package migrations import ( "context" "fmt" + "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/service/permission" "github.com/segmentfault/pacman/log" diff --git a/internal/migrations/v18.go b/internal/migrations/v18.go index 89db524f5..7178c704e 100644 --- a/internal/migrations/v18.go +++ b/internal/migrations/v18.go @@ -23,6 +23,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/schema" diff --git a/internal/migrations/v19.go b/internal/migrations/v19.go index b45d374bb..b50c89f14 100644 --- a/internal/migrations/v19.go +++ b/internal/migrations/v19.go @@ -21,6 +21,7 @@ package migrations import ( "context" + "github.com/apache/answer/internal/entity" "xorm.io/xorm" ) diff --git a/internal/migrations/v2.go b/internal/migrations/v2.go index 4e17597dc..601ff98b2 100644 --- a/internal/migrations/v2.go +++ b/internal/migrations/v2.go @@ -21,6 +21,7 @@ package migrations import ( "context" + "xorm.io/xorm" ) diff --git a/internal/migrations/v21.go b/internal/migrations/v21.go index 880852f8e..de38bffbd 100644 --- a/internal/migrations/v21.go +++ b/internal/migrations/v21.go @@ -21,6 +21,7 @@ package migrations import ( "context" + "xorm.io/xorm" ) diff --git a/internal/migrations/v22.go b/internal/migrations/v22.go index 14292a1e7..e7177deae 100644 --- a/internal/migrations/v22.go +++ b/internal/migrations/v22.go @@ -22,6 +22,7 @@ package migrations import ( "context" "fmt" + "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/repo/unique" diff --git a/internal/migrations/v24.go b/internal/migrations/v24.go index 19358af45..a488679f6 100644 --- a/internal/migrations/v24.go +++ b/internal/migrations/v24.go @@ -23,6 +23,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/schema" diff --git a/internal/repo/activity/answer_repo.go b/internal/repo/activity/answer_repo.go index db6e3bde4..4aca874a7 100644 --- a/internal/repo/activity/answer_repo.go +++ b/internal/repo/activity/answer_repo.go @@ -22,8 +22,9 @@ package activity import ( "context" "fmt" - "github.com/segmentfault/pacman/log" "time" + + "github.com/segmentfault/pacman/log" "xorm.io/builder" "github.com/apache/answer/internal/base/constant" diff --git a/internal/repo/activity/user_active_repo.go b/internal/repo/activity/user_active_repo.go index 2452bcf83..68dfec7d7 100644 --- a/internal/repo/activity/user_active_repo.go +++ b/internal/repo/activity/user_active_repo.go @@ -22,6 +22,7 @@ package activity import ( "context" "fmt" + "xorm.io/builder" "github.com/apache/answer/internal/base/data" diff --git a/internal/repo/activity_common/vote.go b/internal/repo/activity_common/vote.go index cb7d23d00..506578424 100644 --- a/internal/repo/activity_common/vote.go +++ b/internal/repo/activity_common/vote.go @@ -21,6 +21,7 @@ package activity_common import ( "context" + "github.com/apache/answer/pkg/uid" "github.com/apache/answer/internal/base/data" diff --git a/internal/repo/auth/auth.go b/internal/repo/auth/auth.go index a1e358f9a..597352b23 100644 --- a/internal/repo/auth/auth.go +++ b/internal/repo/auth/auth.go @@ -22,6 +22,7 @@ package auth import ( "context" "encoding/json" + "github.com/apache/answer/internal/service/auth" "github.com/apache/answer/internal/base/constant" diff --git a/internal/repo/badge/badge_event_rule.go b/internal/repo/badge/badge_event_rule.go index 8c4656db3..786d988ac 100644 --- a/internal/repo/badge/badge_event_rule.go +++ b/internal/repo/badge/badge_event_rule.go @@ -21,6 +21,8 @@ package badge import ( "context" + "strconv" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/base/reason" @@ -29,7 +31,6 @@ import ( "github.com/apache/answer/internal/service/badge" "github.com/segmentfault/pacman/errors" "github.com/segmentfault/pacman/log" - "strconv" ) // eventRuleRepo event rule repo diff --git a/internal/repo/badge/badge_repo.go b/internal/repo/badge/badge_repo.go index 257caef81..baff45d8a 100644 --- a/internal/repo/badge/badge_repo.go +++ b/internal/repo/badge/badge_repo.go @@ -21,6 +21,7 @@ package badge import ( "context" + "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/base/pager" "github.com/apache/answer/internal/base/reason" diff --git a/internal/repo/badge_award/badge_award_repo.go b/internal/repo/badge_award/badge_award_repo.go index eda5d80c2..11429e570 100644 --- a/internal/repo/badge_award/badge_award_repo.go +++ b/internal/repo/badge_award/badge_award_repo.go @@ -22,6 +22,7 @@ package badge_award import ( "context" "fmt" + "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/base/pager" "github.com/apache/answer/internal/base/reason" diff --git a/internal/repo/badge_group/badge_group_repo.go b/internal/repo/badge_group/badge_group_repo.go index 839ba4691..8f1111a48 100644 --- a/internal/repo/badge_group/badge_group_repo.go +++ b/internal/repo/badge_group/badge_group_repo.go @@ -21,6 +21,7 @@ package badge_group import ( "context" + "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/service/badge" diff --git a/internal/repo/collection/collection_repo.go b/internal/repo/collection/collection_repo.go index a3faacdb5..f30692c97 100644 --- a/internal/repo/collection/collection_repo.go +++ b/internal/repo/collection/collection_repo.go @@ -21,6 +21,7 @@ package collection import ( "context" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/base/handler" diff --git a/internal/repo/export/email_repo.go b/internal/repo/export/email_repo.go index 1f8e1ce83..a3e619712 100644 --- a/internal/repo/export/email_repo.go +++ b/internal/repo/export/email_repo.go @@ -21,9 +21,10 @@ package export import ( "context" + "time" + "github.com/apache/answer/internal/base/constant" "github.com/tidwall/gjson" - "time" "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/base/reason" diff --git a/internal/repo/limit/limit.go b/internal/repo/limit/limit.go index 4868accd5..524ad12bc 100644 --- a/internal/repo/limit/limit.go +++ b/internal/repo/limit/limit.go @@ -22,11 +22,12 @@ package limit import ( "context" "fmt" + "time" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/base/reason" "github.com/segmentfault/pacman/errors" - "time" ) // LimitRepo auth repository diff --git a/internal/repo/meta/meta_repo.go b/internal/repo/meta/meta_repo.go index 9680fb419..fecd7bd5d 100644 --- a/internal/repo/meta/meta_repo.go +++ b/internal/repo/meta/meta_repo.go @@ -25,7 +25,7 @@ import ( "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/base/reason" "github.com/apache/answer/internal/entity" - "github.com/apache/answer/internal/service/meta_common" + metacommon "github.com/apache/answer/internal/service/meta_common" "github.com/segmentfault/pacman/errors" "xorm.io/builder" "xorm.io/xorm" diff --git a/internal/repo/plugin_config/plugin_user_config_repo.go b/internal/repo/plugin_config/plugin_user_config_repo.go index 83da8e758..d14442a56 100644 --- a/internal/repo/plugin_config/plugin_user_config_repo.go +++ b/internal/repo/plugin_config/plugin_user_config_repo.go @@ -21,6 +21,7 @@ package plugin_config import ( "context" + "github.com/apache/answer/internal/base/pager" "xorm.io/xorm" diff --git a/internal/repo/search_sync/search_sync.go b/internal/repo/search_sync/search_sync.go index 5c0adc0f9..889ffe5be 100644 --- a/internal/repo/search_sync/search_sync.go +++ b/internal/repo/search_sync/search_sync.go @@ -21,6 +21,7 @@ package search_sync import ( "context" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/entity" diff --git a/internal/repo/user_notification_config/user_notification_config_repo.go b/internal/repo/user_notification_config/user_notification_config_repo.go index 8ea2b065b..0e761514b 100644 --- a/internal/repo/user_notification_config/user_notification_config_repo.go +++ b/internal/repo/user_notification_config/user_notification_config_repo.go @@ -21,6 +21,7 @@ package user_notification_config import ( "context" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/base/reason" diff --git a/internal/schema/email_template.go b/internal/schema/email_template.go index 1fcdfbce3..d7e4b929a 100644 --- a/internal/schema/email_template.go +++ b/internal/schema/email_template.go @@ -21,6 +21,7 @@ package schema import ( "encoding/json" + "github.com/apache/answer/internal/base/constant" ) diff --git a/internal/schema/notification_schema.go b/internal/schema/notification_schema.go index a68328ace..e5d60615e 100644 --- a/internal/schema/notification_schema.go +++ b/internal/schema/notification_schema.go @@ -21,8 +21,9 @@ package schema import ( "encoding/json" - "github.com/apache/answer/internal/entity" "sort" + + "github.com/apache/answer/internal/entity" ) const ( diff --git a/internal/schema/user_notification_schema.go b/internal/schema/user_notification_schema.go index eca97e81c..60cc4a27b 100644 --- a/internal/schema/user_notification_schema.go +++ b/internal/schema/user_notification_schema.go @@ -21,6 +21,7 @@ package schema import ( "encoding/json" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/entity" ) diff --git a/internal/service/activity/activity.go b/internal/service/activity/activity.go index 2d384f34c..061d84493 100644 --- a/internal/service/activity/activity.go +++ b/internal/service/activity/activity.go @@ -26,7 +26,7 @@ import ( "strings" "github.com/apache/answer/internal/service/activity_common" - "github.com/apache/answer/internal/service/meta_common" + metacommon "github.com/apache/answer/internal/service/meta_common" "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/handler" diff --git a/internal/service/activity/answer_activity_service.go b/internal/service/activity/answer_activity_service.go index 169e7eb39..48b5f3ef9 100644 --- a/internal/service/activity/answer_activity_service.go +++ b/internal/service/activity/answer_activity_service.go @@ -21,6 +21,7 @@ package activity import ( "context" + "github.com/apache/answer/internal/schema" "github.com/apache/answer/internal/service/activity_type" "github.com/apache/answer/internal/service/config" diff --git a/internal/service/badge/badge_award_service.go b/internal/service/badge/badge_award_service.go index 397a7471a..982c1d1a4 100644 --- a/internal/service/badge/badge_award_service.go +++ b/internal/service/badge/badge_award_service.go @@ -21,6 +21,7 @@ package badge import ( "context" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/handler" "github.com/apache/answer/internal/base/reason" diff --git a/internal/service/badge/badge_event_handler.go b/internal/service/badge/badge_event_handler.go index 219822947..cc161f6ad 100644 --- a/internal/service/badge/badge_event_handler.go +++ b/internal/service/badge/badge_event_handler.go @@ -21,6 +21,7 @@ package badge import ( "context" + "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/schema" diff --git a/internal/service/badge/badge_group_service.go b/internal/service/badge/badge_group_service.go index e0dab6e89..7c220a0be 100644 --- a/internal/service/badge/badge_group_service.go +++ b/internal/service/badge/badge_group_service.go @@ -21,6 +21,7 @@ package badge import ( "context" + "github.com/apache/answer/internal/entity" ) diff --git a/internal/service/badge/badge_service.go b/internal/service/badge/badge_service.go index 7bc9ffe21..03b8a8774 100644 --- a/internal/service/badge/badge_service.go +++ b/internal/service/badge/badge_service.go @@ -21,6 +21,8 @@ package badge import ( "context" + "strings" + "github.com/apache/answer/internal/base/handler" "github.com/apache/answer/internal/base/reason" "github.com/apache/answer/internal/base/translator" @@ -32,7 +34,6 @@ import ( "github.com/gin-gonic/gin" "github.com/segmentfault/pacman/errors" "github.com/segmentfault/pacman/log" - "strings" ) type BadgeRepo interface { diff --git a/internal/service/content/question_hottest_service.go b/internal/service/content/question_hottest_service.go index a33b155fb..085b36709 100644 --- a/internal/service/content/question_hottest_service.go +++ b/internal/service/content/question_hottest_service.go @@ -21,11 +21,12 @@ package content import ( "context" + "math" + "time" + "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/schema" "github.com/segmentfault/pacman/log" - "math" - "time" ) func (q *QuestionService) RefreshHottestCron(ctx context.Context) { diff --git a/internal/service/content/vote_service.go b/internal/service/content/vote_service.go index ff3ee5974..92f0c9962 100644 --- a/internal/service/content/vote_service.go +++ b/internal/service/content/vote_service.go @@ -22,9 +22,10 @@ package content import ( "context" "fmt" - "github.com/apache/answer/internal/service/event_queue" "strings" + "github.com/apache/answer/internal/service/event_queue" + "github.com/apache/answer/internal/service/activity_common" "github.com/apache/answer/internal/base/constant" diff --git a/internal/service/export/email_service.go b/internal/service/export/email_service.go index b00ee093b..ddf31b348 100644 --- a/internal/service/export/email_service.go +++ b/internal/service/export/email_service.go @@ -23,12 +23,13 @@ import ( "crypto/tls" "encoding/json" "fmt" - "github.com/apache/answer/pkg/display" "mime" "os" "strings" "time" + "github.com/apache/answer/pkg/display" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/handler" "github.com/apache/answer/internal/base/reason" diff --git a/internal/service/meta/meta_service.go b/internal/service/meta/meta_service.go index 9e4f07410..4b3104197 100644 --- a/internal/service/meta/meta_service.go +++ b/internal/service/meta/meta_service.go @@ -23,10 +23,11 @@ import ( "context" "encoding/json" "errors" - "github.com/apache/answer/internal/service/event_queue" "strconv" "strings" + "github.com/apache/answer/internal/service/event_queue" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/handler" "github.com/apache/answer/internal/base/reason" diff --git a/internal/service/notification/notification_service.go b/internal/service/notification/notification_service.go index 598212aa1..09d871351 100644 --- a/internal/service/notification/notification_service.go +++ b/internal/service/notification/notification_service.go @@ -23,6 +23,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/data" "github.com/apache/answer/internal/base/handler" diff --git a/internal/service/permission/answer_permission.go b/internal/service/permission/answer_permission.go index 4eb563a5a..340fca8db 100644 --- a/internal/service/permission/answer_permission.go +++ b/internal/service/permission/answer_permission.go @@ -21,6 +21,7 @@ package permission import ( "context" + "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/base/handler" diff --git a/internal/service/permission/question_permission.go b/internal/service/permission/question_permission.go index b6750beae..eca0a58f2 100644 --- a/internal/service/permission/question_permission.go +++ b/internal/service/permission/question_permission.go @@ -21,6 +21,7 @@ package permission import ( "context" + "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/base/handler" diff --git a/internal/service/provider.go b/internal/service/provider.go index 4b1b64276..65535f41b 100644 --- a/internal/service/provider.go +++ b/internal/service/provider.go @@ -40,7 +40,7 @@ import ( "github.com/apache/answer/internal/service/follow" "github.com/apache/answer/internal/service/importer" "github.com/apache/answer/internal/service/meta" - "github.com/apache/answer/internal/service/meta_common" + metacommon "github.com/apache/answer/internal/service/meta_common" "github.com/apache/answer/internal/service/notice_queue" "github.com/apache/answer/internal/service/notification" notficationcommon "github.com/apache/answer/internal/service/notification_common" diff --git a/internal/service/report/report_service.go b/internal/service/report/report_service.go index 7dcc1d689..d32ccdabf 100644 --- a/internal/service/report/report_service.go +++ b/internal/service/report/report_service.go @@ -21,6 +21,7 @@ package report import ( "encoding/json" + "github.com/apache/answer/internal/service/event_queue" "github.com/apache/answer/internal/base/constant" diff --git a/internal/service/search_parser/search_parser.go b/internal/service/search_parser/search_parser.go index e87efaf6f..3e6182e15 100644 --- a/internal/service/search_parser/search_parser.go +++ b/internal/service/search_parser/search_parser.go @@ -22,10 +22,11 @@ package search_parser import ( "context" "fmt" - "github.com/apache/answer/internal/base/constant" "regexp" "strings" + "github.com/apache/answer/internal/base/constant" + "github.com/apache/answer/internal/schema" "github.com/apache/answer/internal/service/tag_common" usercommon "github.com/apache/answer/internal/service/user_common" diff --git a/internal/service/user_notification_config/user_notification_config_service.go b/internal/service/user_notification_config/user_notification_config_service.go index 7c54df0aa..01da3ee2f 100644 --- a/internal/service/user_notification_config/user_notification_config_service.go +++ b/internal/service/user_notification_config/user_notification_config_service.go @@ -21,6 +21,7 @@ package user_notification_config import ( "context" + "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/schema" diff --git a/pkg/converter/str.go b/pkg/converter/str.go index 5164609ca..8553975be 100644 --- a/pkg/converter/str.go +++ b/pkg/converter/str.go @@ -21,8 +21,9 @@ package converter import ( "fmt" - "github.com/segmentfault/pacman/log" "strconv" + + "github.com/segmentfault/pacman/log" ) func StringToInt64(str string) int64 { diff --git a/pkg/day/day_test.go b/pkg/day/day_test.go index 73e49aca3..4f945d88f 100644 --- a/pkg/day/day_test.go +++ b/pkg/day/day_test.go @@ -20,9 +20,10 @@ package day import ( - "github.com/stretchr/testify/assert" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestFormat(t *testing.T) { diff --git a/pkg/gravatar/gravatar_test.go b/pkg/gravatar/gravatar_test.go index bf504e68f..b88a69649 100644 --- a/pkg/gravatar/gravatar_test.go +++ b/pkg/gravatar/gravatar_test.go @@ -20,9 +20,10 @@ package gravatar import ( - "github.com/apache/answer/internal/base/constant" "testing" + "github.com/apache/answer/internal/base/constant" + "github.com/stretchr/testify/assert" ) From 5e705a124b3ae2d927f8084e545c3809ae70f4a8 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Mon, 1 Dec 2025 12:23:50 +0800 Subject: [PATCH 13/25] refactor(lint): improve error handling and code consistency across multiple files --- .golangci.yaml | 13 ++++- cmd/wire.go | 3 +- internal/base/conf/conf.go | 4 +- internal/base/constant/ctx_flag.go | 7 +++ internal/base/data/data.go | 2 +- internal/base/handler/lang.go | 2 +- internal/base/handler/short_id.go | 2 +- internal/base/server/http_funcmap.go | 9 ++-- internal/base/validator/validator.go | 2 +- internal/cli/build.go | 52 ------------------- internal/cli/config.go | 6 ++- internal/cli/dump.go | 4 +- internal/cli/install_check.go | 8 ++- internal/cli/reset_password.go | 4 +- internal/controller/template_controller.go | 43 ++++++--------- .../controller/template_render/controller.go | 1 - internal/controller/user_controller.go | 7 +-- internal/install/install_from_env.go | 3 +- internal/migrations/migrations.go | 4 +- internal/migrations/v22.go | 3 ++ internal/migrations/v24.go | 3 -- internal/repo/answer/answer_repo.go | 1 + .../plugin_config/plugin_user_config_repo.go | 2 +- internal/repo/repo_test/repo_main_test.go | 2 +- internal/repo/tag/tag_rel_repo.go | 1 + internal/service/action/captcha_service.go | 7 ++- internal/service/action/captcha_strategy.go | 27 +++++----- internal/service/badge/badge_event_handler.go | 1 - internal/service/badge/badge_service.go | 26 +++------- internal/service/content/question_service.go | 22 ++++---- internal/service/content/revision_service.go | 5 +- internal/service/content/search_service.go | 3 ++ internal/service/content/vote_service.go | 3 -- .../service/dashboard/dashboard_service.go | 8 +-- .../file_record/file_record_service.go | 1 - internal/service/importer/importer_service.go | 5 +- internal/service/meta/meta_service.go | 12 +++-- .../invite_answer_notification.go | 2 +- .../notification/new_answer_notification.go | 2 +- .../notification/new_comment_notification.go | 2 +- .../notification/new_question_notification.go | 2 +- .../notification/notification_service.go | 4 +- .../notification_common/notification.go | 3 ++ .../service/report_handle/report_handle.go | 6 +++ internal/service/review/review_service.go | 1 - internal/service/siteinfo/siteinfo_service.go | 4 +- internal/service/uploader/upload.go | 28 +++++++--- internal/service/user_admin/user_backyard.go | 11 ++-- .../user_notification_config_service.go | 8 +-- pkg/checker/file_type.go | 4 +- pkg/checker/password.go | 3 +- pkg/converter/markdown.go | 7 ++- pkg/htmltext/htmltext.go | 4 +- plugin/kv_storage.go | 6 +-- plugin/plugin_test/plugin_main_test.go | 2 +- ui/static.go | 1 - 56 files changed, 194 insertions(+), 214 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 263f63f70..611b49bc2 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -17,7 +17,18 @@ version: "2" linters: - default: none + exclusions: + paths: + - answer-data + - ui + - i18n + enable: + - asasalint # checks for pass []any as any in variadic func(...any) + - asciicheck # checks that your code does not contain non-ASCII identifiers + - bidichk # checks for dangerous unicode character sequences + - bodyclose # checks whether HTTP response body is closed successfully + - canonicalheader # checks whether net/http.Header uses canonical header + - copyloopvar # detects places where loop variables are copied (Go 1.22+) formatters: enable: diff --git a/cmd/wire.go b/cmd/wire.go index b25026e5b..3979ecbf5 100644 --- a/cmd/wire.go +++ b/cmd/wire.go @@ -1,5 +1,4 @@ //go:build wireinject -// +build wireinject /* * Licensed to the Apache Software Foundation (ASF) under one @@ -32,7 +31,7 @@ import ( "github.com/apache/answer/internal/base/server" "github.com/apache/answer/internal/base/translator" "github.com/apache/answer/internal/controller" - "github.com/apache/answer/internal/controller/template_render" + templaterender "github.com/apache/answer/internal/controller/template_render" "github.com/apache/answer/internal/controller_admin" "github.com/apache/answer/internal/repo" "github.com/apache/answer/internal/router" diff --git a/internal/base/conf/conf.go b/internal/base/conf/conf.go index db83862b0..04e3a19ba 100644 --- a/internal/base/conf/conf.go +++ b/internal/base/conf/conf.go @@ -117,7 +117,9 @@ func ReadConfig(configFilePath string) (c *AllConfig, err error) { func RewriteConfig(configFilePath string, allConfig *AllConfig) error { buf := bytes.Buffer{} enc := yaml.NewEncoder(&buf) - defer enc.Close() + defer func() { + _ = enc.Close() + }() enc.SetIndent(2) if err := enc.Encode(allConfig); err != nil { return err diff --git a/internal/base/constant/ctx_flag.go b/internal/base/constant/ctx_flag.go index 2a757fa87..450491bb3 100644 --- a/internal/base/constant/ctx_flag.go +++ b/internal/base/constant/ctx_flag.go @@ -23,3 +23,10 @@ const ( AcceptLanguageFlag = "Accept-Language" ShortIDFlag = "Short-ID-Enabled" ) + +type ContextKey string + +const ( + AcceptLanguageContextKey ContextKey = ContextKey(AcceptLanguageFlag) + ShortIDContextKey ContextKey = ContextKey(ShortIDFlag) +) diff --git a/internal/base/data/data.go b/internal/base/data/data.go index 1d24d7184..7696d8f56 100644 --- a/internal/base/data/data.go +++ b/internal/base/data/data.go @@ -47,7 +47,7 @@ type Data struct { func NewData(db *xorm.Engine, cache cache.Cache) (*Data, func(), error) { cleanup := func() { log.Info("closing the data resources") - db.Close() + _ = db.Close() } return &Data{DB: db, Cache: cache}, cleanup, nil } diff --git a/internal/base/handler/lang.go b/internal/base/handler/lang.go index a676e5bc2..4ff1ac7f1 100644 --- a/internal/base/handler/lang.go +++ b/internal/base/handler/lang.go @@ -38,7 +38,7 @@ func GetLang(ctx *gin.Context) i18n.Language { // GetLangByCtx get language from header func GetLangByCtx(ctx context.Context) i18n.Language { - acceptLanguage, ok := ctx.Value(constant.AcceptLanguageFlag).(i18n.Language) + acceptLanguage, ok := ctx.Value(constant.AcceptLanguageContextKey).(i18n.Language) if ok { return acceptLanguage } diff --git a/internal/base/handler/short_id.go b/internal/base/handler/short_id.go index c763bf944..8f9a2a7e5 100644 --- a/internal/base/handler/short_id.go +++ b/internal/base/handler/short_id.go @@ -27,7 +27,7 @@ import ( // GetEnableShortID get language from header func GetEnableShortID(ctx context.Context) bool { - flag, ok := ctx.Value(constant.ShortIDFlag).(bool) + flag, ok := ctx.Value(constant.ShortIDContextKey).(bool) if ok { return flag } diff --git a/internal/base/server/http_funcmap.go b/internal/base/server/http_funcmap.go index 8f6cac5fc..db4604572 100644 --- a/internal/base/server/http_funcmap.go +++ b/internal/base/server/http_funcmap.go @@ -21,7 +21,6 @@ package server import ( "html/template" - "math" "regexp" "strconv" "strings" @@ -107,15 +106,15 @@ var funcMap = template.FuncMap{ } if between >= 60 && between < 3600 { - min := math.Floor(float64(between / 60)) + min := between / 60 trans = translator.GlobalTrans.Tr(la, "ui.dates.x_minutes_ago") - return strings.ReplaceAll(trans, "{{count}}", strconv.FormatFloat(min, 'f', 0, 64)) + return strings.ReplaceAll(trans, "{{count}}", strconv.FormatInt(min, 10)) } if between >= 3600 && between < 3600*24 { - h := math.Floor(float64(between / 3600)) + h := between / 3600 trans = translator.GlobalTrans.Tr(la, "ui.dates.x_hours_ago") - return strings.ReplaceAll(trans, "{{count}}", strconv.FormatFloat(h, 'f', 0, 64)) + return strings.ReplaceAll(trans, "{{count}}", strconv.FormatInt(h, 10)) } if between >= 3600*24 && diff --git a/internal/base/validator/validator.go b/internal/base/validator/validator.go index 22761c521..9c7f6ec41 100644 --- a/internal/base/validator/validator.go +++ b/internal/base/validator/validator.go @@ -142,7 +142,7 @@ func Sanitizer(fl validator.FieldLevel) (res bool) { switch field.Kind() { case reflect.String: filter := bluemonday.UGCPolicy() - content := strings.Replace(filter.Sanitize(field.String()), "&", "&", -1) + content := strings.ReplaceAll(filter.Sanitize(field.String()), "&", "&") field.SetString(content) return true case reflect.Chan, reflect.Map, reflect.Slice, reflect.Array: diff --git a/internal/cli/build.go b/internal/cli/build.go index a5a4d938e..efc876e31 100644 --- a/internal/cli/build.go +++ b/internal/cli/build.go @@ -34,7 +34,6 @@ import ( "github.com/Masterminds/semver/v3" "github.com/apache/answer/pkg/dir" "github.com/apache/answer/pkg/writer" - "github.com/apache/answer/ui" "github.com/segmentfault/pacman/log" "gopkg.in/yaml.v3" ) @@ -300,50 +299,6 @@ func copyUIFiles(b *buildingMaterial) (err error) { return nil } -// overwriteIndexTs overwrites index.ts file in ui/src/plugins/ dir -func overwriteIndexTs(b *buildingMaterial) (err error) { - localUIPluginDir := filepath.Join(b.tmpDir, "vendor/github.com/apache/answer/ui/src/plugins/") - - folders, err := getFolders(localUIPluginDir) - if err != nil { - return fmt.Errorf("failed to get folders: %w", err) - } - - content := generateIndexTsContent(folders) - err = os.WriteFile(filepath.Join(localUIPluginDir, "index.ts"), []byte(content), 0644) - if err != nil { - return fmt.Errorf("failed to write index.ts: %w", err) - } - return nil -} - -func getFolders(dir string) ([]string, error) { - var folders []string - files, err := os.ReadDir(dir) - if err != nil { - return nil, err - } - for _, file := range files { - if file.IsDir() && file.Name() != "builtin" { - folders = append(folders, file.Name()) - } - } - return folders, nil -} - -func generateIndexTsContent(folders []string) string { - builder := &strings.Builder{} - builder.WriteString("export default null;\n") - // Line 2:1: Delete `⏎` prettier/prettier - if len(folders) > 0 { - builder.WriteString("\n") - } - for _, folder := range folders { - builder.WriteString(fmt.Sprintf("export { default as %s } from '%s';\n", folder, folder)) - } - return builder.String() -} - // buildUI run pnpm install and pnpm build commands to build ui func buildUI(b *buildingMaterial) (err error) { localUIBuildDir := filepath.Join(b.tmpDir, "vendor/github.com/apache/answer/ui") @@ -362,13 +317,6 @@ func buildUI(b *buildingMaterial) (err error) { return nil } -func replaceNecessaryFile(b *buildingMaterial) (err error) { - fmt.Printf("try to replace ui build directory\n") - uiBuildDir := filepath.Join(b.tmpDir, "vendor/github.com/apache/answer/ui") - err = copyDirEntries(ui.Build, ".", uiBuildDir) - return err -} - // mergeI18nFiles merge i18n files func mergeI18nFiles(b *buildingMaterial) (err error) { fmt.Printf("try to merge i18n files\n") diff --git a/internal/cli/config.go b/internal/cli/config.go index ecb62a13c..e2445c590 100644 --- a/internal/cli/config.go +++ b/internal/cli/config.go @@ -42,7 +42,9 @@ func SetDefaultConfig(dbConf *data.Database, cacheConf *data.CacheConf, field *C if err != nil { return err } - defer db.Close() + defer func() { + _ = db.Close() + }() cache, cacheCleanup, err := data.NewCache(cacheConf) if err != nil { @@ -50,7 +52,7 @@ func SetDefaultConfig(dbConf *data.Database, cacheConf *data.CacheConf, field *C } defer func() { if cache != nil { - cache.Flush(context.Background()) + _ = cache.Flush(context.Background()) cacheCleanup() } }() diff --git a/internal/cli/dump.go b/internal/cli/dump.go index e5d528212..e63ef1a93 100644 --- a/internal/cli/dump.go +++ b/internal/cli/dump.go @@ -34,7 +34,9 @@ func DumpAllData(dataConf *data.Database, dumpDataPath string) error { if err != nil { return err } - defer db.Close() + defer func() { + _ = db.Close() + }() if err = db.Ping(); err != nil { return err } diff --git a/internal/cli/install_check.go b/internal/cli/install_check.go index 9326e069f..c3fadcaba 100644 --- a/internal/cli/install_check.go +++ b/internal/cli/install_check.go @@ -43,7 +43,9 @@ func CheckDBConnection(dataConf *data.Database) bool { fmt.Printf("connection database failed: %s\n", err) return false } - defer db.Close() + defer func() { + _ = db.Close() + }() if err = db.Ping(); err != nil { fmt.Printf("connection ping database failed: %s\n", err) return false @@ -59,7 +61,9 @@ func CheckDBTableExist(dataConf *data.Database) bool { fmt.Printf("connection database failed: %s\n", err) return false } - defer db.Close() + defer func() { + _ = db.Close() + }() if err = db.Ping(); err != nil { fmt.Printf("connection ping database failed: %s\n", err) return false diff --git a/internal/cli/reset_password.go b/internal/cli/reset_password.go index 2a7d1af4c..dbb3422af 100644 --- a/internal/cli/reset_password.go +++ b/internal/cli/reset_password.go @@ -77,7 +77,9 @@ func ResetPassword(ctx context.Context, dataDirPath string, opts *ResetPasswordO if err != nil { return fmt.Errorf("connect database failed: %w", err) } - defer db.Close() + defer func() { + _ = db.Close() + }() cache, cacheCleanup, err := data.NewCache(config.Data.Cache) if err != nil { diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index 83cd58c32..801e129c2 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -162,11 +162,9 @@ func (tc *TemplateController) Index(ctx *gin.Context) { siteInfo := tc.SiteInfo(ctx) siteInfo.Canonical = siteInfo.General.SiteUrl - UrlUseTitle := false - if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || - siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID { - UrlUseTitle = true - } + UrlUseTitle := siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || + siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID + siteInfo.Title = "" tc.html(ctx, http.StatusOK, "question.html", siteInfo, gin.H{ "data": data, @@ -205,11 +203,9 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) { siteInfo.Canonical = fmt.Sprintf("%s/questions?page=%d", siteInfo.General.SiteUrl, page) } - UrlUseTitle := false - if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || - siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID { - UrlUseTitle = true - } + UrlUseTitle := siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || + siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID + 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, @@ -371,11 +367,8 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) { return } - UrlUseTitle := false - if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || - siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID { - UrlUseTitle = true - } + UrlUseTitle := siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || + siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID //related question userID := middleware.GetLoginUserIDFromContext(ctx) @@ -434,7 +427,7 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) { for _, tag := range detail.Tags { tags = append(tags, tag.DisplayName) } - siteInfo.Keywords = strings.Replace(strings.Trim(fmt.Sprint(tags), "[]"), " ", ",", -1) + siteInfo.Keywords = strings.ReplaceAll(strings.Trim(fmt.Sprint(tags), "[]"), " ", ",") siteInfo.Title = fmt.Sprintf("%s - %s", detail.Title, siteInfo.General.Name) tc.html(ctx, http.StatusOK, "question-detail.html", siteInfo, gin.H{ "id": id, @@ -504,11 +497,9 @@ func (tc *TemplateController) TagInfo(ctx *gin.Context) { } siteInfo.Keywords = tagInfo.DisplayName - UrlUseTitle := false - if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || - siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID { - UrlUseTitle = true - } + UrlUseTitle := siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || + siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID + siteInfo.Title = fmt.Sprintf("'%s' %s - %s", tagInfo.DisplayName, translator.Tr(handler.GetLang(ctx), constant.QuestionsTitleTrKey), siteInfo.General.Name) tc.html(ctx, http.StatusOK, "tag-detail.html", siteInfo, gin.H{ "tag": tagInfo, @@ -570,11 +561,9 @@ func (tc *TemplateController) Page404(ctx *gin.Context) { } func (tc *TemplateController) html(ctx *gin.Context, code int, tpl string, siteInfo *schema.TemplateSiteInfoResp, data gin.H) { - var ( - prefix = "" - cssPath = "" - scriptPath = make([]string, len(tc.scriptPath)) - ) + prefix := "" + cssPath := "" + scriptPath := make([]string, len(tc.scriptPath)) _ = plugin.CallCDN(func(fn plugin.CDN) error { prefix = fn.GetStaticPrefix() @@ -612,7 +601,7 @@ func (tc *TemplateController) html(ctx *gin.Context, code int, tpl string, siteI data["description"] = siteInfo.Description data["language"] = handler.GetLang(ctx) data["timezone"] = siteInfo.Interface.TimeZone - language := strings.Replace(siteInfo.Interface.Language, "_", "-", -1) + language := strings.ReplaceAll(siteInfo.Interface.Language, "_", "-") data["lang"] = language data["HeadCode"] = siteInfo.CustomCssHtml.CustomHead data["HeaderCode"] = siteInfo.CustomCssHtml.CustomHeader diff --git a/internal/controller/template_render/controller.go b/internal/controller/template_render/controller.go index 5f802fa76..3412010db 100644 --- a/internal/controller/template_render/controller.go +++ b/internal/controller/template_render/controller.go @@ -101,7 +101,6 @@ func Paginator(page, pageSize int, nums int64) *schema.Paginator { case page >= 3 && totalpages > 5: start := page - 3 + 1 pages = make([]int, 5) - prevpage = page - 3 for i := range pages { pages[i] = start + i } diff --git a/internal/controller/user_controller.go b/internal/controller/user_controller.go index 49b9b23c6..e4a3b3d3b 100644 --- a/internal/controller/user_controller.go +++ b/internal/controller/user_controller.go @@ -151,7 +151,7 @@ func (uc *UserController) UserEmailLogin(ctx *gin.Context) { resp, err := uc.userService.EmailLogin(ctx, req) if err != nil { - _, _ = uc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionPassword, ctx.ClientIP()) + uc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionPassword, ctx.ClientIP()) errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "e_mail", ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.EmailOrPasswordWrong), @@ -404,10 +404,7 @@ func (uc *UserController) UserModifyPassWord(ctx *gin.Context) { handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return } - _, err := uc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionEditUserinfo, req.UserID) - if err != nil { - log.Error(err) - } + uc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionEditUserinfo, req.UserID) } oldPassVerification, err := uc.userService.UserModifyPassWordVerification(ctx, req) diff --git a/internal/install/install_from_env.go b/internal/install/install_from_env.go index c05d2aaba..02bc76381 100644 --- a/internal/install/install_from_env.go +++ b/internal/install/install_from_env.go @@ -22,6 +22,7 @@ package install import ( "bytes" "encoding/json" + "errors" "fmt" "net/http" "net/http/httptest" @@ -143,7 +144,7 @@ func requestAPI(req any, method, url string, handlerFunc gin.HandlerFunc) error } handlerFunc(c) if w.Code != http.StatusOK { - return fmt.Errorf(gjson.Get(w.Body.String(), "msg").String()) + return errors.New(gjson.Get(w.Body.String(), "msg").String()) } return nil } diff --git a/internal/migrations/migrations.go b/internal/migrations/migrations.go index 9caa28ed1..2fbfbb7fd 100644 --- a/internal/migrations/migrations.go +++ b/internal/migrations/migrations.go @@ -147,7 +147,9 @@ func Migrate(debug bool, dbConf *data.Database, cacheConf *data.CacheConf, upgra fmt.Println("new database failed: ", err.Error()) return err } - defer engine.Close() + defer func() { + _ = engine.Close() + }() currentDBVersion, err := GetCurrentDBVersion(engine) if err != nil { diff --git a/internal/migrations/v22.go b/internal/migrations/v22.go index e7177deae..5367f5d46 100644 --- a/internal/migrations/v22.go +++ b/internal/migrations/v22.go @@ -61,6 +61,9 @@ func addBadges(ctx context.Context, x *xorm.Engine) (err error) { if exist { badge.ID = beans.ID _, err = x.Context(ctx).ID(beans.ID).Update(badge) + if err != nil { + return fmt.Errorf("update badge failed: %w", err) + } continue } badge.ID, err = uniqueIDRepo.GenUniqueIDStr(ctx, new(entity.Badge).TableName()) diff --git a/internal/migrations/v24.go b/internal/migrations/v24.go index a488679f6..86d624254 100644 --- a/internal/migrations/v24.go +++ b/internal/migrations/v24.go @@ -66,8 +66,5 @@ func addQuestionLinkedCount(ctx context.Context, x *xorm.Engine) error { } } - type Question struct { - LinkedCount int `xorm:"not null default 0 INT(11) linked_count"` - } return x.Context(ctx).Sync(new(entity.Question)) } diff --git a/internal/repo/answer/answer_repo.go b/internal/repo/answer/answer_repo.go index c5447befc..0f1ae8146 100644 --- a/internal/repo/answer/answer_repo.go +++ b/internal/repo/answer/answer_repo.go @@ -503,6 +503,7 @@ func (ar *answerRepo) updateSearch(ctx context.Context, answerID string) (err er err = st.Find(&tagListList) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + return } for _, tag := range tagListList { tags = append(tags, tag.TagID) diff --git a/internal/repo/plugin_config/plugin_user_config_repo.go b/internal/repo/plugin_config/plugin_user_config_repo.go index d14442a56..df5ae29b8 100644 --- a/internal/repo/plugin_config/plugin_user_config_repo.go +++ b/internal/repo/plugin_config/plugin_user_config_repo.go @@ -71,7 +71,7 @@ func (ur *pluginUserConfigRepo) SaveUserPluginConfig(ctx context.Context, userID return nil, nil }) if err != nil { - err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } return nil } diff --git a/internal/repo/repo_test/repo_main_test.go b/internal/repo/repo_test/repo_main_test.go index a59ae6269..919ca94e8 100644 --- a/internal/repo/repo_test/repo_main_test.go +++ b/internal/repo/repo_test/repo_main_test.go @@ -77,7 +77,7 @@ func TestMain(t *testing.M) { dbSetting = dbSettingMapping[string(schemas.SQLITE)] } if dbSetting.Driver == string(schemas.SQLITE) { - os.RemoveAll(dbSetting.Connection) + _ = os.RemoveAll(dbSetting.Connection) } defer func() { diff --git a/internal/repo/tag/tag_rel_repo.go b/internal/repo/tag/tag_rel_repo.go index 3634c97a7..a52b1bf54 100644 --- a/internal/repo/tag/tag_rel_repo.go +++ b/internal/repo/tag/tag_rel_repo.go @@ -198,6 +198,7 @@ func (tr *tagRelRepo) GetTagRelDefaultStatusByObjectID(ctx context.Context, obje exist, err := tr.data.DB.Context(ctx).ID(objectID).Cols("show", "status").Get(&question) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + return } if exist && (question.Show == entity.QuestionHide || question.Status == entity.QuestionStatusDeleted) { return entity.TagRelStatusHide, nil diff --git a/internal/service/action/captcha_service.go b/internal/service/action/captcha_service.go index 04f8b16ac..aefb70519 100644 --- a/internal/service/action/captcha_service.go +++ b/internal/service/action/captcha_service.go @@ -106,11 +106,11 @@ func (cs *CaptchaService) ActionRecordVerifyCaptcha( return pass } -func (cs *CaptchaService) ActionRecordAdd(ctx context.Context, actionType string, unit string) (int, error) { +func (cs *CaptchaService) ActionRecordAdd(ctx context.Context, actionType string, unit string) { info, err := cs.captchaRepo.GetActionType(ctx, unit, actionType) if err != nil { log.Error(err) - return 0, err + return } amount := 1 if info != nil { @@ -118,9 +118,8 @@ func (cs *CaptchaService) ActionRecordAdd(ctx context.Context, actionType string } err = cs.captchaRepo.SetActionType(ctx, unit, actionType, "", amount) if err != nil { - return 0, err + log.Error(err) } - return amount, nil } func (cs *CaptchaService) ActionRecordDel(ctx context.Context, actionType string, unit string) { diff --git a/internal/service/action/captcha_strategy.go b/internal/service/action/captcha_strategy.go index 3befda821..b423b583b 100644 --- a/internal/service/action/captcha_strategy.go +++ b/internal/service/action/captcha_strategy.go @@ -89,7 +89,9 @@ func (cs *CaptchaService) CaptchaActionPassword(ctx context.Context, unit string return false } if now-actionInfo.LastTime != 0 && now-actionInfo.LastTime > setTime { - cs.captchaRepo.SetActionType(ctx, unit, entity.CaptchaActionPassword, "", 0) + if err := cs.captchaRepo.SetActionType(ctx, unit, entity.CaptchaActionPassword, "", 0); err != nil { + log.Error(err) + } } return true } @@ -105,7 +107,9 @@ func (cs *CaptchaService) CaptchaActionEditUserinfo(ctx context.Context, unit st return false } if now-actionInfo.LastTime != 0 && now-actionInfo.LastTime > setTime { - cs.captchaRepo.SetActionType(ctx, unit, entity.CaptchaActionEditUserinfo, "", 0) + if err := cs.captchaRepo.SetActionType(ctx, unit, entity.CaptchaActionEditUserinfo, "", 0); err != nil { + log.Error(err) + } } return true } @@ -154,10 +158,7 @@ func (cs *CaptchaService) CaptchaActionEdit(ctx context.Context, unit string, ac return true } setNum := 10 - if actionInfo.Num >= setNum { - return false - } - return true + return actionInfo.Num < setNum } func (cs *CaptchaService) CaptchaActionInvitationAnswer(ctx context.Context, unit string, actionInfo *entity.ActionRecordInfo) bool { @@ -165,10 +166,7 @@ func (cs *CaptchaService) CaptchaActionInvitationAnswer(ctx context.Context, uni return true } setNum := 30 - if actionInfo.Num >= setNum { - return false - } - return true + return actionInfo.Num < setNum } func (cs *CaptchaService) CaptchaActionSearch(ctx context.Context, unit string, actionInfo *entity.ActionRecordInfo) bool { @@ -182,7 +180,9 @@ func (cs *CaptchaService) CaptchaActionSearch(ctx context.Context, unit string, return false } if now-actionInfo.LastTime > setTime { - cs.captchaRepo.SetActionType(ctx, unit, entity.CaptchaActionSearch, "", 0) + if err := cs.captchaRepo.SetActionType(ctx, unit, entity.CaptchaActionSearch, "", 0); err != nil { + log.Error(err) + } } return true } @@ -218,8 +218,5 @@ func (cs *CaptchaService) CaptchaActionVote(ctx context.Context, unit string, ac return true } setNum := 40 - if actionInfo.Num >= setNum { - return false - } - return true + return actionInfo.Num < setNum } diff --git a/internal/service/badge/badge_event_handler.go b/internal/service/badge/badge_event_handler.go index cc161f6ad..24cabf29b 100644 --- a/internal/service/badge/badge_event_handler.go +++ b/internal/service/badge/badge_event_handler.go @@ -32,7 +32,6 @@ import ( type BadgeEventService struct { data *data.Data eventQueueService event_queue.EventQueueService - badgeAwardRepo BadgeAwardRepo badgeRepo BadgeRepo eventRuleRepo EventRuleRepo badgeAwardService *BadgeAwardService diff --git a/internal/service/badge/badge_service.go b/internal/service/badge/badge_service.go index 03b8a8774..ebb90450a 100644 --- a/internal/service/badge/badge_service.go +++ b/internal/service/badge/badge_service.go @@ -206,10 +206,8 @@ func (b *BadgeService) ListPaged(ctx context.Context, req *schema.GetBadgeListPa resp = make([]*schema.GetBadgeListPagedResp, len(badges)) general, siteErr := b.siteInfoCommonService.GetSiteGeneral(ctx) - var baseURL = "" - if siteErr != nil { - baseURL = "" - } else { + baseURL := "" + if siteErr == nil { baseURL = general.SiteUrl } @@ -246,31 +244,23 @@ func (b *BadgeService) searchByName(ctx context.Context, name string) (result [] // GetBadgeInfo get badge info func (b *BadgeService) GetBadgeInfo(ctx *gin.Context, id string, userID string) (info *schema.GetBadgeInfoResp, err error) { - var ( - badge *entity.Badge - earnedTotal int64 = 0 - exists = false - ) - - badge, exists, err = b.badgeRepo.GetByID(ctx, id) + badge, exists, err := b.badgeRepo.GetByID(ctx, id) if err != nil { - return + return nil, err } if !exists || badge.Status == entity.BadgeStatusInactive { - err = errors.BadRequest(reason.BadgeObjectNotFound) - return + return nil, errors.BadRequest(reason.BadgeObjectNotFound) } + var earnedTotal int64 if len(userID) > 0 { earnedTotal = b.badgeAwardRepo.CountByUserIdAndBadgeId(ctx, userID, badge.ID) } + baseURL := "" general, siteErr := b.siteInfoCommonService.GetSiteGeneral(ctx) - var baseURL = "" - if siteErr != nil { - baseURL = "" - } else { + if siteErr == nil { baseURL = general.SiteUrl } diff --git a/internal/service/content/question_service.go b/internal/service/content/question_service.go index 1d1d1af39..da15fae5d 100644 --- a/internal/service/content/question_service.go +++ b/internal/service/content/question_service.go @@ -277,7 +277,7 @@ func (qs *QuestionService) CheckAddQuestion(ctx context.Context, req *schema.Que if tagerr != nil { return errorlist, tagerr } - if !req.QuestionPermission.CanUseReservedTag { + if !req.CanUseReservedTag { taglist, err := qs.AddQuestionCheckTags(ctx, Tags) errMsg := fmt.Sprintf(`"%s" can only be used by moderators.`, strings.Join(taglist, ",")) @@ -350,7 +350,7 @@ func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.Question if tagerr != nil { return questionInfo, tagerr } - if !req.QuestionPermission.CanUseReservedTag { + if !req.CanUseReservedTag { taglist, err := qs.AddQuestionCheckTags(ctx, tags) errMsg := fmt.Sprintf(`"%s" can only be used by moderators.`, strings.Join(taglist, ",")) @@ -1397,13 +1397,17 @@ func (qs *QuestionService) GetQuestionsByTitle(ctx context.Context, title string for _, question := range res { questionIDs = append(questionIDs, question.ID) } - questions, err = qs.questionRepo.FindByID(ctx, questionIDs) + var questionErr error + questions, questionErr = qs.questionRepo.FindByID(ctx, questionIDs) + if questionErr != nil { + return resp, questionErr + } } else { - questions, err = qs.questionRepo.GetQuestionsByTitle(ctx, title, 10) - } - - if err != nil { - return resp, err + var questionErr error + questions, questionErr = qs.questionRepo.GetQuestionsByTitle(ctx, title, 10) + if questionErr != nil { + return resp, questionErr + } } for _, question := range questions { item := &schema.QuestionBaseInfo{} @@ -1723,7 +1727,7 @@ func (qs *QuestionService) SitemapCron(ctx context.Context) { log.Error(err) return } - ctx = context.WithValue(ctx, constant.ShortIDFlag, siteSeo.IsShortLink()) + ctx = context.WithValue(ctx, constant.ShortIDContextKey, siteSeo.IsShortLink()) qs.questioncommon.SitemapCron(ctx) } diff --git a/internal/service/content/revision_service.go b/internal/service/content/revision_service.go index 1aed4cf82..a5cefeb41 100644 --- a/internal/service/content/revision_service.go +++ b/internal/service/content/revision_service.go @@ -41,7 +41,6 @@ import ( "github.com/apache/answer/internal/service/review" "github.com/apache/answer/internal/service/revision" "github.com/apache/answer/internal/service/tag_common" - tagcommon "github.com/apache/answer/internal/service/tag_common" usercommon "github.com/apache/answer/internal/service/user_common" "github.com/apache/answer/pkg/converter" "github.com/apache/answer/pkg/htmltext" @@ -62,7 +61,7 @@ type RevisionService struct { questionRepo questioncommon.QuestionRepo answerRepo answercommon.AnswerRepo tagRepo tag_common.TagRepo - tagCommon *tagcommon.TagCommonService + tagCommon *tag_common.TagCommonService notificationQueueService notice_queue.NotificationQueueService activityQueueService activity_queue.ActivityQueueService reportRepo report_common.ReportRepo @@ -79,7 +78,7 @@ func NewRevisionService( questionRepo questioncommon.QuestionRepo, answerRepo answercommon.AnswerRepo, tagRepo tag_common.TagRepo, - tagCommon *tagcommon.TagCommonService, + tagCommon *tag_common.TagCommonService, notificationQueueService notice_queue.NotificationQueueService, activityQueueService activity_queue.ActivityQueueService, reportRepo report_common.ReportRepo, diff --git a/internal/service/content/search_service.go b/internal/service/content/search_service.go index 98add0938..ccafcd82c 100644 --- a/internal/service/content/search_service.go +++ b/internal/service/content/search_service.go @@ -93,6 +93,9 @@ func (ss *SearchService) searchByPlugin(ctx context.Context, finder plugin.Searc } else if cond.SearchAnswer() { res, resp.Total, err = finder.SearchAnswers(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order)) } + if err != nil { + return resp, err + } resp.SearchResults, err = ss.searchRepo.ParseSearchPluginResult(ctx, res, cond.Words) return resp, err diff --git a/internal/service/content/vote_service.go b/internal/service/content/vote_service.go index 92f0c9962..aa6150497 100644 --- a/internal/service/content/vote_service.go +++ b/internal/service/content/vote_service.go @@ -26,8 +26,6 @@ import ( "github.com/apache/answer/internal/service/event_queue" - "github.com/apache/answer/internal/service/activity_common" - "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/handler" "github.com/apache/answer/internal/base/pager" @@ -64,7 +62,6 @@ type VoteService struct { answerRepo answercommon.AnswerRepo commentCommonRepo comment_common.CommentCommonRepo objectService *object_info.ObjService - activityRepo activity_common.ActivityRepo eventQueueService event_queue.EventQueueService } diff --git a/internal/service/dashboard/dashboard_service.go b/internal/service/dashboard/dashboard_service.go index d9198e6db..91f0e338a 100644 --- a/internal/service/dashboard/dashboard_service.go +++ b/internal/service/dashboard/dashboard_service.go @@ -274,7 +274,9 @@ func (ds *dashboardService) remoteVersion(ctx context.Context) string { log.Errorf("request remote version failed: %s", err) return "" } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() respByte, err := io.ReadAll(resp.Body) if err != nil { @@ -358,7 +360,7 @@ func (ds *dashboardService) GetDatabaseSize() (dbSize string) { if err != nil { log.Warnf("get db size failed: %s", err) } else { - if res != nil && len(res) > 0 && res[0]["db_size"] != nil { + if len(res) > 0 && res[0]["db_size"] != nil { dbSizeStr, _ := res[0]["db_size"].(string) dbSize = dir.FormatFileSize(converter.StringToInt64(dbSizeStr)) } @@ -370,7 +372,7 @@ func (ds *dashboardService) GetDatabaseSize() (dbSize string) { if err != nil { log.Warnf("get db size failed: %s", err) } else { - if res != nil && len(res) > 0 && res[0]["db_size"] != nil { + if len(res) > 0 && res[0]["db_size"] != nil { dbSizeStr, _ := res[0]["db_size"].(int32) dbSize = dir.FormatFileSize(int64(dbSizeStr)) } diff --git a/internal/service/file_record/file_record_service.go b/internal/service/file_record/file_record_service.go index 29097ba8c..aa526f014 100644 --- a/internal/service/file_record/file_record_service.go +++ b/internal/service/file_record/file_record_service.go @@ -174,7 +174,6 @@ func (fs *FileRecordService) PurgeDeletedFiles(ctx context.Context) { if err != nil { log.Errorf("create deleted directory error: %v", err) } - return } func (fs *FileRecordService) DeleteAndMoveFileRecord(ctx context.Context, fileRecord *entity.FileRecord) error { diff --git a/internal/service/importer/importer_service.go b/internal/service/importer/importer_service.go index 45aabf39b..c7673ffb5 100644 --- a/internal/service/importer/importer_service.go +++ b/internal/service/importer/importer_service.go @@ -62,8 +62,7 @@ type ImporterFunc struct { } func (ipfunc *ImporterFunc) AddQuestion(ctx context.Context, questionInfo plugin.QuestionImporterInfo) (err error) { - ipfunc.importerService.ImportQuestion(ctx, questionInfo) - return nil + return ipfunc.importerService.ImportQuestion(ctx, questionInfo) } func (ip *ImporterService) NewImporterFunc() plugin.ImporterFunc { @@ -84,7 +83,7 @@ func (ip *ImporterService) ImportQuestion(ctx context.Context, questionInfo plug return err } if !exist { - return fmt.Errorf("User not found") + return fmt.Errorf("user not found") } // To limit rate, remove the following code from comment: Part 2/2 diff --git a/internal/service/meta/meta_service.go b/internal/service/meta/meta_service.go index 4b3104197..c1ca7c619 100644 --- a/internal/service/meta/meta_service.go +++ b/internal/service/meta/meta_service.go @@ -97,7 +97,8 @@ func (ms *MetaService) AddOrUpdateReaction(ctx context.Context, req *schema.Upda return nil, err } var event *schema.EventMsg - if objectType == constant.AnswerObjectType { + switch objectType { + case constant.AnswerObjectType: answerInfo, exist, err := ms.answerRepo.GetAnswer(ctx, req.ObjectID) if err != nil { return nil, err @@ -107,7 +108,7 @@ func (ms *MetaService) AddOrUpdateReaction(ctx context.Context, req *schema.Upda } event = schema.NewEvent(constant.EventAnswerReact, req.UserID).TID(answerInfo.ID). AID(answerInfo.ID, answerInfo.UserID) - } else if objectType == constant.QuestionObjectType { + case constant.QuestionObjectType: questionInfo, exist, err := ms.questionRepo.GetQuestion(ctx, req.ObjectID) if err != nil { return nil, err @@ -117,7 +118,7 @@ func (ms *MetaService) AddOrUpdateReaction(ctx context.Context, req *schema.Upda } event = schema.NewEvent(constant.EventQuestionReact, req.UserID).TID(questionInfo.ID). QID(questionInfo.ID, questionInfo.UserID) - } else { + default: return nil, myErrors.BadRequest(reason.ObjectNotFound) } @@ -159,9 +160,10 @@ func (ms *MetaService) AddOrUpdateReaction(ctx context.Context, req *schema.Upda // updateReaction update reaction func (ms *MetaService) updateReaction(req *schema.UpdateReactionReq, reactions *schema.ReactionsSummaryMeta) { - if req.Reaction == "activate" { + switch req.Reaction { + case "activate": reactions.AddReactionSummary(req.Emoji, req.UserID) - } else if req.Reaction == "deactivate" { + case "deactivate": reactions.RemoveReactionSummary(req.Emoji, req.UserID) } } diff --git a/internal/service/notification/invite_answer_notification.go b/internal/service/notification/invite_answer_notification.go index 4e7c051cd..f68feb067 100644 --- a/internal/service/notification/invite_answer_notification.go +++ b/internal/service/notification/invite_answer_notification.go @@ -70,7 +70,7 @@ func (ns *ExternalNotificationService) sendInviteAnswerNotificationEmail(ctx con // If receiver has set language, use it to send email. if len(lang) > 0 { - ctx = context.WithValue(ctx, constant.AcceptLanguageFlag, i18n.Language(lang)) + ctx = context.WithValue(ctx, constant.AcceptLanguageContextKey, i18n.Language(lang)) } title, body, err := ns.emailService.NewInviteAnswerTemplate(ctx, rawData) if err != nil { diff --git a/internal/service/notification/new_answer_notification.go b/internal/service/notification/new_answer_notification.go index 91b7e2ae3..c54fd961c 100644 --- a/internal/service/notification/new_answer_notification.go +++ b/internal/service/notification/new_answer_notification.go @@ -70,7 +70,7 @@ func (ns *ExternalNotificationService) sendNewAnswerNotificationEmail(ctx contex // If receiver has set language, use it to send email. if len(lang) > 0 { - ctx = context.WithValue(ctx, constant.AcceptLanguageFlag, i18n.Language(lang)) + ctx = context.WithValue(ctx, constant.AcceptLanguageContextKey, i18n.Language(lang)) } title, body, err := ns.emailService.NewAnswerTemplate(ctx, rawData) if err != nil { diff --git a/internal/service/notification/new_comment_notification.go b/internal/service/notification/new_comment_notification.go index 3ec99d13c..e622ed4f7 100644 --- a/internal/service/notification/new_comment_notification.go +++ b/internal/service/notification/new_comment_notification.go @@ -69,7 +69,7 @@ func (ns *ExternalNotificationService) sendNewCommentNotificationEmail(ctx conte } // If receiver has set language, use it to send email. if len(lang) > 0 { - ctx = context.WithValue(ctx, constant.AcceptLanguageFlag, i18n.Language(lang)) + ctx = context.WithValue(ctx, constant.AcceptLanguageContextKey, i18n.Language(lang)) } title, body, err := ns.emailService.NewCommentTemplate(ctx, rawData) if err != nil { diff --git a/internal/service/notification/new_question_notification.go b/internal/service/notification/new_question_notification.go index 8a12d0b8c..debfb8c27 100644 --- a/internal/service/notification/new_question_notification.go +++ b/internal/service/notification/new_question_notification.go @@ -176,7 +176,7 @@ func (ns *ExternalNotificationService) sendNewQuestionNotificationEmail(ctx cont } // If receiver has set language, use it to send email. if len(userInfo.Language) > 0 { - ctx = context.WithValue(ctx, constant.AcceptLanguageFlag, i18n.Language(userInfo.Language)) + ctx = context.WithValue(ctx, constant.AcceptLanguageContextKey, i18n.Language(userInfo.Language)) } title, body, err := ns.emailService.NewQuestionTemplate(ctx, rawData) if err != nil { diff --git a/internal/service/notification/notification_service.go b/internal/service/notification/notification_service.go index 09d871351..0369d4557 100644 --- a/internal/service/notification/notification_service.go +++ b/internal/service/notification/notification_service.go @@ -82,8 +82,8 @@ func (ns *NotificationService) GetRedDot(ctx context.Context, req *schema.GetRed achievementKey := fmt.Sprintf(constant.RedDotCacheKey, constant.NotificationTypeAchievement, req.UserID) redBot := &schema.RedDot{} - redBot.Inbox, _, err = ns.data.Cache.GetInt64(ctx, inboxKey) - redBot.Achievement, _, err = ns.data.Cache.GetInt64(ctx, achievementKey) + redBot.Inbox, _, _ = ns.data.Cache.GetInt64(ctx, inboxKey) + redBot.Achievement, _, _ = ns.data.Cache.GetInt64(ctx, achievementKey) // get review amount if req.CanReviewAnswer || req.CanReviewQuestion || req.CanReviewTag { diff --git a/internal/service/notification_common/notification.go b/internal/service/notification_common/notification.go index 2bceb6298..55d638424 100644 --- a/internal/service/notification_common/notification.go +++ b/internal/service/notification_common/notification.go @@ -206,6 +206,9 @@ func (ns *NotificationCommon) AddNotification(ctx context.Context, msg *schema.N } if req.ObjectInfo.ObjectType == constant.BadgeAwardObjectType { err = ns.AddBadgeAwardAlertCache(ctx, info.UserID, info.ID, req.ObjectInfo.ObjectMap["badge_id"]) + if err != nil { + log.Error("AddBadgeAwardAlertCache Error", err.Error()) + } } go ns.SendNotificationToAllFollower(ctx, msg, questionID) diff --git a/internal/service/report_handle/report_handle.go b/internal/service/report_handle/report_handle.go index 27cffb111..a04681663 100644 --- a/internal/service/report_handle/report_handle.go +++ b/internal/service/report_handle/report_handle.go @@ -112,6 +112,9 @@ func (rh *ReportHandle) updateReportedAnswerReport(ctx context.Context, report * NoNeedReview: true, }) } + if err != nil { + return err + } return nil } @@ -128,5 +131,8 @@ func (rh *ReportHandle) updateReportedCommentReport(ctx context.Context, report UserID: req.UserID, }) } + if err != nil { + return err + } return nil } diff --git a/internal/service/review/review_service.go b/internal/service/review/review_service.go index 40089fb2d..a23b9ee43 100644 --- a/internal/service/review/review_service.go +++ b/internal/service/review/review_service.go @@ -469,7 +469,6 @@ func (cs *ReviewService) notificationCommentOnTheQuestion(ctx context.Context, c cs.notificationAnswerComment(ctx, objInfo.QuestionID, objInfo.Title, objInfo.AnswerID, objInfo.ObjectCreatorUserID, comment.ID, comment.UserID, htmltext.FetchExcerpt(comment.ParsedText, "...", 240)) } - return } func (cs *ReviewService) notificationCommentReply(ctx context.Context, replyUserID, commentID, commentUserID, diff --git a/internal/service/siteinfo/siteinfo_service.go b/internal/service/siteinfo/siteinfo_service.go index cf43d68d5..f355d09f4 100644 --- a/internal/service/siteinfo/siteinfo_service.go +++ b/internal/service/siteinfo/siteinfo_service.go @@ -345,7 +345,7 @@ func (s *SiteInfoService) GetPrivilegesConfig(ctx context.Context) (resp *schema return nil, err } privilegeOptions := schema.DefaultPrivilegeOptions - if privilege.CustomPrivileges != nil && len(privilege.CustomPrivileges) > 0 { + if len(privilege.CustomPrivileges) > 0 { privilegeOptions = append(privilegeOptions, &schema.PrivilegeOption{ Level: schema.PrivilegeLevelCustom, LevelDesc: reason.PrivilegeLevelCustomDesc, @@ -358,7 +358,7 @@ func (s *SiteInfoService) GetPrivilegesConfig(ctx context.Context) (resp *schema Options: s.translatePrivilegeOptions(ctx, privilegeOptions), SelectedLevel: schema.PrivilegeLevel3, } - if privilege != nil && privilege.Level > 0 { + if privilege.Level > 0 { resp.SelectedLevel = privilege.Level } return resp, nil diff --git a/internal/service/uploader/upload.go b/internal/service/uploader/upload.go index 2ae5369df..30029193b 100644 --- a/internal/service/uploader/upload.go +++ b/internal/service/uploader/upload.go @@ -119,7 +119,9 @@ func (us *uploaderService) UploadAvatarFile(ctx *gin.Context, userID string) (ur if err != nil { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) } - file.Close() + defer func() { + _ = file.Close() + }() fileExt := strings.ToLower(path.Ext(fileHeader.Filename)) if _, ok := plugin.DefaultFileTypeCheckMapping[plugin.UserAvatar][fileExt]; !ok { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) @@ -148,12 +150,12 @@ func (us *uploaderService) AvatarThumbFile(ctx *gin.Context, fileName string, si thumbFileName := fmt.Sprintf("%d_%d@%s", size, size, fileName) thumbFilePath := fmt.Sprintf("%s/%s/%s", us.serviceConfig.UploadPath, constant.AvatarThumbSubPath, thumbFileName) - avatarFile, err := os.ReadFile(thumbFilePath) + _, err = os.ReadFile(thumbFilePath) if err == nil { return thumbFilePath, nil } filePath := fmt.Sprintf("%s/%s/%s", us.serviceConfig.UploadPath, constant.AvatarSubPath, fileName) - avatarFile, err = os.ReadFile(filePath) + avatarFile, err := os.ReadFile(filePath) if err != nil { return "", errors.NotFound(reason.UnknownError).WithError(err) } @@ -179,7 +181,9 @@ func (us *uploaderService) AvatarThumbFile(ctx *gin.Context, fileName string, si if err != nil { return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack() } - defer out.Close() + defer func() { + _ = out.Close() + }() thumbReader := bytes.NewReader(buf.Bytes()) if _, err = io.Copy(out, thumbReader); err != nil { @@ -208,7 +212,9 @@ func (us *uploaderService) UploadPostFile(ctx *gin.Context, userID string) ( if err != nil { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) } - defer file.Close() + defer func() { + _ = file.Close() + }() if checker.IsUnAuthorizedExtension(fileHeader.Filename, siteWrite.AuthorizedImageExtensions) { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) } @@ -244,7 +250,9 @@ func (us *uploaderService) UploadPostAttachment(ctx *gin.Context, userID string) if err != nil { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) } - defer file.Close() + defer func() { + _ = file.Close() + }() if checker.IsUnAuthorizedExtension(fileHeader.Filename, resp.AuthorizedAttachmentExtensions) { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) } @@ -280,7 +288,9 @@ func (us *uploaderService) UploadBrandingFile(ctx *gin.Context, userID string) ( if err != nil { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) } - file.Close() + defer func() { + _ = file.Close() + }() fileExt := strings.ToLower(path.Ext(fileHeader.Filename)) if _, ok := plugin.DefaultFileTypeCheckMapping[plugin.AdminBranding][fileExt]; !ok { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) @@ -316,7 +326,9 @@ func (us *uploaderService) uploadImageFile(ctx *gin.Context, file *multipart.Fil if err != nil { return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack() } - defer src.Close() + defer func() { + _ = src.Close() + }() if !checker.DecodeAndCheckImageFile(filePath, siteWrite.GetMaxImageMegapixel()) { return "", errors.BadRequest(reason.UploadFileUnsupportedFileFormat) diff --git a/internal/service/user_admin/user_backyard.go b/internal/service/user_admin/user_backyard.go index 0f6ec81ed..6fce161ce 100644 --- a/internal/service/user_admin/user_backyard.go +++ b/internal/service/user_admin/user_backyard.go @@ -400,7 +400,7 @@ func (us *UserAdminService) EditUserProfile(ctx context.Context, req *schema.Edi if req.UserID == req.LoginUserID { return nil, errors.BadRequest(reason.AdminCannotEditTheirProfile) } - userInfo, exist, err := us.userRepo.GetUserInfo(ctx, req.UserID) + _, exist, err := us.userRepo.GetUserInfo(ctx, req.UserID) if err != nil { return nil, err } @@ -415,7 +415,7 @@ func (us *UserAdminService) EditUserProfile(ctx context.Context, req *schema.Edi }), errors.BadRequest(reason.UsernameInvalid) } - userInfo, exist, err = us.userCommonService.GetByUsername(ctx, req.Username) + userInfo, exist, err := us.userCommonService.GetByUsername(ctx, req.Username) if err != nil { return nil, err } @@ -620,11 +620,12 @@ func (us *UserAdminService) SendUserActivation(ctx context.Context, req *schema. } func (us *UserAdminService) DeletePermanently(ctx context.Context, req *schema.DeletePermanentlyReq) (err error) { - if req.Type == constant.DeletePermanentlyUsers { + switch req.Type { + case constant.DeletePermanentlyUsers: return us.userRepo.DeletePermanentlyUsers(ctx) - } else if req.Type == constant.DeletePermanentlyQuestions { + case constant.DeletePermanentlyQuestions: return us.questionCommonRepo.DeletePermanentlyQuestions(ctx) - } else if req.Type == constant.DeletePermanentlyAnswers { + case constant.DeletePermanentlyAnswers: return us.answerCommonRepo.DeletePermanentlyAnswers(ctx) } diff --git a/internal/service/user_notification_config/user_notification_config_service.go b/internal/service/user_notification_config/user_notification_config_service.go index 01da3ee2f..c40df55cf 100644 --- a/internal/service/user_notification_config/user_notification_config_service.go +++ b/internal/service/user_notification_config/user_notification_config_service.go @@ -68,21 +68,21 @@ func (us *UserNotificationConfigService) GetUserNotificationConfig(ctx context.C func (us *UserNotificationConfigService) UpdateUserNotificationConfig( ctx context.Context, req *schema.UpdateUserNotificationConfigReq) (err error) { - req.NotificationConfig.Format() + req.Format() err = us.userNotificationConfigRepo.Save(ctx, - us.convertToEntity(ctx, req.UserID, constant.InboxSource, req.NotificationConfig.Inbox)) + us.convertToEntity(ctx, req.UserID, constant.InboxSource, req.Inbox)) if err != nil { return err } err = us.userNotificationConfigRepo.Save(ctx, - us.convertToEntity(ctx, req.UserID, constant.AllNewQuestionSource, req.NotificationConfig.AllNewQuestion)) + us.convertToEntity(ctx, req.UserID, constant.AllNewQuestionSource, req.AllNewQuestion)) if err != nil { return err } err = us.userNotificationConfigRepo.Save(ctx, us.convertToEntity(ctx, req.UserID, constant.AllNewQuestionForFollowingTagsSource, - req.NotificationConfig.AllNewQuestionForFollowingTags)) + req.AllNewQuestionForFollowingTags)) if err != nil { return err } diff --git a/pkg/checker/file_type.go b/pkg/checker/file_type.go index 51f687d6c..ac1fbcaf9 100644 --- a/pkg/checker/file_type.go +++ b/pkg/checker/file_type.go @@ -75,7 +75,9 @@ func decodeAndCheckImageFile(localFilePath string, maxImageMegapixel int, checke log.Errorf("open file error: %v", err) return false } - defer file.Close() + defer func() { + _ = file.Close() + }() if err = checker(file, maxImageMegapixel); err != nil { log.Errorf("check image format error: %v", err) diff --git a/pkg/checker/password.go b/pkg/checker/password.go index ac274f352..ac99fd433 100644 --- a/pkg/checker/password.go +++ b/pkg/checker/password.go @@ -20,6 +20,7 @@ package checker import ( + "errors" "fmt" "regexp" "strings" @@ -40,7 +41,7 @@ const ( // CheckPassword checks the password strength func CheckPassword(password string) error { if strings.Contains(password, " ") { - return fmt.Errorf(PasswordCannotContainSpaces) + return errors.New(PasswordCannotContainSpaces) } // TODO Currently there is no requirement for password strength diff --git a/pkg/converter/markdown.go b/pkg/converter/markdown.go index 1789a32cd..d16915a84 100644 --- a/pkg/converter/markdown.go +++ b/pkg/converter/markdown.go @@ -32,7 +32,6 @@ import ( "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" "github.com/yuin/goldmark/renderer" - "github.com/yuin/goldmark/renderer/html" goldmarkHTML "github.com/yuin/goldmark/renderer/html" "github.com/yuin/goldmark/util" ) @@ -141,7 +140,7 @@ func (r *DangerousHTMLRenderer) renderLink(w util.BufWriter, source []byte, node if entering && r.renderLinkIsUrl(string(n.Destination)) { _, _ = w.WriteString("') } else { @@ -175,7 +174,7 @@ func (r *DangerousHTMLRenderer) renderAutoLink(w util.BufWriter, source []byte, _, _ = w.Write(util.EscapeHTML(util.URLEscape(url, false))) if n.Attributes() != nil { _ = w.WriteByte('"') - html.RenderAttributes(w, n, html.LinkAttributeFilter) + goldmarkHTML.RenderAttributes(w, n, goldmarkHTML.LinkAttributeFilter) _ = w.WriteByte('>') } else { _, _ = w.WriteString(`">`) diff --git a/pkg/htmltext/htmltext.go b/pkg/htmltext/htmltext.go index 707c20a80..56db4d2b2 100644 --- a/pkg/htmltext/htmltext.go +++ b/pkg/htmltext/htmltext.go @@ -194,7 +194,9 @@ func GetPicByUrl(Url string) string { if err != nil { return "" } - defer res.Body.Close() + defer func() { + _ = res.Body.Close() + }() pix, err := io.ReadAll(res.Body) if err != nil { return "" diff --git a/plugin/kv_storage.go b/plugin/kv_storage.go index d1ed3eaa6..204e5ee68 100644 --- a/plugin/kv_storage.go +++ b/plugin/kv_storage.go @@ -88,7 +88,7 @@ func (kv *KVOperator) getSession(ctx context.Context) (*xorm.Session, func()) { session = kv.data.DB.NewSession().Context(ctx) cleanup = func() { if session != nil { - session.Close() + _ = session.Close() } } } @@ -281,7 +281,7 @@ func (kv *KVOperator) Tx(ctx context.Context, fn func(ctx context.Context, kv *K if kv.session == nil { session := kv.data.DB.NewSession().Context(ctx) if err := session.Begin(); err != nil { - session.Close() + _ = session.Close() return fmt.Errorf("%w: begin transaction failed: %v", ErrKVTransactionFailed, err) } @@ -291,7 +291,7 @@ func (kv *KVOperator) Tx(ctx context.Context, fn func(ctx context.Context, kv *K log.Errorf("rollback failed: %v", rollbackErr) } } - session.Close() + _ = session.Close() }() txKv = &KVOperator{ diff --git a/plugin/plugin_test/plugin_main_test.go b/plugin/plugin_test/plugin_main_test.go index add11460b..fd9015c86 100644 --- a/plugin/plugin_test/plugin_main_test.go +++ b/plugin/plugin_test/plugin_main_test.go @@ -78,7 +78,7 @@ func TestMain(t *testing.M) { dbSetting = dbSettingMapping[string(schemas.SQLITE)] } if dbSetting.Driver == string(schemas.SQLITE) { - os.RemoveAll(dbSetting.Connection) + _ = os.RemoveAll(dbSetting.Connection) } defer func() { diff --git a/ui/static.go b/ui/static.go index dc79a1785..65caae461 100644 --- a/ui/static.go +++ b/ui/static.go @@ -21,7 +21,6 @@ package ui import ( "embed" - _ "embed" ) //go:embed build From 670aa323254ca8f2a5d3927353afb83b7724e424 Mon Sep 17 00:00:00 2001 From: ferhat elmas Date: Mon, 1 Dec 2025 21:22:18 +0100 Subject: [PATCH 14/25] refactor(lint): add new linters and fix their issues * gocritic * misspell * modernize (aside, bumping go would be nice) * testifylint * unconvert * unparam * whitespace related to #1432 Signed-off-by: ferhat elmas --- .golangci.yaml | 7 +++ i18n/cs_CZ.yaml | 2 +- i18n/cy_GB.yaml | 2 +- i18n/da_DK.yaml | 2 +- i18n/de_DE.yaml | 2 +- i18n/en_US.yaml | 2 +- i18n/es_ES.yaml | 2 +- i18n/fa_IR.yaml | 2 +- i18n/fr_FR.yaml | 2 +- i18n/hi_IN.yaml | 2 +- i18n/id_ID.yaml | 2 +- i18n/it_IT.yaml | 2 +- i18n/ja_JP.yaml | 2 +- i18n/ko_KR.yaml | 2 +- i18n/ml_IN.yaml | 2 +- i18n/pl_PL.yaml | 2 +- i18n/pt_PT.yaml | 2 +- i18n/ro_RO.yaml | 2 +- i18n/ru_RU.yaml | 2 +- i18n/sk_SK.yaml | 2 +- i18n/sv_SE.yaml | 10 ++-- i18n/te_IN.yaml | 2 +- i18n/tr_TR.yaml | 2 +- i18n/uk_UA.yaml | 2 +- i18n/vi_VN.yaml | 2 +- i18n/zh_CN.yaml | 2 +- i18n/zh_TW.yaml | 2 +- internal/base/middleware/avatar.go | 1 - internal/base/reason/reason.go | 2 +- internal/base/server/http.go | 1 - internal/base/server/http_funcmap.go | 4 +- internal/controller/question_controller.go | 3 +- internal/controller/template_controller.go | 8 +-- .../controller/template_render/comment.go | 1 - .../controller/template_render/controller.go | 10 ++-- internal/controller/user_controller.go | 1 - internal/entity/collection_entity.go | 4 +- internal/install/install_req.go | 9 +-- internal/migrations/v12.go | 1 - internal/migrations/v13.go | 4 +- internal/repo/activity/follow_repo.go | 2 +- internal/repo/activity_common/follow.go | 6 +- internal/repo/answer/answer_repo.go | 2 +- internal/repo/collection/collection_repo.go | 4 +- internal/repo/question/question_repo.go | 8 +-- internal/repo/rank/user_rank_repo.go | 2 +- internal/repo/repo_test/auth_test.go | 31 +++++----- internal/repo/repo_test/captcha_test.go | 11 ++-- internal/repo/repo_test/comment_repo_test.go | 27 ++++----- internal/repo/repo_test/email_repo_test.go | 5 +- internal/repo/repo_test/meta_repo_test.go | 31 +++++----- .../repo/repo_test/notification_repo_test.go | 33 ++++++----- internal/repo/repo_test/reason_repo_test.go | 5 +- internal/repo/repo_test/recommend_test.go | 27 ++++----- internal/repo/repo_test/repo_main_test.go | 2 +- internal/repo/repo_test/revision_repo_test.go | 17 +++--- internal/repo/repo_test/siteinfo_repo_test.go | 9 +-- internal/repo/repo_test/tag_rel_repo_test.go | 25 ++++---- internal/repo/repo_test/tag_repo_test.go | 33 ++++++----- .../repo/repo_test/user_backyard_repo_test.go | 15 ++--- internal/repo/repo_test/user_repo_test.go | 35 +++++------ internal/repo/search_common/search_repo.go | 4 +- internal/schema/backyard_user_schema.go | 2 +- internal/schema/meta_schema.go | 16 ++--- internal/schema/notification_schema.go | 6 +- internal/schema/revision_schema.go | 2 +- internal/schema/siteinfo_schema.go | 2 +- internal/schema/tag_schema.go | 2 +- internal/service/action/captcha_strategy.go | 21 ++++--- internal/service/auth/auth.go | 2 +- internal/service/comment/comment_service.go | 15 +++-- internal/service/content/answer_service.go | 13 ++--- .../content/question_hottest_service.go | 1 - internal/service/content/question_service.go | 58 ++++++++----------- internal/service/content/revision_service.go | 1 - internal/service/content/search_service.go | 14 +++-- internal/service/content/user_service.go | 7 +-- .../service/dashboard/dashboard_service.go | 18 +++--- .../invite_answer_notification.go | 3 +- .../notification/new_answer_notification.go | 3 +- .../notification/new_comment_notification.go | 3 +- .../notification/new_question_notification.go | 3 +- .../notification/notification_service.go | 13 ++--- .../notification_common/notification.go | 2 +- .../plugin_common/plugin_common_service.go | 1 - internal/service/question_common/question.go | 11 ++-- .../siteinfo_common/siteinfo_service_test.go | 5 +- internal/service/tag/tag_service.go | 4 +- internal/service/tag_common/tag_common.go | 8 +-- internal/service/uploader/upload.go | 2 - internal/service/user_admin/user_backyard.go | 23 ++++---- internal/service/user_common/user.go | 4 +- .../user_notification_config_service.go | 2 +- pkg/checker/file_type.go | 8 +-- pkg/checker/path_ignore.go | 15 +---- pkg/checker/question_link.go | 11 ++-- pkg/converter/markdown.go | 18 +++--- pkg/day/day.go | 7 ++- pkg/dir/dir.go | 16 ++--- pkg/htmltext/htmltext.go | 14 ++--- pkg/htmltext/htmltext_test.go | 4 +- plugin/plugin_test/plugin_main_test.go | 13 ++--- 102 files changed, 392 insertions(+), 431 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 611b49bc2..09fca51c5 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -29,6 +29,13 @@ linters: - bodyclose # checks whether HTTP response body is closed successfully - canonicalheader # checks whether net/http.Header uses canonical header - copyloopvar # detects places where loop variables are copied (Go 1.22+) + - gocritic # provides diagnostics that check for bugs, performance and style issues + - misspell # finds commonly misspelled English words in comments and strings + - modernize # detects code that can be modernized to use newer Go features + - testifylint # checks usage of github.com/stretchr/testify + - unconvert # removes unnecessary type conversions + - unparam # reports unused function parameters + - whitespace # detects leading and trailing whitespace formatters: enable: diff --git a/i18n/cs_CZ.yaml b/i18n/cs_CZ.yaml index d9f972a63..ab53cb635 100644 --- a/i18n/cs_CZ.yaml +++ b/i18n/cs_CZ.yaml @@ -234,7 +234,7 @@ backend: other: Nemáte oprávnění pro aktualizaci. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/cy_GB.yaml b/i18n/cy_GB.yaml index 267070a08..5a5b9a654 100644 --- a/i18n/cy_GB.yaml +++ b/i18n/cy_GB.yaml @@ -234,7 +234,7 @@ backend: other: Dim caniatâd i ddiweddaru. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/da_DK.yaml b/i18n/da_DK.yaml index d3f410e45..37adc7db0 100644 --- a/i18n/da_DK.yaml +++ b/i18n/da_DK.yaml @@ -234,7 +234,7 @@ backend: other: Ingen tilladelse til at opdatere. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/de_DE.yaml b/i18n/de_DE.yaml index d7683f03b..542dca9b8 100644 --- a/i18n/de_DE.yaml +++ b/i18n/de_DE.yaml @@ -234,7 +234,7 @@ backend: other: Keine Berechtigung zum Aktualisieren. content_cannot_empty: other: Der Inhalt darf nicht leer sein. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/en_US.yaml b/i18n/en_US.yaml index 40017b75a..6ff6ef3c6 100644 --- a/i18n/en_US.yaml +++ b/i18n/en_US.yaml @@ -235,7 +235,7 @@ backend: other: No permission to update. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/es_ES.yaml b/i18n/es_ES.yaml index 99071e2fe..f53a2810c 100644 --- a/i18n/es_ES.yaml +++ b/i18n/es_ES.yaml @@ -234,7 +234,7 @@ backend: other: Sin permiso para actualizar. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/fa_IR.yaml b/i18n/fa_IR.yaml index 600d5cc11..d013d0172 100644 --- a/i18n/fa_IR.yaml +++ b/i18n/fa_IR.yaml @@ -234,7 +234,7 @@ backend: other: اجازه بروزرسانی ندارید. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/fr_FR.yaml b/i18n/fr_FR.yaml index ecb87bef1..879906fa5 100644 --- a/i18n/fr_FR.yaml +++ b/i18n/fr_FR.yaml @@ -234,7 +234,7 @@ backend: other: Pas de permission pour mettre à jour. content_cannot_empty: other: Le contenu ne peut pas être vide. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/hi_IN.yaml b/i18n/hi_IN.yaml index 09be62019..eb0cb50bd 100644 --- a/i18n/hi_IN.yaml +++ b/i18n/hi_IN.yaml @@ -234,7 +234,7 @@ backend: other: No permission to update. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/id_ID.yaml b/i18n/id_ID.yaml index f8a4a8a88..43c0d70d1 100644 --- a/i18n/id_ID.yaml +++ b/i18n/id_ID.yaml @@ -234,7 +234,7 @@ backend: other: Tidak diizinkan untuk memperbarui. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/it_IT.yaml b/i18n/it_IT.yaml index 29cd1f521..50f60aa6a 100644 --- a/i18n/it_IT.yaml +++ b/i18n/it_IT.yaml @@ -234,7 +234,7 @@ backend: other: Nessun permesso per l'aggiornamento. content_cannot_empty: other: Il contenuto non può essere vuoto. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/ja_JP.yaml b/i18n/ja_JP.yaml index 8e2fb52c3..4bfe45c97 100644 --- a/i18n/ja_JP.yaml +++ b/i18n/ja_JP.yaml @@ -234,7 +234,7 @@ backend: other: 更新する権限がありません。 content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/ko_KR.yaml b/i18n/ko_KR.yaml index be1807457..0ddefa61f 100644 --- a/i18n/ko_KR.yaml +++ b/i18n/ko_KR.yaml @@ -234,7 +234,7 @@ backend: other: 업데이트 권한이 없습니다. content_cannot_empty: other: 내용은 비워둘 수 없습니다. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/ml_IN.yaml b/i18n/ml_IN.yaml index 421350311..e2cac0e0b 100644 --- a/i18n/ml_IN.yaml +++ b/i18n/ml_IN.yaml @@ -234,7 +234,7 @@ backend: other: No permission to update. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/pl_PL.yaml b/i18n/pl_PL.yaml index ae26c6d1a..e5972d9b3 100644 --- a/i18n/pl_PL.yaml +++ b/i18n/pl_PL.yaml @@ -234,7 +234,7 @@ backend: other: Brak uprawnień do edycji. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/pt_PT.yaml b/i18n/pt_PT.yaml index 997bb0552..5989071e8 100644 --- a/i18n/pt_PT.yaml +++ b/i18n/pt_PT.yaml @@ -234,7 +234,7 @@ backend: other: Sem permissão para atualizar. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/ro_RO.yaml b/i18n/ro_RO.yaml index cd0afb8a3..43af2180b 100644 --- a/i18n/ro_RO.yaml +++ b/i18n/ro_RO.yaml @@ -234,7 +234,7 @@ backend: other: Nu aveți permisiunea de a actualiza. content_cannot_empty: other: Conținutul nu poate fi gol. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/ru_RU.yaml b/i18n/ru_RU.yaml index c554ac8d7..458fd2e66 100644 --- a/i18n/ru_RU.yaml +++ b/i18n/ru_RU.yaml @@ -234,7 +234,7 @@ backend: other: Нет разрешения на обновление. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/sk_SK.yaml b/i18n/sk_SK.yaml index 72bd4726e..cd629fc94 100644 --- a/i18n/sk_SK.yaml +++ b/i18n/sk_SK.yaml @@ -234,7 +234,7 @@ backend: other: Žiadne povolenie na aktualizáciu. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/sv_SE.yaml b/i18n/sv_SE.yaml index 243703ce0..abf58112d 100644 --- a/i18n/sv_SE.yaml +++ b/i18n/sv_SE.yaml @@ -162,7 +162,7 @@ backend: cannot_modify_self_status: other: Du får inte ändra din status. email_or_password_wrong: - other: Fel e-post eller lösenord. + other: Fel e-post eller lösenord. answer: not_found: other: Svar hittades inte. @@ -189,12 +189,12 @@ backend: need_to_be_verified: other: E-postadressen ska vara verifierad. verify_url_expired: - other: Länken för att verifiera e-postadressen har gått ut. Vänligen skicka igen. + other: Länken för att verifiera e-postadressen har gått ut. Vänligen skicka igen. illegal_email_domain_error: - other: E-post från den domänen tillåts inte. Vänligen använt en annan. + other: E-post från den domänen tillåts inte. Vänligen använt en annan. lang: not_found: - other: Språkfilen hittas inte. + other: Språkfilen hittas inte. object: captcha_verification_failed: other: Fel Captcha. @@ -234,7 +234,7 @@ backend: other: No permission to update. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/te_IN.yaml b/i18n/te_IN.yaml index dbf4acb14..9e80aa8d8 100644 --- a/i18n/te_IN.yaml +++ b/i18n/te_IN.yaml @@ -234,7 +234,7 @@ backend: other: No permission to update. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/tr_TR.yaml b/i18n/tr_TR.yaml index fdecee532..92d97ebe2 100644 --- a/i18n/tr_TR.yaml +++ b/i18n/tr_TR.yaml @@ -234,7 +234,7 @@ backend: other: Güncelleme izni yok. content_cannot_empty: other: İçerik boş olamaz. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/uk_UA.yaml b/i18n/uk_UA.yaml index ea0e4591c..67496262a 100644 --- a/i18n/uk_UA.yaml +++ b/i18n/uk_UA.yaml @@ -234,7 +234,7 @@ backend: other: Немає дозволу на оновлення. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/vi_VN.yaml b/i18n/vi_VN.yaml index 6f5e5cbbb..af01b1da4 100644 --- a/i18n/vi_VN.yaml +++ b/i18n/vi_VN.yaml @@ -234,7 +234,7 @@ backend: other: Không có quyền cập nhật. content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/i18n/zh_CN.yaml b/i18n/zh_CN.yaml index 0f7a25154..35321ac1f 100644 --- a/i18n/zh_CN.yaml +++ b/i18n/zh_CN.yaml @@ -234,7 +234,7 @@ backend: other: 没有更新权限。 content_cannot_empty: other: 内容不能为空。 - content_less_than_minumum: + content_less_than_minimum: other: 输入的内容不足。 rank: fail_to_meet_the_condition: diff --git a/i18n/zh_TW.yaml b/i18n/zh_TW.yaml index cc362ea1e..4b239c1e1 100644 --- a/i18n/zh_TW.yaml +++ b/i18n/zh_TW.yaml @@ -234,7 +234,7 @@ backend: other: 無更新權限。 content_cannot_empty: other: Content cannot be empty. - content_less_than_minumum: + content_less_than_minimum: other: Not enough content entered. rank: fail_to_meet_the_condition: diff --git a/internal/base/middleware/avatar.go b/internal/base/middleware/avatar.go index 98430638b..42b28da99 100644 --- a/internal/base/middleware/avatar.go +++ b/internal/base/middleware/avatar.go @@ -80,7 +80,6 @@ func (am *AvatarMiddleware) AvatarThumb() gin.HandlerFunc { } ctx.Abort() return - } else { urlInfo, err := url.Parse(uri) if err != nil { diff --git a/internal/base/reason/reason.go b/internal/base/reason/reason.go index 42e29f4c5..97aaa75a9 100644 --- a/internal/base/reason/reason.go +++ b/internal/base/reason/reason.go @@ -47,7 +47,7 @@ const ( QuestionAlreadyDeleted = "error.question.already_deleted" QuestionUnderReview = "error.question.under_review" QuestionContentCannotEmpty = "error.question.content_cannot_empty" - QuestionContentLessThanMinimum = "error.question.content_less_than_minumum" + QuestionContentLessThanMinimum = "error.question.content_less_than_minimum" AnswerNotFound = "error.answer.not_found" AnswerCannotDeleted = "error.answer.cannot_deleted" AnswerCannotUpdate = "error.answer.cannot_update" diff --git a/internal/base/server/http.go b/internal/base/server/http.go index 088bbc9e4..4fbb04cb2 100644 --- a/internal/base/server/http.go +++ b/internal/base/server/http.go @@ -44,7 +44,6 @@ func NewHTTPServer(debug bool, pluginAPIRouter *router.PluginAPIRouter, uiConf *UI, ) *gin.Engine { - if debug { gin.SetMode(gin.DebugMode) } else { diff --git a/internal/base/server/http_funcmap.go b/internal/base/server/http_funcmap.go index db4604572..a5d530b50 100644 --- a/internal/base/server/http_funcmap.go +++ b/internal/base/server/http_funcmap.go @@ -134,9 +134,7 @@ var funcMap = template.FuncMap{ "timezone": tz, } }, - "urlTitle": func(title string) string { - return htmltext.UrlTitle(title) - }, + "urlTitle": htmltext.UrlTitle, } func FormatLinkNofollow(html string) string { diff --git a/internal/controller/question_controller.go b/internal/controller/question_controller.go index 4b1869fa7..581cf548b 100644 --- a/internal/controller/question_controller.go +++ b/internal/controller/question_controller.go @@ -287,7 +287,6 @@ func (qc *QuestionController) GetQuestionInviteUserInfo(ctx *gin.Context) { questionID := uid.DeShortID(ctx.Query("id")) resp, err := qc.questionService.InviteUserInfo(ctx, questionID) handler.HandleResponse(ctx, err, resp) - } // SimilarQuestion godoc @@ -578,7 +577,7 @@ func (qc *QuestionController) AddQuestionByAnswer(ctx *gin.Context) { handler.HandleResponse(ctx, errors.BadRequest(reason.RequestFormatError), errFields) return } - //add the question id to the answer + // add the question id to the answer questionInfo, ok := resp.(*schema.QuestionInfoResp) if ok { answerReq := &schema.AnswerAddReq{} diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index 801e129c2..f6a442c21 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -263,14 +263,13 @@ func (tc *TemplateController) QuestionInfoRedirect(ctx *gin.Context, siteInfo *s if needChangeShortID { return true, url } - //not have title + // not have title if titleIsAnswerID || len(title) == 0 { return false, "" } return true, url } else { - detail, err := tc.templateRenderController.QuestionDetail(ctx, questionID) if err != nil { tc.Page404(ctx) @@ -284,7 +283,7 @@ func (tc *TemplateController) QuestionInfoRedirect(ctx *gin.Context, siteInfo *s if len(ctx.Request.URL.Query()) > 0 { url = fmt.Sprintf("%s?%s", url, ctx.Request.URL.RawQuery) } - //have title + // have title if len(title) > 0 && !titleIsAnswerID && correctTitle { if needChangeShortID { return true, url @@ -370,7 +369,7 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) { UrlUseTitle := siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID - //related question + // related question userID := middleware.GetLoginUserIDFromContext(ctx) relatedQuestion, _, _ := tc.questionService.SimilarQuestion(ctx, id, userID) @@ -553,7 +552,6 @@ func (tc *TemplateController) UserInfo(ctx *gin.Context) { "topQuestions": questionList, "topAnswers": answerList, }) - } func (tc *TemplateController) Page404(ctx *gin.Context) { diff --git a/internal/controller/template_render/comment.go b/internal/controller/template_render/comment.go index 2862ad8dd..c1265bd05 100644 --- a/internal/controller/template_render/comment.go +++ b/internal/controller/template_render/comment.go @@ -33,7 +33,6 @@ func (t *TemplateRenderController) CommentList( comments map[string][]*schema.GetCommentResp, err error, ) { - comments = make(map[string][]*schema.GetCommentResp, len(objectIDs)) for _, objectID := range objectIDs { diff --git a/internal/controller/template_render/controller.go b/internal/controller/template_render/controller.go index 3412010db..297b3f9a6 100644 --- a/internal/controller/template_render/controller.go +++ b/internal/controller/template_render/controller.go @@ -78,10 +78,10 @@ func Paginator(page, pageSize int, nums int64) *schema.Paginator { pageSize = 10 } - var prevpage int //Previous page address - var nextpage int //Address on the last page - //Generate the total number of pages based on the total number of nums and the number of prepage pages - totalpages := int(math.Ceil(float64(nums) / float64(pageSize))) //Total number of Pages + var prevpage int // Previous page address + var nextpage int // Address on the last page + // Generate the total number of pages based on the total number of nums and the number of prepage pages + totalpages := int(math.Ceil(float64(nums) / float64(pageSize))) // Total number of Pages if page > totalpages { page = totalpages } @@ -90,7 +90,7 @@ func Paginator(page, pageSize int, nums int64) *schema.Paginator { } var pages []int switch { - case page >= totalpages-5 && totalpages > 5: //The last 5 pages + case page >= totalpages-5 && totalpages > 5: // The last 5 pages start := totalpages - 5 + 1 prevpage = page - 1 nextpage = int(math.Min(float64(totalpages), float64(page+1))) diff --git a/internal/controller/user_controller.go b/internal/controller/user_controller.go index e4a3b3d3b..cc89caf1a 100644 --- a/internal/controller/user_controller.go +++ b/internal/controller/user_controller.go @@ -509,7 +509,6 @@ func (uc *UserController) ActionRecord(ctx *gin.Context) { resp, err := uc.actionService.ActionRecord(ctx, req) handler.HandleResponse(ctx, err, resp) } - } // GetUserNotificationConfig get user's notification config diff --git a/internal/entity/collection_entity.go b/internal/entity/collection_entity.go index 5fbd5b0eb..24ae232f4 100644 --- a/internal/entity/collection_entity.go +++ b/internal/entity/collection_entity.go @@ -33,8 +33,8 @@ type Collection struct { type CollectionSearch struct { Collection - Page int `json:"page" form:"page"` //Query number of pages - PageSize int `json:"page_size" form:"page_size"` //Search page size + Page int `json:"page" form:"page"` // Query number of pages + PageSize int `json:"page_size" form:"page_size"` // Search page size } // TableName collection table name diff --git a/internal/install/install_req.go b/internal/install/install_req.go index e5b8839e9..39657a546 100644 --- a/internal/install/install_req.go +++ b/internal/install/install_req.go @@ -65,13 +65,14 @@ func (r *CheckDatabaseReq) GetConnection() string { } if r.DbType == string(schemas.POSTGRES) { host, port := parsePgSQLHostPort(r.DbHost) - if !r.Ssl { + switch { + case !r.Ssl: return fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", host, port, r.DbUsername, r.DbPassword, r.DbName) - } else if r.SslMode == "require" { + case r.SslMode == "require": return fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s", host, port, r.DbUsername, r.DbPassword, r.DbName, r.SslMode) - } else if r.SslMode == "verify-ca" || r.SslMode == "verify-full" { + case r.SslMode == "verify-ca" || r.SslMode == "verify-full": connection := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s", host, port, r.DbUsername, r.DbPassword, r.DbName, r.SslMode) if len(r.SslRootCert) > 0 && dir.CheckFileExist(r.SslRootCert) { @@ -150,7 +151,7 @@ func (r *InitBaseInfoReq) FormatSiteUrl() { } r.SiteURL = fmt.Sprintf("%s://%s", parsedUrl.Scheme, parsedUrl.Host) if len(parsedUrl.Path) > 0 { - r.SiteURL = r.SiteURL + parsedUrl.Path + r.SiteURL += parsedUrl.Path r.SiteURL = strings.TrimSuffix(r.SiteURL, "/") } } diff --git a/internal/migrations/v12.go b/internal/migrations/v12.go index 2dd3ce71e..23e8acdcd 100644 --- a/internal/migrations/v12.go +++ b/internal/migrations/v12.go @@ -75,7 +75,6 @@ func updateQuestionPostTime(ctx context.Context, x *xorm.Engine) error { return fmt.Errorf("update question failed: %w", err) } } - } return nil diff --git a/internal/migrations/v13.go b/internal/migrations/v13.go index 57d248482..16ba177e8 100644 --- a/internal/migrations/v13.go +++ b/internal/migrations/v13.go @@ -136,7 +136,7 @@ func addPrivilegeForInviteSomeoneToAnswer(ctx context.Context, x *xorm.Engine) e } func updateQuestionCount(ctx context.Context, x *xorm.Engine) error { - //question answer count + // question answer count answers := make([]AnswerV13, 0) err := x.Context(ctx).Find(&answers, &AnswerV13{Status: entity.AnswerStatusAvailable}) if err != nil { @@ -216,7 +216,7 @@ func updateTagCount(ctx context.Context, x *xorm.Engine) error { } } - //select tag count + // select tag count newTagRelList := make([]entity.TagRel, 0) err = x.Context(ctx).Find(&newTagRelList, &entity.TagRel{Status: entity.TagRelStatusAvailable}) if err != nil { diff --git a/internal/repo/activity/follow_repo.go b/internal/repo/activity/follow_repo.go index 7af2189a6..4c6fc431b 100644 --- a/internal/repo/activity/follow_repo.go +++ b/internal/repo/activity/follow_repo.go @@ -168,7 +168,7 @@ func (ar *FollowRepo) FollowCancel(ctx context.Context, objectID, userID string) return err } -func (ar *FollowRepo) updateFollows(ctx context.Context, session *xorm.Session, objectID string, follows int) error { +func (ar *FollowRepo) updateFollows(_ context.Context, session *xorm.Session, objectID string, follows int) error { objectType, err := obj.GetObjectTypeStrByObjectID(objectID) if err != nil { return err diff --git a/internal/repo/activity_common/follow.go b/internal/repo/activity_common/follow.go index 99e5a6e67..a185c3d8a 100644 --- a/internal/repo/activity_common/follow.go +++ b/internal/repo/activity_common/follow.go @@ -66,19 +66,19 @@ func (ar *FollowRepo) GetFollowAmount(ctx context.Context, objectID string) (fol model := &entity.Question{} _, err = ar.data.DB.Context(ctx).Where("id = ?", objectID).Cols("`follow_count`").Get(model) if err == nil { - follows = int(model.FollowCount) + follows = model.FollowCount } case "user": model := &entity.User{} _, err = ar.data.DB.Context(ctx).Where("id = ?", objectID).Cols("`follow_count`").Get(model) if err == nil { - follows = int(model.FollowCount) + follows = model.FollowCount } case "tag": model := &entity.Tag{} _, err = ar.data.DB.Context(ctx).Where("id = ?", objectID).Cols("`follow_count`").Get(model) if err == nil { - follows = int(model.FollowCount) + follows = model.FollowCount } default: err = errors.InternalServer(reason.DisallowFollow).WithMsg("this object can't be followed") diff --git a/internal/repo/answer/answer_repo.go b/internal/repo/answer/answer_repo.go index 0f1ae8146..52963c44c 100644 --- a/internal/repo/answer/answer_repo.go +++ b/internal/repo/answer/answer_repo.go @@ -335,7 +335,7 @@ func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearc var err error rows := make([]*entity.Answer, 0) if search.Page > 0 { - search.Page = search.Page - 1 + search.Page-- } else { search.Page = 0 } diff --git a/internal/repo/collection/collection_repo.go b/internal/repo/collection/collection_repo.go index f30692c97..482cb075d 100644 --- a/internal/repo/collection/collection_repo.go +++ b/internal/repo/collection/collection_repo.go @@ -167,7 +167,7 @@ func (cr *collectionRepo) GetCollectionPage(ctx context.Context, page, pageSize // SearchObjectCollected check object is collected or not func (cr *collectionRepo) SearchObjectCollected(ctx context.Context, userID string, objectIds []string) (map[string]bool, error) { - for i := 0; i < len(objectIds); i++ { + for i := range objectIds { objectIds[i] = uid.DeShortID(objectIds[i]) } @@ -193,7 +193,7 @@ func (cr *collectionRepo) SearchList(ctx context.Context, search *entity.Collect var err error rows := make([]*entity.Collection, 0) if search.Page > 0 { - search.Page = search.Page - 1 + search.Page-- } else { search.Page = 0 } diff --git a/internal/repo/question/question_repo.go b/internal/repo/question/question_repo.go index 3935e6102..3449efb8b 100644 --- a/internal/repo/question/question_repo.go +++ b/internal/repo/question/question_repo.go @@ -89,9 +89,9 @@ func (qr *questionRepo) RemoveQuestion(ctx context.Context, id string) (err erro } // UpdateQuestion update question -func (qr *questionRepo) UpdateQuestion(ctx context.Context, question *entity.Question, Cols []string) (err error) { +func (qr *questionRepo) UpdateQuestion(ctx context.Context, question *entity.Question, cols []string) (err error) { question.ID = uid.DeShortID(question.ID) - _, err = qr.data.DB.Context(ctx).Where("id =?", question.ID).Cols(Cols...).Update(question) + _, err = qr.data.DB.Context(ctx).Where("id =?", question.ID).Cols(cols...).Update(question) if err != nil { return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } @@ -344,7 +344,7 @@ func (qr *questionRepo) GetUserQuestionCount(ctx context.Context, userID string, func (qr *questionRepo) SitemapQuestions(ctx context.Context, page, pageSize int) ( questionIDList []*schema.SiteMapQuestionInfo, err error) { - page = page - 1 + page-- questionIDList = make([]*schema.SiteMapQuestionInfo, 0) // try to get sitemap data from cache @@ -524,7 +524,7 @@ func (qr *questionRepo) AdminQuestionPage(ctx context.Context, search *schema.Ad rows := make([]*entity.Question, 0) if search.Page > 0 { - search.Page = search.Page - 1 + search.Page-- } else { search.Page = 0 } diff --git a/internal/repo/rank/user_rank_repo.go b/internal/repo/rank/user_rank_repo.go index cb9ca1b3d..5e86f5929 100644 --- a/internal/repo/rank/user_rank_repo.go +++ b/internal/repo/rank/user_rank_repo.go @@ -141,7 +141,7 @@ func (ur *UserRankRepo) TriggerUserRank(ctx context.Context, return false, nil } -func (ur *UserRankRepo) checkUserMinRank(ctx context.Context, session *xorm.Session, userID string, deltaRank int) ( +func (ur *UserRankRepo) checkUserMinRank(_ context.Context, session *xorm.Session, userID string, deltaRank int) ( isReachStandard bool, err error, ) { bean := &entity.User{ID: userID} diff --git a/internal/repo/repo_test/auth_test.go b/internal/repo/repo_test/auth_test.go index 387332399..0c9919020 100644 --- a/internal/repo/repo_test/auth_test.go +++ b/internal/repo/repo_test/auth_test.go @@ -26,6 +26,7 @@ import ( "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/repo/auth" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var ( @@ -38,10 +39,10 @@ func Test_authRepo_SetUserCacheInfo(t *testing.T) { authRepo := auth.NewAuthRepo(testDataSource) err := authRepo.SetUserCacheInfo(context.TODO(), accessToken, visitToken, &entity.UserCacheInfo{UserID: userID}) - assert.NoError(t, err) + require.NoError(t, err) cacheInfo, err := authRepo.GetUserCacheInfo(context.TODO(), accessToken) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, userID, cacheInfo.UserID) } @@ -49,13 +50,13 @@ func Test_authRepo_RemoveUserCacheInfo(t *testing.T) { authRepo := auth.NewAuthRepo(testDataSource) err := authRepo.SetUserCacheInfo(context.TODO(), accessToken, visitToken, &entity.UserCacheInfo{UserID: userID}) - assert.NoError(t, err) + require.NoError(t, err) err = authRepo.RemoveUserCacheInfo(context.TODO(), accessToken) - assert.NoError(t, err) + require.NoError(t, err) userInfo, err := authRepo.GetUserCacheInfo(context.TODO(), accessToken) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, userInfo) } @@ -63,23 +64,23 @@ func Test_authRepo_SetUserStatus(t *testing.T) { authRepo := auth.NewAuthRepo(testDataSource) err := authRepo.SetUserStatus(context.TODO(), userID, &entity.UserCacheInfo{UserID: userID}) - assert.NoError(t, err) + require.NoError(t, err) cacheInfo, err := authRepo.GetUserStatus(context.TODO(), userID) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, userID, cacheInfo.UserID) } func Test_authRepo_RemoveUserStatus(t *testing.T) { authRepo := auth.NewAuthRepo(testDataSource) err := authRepo.SetUserStatus(context.TODO(), userID, &entity.UserCacheInfo{UserID: userID}) - assert.NoError(t, err) + require.NoError(t, err) err = authRepo.RemoveUserStatus(context.TODO(), userID) - assert.NoError(t, err) + require.NoError(t, err) userInfo, err := authRepo.GetUserStatus(context.TODO(), userID) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, userInfo) } @@ -87,10 +88,10 @@ func Test_authRepo_SetAdminUserCacheInfo(t *testing.T) { authRepo := auth.NewAuthRepo(testDataSource) err := authRepo.SetAdminUserCacheInfo(context.TODO(), accessToken, &entity.UserCacheInfo{UserID: userID}) - assert.NoError(t, err) + require.NoError(t, err) cacheInfo, err := authRepo.GetAdminUserCacheInfo(context.TODO(), accessToken) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, userID, cacheInfo.UserID) } @@ -98,12 +99,12 @@ func Test_authRepo_RemoveAdminUserCacheInfo(t *testing.T) { authRepo := auth.NewAuthRepo(testDataSource) err := authRepo.SetAdminUserCacheInfo(context.TODO(), accessToken, &entity.UserCacheInfo{UserID: userID}) - assert.NoError(t, err) + require.NoError(t, err) err = authRepo.RemoveAdminUserCacheInfo(context.TODO(), accessToken) - assert.NoError(t, err) + require.NoError(t, err) userInfo, err := authRepo.GetAdminUserCacheInfo(context.TODO(), accessToken) - assert.NoError(t, err) + require.NoError(t, err) assert.Nil(t, userInfo) } diff --git a/internal/repo/repo_test/captcha_test.go b/internal/repo/repo_test/captcha_test.go index 48e9dd806..e6954a232 100644 --- a/internal/repo/repo_test/captcha_test.go +++ b/internal/repo/repo_test/captcha_test.go @@ -25,6 +25,7 @@ import ( "github.com/apache/answer/internal/repo/captcha" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var ( @@ -36,23 +37,23 @@ var ( func Test_captchaRepo_DelActionType(t *testing.T) { captchaRepo := captcha.NewCaptchaRepo(testDataSource) err := captchaRepo.SetActionType(context.TODO(), ip, actionType, "", amount) - assert.NoError(t, err) + require.NoError(t, err) actionInfo, err := captchaRepo.GetActionType(context.TODO(), ip, actionType) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, amount, actionInfo.Num) err = captchaRepo.DelActionType(context.TODO(), ip, actionType) - assert.NoError(t, err) + require.NoError(t, err) } func Test_captchaRepo_SetCaptcha(t *testing.T) { captchaRepo := captcha.NewCaptchaRepo(testDataSource) key, capt := "key", "1234" err := captchaRepo.SetCaptcha(context.TODO(), key, capt) - assert.NoError(t, err) + require.NoError(t, err) gotCaptcha, err := captchaRepo.GetCaptcha(context.TODO(), key) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, capt, gotCaptcha) } diff --git a/internal/repo/repo_test/comment_repo_test.go b/internal/repo/repo_test/comment_repo_test.go index 3de154817..41ba04464 100644 --- a/internal/repo/repo_test/comment_repo_test.go +++ b/internal/repo/repo_test/comment_repo_test.go @@ -29,6 +29,7 @@ import ( "github.com/apache/answer/internal/repo/unique" commentService "github.com/apache/answer/internal/service/comment" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func buildCommentEntity() *entity.Comment { @@ -48,10 +49,10 @@ func Test_commentRepo_AddComment(t *testing.T) { commentRepo := comment.NewCommentRepo(testDataSource, uniqueIDRepo) testCommentEntity := buildCommentEntity() err := commentRepo.AddComment(context.TODO(), testCommentEntity) - assert.NoError(t, err) + require.NoError(t, err) err = commentRepo.RemoveComment(context.TODO(), testCommentEntity.ID) - assert.NoError(t, err) + require.NoError(t, err) } func Test_commentRepo_GetCommentPage(t *testing.T) { @@ -59,7 +60,7 @@ func Test_commentRepo_GetCommentPage(t *testing.T) { commentRepo := comment.NewCommentRepo(testDataSource, uniqueIDRepo) testCommentEntity := buildCommentEntity() err := commentRepo.AddComment(context.TODO(), testCommentEntity) - assert.NoError(t, err) + require.NoError(t, err) resp, total, err := commentRepo.GetCommentPage(context.TODO(), &commentService.CommentQuery{ PageCond: pager.PageCond{ @@ -67,12 +68,12 @@ func Test_commentRepo_GetCommentPage(t *testing.T) { PageSize: 10, }, }) - assert.NoError(t, err) - assert.Equal(t, total, int64(1)) + require.NoError(t, err) + assert.Equal(t, int64(1), total) assert.Equal(t, resp[0].ID, testCommentEntity.ID) err = commentRepo.RemoveComment(context.TODO(), testCommentEntity.ID) - assert.NoError(t, err) + require.NoError(t, err) } func Test_commentRepo_UpdateComment(t *testing.T) { @@ -81,19 +82,19 @@ func Test_commentRepo_UpdateComment(t *testing.T) { commonCommentRepo := comment.NewCommentCommonRepo(testDataSource, uniqueIDRepo) testCommentEntity := buildCommentEntity() err := commentRepo.AddComment(context.TODO(), testCommentEntity) - assert.NoError(t, err) + require.NoError(t, err) testCommentEntity.ParsedText = "test" err = commentRepo.UpdateCommentContent(context.TODO(), testCommentEntity.ID, "test", "test") - assert.NoError(t, err) + require.NoError(t, err) newComment, exist, err := commonCommentRepo.GetComment(context.TODO(), testCommentEntity.ID) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, testCommentEntity.ParsedText, newComment.ParsedText) err = commentRepo.RemoveComment(context.TODO(), testCommentEntity.ID) - assert.NoError(t, err) + require.NoError(t, err) } func Test_commentRepo_CannotGetDeletedComment(t *testing.T) { @@ -102,12 +103,12 @@ func Test_commentRepo_CannotGetDeletedComment(t *testing.T) { testCommentEntity := buildCommentEntity() err := commentRepo.AddComment(context.TODO(), testCommentEntity) - assert.NoError(t, err) + require.NoError(t, err) err = commentRepo.RemoveComment(context.TODO(), testCommentEntity.ID) - assert.NoError(t, err) + require.NoError(t, err) _, exist, err := commentRepo.GetComment(context.TODO(), testCommentEntity.ID) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, exist) } diff --git a/internal/repo/repo_test/email_repo_test.go b/internal/repo/repo_test/email_repo_test.go index 82fc6c571..03ca9efe3 100644 --- a/internal/repo/repo_test/email_repo_test.go +++ b/internal/repo/repo_test/email_repo_test.go @@ -26,15 +26,16 @@ import ( "github.com/apache/answer/internal/repo/export" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_emailRepo_VerifyCode(t *testing.T) { emailRepo := export.NewEmailRepo(testDataSource) code, content := "1111", "{\"source_type\":\"\",\"e_mail\":\"\",\"user_id\":\"1\",\"skip_validation_latest_code\":false}" err := emailRepo.SetCode(context.TODO(), "1", code, content, time.Minute) - assert.NoError(t, err) + require.NoError(t, err) verifyContent, err := emailRepo.VerifyCode(context.TODO(), code) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, content, verifyContent) } diff --git a/internal/repo/repo_test/meta_repo_test.go b/internal/repo/repo_test/meta_repo_test.go index e910dab3f..68965f22b 100644 --- a/internal/repo/repo_test/meta_repo_test.go +++ b/internal/repo/repo_test/meta_repo_test.go @@ -26,6 +26,7 @@ import ( "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/repo/meta" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func buildMetaEntity() *entity.Meta { @@ -41,15 +42,15 @@ func Test_metaRepo_GetMetaByObjectIdAndKey(t *testing.T) { metaEnt := buildMetaEntity() err := metaRepo.AddMeta(context.TODO(), metaEnt) - assert.NoError(t, err) + require.NoError(t, err) gotMeta, exist, err := metaRepo.GetMetaByObjectIdAndKey(context.TODO(), metaEnt.ObjectID, metaEnt.Key) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, metaEnt.ID, gotMeta.ID) err = metaRepo.RemoveMeta(context.TODO(), metaEnt.ID) - assert.NoError(t, err) + require.NoError(t, err) } func Test_metaRepo_GetMetaList(t *testing.T) { @@ -57,15 +58,15 @@ func Test_metaRepo_GetMetaList(t *testing.T) { metaEnt := buildMetaEntity() err := metaRepo.AddMeta(context.TODO(), metaEnt) - assert.NoError(t, err) + require.NoError(t, err) gotMetaList, err := metaRepo.GetMetaList(context.TODO(), metaEnt) - assert.NoError(t, err) - assert.Equal(t, len(gotMetaList), 1) + require.NoError(t, err) + assert.Len(t, gotMetaList, 1) assert.Equal(t, gotMetaList[0].ID, metaEnt.ID) err = metaRepo.RemoveMeta(context.TODO(), metaEnt.ID) - assert.NoError(t, err) + require.NoError(t, err) } func Test_metaRepo_GetMetaPage(t *testing.T) { @@ -73,15 +74,15 @@ func Test_metaRepo_GetMetaPage(t *testing.T) { metaEnt := buildMetaEntity() err := metaRepo.AddMeta(context.TODO(), metaEnt) - assert.NoError(t, err) + require.NoError(t, err) gotMetaList, err := metaRepo.GetMetaList(context.TODO(), metaEnt) - assert.NoError(t, err) - assert.Equal(t, len(gotMetaList), 1) + require.NoError(t, err) + assert.Len(t, gotMetaList, 1) assert.Equal(t, gotMetaList[0].ID, metaEnt.ID) err = metaRepo.RemoveMeta(context.TODO(), metaEnt.ID) - assert.NoError(t, err) + require.NoError(t, err) } func Test_metaRepo_UpdateMeta(t *testing.T) { @@ -89,17 +90,17 @@ func Test_metaRepo_UpdateMeta(t *testing.T) { metaEnt := buildMetaEntity() err := metaRepo.AddMeta(context.TODO(), metaEnt) - assert.NoError(t, err) + require.NoError(t, err) metaEnt.Value = "testing" err = metaRepo.UpdateMeta(context.TODO(), metaEnt) - assert.NoError(t, err) + require.NoError(t, err) gotMeta, exist, err := metaRepo.GetMetaByObjectIdAndKey(context.TODO(), metaEnt.ObjectID, metaEnt.Key) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, gotMeta.Value, metaEnt.Value) err = metaRepo.RemoveMeta(context.TODO(), metaEnt.ID) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/repo/repo_test/notification_repo_test.go b/internal/repo/repo_test/notification_repo_test.go index a05913ba1..4f843e777 100644 --- a/internal/repo/repo_test/notification_repo_test.go +++ b/internal/repo/repo_test/notification_repo_test.go @@ -27,6 +27,7 @@ import ( "github.com/apache/answer/internal/repo/notification" "github.com/apache/answer/internal/schema" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func buildNotificationEntity() *entity.Notification { @@ -44,13 +45,13 @@ func Test_notificationRepo_ClearIDUnRead(t *testing.T) { notificationRepo := notification.NewNotificationRepo(testDataSource) ent := buildNotificationEntity() err := notificationRepo.AddNotification(context.TODO(), ent) - assert.NoError(t, err) + require.NoError(t, err) err = notificationRepo.ClearIDUnRead(context.TODO(), ent.UserID, ent.ID) - assert.NoError(t, err) + require.NoError(t, err) got, exists, err := notificationRepo.GetById(context.TODO(), ent.ID) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exists) assert.Equal(t, schema.NotificationRead, got.IsRead) } @@ -59,13 +60,13 @@ func Test_notificationRepo_ClearUnRead(t *testing.T) { notificationRepo := notification.NewNotificationRepo(testDataSource) ent := buildNotificationEntity() err := notificationRepo.AddNotification(context.TODO(), ent) - assert.NoError(t, err) + require.NoError(t, err) err = notificationRepo.ClearUnRead(context.TODO(), ent.UserID, ent.Type) - assert.NoError(t, err) + require.NoError(t, err) got, exists, err := notificationRepo.GetById(context.TODO(), ent.ID) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exists) assert.Equal(t, schema.NotificationRead, got.IsRead) } @@ -74,10 +75,10 @@ func Test_notificationRepo_GetById(t *testing.T) { notificationRepo := notification.NewNotificationRepo(testDataSource) ent := buildNotificationEntity() err := notificationRepo.AddNotification(context.TODO(), ent) - assert.NoError(t, err) + require.NoError(t, err) got, exists, err := notificationRepo.GetById(context.TODO(), ent.ID) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exists) assert.Equal(t, got.ID, ent.ID) } @@ -86,10 +87,10 @@ func Test_notificationRepo_GetByUserIdObjectIdTypeId(t *testing.T) { notificationRepo := notification.NewNotificationRepo(testDataSource) ent := buildNotificationEntity() err := notificationRepo.AddNotification(context.TODO(), ent) - assert.NoError(t, err) + require.NoError(t, err) got, exists, err := notificationRepo.GetByUserIdObjectIdTypeId(context.TODO(), ent.UserID, ent.ObjectID, ent.Type) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exists) assert.Equal(t, got.ObjectID, ent.ObjectID) } @@ -98,11 +99,11 @@ func Test_notificationRepo_GetNotificationPage(t *testing.T) { notificationRepo := notification.NewNotificationRepo(testDataSource) ent := buildNotificationEntity() err := notificationRepo.AddNotification(context.TODO(), ent) - assert.NoError(t, err) + require.NoError(t, err) notificationPage, total, err := notificationRepo.GetNotificationPage(context.TODO(), &schema.NotificationSearch{UserID: ent.UserID}) - assert.NoError(t, err) - assert.True(t, total > 0) + require.NoError(t, err) + assert.Positive(t, total) assert.Equal(t, notificationPage[0].UserID, ent.UserID) } @@ -110,14 +111,14 @@ func Test_notificationRepo_UpdateNotificationContent(t *testing.T) { notificationRepo := notification.NewNotificationRepo(testDataSource) ent := buildNotificationEntity() err := notificationRepo.AddNotification(context.TODO(), ent) - assert.NoError(t, err) + require.NoError(t, err) ent.Content = "test" err = notificationRepo.UpdateNotificationContent(context.TODO(), ent) - assert.NoError(t, err) + require.NoError(t, err) got, exists, err := notificationRepo.GetById(context.TODO(), ent.ID) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exists) assert.Equal(t, got.Content, ent.Content) } diff --git a/internal/repo/repo_test/reason_repo_test.go b/internal/repo/repo_test/reason_repo_test.go index 636f8d278..acb8c861a 100644 --- a/internal/repo/repo_test/reason_repo_test.go +++ b/internal/repo/repo_test/reason_repo_test.go @@ -28,12 +28,13 @@ import ( "github.com/apache/answer/internal/repo/reason" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_reasonRepo_ListReasons(t *testing.T) { configRepo := config.NewConfigRepo(testDataSource) reasonRepo := reason.NewReasonRepo(serviceconfig.NewConfigService(configRepo)) reasonItems, err := reasonRepo.ListReasons(context.TODO(), "question", "close") - assert.NoError(t, err) - assert.Equal(t, 4, len(reasonItems)) + require.NoError(t, err) + assert.Len(t, reasonItems, 4) } diff --git a/internal/repo/repo_test/recommend_test.go b/internal/repo/repo_test/recommend_test.go index a21693886..7675aa204 100644 --- a/internal/repo/repo_test/recommend_test.go +++ b/internal/repo/repo_test/recommend_test.go @@ -34,6 +34,7 @@ import ( "github.com/apache/answer/internal/repo/user" config2 "github.com/apache/answer/internal/service/config" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_questionRepo_GetRecommend(t *testing.T) { @@ -61,8 +62,8 @@ func Test_questionRepo_GetRecommend(t *testing.T) { IsAdmin: false, } err := userRepo.AddUser(context.TODO(), user) - assert.NoError(t, err) - assert.NotEqual(t, "", user.ID) + require.NoError(t, err) + assert.NotEmpty(t, user.ID) questions := make([]*entity.Question, 0) // tag, unjoin, unfollow @@ -140,8 +141,8 @@ func Test_questionRepo_GetRecommend(t *testing.T) { for _, question := range questions { err = questionRepo.AddQuestion(context.TODO(), question) - assert.NoError(t, err) - assert.NotEqual(t, "", question.ID) + require.NoError(t, err) + assert.NotEmpty(t, question.ID) } tags := []*entity.Tag{ @@ -161,7 +162,7 @@ func Test_questionRepo_GetRecommend(t *testing.T) { }, } err = tagCommenRepo.AddTagList(context.TODO(), tags) - assert.NoError(t, err) + require.NoError(t, err) tagRels := make([]*entity.TagRel, 0) for i, question := range questions { @@ -173,7 +174,7 @@ func Test_questionRepo_GetRecommend(t *testing.T) { tagRels = append(tagRels, tagRel) } err = tagRelRepo.AddTagRelList(context.TODO(), tagRels) - assert.NoError(t, err) + require.NoError(t, err) followQuestionIDs := make([]string, 0) for i := range questions { @@ -181,15 +182,15 @@ func Test_questionRepo_GetRecommend(t *testing.T) { continue } err = followRepo.Follow(context.TODO(), questions[i].ID, user.ID) - assert.NoError(t, err) + require.NoError(t, err) followQuestionIDs = append(followQuestionIDs, questions[i].ID) } // get recommend questionList, total, err := questionRepo.GetRecommendQuestionPageByTags(context.TODO(), user.ID, []string{tags[0].ID}, followQuestionIDs, 1, 20) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int64(5), total) - assert.Equal(t, 5, len(questionList)) + assert.Len(t, questionList, 5) // recovery t.Cleanup(func() { @@ -197,19 +198,19 @@ func Test_questionRepo_GetRecommend(t *testing.T) { for i, tagRel := range tagRels { if i%2 == 1 { err = followRepo.FollowCancel(context.TODO(), questions[i].ID, user.ID) - assert.NoError(t, err) + require.NoError(t, err) } tagRelIDs = append(tagRelIDs, tagRel.ID) } err = tagRelRepo.RemoveTagRelListByIDs(context.TODO(), tagRelIDs) - assert.NoError(t, err) + require.NoError(t, err) for _, tag := range tags { err = tagRepo.RemoveTag(context.TODO(), tag.ID) - assert.NoError(t, err) + require.NoError(t, err) } for _, q := range questions { err = questionRepo.RemoveQuestion(context.TODO(), q.ID) - assert.NoError(t, err) + require.NoError(t, err) } }) } diff --git a/internal/repo/repo_test/repo_main_test.go b/internal/repo/repo_test/repo_main_test.go index 919ca94e8..e2f40f276 100644 --- a/internal/repo/repo_test/repo_main_test.go +++ b/internal/repo/repo_test/repo_main_test.go @@ -153,7 +153,7 @@ func initDatabaseImage(dbSetting TestDBSetting) (connection string, cleanup func return "", nil, fmt.Errorf("could not connect to docker: %s", err) } - //resource, err := pool.Run(dbSetting.ImageName, dbSetting.ImageVersion, dbSetting.ENV) + // resource, err := pool.Run(dbSetting.ImageName, dbSetting.ImageVersion, dbSetting.ENV) resource, err := pool.RunWithOptions(&dockertest.RunOptions{ Repository: dbSetting.ImageName, Tag: dbSetting.ImageVersion, diff --git a/internal/repo/repo_test/revision_repo_test.go b/internal/repo/repo_test/revision_repo_test.go index 01d262d2b..6fd067b30 100644 --- a/internal/repo/repo_test/revision_repo_test.go +++ b/internal/repo/repo_test/revision_repo_test.go @@ -29,6 +29,7 @@ import ( "github.com/apache/answer/internal/repo/revision" "github.com/apache/answer/internal/repo/unique" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var q = &entity.Question{ @@ -69,29 +70,29 @@ func Test_revisionRepo_AddRevision(t *testing.T) { // create question err := questionRepo.AddQuestion(context.TODO(), q) - assert.NoError(t, err) - assert.NotEqual(t, "", q.ID) + require.NoError(t, err) + assert.NotEmpty(t, q.ID) content, err := json.Marshal(q) - assert.NoError(t, err) + require.NoError(t, err) // auto update false rev := getRev(q.ID, q.Title, string(content)) err = revisionRepo.AddRevision(context.TODO(), rev, false) - assert.NoError(t, err) + require.NoError(t, err) qr, _, _ := questionRepo.GetQuestion(context.TODO(), q.ID) assert.NotEqual(t, rev.ID, qr.RevisionID) // auto update false rev = getRev(q.ID, q.Title, string(content)) err = revisionRepo.AddRevision(context.TODO(), rev, true) - assert.NoError(t, err) + require.NoError(t, err) qr, _, _ = questionRepo.GetQuestion(context.TODO(), q.ID) assert.Equal(t, rev.ID, qr.RevisionID) // recovery t.Cleanup(func() { err = questionRepo.RemoveQuestion(context.TODO(), q.ID) - assert.NoError(t, err) + require.NoError(t, err) }) } @@ -103,7 +104,7 @@ func Test_revisionRepo_GetLastRevisionByObjectID(t *testing.T) { Test_revisionRepo_AddRevision(t) rev, exists, err := revisionRepo.GetLastRevisionByObjectID(context.TODO(), q.ID) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exists) assert.NotNil(t, rev) } @@ -115,6 +116,6 @@ func Test_revisionRepo_GetRevisionList(t *testing.T) { ) Test_revisionRepo_AddRevision(t) revs, err := revisionRepo.GetRevisionList(context.TODO(), &entity.Revision{ObjectID: q.ID}) - assert.NoError(t, err) + require.NoError(t, err) assert.GreaterOrEqual(t, len(revs), 1) } diff --git a/internal/repo/repo_test/siteinfo_repo_test.go b/internal/repo/repo_test/siteinfo_repo_test.go index cb5d8fc0d..9fa59d177 100644 --- a/internal/repo/repo_test/siteinfo_repo_test.go +++ b/internal/repo/repo_test/siteinfo_repo_test.go @@ -26,6 +26,7 @@ import ( "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/repo/site_info" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_siteInfoRepo_SaveByType(t *testing.T) { @@ -34,19 +35,19 @@ func Test_siteInfoRepo_SaveByType(t *testing.T) { data := &entity.SiteInfo{Content: "site_info", Type: "test"} err := siteInfoRepo.SaveByType(context.TODO(), data.Type, data) - assert.NoError(t, err) + require.NoError(t, err) got, exist, err := siteInfoRepo.GetByType(context.TODO(), data.Type) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, data.Content, got.Content) data.Content = "new site_info" err = siteInfoRepo.SaveByType(context.TODO(), data.Type, data) - assert.NoError(t, err) + require.NoError(t, err) got, exist, err = siteInfoRepo.GetByType(context.TODO(), data.Type) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, data.Content, got.Content) } diff --git a/internal/repo/repo_test/tag_rel_repo_test.go b/internal/repo/repo_test/tag_rel_repo_test.go index e3af67a14..47c09a6a3 100644 --- a/internal/repo/repo_test/tag_rel_repo_test.go +++ b/internal/repo/repo_test/tag_rel_repo_test.go @@ -30,6 +30,7 @@ import ( "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/repo/tag" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var ( @@ -61,15 +62,15 @@ func Test_tagListRepo_BatchGetObjectTagRelList(t *testing.T) { tagRelRepo := tag.NewTagRelRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) relList, err := tagRelRepo.BatchGetObjectTagRelList(context.TODO(), []string{testTagRelList[0].ObjectID, testTagRelList[1].ObjectID}) - assert.NoError(t, err) - assert.Equal(t, 2, len(relList)) + require.NoError(t, err) + assert.Len(t, relList, 2) } func Test_tagListRepo_CountTagRelByTagID(t *testing.T) { tagRelOnce.Do(addTagRelList) tagRelRepo := tag.NewTagRelRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) count, err := tagRelRepo.CountTagRelByTagID(context.TODO(), "10030000000000101") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int64(1), count) } @@ -79,8 +80,8 @@ func Test_tagListRepo_GetObjectTagRelList(t *testing.T) { relList, err := tagRelRepo.GetObjectTagRelList(context.TODO(), testTagRelList[0].ObjectID) - assert.NoError(t, err) - assert.Equal(t, 1, len(relList)) + require.NoError(t, err) + assert.Len(t, relList, 1) } func Test_tagListRepo_GetObjectTagRelWithoutStatus(t *testing.T) { @@ -89,25 +90,25 @@ func Test_tagListRepo_GetObjectTagRelWithoutStatus(t *testing.T) { relList, err := tagRelRepo.BatchGetObjectTagRelList(context.TODO(), []string{testTagRelList[0].ObjectID, testTagRelList[1].ObjectID}) - assert.NoError(t, err) - assert.Equal(t, 2, len(relList)) + require.NoError(t, err) + assert.Len(t, relList, 2) ids := []int64{relList[0].ID, relList[1].ID} err = tagRelRepo.RemoveTagRelListByIDs(context.TODO(), ids) - assert.NoError(t, err) + require.NoError(t, err) count, err := tagRelRepo.CountTagRelByTagID(context.TODO(), "10030000000000101") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int64(0), count) _, exist, err := tagRelRepo.GetObjectTagRelWithoutStatus(context.TODO(), relList[0].ObjectID, relList[0].TagID) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) err = tagRelRepo.EnableTagRelByIDs(context.TODO(), ids, false) - assert.NoError(t, err) + require.NoError(t, err) count, err = tagRelRepo.CountTagRelByTagID(context.TODO(), "10030000000000101") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int64(1), count) } diff --git a/internal/repo/repo_test/tag_repo_test.go b/internal/repo/repo_test/tag_repo_test.go index b2475a227..aa1ec1a25 100644 --- a/internal/repo/repo_test/tag_repo_test.go +++ b/internal/repo/repo_test/tag_repo_test.go @@ -32,6 +32,7 @@ import ( "github.com/apache/answer/internal/repo/unique" "github.com/apache/answer/pkg/converter" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var ( @@ -75,7 +76,7 @@ func Test_tagRepo_GetTagByID(t *testing.T) { tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID, true) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, testTagList[0].SlugName, gotTag.SlugName) } @@ -85,7 +86,7 @@ func Test_tagRepo_GetTagBySlugName(t *testing.T) { tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) gotTag, exist, err := tagCommonRepo.GetTagBySlugName(context.TODO(), testTagList[0].SlugName) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, testTagList[0].SlugName, gotTag.SlugName) } @@ -95,7 +96,7 @@ func Test_tagRepo_GetTagList(t *testing.T) { tagRepo := tag.NewTagRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) gotTags, err := tagRepo.GetTagList(context.TODO(), &entity.Tag{ID: testTagList[0].ID}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName) } @@ -104,7 +105,7 @@ func Test_tagRepo_GetTagListByIDs(t *testing.T) { tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) gotTags, err := tagCommonRepo.GetTagListByIDs(context.TODO(), []string{testTagList[0].ID}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName) } @@ -113,7 +114,7 @@ func Test_tagRepo_GetTagListByName(t *testing.T) { tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) gotTags, err := tagCommonRepo.GetTagListByName(context.TODO(), testTagList[0].SlugName, false, false) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName) } @@ -122,7 +123,7 @@ func Test_tagRepo_GetTagListByNames(t *testing.T) { tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) gotTags, err := tagCommonRepo.GetTagListByNames(context.TODO(), []string{testTagList[0].SlugName}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName) } @@ -131,7 +132,7 @@ func Test_tagRepo_GetTagPage(t *testing.T) { tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) gotTags, _, err := tagCommonRepo.GetTagPage(context.TODO(), 1, 1, &entity.Tag{SlugName: testTagList[0].SlugName}, "") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName) } @@ -140,12 +141,12 @@ func Test_tagRepo_RemoveTag(t *testing.T) { uniqueIDRepo := unique.NewUniqueIDRepo(testDataSource) tagRepo := tag.NewTagRepo(testDataSource, uniqueIDRepo) err := tagRepo.RemoveTag(context.TODO(), testTagList[1].ID) - assert.NoError(t, err) + require.NoError(t, err) tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) _, exist, err := tagCommonRepo.GetTagBySlugName(context.TODO(), testTagList[1].SlugName) - assert.NoError(t, err) + require.NoError(t, err) assert.False(t, exist) } @@ -155,12 +156,12 @@ func Test_tagRepo_UpdateTag(t *testing.T) { testTagList[0].DisplayName = "golang" err := tagRepo.UpdateTag(context.TODO(), testTagList[0]) - assert.NoError(t, err) + require.NoError(t, err) tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID, true) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, testTagList[0].DisplayName, gotTag.DisplayName) } @@ -170,10 +171,10 @@ func Test_tagRepo_UpdateTagQuestionCount(t *testing.T) { testTagList[0].DisplayName = "golang" err := tagCommonRepo.UpdateTagQuestionCount(context.TODO(), testTagList[0].ID, 100) - assert.NoError(t, err) + require.NoError(t, err) gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID, true) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, 100, gotTag.QuestionCount) } @@ -184,16 +185,16 @@ func Test_tagRepo_UpdateTagSynonym(t *testing.T) { testTagList[0].DisplayName = "golang" err := tagRepo.UpdateTag(context.TODO(), testTagList[0]) - assert.NoError(t, err) + require.NoError(t, err) err = tagRepo.UpdateTagSynonym(context.TODO(), []string{testTagList[2].SlugName}, converter.StringToInt64(testTagList[0].ID), testTagList[0].SlugName) - assert.NoError(t, err) + require.NoError(t, err) tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource)) gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[2].ID, true) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, testTagList[0].ID, fmt.Sprintf("%d", gotTag.MainTagID)) } diff --git a/internal/repo/repo_test/user_backyard_repo_test.go b/internal/repo/repo_test/user_backyard_repo_test.go index 073a600cf..eb4db102b 100644 --- a/internal/repo/repo_test/user_backyard_repo_test.go +++ b/internal/repo/repo_test/user_backyard_repo_test.go @@ -28,12 +28,13 @@ import ( "github.com/apache/answer/internal/repo/auth" "github.com/apache/answer/internal/repo/user" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_userAdminRepo_GetUserInfo(t *testing.T) { userAdminRepo := user.NewUserAdminRepo(testDataSource, auth.NewAuthRepo(testDataSource)) got, exist, err := userAdminRepo.GetUserInfo(context.TODO(), "1") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, "1", got.ID) } @@ -41,7 +42,7 @@ func Test_userAdminRepo_GetUserInfo(t *testing.T) { func Test_userAdminRepo_GetUserPage(t *testing.T) { userAdminRepo := user.NewUserAdminRepo(testDataSource, auth.NewAuthRepo(testDataSource)) got, total, err := userAdminRepo.GetUserPage(context.TODO(), 1, 1, &entity.User{Username: "admin"}, "", false) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, int64(1), total) assert.Equal(t, "1", got[0].ID) } @@ -49,25 +50,25 @@ func Test_userAdminRepo_GetUserPage(t *testing.T) { func Test_userAdminRepo_UpdateUserStatus(t *testing.T) { userAdminRepo := user.NewUserAdminRepo(testDataSource, auth.NewAuthRepo(testDataSource)) got, exist, err := userAdminRepo.GetUserInfo(context.TODO(), "1") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, entity.UserStatusAvailable, got.Status) err = userAdminRepo.UpdateUserStatus(context.TODO(), "1", entity.UserStatusSuspended, entity.EmailStatusAvailable, "admin@admin.com", time.Now().Add(time.Minute*5)) - assert.NoError(t, err) + require.NoError(t, err) got, exist, err = userAdminRepo.GetUserInfo(context.TODO(), "1") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, entity.UserStatusSuspended, got.Status) err = userAdminRepo.UpdateUserStatus(context.TODO(), "1", entity.UserStatusAvailable, entity.EmailStatusAvailable, "admin@admin.com", time.Time{}) - assert.NoError(t, err) + require.NoError(t, err) got, exist, err = userAdminRepo.GetUserInfo(context.TODO(), "1") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, entity.UserStatusAvailable, got.Status) } diff --git a/internal/repo/repo_test/user_repo_test.go b/internal/repo/repo_test/user_repo_test.go index 7b18833dd..95a85ab99 100644 --- a/internal/repo/repo_test/user_repo_test.go +++ b/internal/repo/repo_test/user_repo_test.go @@ -26,6 +26,7 @@ import ( "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/repo/user" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_userRepo_AddUser(t *testing.T) { @@ -40,21 +41,21 @@ func Test_userRepo_AddUser(t *testing.T) { IsAdmin: false, } err := userRepo.AddUser(context.TODO(), userInfo) - assert.NoError(t, err) + require.NoError(t, err) } func Test_userRepo_BatchGetByID(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) got, err := userRepo.BatchGetByID(context.TODO(), []string{"1"}) - assert.NoError(t, err) - assert.Equal(t, 1, len(got)) + require.NoError(t, err) + assert.Len(t, got, 1) assert.Equal(t, "admin", got[0].Username) } func Test_userRepo_GetByEmail(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) got, exist, err := userRepo.GetByEmail(context.TODO(), "admin@admin.com") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, "admin", got.Username) } @@ -62,7 +63,7 @@ func Test_userRepo_GetByEmail(t *testing.T) { func Test_userRepo_GetByUserID(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) got, exist, err := userRepo.GetByUserID(context.TODO(), "1") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, "admin", got.Username) } @@ -70,7 +71,7 @@ func Test_userRepo_GetByUserID(t *testing.T) { func Test_userRepo_GetByUsername(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) got, exist, err := userRepo.GetByUsername(context.TODO(), "admin") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, "admin", got.Username) } @@ -78,10 +79,10 @@ func Test_userRepo_GetByUsername(t *testing.T) { func Test_userRepo_IncreaseAnswerCount(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) err := userRepo.IncreaseAnswerCount(context.TODO(), "1", 1) - assert.NoError(t, err) + require.NoError(t, err) got, exist, err := userRepo.GetByUserID(context.TODO(), "1") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, 1, got.AnswerCount) } @@ -89,10 +90,10 @@ func Test_userRepo_IncreaseAnswerCount(t *testing.T) { func Test_userRepo_IncreaseQuestionCount(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) err := userRepo.IncreaseQuestionCount(context.TODO(), "1", 1) - assert.NoError(t, err) + require.NoError(t, err) got, exist, err := userRepo.GetByUserID(context.TODO(), "1") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, 1, got.AnswerCount) } @@ -100,22 +101,22 @@ func Test_userRepo_IncreaseQuestionCount(t *testing.T) { func Test_userRepo_UpdateEmail(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) err := userRepo.UpdateEmail(context.TODO(), "1", "admin@admin.com") - assert.NoError(t, err) + require.NoError(t, err) } func Test_userRepo_UpdateEmailStatus(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) err := userRepo.UpdateEmailStatus(context.TODO(), "1", entity.EmailStatusToBeVerified) - assert.NoError(t, err) + require.NoError(t, err) } func Test_userRepo_UpdateInfo(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) err := userRepo.UpdateInfo(context.TODO(), &entity.User{ID: "1", Bio: "test"}) - assert.NoError(t, err) + require.NoError(t, err) got, exist, err := userRepo.GetByUserID(context.TODO(), "1") - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, exist) assert.Equal(t, "test", got.Bio) } @@ -123,17 +124,17 @@ func Test_userRepo_UpdateInfo(t *testing.T) { func Test_userRepo_UpdateLastLoginDate(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) err := userRepo.UpdateLastLoginDate(context.TODO(), "1") - assert.NoError(t, err) + require.NoError(t, err) } func Test_userRepo_UpdateNoticeStatus(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) err := userRepo.UpdateNoticeStatus(context.TODO(), "1", 1) - assert.NoError(t, err) + require.NoError(t, err) } func Test_userRepo_UpdatePass(t *testing.T) { userRepo := user.NewUserRepo(testDataSource) err := userRepo.UpdatePass(context.TODO(), "1", "admin") - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/repo/search_common/search_repo.go b/internal/repo/search_common/search_repo.go index 806517234..a56b8edb6 100644 --- a/internal/repo/search_common/search_repo.go +++ b/internal/repo/search_common/search_repo.go @@ -190,7 +190,7 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagIDs argsA = append(argsA, votes) } - //b = b.Union("all", ub) + // b = b.Union("all", ub) ubSQL, _, err := ub.ToSQL() if err != nil { return @@ -447,7 +447,7 @@ func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, tagIDs return } -func (sr *searchRepo) parseOrder(ctx context.Context, order string) (res string) { +func (sr *searchRepo) parseOrder(_ context.Context, order string) (res string) { switch order { case "newest": res = "created_at desc" diff --git a/internal/schema/backyard_user_schema.go b/internal/schema/backyard_user_schema.go index 6ec848721..d36ff8083 100644 --- a/internal/schema/backyard_user_schema.go +++ b/internal/schema/backyard_user_schema.go @@ -222,7 +222,7 @@ func (req *AddUsersReq) ParseUsers(ctx context.Context) (errFields []*validator. } // check users amount - if len(req.Users) <= 0 || len(req.Users) > constant.DefaultBulkUser { + if len(req.Users) == 0 || len(req.Users) > constant.DefaultBulkUser { errFields = append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "users", ErrorMsg: translator.TrWithData(handler.GetLangByCtx(ctx), reason.AddBulkUsersAmountError, diff --git a/internal/schema/meta_schema.go b/internal/schema/meta_schema.go index 286e2e7d6..e5a072529 100644 --- a/internal/schema/meta_schema.go +++ b/internal/schema/meta_schema.go @@ -19,6 +19,8 @@ package schema +import "slices" + type UpdateReactionReq struct { ObjectID string `validate:"required" json:"object_id"` Emoji string `validate:"required,oneof=heart smile frown" json:"emoji"` @@ -48,13 +50,7 @@ func (r *ReactionsSummaryMeta) AddReactionSummary(emoji, userID string) { if reaction.Emoji != emoji { continue } - exist := false - for _, id := range reaction.UserIDs { - if id == userID { - exist = true - break - } - } + exist := slices.Contains(reaction.UserIDs, userID) if !exist { reaction.UserIDs = append(reaction.UserIDs, userID) } @@ -94,10 +90,8 @@ func (r *ReactionsSummaryMeta) CheckUserInReactionSummary(emoji, userID string) if reaction.Emoji != emoji { continue } - for _, id := range reaction.UserIDs { - if id == userID { - return true - } + if slices.Contains(reaction.UserIDs, userID) { + return true } } return false diff --git a/internal/schema/notification_schema.go b/internal/schema/notification_schema.go index e5d60615e..b9e029389 100644 --- a/internal/schema/notification_schema.go +++ b/internal/schema/notification_schema.go @@ -53,7 +53,7 @@ var NotificationInboxType = map[string]int{ type NotificationContent struct { ID string `json:"id"` - TriggerUserID string `json:"-"` //show userid + TriggerUserID string `json:"-"` // show userid ReceiverUserID string `json:"-"` // receiver userid UserInfo *UserBasicInfo `json:"user_info,omitempty"` ObjectInfo ObjectInfo `json:"object_info"` @@ -169,8 +169,8 @@ func (r *RedDotBadgeAwardCache) RemoveBadgeAward(notificationID string) { } type NotificationSearch struct { - Page int `json:"page" form:"page"` //Query number of pages - PageSize int `json:"page_size" form:"page_size"` //Search page size + Page int `json:"page" form:"page"` // Query number of pages + PageSize int `json:"page_size" form:"page_size"` // Search page size Type int `json:"-" form:"-"` TypeStr string `json:"type" form:"type"` // inbox achievement InboxTypeStr string `json:"inbox_type" form:"inbox_type"` // inbox achievement diff --git a/internal/schema/revision_schema.go b/internal/schema/revision_schema.go index b3ac0aadd..6f3246e51 100644 --- a/internal/schema/revision_schema.go +++ b/internal/schema/revision_schema.go @@ -53,7 +53,7 @@ const RevisionAuditReject = "reject" type RevisionAuditReq struct { // object id ID string `validate:"required" comment:"id" form:"id"` - Operation string `validate:"required" comment:"operation" form:"operation"` //approve or reject + Operation string `validate:"required" comment:"operation" form:"operation"` // approve or reject UserID string `json:"-"` CanReviewQuestion bool `json:"-"` CanReviewAnswer bool `json:"-"` diff --git a/internal/schema/siteinfo_schema.go b/internal/schema/siteinfo_schema.go index 0e43bb420..7ab657512 100644 --- a/internal/schema/siteinfo_schema.go +++ b/internal/schema/siteinfo_schema.go @@ -52,7 +52,7 @@ func (r *SiteGeneralReq) FormatSiteUrl() { } r.SiteUrl = fmt.Sprintf("%s://%s", parsedUrl.Scheme, parsedUrl.Host) if len(parsedUrl.Path) > 0 { - r.SiteUrl = r.SiteUrl + parsedUrl.Path + r.SiteUrl += parsedUrl.Path r.SiteUrl = strings.TrimSuffix(r.SiteUrl, "/") } } diff --git a/internal/schema/tag_schema.go b/internal/schema/tag_schema.go index a51b2d2d5..8eb3212c4 100644 --- a/internal/schema/tag_schema.go +++ b/internal/schema/tag_schema.go @@ -109,7 +109,7 @@ type GetTagPageResp struct { DisplayName string `json:"display_name"` // excerpt Excerpt string `json:"excerpt"` - //description + // description Description string `json:"description"` // original text OriginalText string `json:"original_text"` diff --git a/internal/service/action/captcha_strategy.go b/internal/service/action/captcha_strategy.go index b423b583b..edda73252 100644 --- a/internal/service/action/captcha_strategy.go +++ b/internal/service/action/captcha_strategy.go @@ -67,9 +67,8 @@ func (cs *CaptchaService) ValidationStrategy(ctx context.Context, unit, actionTy return cs.CaptchaActionDelete(ctx, unit, info) case entity.CaptchaActionVote: return cs.CaptchaActionVote(ctx, unit, info) - } - //actionType not found + // actionType not found return false } @@ -83,7 +82,7 @@ func (cs *CaptchaService) CaptchaActionPassword(ctx context.Context, unit string return true } setNum := 3 - setTime := int64(60 * 30) //seconds + setTime := int64(60 * 30) // seconds now := time.Now().Unix() if now-actionInfo.LastTime <= setTime && actionInfo.Num >= setNum { return false @@ -101,7 +100,7 @@ func (cs *CaptchaService) CaptchaActionEditUserinfo(ctx context.Context, unit st return true } setNum := 3 - setTime := int64(60 * 30) //seconds + setTime := int64(60 * 30) // seconds now := time.Now().Unix() if now-actionInfo.LastTime <= setTime && actionInfo.Num >= setNum { return false @@ -119,7 +118,7 @@ func (cs *CaptchaService) CaptchaActionQuestion(ctx context.Context, unit string return true } setNum := 10 - setTime := int64(5) //seconds + setTime := int64(5) // seconds now := time.Now().Unix() if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum { return false @@ -132,7 +131,7 @@ func (cs *CaptchaService) CaptchaActionAnswer(ctx context.Context, unit string, return true } setNum := 10 - setTime := int64(5) //seconds + setTime := int64(5) // seconds now := time.Now().Unix() if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum { return false @@ -145,7 +144,7 @@ func (cs *CaptchaService) CaptchaActionComment(ctx context.Context, unit string, return true } setNum := 30 - setTime := int64(1) //seconds + setTime := int64(1) // seconds now := time.Now().Unix() if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum { return false @@ -175,8 +174,8 @@ func (cs *CaptchaService) CaptchaActionSearch(ctx context.Context, unit string, } now := time.Now().Unix() setNum := 20 - setTime := int64(60) //seconds - if now-int64(actionInfo.LastTime) <= setTime && actionInfo.Num >= setNum { + setTime := int64(60) // seconds + if now-actionInfo.LastTime <= setTime && actionInfo.Num >= setNum { return false } if now-actionInfo.LastTime > setTime { @@ -192,7 +191,7 @@ func (cs *CaptchaService) CaptchaActionReport(ctx context.Context, unit string, return true } setNum := 30 - setTime := int64(1) //seconds + setTime := int64(1) // seconds now := time.Now().Unix() if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum { return false @@ -205,7 +204,7 @@ func (cs *CaptchaService) CaptchaActionDelete(ctx context.Context, unit string, return true } setNum := 5 - setTime := int64(5) //seconds + setTime := int64(5) // seconds now := time.Now().Unix() if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum { return false diff --git a/internal/service/auth/auth.go b/internal/service/auth/auth.go index 9ee5f3ee0..b94f7912a 100644 --- a/internal/service/auth/auth.go +++ b/internal/service/auth/auth.go @@ -138,7 +138,7 @@ func (as *AuthService) RemoveTokensExceptCurrentUser(ctx context.Context, userID as.authRepo.RemoveUserTokens(ctx, userID, accessToken) } -//Admin +// Admin func (as *AuthService) GetAdminUserCacheInfo(ctx context.Context, accessToken string) (userInfo *entity.UserCacheInfo, err error) { return as.authRepo.GetAdminUserCacheInfo(ctx, accessToken) diff --git a/internal/service/comment/comment_service.go b/internal/service/comment/comment_service.go index 3a5b3e6c9..dc599e6df 100644 --- a/internal/service/comment/comment_service.go +++ b/internal/service/comment/comment_service.go @@ -178,9 +178,8 @@ func (cs *CommentService) AddComment(ctx context.Context, req *schema.AddComment time.Now(), req.CanEdit, req.CanDelete) if comment.Status == entity.CommentStatusAvailable { - commentResp, err := cs.addCommentNotification(ctx, req, resp, comment, objInfo) - if err != nil { - return commentResp, err + if err := cs.addCommentNotification(ctx, req, resp, comment, objInfo); err != nil { + return nil, err } } @@ -220,7 +219,7 @@ func (cs *CommentService) AddComment(ctx context.Context, req *schema.AddComment func (cs *CommentService) addCommentNotification( ctx context.Context, req *schema.AddCommentReq, resp *schema.GetCommentResp, - comment *entity.Comment, objInfo *schema.SimpleObjectInfo) (*schema.GetCommentResp, error) { + comment *entity.Comment, objInfo *schema.SimpleObjectInfo) error { // The priority of the notification // 1. reply to user // 2. comment mention to user @@ -231,7 +230,7 @@ func (cs *CommentService) addCommentNotification( if len(resp.ReplyUserID) > 0 && resp.ReplyUserID != req.UserID { replyUser, exist, err := cs.userCommon.GetUserBasicInfoByID(ctx, resp.ReplyUserID) if err != nil { - return nil, err + return err } if exist { resp.ReplyUsername = replyUser.Username @@ -241,7 +240,7 @@ func (cs *CommentService) addCommentNotification( cs.notificationCommentReply(ctx, replyUser.ID, comment.ID, req.UserID, objInfo.QuestionID, objInfo.Title, htmltext.FetchExcerpt(comment.ParsedText, "...", 240)) alreadyNotifiedUserID[replyUser.ID] = true - return nil, nil + return nil } if len(req.MentionUsernameList) > 0 { @@ -250,7 +249,7 @@ func (cs *CommentService) addCommentNotification( for _, userID := range alreadyNotifiedUserIDs { alreadyNotifiedUserID[userID] = true } - return nil, nil + return nil } if objInfo.ObjectType == constant.QuestionObjectType && !alreadyNotifiedUserID[objInfo.ObjectCreatorUserID] { @@ -260,7 +259,7 @@ func (cs *CommentService) addCommentNotification( cs.notificationAnswerComment(ctx, objInfo.QuestionID, objInfo.Title, objInfo.AnswerID, objInfo.ObjectCreatorUserID, comment.ID, req.UserID, htmltext.FetchExcerpt(comment.ParsedText, "...", 240)) } - return nil, nil + return nil } // RemoveComment delete comment diff --git a/internal/service/content/answer_service.go b/internal/service/content/answer_service.go index 982bbf88a..f904b82f0 100644 --- a/internal/service/content/answer_service.go +++ b/internal/service/content/answer_service.go @@ -146,7 +146,6 @@ func (as *AnswerService) RemoveAnswer(ctx context.Context, req *schema.RemoveAns if !exist { return errors.BadRequest(reason.AnswerCannotDeleted) } - } err = as.answerRepo.RemoveAnswer(ctx, req.ID) @@ -180,10 +179,10 @@ func (as *AnswerService) RemoveAnswer(ctx context.Context, req *schema.RemoveAns // #2372 In order to simplify the process and complexity, as well as to consider if it is in-house, // facing the problem of recovery. - //err = as.answerActivityService.DeleteAnswer(ctx, answerInfo.ID, answerInfo.CreatedAt, answerInfo.VoteCount) - //if err != nil { - // log.Errorf("delete answer activity change failed: %s", err.Error()) - //} + // err = as.answerActivityService.DeleteAnswer(ctx, answerInfo.ID, answerInfo.CreatedAt, answerInfo.VoteCount) + // if err != nil { + // log.Errorf("delete answer activity change failed: %s", err.Error()) + // } as.activityQueueService.Send(ctx, &schema.ActivityMsg{ UserID: req.UserID, TriggerUserID: converter.StringToInt64(req.UserID), @@ -264,7 +263,7 @@ func (as *AnswerService) Insert(ctx context.Context, req *schema.AnswerAddReq) ( insertData.RevisionID = "0" insertData.LastEditUserID = "0" insertData.Status = entity.AnswerStatusPending - //insertData.UpdatedAt = now + // insertData.UpdatedAt = now if err = as.answerRepo.AddAnswer(ctx, insertData); err != nil { return "", err } @@ -365,7 +364,7 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq return "", errors.BadRequest(reason.QuestionNotFound) } - //If the content is the same, ignore it + // If the content is the same, ignore it if answerInfo.OriginalText == req.Content { return "", nil } diff --git a/internal/service/content/question_hottest_service.go b/internal/service/content/question_hottest_service.go index 085b36709..b73e7a30d 100644 --- a/internal/service/content/question_hottest_service.go +++ b/internal/service/content/question_hottest_service.go @@ -30,7 +30,6 @@ import ( ) func (q *QuestionService) RefreshHottestCron(ctx context.Context) { - var ( page = 1 pageSize = 100 diff --git a/internal/service/content/question_service.go b/internal/service/content/question_service.go index da15fae5d..b8372a72e 100644 --- a/internal/service/content/question_service.go +++ b/internal/service/content/question_service.go @@ -216,9 +216,9 @@ func (qs *QuestionService) ReopenQuestion(ctx context.Context, req *schema.Reope return nil } -func (qs *QuestionService) AddQuestionCheckTags(ctx context.Context, Tags []*entity.Tag) ([]string, error) { +func (qs *QuestionService) AddQuestionCheckTags(ctx context.Context, tags []*entity.Tag) ([]string, error) { list := make([]string, 0) - for _, tag := range Tags { + for _, tag := range tags { if tag.Reserved { list = append(list, tag.DisplayName) } @@ -374,14 +374,14 @@ func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.Question question.AcceptedAnswerID = "0" question.LastAnswerID = "0" question.LastEditUserID = "0" - //question.PostUpdateTime = nil + // question.PostUpdateTime = nil question.Status = entity.QuestionStatusPending question.RevisionID = "0" question.CreatedAt = now question.PostUpdateTime = now question.Pin = entity.QuestionUnPin question.Show = entity.QuestionShow - //question.UpdatedAt = nil + // question.UpdatedAt = nil err = qs.questionRepo.AddQuestion(ctx, question) if err != nil { return @@ -416,10 +416,7 @@ func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.Question Title: question.Title, } - questionWithTagsRevision, err := qs.changeQuestionToRevision(ctx, question, tags) - if err != nil { - return nil, err - } + questionWithTagsRevision := qs.changeQuestionToRevision(ctx, question, tags) infoJSON, _ := json.Marshal(questionWithTagsRevision) revisionDTO.Content = string(infoJSON) revisionID, err := qs.revisionService.AddRevision(ctx, revisionDTO, true) @@ -554,7 +551,7 @@ func (qs *QuestionService) RemoveQuestion(ctx context.Context, req *schema.Remov if err != nil { return err } - //if the status is deleted, return directly + // if the status is deleted, return directly if questionInfo.Status == entity.QuestionStatusDeleted { return nil } @@ -613,7 +610,7 @@ func (qs *QuestionService) RemoveQuestion(ctx context.Context, req *schema.Remov } } - //tag count + // tag count tagIDs := make([]string, 0) Tags, tagerr := qs.tagCommon.GetObjectEntityTag(ctx, req.ID) if tagerr != nil { @@ -684,7 +681,7 @@ func (qs *QuestionService) UpdateQuestionCheckTags(ctx context.Context, req *sch isChange := qs.tagCommon.CheckTagsIsChange(ctx, tagNameList, oldtagNameList) - //If the content is the same, ignore it + // If the content is the same, ignore it if dbinfo.Title == req.Title && dbinfo.OriginalText == req.Content && !isChange { return } @@ -798,7 +795,7 @@ func (qs *QuestionService) UpdateQuestionInviteUser(ctx context.Context, req *sc return errors.BadRequest(reason.QuestionNotFound) } - //verify invite user + // verify invite user inviteUserInfoList, err := qs.userCommon.BatchGetUserBasicInfoByUserNames(ctx, req.InviteUser) if err != nil { log.Error("BatchGetUserBasicInfoByUserNames error", err.Error()) @@ -826,7 +823,7 @@ func (qs *QuestionService) UpdateQuestionInviteUser(ctx context.Context, req *sc if saveerr != nil { return saveerr } - //send notification + // send notification oldInviteUserIDsStr := originQuestion.InviteUserID oldInviteUserIDs := make([]string, 0) needSendNotificationUserIDs := make([]string, 0) @@ -964,7 +961,7 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest isChange := qs.tagCommon.CheckTagsIsChange(ctx, tagNameList, oldtagNameList) - //If the content is the same, ignore it + // If the content is the same, ignore it if dbinfo.Title == req.Title && dbinfo.OriginalText == req.Content && !isChange { return } @@ -1015,7 +1012,7 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest return errorlist, err } - //Administrators and themselves do not need to be audited + // Administrators and themselves do not need to be audited revisionDTO := &schema.AddRevisionDTO{ UserID: question.UserID, @@ -1031,11 +1028,11 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest // It's not you or the administrator that needs to be reviewed if !canUpdate { revisionDTO.Status = entity.RevisionUnreviewedStatus - revisionDTO.UserID = req.UserID //use revision userid + revisionDTO.UserID = req.UserID // use revision userid } else { - //Direct modification + // Direct modification revisionDTO.Status = entity.RevisionReviewPassStatus - //update question to db + // update question to db question.ParsedText, err = qs.questioncommon.UpdateQuestionLink(ctx, question.ID, "", question.ParsedText, question.OriginalText) if err != nil { return questionInfo, err @@ -1054,10 +1051,7 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest } } - questionWithTagsRevision, err := qs.changeQuestionToRevision(ctx, question, Tags) - if err != nil { - return nil, err - } + questionWithTagsRevision := qs.changeQuestionToRevision(ctx, question, Tags) infoJSON, _ := json.Marshal(questionWithTagsRevision) revisionDTO.Content = string(infoJSON) revisionID, err := qs.revisionService.AddRevision(ctx, revisionDTO, true) @@ -1165,7 +1159,6 @@ func (qs *QuestionService) CheckChangeReservedTag(ctx context.Context, oldobject // PersonalQuestionPage get question list by user func (qs *QuestionService) PersonalQuestionPage(ctx context.Context, req *schema.PersonalQuestionPageReq) ( pageModel *pager.PageModel, err error) { - userinfo, exist, err := qs.userCommon.GetUserBasicInfoByUserName(ctx, req.Username) if err != nil { return nil, err @@ -1250,7 +1243,6 @@ func (qs *QuestionService) PersonalAnswerPage(ctx context.Context, req *schema.P info.QuestionID = item.QuestionID if item.QuestionInfo.Status == entity.QuestionStatusDeleted { info.QuestionInfo.Title = "Deleted question" - } userAnswerlist = append(userAnswerlist, info) } @@ -1489,7 +1481,8 @@ func (qs *QuestionService) GetQuestionPage(ctx context.Context, req *schema.Ques if err != nil { return nil, 0, err } - tagIDs = append(synTagIds, tagInfo.ID) + tagIDs = append(tagIDs, synTagIds...) + tagIDs = append(tagIDs, tagInfo.ID) } else { return questions, 0, nil } @@ -1585,10 +1578,10 @@ func (qs *QuestionService) AdminSetQuestionStatus(ctx context.Context, req *sche if setStatus == entity.QuestionStatusDeleted { // #2372 In order to simplify the process and complexity, as well as to consider if it is in-house, // facing the problem of recovery. - //err = qs.answerActivityService.DeleteQuestion(ctx, questionInfo.ID, questionInfo.CreatedAt, questionInfo.VoteCount) - //if err != nil { - // log.Errorf("admin delete question then rank rollback error %s", err.Error()) - //} + // err = qs.answerActivityService.DeleteQuestion(ctx, questionInfo.ID, questionInfo.CreatedAt, questionInfo.VoteCount) + // if err != nil { + // log.Errorf("admin delete question then rank rollback error %s", err.Error()) + // } qs.activityQueueService.Send(ctx, &schema.ActivityMsg{ UserID: questionInfo.UserID, TriggerUserID: converter.StringToInt64(req.UserID), @@ -1642,7 +1635,6 @@ func (qs *QuestionService) AdminSetQuestionStatus(ctx context.Context, req *sche func (qs *QuestionService) AdminQuestionPage( ctx context.Context, req *schema.AdminQuestionPageReq) ( resp *pager.PageModel, err error) { - list := make([]*schema.AdminQuestionInfo, 0) questionList, count, err := qs.questionRepo.AdminQuestionPage(ctx, req) if err != nil { @@ -1708,8 +1700,8 @@ func (qs *QuestionService) AdminAnswerPage(ctx context.Context, req *schema.Admi return pager.NewPageModel(count, answerResp), nil } -func (qs *QuestionService) changeQuestionToRevision(ctx context.Context, questionInfo *entity.Question, tags []*entity.Tag) ( - questionRevision *entity.QuestionWithTagsRevision, err error) { +func (qs *QuestionService) changeQuestionToRevision(_ context.Context, questionInfo *entity.Question, tags []*entity.Tag) ( + questionRevision *entity.QuestionWithTagsRevision) { questionRevision = &entity.QuestionWithTagsRevision{} questionRevision.Question = *questionInfo @@ -1718,7 +1710,7 @@ func (qs *QuestionService) changeQuestionToRevision(ctx context.Context, questio _ = copier.Copy(item, tag) questionRevision.Tags = append(questionRevision.Tags, item) } - return questionRevision, nil + return questionRevision } func (qs *QuestionService) SitemapCron(ctx context.Context) { diff --git a/internal/service/content/revision_service.go b/internal/service/content/revision_service.go index a5cefeb41..4ac08e769 100644 --- a/internal/service/content/revision_service.go +++ b/internal/service/content/revision_service.go @@ -235,7 +235,6 @@ func (rs *RevisionService) revisionAuditQuestion(ctx context.Context, revisionit func (rs *RevisionService) revisionAuditAnswer(ctx context.Context, revisionitem *schema.GetRevisionResp) (err error) { answerinfo, ok := revisionitem.ContentParsed.(*schema.AnswerInfo) if ok { - var PostUpdateTime time.Time dbquestion, exist, dberr := rs.questionRepo.GetQuestion(ctx, answerinfo.QuestionID) if dberr != nil || !exist { diff --git a/internal/service/content/search_service.go b/internal/service/content/search_service.go index ccafcd82c..866f1c6e2 100644 --- a/internal/service/content/search_service.go +++ b/internal/service/content/search_service.go @@ -68,13 +68,14 @@ func (ss *SearchService) Search(ctx context.Context, dto *schema.SearchDTO) (res resp = &schema.SearchResp{} // search plugin is not found, call system search if finder == nil { - if cond.SearchAll() { + switch { + case cond.SearchAll(): resp.SearchResults, resp.Total, err = ss.searchRepo.SearchContents(ctx, cond.Words, cond.Tags, cond.UserID, cond.VoteAmount, dto.Page, dto.Size, dto.Order) - } else if cond.SearchQuestion() { + case cond.SearchQuestion(): resp.SearchResults, resp.Total, err = ss.searchRepo.SearchQuestions(ctx, cond.Words, cond.Tags, cond.NotAccepted, cond.Views, cond.AnswerAmount, dto.Page, dto.Size, dto.Order) - } else if cond.SearchAnswer() { + case cond.SearchAnswer(): resp.SearchResults, resp.Total, err = ss.searchRepo.SearchAnswers(ctx, cond.Words, cond.Tags, cond.Accepted, cond.QuestionID, dto.Page, dto.Size, dto.Order) } @@ -86,11 +87,12 @@ func (ss *SearchService) Search(ctx context.Context, dto *schema.SearchDTO) (res func (ss *SearchService) searchByPlugin(ctx context.Context, finder plugin.Search, cond *schema.SearchCondition, dto *schema.SearchDTO) (resp *schema.SearchResp, err error) { var res []plugin.SearchResult resp = &schema.SearchResp{} - if cond.SearchAll() { + switch { + case cond.SearchAll(): res, resp.Total, err = finder.SearchContents(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order)) - } else if cond.SearchQuestion() { + case cond.SearchQuestion(): res, resp.Total, err = finder.SearchQuestions(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order)) - } else if cond.SearchAnswer() { + case cond.SearchAnswer(): res, resp.Total, err = finder.SearchAnswers(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order)) } if err != nil { diff --git a/internal/service/content/user_service.go b/internal/service/content/user_service.go index 81f7ac824..e9cc35788 100644 --- a/internal/service/content/user_service.go +++ b/internal/service/content/user_service.go @@ -314,7 +314,6 @@ func (us *UserService) UserModifyPassword(ctx context.Context, req *schema.UserM // UpdateInfo update user info func (us *UserService) UpdateInfo(ctx context.Context, req *schema.UpdateInfoRequest) ( errFields []*validator.FormErrorField, err error) { - if len(req.Username) > 0 { if checker.IsInvalidUsername(req.Username) { return append(errFields, &validator.FormErrorField{ @@ -598,7 +597,7 @@ func (us *UserService) UserVerifyEmail(ctx context.Context, req *schema.UserVeri // verifyPassword // Compare whether the password is correct -func (us *UserService) verifyPassword(ctx context.Context, loginPass, userPass string) bool { +func (us *UserService) verifyPassword(_ context.Context, loginPass, userPass string) bool { if len(loginPass) == 0 && len(userPass) == 0 { return true } @@ -608,8 +607,8 @@ func (us *UserService) verifyPassword(ctx context.Context, loginPass, userPass s // encryptPassword // The password does irreversible encryption. -func (us *UserService) encryptPassword(ctx context.Context, Pass string) (string, error) { - hashPwd, err := bcrypt.GenerateFromPassword([]byte(Pass), bcrypt.DefaultCost) +func (us *UserService) encryptPassword(_ context.Context, pass string) (string, error) { + hashPwd, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) // This encrypted string can be saved to the database and can be used as password matching verification return string(hashPwd), err } diff --git a/internal/service/dashboard/dashboard_service.go b/internal/service/dashboard/dashboard_service.go index 91f0e338a..8b08ba02f 100644 --- a/internal/service/dashboard/dashboard_service.go +++ b/internal/service/dashboard/dashboard_service.go @@ -264,7 +264,7 @@ func (ds *dashboardService) voteCount(ctx context.Context) int64 { return voteCount } -func (ds *dashboardService) remoteVersion(ctx context.Context) string { +func (ds *dashboardService) remoteVersion(_ context.Context) string { req, _ := http.NewRequest("GET", "https://answer.apache.org/data/latest.json?from_version="+constant.Version, nil) req.Header.Set("User-Agent", "Answer/"+constant.Version) httpClient := &http.Client{} @@ -359,11 +359,9 @@ func (ds *dashboardService) GetDatabaseSize() (dbSize string) { res, err := ds.data.DB.QueryInterface(sql) if err != nil { log.Warnf("get db size failed: %s", err) - } else { - if len(res) > 0 && res[0]["db_size"] != nil { - dbSizeStr, _ := res[0]["db_size"].(string) - dbSize = dir.FormatFileSize(converter.StringToInt64(dbSizeStr)) - } + } else if len(res) > 0 && res[0]["db_size"] != nil { + dbSizeStr, _ := res[0]["db_size"].(string) + dbSize = dir.FormatFileSize(converter.StringToInt64(dbSizeStr)) } case schemas.POSTGRES: sql := fmt.Sprintf("SELECT pg_database_size('%s') AS db_size", @@ -371,11 +369,9 @@ func (ds *dashboardService) GetDatabaseSize() (dbSize string) { res, err := ds.data.DB.QueryInterface(sql) if err != nil { log.Warnf("get db size failed: %s", err) - } else { - if len(res) > 0 && res[0]["db_size"] != nil { - dbSizeStr, _ := res[0]["db_size"].(int32) - dbSize = dir.FormatFileSize(int64(dbSizeStr)) - } + } else if len(res) > 0 && res[0]["db_size"] != nil { + dbSizeStr, _ := res[0]["db_size"].(int32) + dbSize = dir.FormatFileSize(int64(dbSizeStr)) } case schemas.SQLITE: dirSize, err := dir.DirSize(ds.data.DB.DataSourceName()) diff --git a/internal/service/notification/invite_answer_notification.go b/internal/service/notification/invite_answer_notification.go index f68feb067..6b0407f9f 100644 --- a/internal/service/notification/invite_answer_notification.go +++ b/internal/service/notification/invite_answer_notification.go @@ -45,8 +45,7 @@ func (ns *ExternalNotificationService) handleInviteAnswerNotification(ctx contex if !channel.Enable { continue } - switch channel.Key { - case constant.EmailChannel: + if channel.Key == constant.EmailChannel { ns.sendInviteAnswerNotificationEmail(ctx, msg.ReceiverUserID, msg.ReceiverEmail, msg.ReceiverLang, msg.NewInviteAnswerTemplateRawData) } } diff --git a/internal/service/notification/new_answer_notification.go b/internal/service/notification/new_answer_notification.go index c54fd961c..4ae9ca9ea 100644 --- a/internal/service/notification/new_answer_notification.go +++ b/internal/service/notification/new_answer_notification.go @@ -45,8 +45,7 @@ func (ns *ExternalNotificationService) handleNewAnswerNotification(ctx context.C if !channel.Enable { continue } - switch channel.Key { - case constant.EmailChannel: + if channel.Key == constant.EmailChannel { ns.sendNewAnswerNotificationEmail(ctx, msg.ReceiverUserID, msg.ReceiverEmail, msg.ReceiverLang, msg.NewAnswerTemplateRawData) } } diff --git a/internal/service/notification/new_comment_notification.go b/internal/service/notification/new_comment_notification.go index e622ed4f7..9734e54e5 100644 --- a/internal/service/notification/new_comment_notification.go +++ b/internal/service/notification/new_comment_notification.go @@ -45,8 +45,7 @@ func (ns *ExternalNotificationService) handleNewCommentNotification(ctx context. if !channel.Enable { continue } - switch channel.Key { - case constant.EmailChannel: + if channel.Key == constant.EmailChannel { ns.sendNewCommentNotificationEmail(ctx, msg.ReceiverUserID, msg.ReceiverEmail, msg.ReceiverLang, msg.NewCommentTemplateRawData) } } diff --git a/internal/service/notification/new_question_notification.go b/internal/service/notification/new_question_notification.go index debfb8c27..2f83042b2 100644 --- a/internal/service/notification/new_question_notification.go +++ b/internal/service/notification/new_question_notification.go @@ -55,8 +55,7 @@ func (ns *ExternalNotificationService) handleNewQuestionNotification(ctx context if !channel.Enable { continue } - switch channel.Key { - case constant.EmailChannel: + if channel.Key == constant.EmailChannel { ns.sendNewQuestionNotificationEmail(ctx, subscriber.UserID, &schema.NewQuestionTemplateRawData{ QuestionTitle: msg.NewQuestionTemplateRawData.QuestionTitle, QuestionID: msg.NewQuestionTemplateRawData.QuestionID, diff --git a/internal/service/notification/notification_service.go b/internal/service/notification/notification_service.go index 0369d4557..6a69cbaef 100644 --- a/internal/service/notification/notification_service.go +++ b/internal/service/notification/notification_service.go @@ -226,15 +226,12 @@ func (ns *NotificationService) GetNotificationPage(ctx context.Context, searchCo if err != nil { return nil, err } - resp, err = ns.formatNotificationPage(ctx, notifications) - if err != nil { - return nil, err - } + resp = ns.formatNotificationPage(ctx, notifications) return pager.NewPageModel(total, resp), nil } func (ns *NotificationService) formatNotificationPage(ctx context.Context, notifications []*entity.Notification) ( - resp []*schema.NotificationContent, err error) { + resp []*schema.NotificationContent) { lang := handler.GetLangByCtx(ctx) enableShortID := handler.GetEnableShortID(ctx) userIDs := make([]string, 0) @@ -287,13 +284,13 @@ func (ns *NotificationService) formatNotificationPage(ctx context.Context, notif } if len(userIDs) == 0 { - return resp, nil + return resp } users, err := ns.userRepo.BatchGetByID(ctx, userIDs) if err != nil { log.Error(err) - return resp, nil + return resp } userIDMapping := make(map[string]*entity.User, len(users)) for _, user := range users { @@ -314,5 +311,5 @@ func (ns *NotificationService) formatNotificationPage(ctx context.Context, notif } } } - return resp, nil + return resp } diff --git a/internal/service/notification_common/notification.go b/internal/service/notification_common/notification.go index 55d638424..0bbd1865f 100644 --- a/internal/service/notification_common/notification.go +++ b/internal/service/notification_common/notification.go @@ -155,7 +155,7 @@ func (ns *NotificationCommon) AddNotification(ctx context.Context, msg *schema.N } req.Rank = rank if exist { - //modify notification + // modify notification updateContent := &schema.NotificationContent{} err := json.Unmarshal([]byte(notificationInfo.Content), updateContent) if err != nil { diff --git a/internal/service/plugin_common/plugin_common_service.go b/internal/service/plugin_common/plugin_common_service.go index d3aa839b2..7d39a5aa0 100644 --- a/internal/service/plugin_common/plugin_common_service.go +++ b/internal/service/plugin_common/plugin_common_service.go @@ -69,7 +69,6 @@ func NewPluginCommonService( data *data.Data, importerService *importer.ImporterService, ) *PluginCommonService { - p := &PluginCommonService{ configService: configService, pluginConfigRepo: pluginConfigRepo, diff --git a/internal/service/question_common/question.go b/internal/service/question_common/question.go index 333806445..846dea894 100644 --- a/internal/service/question_common/question.go +++ b/internal/service/question_common/question.go @@ -179,17 +179,17 @@ func (qs *QuestionCommon) UpdateCollectionCount(ctx context.Context, questionID return qs.questionRepo.UpdateCollectionCount(ctx, questionID) } -func (qs *QuestionCommon) UpdateAccepted(ctx context.Context, questionID, AnswerID string) error { +func (qs *QuestionCommon) UpdateAccepted(ctx context.Context, questionID, answerID string) error { question := &entity.Question{} question.ID = questionID - question.AcceptedAnswerID = AnswerID + question.AcceptedAnswerID = answerID return qs.questionRepo.UpdateAccepted(ctx, question) } -func (qs *QuestionCommon) UpdateLastAnswer(ctx context.Context, questionID, AnswerID string) error { +func (qs *QuestionCommon) UpdateLastAnswer(ctx context.Context, questionID, answerID string) error { question := &entity.Question{} question.ID = questionID - question.LastAnswerID = AnswerID + question.LastAnswerID = answerID return qs.questionRepo.UpdateLastAnswer(ctx, question) } @@ -232,7 +232,7 @@ func (qs *QuestionCommon) InviteUserInfo(ctx context.Context, questionID string) if !has { return InviteUserInfo, errors.NotFound(reason.QuestionNotFound) } - //InviteUser + // InviteUser if dbinfo.InviteUserID != "" { InviteUserIDs := make([]string, 0) err := json.Unmarshal([]byte(dbinfo.InviteUserID), &InviteUserIDs) @@ -681,7 +681,6 @@ func (qs *QuestionCommon) ShowFormat(ctx context.Context, data *entity.Question) info.LastAnsweredUserID = answerInfo.UserID } } - } info.Tags = make([]*schema.TagResp, 0) return &info diff --git a/internal/service/siteinfo_common/siteinfo_service_test.go b/internal/service/siteinfo_common/siteinfo_service_test.go index 3a567dcb9..a87d427f2 100644 --- a/internal/service/siteinfo_common/siteinfo_service_test.go +++ b/internal/service/siteinfo_common/siteinfo_service_test.go @@ -27,6 +27,7 @@ import ( "github.com/apache/answer/internal/entity" "github.com/apache/answer/internal/service/mock" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ) @@ -46,6 +47,6 @@ func TestSiteInfoCommonService_GetSiteGeneral(t *testing.T) { mockInit(ctl) siteInfoCommonService := NewSiteInfoCommonService(mockSiteInfoRepo) resp, err := siteInfoCommonService.GetSiteGeneral(context.TODO()) - assert.NoError(t, err) - assert.Equal(t, resp.Name, "name") + require.NoError(t, err) + assert.Equal(t, "name", resp.Name) } diff --git a/internal/service/tag/tag_service.go b/internal/service/tag/tag_service.go index 577199ec8..e61bfa06e 100644 --- a/internal/service/tag/tag_service.go +++ b/internal/service/tag/tag_service.go @@ -74,7 +74,7 @@ func NewTagService( // RemoveTag delete tag func (ts *TagService) RemoveTag(ctx context.Context, req *schema.RemoveTagReq) (err error) { - //If the tag has associated problems, it cannot be deleted + // If the tag has associated problems, it cannot be deleted tagCount, err := ts.tagCommonService.CountTagRelByTagID(ctx, req.TagID) if err != nil { return err @@ -83,7 +83,7 @@ func (ts *TagService) RemoveTag(ctx context.Context, req *schema.RemoveTagReq) ( return errors.BadRequest(reason.TagIsUsedCannotDelete) } - //If the tag has associated problems, it cannot be deleted + // If the tag has associated problems, it cannot be deleted tagSynonymCount, err := ts.tagRepo.GetTagSynonymCount(ctx, req.TagID) if err != nil { return err diff --git a/internal/service/tag_common/tag_common.go b/internal/service/tag_common/tag_common.go index fed5dfbfb..87c10bcc9 100644 --- a/internal/service/tag_common/tag_common.go +++ b/internal/service/tag_common/tag_common.go @@ -591,7 +591,6 @@ func (ts *TagCommonService) CheckTag(ctx context.Context, tags []string, userID err = errors.BadRequest(reason.TagNotFound).WithMsg(fmt.Sprintf("tag [%s] does not exist", strings.Join(addTagMsgList, ","))) return err - } return nil @@ -660,9 +659,8 @@ func (ts *TagCommonService) CheckChangeReservedTag(ctx context.Context, oldobjec // ObjectChangeTag change object tag list func (ts *TagCommonService) ObjectChangeTag(ctx context.Context, objectTagData *schema.TagChange, minimumTags int) (errorlist []*validator.FormErrorField, err error) { - //checks if the tags sent in the put req are less than the minimum, if so, tag changes are not applied + // checks if the tags sent in the put req are less than the minimum, if so, tag changes are not applied if len(objectTagData.Tags) < minimumTags { - errorlist := make([]*validator.FormErrorField, 0) errorlist = append(errorlist, &validator.FormErrorField{ ErrorField: "tags", @@ -884,11 +882,11 @@ func (ts *TagCommonService) UpdateTag(ctx context.Context, req *schema.UpdateTag return errors.BadRequest(reason.TagNotFound) } - //Adding equivalent slug formatting for tag update + // Adding equivalent slug formatting for tag update slugName := strings.ReplaceAll(req.SlugName, " ", "-") slugName = strings.ToLower(slugName) - //If the content is the same, ignore it + // If the content is the same, ignore it if tagInfo.OriginalText == req.OriginalText && tagInfo.DisplayName == req.DisplayName && tagInfo.SlugName == slugName { diff --git a/internal/service/uploader/upload.go b/internal/service/uploader/upload.go index 30029193b..8dea746ce 100644 --- a/internal/service/uploader/upload.go +++ b/internal/service/uploader/upload.go @@ -135,7 +135,6 @@ func (us *uploaderService) UploadAvatarFile(ctx *gin.Context, userID string) (ur } us.fileRecordService.AddFileRecord(ctx, userID, avatarFilePath, url, string(plugin.UserAvatar)) return url, nil - } func (us *uploaderService) AvatarThumbFile(ctx *gin.Context, fileName string, size int) (url string, err error) { @@ -304,7 +303,6 @@ func (us *uploaderService) UploadBrandingFile(ctx *gin.Context, userID string) ( } us.fileRecordService.AddFileRecord(ctx, userID, avatarFilePath, url, string(plugin.AdminBranding)) return url, nil - } func (us *uploaderService) uploadImageFile(ctx *gin.Context, file *multipart.FileHeader, fileSubPath string) ( diff --git a/internal/service/user_admin/user_backyard.go b/internal/service/user_admin/user_backyard.go index 6fce161ce..fcced1c8b 100644 --- a/internal/service/user_admin/user_backyard.go +++ b/internal/service/user_admin/user_backyard.go @@ -470,14 +470,15 @@ func (us *UserAdminService) GetUserPage(ctx context.Context, req *schema.GetUser user := &entity.User{} _ = copier.Copy(user, req) - if req.IsInactive() { + switch { + case req.IsInactive(): user.MailStatus = entity.EmailStatusToBeVerified user.Status = entity.UserStatusAvailable - } else if req.IsSuspended() { + case req.IsSuspended(): user.Status = entity.UserStatusSuspended - } else if req.IsDeleted() { + case req.IsDeleted(): user.Status = entity.UserStatusDeleted - } else { + default: user.MailStatus = entity.EmailStatusAvailable user.Status = entity.UserStatusAvailable } @@ -486,8 +487,8 @@ func (us *UserAdminService) GetUserPage(ctx context.Context, req *schema.GetUser if email, e := mail.ParseAddress(req.Query); e == nil { user.EMail = email.Address req.Query = "" - } else if strings.HasPrefix(req.Query, "user:") { - id := strings.TrimSpace(strings.TrimPrefix(req.Query, "user:")) + } else if after, ok := strings.CutPrefix(req.Query, "user:"); ok { + id := strings.TrimSpace(after) idSearch := true for _, r := range id { if !unicode.IsDigit(r) { @@ -521,18 +522,19 @@ func (us *UserAdminService) GetUserPage(ctx context.Context, req *schema.GetUser DisplayName: u.DisplayName, Avatar: avatarMapping[u.ID].GetURL(), } - if u.Status == entity.UserStatusDeleted { + switch { + case u.Status == entity.UserStatusDeleted: t.Status = constant.UserDeleted t.DeletedAt = u.DeletedAt.Unix() - } else if u.Status == entity.UserStatusSuspended { + case u.Status == entity.UserStatusSuspended: t.Status = constant.UserSuspended t.SuspendedAt = u.SuspendedAt.Unix() if !u.SuspendedUntil.IsZero() { t.SuspendedUntil = u.SuspendedUntil.Unix() } - } else if u.MailStatus == entity.EmailStatusToBeVerified { + case u.MailStatus == entity.EmailStatusToBeVerified: t.Status = constant.UserInactive - } else { + default: t.Status = constant.UserNormal } resp = append(resp, t) @@ -646,7 +648,6 @@ func (us *UserAdminService) CheckAndUnsuspendExpiredUsers(ctx context.Context) e if user.Status == entity.UserStatusSuspended && !user.SuspendedUntil.IsZero() && user.SuspendedUntil.Before(now) { - log.Infof("Unsuspending user %s (ID: %s) - suspension expired at %v", user.Username, user.ID, user.SuspendedUntil) diff --git a/internal/service/user_common/user.go b/internal/service/user_common/user.go index 124972a16..2e777f14c 100644 --- a/internal/service/user_common/user.go +++ b/internal/service/user_common/user.go @@ -85,9 +85,9 @@ func NewUserCommon( } } -func (us *UserCommon) GetUserBasicInfoByID(ctx context.Context, ID string) ( +func (us *UserCommon) GetUserBasicInfoByID(ctx context.Context, id string) ( userBasicInfo *schema.UserBasicInfo, exist bool, err error) { - userInfo, exist, err := us.userRepo.GetByUserID(ctx, ID) + userInfo, exist, err := us.userRepo.GetByUserID(ctx, id) if err != nil { return nil, exist, err } diff --git a/internal/service/user_notification_config/user_notification_config_service.go b/internal/service/user_notification_config/user_notification_config_service.go index c40df55cf..8ab72fa94 100644 --- a/internal/service/user_notification_config/user_notification_config_service.go +++ b/internal/service/user_notification_config/user_notification_config_service.go @@ -96,7 +96,7 @@ func (us *UserNotificationConfigService) SetDefaultUserNotificationConfig(ctx co string(constant.InboxSource), `[{"key":"email","enable":true}]`) } -func (us *UserNotificationConfigService) convertToEntity(ctx context.Context, userID string, +func (us *UserNotificationConfigService) convertToEntity(_ context.Context, userID string, source constant.NotificationSource, channel schema.NotificationChannelConfig) (c *entity.UserNotificationConfig) { var channels schema.NotificationChannels channels = append(channels, &channel) diff --git a/pkg/checker/file_type.go b/pkg/checker/file_type.go index ac1fbcaf9..8eaabcbfc 100644 --- a/pkg/checker/file_type.go +++ b/pkg/checker/file_type.go @@ -28,6 +28,7 @@ import ( "io" "os" "path/filepath" + "slices" "strings" "github.com/segmentfault/pacman/log" @@ -38,12 +39,7 @@ import ( // WANING Only checks the file extension is not reliable, but `http.DetectContentType` and `mimetype` are not reliable for all file types. func IsUnAuthorizedExtension(fileName string, allowedExtensions []string) bool { ext := strings.ToLower(strings.Trim(filepath.Ext(fileName), ".")) - for _, extension := range allowedExtensions { - if extension == ext { - return false - } - } - return true + return !slices.Contains(allowedExtensions, ext) } // DecodeAndCheckImageFile currently answers support image type is diff --git a/pkg/checker/path_ignore.go b/pkg/checker/path_ignore.go index 8be757be5..24b092f7c 100644 --- a/pkg/checker/path_ignore.go +++ b/pkg/checker/path_ignore.go @@ -20,6 +20,7 @@ package checker import ( + "slices" "sync" "github.com/apache/answer/configs" @@ -46,21 +47,11 @@ func initPathIgnore() { // IsUsersIgnorePath checks whether the username is in ignore path func IsUsersIgnorePath(username string) bool { ignorePathInit.Do(initPathIgnore) - for _, u := range pathIgnore.Users { - if u == username { - return true - } - } - return false + return slices.Contains(pathIgnore.Users, username) } // IsQuestionsIgnorePath checks whether the questionID is in ignore path func IsQuestionsIgnorePath(questionID string) bool { ignorePathInit.Do(initPathIgnore) - for _, u := range pathIgnore.Questions { - if u == questionID { - return true - } - } - return false + return slices.Contains(pathIgnore.Questions, questionID) } diff --git a/pkg/checker/question_link.go b/pkg/checker/question_link.go index 41b246c36..efd19b3c3 100644 --- a/pkg/checker/question_link.go +++ b/pkg/checker/question_link.go @@ -44,15 +44,16 @@ func GetQuestionLink(content string) []QuestionLink { left, right := 0, 0 for right < len(content) { // find "/questions/" or "#" - if right+11 < len(content) && content[right:right+11] == "/questions/" { + switch { + case right+11 < len(content) && content[right:right+11] == "/questions/": left = right right += 11 processURL(content, &left, &right, uniqueIDs, &questionLinks) - } else if content[right] == '#' { + case content[right] == '#': left = right + 1 right = left processID(content, &left, &right, uniqueIDs, &questionLinks) - } else { + default: right++ } } @@ -101,9 +102,7 @@ func addUniqueID(questionID, answerID string, linkType int, uniqueIDs map[string objectType, err := obj.GetObjectTypeStrByObjectID(uid.DeShortID(answerID)) if err != nil { answerID = "" - } - - if objectType == constant.AnswerObjectType { + } else if objectType == constant.AnswerObjectType { if _, ok := uniqueIDs[answerID]; !ok { uniqueIDs[answerID] = struct{}{} isAdd = true diff --git a/pkg/converter/markdown.go b/pkg/converter/markdown.go index d16915a84..adae3faf6 100644 --- a/pkg/converter/markdown.go +++ b/pkg/converter/markdown.go @@ -107,7 +107,7 @@ func (r *DangerousHTMLRenderer) renderRawHTML(w util.BufWriter, source []byte, n } n := node.(*ast.RawHTML) l := n.Segments.Len() - for i := 0; i < l; i++ { + for i := range l { segment := n.Segments.At(i) if string(source[segment.Start:segment.Stop]) == "" || string(source[segment.Start:segment.Stop]) == "" { _, _ = w.Write(segment.Value(source)) @@ -122,15 +122,13 @@ func (r *DangerousHTMLRenderer) renderHTMLBlock(w util.BufWriter, source []byte, n := node.(*ast.HTMLBlock) if entering { l := n.Lines().Len() - for i := 0; i < l; i++ { + for i := range l { line := n.Lines().At(i) r.Writer.SecureWrite(w, line.Value(source)) } - } else { - if n.HasClosure() { - closure := n.ClosureLine - r.Writer.SecureWrite(w, closure.Value(source)) - } + } else if n.HasClosure() { + closure := n.ClosureLine + r.Writer.SecureWrite(w, closure.Value(source)) } return ast.WalkContinue, nil } @@ -184,8 +182,8 @@ func (r *DangerousHTMLRenderer) renderAutoLink(w util.BufWriter, source []byte, return ast.WalkContinue, nil } -func (r *DangerousHTMLRenderer) renderLinkIsUrl(verifyUrl string) bool { - isURL := govalidator.IsURL(verifyUrl) - isPath, _ := regexp.MatchString(`^/`, verifyUrl) +func (r *DangerousHTMLRenderer) renderLinkIsUrl(verifyURL string) bool { + isURL := govalidator.IsURL(verifyURL) + isPath, _ := regexp.MatchString(`^/`, verifyURL) return isURL || isPath } diff --git a/pkg/day/day.go b/pkg/day/day.go index 90afac0ad..2fd86a6c9 100644 --- a/pkg/day/day.go +++ b/pkg/day/day.go @@ -20,6 +20,7 @@ package day import ( + "strings" "time" ) @@ -50,16 +51,16 @@ func Format(unix int64, format, tz string) (formatted string) { for i := l; i >= 0; i-- { format = strings.ReplaceAll(format, placeholders[i].old, placeholders[i].new) }*/ - toFormat := "" + var toFormat strings.Builder from := []rune(format) for len(from) > 0 { to, suffix := nextStdChunk(from) - toFormat += string(to) + toFormat.WriteString(string(to)) from = suffix } _, _ = time.LoadLocation(tz) - formatted = time.Unix(unix, 0).Format(toFormat) + formatted = time.Unix(unix, 0).Format(toFormat.String()) return } diff --git a/pkg/dir/dir.go b/pkg/dir/dir.go index 928883c2e..09591f6ca 100644 --- a/pkg/dir/dir.go +++ b/pkg/dir/dir.go @@ -51,19 +51,19 @@ func DirSize(path string) (int64, error) { } func FormatFileSize(fileSize int64) (size string) { - if fileSize < 1024 { - //return strconv.FormatInt(fileSize, 10) + "B" + switch { + case fileSize < 1024: + // return strconv.FormatInt(fileSize, 10) + "B" return fmt.Sprintf("%.2f B", float64(fileSize)/float64(1)) - } else if fileSize < (1024 * 1024) { + case fileSize < (1024 * 1024): return fmt.Sprintf("%.2f KB", float64(fileSize)/float64(1024)) - } else if fileSize < (1024 * 1024 * 1024) { + case fileSize < (1024 * 1024 * 1024): return fmt.Sprintf("%.2f MB", float64(fileSize)/float64(1024*1024)) - } else if fileSize < (1024 * 1024 * 1024 * 1024) { + case fileSize < (1024 * 1024 * 1024 * 1024): return fmt.Sprintf("%.2f GB", float64(fileSize)/float64(1024*1024*1024)) - } else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) { + case fileSize < (1024 * 1024 * 1024 * 1024 * 1024): return fmt.Sprintf("%.2f TB", float64(fileSize)/float64(1024*1024*1024*1024)) - } else { //if fileSize < (1024 * 1024 * 1024 * 1024 * 1024 * 1024) + default: // if fileSize < (1024 * 1024 * 1024 * 1024 * 1024 * 1024) return fmt.Sprintf("%.2f EB", float64(fileSize)/float64(1024*1024*1024*1024*1024)) } - } diff --git a/pkg/htmltext/htmltext.go b/pkg/htmltext/htmltext.go index 56db4d2b2..e2e017c8d 100644 --- a/pkg/htmltext/htmltext.go +++ b/pkg/htmltext/htmltext.go @@ -77,14 +77,14 @@ func UrlTitle(title string) (text string) { } func clearEmoji(s string) string { - ret := "" + var ret strings.Builder rs := []rune(s) - for i := 0; i < len(rs); i++ { + for i := range rs { if len(string(rs[i])) != 4 { - ret += string(rs[i]) + ret.WriteString(string(rs[i])) } } - return ret + return ret.String() } func convertChinese(content string) string { @@ -164,7 +164,7 @@ func FetchRangedExcerpt(html, trimMarker string, offset int, limit int) (text st text = trimMarker + text } if end < len(runeText) { - text = text + trimMarker + text += trimMarker } return @@ -189,8 +189,8 @@ func FetchMatchedExcerpt(html string, words []string, trimMarker string, trimLen return FetchRangedExcerpt(html, trimMarker, runeOffset, runeLimit) } -func GetPicByUrl(Url string) string { - res, err := http.Get(Url) +func GetPicByUrl(url string) string { + res, err := http.Get(url) if err != nil { return "" } diff --git a/pkg/htmltext/htmltext_test.go b/pkg/htmltext/htmltext_test.go index 63866eb28..39de9e960 100644 --- a/pkg/htmltext/htmltext_test.go +++ b/pkg/htmltext/htmltext_test.go @@ -186,11 +186,11 @@ func TestCutLongTitle(t *testing.T) { // Exactly max bytes, no cutting needed exact150 := strings.Repeat("a", 150) - assert.Equal(t, 150, len(cutLongTitle(exact150))) + assert.Len(t, cutLongTitle(exact150), 150) // Just over max bytes, should be cut exact151 := strings.Repeat("a", 151) - assert.Equal(t, 150, len(cutLongTitle(exact151))) + assert.Len(t, cutLongTitle(exact151), 150) // Multi-byte rune at boundary gets removed properly asciiPart := strings.Repeat("a", 149) // 149 bytes diff --git a/plugin/plugin_test/plugin_main_test.go b/plugin/plugin_test/plugin_main_test.go index fd9015c86..7ba6f8ae3 100644 --- a/plugin/plugin_test/plugin_main_test.go +++ b/plugin/plugin_test/plugin_main_test.go @@ -81,19 +81,16 @@ func TestMain(t *testing.M) { _ = os.RemoveAll(dbSetting.Connection) } - defer func() { - if tearDown != nil { - tearDown() - } - }() if err := initTestDataSource(dbSetting); err != nil { panic(err) } log.Info("init test database successfully") - if ret := t.Run(); ret != 0 { - os.Exit(ret) + ret := t.Run() + if tearDown != nil { + tearDown() } + os.Exit(ret) } type TestDBSetting struct { @@ -155,7 +152,7 @@ func initDatabaseImage(dbSetting TestDBSetting) (connection string, cleanup func return "", nil, fmt.Errorf("could not connect to docker: %s", err) } - //resource, err := pool.Run(dbSetting.ImageName, dbSetting.ImageVersion, dbSetting.ENV) + // resource, err := pool.Run(dbSetting.ImageName, dbSetting.ImageVersion, dbSetting.ENV) resource, err := pool.RunWithOptions(&dockertest.RunOptions{ Repository: dbSetting.ImageName, Tag: dbSetting.ImageVersion, From 6660cdf6e25df42a6e86deca5d25e9817d67a5d2 Mon Sep 17 00:00:00 2001 From: Krypt0n123 <352600525@qq.com> Date: Tue, 2 Dec 2025 22:59:33 +0800 Subject: [PATCH 15/25] fix: add missing revision data for default content (fixes #1436) --- internal/migrations/init.go | 95 ++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/internal/migrations/init.go b/internal/migrations/init.go index 184c986b9..8a72794fe 100644 --- a/internal/migrations/init.go +++ b/internal/migrations/init.go @@ -28,6 +28,7 @@ import ( "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/data" + "github.com/apache/answer/internal/repo/revision" "github.com/apache/answer/internal/repo/unique" "github.com/apache/answer/internal/schema" "github.com/segmentfault/pacman/log" @@ -311,6 +312,7 @@ func (m *Mentor) initSiteInfoWrite() { func (m *Mentor) initDefaultContent() { uniqueIDRepo := unique.NewUniqueIDRepo(&data.Data{DB: m.engine}) + revisionRepo := revision.NewRevisionRepo(&data.Data{DB: m.engine}, uniqueIDRepo) now := time.Now() tagId, err := uniqueIDRepo.GenUniqueIDStr(m.ctx, entity.Tag{}.TableName()) @@ -343,7 +345,7 @@ func (m *Mentor) initDefaultContent() { return } - tag := entity.Tag{ + tag := &entity.Tag{ ID: tagId, SlugName: "support", DisplayName: "support", @@ -419,16 +421,74 @@ func (m *Mentor) initDefaultContent() { if m.err != nil { return } + tagContent, err := json.Marshal(tag) + if err != nil { + m.err = err + return + } + m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{ + UserID: tag.UserID, + ObjectID: tag.ID, + Title: tag.SlugName, + Content: string(tagContent), + Status: entity.RevisionReviewPassStatus, + }, true) + if m.err != nil { + return + } + tagForRevision := &entity.TagSimpleInfoForRevision{ + ID: tag.ID, + MainTagID: tag.MainTagID, + MainTagSlugName: tag.MainTagSlugName, + SlugName: tag.SlugName, + DisplayName: tag.DisplayName, + Recommend: tag.Recommend, + Reserved: tag.Reserved, + RevisionID: tag.RevisionID, + } _, m.err = m.engine.Context(m.ctx).Insert(q1) if m.err != nil { return } + q1Revision := &entity.QuestionWithTagsRevision{ + Question: *q1, + Tags: []*entity.TagSimpleInfoForRevision{tagForRevision}, + } + q1Content, err := json.Marshal(q1Revision) + if err != nil { + m.err = err + return + } + m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{ + UserID: q1.UserID, + ObjectID: q1.ID, + Title: q1.Title, + Content: string(q1Content), + Status: entity.RevisionReviewPassStatus, + }, true) + if m.err != nil { + return + } _, m.err = m.engine.Context(m.ctx).Insert(a1) if m.err != nil { return } + a1Content, err := json.Marshal(a1) + if err != nil { + m.err = err + return + } + m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{ + UserID: a1.UserID, + ObjectID: a1.ID, + Content: string(a1Content), + Status: entity.RevisionReviewPassStatus, + }, true) + if m.err != nil { + return + } _, m.err = m.engine.Context(m.ctx).Insert(entity.TagRel{ ObjectID: q1.ID, @@ -443,11 +503,44 @@ func (m *Mentor) initDefaultContent() { if m.err != nil { return } + q2Revision := &entity.QuestionWithTagsRevision{ + Question: *q2, + Tags: []*entity.TagSimpleInfoForRevision{tagForRevision}, + } + q2Content, err := json.Marshal(q2Revision) + if err != nil { + m.err = err + return + } + m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{ + UserID: q2.UserID, + ObjectID: q2.ID, + Title: q2.Title, + Content: string(q2Content), + Status: entity.RevisionReviewPassStatus, + }, true) + if m.err != nil { + return + } _, m.err = m.engine.Context(m.ctx).Insert(a2) if m.err != nil { return } + a2Content, err := json.Marshal(a2) + if err != nil { + m.err = err + return + } + m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{ + UserID: a2.UserID, + ObjectID: a2.ID, + Content: string(a2Content), + Status: entity.RevisionReviewPassStatus, + }, true) + if m.err != nil { + return + } _, m.err = m.engine.Context(m.ctx).Insert(entity.TagRel{ ObjectID: q2.ID, From 740ac61bb228ec48bf3d15231e4ec6ccc30a8bfc Mon Sep 17 00:00:00 2001 From: liruohrh <2372221537@qq.com> Date: Tue, 2 Dec 2025 01:21:49 +0800 Subject: [PATCH 16/25] fix: get right lang --- internal/base/handler/handler.go | 8 +++---- internal/base/handler/lang.go | 10 --------- internal/base/middleware/accept_language.go | 5 ++--- internal/controller/answer_controller.go | 6 ++--- internal/controller/comment_controller.go | 6 ++--- internal/controller/lang_controller.go | 2 +- internal/controller/question_controller.go | 14 ++++++------ internal/controller/report_controller.go | 2 +- internal/controller/search_controller.go | 2 +- internal/controller/template_controller.go | 10 ++++----- internal/controller/user_controller.go | 22 +++++++++---------- internal/controller/vote_controller.go | 8 +++---- .../user_backyard_controller.go | 2 +- internal/service/importer/importer_service.go | 2 +- plugin/plugin.go | 2 +- 15 files changed, 44 insertions(+), 57 deletions(-) diff --git a/internal/base/handler/handler.go b/internal/base/handler/handler.go index b545b5e01..0c2fe8f4f 100644 --- a/internal/base/handler/handler.go +++ b/internal/base/handler/handler.go @@ -23,7 +23,6 @@ import ( "errors" "net/http" - "github.com/apache/answer/internal/base/constant" "github.com/apache/answer/internal/base/reason" "github.com/apache/answer/internal/base/validator" "github.com/gin-gonic/gin" @@ -33,7 +32,7 @@ import ( // HandleResponse Handle response body func HandleResponse(ctx *gin.Context, err error, data any) { - lang := GetLang(ctx) + lang := GetLangByCtx(ctx) // no error if err == nil { ctx.JSON(http.StatusOK, NewRespBodyData(http.StatusOK, reason.Success, data).TrMsg(lang)) @@ -63,8 +62,7 @@ func HandleResponse(ctx *gin.Context, err error, data any) { // BindAndCheck bind request and check func BindAndCheck(ctx *gin.Context, data any) bool { - lang := GetLang(ctx) - ctx.Set(constant.AcceptLanguageFlag, lang) + lang := GetLangByCtx(ctx) if err := ctx.ShouldBind(data); err != nil { log.Errorf("http_handle BindAndCheck fail, %s", err.Error()) HandleResponse(ctx, myErrors.New(http.StatusBadRequest, reason.RequestFormatError), nil) @@ -81,7 +79,7 @@ func BindAndCheck(ctx *gin.Context, data any) bool { // BindAndCheckReturnErr bind request and check func BindAndCheckReturnErr(ctx *gin.Context, data any) (errFields []*validator.FormErrorField) { - lang := GetLang(ctx) + lang := GetLangByCtx(ctx) if err := ctx.ShouldBind(data); err != nil { log.Errorf("http_handle BindAndCheck fail, %s", err.Error()) HandleResponse(ctx, myErrors.New(http.StatusBadRequest, reason.RequestFormatError), nil) diff --git a/internal/base/handler/lang.go b/internal/base/handler/lang.go index 4ff1ac7f1..8886f0631 100644 --- a/internal/base/handler/lang.go +++ b/internal/base/handler/lang.go @@ -23,19 +23,9 @@ import ( "context" "github.com/apache/answer/internal/base/constant" - "github.com/gin-gonic/gin" "github.com/segmentfault/pacman/i18n" ) -// GetLang get language from header -func GetLang(ctx *gin.Context) i18n.Language { - acceptLanguage := ctx.GetHeader(constant.AcceptLanguageFlag) - if len(acceptLanguage) == 0 { - return i18n.DefaultLanguage - } - return i18n.Language(acceptLanguage) -} - // GetLangByCtx get language from header func GetLangByCtx(ctx context.Context) i18n.Language { acceptLanguage, ok := ctx.Value(constant.AcceptLanguageContextKey).(i18n.Language) diff --git a/internal/base/middleware/accept_language.go b/internal/base/middleware/accept_language.go index ca8a1f903..5d1b12b2d 100644 --- a/internal/base/middleware/accept_language.go +++ b/internal/base/middleware/accept_language.go @@ -23,7 +23,6 @@ import ( "strings" "github.com/apache/answer/internal/base/constant" - "github.com/apache/answer/internal/base/handler" "github.com/apache/answer/internal/base/translator" "github.com/gin-gonic/gin" "github.com/segmentfault/pacman/i18n" @@ -33,8 +32,8 @@ import ( // ExtractAndSetAcceptLanguage extract accept language from header and set to context func ExtractAndSetAcceptLanguage(ctx *gin.Context) { // The language of our front-end configuration, like en_US - lang := handler.GetLang(ctx) - tag, _, err := language.ParseAcceptLanguage(string(lang)) + acceptLanguage := ctx.GetHeader(constant.AcceptLanguageFlag) + tag, _, err := language.ParseAcceptLanguage(acceptLanguage) if err != nil || len(tag) == 0 { ctx.Set(constant.AcceptLanguageFlag, i18n.LanguageEnglish) return diff --git a/internal/controller/answer_controller.go b/internal/controller/answer_controller.go index 0e43121c5..e76b02ccc 100644 --- a/internal/controller/answer_controller.go +++ b/internal/controller/answer_controller.go @@ -89,7 +89,7 @@ func (ac *AnswerController) RemoveAnswer(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -225,7 +225,7 @@ func (ac *AnswerController) AddAnswer(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -325,7 +325,7 @@ func (ac *AnswerController) UpdateAnswer(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return diff --git a/internal/controller/comment_controller.go b/internal/controller/comment_controller.go index 65fbedf04..7289a0e18 100644 --- a/internal/controller/comment_controller.go +++ b/internal/controller/comment_controller.go @@ -106,7 +106,7 @@ func (cc *CommentController) AddComment(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -154,7 +154,7 @@ func (cc *CommentController) RemoveComment(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -215,7 +215,7 @@ func (cc *CommentController) UpdateComment(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return diff --git a/internal/controller/lang_controller.go b/internal/controller/lang_controller.go index c7c607bdc..1e70fa88c 100644 --- a/internal/controller/lang_controller.go +++ b/internal/controller/lang_controller.go @@ -48,7 +48,7 @@ func NewLangController(tr i18n.Translator, siteInfoService siteinfo_common.SiteI // @Success 200 {object} handler.RespBody{} // @Router /answer/api/v1/language/config [get] func (u *LangController) GetLangMapping(ctx *gin.Context) { - data, _ := u.translator.Dump(handler.GetLang(ctx)) + data, _ := u.translator.Dump(handler.GetLangByCtx(ctx)) var resp map[string]any _ = json.Unmarshal(data, &resp) handler.HandleResponse(ctx, nil, resp) diff --git a/internal/controller/question_controller.go b/internal/controller/question_controller.go index 581cf548b..d5164fc86 100644 --- a/internal/controller/question_controller.go +++ b/internal/controller/question_controller.go @@ -94,7 +94,7 @@ func (qc *QuestionController) RemoveQuestion(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -419,7 +419,7 @@ func (qc *QuestionController) AddQuestion(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -445,7 +445,7 @@ func (qc *QuestionController) AddQuestion(ctx *gin.Context) { return } if !req.CanAddTag && hasNewTag { - lang := handler.GetLang(ctx) + lang := handler.GetLangByCtx(ctx) msg := translator.TrWithData(lang, reason.NoEnoughRankToOperate, &schema.PermissionTrTplData{Rank: requireRanks[6]}) handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil) return @@ -524,7 +524,7 @@ func (qc *QuestionController) AddQuestionByAnswer(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -646,7 +646,7 @@ func (qc *QuestionController) UpdateQuestion(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -681,7 +681,7 @@ func (qc *QuestionController) UpdateQuestion(ctx *gin.Context) { return } if !req.CanAddTag && hasNewTag { - lang := handler.GetLang(ctx) + lang := handler.GetLangByCtx(ctx) msg := translator.TrWithData(lang, reason.NoEnoughRankToOperate, &schema.PermissionTrTplData{Rank: requireRanks[4]}) handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil) return @@ -765,7 +765,7 @@ func (qc *QuestionController) UpdateQuestionInviteUser(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return diff --git a/internal/controller/report_controller.go b/internal/controller/report_controller.go index 28048dd3d..13b4c0953 100644 --- a/internal/controller/report_controller.go +++ b/internal/controller/report_controller.go @@ -79,7 +79,7 @@ func (rc *ReportController) AddReport(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return diff --git a/internal/controller/search_controller.go b/internal/controller/search_controller.go index 64acbe252..a5d3e8d13 100644 --- a/internal/controller/search_controller.go +++ b/internal/controller/search_controller.go @@ -78,7 +78,7 @@ func (sc *SearchController) Search(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index f6a442c21..257b02fa4 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -206,7 +206,7 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) { UrlUseTitle := siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID - siteInfo.Title = fmt.Sprintf("%s - %s", translator.Tr(handler.GetLang(ctx), constant.QuestionsTitleTrKey), siteInfo.General.Name) + siteInfo.Title = fmt.Sprintf("%s - %s", translator.Tr(handler.GetLangByCtx(ctx), constant.QuestionsTitleTrKey), siteInfo.General.Name) tc.html(ctx, http.StatusOK, "question.html", siteInfo, gin.H{ "data": data, "useTitle": UrlUseTitle, @@ -461,7 +461,7 @@ func (tc *TemplateController) TagList(ctx *gin.Context) { if req.Page > 1 { siteInfo.Canonical = fmt.Sprintf("%s/tags?page=%d", siteInfo.General.SiteUrl, req.Page) } - siteInfo.Title = fmt.Sprintf("%s - %s", translator.Tr(handler.GetLang(ctx), constant.TagsListTitleTrKey), siteInfo.General.Name) + siteInfo.Title = fmt.Sprintf("%s - %s", translator.Tr(handler.GetLangByCtx(ctx), constant.TagsListTitleTrKey), siteInfo.General.Name) tc.html(ctx, http.StatusOK, "tags.html", siteInfo, gin.H{ "page": page, "data": data, @@ -492,14 +492,14 @@ func (tc *TemplateController) TagInfo(ctx *gin.Context) { } siteInfo.Description = htmltext.FetchExcerpt(tagInfo.ParsedText, "...", 240) if len(tagInfo.ParsedText) == 0 { - siteInfo.Description = translator.Tr(handler.GetLang(ctx), constant.TagHasNoDescription) + siteInfo.Description = translator.Tr(handler.GetLangByCtx(ctx), constant.TagHasNoDescription) } siteInfo.Keywords = tagInfo.DisplayName UrlUseTitle := siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle || siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID - siteInfo.Title = fmt.Sprintf("'%s' %s - %s", tagInfo.DisplayName, translator.Tr(handler.GetLang(ctx), constant.QuestionsTitleTrKey), siteInfo.General.Name) + siteInfo.Title = fmt.Sprintf("'%s' %s - %s", tagInfo.DisplayName, translator.Tr(handler.GetLangByCtx(ctx), constant.QuestionsTitleTrKey), siteInfo.General.Name) tc.html(ctx, http.StatusOK, "tag-detail.html", siteInfo, gin.H{ "tag": tagInfo, "questionList": questionList, @@ -597,7 +597,7 @@ func (tc *TemplateController) html(ctx *gin.Context, code int, tpl string, siteI data["title"] = siteInfo.General.Name } data["description"] = siteInfo.Description - data["language"] = handler.GetLang(ctx) + data["language"] = handler.GetLangByCtx(ctx) data["timezone"] = siteInfo.Interface.TimeZone language := strings.ReplaceAll(siteInfo.Interface.Language, "_", "-") data["lang"] = language diff --git a/internal/controller/user_controller.go b/internal/controller/user_controller.go index cc89caf1a..77c806e07 100644 --- a/internal/controller/user_controller.go +++ b/internal/controller/user_controller.go @@ -142,7 +142,7 @@ func (uc *UserController) UserEmailLogin(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -154,7 +154,7 @@ func (uc *UserController) UserEmailLogin(ctx *gin.Context) { uc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionPassword, ctx.ClientIP()) errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "e_mail", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.EmailOrPasswordWrong), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.EmailOrPasswordWrong), }) handler.HandleResponse(ctx, errors.BadRequest(reason.EmailOrPasswordWrong), errFields) return @@ -191,7 +191,7 @@ func (uc *UserController) RetrievePassWord(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -286,7 +286,7 @@ func (uc *UserController) UserRegisterByEmail(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -297,7 +297,7 @@ func (uc *UserController) UserRegisterByEmail(ctx *gin.Context) { if len(errFields) > 0 { for _, field := range errFields { field.ErrorMsg = translator. - Tr(handler.GetLang(ctx), field.ErrorMsg) + Tr(handler.GetLangByCtx(ctx), field.ErrorMsg) } handler.HandleResponse(ctx, err, errFields) } else { @@ -364,7 +364,7 @@ func (uc *UserController) UserVerifyEmailSend(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -399,7 +399,7 @@ func (uc *UserController) UserModifyPassWord(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -415,7 +415,7 @@ func (uc *UserController) UserModifyPassWord(ctx *gin.Context) { if !oldPassVerification { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "old_pass", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.OldPasswordVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.OldPasswordVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.OldPasswordVerificationFailed), errFields) return @@ -424,7 +424,7 @@ func (uc *UserController) UserModifyPassWord(ctx *gin.Context) { if req.OldPass == req.Pass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "pass", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.NewPasswordSameAsPreviousSetting), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.NewPasswordSameAsPreviousSetting), }) handler.HandleResponse(ctx, errors.BadRequest(reason.NewPasswordSameAsPreviousSetting), errFields) return @@ -456,7 +456,7 @@ func (uc *UserController) UserUpdateInfo(ctx *gin.Context) { req.IsAdmin = middleware.GetUserIsAdminModerator(ctx) errFields, err := uc.userService.UpdateInfo(ctx, req) for _, field := range errFields { - field.ErrorMsg = translator.Tr(handler.GetLang(ctx), field.ErrorMsg) + field.ErrorMsg = translator.Tr(handler.GetLangByCtx(ctx), field.ErrorMsg) } handler.HandleResponse(ctx, err, errFields) } @@ -587,7 +587,7 @@ func (uc *UserController) UserChangeEmailSendCode(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return diff --git a/internal/controller/vote_controller.go b/internal/controller/vote_controller.go index 2e0ee6121..302796677 100644 --- a/internal/controller/vote_controller.go +++ b/internal/controller/vote_controller.go @@ -79,7 +79,7 @@ func (vc *VoteController) VoteUp(ctx *gin.Context) { return } if !can { - lang := handler.GetLang(ctx) + lang := handler.GetLangByCtx(ctx) msg := translator.TrWithData(lang, reason.NoEnoughRankToOperate, &schema.PermissionTrTplData{Rank: needRank}) handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil) return @@ -91,7 +91,7 @@ func (vc *VoteController) VoteUp(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return @@ -134,7 +134,7 @@ func (vc *VoteController) VoteDown(ctx *gin.Context) { return } if !can { - lang := handler.GetLang(ctx) + lang := handler.GetLangByCtx(ctx) msg := translator.TrWithData(lang, reason.NoEnoughRankToOperate, &schema.PermissionTrTplData{Rank: needRank}) handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil) return @@ -145,7 +145,7 @@ func (vc *VoteController) VoteDown(ctx *gin.Context) { if !captchaPass { errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ ErrorField: "captcha_code", - ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed), + ErrorMsg: translator.Tr(handler.GetLangByCtx(ctx), reason.CaptchaVerificationFailed), }) handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields) return diff --git a/internal/controller_admin/user_backyard_controller.go b/internal/controller_admin/user_backyard_controller.go index 00dfa2c3d..1356c55a1 100644 --- a/internal/controller_admin/user_backyard_controller.go +++ b/internal/controller_admin/user_backyard_controller.go @@ -177,7 +177,7 @@ func (uc *UserAdminController) EditUserProfile(ctx *gin.Context) { errFields, err := uc.userService.EditUserProfile(ctx, req) for _, field := range errFields { - field.ErrorMsg = translator.Tr(handler.GetLang(ctx), field.ErrorMsg) + field.ErrorMsg = translator.Tr(handler.GetLangByCtx(ctx), field.ErrorMsg) } handler.HandleResponse(ctx, err, errFields) } diff --git a/internal/service/importer/importer_service.go b/internal/service/importer/importer_service.go index c7673ffb5..9d12bf07b 100644 --- a/internal/service/importer/importer_service.go +++ b/internal/service/importer/importer_service.go @@ -135,7 +135,7 @@ func (ip *ImporterService) ImportQuestion(ctx context.Context, questionInfo plug return err } if !req.CanAddTag && hasNewTag { - lang := handler.GetLang(ctx.(*gin.Context)) + lang := handler.GetLangByCtx(ctx.(*gin.Context)) msg := translator.TrWithData(lang, reason.NoEnoughRankToOperate, &schema.PermissionTrTplData{Rank: requireRanks[6]}) log.Errorf("error: %v", msg) return errors.BadRequest(msg) diff --git a/plugin/plugin.go b/plugin/plugin.go index 266848353..8778b1625 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -216,7 +216,7 @@ func (m *statusManager) UnmarshalJSON(data []byte) error { // Translate translates the key to the current language of the context func Translate(ctx *GinContext, key string) string { - return translator.Tr(handler.GetLang(ctx), key) + return translator.Tr(handler.GetLangByCtx(ctx), key) } // TranslateWithData translates the key to the language with data From 8e395d421e5ded9277414c69cee1452429acc524 Mon Sep 17 00:00:00 2001 From: kinjelom Date: Sat, 22 Nov 2025 12:36:06 +0100 Subject: [PATCH 17/25] Polish translation --- i18n/pl_PL.yaml | 544 ++++++++++++++++++++++++++---------------------- 1 file changed, 300 insertions(+), 244 deletions(-) diff --git a/i18n/pl_PL.yaml b/i18n/pl_PL.yaml index e5972d9b3..c5c97d118 100644 --- a/i18n/pl_PL.yaml +++ b/i18n/pl_PL.yaml @@ -486,43 +486,42 @@ backend: title: other: "[{{.SiteName}}] Potwierdź swój nowy adres e-mail" body: - other: "Confirm your new email address for {{.SiteName}} by clicking on the following link:
\n
{{.ChangeEmailUrl}}

\n\nIf you did not request this change, please ignore this email.

\n\n--
\nNote: This is an automatic system email, please do not reply to this message as your response will not be seen." + other: "Potwierdź swój nowy adres e-mail dla {{.SiteName}}, klikając poniższy link:
\n{{.ChangeEmailUrl}}

\n\nJeśli nie prosiłeś(-aś) o zmianę adresu e-mail, zignoruj tę wiadomość.

\n\n--
\nUwaga: to jest automatyczna wiadomość systemowa, nie odpowiadaj na nią, ponieważ odpowiedź nie będzie odczytana." new_answer: title: other: "[{{.SiteName}}] {{.DisplayName}} odpowiedział(-a) na pytanie" body: - other: "{{.QuestionTitle}}

\n\n{{.DisplayName}}:
\n
{{.AnswerSummary}}

\nView it on {{.SiteName}}

\n\n--
\nNote: This is an automatic system email, please do not reply to this message as your response will not be seen.

\n\nUnsubscribe" + other: "{{.QuestionTitle}}

\n\n{{.DisplayName}} napisał(-a):
\n
{{.AnswerSummary}}

\nZobacz na {{.SiteName}}

\n\n--
\nUwaga: to jest automatyczna wiadomość systemowa, nie odpowiadaj na nią, ponieważ odpowiedź nie będzie odczytana.

\n\nZrezygnuj z subskrypcji" invited_you_to_answer: title: - other: "[{{.SiteName}}] {{.DisplayName}} zaprosił(a) Cię do odpowiedzi" + other: "[{{.SiteName}}] {{.DisplayName}} zaprosił(-a) Cię do odpowiedzi" body: - other: "{{.QuestionTitle}}

\n\n{{.DisplayName}}:
\n
I think you may know the answer.

\nView it on {{.SiteName}}

\n\n--
\nNote: This is an automatic system email, please do not reply to this message as your response will not be seen.

\n\nUnsubscribe" + other: "{{.QuestionTitle}}

\n\n{{.DisplayName}} napisał(-a):
\n
Myślę, że możesz znać odpowiedź.

\nZobacz na {{.SiteName}}

\n\n--
\nUwaga: to jest automatyczna wiadomość systemowa, nie odpowiadaj na nią, ponieważ odpowiedź nie będzie odczytana.

\n\nZrezygnuj z subskrypcji" new_comment: title: - other: "[{{.SiteName}}] {{.DisplayName}} skomentował/-a Twój wpis" + other: "[{{.SiteName}}] {{.DisplayName}} skomentował(-a) Twój wpis" body: - other: "{{.QuestionTitle}}

\n\n{{.DisplayName}}:
\n
{{.CommentSummary}}

\nView it on {{.SiteName}}

\n\n--
\nNote: This is an automatic system email, please do not reply to this message as your response will not be seen.

\n\nUnsubscribe" + other: "{{.QuestionTitle}}

\n\n{{.DisplayName}} napisał(-a):
\n
{{.CommentSummary}}

\nZobacz na {{.SiteName}}

\n\n--
\nUwaga: to jest automatyczna wiadomość systemowa, nie odpowiadaj na nią, ponieważ odpowiedź nie będzie odczytana.

\n\nZrezygnuj z subskrypcji" new_question: title: other: "[{{.SiteName}}] Nowe pytanie: {{.QuestionTitle}}" body: - other: "{{.QuestionTitle}}
\n{{.Tags}}

\n\n--
\nNote: This is an automatic system email, please do not reply to this message as your response will not be seen.

\n\nUnsubscribe" + other: "{{.QuestionTitle}}
\n{{.Tags}}

\n\n--
\nUwaga: to jest automatyczna wiadomość systemowa, nie odpowiadaj na nią, ponieważ odpowiedź nie będzie odczytana.

\n\nZrezygnuj z subskrypcji" pass_reset: title: - other: "[{{.SiteName }}] Reset hasła" + other: "[{{.SiteName}}] Reset hasła" body: - other: "Somebody asked to reset your password on {{.SiteName}}.

\n\nIf it was not you, you can safely ignore this email.

\n\nClick the following link to choose a new password:
\n{{.PassResetUrl}}\n

\n\n--
\nNote: This is an automatic system email, please do not reply to this message as your response will not be seen." + other: "Otrzymaliśmy prośbę o zresetowanie Twojego hasła w serwisie {{.SiteName}}.

\n\nJeśli to nie Ty wysłałeś(-aś) tę prośbę, możesz bezpiecznie zignorować tę wiadomość.

\n\nKliknij poniższy link, aby ustawić nowe hasło:
\n{{.PassResetUrl}}\n

\n\n--
\nUwaga: to jest automatyczna wiadomość systemowa, nie odpowiadaj na nią, ponieważ odpowiedź nie będzie odczytana." register: title: other: "[{{.SiteName}}] Potwierdź swoje nowe konto" body: - other: "Welcome to {{.SiteName}}!

\n\nClick the following link to confirm and activate your new account:
\n{{.RegisterUrl}}

\n\nIf the above link is not clickable, try copying and pasting it into the address bar of your web browser.\n

\n\n--
\nNote: This is an automatic system email, please do not reply to this message as your response will not be seen." + other: "Witamy w {{.SiteName}}!

\n\nKliknij poniższy link, aby potwierdzić i aktywować swoje nowe konto:
\n{{.RegisterUrl}}

\n\nJeśli powyższy link nie jest klikalny, spróbuj skopiować go i wkleić do paska adresu przeglądarki.\n

\n\n--
\nUwaga: to jest automatyczna wiadomość systemowa, nie odpowiadaj na nią, ponieważ odpowiedź nie będzie odczytana." test: title: other: "[{{.SiteName}}] Wiadomość testowa" body: - other: "This is a test email.\n

\n\n--
\nNote: This is an automatic system email, please do not reply to this message as your response will not be seen." - action_activity_type: + other: "To jest testowa wiadomość e-mail.\n

\n\n--
\nUwaga: to jest automatyczna wiadomość systemowa, nie odpowiadaj na nią, ponieważ odpowiedź nie będzie odczytana." upvote: other: oceń pozytywnie upvoted: @@ -573,244 +572,300 @@ backend: name: other: Pierwszy pozytywny głos desc: - other: First up voted a post. + other: Po raz pierwszy oddano pozytywny głos na post. first_link: name: other: Pierwszy odnośnik desc: - other: First added a link to another post. + other: Po raz pierwszy dodano link do innego wpisu. + first_reaction: name: - other: Pierwsza Reakcja + other: Pierwsza reakcja desc: - other: First reacted to the post. + other: Po raz pierwszy zareagowano na wpis. + first_share: name: - other: Pierwsze udostępnianie + other: Pierwsze udostępnienie desc: - other: First shared a post. + other: Po raz pierwszy udostępniono wpis. + scholar: name: other: Scholar desc: - other: Zadane pytania i zaakceptowane odpowiedź. + other: Zadano pytanie i zaakceptowano odpowiedź. + commentator: name: - other: Commentator + other: Komentator desc: - other: Pozostaw 5 komentarzy. + other: Pozostawiono 5 komentarzy. + new_user_of_the_month: name: other: Nowy użytkownik miesiąca desc: - other: Outstanding contributions in their first month. + other: Wyjątkowy wkład w pierwszym miesiącu aktywności. + read_guidelines: name: - other: Read Guidelines + other: Przeczytano zasady desc: - other: Read the [community guidelines]. + other: Przeczytano [zasady społeczności]. + reader: name: - other: Reader + other: Czytelnik desc: - other: Read every answers in a topic with more than 10 answers. + other: Przeczytano wszystkie odpowiedzi w wątku mającym ponad 10 odpowiedzi. + welcome: name: - other: Welcome + other: Witamy desc: - other: Received a up vote. + other: Otrzymano pozytywny głos. + nice_share: name: - other: Nice Share + other: Udane udostępnienie desc: - other: Shared a post with 25 unique visitors. + other: Udostępniono wpis, który odwiedziło 25 unikalnych użytkowników. + good_share: name: - other: Good Share + other: Dobre udostępnienie desc: - other: Shared a post with 300 unique visitors. + other: Udostępniono wpis, który odwiedziło 300 unikalnych użytkowników. + great_share: name: - other: Great Share + other: Świetne udostępnienie desc: - other: Shared a post with 1000 unique visitors. + other: Udostępniono wpis, który odwiedziło 1000 unikalnych użytkowników. + out_of_love: name: - other: Out of Love + other: Z miłości desc: - other: Used 50 up votes in a day. + other: Wykorzystano 50 pozytywnych głosów w ciągu dnia. + higher_love: name: - other: Higher Love + other: Więcej miłości desc: - other: Used 50 up votes in a day 5 times. + other: Wykorzystano 50 pozytywnych głosów w ciągu dnia - 5 razy. + crazy_in_love: name: - other: Crazy in Love + other: Szaleństwo miłości desc: - other: Used 50 up votes in a day 20 times. + other: Wykorzystano 50 pozytywnych głosów w ciągu dnia - 20 razy. + promoter: name: - other: Promoter + other: Promotor desc: - other: Invited a user. + other: Zaproszono użytkownika. + campaigner: name: - other: Campaigner + other: Kampanier desc: - other: Invited 3 basic users. + other: Zaproszono 3 podstawowych użytkowników. + champion: name: - other: Champion + other: Mistrz desc: - other: Invited 5 members. + other: Zaproszono 5 użytkowników. + thank_you: name: - other: Thank You + other: Dziękuję desc: - other: Has 20 up voted posts and gave 10 up votes. + other: Otrzymano 20 pozytywnych głosów i oddano 10. + gives_back: name: - other: Gives Back + other: Oddający dalej desc: - other: Has 100 up voted posts and gave 100 up votes. + other: Otrzymano 100 pozytywnych głosów i oddano 100. + empathetic: name: - other: Empathetic + other: Empatyczny desc: - other: Has 500 up voted posts and gave 1000 up votes. + other: Otrzymano 500 pozytywnych głosów i oddano 1000. + enthusiast: name: - other: Enthusiast + other: Entuzjasta desc: - other: Visited 10 consecutive days. + other: Odwiedzono serwis 10 dni z rzędu. + aficionado: name: - other: Aficionado + other: Koneser desc: - other: Visited 100 consecutive days. + other: Odwiedzono serwis 100 dni z rzędu. + devotee: name: - other: Devotee + other: Wytrwały desc: - other: Visited 365 consecutive days. + other: Odwiedzono serwis 365 dni z rzędu. + anniversary: name: - other: Anniversary + other: Rocznica desc: - other: Active member for a year, posted at least once. + other: Aktywny użytkownik od roku, co najmniej jeden wpis. + appreciated: name: - other: Appreciated + other: Doceniony desc: - other: Received 1 up vote on 20 posts. + other: Otrzymano 1 pozytywny głos na 20 wpisach. + respected: name: - other: Respected + other: Szanujący desc: - other: Received 2 up votes on 100 posts. + other: Otrzymano 2 pozytywne głosy na 100 wpisach. + admired: name: - other: Admired + other: Podziwiany desc: - other: Received 5 up votes on 300 posts. + other: Otrzymano 5 pozytywnych głosów na 300 wpisach. + solved: name: - other: Solved + other: Rozwiązane desc: - other: Have an answer be accepted. + other: Udzielono odpowiedzi, która została zaakceptowana. + guidance_counsellor: name: - other: Guidance Counsellor + other: Doradca desc: - other: Have 10 answers be accepted. + other: 10 udzielonych odpowiedzi zostało zaakceptowanych. + know_it_all: name: - other: Know-it-All + other: Wszystkowiedzący desc: - other: Have 50 answers be accepted. + other: 50 udzielonych odpowiedzi zostało zaakceptowanych. + solution_institution: name: - other: Solution Institution + other: Instytucja rozwiązań desc: - other: Have 150 answers be accepted. + other: 150 udzielonych odpowiedzi zostało zaakceptowanych. + nice_answer: name: - other: Nice Answer + other: Dobra odpowiedź desc: - other: Answer score of 10 or more. + other: Odpowiedź z wynikiem co najmniej 10. + good_answer: name: - other: Good Answer + other: Bardzo dobra odpowiedź desc: - other: Answer score of 25 or more. + other: Odpowiedź z wynikiem co najmniej 25. + great_answer: name: - other: Great Answer + other: Świetna odpowiedź desc: - other: Answer score of 50 or more. + other: Odpowiedź z wynikiem co najmniej 50. + nice_question: name: - other: Nice Question + other: Dobre pytanie desc: - other: Question score of 10 or more. + other: Pytanie z wynikiem co najmniej 10. + good_question: name: - other: Good Question + other: Bardzo dobre pytanie desc: - other: Question score of 25 or more. + other: Pytanie z wynikiem co najmniej 25. + great_question: name: - other: Great Question + other: Świetne pytanie desc: - other: Question score of 50 or more. + other: Pytanie z wynikiem co najmniej 50. + popular_question: name: - other: Popular Question + other: Popularne pytanie desc: - other: Question with 500 views. + other: Pytanie z 500 wyświetleniami. + notable_question: name: - other: Notable Question + other: Zauważalne pytanie desc: - other: Question with 1,000 views. + other: Pytanie z 1000 wyświetleniami. + famous_question: name: - other: Famous Question + other: Słynne pytanie desc: - other: Question with 5,000 views. + other: Pytanie z 5000 wyświetleniami. + popular_link: name: - other: Popular Link + other: Popularny link desc: - other: Posted an external link with 50 clicks. + other: Opublikowano zewnętrzny link z 50 kliknięciami. + hot_link: name: - other: Hot Link + other: Gorący link desc: - other: Posted an external link with 300 clicks. + other: Opublikowano zewnętrzny link z 300 kliknięciami. + famous_link: name: - other: Famous Link + other: Słynny link desc: - other: Posted an external link with 100 clicks. + other: Opublikowano zewnętrzny link z 1000 kliknięciami. default_badge_groups: getting_started: name: - other: Getting Started + other: Pierwsze kroki community: name: - other: Community + other: Społeczność posting: name: - other: Posting + other: Publikowanie # The following fields are used for interface presentation(Front-end) ui: how_to_format: title: Jak formatować desc: >- -
  • mention a post: #post_id

  • to make links

    <https://url.com>

    [Title](https://url.com)
  • put returns between paragraphs

  • _italic_ or **bold**

  • indent code by 4 spaces

  • quote by placing > at start of line

  • backtick escapes `like _this_`

  • create code fences with backticks `

    ```
    code here
    ```
- pagination: +
    +
  • wspomnij wpis: #post_id

  • +
  • tworzenie linków

    +
    <https://url.com>

    [Tytuł](https://url.com)
    +
  • +
  • oddziel akapity pustą linią

  • +
  • _kursywa_ lub **pogrubienie**

  • +
  • zagnieźdź kod, dodając 4 spacje na początku wiersza

  • +
  • cytuj, dodając > na początku wiersza

  • +
  • użyj odwrotnego apostrofu (backtick) do zagnieżdżonego kodu `tak _to_ działa`

  • +
  • twórz bloki kodu przy pomocy potrójnych odwrotnych apostrofów `

    +
    ```
    kod tutaj
    ```
    +
  • +
+ pagination: prev: Poprzedni next: Następny page_title: @@ -970,9 +1025,9 @@ ui: heading: Nagłówek cell: Komórka file: - text: Attach files - not_supported: "Don’t support that file type. Try again with {{file_type}}." - max_size: "Attach files size cannot exceed {{size}} MB." + text: Dołącz pliki + not_supported: "Ten typ pliku nie jest obsługiwany. Spróbuj ponownie z {{file_type}}." + max_size: "Rozmiar dołączanych plików nie może przekraczać {{size}} MB." close_modal: title: Zamykam ten post jako... btn_cancel: Anuluj @@ -1037,20 +1092,22 @@ ui: delete: title: Usuń ten tag tip_with_posts: >- -

We do not allow deleting tag with posts.

Please remove this tag from the posts first.

+

Nie można usunąć tagu, który jest używany w postach.

+

Najpierw usuń ten tag z powiązanych postów.

tip_with_synonyms: >- -

We do not allow deleting tag with synonyms.

Please remove the synonyms from this tag first.

+

Nie można usunąć tagu, który ma synonimy.

+

Najpierw usuń synonimy przypisane do tego tagu.

tip: Czy na pewno chcesz usunąć? close: Zamknij merge: - title: Merge tag - source_tag_title: Source tag - source_tag_description: The source tag and its associated data will be remapped to the target tag. - target_tag_title: Target tag - target_tag_description: A synonym between these two tags will be created after merging. - no_results: No tags matched - btn_submit: Submit - btn_close: Close + title: Scal tag + source_tag_title: Źródłowy tag + source_tag_description: Źródłowy tag i wszystkie powiązane dane zostaną przemapowane na tag docelowy. + target_tag_title: Docelowy tag + target_tag_description: Po scaleniu zostanie utworzony synonim między tymi dwoma tagami. + no_results: Brak pasujących tagów + btn_submit: Zatwierdź + btn_close: Zamknij edit_tag: title: Edytuj tag default_reason: Edytuj tag @@ -1058,20 +1115,20 @@ ui: btn_save_edits: Zapisz edycje btn_cancel: Anuluj dates: - long_date: MMM D - long_date_with_year: "MMM D, YYYY" - long_date_with_time: "MMM D, YYYY [o] HH:mm" + long_date: D MMM + long_date_with_year: "YYYY MMM D" + long_date_with_time: "YYYY MMM D [o] HH:mm" now: teraz - x_seconds_ago: "{{count}} s temu" - x_minutes_ago: "{{count}} min temu" - x_hours_ago: "{{count}} h temu" + x_seconds_ago: "{{count}} sek. temu" + x_minutes_ago: "{{count}} min. temu" + x_hours_ago: "{{count}} godz. temu" hour: godzina day: dzień hours: godziny days: dni month: month months: months - year: year + year: rok reaction: heart: serce smile: uśmiech @@ -1127,7 +1184,7 @@ ui: more: Więcej wiki: Wiki ask: - title: Create Question + title: Utwórz pytanie edit_title: Edytuj pytanie default_reason: Edytuj pytanie default_first_reason: Create question @@ -1138,7 +1195,7 @@ ui: label: Rewizja title: label: Tytuł - placeholder: What's your topic? Be specific. + placeholder: Jaki jest temat? Bądź konkretny. msg: empty: Tytuł nie może być pusty. range: Tytuł do 150 znaków @@ -1147,8 +1204,8 @@ ui: msg: empty: Treść nie może być pusta. hint: - optional_body: Describe what the question is about. - minimum_characters: "Describe what the question is about, at least {{min_content_length}} characters are required." + optional_body: Opisz, czego dotyczy pytanie. + minimum_characters: "Opisz, czego dotyczy pytanie — wymagane jest co najmniej {{min_content_length}} znaków." tags: label: Tagi msg: @@ -1169,9 +1226,9 @@ ui: add_btn: Dodaj tag create_btn: Utwórz nowy tag search_tag: Wyszukaj tag - hint: Describe what your content is about, at least one tag is required. - hint_zero_tags: Describe what your content is about. - hint_more_than_one_tag: "Describe what your content is about, at least {{min_tags_number}} tags are required." + hint: Opisz, czego dotyczy Twoja treść — wymagany jest co najmniej jeden tag. + hint_zero_tags: Opisz, czego dotyczy Twoja treść. + hint_more_than_one_tag: "Opisz, czego dotyczy Twoja treść — wymagane są co najmniej {{min_tags_number}} tagi." no_result: Nie znaleziono pasujących tagów tag_required_text: Wymagany tag (co najmniej jeden) header: @@ -1179,7 +1236,7 @@ ui: question: Pytania tag: Tagi user: Użytkownicy - badges: Badges + badges: Odznaki profile: Profil setting: Ustawienia logout: Wyloguj @@ -1296,13 +1353,13 @@ ui: display_name: label: Nazwa wyświetlana msg: Wyświetlana nazwa nie może być pusta. - msg_range: Display name must be 2-30 characters in length. + msg_range: Wyświetlana nazwa musi mieć od 2 do 30 znaków długości. username: label: Nazwa użytkownika caption: Ludzie mogą oznaczać Cię jako "@nazwa_użytkownika". msg: Nazwa użytkownika nie może być pusta. - msg_range: Username must be 2-30 characters in length. - character: 'Must use the character set "a-z", "0-9", "- . _"' + msg_range: Nazwa użytkownika musi mieć od 2 do 30 znaków długości. + character: 'Muszą być znaki ze zbioru "a-z", "0-9", "- . _"' avatar: label: Zdjęcie profilowe gravatar: Gravatar @@ -1391,11 +1448,11 @@ ui: search: Wyszukaj osoby question_detail: action: Akcja - created: Created + created: Utworzono Asked: Zadane asked: zadał(a) update: Zmodyfikowane - Edited: Edited + Edited: Wyedytowane edit: edytowany commented: skomentowano Views: Wyświetlone @@ -1442,7 +1499,7 @@ ui: list: confirm_btn: Lista title: Pokaż ten post - content: Are you sure you want to list? + content: Czy na pewno chcesz wyświetlić tę listę? unlist: confirm_btn: Usuń z listy title: Usuń ten post z listy @@ -1507,16 +1564,16 @@ ui: normal: Normalny closed: Zamknięty deleted: Usunięty - deleted_permanently: Deleted permanently + deleted_permanently: Usunięto trwale pending: Oczekujący more: Więcej - view: View - card: Card - compact: Compact - display_below: Display below - always_display: Always display - or: or - back_sites: Back to sites + view: Podgląd + card: Karta + compact: Kompakt + display_below: Wyświetl poniżej + always_display: Wyświetlaj zawsze + or: lub + back_sites: Powrót do stron search: title: Wyniki wyszukiwania keywords: Słowa kluczowe @@ -1524,7 +1581,7 @@ ui: follow: Obserwuj following: Obserwuje counts: "Liczba wyników: {{count}}" - counts_loading: "... Results" + counts_loading: "... Wyniki" more: Więcej sort_btns: relevance: Relewantność @@ -1547,13 +1604,13 @@ ui: via: Udostępnij post za pośrednictwem... copied: Skopiowano facebook: Udostępnij na Facebooku - twitter: Share to X + twitter: Udostępnij na X cannot_vote_for_self: Nie możesz głosować na własne posty. modal_confirm: title: Błąd... delete_permanently: - title: Delete permanently - content: Are you sure you want to delete permanently? + title: Usuń trwale + content: Czy na pewno chcesz usunąć to trwale? account_result: success: Twoje nowe konto zostało potwierdzone; zostaniesz przekierowany na stronę główną. link: Kontynuuj do strony głównej @@ -1582,7 +1639,7 @@ ui: newest: Najnowsze active: Aktywne hot: Gorące - frequent: Frequent + frequent: Częste recommend: Polecane score: Ocena unanswered: Bez odpowiedzi @@ -1628,7 +1685,7 @@ ui: x_votes: otrzymane głosy x_answers: odpowiedzi x_questions: pytania - recent_badges: Recent Badges + recent_badges: Ostatnie odznaki install: title: Instalacja next: Dalej @@ -1667,14 +1724,14 @@ ui: ssl_mode: label: SSL Mode ssl_root_cert: - placeholder: sslrootcert file path - msg: Path to sslrootcert file cannot be empty + placeholder: Ścieżka do pliku sslrootcert + msg: Ścieżka do pliku sslrootcert nie może być pusta ssl_cert: - placeholder: sslcert file path - msg: Path to sslcert file cannot be empty + placeholder: Ścieżka do pliku sslcert + msg: Ścieżka do pliku sslcert nie może być pusta ssl_key: - placeholder: sslkey file path - msg: Path to sslkey file cannot be empty + placeholder: Ścieżka do pliku sslkey + msg: Ścieżka do pliku sslkey nie może być pusta config_yaml: title: Utwórz plik config.yaml label: Plik config.yaml utworzony. @@ -1717,9 +1774,9 @@ ui: msg_min_length: Hasło musi mieć co najmniej 8 znaków. msg_max_length: Hasło musi mieć maksymalnie 32 znaki. admin_confirm_password: - label: "Confirm Password" - text: "Please re-enter your password to confirm." - msg: "Confirm password does not match." + label: "Potwierdź hasło" + text: "Wprowadź ponownie swoje hasło, aby potwierdzić." + msg: "Potwierdzenie hasła nie jest zgodne." admin_email: label: Email text: Będziesz potrzebować tego adresu e-mail do logowania. @@ -1777,7 +1834,7 @@ ui: privileges: Uprawnienia plugins: Wtyczki installed_plugins: Zainstalowane wtyczki - apperance: Appearance + apperance: Wygląd website_welcome: Witamy w serwisie {{site_name}} user_center: login: Zaloguj się @@ -1786,15 +1843,15 @@ ui: badges: modal: title: Gratulacje - content: You've earned a new badge. - close: Close - confirm: View badges - title: Badges - awarded: Awarded - earned_×: Earned ×{{ number }} - ×_awarded: "{{ number }} awarded" - can_earn_multiple: You can earn this multiple times. - earned: Earned + content: Zdobyłeś nową odznakę. + close: Zamknij + confirm: Zobacz odznaki + title: Odznaki + awarded: Przyznano + earned_×: Zdobyto ×{{ number }} + ×_awarded: „{{ number }} przyznano” + can_earn_multiple: Możesz zdobyć tę odznakę wielokrotnie. + earned: Zdobyto admin: admin_header: title: Administrator @@ -1803,15 +1860,15 @@ ui: welcome: Witaj Administratorze! site_statistics: Statystyki witryny questions: "Pytania:" - resolved: "Resolved:" - unanswered: "Unanswered:" + resolved: "Rozwiązane:" + unanswered: "Bez odpowiedzi:" answers: "Odpowiedzi:" comments: "Komentarze:" votes: "Głosy:" users: "Użytkownicy:" - flags: "Flagi:" - reviews: "Reviews:" - site_health: Site health + flags: "Zgłoszenia:" + reviews: "Przeglądy:" + site_health: "Stan serwisu" version: "Wersja:" https: "HTTPS:" upload_folder: "Prześlij folder:" @@ -1876,14 +1933,14 @@ ui: form: fields: display_name: - label: Display name - msg_range: Display name must be 2-30 characters in length. + label: Wyświetlana nazwa + msg_range: Wyświetlana nazwa musi mieć od 2 do 30 znaków. username: - label: Nazwa - msg_range: Username must be 2-30 characters in length. + label: Nazwa użytkownika + msg_range: Nazwa użytkownika musi mieć od 2 do 30 znaków. email: label: Email - msg_invalid: Błędny adresy email. + msg_invalid: Błędny adres e-mail. edit_success: Edycja zakończona pomyślnie btn_cancel: Anuluj btn_submit: Prześlij @@ -1898,7 +1955,7 @@ ui: msg: "Podaj adresy e-mail użytkowników, jeden w każdej linii." display_name: label: Nazwa wyświetlana - msg: Display name must be 2-30 characters in length. + msg: Wyświetlana nazwa musi mieć od 2 do 30 znaków. email: label: E-mail msg: Email nie jest prawidłowy. @@ -1912,10 +1969,10 @@ ui: name: Imię email: E-mail reputation: Reputacja - created_at: Created time - delete_at: Deleted time - suspend_at: Suspended time - suspend_until: Suspend until + created_at: Czas utworzenia + delete_at: Czas usunięcia + suspend_at: Czas zawieszenia + suspend_until: Zawieszone do status: Status role: Rola action: Akcja @@ -1950,8 +2007,8 @@ ui: suspend_user: title: Zawieś tego użytkownika content: Zawieszony użytkownik nie może się logować. - label: How long will the user be suspended for? - forever: Forever + label: Na jak długo użytkownik zostanie zawieszony? + forever: Na zawsze questions: page_title: Pytania unlisted: Unlisted @@ -2013,11 +2070,11 @@ ui: msg: Strefa czasowa nie może być pusta. text: Wybierz miasto w tej samej strefie czasowej, co Ty. avatar: - label: Default avatar - text: For users without a custom avatar of their own. + label: Domyślny awatar + text: Dla użytkowników, którzy nie ustawili własnego awatara. gravatar_base_url: - label: Gravatar base URL - text: URL of the Gravatar provider's API base. Ignored when empty. + label: Bazowy URL Gravatara + text: Adres bazowy API dostawcy Gravatara. Ignorowane, jeśli puste. smtp: page_title: SMTP from_email: @@ -2096,37 +2153,37 @@ ui: restrict_answer: title: Answer write label: Każdy użytkownik może napisać tylko jedną odpowiedź na każde pytanie - text: "Turn off to allow users to write multiple answers to the same question, which may cause answers to be unfocused." + text: "Wyłącz, aby pozwolić użytkownikom pisać wiele odpowiedzi na to samo pytanie, co może powodować, że odpowiedzi będą mniej skupione." min_tags: - label: "Minimum tags per question" - text: "Minimum number of tags required in a question." + label: "Minimalna liczba tagów na pytanie" + text: "Minimalna liczba tagów wymagana w pytaniu." recommend_tags: label: Rekomendowane tagi - text: "Recommend tags will show in the dropdown list by default." + text: "Rekomendowane tagi będą domyślnie wyświetlane na liście wyboru." msg: - contain_reserved: "recommended tags cannot contain reserved tags" + contain_reserved: "Rekomendowane tagi nie mogą zawierać tagów zarezerwowanych." required_tag: - title: Set required tags - label: Set “Recommend tags” as required tags + title: Ustaw wymagane tagi + label: Ustaw „Rekomendowane tagi” jako wymagane text: "Każde nowe pytanie musi mieć przynajmniej jeden rekomendowany tag." reserved_tags: label: Zarezerwowane tagi - text: "Reserved tags can only be used by moderator." + text: "Zarezerwowane tagi mogą być używane tylko przez moderatorów." image_size: - label: Max image size (MB) - text: "The maximum image upload size." + label: Maksymalny rozmiar obrazu (MB) + text: "Maksymalny dopuszczalny rozmiar przesyłanego obrazu." attachment_size: - label: Max attachment size (MB) - text: "The maximum attachment files upload size." + label: Maksymalny rozmiar załącznika (MB) + text: "Maksymalny dopuszczalny rozmiar przesyłanych plików." image_megapixels: - label: Max image megapixels - text: "Maximum number of megapixels allowed for an image." + label: Maksymalna liczba megapikseli + text: "Maksymalna liczba megapikseli dopuszczona dla obrazu." image_extensions: - label: Authorized image extensions - text: "A list of file extensions allowed for image display, separate with commas." + label: Dozwolone rozszerzenia obrazów + text: "Lista rozszerzeń plików dozwolonych dla obrazów; oddziel po przecinkach." attachment_extensions: - label: Authorized attachment extensions - text: "A list of file extensions allowed for upload, separate with commas. WARNING: Allowing uploads may cause security issues." + label: Dozwolone rozszerzenia załączników + text: "Lista rozszerzeń plików dozwolonych do przesyłania; oddziel po przecinkach. UWAGA: Zezwolenie na przesyłanie plików może powodować ryzyko bezpieczeństwa." seo: page_title: SEO permalink: @@ -2190,7 +2247,7 @@ ui: text: "OSTRZEŻENIE: Jeśli wyłączone, już się nie zalogujesz, jeśli wcześniej nie skonfigurowałeś innej metody logowania." installed_plugins: title: Zainstalowane wtyczki - plugin_link: Plugins extend and expand the functionality. You may find plugins in the <1>Plugin Repository. + plugin_link: Wtyczki rozszerzają i rozbudowują funkcjonalność. Wtyczki znajdziesz w <1>Repozytorium Wtyczek. filter: all: Wszystkie active: Aktywne @@ -2232,25 +2289,25 @@ ui: title: Uprawnienia level: label: Wymagany poziom reputacji - text: Wybierz reputację wymaganą dla uprawnień + text: Wybierz reputację wymaganą dla tego uprawnienia msg: - should_be_number: the input should be number - number_larger_1: number should be equal or larger than 1 + should_be_number: Wartość musi być liczbą + number_larger_1: Liczba musi być równa 1 lub większa badges: - action: Action - active: Active - activate: Activate - all: All - awards: Awards - deactivate: Deactivate + action: Akcja + active: Aktywne + activate: Aktywuj + all: Wszystkie + awards: Przyznane + deactivate: Dezaktywuj filter: - placeholder: Filter by name, badge:id + placeholder: Filtruj po nazwie, badge:id group: Grupa - inactive: Inactive - name: Name + inactive: Nieaktywne + name: Nazwa show_logs: Wyświetl dzienniki status: Status - title: Badges + title: Odznaki form: optional: (opcjonalne) empty: nie może być puste @@ -2273,11 +2330,11 @@ ui: approve_flag_tip: Czy akceptujesz tę flagę? approve_post_tip: Czy zatwierdzasz ten post? approve_user_tip: Czy zatwierdzasz tego użytkownika? - suggest_edits: Suggested edits + suggest_edits: Sugerowane edycje flag_post: Oznacz wpis flag_user: Oznacz użytkownika - queued_post: Queued post - queued_user: Queued user + queued_post: Oczekujący post + queued_user: Oczekujący użytkownik filter_label: Typ reputation: reputacja flag_post_type: Oznaczono ten wpis jako {{ type }}. @@ -2330,7 +2387,7 @@ ui: discard_confirm: Czy na pewno chcesz odrzucić swoją wersję roboczą? messages: post_deleted: Ten post został usunięty. - post_cancel_deleted: This post has been undeleted. + post_cancel_deleted: Usunięcie tego posta zostało anulowane. post_pin: Ten post został przypięty. post_unpin: Ten post został odpięty. post_hide_list: Ten post został ukryty na liście. @@ -2339,21 +2396,20 @@ ui: post_list: Ten wpis został umieszczony na liście. post_unlist: Ten wpis został usunięty z listy. post_pending: Twój wpis oczekuje na recenzje. Będzie widoczny po jej akceptacji. - post_closed: This post has been closed. - answer_deleted: This answer has been deleted. - answer_cancel_deleted: This answer has been undeleted. - change_user_role: This user's role has been changed. - user_inactive: This user is already inactive. - user_normal: This user is already normal. - user_suspended: This user has been suspended. - user_deleted: This user has been deleted. - badge_activated: This badge has been activated. - badge_inactivated: This badge has been inactivated. - users_deleted: These users have been deleted. - posts_deleted: These questions have been deleted. - answers_deleted: These answers have been deleted. - copy: Copy to clipboard - copied: Copied - external_content_warning: External images/media are not displayed. - + post_closed: Ten post został zamknięty. + answer_deleted: Ta odpowiedź została usunięta. + answer_cancel_deleted: Ta odpowiedź została przywrócona. + change_user_role: Rola tego użytkownika została zmieniona. + user_inactive: Ten użytkownik jest już nieaktywny. + user_normal: Ten użytkownik jest już aktywny. + user_suspended: Ten użytkownik został zawieszony. + user_deleted: Ten użytkownik został usunięty. + badge_activated: Ta odznaka została aktywowana. + badge_inactivated: Ta odznaka została dezaktywowana. + users_deleted: Ci użytkownicy zostali usunięci. + posts_deleted: Te pytania zostały usunięte. + answers_deleted: Te odpowiedzi zostały usunięte. + copy: Skopiuj do schowka + copied: Skopiowano + external_content_warning: Zewnętrzne obrazy/media nie są wyświetlane. From 48b1de831473ed9e79fc4f453696428a43e69474 Mon Sep 17 00:00:00 2001 From: joaoback <156559121+joaoback@users.noreply.github.com> Date: Fri, 12 Sep 2025 22:21:32 -0300 Subject: [PATCH 18/25] Update pt_BR.yaml Translations of items that had not yet been translated. Adjustments to translations already made. --- i18n/pt_BR.yaml | 248 ++++++++++++++++++++++++------------------------ 1 file changed, 124 insertions(+), 124 deletions(-) diff --git a/i18n/pt_BR.yaml b/i18n/pt_BR.yaml index 42d56aaf7..45e00873c 100644 --- a/i18n/pt_BR.yaml +++ b/i18n/pt_BR.yaml @@ -288,7 +288,7 @@ ui: change_email: Modificar e-mail install: Instalação do Resposta upgrade: Atualização do Resposta - maintenance: Manutençã do Website + maintenance: Manutenção do Website users: Usuários notifications: title: Notificações @@ -327,7 +327,7 @@ ui: empty: Código não pode ser vazio. language: label: Idioma (opcional) - placeholder: Tetecção automática + placeholder: Detecção automática btn_cancel: Cancelar btn_confirm: Adicionar formula: @@ -351,7 +351,7 @@ ui: image: text: Imagem add_image: Adicionar imagem - tab_image: Enviar image, + tab_image: Enviar imagem form_image: fields: file: @@ -380,7 +380,7 @@ ui: outdent: text: Não identado italic: - text: Emphase + text: Ênfase link: text: Superlink (Hyperlink) add_link: Adicionar superlink (hyperlink) @@ -537,7 +537,7 @@ ui: title: Adicionar Pergunta edit_title: Editar Pergunta default_reason: Editar pergunta - similar_questions: Similar perguntas + similar_questions: Perguntas similares form: fields: revision: @@ -564,10 +564,10 @@ ui: label: Resumo da edição placeholder: >- Explique resumidamente suas alterações (ortografia corrigida, gramática corrigida, formatação aprimorada) - btn_post_question: Publicação a sua pergunta + btn_post_question: Publicar a sua pergunta btn_save_edits: Salvar edições answer_question: Responda a sua própria pergunta - post_question&answer: Publicação a sua pergunta e resposta + post_question&answer: Publicar a sua pergunta e resposta tag_selector: add_btn: Adicionar marcador create_btn: Criar novo marcador @@ -589,7 +589,7 @@ ui: placeholder: Procurar footer: build_on: >- - Built on <1> Answer - the open-source software that powers Q&A communities.
Made with love © {{cc}}. + Desenvolvido com base no <1> Answer — o software de código aberto que alimenta comunidades de perguntas e respostas.
Feito com amor © {{cc}}. upload_img: name: Mudar loading: carregando... @@ -604,13 +604,13 @@ ui: info: "Se não chegar, verifique sua pasta de spam." another: >- Enviamos outro e-mail de ativação para você em {{mail}}. Pode levar alguns minutos para chegar; certifique-se de verificar sua pasta de spam. - btn_name: Resend activation email + btn_name: Reenviar e-mail de ativação change_btn_name: Mudar email msg: empty: Não pode ser vazio. login: page_title: Bem vindo ao {{site_name}} - login_to_continue: Entre para continue + login_to_continue: Entre para continuar info_sign: Não possui uma conta? <1>Cadastrar-se info_login: Já possui uma conta? <1>Entre agreements: Ao se registrar, você concorda com as <1>políticas de privacidades e os <3>termos de serviços. @@ -776,9 +776,9 @@ ui: delete: title: Excluir esta postagem question: >- - Nós não recomendamos excluindo perguntas com respostas porque isso priva os futuros leitores desse conhecimento.

Repeated deletion of answered questions can result in a sua account being blocked from asking. Você tem certeza que deseja deletar? + Nós não recomendamos excluir perguntas com respostas porque isso priva os futuros leitores desse conhecimento.

A exclusão repetida de perguntas respondidas pode resultar no bloqueio de perguntas de sua conta. Você tem certeza que deseja excluir? answer_accepted: >- -

Nós não recomendamos deleting accepted answer porque isso priva os futuros leitores desse conhecimento.

Repeated deletion of accepted answers can result in a sua account being blocked from answering. Você tem certeza que deseja deletar? +

Não recomendamos excluir resposta aceita porque isso priva os futuros leitores desse conhecimento.

A exclusão repetida de respostas aceitas pode resultar no bloqueio de respostas de uma conta sua. Você tem certeza que deseja excluir? other: Você tem certeza que deseja deletar? tip_question_deleted: Esta postagem foi deletada tip_answer_deleted: Esta resposta foi deletada @@ -834,7 +834,7 @@ ui: link: Continuar para a página inicial. invalid: >- Desculpe, este link de confirmação não é mais válido. Talvez a sua já está ativa. - confirm_new_email: Your email has been updated. + confirm_new_email: Seu e-mail foi atualizado. confirm_new_email_invalid: >- Desculpe, este link de confirmação não é mais válido. Talvez o seu e-mail já tenha sido alterado. unsubscribe: @@ -846,7 +846,7 @@ ui: following_tags: Seguindo Marcadores edit: Editar save: Salvar - follow_tag_tip: Seguir tags to curate a sua lista de perguntas. + follow_tag_tip: Siga as tags para selecionar sua lista de perguntas. hot_questions: Perguntas quentes all_questions: Todas Perguntas x_questions: "{{ count }} perguntas" @@ -878,7 +878,7 @@ ui: score: Pontuação edit_profile: Editar Perfil visited_x_days: "Visitado {{ count }} dias" - viewed: Viewed + viewed: Visualizado joined: Ingressou last_login: Visto about_me: Sobre mim @@ -900,13 +900,13 @@ ui: x_questions: perguntas install: title: Instalação - next: Proximo + next: Próximo done: Completo config_yaml_error: Não é possível criar o arquivo config.yaml. lang: label: Por favor Escolha um Idioma db_type: - label: Database Engine + label: Mecanismo de banco de dados db_username: label: Nome de usuário placeholder: root @@ -916,68 +916,68 @@ ui: placeholder: root msg: Senha não pode ser vazio. db_host: - label: Database Host + label: Host do banco de dados placeholder: "db:3306" - msg: Database Host não pode ser vazio. + msg: Host de banco de dados não pode ficar vazio. db_name: - label: Database Nome + label: Nome do banco de dados placeholder: answer - msg: Database Nome não pode ser vazio. + msg: O nome do banco de dados não pode ficar vazio. db_file: - label: Database File + label: Arquivo de banco de dados placeholder: /data/answer.db - msg: Database File não pode ser vazio. + msg: O arquivo de banco de dados não pode ficar vazio. config_yaml: - title: Create config.yaml - label: The config.yaml file created. + title: Criar config.yaml + label: O arquivo config.yaml foi criado. desc: >- - You can create the <1>config.yaml file manually in the <1>/var/wwww/xxx/ directory and paste the following text into it. - info: After you've done that, click "Next" button. - site_information: Site Information + Você pode criar o arquivo <1>config.yaml manualmente no diretório <1>/var/www/xxx/ e colar o seguinte texto nele. + info: Depois de fazer isso, clique no botão "Avançar". + site_information: Informações do site admin_account: Administrador Conta site_name: label: Site Nome msg: Site Nome não pode ser vazio. site_url: label: Site URL - text: The address of a sua site. + text: O endereço do seu site. msg: empty: Site URL não pode ser vazio. - incorrect: Site URL incorrect format. + incorrect: Formato incorreto da URL do site. contact_email: - label: E-mail par contato - text: Email address of key contact responsible for this site. + label: E-mail para contato + text: Endereço de e-mail do contato principal responsável por este site. msg: - empty: E-mail par contato não pode ser vazio. - incorrect: E-mail par contato incorrect format. + empty: E-mail para contato não pode ser vazio. + incorrect: E-mail para contato em formato incorreto. admin_name: label: Nome msg: Nome não pode ser vazio. admin_password: label: Senha text: >- - You will need this password to log in. Por favor store it in a secure location. - msg: Senha não pode ser vazio. + Você precisará dessa senha para efetuar login. Por favor, guarde-a em um local seguro. + msg: Senha não pode ser vazia. admin_email: label: Email - text: You will need this email to log in. + text: Você precisará deste e-mail para fazer login. msg: empty: Email não pode ser vazio. - incorrect: Email incorrect format. - ready_title: Your Resposta is Ready! + incorrect: Formato de e-mail incorreto. + ready_title: Sua resposta está pronta! ready_desc: >- - If you ever feel like changing more settings, visit <1>admin section; find it in the site menu. - good_luck: "Have fun, and good luck!" - warn_title: Warning + Se você quiser alterar mais configurações, visite a <1>seção de administração; encontre-a no menu do site. + good_luck: "Divirta-se e boa sorte!" + warn_title: Aviso warn_desc: >- - The file <1>config.yaml already exists. If you need to reset any of the configuration items in this file, please delete it first. - install_now: You may try <1>installing now. - installed: Already installed + O arquivo <1>config.yaml já existe. Se precisar redefinir algum item de configuração neste arquivo, exclua-o primeiro. + install_now: Você pode tentar <1>instalar agora. + installed: Já instalado installed_desc: >- - You appear to have already installed. To reinstall please clear a sua old database tables first. - db_failed: Database connection failed + Parece que você já instalou. Para reinstalar, limpe primeiro as tabelas antigas do seu banco de dados. + db_failed: Falha na conexão do banco de dados db_failed_desc: >- - This either means that the database information in a sua <1>config.yaml file is incorrect or that contact with the database server could not be established. This could mean a sua host's database server is down. + Isso significa que as informações do banco de dados em um arquivo <1>config.yaml do SUA estão incorretas ou que o contato com o servidor do banco de dados não pôde ser estabelecido. Isso pode significar que o servidor de banco de dados de um host SUA está inativo. counts: views: visualizações Votos: votos @@ -987,7 +987,7 @@ ui: desc: "Infelizmente, esta postagem não existe mais." back_home: Voltar para a página inicial page_50X: - desc: O servidor encontrou um erro e não pôde concluir uma solicitação sua. + desc: O servidor encontrou um erro e não pôde concluir sua solicitação. back_home: Voltar para a página inicial page_maintenance: desc: "Estamos em manutenção, voltaremos em breve." @@ -1037,7 +1037,7 @@ ui: answer_links: Links das Respostas documents: Documentos feedback: Opinião - support: Supporte + support: Suporte review: Revisar config: Configurações update_to: Atualizar ao @@ -1233,7 +1233,7 @@ ui: smtp_port: label: SMTP Port msg: SMTP port must be number 1 ~ 65535. - text: The port to a sua mail server. + text: A porta para seu servidor de e-mail. smtp_username: label: SMTP Nome de usuário msg: SMTP username não pode ser vazio. @@ -1241,9 +1241,9 @@ ui: label: SMTP Senha msg: SMTP password não pode ser vazio. test_email_recipient: - label: Test Email Recipients - text: Provide email address that will receive test sends. - msg: Test email recipients is invalid + label: Destinatários de e-mail de teste + text: Forneça o endereço de e-mail que receberá os envios de testes. + msg: Os destinatários do e-mail de teste são inválidos smtp_authentication: label: Enable authentication title: SMTP Authentication @@ -1255,127 +1255,127 @@ ui: logo: label: Logo (opcional) msg: Logo não pode ser vazio. - text: The logo image at the top left of a sua site. Use a wide rectangular image with a height of 56 and an aspect ratio greater than 3:1. If left blank, the site title text will be shown. + text: A imagem do logotipo no canto superior esquerdo do seu site. Use uma imagem retangular larga com altura de 56 e proporção maior que 3:1. Se deixada em branco, o texto do título do site será exibido. mobile_logo: label: Mobile Logo (opcional) - text: The logo used on mobile version of a sua site. Use a wide rectangular image with a height of 56. If left blank, the image from the "logo" setting will be used. + text: O logotipo usado na versão mobile do seu site. Use uma imagem retangular larga com altura de 56. Se deixado em branco, a imagem da configuração "logotipo" será usada. square_icon: label: Square Icon (opcional) msg: Square icon não pode ser vazio. - text: Imagem used as the base for metadata icons. Should ideally be larger than 512x512. + text: Imagem usada como base para ícones de metadados. Idealmente, deve ser maior que 512x512. favicon: label: Favicon (opcional) - text: A favicon for a sua site. To work correctly over a CDN it must be a png. Will be resized to 32x32. If left blank, "square icon" will be used. + text: Um favicon para o seu site. Para funcionar corretamente em uma CDN, ele deve ser um png. Será redimensionado para 32x32. Se deixado em branco, o "ícone quadrado" será usado. legal: page_title: Legal terms_of_service: - label: Terms of Service - text: "You can add terms of service content here. If you already have a document hosted elsewhere, provide the full URL here." + label: Termos de Serviço + text: "Você pode adicionar conteúdo dos termos de serviço aqui. Se você já possui um documento hospedado em outro lugar, informe o URL completo aqui." privacy_policy: - label: Privacy Policy - text: "You can add privacy policy content here. If you already have a document hosted elsewhere, provide the full URL here." + label: Política de Privacidade + text: "Você pode adicionar o conteúdo da política de privacidade aqui. Se você já possui um documento hospedado em outro lugar, informe o URL completo aqui." write: - page_title: Write + page_title: Escrever recommend_tags: - label: Recommend Marcadores - text: "Por favor input tag slug above, one tag per line." + label: Recomendar Marcadores + text: "Por favor, insira o slug da tag acima, uma tag por linha." required_tag: - title: Required Tag - label: Set recommend tag as requirido - text: "Every new question must have ao menos one recommend tag." + title: Tag necessária + label: Definir tag recomendada como necessária + text: "Cada nova pergunta deve ter pelo menos uma tag de recomendação." reserved_tags: - label: Reserved Marcadores - text: "Reserved tags can only be added to a post by moderator." + label: Marcadores Reservados + text: "Tags reservadas só podem ser adicionadas a uma postagem pelo moderador." seo: page_title: SEO permalink: label: Permalink - text: Custom URL structures can improve the usability, and forward-compatibility of a sua links. + text: Estruturas de URL personalizadas podem melhorar a usabilidade e a compatibilidade futura de seus links. robots: label: robots.txt - text: This will permanently override any related site settings. + text: Isso substituirá permanentemente todas as configurações relacionadas do site. Temas: page_title: Temas Temas: label: Temas - text: Select an existing Tema. + text: Selecione um tema existente. navbar_style: - label: Navbar Style - text: Select an existing Tema. + label: Estilo da barra de navegação + text: Selecione um tema existente. primary_color: - label: Primary Color - text: Modify the colors used by a sua Temas + label: Cor primária + text: Modifique as cores usadas por seus Temas css_and_html: - page_title: CSS and HTML + page_title: CSS e HTML custom_css: label: Custom CSS - text: This will insert as + text: Isto será inserido como head: label: Head - text: This will insert before + text: Isto será inserido antes de header: label: Header - text: This will insert after + text: Isto será inserido após footer: label: Footer - text: This will insert before . + text: Isso será inserido antes de . login: page_title: Login membership: - title: Membership - label: Allow new registrations - text: Turn off to prevent anyone from creating a new account. + title: Associação + label: Permitir novos registros + text: Desative para impedir que alguém crie uma nova conta. private: - title: Private + title: Privado label: Login requirido - text: Only logged in users can access this community. + text: Somente usuários logados podem acessar esta comunidade. form: empty: não pode ser vazio - invalid: is invalid + invalid: é inválido btn_submit: Salvar - not_found_props: "Required property {{ key }} not found." + not_found_props: "Propriedade necessária {{ key }} não encontrada." page_review: review: Revisar - proposed: proposed - question_edit: Pergunta edit - answer_edit: Resposta edit - tag_edit: Tag edit - edit_summary: Editar summary - edit_question: Editar question - edit_answer: Editar answer + proposed: proposta + question_edit: Editar Pergunta + answer_edit: Editar Resposta + tag_edit: Editar Tag + edit_summary: Editar resumo + edit_question: Editar pergunta + edit_answer: Editar resposta edit_tag: Editar tag - empty: No review tasks left. + empty: Não há mais tarefas de revisão. timeline: - undeleted: undeleted - deleted: deleted - downvote: downvote - upvote: upvote - accept: accept - cancelled: cancelled - commented: commented + undeleted: não excluído + deleted: apagado + downvote: voto negativo + upvote: voto positivo + accept: aceitar + cancelled: cancelado + commented: comentado rollback: rollback - edited: edited - answered: answered - asked: asked - closed: closed - reopened: reopened - created: created - title: "Histórico for" - tag_title: "Timeline for" - show_Votos: "Show Votos" + edited: editado + answered: respondido + asked: perguntado + closed: fechado + reopened: reaberto + created: criado + title: "Histórico para" + tag_title: "Linha do tempo para" + show_Votos: "Mostrar votos" n_or_a: N/A - title_for_question: "Timeline for" - title_for_answer: "Timeline for answer to {{ title }} by {{ author }}" - title_for_tag: "Timeline for tag" + title_for_question: "Linha do tempo para" + title_for_answer: "Linha do tempo para resposta a {{ title }} por {{ author }}" + title_for_tag: "Linha do tempo para tag" datetime: Datetime - type: Type - by: By - comment: Comment - no_data: "We couldn't find anything." + type: Tipo + by: Por + comment: Comentário + no_data: "Não conseguimos encontrar nada." users: title: Usuários - users_with_the_most_reputation: Usuários with the highest reputation scores - users_with_the_most_vote: Usuários who voted the most - staffs: Our community staff - reputation: reputation + users_with_the_most_reputation: Usuários com as maiores pontuações de reputação + users_with_the_most_vote: Usuários que mais votaram + staffs: Nossa equipe comunitária + reputation: reputação Votos: Votos From 57ba299543e91b9f00362bfb3b0452bf2ccf0f35 Mon Sep 17 00:00:00 2001 From: Burak Tekin Date: Thu, 11 Dec 2025 04:42:21 +0300 Subject: [PATCH 19/25] chore: turkish translation improved (#1454) turkish translations improved Co-authored-by: dashuai --- i18n/tr_TR.yaml | 56 ++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/i18n/tr_TR.yaml b/i18n/tr_TR.yaml index 92d97ebe2..86a6321c2 100644 --- a/i18n/tr_TR.yaml +++ b/i18n/tr_TR.yaml @@ -234,8 +234,8 @@ backend: other: Güncelleme izni yok. content_cannot_empty: other: İçerik boş olamaz. - content_less_than_minimum: - other: Not enough content entered. + content_less_than_minumum: + other: Yeterli içerik girilmedi. rank: fail_to_meet_the_condition: other: İtibar seviyesi koşulu karşılamıyor. @@ -266,7 +266,7 @@ backend: cannot_set_synonym_as_itself: other: Bir etiketin eş anlamlısını kendisi olarak ayarlayamazsınız. minimum_count: - other: Not enough tags were entered. + other: Yeterli sayıda etiket girilmedi. smtp: config_from_name_cannot_be_email: other: Gönderen adı bir e-posta adresi olamaz. @@ -311,13 +311,13 @@ backend: add_bulk_users_amount_error: other: "Bir kerede eklediğiniz kullanıcı sayısı 1-{{.MaxAmount}} aralığında olmalıdır." status_suspended_forever: - other: "This user was suspended forever. This user doesn't meet a community guideline." + other: "Bu kullanıcı süresiz olarak askıya alındı. Bu kullanıcı topluluk kurallarını karşılamıyor." status_suspended_until: - other: "This user was suspended until {{.SuspendedUntil}}. This user doesn't meet a community guideline." + other: "Bu kullanıcı {{.SuspendedUntil}} tarihine kadar askıya alındı. Bu kullanıcı topluluk kurallarını karşılamıyor." status_deleted: - other: "This user was deleted." + other: "Bu kullanıcı silindi." status_inactive: - other: "This user is inactive." + other: "Bu kullanıcı aktif değil." config: read_config_failed: other: Yapılandırma okunamadı. @@ -821,7 +821,7 @@ ui: tag_wiki: etiket wikisi create_tag: Etiket Oluştur edit_tag: Etiketi Düzenle - ask_a_question: Create Question + ask_a_question: Soru Oluştur edit_question: Soruyu Düzenle edit_answer: Cevabı Düzenle search: Ara @@ -1069,9 +1069,9 @@ ui: day: gün hours: saatler days: günler - month: month - months: months - year: year + month: ay + months: aylar + year: yıl reaction: heart: kalp smile: gülümseme @@ -1127,10 +1127,10 @@ ui: more: Daha Fazla wiki: Wiki ask: - title: Create Question + title: Soru Oluştur edit_title: Soruyu Düzenle default_reason: Soruyu düzenle - default_first_reason: Create question + default_first_reason: Soru oluştur similar_questions: Benzer sorular form: fields: @@ -1138,7 +1138,7 @@ ui: label: Revizyon title: label: Başlık - placeholder: What's your topic? Be specific. + placeholder: Konunuz nedir? Ayrıntılı belirtin. msg: empty: Başlık boş olamaz. range: Başlık en fazla 150 karakter olabilir @@ -1147,8 +1147,8 @@ ui: msg: empty: İçerik boş olamaz. hint: - optional_body: Describe what the question is about. - minimum_characters: "Describe what the question is about, at least {{min_content_length}} characters are required." + optional_body: Sorunun ne hakkında olduğunu açıklayın. + minimum_characters: "Sorunun ne hakkında olduğunu açıklayın, en az {{min_content_length}} karakter gereklidir." tags: label: Etiketler msg: @@ -1169,9 +1169,9 @@ ui: add_btn: Etiket ekle create_btn: Yeni etiket oluştur search_tag: Etiket ara - hint: Describe what your content is about, at least one tag is required. - hint_zero_tags: Describe what your content is about. - hint_more_than_one_tag: "Describe what your content is about, at least {{min_tags_number}} tags are required." + hint: İçeriğinizin ne hakkında olduğunu açıklayın, en az bir etiket gereklidir. + hint_zero_tags: İçeriğinizin ne hakkında olduğunu açıklayın. + hint_more_than_one_tag: "İçeriğinizin ne hakkında olduğunu açıklayın, en az {{min_tags_number}} etiket gereklidir." no_result: Eşleşen etiket bulunamadı tag_required_text: Gerekli etiket (en az bir tane) header: @@ -1377,12 +1377,12 @@ ui: review: Revizyonunuz incelendikten sonra görünecek. sent_success: Başarıyla gönderildi related_question: - title: Related + title: İlgili answers: cevap linked_question: - title: Linked - description: Posts linked to - no_linked_question: No contents linked from this content. + title: Bağlantılı + description: Bağlantılı gönderiler + no_linked_question: Bu içerikten bağlantı verilen içerik yok. invite_to_answer: title: İnsanları Davet Et desc: Cevap verebileceğini düşündüğünüz kişileri davet edin. @@ -1391,11 +1391,11 @@ ui: search: Kişi ara question_detail: action: Eylem - created: Created + created: Oluşturuldu Asked: Soruldu asked: sordu update: Değiştirildi - Edited: Edited + Edited: Düzenlendi edit: düzenledi commented: yorum yaptı Views: Görüntülendi @@ -1403,7 +1403,7 @@ ui: Following: Takip Ediliyor follow_tip: Bildirim almak için bu soruyu takip edin answered: cevapladı - closed_in: Şurada kapatıldı + closed_in: Burada kapatıldı show_exist: Var olan soruyu göster. useful: Faydalı question_useful: Faydalı ve açık @@ -2098,8 +2098,8 @@ ui: label: Her kullanıcı aynı soru için sadece bir cevap yazabilir text: "Kullanıcıların aynı soruya birden fazla cevap yazmasına izin vermek için kapatın, bu cevapların odaktan uzaklaşmasına neden olabilir." min_tags: - label: "Minimum tags per question" - text: "Minimum number of tags required in a question." + label: "Soru başına minimum etiket" + text: "Bir soruda bulunması gereken minimum etiket sayısı." recommend_tags: label: Önerilen etiketler text: "Önerilen etiketler varsayılan olarak açılır listede gösterilecektir." From d468e2ba8dee2577ff0af8e7cbcfb2b111f6abdb Mon Sep 17 00:00:00 2001 From: liruohrh <2372221537@qq.com> Date: Sun, 7 Dec 2025 00:51:15 +0800 Subject: [PATCH 20/25] feat: add env for glob load template files by gin debug render --- internal/base/server/http.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/internal/base/server/http.go b/internal/base/server/http.go index 4fbb04cb2..512f3da21 100644 --- a/internal/base/server/http.go +++ b/internal/base/server/http.go @@ -22,6 +22,7 @@ package server import ( "html/template" "io/fs" + "os" brotli "github.com/anargu/gin-brotli" "github.com/apache/answer/internal/base/middleware" @@ -53,9 +54,14 @@ func NewHTTPServer(debug bool, r.Use(brotli.Brotli(brotli.DefaultCompression), middleware.ExtractAndSetAcceptLanguage, shortIDMiddleware.SetShortIDFlag()) r.GET("/healthz", func(ctx *gin.Context) { ctx.String(200, "OK") }) - html, _ := fs.Sub(ui.Template, "template") - htmlTemplate := template.Must(template.New("").Funcs(funcMap).ParseFS(html, "*")) - r.SetHTMLTemplate(htmlTemplate) + templatePath := os.Getenv("ANSWER_TEMPLATE_PATH") + if templatePath != "" { + r.LoadHTMLGlob(templatePath) + } else { + html, _ := fs.Sub(ui.Template, "template") + htmlTemplate := template.Must(template.New("").Funcs(funcMap).ParseFS(html, "*")) + r.SetHTMLTemplate(htmlTemplate) + } r.Use(middleware.HeadersByRequestURI()) viewRouter.Register(r, uiConf.BaseURL) From fbb877ab11760b69ee17cb0d00822fead64e60c9 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Thu, 11 Dec 2025 14:23:17 +0800 Subject: [PATCH 21/25] fix(translator): enhance error reporting for invalid translator YAML files --- internal/base/translator/provider.go | 165 +++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/internal/base/translator/provider.go b/internal/base/translator/provider.go index 47212e84f..1a465b1e8 100644 --- a/internal/base/translator/provider.go +++ b/internal/base/translator/provider.go @@ -23,6 +23,8 @@ import ( "fmt" "os" "path/filepath" + "sort" + "strings" "github.com/google/wire" myTran "github.com/segmentfault/pacman/contrib/i18n" @@ -100,6 +102,7 @@ func NewTranslator(c *I18n) (tr i18n.Translator, err error) { // add translator use backend translation if err = myTran.AddTranslator(content, file.Name()); err != nil { log.Debugf("add translator failed: %s %s", file.Name(), err) + reportTranslatorFormatError(file.Name(), buf) continue } } @@ -160,3 +163,165 @@ func TrWithData(lang i18n.Language, key string, templateData any) string { } return translation } + +// reportTranslatorFormatError re-parses the YAML file to locate the invalid entry +// when go-i18n fails to add the translator. +func reportTranslatorFormatError(fileName string, content []byte) { + var raw any + if err := yaml.Unmarshal(content, &raw); err != nil { + log.Errorf("parse translator file %s failed when diagnosing format error: %s", fileName, err) + return + } + if err := inspectTranslatorNode(raw, nil, true); err != nil { + log.Errorf("translator file %s invalid: %s", fileName, err) + } +} + +func inspectTranslatorNode(node any, path []string, isRoot bool) error { + switch data := node.(type) { + case nil: + if isRoot { + return fmt.Errorf("root value is empty") + } + return fmt.Errorf("%s contains an empty value", formatTranslationPath(path)) + case string: + if isRoot { + return fmt.Errorf("root value must be an object but found string") + } + return nil + case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64: + if isRoot { + return fmt.Errorf("root value must be an object but found %T", data) + } + return fmt.Errorf("%s expects a string translation but found %T", formatTranslationPath(path), data) + case map[string]any: + if isMessageMap(data) { + return nil + } + keys := make([]string, 0, len(data)) + for key := range data { + keys = append(keys, key) + } + sort.Strings(keys) + for _, key := range keys { + if err := inspectTranslatorNode(data[key], append(path, key), false); err != nil { + return err + } + } + return nil + case map[string]string: + mapped := make(map[string]any, len(data)) + for k, v := range data { + mapped[k] = v + } + return inspectTranslatorNode(mapped, path, isRoot) + case map[any]any: + if isMessageMap(data) { + return nil + } + type kv struct { + key string + val any + } + items := make([]kv, 0, len(data)) + for key, val := range data { + strKey, ok := key.(string) + if !ok { + return fmt.Errorf("%s uses a non-string key %#v", formatTranslationPath(path), key) + } + items = append(items, kv{key: strKey, val: val}) + } + sort.Slice(items, func(i, j int) bool { + return items[i].key < items[j].key + }) + for _, item := range items { + if err := inspectTranslatorNode(item.val, append(path, item.key), false); err != nil { + return err + } + } + return nil + case []any: + for idx, child := range data { + nextPath := append(path, fmt.Sprintf("[%d]", idx)) + if err := inspectTranslatorNode(child, nextPath, false); err != nil { + return err + } + } + return nil + case []map[string]any: + for idx, child := range data { + nextPath := append(path, fmt.Sprintf("[%d]", idx)) + if err := inspectTranslatorNode(child, nextPath, false); err != nil { + return err + } + } + return nil + default: + if isRoot { + return fmt.Errorf("root value must be an object but found %T", data) + } + return fmt.Errorf("%s contains unsupported value type %T", formatTranslationPath(path), data) + } +} + +var translatorReservedKeys = []string{ + "id", "description", "hash", "leftdelim", "rightdelim", + "zero", "one", "two", "few", "many", "other", +} + +func isMessageMap(data any) bool { + switch v := data.(type) { + case map[string]any: + for _, key := range translatorReservedKeys { + val, ok := v[key] + if !ok { + continue + } + if _, ok := val.(string); ok { + return true + } + } + case map[string]string: + for _, key := range translatorReservedKeys { + val, ok := v[key] + if !ok { + continue + } + if val != "" { + return true + } + } + case map[any]any: + for _, key := range translatorReservedKeys { + val, ok := v[key] + if !ok { + continue + } + if _, ok := val.(string); ok { + return true + } + } + } + return false +} + +func formatTranslationPath(path []string) string { + if len(path) == 0 { + return "root" + } + var b strings.Builder + for _, part := range path { + if part == "" { + continue + } + if part[0] == '[' { + b.WriteString(part) + continue + } + if b.Len() > 0 { + b.WriteByte('.') + } + b.WriteString(part) + } + return b.String() +} From f88ff2e2ca543cb45a62e9347f3e9161b0818f9d Mon Sep 17 00:00:00 2001 From: shuai Date: Fri, 12 Dec 2025 17:37:21 +0800 Subject: [PATCH 22/25] fix: footer width should be aligned with main content --- ui/src/pages/SideNavLayout/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/pages/SideNavLayout/index.tsx b/ui/src/pages/SideNavLayout/index.tsx index 907b9b281..b9bc38b9c 100644 --- a/ui/src/pages/SideNavLayout/index.tsx +++ b/ui/src/pages/SideNavLayout/index.tsx @@ -38,7 +38,7 @@ const Index: FC = () => { -
+
From e35b9551597aa5979b624b342e7e923cee814988 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Mon, 15 Dec 2025 12:34:42 +0800 Subject: [PATCH 23/25] fix(lang): enhance language retrieval from gin context --- internal/base/handler/lang.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/internal/base/handler/lang.go b/internal/base/handler/lang.go index 8886f0631..202449e9d 100644 --- a/internal/base/handler/lang.go +++ b/internal/base/handler/lang.go @@ -23,11 +23,22 @@ import ( "context" "github.com/apache/answer/internal/base/constant" + "github.com/gin-gonic/gin" "github.com/segmentfault/pacman/i18n" ) // GetLangByCtx get language from header func GetLangByCtx(ctx context.Context) i18n.Language { + if ginCtx, ok := ctx.(*gin.Context); ok { + acceptLanguage, ok := ginCtx.Get(constant.AcceptLanguageFlag) + if ok { + if acceptLanguage, ok := acceptLanguage.(i18n.Language); ok { + return acceptLanguage + } + return i18n.DefaultLanguage + } + } + acceptLanguage, ok := ctx.Value(constant.AcceptLanguageContextKey).(i18n.Language) if ok { return acceptLanguage From f43f22b91410030d87c4f06148ecee655b570e06 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Mon, 15 Dec 2025 15:08:51 +0800 Subject: [PATCH 24/25] fix(lang): correct translations in Polish and Turkish language files --- i18n/pl_PL.yaml | 3 +-- i18n/tr_TR.yaml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/i18n/pl_PL.yaml b/i18n/pl_PL.yaml index a8d7b064a..7cf88431b 100644 --- a/i18n/pl_PL.yaml +++ b/i18n/pl_PL.yaml @@ -864,8 +864,7 @@ ui:
  • twórz bloki kodu przy pomocy potrójnych odwrotnych apostrofów `

    ```
    kod tutaj
    ```
  • - - + prev: Poprzedni next: Następny page_title: diff --git a/i18n/tr_TR.yaml b/i18n/tr_TR.yaml index 970ae8cb2..802a81f69 100644 --- a/i18n/tr_TR.yaml +++ b/i18n/tr_TR.yaml @@ -235,7 +235,7 @@ backend: content_cannot_empty: other: İçerik boş olamaz. content_less_than_minimum: - other: Yeterli içerik girilmedi. + other: Not enough content entered. rank: fail_to_meet_the_condition: other: İtibar seviyesi koşulu karşılamıyor. From 59408774fba059d039846a88cf2aebd2b943c042 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Mon, 15 Dec 2025 15:08:51 +0800 Subject: [PATCH 25/25] fix(lang): correct translations in Polish and Turkish language files --- i18n/pl_PL.yaml | 3 +-- i18n/tr_TR.yaml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/i18n/pl_PL.yaml b/i18n/pl_PL.yaml index a8d7b064a..7cf88431b 100644 --- a/i18n/pl_PL.yaml +++ b/i18n/pl_PL.yaml @@ -864,8 +864,7 @@ ui:
  • twórz bloki kodu przy pomocy potrójnych odwrotnych apostrofów `

    ```
    kod tutaj
    ```
  • - - + prev: Poprzedni next: Następny page_title: diff --git a/i18n/tr_TR.yaml b/i18n/tr_TR.yaml index 970ae8cb2..802a81f69 100644 --- a/i18n/tr_TR.yaml +++ b/i18n/tr_TR.yaml @@ -235,7 +235,7 @@ backend: content_cannot_empty: other: İçerik boş olamaz. content_less_than_minimum: - other: Yeterli içerik girilmedi. + other: Not enough content entered. rank: fail_to_meet_the_condition: other: İtibar seviyesi koşulu karşılamıyor.