diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 6970e7d9c..b5f901d25 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -92,6 +92,7 @@ jobs: - name: Exec OpenIM API test run: | + sudo make test-api mkdir -p ./tmp touch ./tmp/test.md echo "# OpenIM Test" >> ./tmp/test.md @@ -104,6 +105,7 @@ jobs: - name: Exec OpenIM E2E Test run: | + sudo make test-e2e echo "" >> ./tmp/test.md echo "## OpenIM E2E Test" >> ./tmp/test.md echo "
Command Output for OpenIM E2E Test" >> ./tmp/test.md diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index bc1b094bf..c123566f1 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -74,6 +74,17 @@ jobs: echo $latest_tag > pkg/common/config/version continue-on-error: true + - name: Gen CHANGELOG file + run: | + current_tag=$(git describe --tags --abbrev=0) + version=$(echo "$current_tag" | sed -E 's/^v?([0-9]+)\.([0-9]+)\..*$/\1.\2/') + echo "OpenIM Version: $version" + make tools.install.git-chglog + cd CHANGELOG + git-chglog --tag-filter-pattern "v${version}.*" -o CHANGELOG-${version}.md + cd .. + continue-on-error: true + - name: Run unit test and get test coverage run: | make cover diff --git a/.golangci.yml b/.golangci.yml index b129ffd68..5bf9eeba9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -40,10 +40,14 @@ run: # "/" will be replaced by current OS file path separator to properly work # on Windows. skip-dirs: + - components + - docs - util - .*~ - api/swagger/docs - server/docs + - components/mnt/config/certs + - logs # default is true. Enables skipping of directories: # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ @@ -58,6 +62,12 @@ run: skip-files: - ".*\\.my\\.go$" - _test.go + - ".*_test.go" + - "mocks/" + - ".github/" + - "logs/" + - "_output/" + - "components/" # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules": # If invoked with -mod=readonly, the go command is disallowed from the implicit @@ -108,7 +118,6 @@ linters-settings: right-to-left-isolate: true first-strong-isolate: true pop-directional-isolate: true - dogsled: # checks assignments with too many blank identifiers; default is 2 max-blank-identifiers: 2 dupl: @@ -131,8 +140,8 @@ linters-settings: # path to a file containing a list of functions to exclude from checking # see https://github.com/kisielk/errcheck#excluding-functions for details - #exclude: errcheck.txt - + # exclude: errcheck.txt + errorlint: # Check whether fmt.Errorf uses the %w verb for formatting errors. See the readme for caveats errorf: true @@ -418,7 +427,7 @@ linters-settings: govet: # report about shadowed variables - check-shadowing: true + check-shadowing: false # settings per analyzer settings: @@ -489,9 +498,9 @@ linters-settings: - github.com\/user\/package\/v4\.Type lll: - # max line length, lines longer will be reported. Default is 120. + # max line length, lines longer will be reported. Default is 250. # '\t' is counted as 1 character by default, and can be changed with the tab-width option - line-length: 240 + line-length: 250 # tab width in spaces. Default to 1. tab-width: 4 maligned: @@ -715,17 +724,34 @@ linters: # enable-all: true disable-all: true enable: - - typecheck # 基本的类型检查 - - gofmt # 格式检查 - - govet # Go 语言的标准检查工具 - - gosimple # 简化代码的建议 - - misspell # 拼写错误 - - staticcheck # 静态检查 - - unused # 未使用的代码检查 - - goimports # 检查导入是否正确排序和格式化 - - godot # 注释句点检查 - - bodyclose # 确保 HTTP response body 被关闭 - - errcheck # 检查是否遗漏了错误返回值 + - typecheck # Basic type checking + - gofmt # Format check + - govet # Go's standard linting tool + - gosimple # Suggestions for simplifying code + - errcheck + - decorder + - sloglint + - ineffassign + - revive + - reassign + - tparallel + - unconvert + - dupl + - dupword + - errname + - gci + - goheader + - goprintffuncname + - gosec + - misspell # Spelling mistakes + - staticcheck # Static analysis + - unused # Checks for unused code + - goimports # Checks if imports are correctly sorted and formatted + - godot # Checks for comment punctuation + - bodyclose # Ensures HTTP response body is closed + - stylecheck # Style checker for Go code + - unused # Checks for unused code + - errcheck # Checks for missed error returns fast: true issues: @@ -792,6 +818,11 @@ issues: - lll source: "^//go:generate " + - text: ".*[\u4e00-\u9fa5]+.*" + linters: + - golint + source: "^//.*$" + # Independently from option `exclude` we use default exclude patterns, # it can be disabled by this option. To list all # excluded by default patterns execute `golangci-lint run --help`. @@ -852,4 +883,4 @@ severity: rules: - linters: - dupl - severity: info \ No newline at end of file + severity: info diff --git a/CHANGELOG/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md index ed9ba77c6..b929922f1 100644 --- a/CHANGELOG/CHANGELOG-3.5.md +++ b/CHANGELOG/CHANGELOG-3.5.md @@ -8,6 +8,12 @@ ## [Unreleased] + +## [v3.5.1-alpha.2] - 2024-01-26 + + +## [v3.5.1-rc.1] - 2024-01-23 + ## [v3.5.1-alpha.1] - 2024-01-09 @@ -59,7 +65,9 @@ - Merge branch 'tuoyun' -[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-alpha.1...HEAD +[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-alpha.2...HEAD +[v3.5.1-alpha.2]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-rc.1...v3.5.1-alpha.2 +[v3.5.1-rc.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-alpha.1...v3.5.1-rc.1 [v3.5.1-alpha.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.0...v3.5.1-alpha.1 [v3.5.0]: https://github.com/openimsdk/open-im-server/compare/v3.5.1...v3.5.0 [v3.5.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-bate.1...v3.5.1 diff --git a/Makefile b/Makefile index 4faf1c21d..89b9e4152 100644 --- a/Makefile +++ b/Makefile @@ -184,7 +184,7 @@ test-e2e: imports: @$(MAKE) go.imports -## clean: Remove all files that are created by building. ✨ +## clean: Delete all files created by the build, as well as all log files. ✨ .PHONY: clean clean: @$(MAKE) go.clean diff --git a/README.md b/README.md index e83afe5aa..1552f62e5 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,8 @@ We support many platforms. Here are the addresses for quick experience on the we ## :hammer_and_wrench: To Start Developing OpenIM +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/openimsdk/open-im-server) + [![Open in Dev Container](https://img.shields.io/static/v1?label=Dev%20Container&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/github/openimsdk/open-im-server) OpenIM Our goal is to build a top-level open source community. We have a set of standards, in the [Community repository](https://github.com/OpenIMSDK/community). diff --git a/config/templates/prometheus-dashboard.yaml b/config/templates/prometheus-dashboard.yaml index 417f3d343..2e1ae7760 100644 --- a/config/templates/prometheus-dashboard.yaml +++ b/config/templates/prometheus-dashboard.yaml @@ -53,7 +53,7 @@ }, "id": 16, "panels": [], - "title": "openim自定义指标", + "title": "openim Custom Metrics", "type": "row" }, { @@ -144,7 +144,7 @@ "refId": "A" } ], - "title": "在线人数", + "title": "Online population", "type": "timeseries" }, { @@ -235,7 +235,7 @@ "refId": "A" } ], - "title": "登入/注册人数", + "title": "Login/registration numbers", "type": "timeseries" }, { @@ -1345,7 +1345,7 @@ "type": "timeseries" } ], - "title": "应用服务器流量指标", + "title": "Traffic indicators of the application server", "type": "row" } ], diff --git a/docs/contrib/code-conventions.md b/docs/contrib/code-conventions.md index 049df6381..6b534779b 100644 --- a/docs/contrib/code-conventions.md +++ b/docs/contrib/code-conventions.md @@ -3,7 +3,15 @@ - [Code conventions](#code-conventions) - [POSIX shell](#posix-shell) - [Go](#go) - - [Directory and file conventions](#directory-and-file-conventions) + - [OpenIM Naming Conventions Guide](#openim-naming-conventions-guide) + - [1. General File Naming](#1-general-file-naming) + - [2. Special File Types](#2-special-file-types) + - [a. Script and Markdown Files](#a-script-and-markdown-files) + - [b. Uppercase Markdown Documentation](#b-uppercase-markdown-documentation) + - [3. Directory Naming](#3-directory-naming) + - [4. Configuration Files](#4-configuration-files) + - [Best Practices](#best-practices) + - [Directory and File Conventions](#directory-and-file-conventions) - [Testing conventions](#testing-conventions) ## POSIX shell @@ -67,12 +75,13 @@ Files within the OpenIM project should adhere to the following rules: + Stick to lowercase naming where possible for consistency and to prevent issues with case-sensitive systems. + Include version numbers or dates in file names if the file is subject to updates, following the format: `project-plan-v1.2.md` or `backup-2023-03-15.sql`. -## Directory and file conventions +## Directory and File Conventions + +- Avoid generic utility packages. Instead of naming a package "util", choose a name that clearly describes its purpose. For instance, functions related to waiting operations are contained within the `wait` package, which includes methods like `Poll`, fully named as `wait.Poll`. +- All filenames, script files, configuration files, and directories should be in lowercase and use dashes (`-`) as separators. +- For Go language files, filenames should be in lowercase and use underscores (`_`). +- Package names should match their directory names to ensure consistency. For example, within the `openim-api` directory, the Go file should be named `openim-api.go`, following the convention of using dashes for directory names and aligning package names with directory names. -- Avoid general utility packages. Packages called "util" are suspect. Instead, derive a name that describes your desired function. For example, the utility functions dealing with waiting for operations are in the `wait` package and include functionality like `Poll`. The full name is `wait.Poll`. -- All filenames should be lowercase. -- All source files and directories should use underscores, not dashes. - - Package directories should generally avoid using separators as much as possible. When package names are multiple words, they usually should be in nested subdirectories. ## Testing conventions diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md index dc11a3c7b..d2db7cbf3 100644 --- a/docs/contrib/environment.md +++ b/docs/contrib/environment.md @@ -449,7 +449,7 @@ This section involves configuring the log settings, including storage location, | Parameter | Example Value | Description | | ------------------------- | ------------------------ | --------------------------------- | -| LOG_STORAGE_LOCATION | "${OPENIM_ROOT}/logs/" | Location for storing logs | +| LOG_STORAGE_LOCATION | "${OPENIM_ROOT}/_output/logs/" | Location for storing logs | | LOG_ROTATION_TIME | "24" | Log rotation time (in hours) | | LOG_REMAIN_ROTATION_COUNT | "2" | Number of log rotations to retain | | LOG_REMAIN_LOG_LEVEL | "6" | Log level to retain | diff --git a/docs/contrib/go-code.md b/docs/contrib/go-code.md index 1de448da7..b122917ca 100644 --- a/docs/contrib/go-code.md +++ b/docs/contrib/go-code.md @@ -26,19 +26,19 @@ jwt "github.com/dgrijalva/jwt-go/v4" ```go import ( -// go standard package -"fmt" - -// third party package -"github.com/jinzhu/gorm" -"github.com/spf13/cobra" -"github.com/spf13/viper" - -// Anonymous packages are grouped separately, and anonymous package references are explained -// import mysql driver -_ "github.com/jinzhu/gorm/dialects/mysql" - -// inner package + // go standard package + "fmt" + + // third party package + "github.com/jinzhu/gorm" + "github.com/spf13/cobra" + "github.com/spf13/viper" + + // Anonymous packages are grouped separately, and anonymous package references are explained + // import mysql driver + _ "github.com/jinzhu/gorm/dialects/mysql" + + // inner package ) ``` @@ -48,33 +48,33 @@ When multiple variables need to be used in a function, the `var` declaration can ```go var ( -Width int -Height int + Width int + Height int ) ``` - When initializing a structure reference, please use `&T{}` instead of `new(T)` to make it consistent with structure initialization. ```go -// bad -sptr := new(T) -sptr.Name = "bar" - -// good -sptr := &T{Name: "bar"} + // bad + sptr := new(T) + sptr.Name = "bar" + + // good + sptr := &T{Name: "bar"} ``` - The struct declaration and initialization format takes multiple lines and is defined as follows. ```go -type User struct{ - Username string - Email string -} - -user := User{ -Username: "belm", -Email: "nosbelm@qq.com", + type User struct{ + Username string + Email string + } + + user := User{ + Username: "belm", + Email: "nosbelm@qq.com", } ``` @@ -217,20 +217,20 @@ if err != nil { // bad v, err := foo() if err != nil || v == nil { -// error handling -return err + // error handling + return err } //good v, err := foo() if err != nil { -// error handling -return err + // error handling + return err } if v == nil { -// error handling -return errors. New("invalid value v") + // error handling + return errors. New("invalid value v") } ``` @@ -239,13 +239,14 @@ return errors. New("invalid value v") ```go v, err := f() if err != nil { - // error handling - return // or continue. + // error handling + return // or continue. } ``` - Bug description suggestions - Error descriptions start with a lowercase letter and do not end with punctuation, for example: + ```go // bad errors.New("Redis connection failed") @@ -254,6 +255,7 @@ errors.New("redis connection failed.") // good errors.New("redis connection failed") ``` + - Tell users what they can do, not what they can't. - When declaring a requirement, use must instead of should. For example, `must be greater than 0, must match regex '[a-z]+'`. - When declaring that a format is incorrect, use must not. For example, `must not contain`. @@ -359,18 +361,18 @@ u := User{ For example: -``` +```go // Seeking to an offset before the start of the file is an error. // Seeking to any positive offset is legal, but the behavior of subsequent // I/O operations on the underlying object are implementation-dependent. type Seeker interface { -Seek(offset int64, whence int) (int64, error) + Seek(offset int64, whence int) (int64, error) } // ReadWriter is the interface that groups the basic Read and Write methods. type ReadWriter interface { -reader -Writer + reader + Writer } ``` @@ -386,7 +388,7 @@ Writer Some common nouns are listed below. -``` +```go // A GonicMapper that contains a list of common initialisms taken from golang/lint var LintGonicMapper = GonicMapper{ "API": true, @@ -523,6 +525,7 @@ package genericclioptions // ErrSigningMethod defines invalid signing method error. var ErrSigningMethod = errors. New("Invalid signing method") ``` + - When there is a large block of constant or variable definition, you can comment a general description in front, and then comment the definition of the constant in detail before or at the end of each line of constant, for example: ```go // Code must start with 1xxxxx. @@ -567,7 +570,7 @@ Each function or method that needs to be exported must have a comment, the forma // BeforeUpdate run before update database record. func (p *Policy) BeforeUpdate() (err error) { // normal code -return nil + return nil } ``` @@ -743,9 +746,9 @@ for i := 0; i < 10; i++ { ```go // bad for file := range files { -fd, err := os. Open(file) -if err != nil { -return err + fd, err := os. Open(file) + if err != nil { + return err } defer fd. Close() // normal code @@ -753,14 +756,14 @@ defer fd. Close() //good for file := range files { -func() { -fd, err := os. Open(file) -if err != nil { -return err -} -defer fd. Close() -// normal code -}() + func() { + fd, err := os. Open(file) + if err != nil { + return err + } + defer fd. Close() + // normal code + }() } ``` @@ -888,6 +891,7 @@ type LogHandler struct { } var_http.Handler = LogHandler{} ``` + - When the server processes a request, it should create a context, save the relevant information of the request (such as requestID), and pass it in the function call chain. ### 9.1 Performance @@ -900,3 +904,246 @@ var_http.Handler = LogHandler{} - If you want to directly modify the value of the map, the value can only be a pointer, otherwise the original value must be overwritten. - map needs to be locked during concurrency. - The conversion of interface{} cannot be checked during compilation, it can only be checked at runtime, be careful to cause panic. + +## 10 Golang CI Lint + +- Golang CI Lint is a fast Go linters runner. It runs linters in parallel, uses caching, and works well with all environments, including CI. + +**In local development, you can use the following command to install Golang CI Lint: ** + +```bash +make lint +``` + +**In CI/CD, Check the Github Actions status code below after you submit the code directly** + +[![OpenIM golangci-lint](https://github.com/openimsdk/open-im-server/actions/workflows/golangci-lint.yml/badge.svg)](https://github.com/openimsdk/open-im-server/actions/workflows/golangci-lint.yml) + +golangci lint can select the types of tools, refer to the official documentation: [https://golangci-lint.run/usage/linters/](https://golangci-lint.run/usage/linters/) + +The types of comments we currently use include: [https://github.com/openimsdk/open-im-server/blob/main/.golangci.yml](https://github.com/openimsdk/open-im-server/blob/main/.golangci.yml) the `linters.enable` field in the file. + +e.g: +```yaml +linters: + # please, do not use `enable-all`: it's deprecated and will be removed soon. + # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint + # enable-all: true + disable-all: true + enable: + - typecheck # Basic type checking + - gofmt # Format check + - govet # Go's standard linting tool + - gosimple # Suggestions for simplifying code + - misspell # Spelling mistakes + - staticcheck # Static analysis + - unused # Checks for unused code + - goimports # Checks if imports are correctly sorted and formatted + - godot # Checks for comment punctuation + - bodyclose # Ensures HTTP response body is closed + - errcheck # Checks for missed error returns + fast: true +``` + +Add that Chinese comments are not allowed in go code, please write a complete golangci lint specification on the basis of the above. + + +### 10.1 Configuration Document + +This configuration document is designed to configure the operational parameters of OpenIM (a hypothetical or specific code analysis tool), customize output formats, and provide detailed settings for specific code checkers (linters). Below is a summary of the document drafted based on the provided configuration information. + +#### 10.1 Runtime Options + +- **Concurrency** (`concurrency`): Default to use the available CPU count, can be manually set to 4 for parallel analysis. +- **Timeout** (`timeout`): Timeout duration for analysis operations, default is 1 minute, set here to 5 minutes. +- **Issue Exit Code** (`issues-exit-code`): Exit code defaults to 1 if at least one issue is found. +- **Test Files** (`tests`): Whether to include test files, defaults to true. +- **Build Tags** (`build-tags`): Specify build tags used by all linters, defaults to an empty list. Example adds `mytag`. +- **Skip Directories** (`skip-dirs`): Configure which directories' issues are not reported, defaults to empty, but some default directories are independently skipped. +- **Skip Files** (`skip-files`): Specify files where issues should not be reported, supports regular expressions. + +#### 10.2 Output Configuration + +- **Format** (`format`): Set output format, default is "colored-line-number". +- **Print Issued Lines** (`print-issued-lines`): Whether to print the lines where issues occur, defaults to true. +- **Print Linter Name** (`print-linter-name`): Whether to print the linter name at the end of issue text, defaults to true. +- **Uniqueness Filter** (`uniq-by-line`): Whether to make issue outputs unique per line, defaults to true. +- **Path Prefix** (`path-prefix`): Prefix to add to output file references, defaults to no prefix. +- **Sort Results** (`sort-results`): Sort results by file path, line number, and column number. + +#### 10.3 Linters Settings + +In the configuration file, the `linters-settings` section allows detailed configuration of individual linters. Below are examples of specific linters settings and their purposes: + +- **bidichk**: Used to check bidirectional text characters, ensuring correct display direction of text, especially when dealing with mixed left-to-right (LTR) and right-to-left (RTL) text. + +- **dogsled**: Monitors excessive use of blank identifiers (`_`) in assignment operations, which may obscure data processing errors or unclear logic. + +- **dupl**: Identifies duplicate code blocks, helping developers avoid code redundancy. The `threshold` parameter in settings allows adjustment of code similarity threshold triggering warnings. + +- **errcheck**: Checks for unhandled errors. In Go, error handling is achieved by checking function return values. This linter helps ensure all errors are properly handled. + +- **exhaustive**: Checks if `switch` statements include all possible values of an enum type, ensuring exhaustiveness of code. This helps avoid forgetting to handle certain cases. + +#### 10.4 Example: `errcheck` + +**Incorrect Code Example**: +```go +package main + +import ( + "fmt" + "os" +) + +func main() { + f, _ := os.Open("filename.ext") + defer f.Close() +} +``` + +**Issue**: In the above code, the error return value of `os.Open` function is explicitly ignored. This is a common mistake as it may lead to unhandled errors and hard-to-trace bugs. + +**Correct Form**: +```go +package main + +import ( + "fmt" + "os" +) + +func main() { + f, err := os.Open("filename.ext") + if err != nil { + fmt.Printf("error opening file: %v\n", err) + return + } + defer f.Close() +} +``` + +In the correct form, by checking the error (`err`) returned by `os.Open`, we gracefully handle error cases rather than simply ignoring them. + +#### 10.5 Example: `gofmt` + +**Incorrect Code Example**: +```go +package main +import "fmt" +func main() { +fmt.Println("Hello, world!") +} +``` + +**Issue**: This code snippet doesn't follow Go's standard formatting rules, for example, incorrect indentation of `fmt.Println`. + +**Correct Form**: +```go +package main + +import "fmt" + +func main() { + fmt.Println("Hello, world!") +} +``` + +Using `gofmt` tool can automatically fix such formatting issues, ensuring the code adheres to the coding standards of the Go community. + +#### 10.6 Example: `unused` + +**Incorrect Code Example**: +```go +package main + +func helper() {} + +func main() {} +``` + +**Issue**: The `helper` function is defined but not called anywhere, indicating potential redundant code or missing functionality implementation. + +**Correct Form**: +```go +package main + +// If the helper function is indeed needed, ensure it's used properly. +func helper() { + // Implement the function's functionality or ensure it's called elsewhere +} + +func main() { + helper() +} +``` + +To improve the section on Linters settings in the document, we'll expand with more detailed explanations and reinforce understanding through examples. + +#### 10.7 Example: `dogsled` + +**Incorrect Code Example**: +```go +func getValues() (int, int, int) { + return 1, 2, 3 +} + +func main() { + _, _, val := getValues() + fmt.Println(val) // Only interested in the third return value +} +``` + +**Explanation**: In the above code, we use two blank identifiers to ignore the first two return values. Excessive use of blank identifiers can make code reading difficult. + +**Improved Code**: +Consider refactoring the function or the usage of return values to reduce the need for blank identifiers or explicitly comment why ignoring certain values is safe. + +#### 10.8: `exhaustive` + +**Incorrect Code Example**: +```go +type Fruit int + +const ( + Apple Fruit = iota + Banana + Orange +) + +func getFruitName(f Fruit) string { + switch f { + case Apple: + return "Apple" + case Banana: + return "Banana" + // Missing handling for Orange + } + return "Unknown" +} +``` + +**Explanation**: In this code, the `switch` statement doesn't cover all possible values of the `Fruit` type; the case for `Orange` is missing. + +**Improved Code**: +```go +func getFruitName(f Fruit) string { + switch f { + case Apple: + return "Apple" + case Banana: + return "Banana" + case Orange: + return "Orange" + } + return "Unknown" +} +``` + +By adding the missing `case`, we ensure the `switch` statement is exhaustive, handling every possible enum value. + +#### 10.9 Optimization of Configuration Files and Application of Code Analysis Tools + +Through these examples, we demonstrate how to improve code quality by identifying and fixing common coding issues. OpenIM's configuration files allow developers to customize linters' behavior according to project requirements, ensuring code compliance with predefined quality standards and style guidelines. + +By employing these tools and configuration strategies, teams can reduce the number of bugs, enhance code maintainability, and facilitate efficient collaboration during code review processes. diff --git a/go.work b/go.work index 97d2816d6..be67ce842 100644 --- a/go.work +++ b/go.work @@ -3,6 +3,7 @@ go 1.19 use ( . ./test/typecheck + ./tools/codescan ./tools/changelog ./tools/component ./tools/data-conversion diff --git a/internal/api/auth.go b/internal/api/auth.go index 88539f63a..0f7a3933b 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -15,11 +15,9 @@ package api import ( - "github.com/gin-gonic/gin" - "github.com/OpenIMSDK/protocol/auth" "github.com/OpenIMSDK/tools/a2r" - + "github.com/gin-gonic/gin" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) diff --git a/internal/api/conversation.go b/internal/api/conversation.go index eb735e550..fe6c67001 100644 --- a/internal/api/conversation.go +++ b/internal/api/conversation.go @@ -15,11 +15,9 @@ package api import ( - "github.com/gin-gonic/gin" - "github.com/OpenIMSDK/protocol/conversation" "github.com/OpenIMSDK/tools/a2r" - + "github.com/gin-gonic/gin" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) diff --git a/internal/api/custom_validator.go b/internal/api/custom_validator.go index 8c5890501..d135b0dc4 100644 --- a/internal/api/custom_validator.go +++ b/internal/api/custom_validator.go @@ -15,24 +15,20 @@ package api import ( - "github.com/go-playground/validator/v10" - "github.com/OpenIMSDK/protocol/constant" + "github.com/go-playground/validator/v10" ) +// RequiredIf validates if the specified field is required based on the session type. func RequiredIf(fl validator.FieldLevel) bool { sessionType := fl.Parent().FieldByName("SessionType").Int() + switch sessionType { case constant.SingleChatType, constant.NotificationChatType: - if fl.FieldName() == "RecvID" { - return fl.Field().String() != "" - } + return fl.FieldName() != "RecvID" || fl.Field().String() != "" case constant.GroupChatType, constant.SuperGroupChatType: - if fl.FieldName() == "GroupID" { - return fl.Field().String() != "" - } + return fl.FieldName() != "GroupID" || fl.Field().String() != "" default: return true } - return true } diff --git a/internal/api/friend.go b/internal/api/friend.go index 7dc898a02..24bcbf899 100644 --- a/internal/api/friend.go +++ b/internal/api/friend.go @@ -17,10 +17,8 @@ package api import ( "github.com/OpenIMSDK/protocol/friend" "github.com/OpenIMSDK/tools/a2r" - - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" - "github.com/gin-gonic/gin" + "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) type FriendApi rpcclient.Friend diff --git a/internal/api/group.go b/internal/api/group.go index e525cd495..c18ded64b 100644 --- a/internal/api/group.go +++ b/internal/api/group.go @@ -17,10 +17,8 @@ package api import ( "github.com/OpenIMSDK/protocol/group" "github.com/OpenIMSDK/tools/a2r" - - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" - "github.com/gin-gonic/gin" + "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) type GroupApi rpcclient.Group diff --git a/internal/api/msg.go b/internal/api/msg.go index bd745df75..d38c14d4e 100644 --- a/internal/api/msg.go +++ b/internal/api/msg.go @@ -27,11 +27,9 @@ import ( "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "github.com/mitchellh/mapstructure" - + "github.com/openimsdk/open-im-server/v3/pkg/apistruct" "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/common/config" - - "github.com/openimsdk/open-im-server/v3/pkg/apistruct" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) @@ -209,6 +207,7 @@ func (m *MessageApi) SendMessage(c *gin.Context) { // Prepare the message request with additional required data. sendMsgReq, err := m.getSendMsgReq(c, req.SendMsg) if err != nil { + // Log and respond with an error if preparation fails. apiresp.GinError(c, err) return } @@ -224,7 +223,6 @@ func (m *MessageApi) SendMessage(c *gin.Context) { if err != nil { // Set the status to failed and respond with an error if sending fails. status = constant.MsgSendFailed - log.ZError(c, "send message err", err) apiresp.GinError(c, err) return } @@ -238,7 +236,8 @@ func (m *MessageApi) SendMessage(c *gin.Context) { }) if err != nil { // Log the error if updating the status fails. - log.ZError(c, "SetSendMsgStatus failed", err) + apiresp.GinError(c, err) + return } // Respond with a success message and the response payload. @@ -297,7 +296,6 @@ func (m *MessageApi) BatchSendMsg(c *gin.Context) { resp apistruct.BatchSendMsgResp ) if err := c.BindJSON(&req); err != nil { - log.ZError(c, "BatchSendMsg BindJSON failed", err) apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap()) return } @@ -308,14 +306,12 @@ func (m *MessageApi) BatchSendMsg(c *gin.Context) { } var recvIDs []string - var err error if req.IsSendAll { pageNumber := 1 showNumber := 500 for { recvIDsPart, err := m.userRpcClient.GetAllUserIDs(c, int32(pageNumber), int32(showNumber)) if err != nil { - log.ZError(c, "GetAllUserIDs failed", err) apiresp.GinError(c, err) return } @@ -331,7 +327,6 @@ func (m *MessageApi) BatchSendMsg(c *gin.Context) { log.ZDebug(c, "BatchSendMsg nums", "nums ", len(recvIDs)) sendMsgReq, err := m.getSendMsgReq(c, req.SendMsg) if err != nil { - log.ZError(c, "decodeData failed", err) apiresp.GinError(c, err) return } diff --git a/internal/api/route.go b/internal/api/route.go index 5cb94507f..ce8e3a62b 100644 --- a/internal/api/route.go +++ b/internal/api/route.go @@ -134,7 +134,7 @@ func Start(config *config.GlobalConfig, port int, proPort int) error { } func newGinRouter(disCov discoveryregistry.SvcDiscoveryRegistry, rdb redis.UniversalClient, config *config.GlobalConfig) *gin.Engine { - disCov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin"))) // 默认RPC中间件 + disCov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin"))) gin.SetMode(gin.ReleaseMode) r := gin.New() if v, ok := binding.Validator.Engine().(*validator.Validate); ok { @@ -340,13 +340,11 @@ func GinParseToken(rdb redis.UniversalClient, config *config.GlobalConfig) gin.H } m, err := dataBase.GetTokensWithoutError(c, claims.UserID, claims.PlatformID) if err != nil { - log.ZWarn(c, "cache get token error", errs.ErrTokenNotExist.Wrap()) apiresp.GinError(c, errs.ErrTokenNotExist.Wrap()) c.Abort() return } if len(m) == 0 { - log.ZWarn(c, "cache do not exist token error", errs.ErrTokenNotExist.Wrap()) apiresp.GinError(c, errs.ErrTokenNotExist.Wrap()) c.Abort() return @@ -355,12 +353,10 @@ func GinParseToken(rdb redis.UniversalClient, config *config.GlobalConfig) gin.H switch v { case constant.NormalToken: case constant.KickedToken: - log.ZWarn(c, "cache kicked token error", errs.ErrTokenKicked.Wrap()) apiresp.GinError(c, errs.ErrTokenKicked.Wrap()) c.Abort() return default: - log.ZWarn(c, "cache unknown token error", errs.ErrTokenUnknown.Wrap()) apiresp.GinError(c, errs.ErrTokenUnknown.Wrap()) c.Abort() return @@ -376,3 +372,10 @@ func GinParseToken(rdb redis.UniversalClient, config *config.GlobalConfig) gin.H } } } + +// // handleGinError logs and returns an error response through Gin context. +// func handleGinError(c *gin.Context, logMessage string, errType errs.CodeError, detail string) { +// wrappedErr := errType.Wrap(detail) +// apiresp.GinError(c, wrappedErr) +// c.Abort() +// } diff --git a/internal/api/statistics.go b/internal/api/statistics.go index 5750a7315..2b80a1585 100644 --- a/internal/api/statistics.go +++ b/internal/api/statistics.go @@ -15,11 +15,9 @@ package api import ( - "github.com/gin-gonic/gin" - "github.com/OpenIMSDK/protocol/user" "github.com/OpenIMSDK/tools/a2r" - + "github.com/gin-gonic/gin" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) diff --git a/internal/api/third.go b/internal/api/third.go index 984faaa20..190e0d540 100644 --- a/internal/api/third.go +++ b/internal/api/third.go @@ -25,7 +25,6 @@ import ( "github.com/OpenIMSDK/tools/a2r" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/mcontext" - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) diff --git a/internal/api/user.go b/internal/api/user.go index a62da6e25..468432ee0 100644 --- a/internal/api/user.go +++ b/internal/api/user.go @@ -67,7 +67,7 @@ func (u *UserApi) GetUsers(c *gin.Context) { func (u *UserApi) GetUsersOnlineStatus(c *gin.Context) { var req msggateway.GetUsersOnlineStatusReq if err := c.BindJSON(&req); err != nil { - apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap()) + apiresp.GinError(c, err) return } conns, err := u.Discov.GetConns(c, u.Config.RpcRegisterName.OpenImMessageGatewayName) @@ -85,7 +85,7 @@ func (u *UserApi) GetUsersOnlineStatus(c *gin.Context) { msgClient := msggateway.NewMsgGatewayClient(v) reply, err := msgClient.GetUsersOnlineStatus(c, &req) if err != nil { - log.ZWarn(c, "GetUsersOnlineStatus rpc err", err) + log.ZDebug(c, "GetUsersOnlineStatus rpc error", err) parseError := apiresp.ParseError(err) if parseError.ErrCode == errs.NoPermissionError { @@ -144,7 +144,7 @@ func (u *UserApi) GetUsersOnlineTokenDetail(c *gin.Context) { msgClient := msggateway.NewMsgGatewayClient(v) reply, err := msgClient.GetUsersOnlineStatus(c, &req) if err != nil { - log.ZWarn(c, "GetUsersOnlineStatus rpc err", err) + log.ZWarn(c, "GetUsersOnlineStatus rpc err", err) continue } else { wsResult = append(wsResult, reply.SuccessResult...) diff --git a/internal/msggateway/callback.go b/internal/msggateway/callback.go index 660404ab4..ab8c1f51f 100644 --- a/internal/msggateway/callback.go +++ b/internal/msggateway/callback.go @@ -20,7 +20,6 @@ import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/tools/mcontext" - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/http" diff --git a/internal/msggateway/client.go b/internal/msggateway/client.go index 9a4005e6c..4e843821e 100644 --- a/internal/msggateway/client.go +++ b/internal/msggateway/client.go @@ -22,18 +22,15 @@ import ( "sync" "sync/atomic" - "github.com/OpenIMSDK/tools/errs" - - "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" - - "google.golang.org/protobuf/proto" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/apiresp" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" + "google.golang.org/protobuf/proto" ) var ( @@ -91,13 +88,7 @@ type Client struct { // } // ResetClient updates the client's state with new connection and context information. -func (c *Client) ResetClient( - ctx *UserConnContext, - conn LongConn, - isBackground, isCompress bool, - longConnServer LongConnServer, - token string, -) { +func (c *Client) ResetClient(ctx *UserConnContext, conn LongConn, isBackground, isCompress bool, longConnServer LongConnServer, token string) { c.w = new(sync.Mutex) c.conn = conn c.PlatformID = utils.StringToInt(ctx.GetPlatformID()) @@ -112,9 +103,11 @@ func (c *Client) ResetClient( c.token = token } -// pingHandler handles ping messages and sends pong responses. func (c *Client) pingHandler(_ string) error { - _ = c.conn.SetReadDeadline(pongWait) + if err := c.conn.SetReadDeadline(pongWait); err != nil { + return err + } + return c.writePongMsg() } @@ -141,7 +134,8 @@ func (c *Client) readMessage() { } log.ZDebug(c.ctx, "readMessage", "messageType", messageType) - if c.closed.Load() { // 连接刚置位已经关闭,但是协程还没退出的场景 + if c.closed.Load() { + // The scenario where the connection has just been closed, but the coroutine has not exited c.closedErr = ErrConnClosed return } @@ -185,11 +179,11 @@ func (c *Client) handleMessage(message []byte) error { err := c.longConnServer.Decode(message, binaryReq) if err != nil { - return errs.Wrap(err) + return err } if err := c.longConnServer.Validate(binaryReq); err != nil { - return errs.Wrap(err) + return err } if binaryReq.SendID != c.UserID { @@ -239,7 +233,7 @@ func (c *Client) setAppBackgroundStatus(ctx context.Context, req *Req) ([]byte, } c.IsBackground = isBackground - // todo callback + // TODO: callback return resp, nil } @@ -273,7 +267,7 @@ func (c *Client) replyMessage(ctx context.Context, binaryReq *Req, err error, re } if binaryReq.ReqIdentifier == WsLogoutMsg { - return errors.New("user logout") + return errs.Wrap(errors.New("user logout")) } return nil } @@ -316,17 +310,21 @@ func (c *Client) writeBinaryMsg(resp Resp) error { encodedBuf, err := c.longConnServer.Encode(resp) if err != nil { - return errs.Wrap(err) + return err } c.w.Lock() defer c.w.Unlock() - _ = c.conn.SetWriteDeadline(writeWait) + err = c.conn.SetWriteDeadline(writeWait) + if err != nil { + return err + } + if c.IsCompress { resultBuf, compressErr := c.longConnServer.CompressWithPool(encodedBuf) if compressErr != nil { - return errs.Wrap(compressErr) + return compressErr } return c.conn.WriteMessage(MessageBinary, resultBuf) } @@ -344,7 +342,7 @@ func (c *Client) writePongMsg() error { err := c.conn.SetWriteDeadline(writeWait) if err != nil { - return errs.Wrap(err) + return err } return c.conn.WriteMessage(PongMessage, nil) diff --git a/internal/msggateway/compressor.go b/internal/msggateway/compressor.go index d4789536e..140aac4d8 100644 --- a/internal/msggateway/compressor.go +++ b/internal/msggateway/compressor.go @@ -17,7 +17,6 @@ package msggateway import ( "bytes" "compress/gzip" - "errors" "io" "sync" @@ -46,12 +45,15 @@ func NewGzipCompressor() *GzipCompressor { func (g *GzipCompressor) Compress(rawData []byte) ([]byte, error) { gzipBuffer := bytes.Buffer{} gz := gzip.NewWriter(&gzipBuffer) + if _, err := gz.Write(rawData); err != nil { - return nil, errs.Wrap(err) + return nil, errs.Wrap(err, "GzipCompressor.Compress: writing to gzip writer failed") } + if err := gz.Close(); err != nil { - return nil, errs.Wrap(err) + return nil, errs.Wrap(err, "GzipCompressor.Compress: closing gzip writer failed") } + return gzipBuffer.Bytes(), nil } @@ -63,10 +65,10 @@ func (g *GzipCompressor) CompressWithPool(rawData []byte) ([]byte, error) { gz.Reset(&gzipBuffer) if _, err := gz.Write(rawData); err != nil { - return nil, errs.Wrap(err) + return nil, errs.Wrap(err, "GzipCompressor.CompressWithPool: error writing data") } if err := gz.Close(); err != nil { - return nil, errs.Wrap(err) + return nil, errs.Wrap(err, "GzipCompressor.CompressWithPool: error closing gzip writer") } return gzipBuffer.Bytes(), nil } @@ -75,32 +77,36 @@ func (g *GzipCompressor) DeCompress(compressedData []byte) ([]byte, error) { buff := bytes.NewBuffer(compressedData) reader, err := gzip.NewReader(buff) if err != nil { - return nil, errs.Wrap(err, "NewReader failed") + return nil, errs.Wrap(err, "GzipCompressor.DeCompress: NewReader creation failed") } - compressedData, err = io.ReadAll(reader) + decompressedData, err := io.ReadAll(reader) if err != nil { - return nil, errs.Wrap(err, "ReadAll failed") + return nil, errs.Wrap(err, "GzipCompressor.DeCompress: reading from gzip reader failed") } - _ = reader.Close() - return compressedData, nil + if err = reader.Close(); err != nil { + // Even if closing the reader fails, we've successfully read the data, + // so we return the decompressed data and an error indicating the close failure. + return decompressedData, errs.Wrap(err, "GzipCompressor.DeCompress: closing gzip reader failed") + } + return decompressedData, nil } func (g *GzipCompressor) DecompressWithPool(compressedData []byte) ([]byte, error) { reader := gzipReaderPool.Get().(*gzip.Reader) - if reader == nil { - return nil, errs.Wrap(errors.New("NewReader failed")) - } defer gzipReaderPool.Put(reader) err := reader.Reset(bytes.NewReader(compressedData)) if err != nil { - return nil, errs.Wrap(err, "NewReader failed") + return nil, errs.Wrap(err, "GzipCompressor.DecompressWithPool: resetting gzip reader failed") } - compressedData, err = io.ReadAll(reader) + decompressedData, err := io.ReadAll(reader) if err != nil { - return nil, errs.Wrap(err, "ReadAll failed") + return nil, errs.Wrap(err, "GzipCompressor.DecompressWithPool: reading from pooled gzip reader failed") + } + if err = reader.Close(); err != nil { + // Similar to DeCompress, return the data and error for close failure. + return decompressedData, errs.Wrap(err, "GzipCompressor.DecompressWithPool: closing pooled gzip reader failed") } - _ = reader.Close() - return compressedData, nil + return decompressedData, nil } diff --git a/internal/msggateway/compressor_test.go b/internal/msggateway/compressor_test.go index b1544f063..173c9bb20 100644 --- a/internal/msggateway/compressor_test.go +++ b/internal/msggateway/compressor_test.go @@ -37,10 +37,16 @@ func TestCompressDecompress(t *testing.T) { // compress dest, err := compressor.CompressWithPool(src) + if err != nil { + t.Log(err) + } assert.Equal(t, nil, err) // decompress res, err := compressor.DecompressWithPool(dest) + if err != nil { + t.Log(err) + } assert.Equal(t, nil, err) // check @@ -60,10 +66,16 @@ func TestCompressDecompressWithConcurrency(t *testing.T) { // compress dest, err := compressor.CompressWithPool(src) + if err != nil { + t.Log(err) + } assert.Equal(t, nil, err) // decompress res, err := compressor.DecompressWithPool(dest) + if err != nil { + t.Log(err) + } assert.Equal(t, nil, err) // check @@ -99,6 +111,7 @@ func BenchmarkDecompress(b *testing.B) { compressor := NewGzipCompressor() comdata, err := compressor.Compress(src) + assert.Equal(b, nil, err) for i := 0; i < b.N; i++ { diff --git a/internal/msggateway/encoder.go b/internal/msggateway/encoder.go index 69a899591..cd2c50d96 100644 --- a/internal/msggateway/encoder.go +++ b/internal/msggateway/encoder.go @@ -37,7 +37,7 @@ func (g *GobEncoder) Encode(data any) ([]byte, error) { enc := gob.NewEncoder(&buff) err := enc.Encode(data) if err != nil { - return nil, err + return nil, errs.Wrap(err, "GobEncoder.Encode failed") } return buff.Bytes(), nil } @@ -47,7 +47,7 @@ func (g *GobEncoder) Decode(encodeData []byte, decodeData any) error { dec := gob.NewDecoder(buff) err := dec.Decode(decodeData) if err != nil { - return errs.Wrap(err) + return errs.Wrap(err, "GobEncoder.Decode failed") } return nil } diff --git a/internal/msggateway/hub_server.go b/internal/msggateway/hub_server.go index ac73f7f6d..739c4232f 100644 --- a/internal/msggateway/hub_server.go +++ b/internal/msggateway/hub_server.go @@ -17,8 +17,6 @@ package msggateway import ( "context" - "google.golang.org/grpc" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/msggateway" "github.com/OpenIMSDK/tools/discoveryregistry" @@ -26,11 +24,11 @@ import ( "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/startrpc" + "google.golang.org/grpc" ) func (s *Server) InitServer(config *config.GlobalConfig, disCov discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error { diff --git a/internal/msggateway/init.go b/internal/msggateway/init.go index 1204b7d25..4efbb7cdf 100644 --- a/internal/msggateway/init.go +++ b/internal/msggateway/init.go @@ -23,14 +23,7 @@ import ( // RunWsAndServer run ws server. func RunWsAndServer(conf *config.GlobalConfig, rpcPort, wsPort, prometheusPort int) error { - fmt.Println( - "start rpc/msg_gateway server, port: ", - rpcPort, - wsPort, - prometheusPort, - ", OpenIM version: ", - config.Version, - ) + fmt.Println("start rpc/msg_gateway server, port: ", rpcPort, wsPort, prometheusPort, ", OpenIM version: ", config.Version) longServer, err := NewWsServer( conf, WithPort(wsPort), diff --git a/internal/msggateway/long_conn.go b/internal/msggateway/long_conn.go index a4251a50f..7dc79c834 100644 --- a/internal/msggateway/long_conn.go +++ b/internal/msggateway/long_conn.go @@ -15,9 +15,11 @@ package msggateway import ( + "errors" "net/http" "time" + "github.com/OpenIMSDK/tools/errs" "github.com/gorilla/websocket" ) @@ -72,7 +74,8 @@ func (d *GWebSocket) GenerateLongConn(w http.ResponseWriter, r *http.Request) er conn, err := upgrader.Upgrade(w, r, nil) if err != nil { - return err + // The upgrader.Upgrade method usually returns enough error messages to diagnose problems that may occur during the upgrade + return errs.Wrap(err, "GenerateLongConn: WebSocket upgrade failed") } d.conn = conn return nil @@ -96,7 +99,16 @@ func (d *GWebSocket) SetReadDeadline(timeout time.Duration) error { } func (d *GWebSocket) SetWriteDeadline(timeout time.Duration) error { - return d.conn.SetWriteDeadline(time.Now().Add(timeout)) + // TODO add error + if timeout <= 0 { + return errs.Wrap(errors.New("timeout must be greater than 0")) + } + + // TODO SetWriteDeadline Future add error handling + if err := d.conn.SetWriteDeadline(time.Now().Add(timeout)); err != nil { + return errs.Wrap(err, "GWebSocket.SetWriteDeadline failed") + } + return nil } func (d *GWebSocket) Dial(urlStr string, requestHeader http.Header) (*http.Response, error) { diff --git a/internal/msggateway/message_handler.go b/internal/msggateway/message_handler.go index e1368558d..208cd6bf7 100644 --- a/internal/msggateway/message_handler.go +++ b/internal/msggateway/message_handler.go @@ -19,17 +19,15 @@ import ( "github.com/openimsdk/open-im-server/v3/pkg/common/config" "sync" - "github.com/OpenIMSDK/protocol/push" - "github.com/OpenIMSDK/tools/discoveryregistry" - - "github.com/go-playground/validator/v10" - "google.golang.org/protobuf/proto" - "github.com/OpenIMSDK/protocol/msg" + "github.com/OpenIMSDK/protocol/push" "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/tools/discoveryregistry" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/utils" - + "github.com/go-playground/validator/v10" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + "google.golang.org/protobuf/proto" ) type Req struct { @@ -120,10 +118,10 @@ func NewGrpcHandler(validate *validator.Validate, client discoveryregistry.SvcDi func (g GrpcHandler) GetSeq(context context.Context, data *Req) ([]byte, error) { req := sdkws.GetMaxSeqReq{} if err := proto.Unmarshal(data.Data, &req); err != nil { - return nil, err + return nil, errs.Wrap(err, "GetSeq: error unmarshaling request") } if err := g.validate.Struct(&req); err != nil { - return nil, err + return nil, errs.Wrap(err, "GetSeq: validation failed") } resp, err := g.msgRpcClient.GetMaxSeq(context, &req) if err != nil { @@ -131,28 +129,37 @@ func (g GrpcHandler) GetSeq(context context.Context, data *Req) ([]byte, error) } c, err := proto.Marshal(resp) if err != nil { - return nil, err + return nil, errs.Wrap(err, "GetSeq: error marshaling response") } return c, nil } -func (g GrpcHandler) SendMessage(context context.Context, data *Req) ([]byte, error) { - msgData := sdkws.MsgData{} +// SendMessage handles the sending of messages through gRPC. It unmarshals the request data, +// validates the message, and then sends it using the message RPC client. +func (g GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]byte, error) { + // Unmarshal the message data from the request. + var msgData sdkws.MsgData if err := proto.Unmarshal(data.Data, &msgData); err != nil { - return nil, err + return nil, errs.Wrap(err, "error unmarshalling message data") } + + // Validate the message data structure. if err := g.validate.Struct(&msgData); err != nil { - return nil, err + return nil, errs.Wrap(err, "message data validation failed") } + req := msg.SendMsgReq{MsgData: &msgData} - resp, err := g.msgRpcClient.SendMsg(context, &req) + + resp, err := g.msgRpcClient.SendMsg(ctx, &req) if err != nil { return nil, err } + c, err := proto.Marshal(resp) if err != nil { - return nil, err + return nil, errs.Wrap(err, "error marshaling response") } + return c, nil } @@ -163,7 +170,7 @@ func (g GrpcHandler) SendSignalMessage(context context.Context, data *Req) ([]by } c, err := proto.Marshal(resp) if err != nil { - return nil, err + return nil, errs.Wrap(err, "error marshaling response") } return c, nil } @@ -171,10 +178,10 @@ func (g GrpcHandler) SendSignalMessage(context context.Context, data *Req) ([]by func (g GrpcHandler) PullMessageBySeqList(context context.Context, data *Req) ([]byte, error) { req := sdkws.PullMessageBySeqsReq{} if err := proto.Unmarshal(data.Data, &req); err != nil { - return nil, err + return nil, errs.Wrap(err, "error unmarshaling request") } if err := g.validate.Struct(data); err != nil { - return nil, err + return nil, errs.Wrap(err, "validation failed") } resp, err := g.msgRpcClient.PullMessageBySeqList(context, &req) if err != nil { @@ -182,7 +189,7 @@ func (g GrpcHandler) PullMessageBySeqList(context context.Context, data *Req) ([ } c, err := proto.Marshal(resp) if err != nil { - return nil, err + return nil, errs.Wrap(err, "error marshaling response") } return c, nil } @@ -190,7 +197,7 @@ func (g GrpcHandler) PullMessageBySeqList(context context.Context, data *Req) ([ func (g GrpcHandler) UserLogout(context context.Context, data *Req) ([]byte, error) { req := push.DelUserPushTokenReq{} if err := proto.Unmarshal(data.Data, &req); err != nil { - return nil, err + return nil, errs.Wrap(err, "error unmarshaling request") } resp, err := g.pushClient.DelUserPushToken(context, &req) if err != nil { @@ -198,7 +205,7 @@ func (g GrpcHandler) UserLogout(context context.Context, data *Req) ([]byte, err } c, err := proto.Marshal(resp) if err != nil { - return nil, err + return nil, errs.Wrap(err, "error marshaling response") } return c, nil } @@ -206,10 +213,10 @@ func (g GrpcHandler) UserLogout(context context.Context, data *Req) ([]byte, err func (g GrpcHandler) SetUserDeviceBackground(_ context.Context, data *Req) ([]byte, bool, error) { req := sdkws.SetAppBackgroundStatusReq{} if err := proto.Unmarshal(data.Data, &req); err != nil { - return nil, false, err + return nil, false, errs.Wrap(err, "error unmarshaling request") } if err := g.validate.Struct(data); err != nil { - return nil, false, err + return nil, false, errs.Wrap(err, "validation failed") } return nil, req.IsBackground, nil } diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go index d2ca88b14..f5838c703 100644 --- a/internal/msggateway/n_ws_server.go +++ b/internal/msggateway/n_ws_server.go @@ -25,24 +25,21 @@ import ( "sync/atomic" "time" - "github.com/OpenIMSDK/tools/apiresp" - - "github.com/go-playground/validator/v10" - "github.com/redis/go-redis/v9" - "golang.org/x/sync/errgroup" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/msggateway" + "github.com/OpenIMSDK/tools/apiresp" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/utils" - + "github.com/go-playground/validator/v10" "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + "github.com/redis/go-redis/v9" + "golang.org/x/sync/errgroup" ) type LongConnServer interface { @@ -89,6 +86,7 @@ type WsServer struct { Encoder MessageHandler } + type kickHandler struct { clientOK bool oldClients []*Client @@ -130,7 +128,9 @@ func (ws *WsServer) UnRegister(c *Client) { } func (ws *WsServer) Validate(s any) error { - //?question? + if s == nil { + return errs.Wrap(errors.New("input cannot be nil")) + } return nil } @@ -278,7 +278,7 @@ func (ws *WsServer) registerClient(client *Client) { log.ZDebug(client.ctx, "user exist", "userID", client.UserID, "platformID", client.PlatformID) if clientOK { ws.clients.Set(client.UserID, client) - // 已经有同平台的连接存在 + // There is already a connection to the platform log.ZInfo(client.ctx, "repeat login", "userID", client.UserID, "platformID", client.PlatformID, "old remote addr", getRemoteAdders(oldClients)) ws.onlineUserConnNum.Add(1) } else { diff --git a/internal/msggateway/options.go b/internal/msggateway/options.go index 6513ac5dc..b65f8e36c 100644 --- a/internal/msggateway/options.go +++ b/internal/msggateway/options.go @@ -19,15 +19,15 @@ import "time" type ( Option func(opt *configs) configs struct { - // 长连接监听端口 + // Long connection listening port port int - // 长连接允许最大链接数 + // Maximum number of connections allowed for long connection maxConnNum int64 - // 连接握手超时时间 + // Connection handshake timeout handshakeTimeout time.Duration - // 允许消息最大长度 + // Maximum length allowed for messages messageMaxMsgLength int - // websocket write buffer, default: 4096, 4kb. + // Websocket write buffer, default: 4096, 4kb. writeBufferSize int } ) diff --git a/internal/msgtransfer/init.go b/internal/msgtransfer/init.go index 3f5df905a..5e9e80663 100644 --- a/internal/msgtransfer/init.go +++ b/internal/msgtransfer/init.go @@ -18,23 +18,13 @@ import ( "context" "errors" "fmt" - - "github.com/OpenIMSDK/tools/errs" - - util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" - "net/http" "os" "os/signal" "syscall" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/mw" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/collectors" - "github.com/prometheus/client_golang/prometheus/promhttp" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" @@ -42,14 +32,25 @@ import ( kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister" "github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/collectors" + "github.com/prometheus/client_golang/prometheus/promhttp" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) type MsgTransfer struct { - historyCH *OnlineHistoryRedisConsumerHandler // 这个消费者聚合消息, 订阅的topic:ws2ms_chat, 修改通知发往msg_to_modify topic, 消息存入redis后Incr Redis, 再发消息到ms2pschat topic推送, 发消息到msg_to_mongo topic持久化 - historyMongoCH *OnlineHistoryMongoConsumerHandler // mongoDB批量插入, 成功后删除redis中消息,以及处理删除通知消息删除的 订阅的topic: msg_to_mongo - ctx context.Context - cancel context.CancelFunc - config *config.GlobalConfig + // This consumer aggregated messages, subscribed to the topic:ws2ms_chat, + // the modification notification is sent to msg_to_modify topic, the message is stored in redis, Incr Redis, + // and then the message is sent to ms2pschat topic for push, and the message is sent to msg_to_mongo topic for persistence + historyCH *OnlineHistoryRedisConsumerHandler + historyMongoCH *OnlineHistoryMongoConsumerHandler + // mongoDB batch insert, delete messages in redis after success, + // and handle the deletion notification message deleted subscriptions topic: msg_to_mongo + ctx context.Context + cancel context.CancelFunc + config *config.GlobalConfig } func StartTransfer(config *config.GlobalConfig, prometheusPort int) error { @@ -74,6 +75,7 @@ func StartTransfer(config *config.GlobalConfig, prometheusPort int) error { if err := client.CreateRpcRootNodes(config.GetServiceNames()); err != nil { return err } + client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin"))) msgModel := cache.NewMsgCacheModel(rdb, config) msgDocModel := unrelation.NewMsgMongoDriver(mongo.GetDatabase(config.Mongo.Database)) diff --git a/internal/msgtransfer/online_history_msg_handler.go b/internal/msgtransfer/online_history_msg_handler.go index 96d27d908..b81bd12b8 100644 --- a/internal/msgtransfer/online_history_msg_handler.go +++ b/internal/msgtransfer/online_history_msg_handler.go @@ -22,24 +22,20 @@ import ( "sync/atomic" "time" - "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" - - "github.com/OpenIMSDK/tools/errs" - "github.com/IBM/sarama" - "github.com/go-redis/redis" - "google.golang.org/protobuf/proto" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" - + "github.com/go-redis/redis" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" "github.com/openimsdk/open-im-server/v3/pkg/common/kafka" + "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + "google.golang.org/protobuf/proto" ) const ( @@ -174,21 +170,13 @@ func (och *OnlineHistoryRedisConsumerHandler) Run(channelID int) { notStorageNotificationList, ) if err := och.msgDatabase.MsgToModifyMQ(ctx, msgChannelValue.uniqueKey, conversationIDNotification, modifyMsgList); err != nil { - log.ZError( - ctx, - "msg to modify mq error", - err, - "uniqueKey", - msgChannelValue.uniqueKey, - "modifyMsgList", - modifyMsgList, - ) + log.ZError(ctx, "msg to modify mq error", err, "uniqueKey", msgChannelValue.uniqueKey, "modifyMsgList", modifyMsgList) } } } } -// 获取消息/通知 存储的消息列表, 不存储并且推送的消息列表,. +// Get messages/notifications stored message list, not stored and pushed message list. func (och *OnlineHistoryRedisConsumerHandler) getPushStorageMsgList( totalMsgs []*ContextMsg, ) (storageMsgList, notStorageMsgList, storageNotificatoinList, notStorageNotificationList, modifyMsgList []*sdkws.MsgData) { @@ -209,7 +197,7 @@ func (och *OnlineHistoryRedisConsumerHandler) getPushStorageMsgList( // clone msg from notificationMsg if options.IsSendMsg() { msg := proto.Clone(v.message).(*sdkws.MsgData) - // 消息 + // message if v.message.Options != nil { msg.Options = msgprocessor.NewMsgOptions() } @@ -284,7 +272,8 @@ func (och *OnlineHistoryRedisConsumerHandler) toPushTopic( msgs []*sdkws.MsgData, ) { for _, v := range msgs { - och.msgDatabase.MsgToPushMQ(ctx, key, conversationID, v) + och.msgDatabase.MsgToPushMQ(ctx, key, conversationID, v) // nolint: errcheck + } } diff --git a/internal/msgtransfer/online_msg_to_mongo_handler.go b/internal/msgtransfer/online_msg_to_mongo_handler.go index 80b4b200b..045f82220 100644 --- a/internal/msgtransfer/online_msg_to_mongo_handler.go +++ b/internal/msgtransfer/online_msg_to_mongo_handler.go @@ -18,15 +18,13 @@ import ( "context" "github.com/IBM/sarama" - "google.golang.org/protobuf/proto" - pbmsg "github.com/OpenIMSDK/protocol/msg" "github.com/OpenIMSDK/tools/log" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" kfk "github.com/openimsdk/open-im-server/v3/pkg/common/kafka" "github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" + "google.golang.org/protobuf/proto" ) type OnlineHistoryMongoConsumerHandler struct { diff --git a/internal/push/callback.go b/internal/push/callback.go index 4debee19e..6415d63d6 100644 --- a/internal/push/callback.go +++ b/internal/push/callback.go @@ -21,7 +21,6 @@ import ( "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/http" @@ -56,10 +55,12 @@ func callbackOfflinePush( AtUserIDs: msg.AtUserIDList, Content: GetContent(msg), } + resp := &callbackstruct.CallbackBeforePushResp{} if err := http.CallBackPostReturn(ctx, config.Callback.CallbackUrl, req, resp, config.Callback.CallbackOfflinePush); err != nil { return err } + if len(resp.UserIDs) != 0 { *offlinePushUserIDs = resp.UserIDs } diff --git a/internal/push/offlinepush/fcm/push.go b/internal/push/offlinepush/fcm/push.go index 4f82765b5..977254462 100644 --- a/internal/push/offlinepush/fcm/push.go +++ b/internal/push/offlinepush/fcm/push.go @@ -39,6 +39,8 @@ type Fcm struct { cache cache.MsgModel } +// NewClient initializes a new FCM client using the Firebase Admin SDK. +// It requires the FCM service account credentials file located within the project's configuration directory. func NewClient(globalConfig *config.GlobalConfig, cache cache.MsgModel) *Fcm { projectRoot := config.GetProjectRoot() credentialsFilePath := filepath.Join(projectRoot, "config", globalConfig.Push.Fcm.ServiceAccount) @@ -47,12 +49,12 @@ func NewClient(globalConfig *config.GlobalConfig, cache cache.MsgModel) *Fcm { if err != nil { return nil } - ctx := context.Background() fcmMsgClient, err := fcmApp.Messaging(ctx) if err != nil { return nil } + return &Fcm{fcmMsgCli: fcmMsgClient, cache: cache} } @@ -125,7 +127,6 @@ func (f *Fcm) Push(ctx context.Context, userIDs []string, title, content string, response, err := f.fcmMsgCli.SendAll(ctx, messages) if err != nil { Fail = Fail + messageCount - // log.Info(operationID, "some token push err", err.Error(), messageCount) } else { Success = Success + response.SuccessCount Fail = Fail + response.FailureCount diff --git a/internal/push/offlinepush/getui/push.go b/internal/push/offlinepush/getui/push.go index 6d40b2cb3..67f6292db 100644 --- a/internal/push/offlinepush/getui/push.go +++ b/internal/push/offlinepush/getui/push.go @@ -23,17 +23,15 @@ import ( "sync" "time" - "github.com/redis/go-redis/v9" - "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils/splitter" - "github.com/openimsdk/open-im-server/v3/internal/push/offlinepush" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" http2 "github.com/openimsdk/open-im-server/v3/pkg/common/http" + "github.com/redis/go-redis/v9" ) var ( diff --git a/internal/push/push_handler.go b/internal/push/push_handler.go index 0f2c3606d..0e68e76b3 100644 --- a/internal/push/push_handler.go +++ b/internal/push/push_handler.go @@ -18,16 +18,14 @@ import ( "context" "github.com/IBM/sarama" - "google.golang.org/protobuf/proto" - "github.com/OpenIMSDK/protocol/constant" pbchat "github.com/OpenIMSDK/protocol/msg" pbpush "github.com/OpenIMSDK/protocol/push" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" kfk "github.com/openimsdk/open-im-server/v3/pkg/common/kafka" + "google.golang.org/protobuf/proto" ) type ConsumerHandler struct { diff --git a/internal/push/push_rpc_server.go b/internal/push/push_rpc_server.go index eb11f55be..ed2a0b1ef 100644 --- a/internal/push/push_rpc_server.go +++ b/internal/push/push_rpc_server.go @@ -18,19 +18,16 @@ import ( "context" "github.com/openimsdk/open-im-server/v3/pkg/common/config" - "github.com/OpenIMSDK/tools/utils" - - "google.golang.org/grpc" - "github.com/OpenIMSDK/protocol/constant" pbpush "github.com/OpenIMSDK/protocol/push" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/log" - + "github.com/OpenIMSDK/tools/utils" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" "github.com/openimsdk/open-im-server/v3/pkg/common/db/localcache" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + "google.golang.org/grpc" ) type pushServer struct { diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go index 7c26dc54b..49bce70ab 100644 --- a/internal/push/push_to_client.go +++ b/internal/push/push_to_client.go @@ -20,10 +20,6 @@ import ( "errors" "sync" - "google.golang.org/grpc" - - "golang.org/x/sync/errgroup" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/conversation" "github.com/OpenIMSDK/protocol/msggateway" @@ -32,7 +28,6 @@ import ( "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/internal/push/offlinepush" "github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/dummy" "github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/fcm" @@ -45,6 +40,8 @@ import ( "github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc" ) type Pusher struct { @@ -231,7 +228,8 @@ func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws }(groupID, kickedUsers) pushToUserIDs = append(pushToUserIDs, kickedUsers...) case constant.GroupDismissedNotification: - if msgprocessor.IsNotification(msgprocessor.GetConversationIDByMsg(msg)) { // 消息先到,通知后到 + // Messages arrive first, notifications arrive later + if msgprocessor.IsNotification(msgprocessor.GetConversationIDByMsg(msg)) { var tips sdkws.GroupDismissedTips if p.UnmarshalNotificationElem(msg.Content, &tips) != nil { return err diff --git a/internal/rpc/auth/auth.go b/internal/rpc/auth/auth.go index d8dadedbf..eb1e2f68a 100644 --- a/internal/rpc/auth/auth.go +++ b/internal/rpc/auth/auth.go @@ -17,10 +17,6 @@ package auth import ( "context" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" - - "google.golang.org/grpc" - pbauth "github.com/OpenIMSDK/protocol/auth" "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/msggateway" @@ -29,12 +25,13 @@ import ( "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/tokenverify" - + "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" "github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + "google.golang.org/grpc" ) type authServer struct { diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go index 364d198a6..cc08de298 100644 --- a/internal/rpc/conversation/conversaion.go +++ b/internal/rpc/conversation/conversaion.go @@ -20,28 +20,23 @@ import ( "github.com/openimsdk/open-im-server/v3/pkg/common/config" "sort" - "github.com/OpenIMSDK/protocol/sdkws" - - "github.com/OpenIMSDK/tools/tx" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" - - "google.golang.org/grpc" - "github.com/OpenIMSDK/protocol/constant" pbconversation "github.com/OpenIMSDK/protocol/conversation" + "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" + "github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/convert" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification" + "google.golang.org/grpc" ) type conversationServer struct { @@ -313,7 +308,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, unequal++ } } - if err := c.conversationDatabase.SetUsersConversationFiledTx(ctx, req.UserIDs, &conversation, m); err != nil { + if err := c.conversationDatabase.SetUsersConversationFieldTx(ctx, req.UserIDs, &conversation, m); err != nil { return nil, err } if unequal > 0 { @@ -324,7 +319,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, return &pbconversation.SetConversationsResp{}, nil } -// 获取超级大群开启免打扰的用户ID. +// Get user IDs with "Do Not Disturb" enabled in super large groups. func (c *conversationServer) GetRecvMsgNotNotifyUserIDs(ctx context.Context, req *pbconversation.GetRecvMsgNotNotifyUserIDsReq) (*pbconversation.GetRecvMsgNotNotifyUserIDsResp, error) { //userIDs, err := c.conversationDatabase.FindRecvMsgNotNotifyUserIDs(ctx, req.GroupID) //if err != nil { @@ -381,7 +376,7 @@ func (c *conversationServer) CreateGroupChatConversations(ctx context.Context, r } func (c *conversationServer) SetConversationMaxSeq(ctx context.Context, req *pbconversation.SetConversationMaxSeqReq) (*pbconversation.SetConversationMaxSeqResp, error) { - if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, req.OwnerUserID, req.ConversationID, + if err := c.conversationDatabase.UpdateUsersConversationField(ctx, req.OwnerUserID, req.ConversationID, map[string]any{"max_seq": req.MaxSeq}); err != nil { return nil, err } diff --git a/internal/rpc/friend/black.go b/internal/rpc/friend/black.go index e18e27da3..64c63eb73 100644 --- a/internal/rpc/friend/black.go +++ b/internal/rpc/friend/black.go @@ -18,17 +18,15 @@ import ( "context" "time" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" - pbfriend "github.com/OpenIMSDK/protocol/friend" "github.com/OpenIMSDK/tools/mcontext" - + "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/common/convert" "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) func (s *friendServer) GetPaginationBlacks(ctx context.Context, req *pbfriend.GetPaginationBlacksReq) (resp *pbfriend.GetPaginationBlacksResp, err error) { - if accessErr := s.userRpcClient.Access(ctx, req.UserID); accessErr != nil { + if err := s.userRpcClient.Access(ctx, req.UserID); err != nil { return nil, err } total, blacks, err := s.blackDatabase.FindOwnerBlacks(ctx, req.UserID, req.Pagination) diff --git a/internal/rpc/friend/callback.go b/internal/rpc/friend/callback.go index 8db5c5141..78d4fc926 100644 --- a/internal/rpc/friend/callback.go +++ b/internal/rpc/friend/callback.go @@ -19,7 +19,6 @@ import ( pbfriend "github.com/OpenIMSDK/protocol/friend" "github.com/OpenIMSDK/tools/utils" - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/http" diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index 16b9119e7..ffdeee98f 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -118,7 +118,7 @@ func Start(config *config.GlobalConfig, client registry.SvcDiscoveryRegistry, se // ok. func (s *friendServer) ApplyToAddFriend(ctx context.Context, req *pbfriend.ApplyToAddFriendReq) (resp *pbfriend.ApplyToAddFriendResp, err error) { resp = &pbfriend.ApplyToAddFriendResp{} - if accessErr := authverify.CheckAccessV3(ctx, req.FromUserID, s.config); accessErr != nil { + if err := authverify.CheckAccessV3(ctx, req.FromUserID,s.config); err != nil { return nil, err } if req.ToUserID == req.FromUserID { @@ -127,7 +127,7 @@ func (s *friendServer) ApplyToAddFriend(ctx context.Context, req *pbfriend.Apply if err = CallbackBeforeAddFriend(ctx, s.config, req); err != nil && err != errs.ErrCallbackContinue { return nil, err } - if _, getUserInfoErr := s.userRpcClient.GetUsersInfoMap(ctx, []string{req.ToUserID, req.FromUserID}); getUserInfoErr != nil { + if _, err := s.userRpcClient.GetUsersInfoMap(ctx, []string{req.ToUserID, req.FromUserID}); err != nil { return nil, err } in1, in2, err := s.friendDatabase.CheckIn(ctx, req.FromUserID, req.ToUserID) @@ -141,7 +141,7 @@ func (s *friendServer) ApplyToAddFriend(ctx context.Context, req *pbfriend.Apply return nil, err } s.notificationSender.FriendApplicationAddNotification(ctx, req) - if err = CallbackAfterAddFriend(ctx, s.config, req); err != nil && err != errs.ErrCallbackContinue { + if err = CallbackAfterAddFriend(ctx,s.config ,req); err != nil && err != errs.ErrCallbackContinue { return nil, err } return resp, nil @@ -222,7 +222,7 @@ func (s *friendServer) RespondFriendApply(ctx context.Context, req *pbfriend.Res func (s *friendServer) DeleteFriend(ctx context.Context, req *pbfriend.DeleteFriendReq) (resp *pbfriend.DeleteFriendResp, err error) { defer log.ZInfo(ctx, utils.GetFuncName()+" Return") resp = &pbfriend.DeleteFriendResp{} - if accessErr := s.userRpcClient.Access(ctx, req.OwnerUserID); accessErr != nil { + if err := s.userRpcClient.Access(ctx, req.OwnerUserID); err != nil { return nil, err } _, err = s.friendDatabase.FindFriendsWithError(ctx, req.OwnerUserID, []string{req.FriendUserID}) @@ -247,7 +247,7 @@ func (s *friendServer) SetFriendRemark(ctx context.Context, req *pbfriend.SetFri return nil, err } resp = &pbfriend.SetFriendRemarkResp{} - if accessErr := s.userRpcClient.Access(ctx, req.OwnerUserID); accessErr != nil { + if err := s.userRpcClient.Access(ctx, req.OwnerUserID); err != nil { return nil, err } _, err = s.friendDatabase.FindFriendsWithError(ctx, req.OwnerUserID, []string{req.FriendUserID}) @@ -281,6 +281,7 @@ func (s *friendServer) GetDesignatedFriends(ctx context.Context, req *pbfriend.G return resp, nil } +// Get the list of friend requests sent out proactively. func (s *friendServer) GetDesignatedFriendsApply(ctx context.Context, req *pbfriend.GetDesignatedFriendsApplyReq) (resp *pbfriend.GetDesignatedFriendsApplyResp, err error) { friendRequests, err := s.friendDatabase.FindBothFriendRequests(ctx, req.FromUserID, req.ToUserID) @@ -295,10 +296,10 @@ func (s *friendServer) GetDesignatedFriendsApply(ctx context.Context, return resp, nil } -// ok 获取接收到的好友申请(即别人主动申请的). +// Get received friend requests (i.e., those initiated by others). func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context, req *pbfriend.GetPaginationFriendsApplyToReq) (resp *pbfriend.GetPaginationFriendsApplyToResp, err error) { defer log.ZInfo(ctx, utils.GetFuncName()+" Return") - if accessErr := s.userRpcClient.Access(ctx, req.UserID); accessErr != nil { + if err := s.userRpcClient.Access(ctx, req.UserID); err != nil { return nil, err } total, friendRequests, err := s.friendDatabase.PageFriendRequestToMe(ctx, req.UserID, req.Pagination) @@ -314,11 +315,10 @@ func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context, req *pbf return resp, nil } -// ok 获取主动发出去的好友申请列表. func (s *friendServer) GetPaginationFriendsApplyFrom(ctx context.Context, req *pbfriend.GetPaginationFriendsApplyFromReq) (resp *pbfriend.GetPaginationFriendsApplyFromResp, err error) { defer log.ZInfo(ctx, utils.GetFuncName()+" Return") resp = &pbfriend.GetPaginationFriendsApplyFromResp{} - if accessErr := s.userRpcClient.Access(ctx, req.UserID); accessErr != nil { + if err := s.userRpcClient.Access(ctx, req.UserID); err != nil { return nil, err } total, friendRequests, err := s.friendDatabase.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination) @@ -346,7 +346,7 @@ func (s *friendServer) IsFriend(ctx context.Context, req *pbfriend.IsFriendReq) func (s *friendServer) GetPaginationFriends(ctx context.Context, req *pbfriend.GetPaginationFriendsReq) (resp *pbfriend.GetPaginationFriendsResp, err error) { defer log.ZInfo(ctx, utils.GetFuncName()+" Return") - if accessErr := s.userRpcClient.Access(ctx, req.UserID); accessErr != nil { + if err := s.userRpcClient.Access(ctx, req.UserID); err != nil { return nil, err } total, friends, err := s.friendDatabase.PageOwnerFriends(ctx, req.UserID, req.Pagination) @@ -364,7 +364,7 @@ func (s *friendServer) GetPaginationFriends(ctx context.Context, req *pbfriend.G func (s *friendServer) GetFriendIDs(ctx context.Context, req *pbfriend.GetFriendIDsReq) (resp *pbfriend.GetFriendIDsResp, err error) { defer log.ZInfo(ctx, utils.GetFuncName()+" Return") - if accessErr := s.userRpcClient.Access(ctx, req.UserID); accessErr != nil { + if err := s.userRpcClient.Access(ctx, req.UserID); err != nil { return nil, err } resp = &pbfriend.GetFriendIDsResp{} diff --git a/internal/rpc/group/cache.go b/internal/rpc/group/cache.go index fc387736d..54b60c554 100644 --- a/internal/rpc/group/cache.go +++ b/internal/rpc/group/cache.go @@ -18,7 +18,6 @@ import ( "context" pbgroup "github.com/OpenIMSDK/protocol/group" - "github.com/openimsdk/open-im-server/v3/pkg/common/convert" ) diff --git a/internal/rpc/group/callback.go b/internal/rpc/group/callback.go index 18b484a3e..e82177dde 100644 --- a/internal/rpc/group/callback.go +++ b/internal/rpc/group/callback.go @@ -18,16 +18,13 @@ import ( "context" "time" - "github.com/OpenIMSDK/tools/log" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/group" + pbgroup "github.com/OpenIMSDK/protocol/group" "github.com/OpenIMSDK/protocol/wrapperspb" + "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" - - pbgroup "github.com/OpenIMSDK/protocol/group" - "github.com/openimsdk/open-im-server/v3/pkg/apistruct" "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/openimsdk/open-im-server/v3/pkg/common/config" diff --git a/internal/rpc/group/convert.go b/internal/rpc/group/convert.go index 2ee7f5056..ab4d3a2a1 100644 --- a/internal/rpc/group/convert.go +++ b/internal/rpc/group/convert.go @@ -16,7 +16,6 @@ package group import ( "github.com/OpenIMSDK/protocol/sdkws" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) diff --git a/internal/rpc/group/db_map.go b/internal/rpc/group/db_map.go index 07084873c..e4c18bb17 100644 --- a/internal/rpc/group/db_map.go +++ b/internal/rpc/group/db_map.go @@ -18,10 +18,9 @@ import ( "context" "time" - "github.com/OpenIMSDK/tools/mcontext" - pbgroup "github.com/OpenIMSDK/protocol/group" "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/tools/mcontext" ) func UpdateGroupInfoMap(ctx context.Context, group *sdkws.GroupInfoForSet) map[string]any { diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index 8f94b71b2..325c1edce 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -24,40 +24,31 @@ import ( "strings" "time" - "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" - - pbconversation "github.com/OpenIMSDK/protocol/conversation" - "github.com/OpenIMSDK/protocol/wrapperspb" - "github.com/OpenIMSDK/tools/tx" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/grouphash" - - "github.com/openimsdk/open-im-server/v3/pkg/authverify" - "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" - - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification" - - "github.com/OpenIMSDK/tools/mw/specialerror" - - "github.com/openimsdk/open-im-server/v3/pkg/common/convert" - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" - - "google.golang.org/grpc" - "github.com/OpenIMSDK/protocol/constant" + pbconversation "github.com/OpenIMSDK/protocol/conversation" pbgroup "github.com/OpenIMSDK/protocol/group" "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/protocol/wrapperspb" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" + "github.com/OpenIMSDK/tools/mw/specialerror" + "github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/tools/utils" - + "github.com/openimsdk/open-im-server/v3/pkg/authverify" + "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" + "github.com/openimsdk/open-im-server/v3/pkg/common/convert" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" + "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" + "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/grouphash" + "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification" + "google.golang.org/grpc" ) func Start(config *config.GlobalConfig, client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error { @@ -540,7 +531,7 @@ func (s *groupServer) KickGroupMember(ctx context.Context, req *pbgroup.KickGrou if err != nil { return nil, err } - if populateErr := s.PopulateGroupMember(ctx, members...); populateErr != nil { + if err := s.PopulateGroupMember(ctx, members...); err != nil { return nil, err } memberMap := make(map[string]*relationtb.GroupMemberModel) @@ -767,11 +758,11 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup } var inGroup bool if _, takeErr := s.db.TakeGroupMember(ctx, req.GroupID, req.FromUserID); takeErr == nil { - inGroup = true // 已经在群里了 + inGroup = true // Already in group } else if !s.IsNotFound(err) { return nil, err } - if _, getInfoErr := s.User.GetPublicUserInfo(ctx, req.FromUserID); getInfoErr != nil { + if _, err := s.User.GetPublicUserInfo(ctx, req.FromUserID); err != nil { return nil, err } var member *relationtb.GroupMemberModel @@ -858,14 +849,14 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq) JoinTime: time.Now(), MuteEndTime: time.UnixMilli(0), } - if callbackErr := CallbackBeforeMemberJoinGroup(ctx, s.config, groupMember, group.Ex); callbackErr != nil { + if err := CallbackBeforeMemberJoinGroup(ctx, s.config, groupMember, group.Ex); err != nil { return nil, err } - if createErr := s.db.CreateGroup(ctx, nil, []*relationtb.GroupMemberModel{groupMember}); createErr != nil { + if err := s.db.CreateGroup(ctx, nil, []*relationtb.GroupMemberModel{groupMember}); err != nil { return nil, err } - if createErr := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, []string{req.InviterUserID}); createErr != nil { + if err := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, []string{req.InviterUserID}); err != nil { return nil, err } s.Notification.MemberEnterNotification(ctx, req.GroupID, req.InviterUserID) @@ -906,7 +897,7 @@ func (s *groupServer) QuitGroup(ctx context.Context, req *pbgroup.QuitGroupReq) if member.RoleLevel == constant.GroupOwner { return nil, errs.ErrNoPermission.Wrap("group owner can't quit") } - if populateErr := s.PopulateGroupMember(ctx, member); populateErr != nil { + if err := s.PopulateGroupMember(ctx, member); err != nil { return nil, err } err = s.db.DeleteGroupMember(ctx, req.GroupID, []string{req.UserID}) @@ -968,14 +959,14 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf if err != nil { return nil, err } - if populateErr := s.PopulateGroupMember(ctx, owner); populateErr != nil { + if err := s.PopulateGroupMember(ctx, owner); err != nil { return nil, err } update := UpdateGroupInfoMap(ctx, req.GroupInfoForSet) if len(update) == 0 { return resp, nil } - if updateErr := s.db.UpdateGroup(ctx, group.GroupID, update); updateErr != nil { + if err := s.db.UpdateGroup(ctx, group.GroupID, update); err != nil { return nil, err } group, err = s.db.TakeGroup(ctx, req.GroupInfoForSet.GroupID) @@ -1169,7 +1160,7 @@ func (s *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou if err != nil { return nil, err } - if populateErr := s.PopulateGroupMember(ctx, owners...); populateErr != nil { + if err := s.PopulateGroupMember(ctx, owners...); err != nil { return nil, err } ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string { @@ -1201,7 +1192,7 @@ func (s *groupServer) DismissGroup(ctx context.Context, req *pbgroup.DismissGrou return nil, errs.ErrNoPermission.Wrap("not group owner") } } - if populateErr := s.PopulateGroupMember(ctx, owner); populateErr != nil { + if err := s.PopulateGroupMember(ctx, owner); err != nil { return nil, err } group, err := s.db.TakeGroup(ctx, req.GroupID) @@ -1211,7 +1202,7 @@ func (s *groupServer) DismissGroup(ctx context.Context, req *pbgroup.DismissGrou if !req.DeleteMember && group.Status == constant.GroupStatusDismissed { return nil, errs.ErrDismissedAlready.Wrap("group status is dismissed") } - if dismissErr := s.db.DismissGroup(ctx, req.GroupID, req.DeleteMember); dismissErr != nil { + if err := s.db.DismissGroup(ctx, req.GroupID, req.DeleteMember); err != nil { return nil, err } if !req.DeleteMember { @@ -1567,7 +1558,7 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req * if err != nil { return nil, err } - if populateErr := s.PopulateGroupMember(ctx, owners...); populateErr != nil { + if err := s.PopulateGroupMember(ctx, owners...); err != nil { return nil, err } ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string { diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go index bcb2b81c8..f16fdc62f 100644 --- a/internal/rpc/msg/as_read.go +++ b/internal/rpc/msg/as_read.go @@ -17,17 +17,14 @@ package msg import ( "context" - utils2 "github.com/OpenIMSDK/tools/utils" - - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" - - "github.com/redis/go-redis/v9" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/msg" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" + utils2 "github.com/OpenIMSDK/tools/utils" + cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" + "github.com/redis/go-redis/v9" ) func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *msg.GetConversationsHasReadAndMaxSeqReq) (resp *msg.GetConversationsHasReadAndMaxSeqResp, err error) { @@ -82,7 +79,7 @@ func (m *msgServer) SetConversationHasReadSeq( if req.HasReadSeq > maxSeq { return nil, errs.ErrArgs.Wrap("hasReadSeq must not be bigger than maxSeq") } - if setErr := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); setErr != nil { + if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil { return nil, err } if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID, diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go index d5e197ca2..536402bf9 100644 --- a/internal/rpc/msg/callback.go +++ b/internal/rpc/msg/callback.go @@ -17,19 +17,16 @@ package msg import ( "context" - "github.com/OpenIMSDK/protocol/sdkws" - "google.golang.org/protobuf/proto" - "github.com/OpenIMSDK/protocol/constant" pbchat "github.com/OpenIMSDK/protocol/msg" + "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/http" + "google.golang.org/protobuf/proto" ) func toCommonCallback(ctx context.Context, msg *pbchat.SendMsgReq, command string) cbapi.CommonCallbackReq { diff --git a/internal/rpc/msg/delete.go b/internal/rpc/msg/delete.go index 199028614..14e24d23e 100644 --- a/internal/rpc/msg/delete.go +++ b/internal/rpc/msg/delete.go @@ -17,14 +17,13 @@ package msg import ( "context" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/conversation" "github.com/OpenIMSDK/protocol/msg" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/open-im-server/v3/pkg/authverify" ) func (m *msgServer) getMinSeqs(maxSeqs map[string]int64) map[string]int64 { diff --git a/internal/rpc/msg/message_interceptor.go b/internal/rpc/msg/message_interceptor.go index d7421215d..97eac613d 100644 --- a/internal/rpc/msg/message_interceptor.go +++ b/internal/rpc/msg/message_interceptor.go @@ -21,7 +21,6 @@ import ( "github.com/OpenIMSDK/protocol/msg" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/errs" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" ) diff --git a/internal/rpc/msg/revoke.go b/internal/rpc/msg/revoke.go index 31a442d57..4f844369f 100644 --- a/internal/rpc/msg/revoke.go +++ b/internal/rpc/msg/revoke.go @@ -67,7 +67,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg. if !authverify.IsAppManagerUid(ctx, m.config) { switch msgs[0].SessionType { case constant.SingleChatType: - if accessErr := authverify.CheckAccessV3(ctx, msgs[0].SendID, m.config); accessErr != nil { + if err := authverify.CheckAccessV3(ctx, msgs[0].SendID, m.config); err != nil { return nil, err } role = user.AppMangerLevel @@ -132,7 +132,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg. } else { recvID = msgs[0].RecvID } - if notificationErr := m.notificationSender.NotificationWithSesstionType(ctx, req.UserID, recvID, constant.MsgRevokeNotification, msgs[0].SessionType, &tips); notificationErr != nil { + if err := m.notificationSender.NotificationWithSesstionType(ctx, req.UserID, recvID, constant.MsgRevokeNotification, msgs[0].SessionType, &tips); err != nil { return nil, err } if err = CallbackAfterRevokeMsg(ctx, m.config, req); err != nil { diff --git a/internal/rpc/msg/send.go b/internal/rpc/msg/send.go index 9d1672d58..4bac4d1e0 100644 --- a/internal/rpc/msg/send.go +++ b/internal/rpc/msg/send.go @@ -66,7 +66,7 @@ func (m *msgServer) sendMsgSuperGroupChat( return nil, err } - if modifyErr := callbackMsgModify(ctx, m.config, req); modifyErr != nil { + if err := callbackMsgModify(ctx, m.config, req); err != nil { return nil, err } err = m.MsgDatabase.MsgToMQ(ctx, utils.GenConversationUniqueKeyForGroup(req.MsgData.GroupID), req.MsgData) @@ -144,7 +144,7 @@ func (m *msgServer) sendMsgNotification( } func (m *msgServer) sendMsgSingleChat(ctx context.Context, req *pbmsg.SendMsgReq) (resp *pbmsg.SendMsgResp, err error) { - if verificationErr := m.messageVerification(ctx, req); verificationErr != nil { + if err := m.messageVerification(ctx, req); err != nil { return nil, err } isSend := true @@ -169,10 +169,10 @@ func (m *msgServer) sendMsgSingleChat(ctx context.Context, req *pbmsg.SendMsgReq return nil, err } - if modifyErr := callbackMsgModify(ctx, m.config, req); modifyErr != nil { + if err := callbackMsgModify(ctx, m.config, req); err != nil { return nil, err } - if mqErr := m.MsgDatabase.MsgToMQ(ctx, utils.GenConversationUniqueKeyForSingle(req.MsgData.SendID, req.MsgData.RecvID), req.MsgData); mqErr != nil { + if err := m.MsgDatabase.MsgToMQ(ctx, utils.GenConversationUniqueKeyForSingle(req.MsgData.SendID, req.MsgData.RecvID), req.MsgData); err != nil { prommetrics.SingleChatMsgProcessFailedCounter.Inc() return nil, err } diff --git a/internal/rpc/msg/server.go b/internal/rpc/msg/server.go index 8be6e28b0..5b7cd2f66 100644 --- a/internal/rpc/msg/server.go +++ b/internal/rpc/msg/server.go @@ -72,7 +72,7 @@ func Start(config *config.GlobalConfig, client discoveryregistry.SvcDiscoveryReg if err != nil { return err } - if indexErr := mongo.CreateMsgIndex(); indexErr != nil { + if err := mongo.CreateMsgIndex(); err != nil { return err } cacheModel := cache.NewMsgCacheModel(rdb, config) diff --git a/internal/rpc/msg/statistics.go b/internal/rpc/msg/statistics.go index ac09e3f69..d7d33459b 100644 --- a/internal/rpc/msg/statistics.go +++ b/internal/rpc/msg/statistics.go @@ -21,7 +21,6 @@ import ( "github.com/OpenIMSDK/protocol/msg" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" ) diff --git a/internal/rpc/msg/sync_msg.go b/internal/rpc/msg/sync_msg.go index 494858e81..b714da375 100644 --- a/internal/rpc/msg/sync_msg.go +++ b/internal/rpc/msg/sync_msg.go @@ -17,15 +17,13 @@ package msg import ( "context" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" - "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/msg" - "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/open-im-server/v3/pkg/authverify" + "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" ) func (m *msgServer) PullMessageBySeqs( diff --git a/internal/rpc/msg/utils.go b/internal/rpc/msg/utils.go index e2ec23f2e..48665562a 100644 --- a/internal/rpc/msg/utils.go +++ b/internal/rpc/msg/utils.go @@ -18,10 +18,9 @@ import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/redis/go-redis/v9" "go.mongodb.org/mongo-driver/mongo" - - "github.com/openimsdk/open-im-server/v3/pkg/common/config" ) func isMessageHasReadEnabled(msgData *sdkws.MsgData, config *config.GlobalConfig) bool { diff --git a/internal/rpc/third/log.go b/internal/rpc/third/log.go index cd764ae44..b425dd819 100644 --- a/internal/rpc/third/log.go +++ b/internal/rpc/third/log.go @@ -25,7 +25,6 @@ import ( "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/utils" utils2 "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) diff --git a/internal/rpc/third/s3.go b/internal/rpc/third/s3.go index 2e5bfebde..acd1e1f9d 100644 --- a/internal/rpc/third/s3.go +++ b/internal/rpc/third/s3.go @@ -74,7 +74,7 @@ func (t *thirdServer) InitiateMultipartUpload(ctx context.Context, req *third.In Group: req.Cause, CreateTime: time.Now(), } - if setObjectErr := t.s3dataBase.SetObject(ctx, obj); setObjectErr != nil { + if err := t.s3dataBase.SetObject(ctx, obj); err != nil { return nil, err } return &third.InitiateMultipartUploadResp{ @@ -256,10 +256,10 @@ func (t *thirdServer) CompleteFormData(ctx context.Context, req *third.CompleteF return nil, errs.ErrArgs.Wrap("invalid id " + err.Error()) } var mate FormDataMate - if unmarshalErr := json.Unmarshal(data, &mate); unmarshalErr != nil { + if err := json.Unmarshal(data, &mate); err != nil { return nil, errs.ErrArgs.Wrap("invalid id " + err.Error()) } - if uploadErr := checkUploadName(ctx, mate.Name, t.config); uploadErr != nil { + if err := checkUploadName(ctx, mate.Name, t.config); err != nil { return nil, err } info, err := t.s3dataBase.StatObject(ctx, mate.Key) diff --git a/internal/rpc/third/third.go b/internal/rpc/third/third.go index 76c6d9254..258f45645 100644 --- a/internal/rpc/third/third.go +++ b/internal/rpc/third/third.go @@ -17,7 +17,6 @@ package third import ( "context" "fmt" - "github.com/OpenIMSDK/tools/log" "net/url" "time" @@ -41,7 +40,6 @@ import ( ) func Start(config *config.GlobalConfig, client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error { - log.ZDebug(context.Background(), "config19999999999999999999999999999999999", config, "javadfdas") mongo, err := unrelation.NewMongo(config) if err != nil { @@ -59,7 +57,7 @@ func Start(config *config.GlobalConfig, client discoveryregistry.SvcDiscoveryReg if apiURL == "" { return fmt.Errorf("api url is empty") } - if _, parseErr := url.Parse(config.Object.ApiURL); parseErr != nil { + if _, err := url.Parse(config.Object.ApiURL); err != nil { return err } if apiURL[len(apiURL)-1] != '/' { @@ -70,7 +68,7 @@ func Start(config *config.GlobalConfig, client discoveryregistry.SvcDiscoveryReg if err != nil { return err } - // 根据配置文件策略选择 oss 方式 + // Select based on the configuration file strategy enable := config.Object.Enable var o s3.Interface switch config.Object.Enable { diff --git a/internal/rpc/third/tool.go b/internal/rpc/third/tool.go index 14689c746..6417ead20 100644 --- a/internal/rpc/third/tool.go +++ b/internal/rpc/third/tool.go @@ -22,11 +22,10 @@ import ( "strings" "unicode/utf8" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" - "github.com/OpenIMSDK/protocol/third" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/mcontext" + "github.com/openimsdk/open-im-server/v3/pkg/authverify" ) func toPbMapArray(m map[string][]string) []*third.KeyValues { diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go index e8e23a2c4..34f211973 100644 --- a/internal/rpc/user/callback.go +++ b/internal/rpc/user/callback.go @@ -19,7 +19,6 @@ import ( pbuser "github.com/OpenIMSDK/protocol/user" "github.com/OpenIMSDK/tools/utils" - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/http" diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index ad7c1c646..02e641d20 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -125,11 +125,11 @@ func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserI if err != nil { return nil, err } - if callbackErr := CallbackBeforeUpdateUserInfo(ctx, s.config, req); callbackErr != nil { + if err := CallbackBeforeUpdateUserInfo(ctx, s.config, req); err != nil { return nil, err } data := convert.UserPb2DBMap(req.UserInfo) - if updateErr := s.UpdateByMap(ctx, req.UserInfo.UserID, data); updateErr != nil { + if err := s.UpdateByMap(ctx, req.UserInfo.UserID, data); err != nil { return nil, err } _ = s.friendNotificationSender.UserInfoUpdatedNotification(ctx, req.UserInfo.UserID) diff --git a/internal/tools/conversation.go b/internal/tools/conversation.go index 0d0275339..b555a3361 100644 --- a/internal/tools/conversation.go +++ b/internal/tools/conversation.go @@ -20,11 +20,9 @@ import ( "time" "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) @@ -58,9 +56,9 @@ import ( // continue // } // if len(seqs) > 0 { -// if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]interface{}{"latest_msg_destruct_time": now}); err +// if err := c.conversationDatabase.UpdateUsersConversationField(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]interface{}{"latest_msg_destruct_time": now}); err // != nil { -// log.ZError(ctx, "updateUsersConversationFiled failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) +// log.ZError(ctx, "updateUsersConversationField failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) // continue // } // if err := c.msgNotificationSender.UserDeleteMsgsNotification(ctx, conversation.OwnerUserID, conversation.ConversationID, seqs); err != nil { @@ -139,8 +137,8 @@ func (c *MsgTool) ConversationsDestructMsgs() { continue } if len(seqs) > 0 { - if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]any{"latest_msg_destruct_time": now}); err != nil { - log.ZError(ctx, "updateUsersConversationFiled failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) + if err := c.conversationDatabase.UpdateUsersConversationField(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]any{"latest_msg_destruct_time": now}); err != nil { + log.ZError(ctx, "updateUsersConversationField failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) continue } if err := c.msgNotificationSender.UserDeleteMsgsNotification(ctx, conversation.OwnerUserID, conversation.ConversationID, seqs); err != nil { diff --git a/internal/tools/cron_task.go b/internal/tools/cron_task.go index d6f042513..ce87e9b90 100644 --- a/internal/tools/cron_task.go +++ b/internal/tools/cron_task.go @@ -23,7 +23,6 @@ import ( "time" "github.com/OpenIMSDK/tools/errs" - "github.com/redis/go-redis/v9" "github.com/robfig/cron/v3" @@ -48,16 +47,16 @@ func StartTask(config *config.GlobalConfig) error { // register cron tasks var crontab = cron.New() - fmt.Println("start chatRecordsClearTime cron task", "cron config", config.ChatRecordsClearTime) - _, err = crontab.AddFunc(config.ChatRecordsClearTime, cronWrapFunc(config, rdb, "cron_clear_msg_and_fix_seq", msgTool.AllConversationClearMsgAndFixSeq)) + fmt.Printf("Start chatRecordsClearTime cron task, cron config: %s\n", config.ChatRecordsClearTime) + _, err = crontab.AddFunc(config.ChatRecordsClearTime, cronWrapFunc(config,rdb, "cron_clear_msg_and_fix_seq", msgTool.AllConversationClearMsgAndFixSeq)) if err != nil { return errs.Wrap(err) } - fmt.Println("start msgDestruct cron task", "cron config", config.MsgDestructTime) - _, err = crontab.AddFunc(config.MsgDestructTime, cronWrapFunc(config, rdb, "cron_conversations_destruct_msgs", msgTool.ConversationsDestructMsgs)) + fmt.Printf("Start msgDestruct cron task, cron config: %s\n", config.MsgDestructTime) + _, err = crontab.AddFunc(config.MsgDestructTime, cronWrapFunc(config,rdb, "cron_conversations_destruct_msgs", msgTool.ConversationsDestructMsgs)) if err != nil { - return errs.Wrap(err) + return errs.Wrap(err, "cron_conversations_destruct_msgs") } // start crontab diff --git a/internal/tools/msg.go b/internal/tools/msg.go index a61bda2c5..67c3895cb 100644 --- a/internal/tools/msg.go +++ b/internal/tools/msg.go @@ -18,32 +18,26 @@ import ( "context" "fmt" "math" - - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/tx" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" - - "github.com/redis/go-redis/v9" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister" - "math/rand" + "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/mw" + "github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" + kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification" + "github.com/redis/go-redis/v9" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) type MsgTool struct { @@ -200,7 +194,8 @@ func (c *MsgTool) checkMaxSeqWithMongo(ctx context.Context, conversationID strin return err } if math.Abs(float64(maxSeqMongo-maxSeqCache)) > 10 { - log.ZError(ctx, "cache max seq and mongo max seq is diff > 10", nil, "maxSeqMongo", maxSeqMongo, "minSeqMongo", minSeqMongo, "maxSeqCache", maxSeqCache, "conversationID", conversationID) + err = fmt.Errorf("cache max seq and mongo max seq is diff > 10, maxSeqMongo:%d,minSeqMongo:%d,maxSeqCache:%d,conversationID:%s", maxSeqMongo, minSeqMongo, maxSeqCache, conversationID) + return errs.Wrap(err) } return nil } @@ -222,7 +217,6 @@ func (c *MsgTool) checkMaxSeq(ctx context.Context, conversationID string) error func (c *MsgTool) FixAllSeq(ctx context.Context) error { conversationIDs, err := c.conversationDatabase.GetAllConversationIDs(ctx) if err != nil { - log.ZError(ctx, "GetAllConversationIDs failed", err) return err } for _, conversationID := range conversationIDs { diff --git a/internal/tools/msg_doc_convert.go b/internal/tools/msg_doc_convert.go index b9150c362..eea1b69e8 100644 --- a/internal/tools/msg_doc_convert.go +++ b/internal/tools/msg_doc_convert.go @@ -18,7 +18,6 @@ import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" - "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" ) diff --git a/pkg/apistruct/msg.go b/pkg/apistruct/msg.go index d23db9bf5..d1ce427fc 100644 --- a/pkg/apistruct/msg.go +++ b/pkg/apistruct/msg.go @@ -67,6 +67,7 @@ type LocationElem struct { Longitude float64 `mapstructure:"longitude" validate:"required"` Latitude float64 `mapstructure:"latitude" validate:"required"` } + type CustomElem struct { Data string `mapstructure:"data" validate:"required"` Description string `mapstructure:"description"` diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go index 43a8c2a3f..26c43532d 100644 --- a/pkg/authverify/token.go +++ b/pkg/authverify/token.go @@ -23,7 +23,6 @@ import ( "github.com/OpenIMSDK/tools/tokenverify" "github.com/OpenIMSDK/tools/utils" "github.com/golang-jwt/jwt/v4" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" ) diff --git a/pkg/callbackstruct/group.go b/pkg/callbackstruct/group.go index 5968f1e55..467061a4a 100644 --- a/pkg/callbackstruct/group.go +++ b/pkg/callbackstruct/group.go @@ -16,7 +16,6 @@ package callbackstruct import ( common "github.com/OpenIMSDK/protocol/sdkws" - "github.com/openimsdk/open-im-server/v3/pkg/apistruct" ) diff --git a/pkg/common/cmd/api.go b/pkg/common/cmd/api.go index 859508ce3..72de059ed 100644 --- a/pkg/common/cmd/api.go +++ b/pkg/common/cmd/api.go @@ -15,6 +15,9 @@ package cmd import ( + "errors" + "fmt" + "github.com/OpenIMSDK/protocol/constant" "github.com/openimsdk/open-im-server/v3/internal/api" "github.com/spf13/cobra" @@ -35,6 +38,7 @@ func NewApiCmd() *ApiCmd { return ret } +// 原来代码 func (a *ApiCmd) addPreRun() { a.Command.PreRun = func(cmd *cobra.Command, args []string) { a.port = a.getPortFlag(cmd) @@ -48,11 +52,17 @@ func (a *ApiCmd) addRunE() { } } -func (a *ApiCmd) GetPortFromConfig(portType string) int { +func (a *ApiCmd) GetPortFromConfig(portType string) (int, error) { if portType == constant.FlagPort { - return a.config.Api.OpenImApiPort[0] + if len(a.config.Api.OpenImApiPort) > 0 { + return a.config.Api.OpenImApiPort[0], nil + } + return 0, errors.New("API port configuration is empty or missing") } else if portType == constant.FlagPrometheusPort { - return a.config.Prometheus.ApiPrometheusPort[0] + if len(a.config.Prometheus.ApiPrometheusPort) > 0 { + return a.config.Prometheus.ApiPrometheusPort[0], nil + } + return 0, errors.New("Prometheus port configuration is empty or missing") } - return 0 + return 0, fmt.Errorf("unknown port type: %s", portType) } diff --git a/pkg/common/cmd/cron_task.go b/pkg/common/cmd/cron_task.go index e7fd24cba..3ce2d5ab5 100644 --- a/pkg/common/cmd/cron_task.go +++ b/pkg/common/cmd/cron_task.go @@ -42,3 +42,7 @@ func (c *CronTaskCmd) addRunE() { func (c *CronTaskCmd) Exec() error { return c.Execute() } + +func (c *CronTaskCmd) GetPortFromConfig(portType string) (int, error) { + return 0, nil +} diff --git a/pkg/common/cmd/msg_gateway_test.go b/pkg/common/cmd/msg_gateway_test.go index c0ea2b057..106ad74ec 100644 --- a/pkg/common/cmd/msg_gateway_test.go +++ b/pkg/common/cmd/msg_gateway_test.go @@ -44,7 +44,7 @@ func TestMsgGatewayCmd_GetPortFromConfig(t *testing.T) { } for _, tt := range tests { t.Run(tt.portType, func(t *testing.T) { - got := msgGatewayCmd.GetPortFromConfig(tt.portType) + got, _ := msgGatewayCmd.GetPortFromConfig(tt.portType) assert.Equal(t, tt.want, got) }) } diff --git a/pkg/common/cmd/msg_utils.go b/pkg/common/cmd/msg_utils.go index 6ecad14e6..df15acd87 100644 --- a/pkg/common/cmd/msg_utils.go +++ b/pkg/common/cmd/msg_utils.go @@ -15,9 +15,9 @@ package cmd import ( - "github.com/spf13/cobra" - "github.com/openimsdk/open-im-server/v3/internal/tools" + util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" + "github.com/spf13/cobra" ) type MsgUtilsCmd struct { @@ -138,7 +138,7 @@ func (s *SeqCmd) GetSeqCmd() *cobra.Command { s.Command.Run = func(cmdLines *cobra.Command, args []string) { _, err := tools.InitMsgTool(s.MsgTool.Config) if err != nil { - panic(err) + util.ExitWithError(err) } userID := s.getUserIDFlag(cmdLines) superGroupID := s.getSuperGroupIDFlag(cmdLines) diff --git a/pkg/common/cmd/root.go b/pkg/common/cmd/root.go index 651681e5b..478942a5b 100644 --- a/pkg/common/cmd/root.go +++ b/pkg/common/cmd/root.go @@ -17,19 +17,18 @@ package cmd import ( "fmt" - config2 "github.com/openimsdk/open-im-server/v3/pkg/common/config" - - "github.com/spf13/cobra" - "github.com/OpenIMSDK/protocol/constant" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" + config2 "github.com/openimsdk/open-im-server/v3/pkg/common/config" + "github.com/spf13/cobra" ) type RootCmdPt interface { GetPortFromConfig(portType string) int } + type RootCmd struct { Command cobra.Command Name string @@ -49,7 +48,7 @@ type CmdOpts struct { func WithCronTaskLogName() func(*CmdOpts) { return func(opts *CmdOpts) { - opts.loggerPrefixName = "openim.crontask.log.all" + opts.loggerPrefixName = "openim-crontask" } } @@ -82,7 +81,7 @@ func (rc *RootCmd) persistentPreRun(cmd *cobra.Command, opts ...func(*CmdOpts)) cmdOpts := rc.applyOptions(opts...) if err := rc.initializeLogger(cmdOpts); err != nil { - return fmt.Errorf("failed to initialize from config: %w", err) + return errs.Wrap(err, "failed to initialize logger") } return nil @@ -119,7 +118,7 @@ func (rc *RootCmd) initializeLogger(cmdOpts *CmdOpts) error { func defaultCmdOpts() *CmdOpts { return &CmdOpts{ - loggerPrefixName: "OpenIM.log.all", + loggerPrefixName: "openim-all", } } @@ -138,7 +137,8 @@ func (r *RootCmd) AddPortFlag() { func (r *RootCmd) getPortFlag(cmd *cobra.Command) int { port, err := cmd.Flags().GetInt(constant.FlagPort) if err != nil { - fmt.Println("Error getting ws port flag:", err) + // Wrapping the error with additional context + return 0 } if port == 0 { port = r.PortFromConfig(constant.FlagPort) @@ -146,6 +146,7 @@ func (r *RootCmd) getPortFlag(cmd *cobra.Command) int { return port } +// // GetPortFlag returns the port flag. func (r *RootCmd) GetPortFlag() int { return r.port } @@ -155,9 +156,12 @@ func (r *RootCmd) AddPrometheusPortFlag() { } func (r *RootCmd) getPrometheusPortFlag(cmd *cobra.Command) int { - port, _ := cmd.Flags().GetInt(constant.FlagPrometheusPort) - if port == 0 { + port, err := cmd.Flags().GetInt(constant.FlagPrometheusPort) + if err != nil || port == 0 { port = r.PortFromConfig(constant.FlagPrometheusPort) + if err != nil { + return 0 + } } return port } @@ -180,10 +184,8 @@ func (r *RootCmd) AddCommand(cmds ...*cobra.Command) { r.Command.AddCommand(cmds...) } -func (r *RootCmd) GetPortFromConfig(portType string) int { - return 0 -} - func (r *RootCmd) PortFromConfig(portType string) int { - return r.cmdItf.GetPortFromConfig(portType) + // Retrieve the port and cache it + port := r.cmdItf.GetPortFromConfig(portType) + return port } diff --git a/pkg/common/config/parse.go b/pkg/common/config/parse.go index 866982feb..bfbf6daf7 100644 --- a/pkg/common/config/parse.go +++ b/pkg/common/config/parse.go @@ -83,6 +83,9 @@ func GetOptionsByNotification(cfg NotificationConf) msgprocessor.Options { return opts } +// initConfig loads configuration from a specified path into the provided config structure. +// If the specified config file does not exist, it attempts to load from the project's default "config" directory. +// It logs informative messages regarding the configuration path being used. func initConfig(config any, configName, configFolderPath string) error { configFolderPath = filepath.Join(configFolderPath, configName) _, err := os.Stat(configFolderPath) diff --git a/pkg/common/config/parse_test.go b/pkg/common/config/parse_test.go index 6291cd2cf..84dee1165 100644 --- a/pkg/common/config/parse_test.go +++ b/pkg/common/config/parse_test.go @@ -31,7 +31,7 @@ func TestGetDefaultConfigPath(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := GetDefaultConfigPath(); got != tt.want { + if got, _ := GetDefaultConfigPath(); got != tt.want { t.Errorf("GetDefaultConfigPath() = %v, want %v", got, tt.want) } }) @@ -47,7 +47,7 @@ func TestGetProjectRoot(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := GetProjectRoot(); got != tt.want { + if got, _ := GetProjectRoot(); got != tt.want { t.Errorf("GetProjectRoot() = %v, want %v", got, tt.want) } }) diff --git a/pkg/common/convert/black.go b/pkg/common/convert/black.go index 50c270dcb..683517fbc 100644 --- a/pkg/common/convert/black.go +++ b/pkg/common/convert/black.go @@ -19,15 +19,10 @@ import ( "github.com/OpenIMSDK/protocol/sdkws" sdk "github.com/OpenIMSDK/protocol/sdkws" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) -func BlackDB2Pb( - ctx context.Context, - blackDBs []*relation.BlackModel, - f func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error), -) (blackPbs []*sdk.BlackInfo, err error) { +func BlackDB2Pb(ctx context.Context, blackDBs []*relation.BlackModel, f func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error)) (blackPbs []*sdk.BlackInfo, err error) { if len(blackDBs) == 0 { return nil, nil } diff --git a/pkg/common/convert/conversation.go b/pkg/common/convert/conversation.go index 165262b7f..b3f4913eb 100644 --- a/pkg/common/convert/conversation.go +++ b/pkg/common/convert/conversation.go @@ -17,7 +17,6 @@ package convert import ( "github.com/OpenIMSDK/protocol/conversation" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) diff --git a/pkg/common/convert/friend.go b/pkg/common/convert/friend.go index f3a19e459..4231eb49d 100644 --- a/pkg/common/convert/friend.go +++ b/pkg/common/convert/friend.go @@ -20,7 +20,6 @@ import ( "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) @@ -89,8 +88,7 @@ func FriendsDB2Pb( } -func FriendRequestDB2Pb( - ctx context.Context, +func FriendRequestDB2Pb(ctx context.Context, friendRequests []*relation.FriendRequestModel, getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error), ) ([]*sdkws.FriendRequest, error) { diff --git a/pkg/common/convert/group.go b/pkg/common/convert/group.go index 18940f518..63372f21d 100644 --- a/pkg/common/convert/group.go +++ b/pkg/common/convert/group.go @@ -19,7 +19,6 @@ import ( pbgroup "github.com/OpenIMSDK/protocol/group" sdkws "github.com/OpenIMSDK/protocol/sdkws" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) diff --git a/pkg/common/convert/msg.go b/pkg/common/convert/msg.go index 56f71f018..34638049b 100644 --- a/pkg/common/convert/msg.go +++ b/pkg/common/convert/msg.go @@ -17,7 +17,6 @@ package convert import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/sdkws" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" ) diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go index 62f80e458..38afd8c19 100644 --- a/pkg/common/convert/user.go +++ b/pkg/common/convert/user.go @@ -18,7 +18,6 @@ import ( "time" "github.com/OpenIMSDK/protocol/sdkws" - relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) diff --git a/pkg/common/db/cache/black.go b/pkg/common/db/cache/black.go index d1abe945c..c8cf2ddd3 100644 --- a/pkg/common/db/cache/black.go +++ b/pkg/common/db/cache/black.go @@ -19,9 +19,8 @@ import ( "time" "github.com/dtm-labs/rockscache" - "github.com/redis/go-redis/v9" - relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/redis/go-redis/v9" ) const ( @@ -46,11 +45,7 @@ type BlackCacheRedis struct { blackDB relationtb.BlackModelInterface } -func NewBlackCacheRedis( - rdb redis.UniversalClient, - blackDB relationtb.BlackModelInterface, - options rockscache.Options, -) BlackCache { +func NewBlackCacheRedis(rdb redis.UniversalClient, blackDB relationtb.BlackModelInterface, options rockscache.Options) BlackCache { rcClient := rockscache.NewClient(rdb, options) return &BlackCacheRedis{ diff --git a/pkg/common/db/cache/conversation.go b/pkg/common/db/cache/conversation.go index 047188947..90e400363 100644 --- a/pkg/common/db/cache/conversation.go +++ b/pkg/common/db/cache/conversation.go @@ -20,12 +20,10 @@ import ( "strings" "time" - "github.com/dtm-labs/rockscache" - "github.com/redis/go-redis/v9" - "github.com/OpenIMSDK/tools/utils" - + "github.com/dtm-labs/rockscache" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/redis/go-redis/v9" ) const ( diff --git a/pkg/common/db/cache/friend.go b/pkg/common/db/cache/friend.go index a2b60d48f..a160837ba 100644 --- a/pkg/common/db/cache/friend.go +++ b/pkg/common/db/cache/friend.go @@ -18,12 +18,10 @@ import ( "context" "time" - "github.com/dtm-labs/rockscache" - "github.com/redis/go-redis/v9" - "github.com/OpenIMSDK/tools/utils" - + "github.com/dtm-labs/rockscache" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/redis/go-redis/v9" ) const ( diff --git a/pkg/common/db/cache/group.go b/pkg/common/db/cache/group.go index 57fcf1a9b..4a5266db5 100644 --- a/pkg/common/db/cache/group.go +++ b/pkg/common/db/cache/group.go @@ -22,15 +22,11 @@ import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/log" - - "github.com/dtm-labs/rockscache" - "github.com/redis/go-redis/v9" - "github.com/OpenIMSDK/tools/utils" - + "github.com/dtm-labs/rockscache" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/redis/go-redis/v9" ) const ( diff --git a/pkg/common/db/cache/init_redis.go b/pkg/common/db/cache/init_redis.go index f98d84ed0..8f4e2c592 100644 --- a/pkg/common/db/cache/init_redis.go +++ b/pkg/common/db/cache/init_redis.go @@ -22,12 +22,10 @@ import ( "strings" "time" - "github.com/redis/go-redis/v9" - "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/mw/specialerror" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" + "github.com/redis/go-redis/v9" ) var ( @@ -77,8 +75,7 @@ func NewRedis(config *config.GlobalConfig) (redis.UniversalClient, error) { defer cancel() err = rdb.Ping(ctx).Err() if err != nil { - uriFormat := "address:%s, username:%s, password:%s, clusterMode:%t, enablePipeline:%t" - errMsg := fmt.Sprintf(uriFormat, config.Redis.Address, config.Redis.Username, + errMsg := fmt.Sprintf("address:%s, username:%s, password:%s, clusterMode:%t, enablePipeline:%t", config.Redis.Address, config.Redis.Username, config.Redis.Password, config.Redis.ClusterMode, config.Redis.EnablePipeline) return nil, errs.Wrap(err, errMsg) } @@ -99,9 +96,11 @@ func overrideConfigFromEnv(config *config.GlobalConfig) { config.Redis.Address = strings.Split(envAddr, ",") } } + if envUser := os.Getenv("REDIS_USERNAME"); envUser != "" { config.Redis.Username = envUser } + if envPass := os.Getenv("REDIS_PASSWORD"); envPass != "" { config.Redis.Password = envPass } diff --git a/pkg/common/db/cache/msg.go b/pkg/common/db/cache/msg.go index 207eb3983..1266875f1 100644 --- a/pkg/common/db/cache/msg.go +++ b/pkg/common/db/cache/msg.go @@ -20,22 +20,16 @@ import ( "strconv" "time" - "golang.org/x/sync/errgroup" - - "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" - - "github.com/OpenIMSDK/tools/errs" - - "github.com/gogo/protobuf/jsonpb" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/utils" - + "github.com/gogo/protobuf/jsonpb" "github.com/openimsdk/open-im-server/v3/pkg/common/config" - + "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" "github.com/redis/go-redis/v9" + "golang.org/x/sync/errgroup" ) const ( @@ -434,7 +428,7 @@ func (c *msgCache) PipeSetMessageToCache(ctx context.Context, conversationID str for _, msg := range msgs { s, err := msgprocessor.Pb2String(msg) if err != nil { - return 0, errs.Wrap(err, "pb.marshal") + return 0, err } key := c.getMessageCacheKey(conversationID, msg.Seq) @@ -443,7 +437,7 @@ func (c *msgCache) PipeSetMessageToCache(ctx context.Context, conversationID str results, err := pipe.Exec(ctx) if err != nil { - return 0, errs.Wrap(err, "pipe.set") + return 0, errs.Wrap(err) } for _, res := range results { diff --git a/pkg/common/db/cache/s3.go b/pkg/common/db/cache/s3.go index 1e68cedf8..28e993be0 100644 --- a/pkg/common/db/cache/s3.go +++ b/pkg/common/db/cache/s3.go @@ -20,10 +20,9 @@ import ( "time" "github.com/dtm-labs/rockscache" - "github.com/redis/go-redis/v9" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/redis/go-redis/v9" ) type ObjectCache interface { diff --git a/pkg/common/db/cache/user.go b/pkg/common/db/cache/user.go index 34bf68242..34c220624 100644 --- a/pkg/common/db/cache/user.go +++ b/pkg/common/db/cache/user.go @@ -293,7 +293,7 @@ func (u *UserCacheRedis) refreshStatusOnline(ctx context.Context, userID string, onlineStatus.UserID = userID newjsonData, err := json.Marshal(&onlineStatus) if err != nil { - return errs.Wrap(err) + return errs.Wrap(err, "json.Marshal failed") } _, err = u.rdb.HSet(ctx, key, userID, string(newjsonData)).Result() if err != nil { diff --git a/pkg/common/db/controller/auth.go b/pkg/common/db/controller/auth.go index 87d20c645..19bea5981 100644 --- a/pkg/common/db/controller/auth.go +++ b/pkg/common/db/controller/auth.go @@ -18,22 +18,18 @@ import ( "context" "github.com/openimsdk/open-im-server/v3/pkg/common/config" - "github.com/OpenIMSDK/tools/errs" - - "github.com/openimsdk/open-im-server/v3/pkg/authverify" - - "github.com/golang-jwt/jwt/v4" - "github.com/OpenIMSDK/protocol/constant" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/tokenverify" - + "github.com/golang-jwt/jwt/v4" + "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" ) type AuthDatabase interface { - // 结果为空 不返回错误 + // If the result is empty, no error is returned. GetTokensWithoutError(ctx context.Context, userID string, platformID int) (map[string]int, error) - // 创建token + // Create token CreateToken(ctx context.Context, userID string, platformID int) (string, error) } @@ -48,16 +44,12 @@ func NewAuthDatabase(cache cache.MsgModel, accessSecret string, accessExpire int return &authDatabase{cache: cache, accessSecret: accessSecret, accessExpire: accessExpire, config: config} } -// 结果为空 不返回错误. -func (a *authDatabase) GetTokensWithoutError( - ctx context.Context, - userID string, - platformID int, -) (map[string]int, error) { +// If the result is empty. +func (a *authDatabase) GetTokensWithoutError(ctx context.Context, userID string, platformID int) (map[string]int, error) { return a.cache.GetTokensWithoutError(ctx, userID, platformID) } -// 创建token. +// Create Token. func (a *authDatabase) CreateToken(ctx context.Context, userID string, platformID int) (string, error) { tokens, err := a.cache.GetTokensWithoutError(ctx, userID, platformID) if err != nil { @@ -81,7 +73,7 @@ func (a *authDatabase) CreateToken(ctx context.Context, userID string, platformI token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString([]byte(a.accessSecret)) if err != nil { - return "", errs.Wrap(err) + return "", errs.Wrap(err, "token.SignedString") } return tokenString, a.cache.AddTokenFlag(ctx, userID, platformID, tokenString, constant.NormalToken) } diff --git a/pkg/common/db/controller/black.go b/pkg/common/db/controller/black.go index e68d06b01..c4b253c2f 100644 --- a/pkg/common/db/controller/black.go +++ b/pkg/common/db/controller/black.go @@ -17,24 +17,22 @@ package controller import ( "context" - "github.com/OpenIMSDK/tools/pagination" - "github.com/OpenIMSDK/tools/log" + "github.com/OpenIMSDK/tools/pagination" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) type BlackDatabase interface { - // Create 增加黑名单 + // Create add BlackList Create(ctx context.Context, blacks []*relation.BlackModel) (err error) - // Delete 删除黑名单 + // Delete delete BlackList Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) - // FindOwnerBlacks 获取黑名单列表 + // FindOwnerBlacks get BlackList list FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) FindBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) - // CheckIn 检查user2是否在user1的黑名单列表中(inUser1Blacks==true) 检查user1是否在user2的黑名单列表中(inUser2Blacks==true) + // CheckIn Check whether user2 is in the black list of user1 (inUser1Blacks==true) Check whether user1 is in the black list of user2 (inUser2Blacks==true) CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Blacks bool, inUser2Blacks bool, err error) } @@ -47,7 +45,7 @@ func NewBlackDatabase(black relation.BlackModelInterface, cache cache.BlackCache return &blackDatabase{black, cache} } -// Create 增加黑名单. +// Create Add Blacklist. func (b *blackDatabase) Create(ctx context.Context, blacks []*relation.BlackModel) (err error) { if err := b.black.Create(ctx, blacks); err != nil { return err @@ -55,7 +53,7 @@ func (b *blackDatabase) Create(ctx context.Context, blacks []*relation.BlackMode return b.deleteBlackIDsCache(ctx, blacks) } -// Delete 删除黑名单. +// Delete Delete Blacklist. func (b *blackDatabase) Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) { if err := b.black.Delete(ctx, blacks); err != nil { return err @@ -63,6 +61,7 @@ func (b *blackDatabase) Delete(ctx context.Context, blacks []*relation.BlackMode return b.deleteBlackIDsCache(ctx, blacks) } +// FindOwnerBlacks Get Blacklist List. func (b *blackDatabase) deleteBlackIDsCache(ctx context.Context, blacks []*relation.BlackModel) (err error) { cache := b.cache.NewCache() for _, black := range blacks { @@ -71,16 +70,13 @@ func (b *blackDatabase) deleteBlackIDsCache(ctx context.Context, blacks []*relat return cache.ExecDel(ctx) } -// FindOwnerBlacks 获取黑名单列表. +// FindOwnerBlacks Get Blacklist List. func (b *blackDatabase) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) { return b.black.FindOwnerBlacks(ctx, ownerUserID, pagination) } -// CheckIn 检查user2是否在user1的黑名单列表中(inUser1Blacks==true) 检查user1是否在user2的黑名单列表中(inUser2Blacks==true). -func (b *blackDatabase) CheckIn( - ctx context.Context, - userID1, userID2 string, -) (inUser1Blacks bool, inUser2Blacks bool, err error) { +// FindOwnerBlacks Get Blacklist List. +func (b *blackDatabase) CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Blacks bool, inUser2Blacks bool, err error) { userID1BlackIDs, err := b.cache.GetBlackIDs(ctx, userID1) if err != nil { return @@ -93,10 +89,12 @@ func (b *blackDatabase) CheckIn( return utils.IsContain(userID2, userID1BlackIDs), utils.IsContain(userID1, userID2BlackIDs), nil } +// FindBlackIDs Get Blacklist List. func (b *blackDatabase) FindBlackIDs(ctx context.Context, ownerUserID string) (blackIDs []string, err error) { return b.cache.GetBlackIDs(ctx, ownerUserID) } +// FindBlackInfos Get Blacklist List. func (b *blackDatabase) FindBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) { return b.black.FindOwnerBlackInfos(ctx, ownerUserID, userIDs) } diff --git a/pkg/common/db/controller/conversation.go b/pkg/common/db/controller/conversation.go index c53d4ab87..3d46e4fbc 100644 --- a/pkg/common/db/controller/conversation.go +++ b/pkg/common/db/controller/conversation.go @@ -18,46 +18,52 @@ import ( "context" "time" - "github.com/OpenIMSDK/tools/pagination" - - "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/tools/log" + "github.com/OpenIMSDK/tools/pagination" "github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" ) type ConversationDatabase interface { - // UpdateUserConversationFiled 更新用户该会话的属性信息 - UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error - // CreateConversation 创建一批新的会话 + // UpdateUsersConversationField updates the properties of a conversation for specified users. + UpdateUsersConversationField(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error + // CreateConversation creates a batch of new conversations. CreateConversation(ctx context.Context, conversations []*relationtb.ConversationModel) error - // SyncPeerUserPrivateConversation 同步对端私聊会话内部保证事务操作 + // SyncPeerUserPrivateConversationTx ensures transactional operation while syncing private conversations between peers. SyncPeerUserPrivateConversationTx(ctx context.Context, conversation []*relationtb.ConversationModel) error - // FindConversations 根据会话ID获取某个用户的多个会话 + // FindConversations retrieves multiple conversations of a user by conversation IDs. FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error) - // FindRecvMsgNotNotifyUserIDs 获取超级大群开启免打扰的用户ID - //FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) - // GetUserAllConversation 获取一个用户在服务器上所有的会话 + // GetUserAllConversation fetches all conversations of a user on the server. GetUserAllConversation(ctx context.Context, ownerUserID string) ([]*relationtb.ConversationModel, error) - // SetUserConversations 设置用户多个会话属性,如果会话不存在则创建,否则更新,内部保证原子性 + // SetUserConversations sets multiple conversation properties for a user, creates new conversations if they do not exist, or updates them otherwise. This operation is atomic. SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error - // SetUsersConversationFiledTx 设置多个用户会话关于某个字段的更新操作,如果会话不存在则创建,否则更新,内部保证事务操作 - SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]any) error + // SetUsersConversationFieldTx updates a specific field for multiple users' conversations, creating new conversations if they do not exist, or updates them otherwise. This operation is + // transactional. + SetUsersConversationFieldTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, fieldMap map[string]any) error + // CreateGroupChatConversation creates a group chat conversation for the specified group ID and user IDs. CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error + // GetConversationIDs retrieves conversation IDs for a given user. GetConversationIDs(ctx context.Context, userID string) ([]string, error) + // GetUserConversationIDsHash gets the hash of conversation IDs for a given user. GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error) + // GetAllConversationIDs fetches all conversation IDs. GetAllConversationIDs(ctx context.Context) ([]string, error) + // GetAllConversationIDsNumber returns the number of all conversation IDs. GetAllConversationIDsNumber(ctx context.Context) (int64, error) + // PageConversationIDs paginates through conversation IDs based on the specified pagination settings. PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error) - //GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error) + // GetConversationsByConversationID retrieves conversations by their IDs. GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error) + // GetConversationIDsNeedDestruct fetches conversations that need to be destructed based on specific criteria. GetConversationIDsNeedDestruct(ctx context.Context) ([]*relationtb.ConversationModel, error) + // GetConversationNotReceiveMessageUserIDs gets user IDs for users in a conversation who have not received messages. GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) + //GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error) + //FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) } func NewConversationDatabase(conversation relationtb.ConversationModelInterface, cache cache.ConversationCache, tx tx.CtxTx) ConversationDatabase { @@ -74,7 +80,7 @@ type conversationDatabase struct { tx tx.CtxTx } -func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]any) (err error) { +func (c *conversationDatabase) SetUsersConversationFieldTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, fieldMap map[string]any) (err error) { return c.tx.Transaction(ctx, func(ctx context.Context) error { cache := c.cache.NewCache() if conversation.GroupID != "" { @@ -85,22 +91,22 @@ func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context, return err } if len(haveUserIDs) > 0 { - _, err = c.conversationDB.UpdateByMap(ctx, haveUserIDs, conversation.ConversationID, filedMap) + _, err = c.conversationDB.UpdateByMap(ctx, haveUserIDs, conversation.ConversationID, fieldMap) if err != nil { return err } cache = cache.DelUsersConversation(conversation.ConversationID, haveUserIDs...) - if _, ok := filedMap["has_read_seq"]; ok { + if _, ok := fieldMap["has_read_seq"]; ok { for _, userID := range haveUserIDs { cache = cache.DelUserAllHasReadSeqs(userID, conversation.ConversationID) } } - if _, ok := filedMap["recv_msg_opt"]; ok { + if _, ok := fieldMap["recv_msg_opt"]; ok { cache = cache.DelConversationNotReceiveMessageUserIDs(conversation.ConversationID) } } NotUserIDs := utils.DifferenceString(haveUserIDs, userIDs) - log.ZDebug(ctx, "SetUsersConversationFiledTx", "NotUserIDs", NotUserIDs, "haveUserIDs", haveUserIDs, "userIDs", userIDs) + log.ZDebug(ctx, "SetUsersConversationFieldTx", "NotUserIDs", NotUserIDs, "haveUserIDs", haveUserIDs, "userIDs", userIDs) var conversations []*relationtb.ConversationModel now := time.Now() for _, v := range NotUserIDs { @@ -123,7 +129,7 @@ func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context, }) } -func (c *conversationDatabase) UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error { +func (c *conversationDatabase) UpdateUsersConversationField(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error { _, err := c.conversationDB.UpdateByMap(ctx, userIDs, conversationID, args) if err != nil { return err diff --git a/pkg/common/db/controller/friend.go b/pkg/common/db/controller/friend.go index 3b98f5d7b..3c81d922c 100644 --- a/pkg/common/db/controller/friend.go +++ b/pkg/common/db/controller/friend.go @@ -16,17 +16,16 @@ package controller import ( "context" + "fmt" "time" - "github.com/OpenIMSDK/tools/pagination" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" + "github.com/OpenIMSDK/tools/pagination" "github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) @@ -89,20 +88,30 @@ func NewFriendDatabase(friend relation.FriendModelInterface, friendRequest relat return &friendDatabase{friend: friend, friendRequest: friendRequest, cache: cache, tx: tx} } -// ok 检查user2是否在user1的好友列表中(inUser1Friends==true) 检查user1是否在user2的好友列表中(inUser2Friends==true). +// CheckIn verifies if user2 is in user1's friend list (inUser1Friends returns true) and +// if user1 is in user2's friend list (inUser2Friends returns true). func (f *friendDatabase) CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Friends bool, inUser2Friends bool, err error) { + // Retrieve friend IDs of userID1 from the cache userID1FriendIDs, err := f.cache.GetFriendIDs(ctx, userID1) if err != nil { + err = fmt.Errorf("error retrieving friend IDs for user %s: %w", userID1, err) return } + + // Retrieve friend IDs of userID2 from the cache userID2FriendIDs, err := f.cache.GetFriendIDs(ctx, userID2) if err != nil { + err = fmt.Errorf("error retrieving friend IDs for user %s: %w", userID2, err) return } - return utils.IsContain(userID2, userID1FriendIDs), utils.IsContain(userID1, userID2FriendIDs), nil + + // Check if userID2 is in userID1's friend list and vice versa + inUser1Friends = utils.IsContain(userID2, userID1FriendIDs) + inUser2Friends = utils.IsContain(userID1, userID2FriendIDs) + return inUser1Friends, inUser2Friends, nil } -// 增加或者更新好友申请 如果之前有记录则更新,没有记录则新增. +// AddFriendRequest adds or updates a friend request. func (f *friendDatabase) AddFriendRequest(ctx context.Context, fromUserID, toUserID string, reqMsg string, ex string) (err error) { return f.tx.Transaction(ctx, func(ctx context.Context) error { _, err := f.friendRequest.Take(ctx, fromUserID, toUserID) @@ -126,11 +135,11 @@ func (f *friendDatabase) AddFriendRequest(ctx context.Context, fromUserID, toUse }) } -// (1)先判断是否在好友表 (在不在都不返回错误) (2)对于不在好友列表的 插入即可. +// (1) First determine whether it is in the friends list (in or out does not return an error) (2) for not in the friends list can be inserted. func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error) { return f.tx.Transaction(ctx, func(ctx context.Context) error { cache := f.cache.NewCache() - // 先find 找出重复的 去掉重复的 + // User find friends fs1, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs) if err != nil { return err @@ -170,26 +179,37 @@ func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string, }) } -// 拒绝好友申请 (1)检查是否有申请记录且为未处理状态 (没有记录返回错误) (2)修改申请记录 已拒绝. -func (f *friendDatabase) RefuseFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) { +// RefuseFriendRequest rejects a friend request. It first checks for an existing, unprocessed request. +// If no such request exists, it returns an error. Otherwise, it marks the request as refused. +func (f *friendDatabase) RefuseFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) error { + // Attempt to retrieve the friend request from the database. fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID) if err != nil { - return err + return fmt.Errorf("failed to retrieve friend request from %s to %s: %w", friendRequest.FromUserID, friendRequest.ToUserID, err) } + + // Check if the friend request has already been handled. if fr.HandleResult != 0 { - return errs.ErrArgs.Wrap("the friend request has been processed") + return fmt.Errorf("friend request from %s to %s has already been processed", friendRequest.FromUserID, friendRequest.ToUserID) } - log.ZDebug(ctx, "refuse friend request", "friendRequest db", fr, "friendRequest arg", friendRequest) + + // Log the action of refusing the friend request for debugging and auditing purposes. + log.ZDebug(ctx, "Refusing friend request", map[string]interface{}{ + "DB_FriendRequest": fr, + "Arg_FriendRequest": friendRequest, + }) + + // Mark the friend request as refused and update the handle time. friendRequest.HandleResult = constant.FriendResponseRefuse friendRequest.HandleTime = time.Now() - err = f.friendRequest.Update(ctx, friendRequest) - if err != nil { - return err + if err := f.friendRequest.Update(ctx, friendRequest); err != nil { + return fmt.Errorf("failed to update friend request from %s to %s as refused: %w", friendRequest.FromUserID, friendRequest.ToUserID, err) } + return nil } -// AgreeFriendRequest 同意好友申请 (1)检查是否有申请记录且为未处理状态 (没有记录返回错误) (2)检查是否好友(不返回错误) (3) 建立双向好友关系(存在的忽略). +// AgreeFriendRequest accepts a friend request. It first checks for an existing, unprocessed request. func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) { return f.tx.Transaction(ctx, func(ctx context.Context) error { defer log.ZDebug(ctx, "return line") @@ -227,10 +247,10 @@ func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest * return err } existsMap := utils.SliceSet(utils.Slice(exists, func(friend *relation.FriendModel) [2]string { - return [...]string{friend.OwnerUserID, friend.FriendUserID} // 自己 - 好友 + return [...]string{friend.OwnerUserID, friend.FriendUserID} // My - Friend })) var adds []*relation.FriendModel - if _, ok := existsMap[[...]string{friendRequest.ToUserID, friendRequest.FromUserID}]; !ok { // 自己 - 好友 + if _, ok := existsMap[[...]string{friendRequest.ToUserID, friendRequest.FromUserID}]; !ok { // My - Friend adds = append( adds, &relation.FriendModel{ @@ -241,7 +261,7 @@ func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest * }, ) } - if _, ok := existsMap[[...]string{friendRequest.FromUserID, friendRequest.ToUserID}]; !ok { // 好友 - 自己 + if _, ok := existsMap[[...]string{friendRequest.FromUserID, friendRequest.ToUserID}]; !ok { // My - Friend adds = append( adds, &relation.FriendModel{ @@ -261,7 +281,7 @@ func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest * }) } -// 删除好友 外部判断是否好友关系. +// Delete removes a friend relationship. It is assumed that the external caller has verified the friendship status. func (f *friendDatabase) Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error) { if err := f.friend.Delete(ctx, ownerUserID, friendUserIDs); err != nil { return err @@ -269,7 +289,7 @@ func (f *friendDatabase) Delete(ctx context.Context, ownerUserID string, friendU return f.cache.DelFriendIDs(append(friendUserIDs, ownerUserID)...).ExecDel(ctx) } -// 更新好友备注 零值也支持. +// UpdateRemark updates the remark for a friend. Zero value for remark is also supported. func (f *friendDatabase) UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error) { if err := f.friend.UpdateRemark(ctx, ownerUserID, friendUserID, remark); err != nil { return err @@ -277,27 +297,27 @@ func (f *friendDatabase) UpdateRemark(ctx context.Context, ownerUserID, friendUs return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx) } -// 获取ownerUserID的好友列表 无结果不返回错误. +// PageOwnerFriends retrieves the list of friends for the ownerUserID. It does not return an error if the result is empty. func (f *friendDatabase) PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) { return f.friend.FindOwnerFriends(ctx, ownerUserID, pagination) } -// friendUserID在哪些人的好友列表中. +// PageInWhoseFriends identifies in whose friend lists the friendUserID appears. func (f *friendDatabase) PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) { return f.friend.FindInWhoseFriends(ctx, friendUserID, pagination) } -// 获取我发出去的好友申请 无结果不返回错误. +// PageFriendRequestFromMe retrieves friend requests sent by me. It does not return an error if the result is empty. func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) { return f.friendRequest.FindFromUserID(ctx, userID, pagination) } -// 获取我收到的的好友申请 无结果不返回错误. +// PageFriendRequestToMe retrieves friend requests received by me. It does not return an error if the result is empty. func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) { return f.friendRequest.FindToUserID(ctx, userID, pagination) } -// 获取某人指定好友的信息 如果有好友不存在,也返回错误. +// FindFriendsWithError retrieves specified friends' information for ownerUserID. Returns an error if any friend does not exist. func (f *friendDatabase) FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error) { friends, err = f.friend.FindFriends(ctx, ownerUserID, friendUserIDs) if err != nil { diff --git a/pkg/common/db/controller/group.go b/pkg/common/db/controller/group.go index decd868d6..45bf87b6f 100644 --- a/pkg/common/db/controller/group.go +++ b/pkg/common/db/controller/group.go @@ -18,60 +18,90 @@ import ( "context" "time" - "github.com/OpenIMSDK/tools/pagination" - "github.com/dtm-labs/rockscache" - "github.com/OpenIMSDK/protocol/constant" + "github.com/OpenIMSDK/tools/pagination" "github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/tools/utils" - "github.com/redis/go-redis/v9" - + "github.com/dtm-labs/rockscache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/redis/go-redis/v9" ) type GroupDatabase interface { - // Group + // CreateGroup creates new groups along with their members. CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error + // TakeGroup retrieves a single group by its ID. TakeGroup(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error) + // FindGroup retrieves multiple groups by their IDs. FindGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) + // SearchGroup searches for groups based on a keyword and pagination settings, returns total count and groups. SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*relationtb.GroupModel, error) + // UpdateGroup updates the properties of a group identified by its ID. UpdateGroup(ctx context.Context, groupID string, data map[string]any) error - DismissGroup(ctx context.Context, groupID string, deleteMember bool) error // 解散群,并删除群成员 + // DismissGroup disbands a group and optionally removes its members based on the deleteMember flag. + DismissGroup(ctx context.Context, groupID string, deleteMember bool) error + // TakeGroupMember retrieves a specific group member by group ID and user ID. TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *relationtb.GroupMemberModel, err error) + // TakeGroupOwner retrieves the owner of a group by group ID. TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) - FindGroupMembers(ctx context.Context, groupID string, userIDs []string) (groupMembers []*relationtb.GroupMemberModel, err error) // * - FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (groupMembers []*relationtb.GroupMemberModel, err error) // * - FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) (groupMembers []*relationtb.GroupMemberModel, err error) // * - FindGroupMemberAll(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error) // * + // FindGroupMembers retrieves members of a group filtered by user IDs. + FindGroupMembers(ctx context.Context, groupID string, userIDs []string) (groupMembers []*relationtb.GroupMemberModel, err error) + // FindGroupMemberUser retrieves groups that a user is a member of, filtered by group IDs. + FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (groupMembers []*relationtb.GroupMemberModel, err error) + // FindGroupMemberRoleLevels retrieves group members filtered by their role levels within a group. + FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) (groupMembers []*relationtb.GroupMemberModel, err error) + // FindGroupMemberAll retrieves all members of a group. + FindGroupMemberAll(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error) + // FindGroupsOwner retrieves the owners for multiple groups. FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error) + // FindGroupMemberUserID retrieves the user IDs of all members in a group. FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) + // FindGroupMemberNum retrieves the number of members in a group. FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error) + // FindUserManagedGroupID retrieves group IDs managed by a user. FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) + // PageGroupRequest paginates through group requests for specified groups. PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) + // GetGroupRoleLevelMemberIDs retrieves user IDs of group members with a specific role level. GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) + // PageGetJoinGroup paginates through groups that a user has joined. PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) + // PageGetGroupMember paginates through members of a group. PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) + // SearchGroupMember searches for group members based on a keyword, group ID, and pagination settings. SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*relationtb.GroupMemberModel, error) + // HandlerGroupRequest processes a group join request with a specified result. HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error + // DeleteGroupMember removes specified users from a group. DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error + // MapGroupMemberUserID maps group IDs to their members' simplified user IDs. MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) + // MapGroupMemberNum maps group IDs to their member count. MapGroupMemberNum(ctx context.Context, groupIDs []string) (map[string]uint32, error) - TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error // 转让群 + // TransferGroupOwner transfers the ownership of a group to another user. + TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error + // UpdateGroupMember updates properties of a group member. UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error + // UpdateGroupMembers batch updates properties of group members. UpdateGroupMembers(ctx context.Context, data []*relationtb.BatchUpdateGroupMember) error - // GroupRequest + + // CreateGroupRequest creates new group join requests. CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error + // TakeGroupRequest retrieves a specific group join request. TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationtb.GroupRequestModel, error) + // FindGroupRequests retrieves multiple group join requests. FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupRequestModel, error) + // PageGroupRequestUser paginates through group join requests made by a user. PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) - // 获取群总数 + // CountTotal counts the total number of groups as of a certain date. CountTotal(ctx context.Context, before *time.Time) (count int64, err error) - // 获取范围内群增量 + // CountRangeEverydayTotal counts the daily group creation total within a specified date range. CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) + // DeleteGroupMemberHash deletes the hash entries for group members in specified groups. DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error } diff --git a/pkg/common/db/controller/msg.go b/pkg/common/db/controller/msg.go index 6441a090c..ccf209b7a 100644 --- a/pkg/common/db/controller/msg.go +++ b/pkg/common/db/controller/msg.go @@ -21,26 +21,20 @@ import ( "time" "github.com/OpenIMSDK/protocol/constant" - - "github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" - - "github.com/redis/go-redis/v9" - + pbmsg "github.com/OpenIMSDK/protocol/msg" + "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" - - "go.mongodb.org/mongo-driver/mongo" - + "github.com/OpenIMSDK/tools/utils" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/convert" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" "github.com/openimsdk/open-im-server/v3/pkg/common/kafka" - - pbmsg "github.com/OpenIMSDK/protocol/msg" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" + "github.com/redis/go-redis/v9" + "go.mongodb.org/mongo-driver/mongo" ) const ( @@ -48,33 +42,33 @@ const ( updateKeyRevoke ) +// CommonMsgDatabase defines the interface for message database operations. type CommonMsgDatabase interface { - // 批量插入消息 + // BatchInsertChat2DB inserts a batch of messages into the database for a specific conversation. BatchInsertChat2DB(ctx context.Context, conversationID string, msgs []*sdkws.MsgData, currentMaxSeq int64) error - // 撤回消息 + // RevokeMsg revokes a message in a conversation. RevokeMsg(ctx context.Context, conversationID string, seq int64, revoke *unrelationtb.RevokeModel) error - // mark as read + // MarkSingleChatMsgsAsRead marks messages as read for a single chat by sequence numbers. MarkSingleChatMsgsAsRead(ctx context.Context, userID string, conversationID string, seqs []int64) error - // 刪除redis中消息缓存 + // DeleteMessagesFromCache deletes message caches from Redis by sequence numbers. DeleteMessagesFromCache(ctx context.Context, conversationID string, seqs []int64) error + // DelUserDeleteMsgsList deletes user's message deletion list. DelUserDeleteMsgsList(ctx context.Context, conversationID string, seqs []int64) - // incrSeq然后批量插入缓存 + // BatchInsertChat2Cache increments the sequence number and then batch inserts messages into the cache. BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNewConversation bool, err error) - - // 通过seqList获取mongo中写扩散消息 + // GetMsgBySeqsRange retrieves messages from MongoDB by a range of sequence numbers. GetMsgBySeqsRange(ctx context.Context, userID string, conversationID string, begin, end, num, userMaxSeq int64) (minSeq int64, maxSeq int64, seqMsg []*sdkws.MsgData, err error) - // 通过seqList获取大群在 mongo里面的消息 + // GetMsgBySeqs retrieves messages for large groups from MongoDB by sequence numbers. GetMsgBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) (minSeq int64, maxSeq int64, seqMsg []*sdkws.MsgData, err error) - // 删除会话消息重置最小seq, remainTime为消息保留的时间单位秒,超时消息删除, 传0删除所有消息(此方法不删除redis cache) + // DeleteConversationMsgsAndSetMinSeq deletes conversation messages and resets the minimum sequence number. If `remainTime` is 0, all messages are deleted (this method does not delete Redis + // cache). DeleteConversationMsgsAndSetMinSeq(ctx context.Context, conversationID string, remainTime int64) error - // 用户标记删除过期消息返回标记删除的seq列表 + // UserMsgsDestruct marks messages for deletion based on destruct time and returns a list of sequence numbers for marked messages. UserMsgsDestruct(ctx context.Context, userID string, conversationID string, destructTime int64, lastMsgDestructTime time.Time) (seqs []int64, err error) - - // 用户根据seq删除消息 + // DeleteUserMsgsBySeqs allows a user to delete messages based on sequence numbers. DeleteUserMsgsBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) error - // 物理删除消息置空 + // DeleteMsgsPhysicalBySeqs physically deletes messages by emptying them based on sequence numbers. DeleteMsgsPhysicalBySeqs(ctx context.Context, conversationID string, seqs []int64) error - SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) GetMaxSeq(ctx context.Context, conversationID string) (int64, error) @@ -217,7 +211,7 @@ func (db *commonMsgDatabase) BatchInsertBlock(ctx context.Context, conversationI } num := db.msg.GetSingleGocMsgNum() // num = 100 - for i, field := range fields { // 检查类型 + for i, field := range fields { // Check the type of the field var ok bool switch key { case updateKeyMsg: @@ -235,7 +229,7 @@ func (db *commonMsgDatabase) BatchInsertBlock(ctx context.Context, conversationI return errs.ErrInternalServer.Wrap("field type is invalid") } } - // 返回值为true表示数据库存在该文档,false表示数据库不存在该文档 + // Returns true if the document exists in the database, false if the document does not exist in the database updateMsgModel := func(seq int64, i int) (bool, error) { var ( res *mongo.UpdateResult @@ -257,21 +251,21 @@ func (db *commonMsgDatabase) BatchInsertBlock(ctx context.Context, conversationI } tryUpdate := true for i := 0; i < len(fields); i++ { - seq := firstSeq + int64(i) // 当前seq + seq := firstSeq + int64(i) // Current sequence number if tryUpdate { matched, err := updateMsgModel(seq, i) if err != nil { return err } if matched { - continue // 匹配到了,继续下一个(不一定修改) + continue // The current data has been updated, skip the current data } } doc := unrelationtb.MsgDocModel{ DocID: db.msg.GetDocID(conversationID, seq), Msg: make([]*unrelationtb.MsgInfoModel, num), } - var insert int // 插入的数量 + var insert int // Inserted data number for j := i; j < len(fields); j++ { seq = firstSeq + int64(j) if db.msg.GetDocID(conversationID, seq) != doc.DocID { @@ -300,14 +294,14 @@ func (db *commonMsgDatabase) BatchInsertBlock(ctx context.Context, conversationI } if err := db.msgDocDatabase.Create(ctx, &doc); err != nil { if mongo.IsDuplicateKeyError(err) { - i-- // 存在并发,重试当前数据 - tryUpdate = true // 以修改模式 + i-- // already inserted + tryUpdate = true // next block use update mode continue } return err } - tryUpdate = false // 当前以插入成功,下一块优先插入模式 - i += insert - 1 // 跳过已插入的数据 + tryUpdate = false // The current block is inserted successfully, and the next block is inserted preferentially + i += insert - 1 // Skip the inserted data } return nil } @@ -771,7 +765,7 @@ func (db *commonMsgDatabase) UserMsgsDestruct(ctx context.Context, userID string log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index) } } - // 获取报错,或者获取不到了,物理删除并且返回seq delMongoMsgsPhysical(delStruct.delDocIDList), 结束递归 + // If an error is reported, or the error cannot be obtained, it is physically deleted and seq delMongoMsgsPhysical(delStruct.delDocIDList) is returned to end the recursion break } index++ @@ -826,7 +820,7 @@ func (d *delMsgRecursionStruct) getSetMinSeq() int64 { // index 0....19(del) 20...69 // seq 70 // set minSeq 21 -// recursion 删除list并且返回设置的最小seq. +// recursion deletes the list and returns the set minimum seq. func (db *commonMsgDatabase) deleteMsgRecursion(ctx context.Context, conversationID string, index int64, delStruct *delMsgRecursionStruct, remainTime int64) (int64, error) { // find from oldest list msgDocModel, err := db.msgDocDatabase.GetMsgDocModelByIndex(ctx, conversationID, index, 1) @@ -838,7 +832,7 @@ func (db *commonMsgDatabase) deleteMsgRecursion(ctx context.Context, conversatio log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index) } } - // 获取报错,或者获取不到了,物理删除并且返回seq delMongoMsgsPhysical(delStruct.delDocIDList), 结束递归 + // If an error is reported, or the error cannot be obtained, it is physically deleted and seq delMongoMsgsPhysical(delStruct.delDocIDList) is returned to end the recursion err = db.msgDocDatabase.DeleteDocs(ctx, delStruct.delDocIDs) if err != nil { return 0, err diff --git a/pkg/common/db/controller/s3.go b/pkg/common/db/controller/s3.go index 95505de41..e847c9c8f 100644 --- a/pkg/common/db/controller/s3.go +++ b/pkg/common/db/controller/s3.go @@ -19,12 +19,11 @@ import ( "path/filepath" "time" - "github.com/redis/go-redis/v9" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/cont" "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/redis/go-redis/v9" ) type S3Database interface { diff --git a/pkg/common/db/controller/third.go b/pkg/common/db/controller/third.go index fb5b0ccbe..996d82c45 100644 --- a/pkg/common/db/controller/third.go +++ b/pkg/common/db/controller/third.go @@ -19,7 +19,6 @@ import ( "time" "github.com/OpenIMSDK/tools/pagination" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) @@ -63,13 +62,7 @@ func NewThirdDatabase(cache cache.MsgModel, logdb relation.LogInterface) ThirdDa return &thirdDatabase{cache: cache, logdb: logdb} } -func (t *thirdDatabase) FcmUpdateToken( - ctx context.Context, - account string, - platformID int, - fcmToken string, - expireTime int64, -) error { +func (t *thirdDatabase) FcmUpdateToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) error { return t.cache.SetFcmToken(ctx, account, platformID, fcmToken, expireTime) } diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go index 8ba1c01d3..0e1bdd314 100644 --- a/pkg/common/db/controller/user.go +++ b/pkg/common/db/controller/user.go @@ -18,19 +18,14 @@ import ( "context" "time" - "github.com/OpenIMSDK/tools/pagination" - "github.com/OpenIMSDK/tools/tx" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" - "github.com/OpenIMSDK/protocol/user" - - unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" - "github.com/OpenIMSDK/tools/errs" + "github.com/OpenIMSDK/tools/pagination" + "github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" ) type UserDatabase interface { diff --git a/pkg/common/db/localcache/conversation.go b/pkg/common/db/localcache/conversation.go index c40bcdbce..9147fd3ce 100644 --- a/pkg/common/db/localcache/conversation.go +++ b/pkg/common/db/localcache/conversation.go @@ -19,7 +19,6 @@ import ( "sync" "github.com/OpenIMSDK/protocol/conversation" - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) diff --git a/pkg/common/db/localcache/group.go b/pkg/common/db/localcache/group.go index 4958d91ee..0fdea8642 100644 --- a/pkg/common/db/localcache/group.go +++ b/pkg/common/db/localcache/group.go @@ -20,7 +20,6 @@ import ( "github.com/OpenIMSDK/protocol/group" "github.com/OpenIMSDK/tools/errs" - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) diff --git a/pkg/common/db/mgo/black.go b/pkg/common/db/mgo/black.go index 1047e5c30..c555e0b77 100644 --- a/pkg/common/db/mgo/black.go +++ b/pkg/common/db/mgo/black.go @@ -19,11 +19,10 @@ import ( "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) func NewBlackMongo(db *mongo.Database) (relation.BlackModelInterface, error) { diff --git a/pkg/common/db/mgo/conversation.go b/pkg/common/db/mgo/conversation.go index d0a46ae47..35e8a28e6 100644 --- a/pkg/common/db/mgo/conversation.go +++ b/pkg/common/db/mgo/conversation.go @@ -18,16 +18,14 @@ import ( "context" "time" - "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/protocol/constant" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) func NewConversationMongo(db *mongo.Database) (*ConversationMgo, error) { diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go index 851db6157..aa7775ce0 100644 --- a/pkg/common/db/mgo/friend.go +++ b/pkg/common/db/mgo/friend.go @@ -19,12 +19,10 @@ import ( "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" - "go.mongodb.org/mongo-driver/mongo/options" - + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "go.mongodb.org/mongo-driver/mongo/options" ) // FriendMgo implements FriendModelInterface using MongoDB as the storage backend. diff --git a/pkg/common/db/mgo/friend_request.go b/pkg/common/db/mgo/friend_request.go index bfc101917..3e0588a0b 100644 --- a/pkg/common/db/mgo/friend_request.go +++ b/pkg/common/db/mgo/friend_request.go @@ -19,12 +19,10 @@ import ( "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" - "go.mongodb.org/mongo-driver/mongo/options" - + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "go.mongodb.org/mongo-driver/mongo/options" ) func NewFriendRequestMongo(db *mongo.Database) (relation.FriendRequestModelInterface, error) { diff --git a/pkg/common/db/mgo/group.go b/pkg/common/db/mgo/group.go index 922bfd424..1bef90ebe 100644 --- a/pkg/common/db/mgo/group.go +++ b/pkg/common/db/mgo/group.go @@ -19,14 +19,12 @@ import ( "time" "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) func NewGroupMongo(db *mongo.Database) (relation.GroupModelInterface, error) { diff --git a/pkg/common/db/mgo/group_member.go b/pkg/common/db/mgo/group_member.go index e28432b11..e1af34f7c 100644 --- a/pkg/common/db/mgo/group_member.go +++ b/pkg/common/db/mgo/group_member.go @@ -17,16 +17,14 @@ package mgo import ( "context" - "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/protocol/constant" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) func NewGroupMember(db *mongo.Database) (relation.GroupMemberModelInterface, error) { diff --git a/pkg/common/db/mgo/group_request.go b/pkg/common/db/mgo/group_request.go index d20682239..9aee0e960 100644 --- a/pkg/common/db/mgo/group_request.go +++ b/pkg/common/db/mgo/group_request.go @@ -18,14 +18,12 @@ import ( "context" "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) func NewGroupRequestMgo(db *mongo.Database) (relation.GroupRequestModelInterface, error) { diff --git a/pkg/common/db/mgo/log.go b/pkg/common/db/mgo/log.go index 09f002ee3..ca28d5964 100644 --- a/pkg/common/db/mgo/log.go +++ b/pkg/common/db/mgo/log.go @@ -20,11 +20,10 @@ import ( "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) func NewLogMongo(db *mongo.Database) (relation.LogInterface, error) { diff --git a/pkg/common/db/mgo/object.go b/pkg/common/db/mgo/object.go index 88bfde213..4c333afd6 100644 --- a/pkg/common/db/mgo/object.go +++ b/pkg/common/db/mgo/object.go @@ -18,11 +18,10 @@ import ( "context" "github.com/OpenIMSDK/tools/mgoutil" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) func NewS3Mongo(db *mongo.Database) (relation.ObjectInfoModelInterface, error) { diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go index 2797bc53f..dcdc14d4a 100644 --- a/pkg/common/db/mgo/user.go +++ b/pkg/common/db/mgo/user.go @@ -20,15 +20,13 @@ import ( "github.com/OpenIMSDK/protocol/user" "github.com/OpenIMSDK/tools/errs" - "go.mongodb.org/mongo-driver/bson/primitive" - "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" ) func NewUserMongo(db *mongo.Database) (relation.UserModelInterface, error) { diff --git a/pkg/common/db/s3/aws/aws.go b/pkg/common/db/s3/aws/aws.go index ba0c1e984..150f595c7 100644 --- a/pkg/common/db/s3/aws/aws.go +++ b/pkg/common/db/s3/aws/aws.go @@ -27,7 +27,6 @@ import ( "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" sdk "github.com/aws/aws-sdk-go/service/s3" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" ) @@ -65,10 +64,10 @@ func NewAWS() (s3.Interface, error) { credential := credentials.NewStaticCredentials( conf.AccessKeyID, // accessKey conf.AccessKeySecret, // secretKey - "") // sts的临时凭证 + "") // stoken sess, err := session.NewSession(&aws.Config{ - Region: aws.String(conf.Region), // 桶所在的区域 + Region: aws.String(conf.Region), // The area where the bucket is located Credentials: credential, }) diff --git a/pkg/common/db/s3/cont/consts.go b/pkg/common/db/s3/cont/consts.go index a01a8312c..b51878e49 100644 --- a/pkg/common/db/s3/cont/consts.go +++ b/pkg/common/db/s3/cont/consts.go @@ -15,10 +15,24 @@ package cont const ( - hashPath = "openim/data/hash/" - tempPath = "openim/temp/" - DirectPath = "openim/direct" - UploadTypeMultipart = 1 // 分片上传 - UploadTypePresigned = 2 // 预签名上传 - partSeparator = "," + // hashPath defines the storage path for hash data within the 'openim' directory. + hashPath = "openim/data/hash/" + + // tempPath specifies the directory for temporary files in the 'openim' structure. + tempPath = "openim/temp/" + + // DirectPath indicates the directory for direct uploads or access within the 'openim' structure. + DirectPath = "openim/direct" + + // UploadTypeMultipart represents the identifier for multipart uploads, + // allowing large files to be uploaded in chunks. + UploadTypeMultipart = 1 + + // UploadTypePresigned signifies the use of presigned URLs for uploads, + // facilitating secure, authorized file transfers without requiring direct access to the storage credentials. + UploadTypePresigned = 2 + + // partSeparator is used as a delimiter in multipart upload processes, + // separating individual file parts. + partSeparator = "," ) diff --git a/pkg/common/db/s3/cont/controller.go b/pkg/common/db/s3/cont/controller.go index e0048817b..6b5a50d3e 100644 --- a/pkg/common/db/s3/cont/controller.go +++ b/pkg/common/db/s3/cont/controller.go @@ -24,13 +24,10 @@ import ( "strings" "time" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" - - "github.com/google/uuid" - "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" - + "github.com/google/uuid" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" ) @@ -120,7 +117,7 @@ func (c *Controller) InitiateUpload(ctx context.Context, hash string, size int64 } if size <= partSize { - // 预签名上传 + // Pre-signed upload key := path.Join(tempPath, c.NowPath(), fmt.Sprintf("%s_%d_%s.presigned", hash, size, c.UUID())) rawURL, err := c.impl.PresignedPutObject(ctx, key, expire) if err != nil { @@ -145,7 +142,7 @@ func (c *Controller) InitiateUpload(ctx context.Context, hash string, size int64 }, }, nil } else { - // 分片上传 + // Fragment upload upload, err := c.impl.InitiateMultipartUpload(ctx, c.HashPath(hash)) if err != nil { return nil, err @@ -212,7 +209,7 @@ func (c *Controller) CompleteUpload(ctx context.Context, uploadID string, partHa ETag: part, } } - // todo: 验证大小 + // todo: Validation size result, err := c.impl.CompleteMultipartUpload(ctx, upload.ID, upload.Key, parts) if err != nil { return nil, err @@ -231,7 +228,7 @@ func (c *Controller) CompleteUpload(ctx context.Context, uploadID string, partHa if md5val := hex.EncodeToString(md5Sum[:]); md5val != upload.Hash { return nil, errs.ErrArgs.Wrap(fmt.Sprintf("md5 mismatching %s != %s", md5val, upload.Hash)) } - // 防止在这个时候,并发操作,导致文件被覆盖 + // Prevents concurrent operations at this time that cause files to be overwritten copyInfo, err := c.impl.CopyObject(ctx, uploadInfo.Key, upload.Key+"."+c.UUID()) if err != nil { return nil, err diff --git a/pkg/common/db/s3/cont/structs.go b/pkg/common/db/s3/cont/structs.go index ff5ca7943..de484cc5f 100644 --- a/pkg/common/db/s3/cont/structs.go +++ b/pkg/common/db/s3/cont/structs.go @@ -17,9 +17,14 @@ package cont import "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" type InitiateUploadResult struct { - UploadID string `json:"uploadID"` // 上传ID - PartSize int64 `json:"partSize"` // 分片大小 - Sign *s3.AuthSignResult `json:"sign"` // 分片信息 + // UploadID uniquely identifies the upload session for tracking and management purposes. + UploadID string `json:"uploadID"` + + // PartSize specifies the size of each part in a multipart upload. This is relevant for breaking down large uploads into manageable pieces. + PartSize int64 `json:"partSize"` + + // Sign contains the authentication and signature information necessary for securely uploading each part. This could include signed URLs or tokens. + Sign *s3.AuthSignResult `json:"sign"` } type UploadResult struct { diff --git a/pkg/common/db/s3/cos/cos.go b/pkg/common/db/s3/cos/cos.go index d44d1407d..fba0ba8fc 100644 --- a/pkg/common/db/s3/cos/cos.go +++ b/pkg/common/db/s3/cos/cos.go @@ -29,10 +29,9 @@ import ( "strings" "time" - "github.com/tencentyun/cos-go-sdk-v5" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" + "github.com/tencentyun/cos-go-sdk-v5" ) const ( diff --git a/pkg/common/db/s3/minio/image.go b/pkg/common/db/s3/minio/image.go index 71db1ea51..f363f94b1 100644 --- a/pkg/common/db/s3/minio/image.go +++ b/pkg/common/db/s3/minio/image.go @@ -42,79 +42,51 @@ func ImageWidthHeight(img image.Image) (int, int) { return bounds.X, bounds.Y } +// resizeImage resizes an image to a specified maximum width and height, maintaining the aspect ratio. +// If both maxWidth and maxHeight are set to 0, the original image is returned. +// If both are non-zero, the image is scaled to fit within the constraints while maintaining aspect ratio. +// If only one of maxWidth or maxHeight is non-zero, the image is scaled accordingly. func resizeImage(img image.Image, maxWidth, maxHeight int) image.Image { bounds := img.Bounds() - imgWidth := bounds.Max.X - imgHeight := bounds.Max.Y + imgWidth, imgHeight := bounds.Dx(), bounds.Dy() - // 计算缩放比例 - scaleWidth := float64(maxWidth) / float64(imgWidth) - scaleHeight := float64(maxHeight) / float64(imgHeight) - - // 如果都为0,则不缩放,返回原始图片 + // Return original image if no resizing is needed. if maxWidth == 0 && maxHeight == 0 { return img } - // 如果宽度和高度都大于0,则选择较小的缩放比例,以保持宽高比 + var scale float64 = 1 if maxWidth > 0 && maxHeight > 0 { - scale := scaleWidth - if scaleHeight < scaleWidth { - scale = scaleHeight - } - - // 计算缩略图尺寸 - thumbnailWidth := int(float64(imgWidth) * scale) - thumbnailHeight := int(float64(imgHeight) * scale) - - // 使用"image"库的Resample方法生成缩略图 - thumbnail := image.NewRGBA(image.Rect(0, 0, thumbnailWidth, thumbnailHeight)) - for y := 0; y < thumbnailHeight; y++ { - for x := 0; x < thumbnailWidth; x++ { - srcX := int(float64(x) / scale) - srcY := int(float64(y) / scale) - thumbnail.Set(x, y, img.At(srcX, srcY)) - } - } - - return thumbnail + scaleWidth := float64(maxWidth) / float64(imgWidth) + scaleHeight := float64(maxHeight) / float64(imgHeight) + // Choose the smaller scale to fit both constraints. + scale = min(scaleWidth, scaleHeight) + } else if maxWidth > 0 { + scale = float64(maxWidth) / float64(imgWidth) + } else if maxHeight > 0 { + scale = float64(maxHeight) / float64(imgHeight) } - // 如果只指定了宽度或高度,则根据最大不超过的规则生成缩略图 - if maxWidth > 0 { - thumbnailWidth := maxWidth - thumbnailHeight := int(float64(imgHeight) * scaleWidth) + newWidth := int(float64(imgWidth) * scale) + newHeight := int(float64(imgHeight) * scale) - // 使用"image"库的Resample方法生成缩略图 - thumbnail := image.NewRGBA(image.Rect(0, 0, thumbnailWidth, thumbnailHeight)) - for y := 0; y < thumbnailHeight; y++ { - for x := 0; x < thumbnailWidth; x++ { - srcX := int(float64(x) / scaleWidth) - srcY := int(float64(y) / scaleWidth) - thumbnail.Set(x, y, img.At(srcX, srcY)) - } + // Resize the image by creating a new image and manually copying pixels. + thumbnail := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight)) + for y := 0; y < newHeight; y++ { + for x := 0; x < newWidth; x++ { + srcX := int(float64(x) / scale) + srcY := int(float64(y) / scale) + thumbnail.Set(x, y, img.At(srcX, srcY)) } - - return thumbnail } - if maxHeight > 0 { - thumbnailWidth := int(float64(imgWidth) * scaleHeight) - thumbnailHeight := maxHeight - - // 使用"image"库的Resample方法生成缩略图 - thumbnail := image.NewRGBA(image.Rect(0, 0, thumbnailWidth, thumbnailHeight)) - for y := 0; y < thumbnailHeight; y++ { - for x := 0; x < thumbnailWidth; x++ { - srcX := int(float64(x) / scaleHeight) - srcY := int(float64(y) / scaleHeight) - thumbnail.Set(x, y, img.At(srcX, srcY)) - } - } + return thumbnail +} - return thumbnail +// min returns the smaller of x or y. +func min(x, y float64) float64 { + if x < y { + return x } - - // 默认情况下,返回原始图片 - return img + return y } diff --git a/pkg/common/db/s3/minio/minio.go b/pkg/common/db/s3/minio/minio.go index c5a73550c..16315ab8e 100644 --- a/pkg/common/db/s3/minio/minio.go +++ b/pkg/common/db/s3/minio/minio.go @@ -29,14 +29,12 @@ import ( "time" "unsafe" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" - "github.com/OpenIMSDK/tools/log" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "github.com/minio/minio-go/v7/pkg/signer" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" ) diff --git a/pkg/common/db/s3/minio/thumbnail.go b/pkg/common/db/s3/minio/thumbnail.go index 5dfdaee09..1bf96c27c 100644 --- a/pkg/common/db/s3/minio/thumbnail.go +++ b/pkg/common/db/s3/minio/thumbnail.go @@ -31,7 +31,6 @@ import ( "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" "github.com/minio/minio-go/v7" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" ) diff --git a/pkg/common/db/s3/oss/oss.go b/pkg/common/db/s3/oss/oss.go index 4a74e9b95..84d9bfa19 100644 --- a/pkg/common/db/s3/oss/oss.go +++ b/pkg/common/db/s3/oss/oss.go @@ -30,8 +30,8 @@ import ( "strings" "time" + "github.com/OpenIMSDK/tools/errs" "github.com/aliyun/aliyun-oss-go-sdk/oss" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" ) @@ -60,7 +60,7 @@ const successCode = http.StatusOK func NewOSS(config *config.GlobalConfig) (s3.Interface, error) { conf := config.Object.Oss if conf.BucketURL == "" { - return nil, errors.New("bucket url is empty") + return nil, errs.Wrap(errors.New("bucket url is empty")) } client, err := oss.New(conf.Endpoint, conf.AccessKeyID, conf.AccessKeySecret) if err != nil { @@ -68,7 +68,7 @@ func NewOSS(config *config.GlobalConfig) (s3.Interface, error) { } bucket, err := client.Bucket(conf.Bucket) if err != nil { - return nil, err + return nil, errs.Wrap(err, "ali-oss bucket error") } if conf.BucketURL[len(conf.BucketURL)-1] != '/' { conf.BucketURL += "/" @@ -140,10 +140,10 @@ func (o *OSS) CompleteMultipartUpload(ctx context.Context, uploadID string, name func (o *OSS) PartSize(ctx context.Context, size int64) (int64, error) { if size <= 0 { - return 0, errors.New("size must be greater than 0") + return 0, errs.Wrap(errors.New("size must be greater than 0")) } if size > maxPartSize*maxNumSize { - return 0, fmt.Errorf("OSS size must be less than the maximum allowed limit") + return 0, errs.Wrap(errors.New("size must be less than the maximum allowed limit")) } if size <= minPartSize*maxNumSize { return minPartSize, nil @@ -198,25 +198,25 @@ func (o *OSS) StatObject(ctx context.Context, name string) (*s3.ObjectInfo, erro } res := &s3.ObjectInfo{Key: name} if res.ETag = strings.ToLower(strings.ReplaceAll(header.Get("ETag"), `"`, ``)); res.ETag == "" { - return nil, errors.New("StatObject etag not found") + return nil, errs.Wrap(errors.New("StatObject etag not found")) } if contentLengthStr := header.Get("Content-Length"); contentLengthStr == "" { return nil, errors.New("StatObject content-length not found") } else { res.Size, err = strconv.ParseInt(contentLengthStr, 10, 64) if err != nil { - return nil, fmt.Errorf("StatObject content-length parse error: %w", err) + return nil, errs.Wrap(err, "StatObject content-length parse error") } if res.Size < 0 { - return nil, errors.New("StatObject content-length must be greater than 0") + return nil, errs.Wrap(errors.New("StatObject content-length must be greater than 0")) } } if lastModified := header.Get("Last-Modified"); lastModified == "" { - return nil, errors.New("StatObject last-modified not found") + return nil, errs.Wrap(errors.New("StatObject last-modified not found")) } else { res.LastModified, err = time.Parse(http.TimeFormat, lastModified) if err != nil { - return nil, fmt.Errorf("StatObject last-modified parse error: %w", err) + return nil, errs.Wrap(err, "StatObject last-modified parse error") } } return res, nil @@ -229,7 +229,7 @@ func (o *OSS) DeleteObject(ctx context.Context, name string) error { func (o *OSS) CopyObject(ctx context.Context, src string, dst string) (*s3.CopyObjectInfo, error) { result, err := o.bucket.CopyObject(src, dst) if err != nil { - return nil, err + return nil, errs.Wrap(err, "CopyObject error") } return &s3.CopyObjectInfo{ Key: dst, @@ -263,7 +263,7 @@ func (o *OSS) ListUploadedParts(ctx context.Context, uploadID string, name strin Bucket: o.bucket.BucketName, }, oss.MaxUploads(100), oss.MaxParts(maxParts), oss.PartNumberMarker(partNumberMarker)) if err != nil { - return nil, err + return nil, errs.Wrap(err, "ListUploadedParts error") } res := &s3.ListUploadedPartsResult{ Key: result.Key, @@ -288,7 +288,7 @@ func (o *OSS) AccessURL(ctx context.Context, name string, expire time.Duration, var opts []oss.Option if opt != nil { if opt.Image != nil { - // 文档地址: https://help.aliyun.com/zh/oss/user-guide/resize-images-4?spm=a2c4g.11186623.0.0.4b3b1e4fWW6yji + // Docs Address: https://help.aliyun.com/zh/oss/user-guide/resize-images-4?spm=a2c4g.11186623.0.0.4b3b1e4fWW6yji var format string switch opt.Image.Format { case @@ -331,7 +331,7 @@ func (o *OSS) AccessURL(ctx context.Context, name string, expire time.Duration, } rawParams, err := oss.GetRawParams(opts) if err != nil { - return "", err + return "", errs.Wrap(err, "AccessURL error") } params := getURLParams(*o.bucket.Client.Conn, rawParams) return getURL(o.um, o.bucket.BucketName, name, params).String(), nil @@ -353,12 +353,12 @@ func (o *OSS) FormData(ctx context.Context, name string, size int64, contentType } policyJson, err := json.Marshal(policy) if err != nil { - return nil, err + return nil, errs.Wrap(err, "Marshal json error") } policyStr := base64.StdEncoding.EncodeToString(policyJson) h := hmac.New(sha1.New, []byte(o.credentials.GetAccessKeySecret())) if _, err := io.WriteString(h, policyStr); err != nil { - return nil, err + return nil, errs.Wrap(err, "WriteString error") } fd := &s3.FormData{ URL: o.bucketURL, diff --git a/pkg/common/db/table/relation/group.go b/pkg/common/db/table/relation/group.go index 57d6b1d62..1f969cd4f 100644 --- a/pkg/common/db/table/relation/group.go +++ b/pkg/common/db/table/relation/group.go @@ -46,8 +46,8 @@ type GroupModelInterface interface { Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error) Take(ctx context.Context, groupID string) (group *GroupModel, err error) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*GroupModel, err error) - // 获取群总数 + // Get Group total quantity CountTotal(ctx context.Context, before *time.Time) (count int64, err error) - // 获取范围内群增量 + // Get Group total quantity every day CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) } diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go index dbb2ff464..375930ddf 100644 --- a/pkg/common/db/table/relation/user.go +++ b/pkg/common/db/table/relation/user.go @@ -19,7 +19,6 @@ import ( "time" "github.com/OpenIMSDK/protocol/user" - "github.com/OpenIMSDK/tools/pagination" ) @@ -62,9 +61,9 @@ type UserModelInterface interface { Exist(ctx context.Context, userID string) (exist bool, err error) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) - // 获取用户总数 + // Get user total quantity CountTotal(ctx context.Context, before *time.Time) (count int64, err error) - // 获取范围内用户增量 + // Get user total quantity every day CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) //CRUD user command AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string, ex string) error diff --git a/pkg/common/db/table/unrelation/msg.go b/pkg/common/db/table/unrelation/msg.go index c95b211a8..60dd7c260 100644 --- a/pkg/common/db/table/unrelation/msg.go +++ b/pkg/common/db/table/unrelation/msg.go @@ -20,10 +20,8 @@ import ( "time" "github.com/OpenIMSDK/protocol/msg" - - "go.mongodb.org/mongo-driver/mongo" - "github.com/OpenIMSDK/protocol/sdkws" + "go.mongodb.org/mongo-driver/mongo" ) const ( diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go index 8e2403b64..363e97867 100644 --- a/pkg/common/db/unrelation/mongo.go +++ b/pkg/common/db/unrelation/mongo.go @@ -21,15 +21,13 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/mw/specialerror" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" ) const ( diff --git a/pkg/common/db/unrelation/msg.go b/pkg/common/db/unrelation/msg.go index bc9118a9a..4deca56f8 100644 --- a/pkg/common/db/unrelation/msg.go +++ b/pkg/common/db/unrelation/msg.go @@ -21,22 +21,17 @@ import ( "fmt" "time" - "github.com/OpenIMSDK/tools/log" - - "github.com/OpenIMSDK/protocol/msg" - "github.com/OpenIMSDK/protocol/constant" - + "github.com/OpenIMSDK/protocol/msg" + "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/tools/errs" + "github.com/OpenIMSDK/tools/log" + table "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "google.golang.org/protobuf/proto" - - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/errs" - - table "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" ) var ErrMsgListNotExist = errors.New("user not have msg in mongoDB") @@ -122,13 +117,7 @@ func (m *MsgMongoDriver) UpdateMsgContent(ctx context.Context, docID string, ind return nil } -func (m *MsgMongoDriver) UpdateMsgStatusByIndexInOneDoc( - ctx context.Context, - docID string, - msg *sdkws.MsgData, - seqIndex int, - status int32, -) error { +func (m *MsgMongoDriver) UpdateMsgStatusByIndexInOneDoc(ctx context.Context, docID string, msg *sdkws.MsgData, seqIndex int, status int32) error { msg.Status = status bytes, err := proto.Marshal(msg) if err != nil { @@ -140,7 +129,7 @@ func (m *MsgMongoDriver) UpdateMsgStatusByIndexInOneDoc( bson.M{"$set": bson.M{fmt.Sprintf("msgs.%d.msg", seqIndex): bytes}}, ) if err != nil { - return errs.Wrap(err) + return errs.Wrap(err, fmt.Sprintf("docID is %s, seqIndex is %d", docID, seqIndex)) } return nil } @@ -166,7 +155,7 @@ func (m *MsgMongoDriver) GetMsgDocModelByIndex( findOpts, ) if err != nil { - return nil, errs.Wrap(err) + return nil, errs.Wrap(err, fmt.Sprintf("conversationID is %s", conversationID)) } var msgs []table.MsgDocModel err = cursor.All(ctx, &msgs) @@ -222,7 +211,7 @@ func (m *MsgMongoDriver) DeleteMsgsInOneDocByIndex(ctx context.Context, docID st } _, err := m.MsgCollection.UpdateMany(ctx, bson.M{"doc_id": docID}, updates) if err != nil { - return errs.Wrap(err) + return errs.Wrap(err, fmt.Sprintf("docID is %s, indexes is %v", docID, indexes)) } return nil } @@ -289,7 +278,7 @@ func (m *MsgMongoDriver) GetMsgBySeqIndexIn1Doc( defer cur.Close(ctx) var msgDocModel []table.MsgDocModel if err := cur.All(ctx, &msgDocModel); err != nil { - return nil, errs.Wrap(err) + return nil, errs.Wrap(err, fmt.Sprintf("docID is %s, seqs is %v", docID, seqs)) } if len(msgDocModel) == 0 { return nil, errs.Wrap(mongo.ErrNoDocuments) @@ -316,14 +305,14 @@ func (m *MsgMongoDriver) GetMsgBySeqIndexIn1Doc( } data, err := json.Marshal(&revokeContent) if err != nil { - return nil, err + return nil, errs.Wrap(err, fmt.Sprintf("docID is %s, seqs is %v", docID, seqs)) } elem := sdkws.NotificationElem{ Detail: string(data), } content, err := json.Marshal(&elem) if err != nil { - return nil, err + return nil, errs.Wrap(err, fmt.Sprintf("docID is %s, seqs is %v", docID, seqs)) } msg.Msg.ContentType = constant.MsgRevokeNotification msg.Msg.Content = string(content) @@ -336,17 +325,12 @@ func (m *MsgMongoDriver) GetMsgBySeqIndexIn1Doc( func (m *MsgMongoDriver) IsExistDocID(ctx context.Context, docID string) (bool, error) { count, err := m.MsgCollection.CountDocuments(ctx, bson.M{"doc_id": docID}) if err != nil { - return false, errs.Wrap(err) + return false, errs.Wrap(err, fmt.Sprintf("docID is %s", docID)) } return count > 0, nil } -func (m *MsgMongoDriver) MarkSingleChatMsgsAsRead( - ctx context.Context, - userID string, - docID string, - indexes []int64, -) error { +func (m *MsgMongoDriver) MarkSingleChatMsgsAsRead(ctx context.Context, userID string, docID string, indexes []int64) error { updates := []mongo.WriteModel{} for _, index := range indexes { filter := bson.M{ @@ -366,7 +350,7 @@ func (m *MsgMongoDriver) MarkSingleChatMsgsAsRead( updates = append(updates, updateModel) } _, err := m.MsgCollection.BulkWrite(ctx, updates) - return err + return errs.Wrap(err, fmt.Sprintf("docID is %s, indexes is %v", docID, indexes)) } // RangeUserSendCount @@ -662,7 +646,7 @@ func (m *MsgMongoDriver) RangeUserSendCount( "$dateToString": bson.M{ "format": "%Y-%m-%d", "date": bson.M{ - "$toDate": "$$item.msg.send_time", // 毫秒时间戳 + "$toDate": "$$item.msg.send_time", // Millisecond timestamp }, }, }, @@ -911,7 +895,7 @@ func (m *MsgMongoDriver) RangeGroupSendCount( "$dateToString": bson.M{ "format": "%Y-%m-%d", "date": bson.M{ - "$toDate": "$$item.msg.send_time", // 毫秒时间戳 + "$toDate": "$$item.msg.send_time", // Millisecond timestamp }, }, }, @@ -1076,6 +1060,7 @@ func (m *MsgMongoDriver) searchMessage(ctx context.Context, req *msg.SearchMessa var pipe mongo.Pipeline condition := bson.A{} if req.SendTime != "" { + // Changed to keyed fields for bson.M to avoid govet errors condition = append(condition, bson.M{"$eq": bson.A{bson.M{"$dateToString": bson.M{"format": "%Y-%m-%d", "date": bson.M{"$toDate": "$$item.msg.send_time"}}}, req.SendTime}}) } if req.MsgType != 0 { @@ -1092,62 +1077,26 @@ func (m *MsgMongoDriver) searchMessage(ctx context.Context, req *msg.SearchMessa } or := bson.A{ - bson.M{ - "doc_id": bson.M{ - "$regex": "^si_", - "$options": "i", - }, - }, + bson.M{"doc_id": bson.M{"$regex": "^si_", "$options": "i"}}, + bson.M{"doc_id": bson.M{"$regex": "^g_", "$options": "i"}}, + bson.M{"doc_id": bson.M{"$regex": "^sg_", "$options": "i"}}, } - or = append(or, - bson.M{ - "doc_id": bson.M{ - "$regex": "^g_", - "$options": "i", - }, - }, - bson.M{ - "doc_id": bson.M{ - "$regex": "^sg_", - "$options": "i", - }, - }, - ) + // Use bson.D with keyed fields to specify the order explicitly pipe = mongo.Pipeline{ - { - {"$match", bson.D{ - { - "$or", or, - }, - }}, - }, - { - {"$project", bson.D{ - { - "msgs", bson.D{ - { - "$filter", bson.D{ - {"input", "$msgs"}, - {"as", "item"}, - { - "cond", bson.D{ - {"$and", condition}, - }, - }, - }, - }, - }, - }, - {"doc_id", 1}, + {{"$match", bson.D{{Key: "$or", Value: or}}}}, + {{"$project", bson.D{ + {Key: "msgs", Value: bson.D{ + {Key: "$filter", Value: bson.D{ + {Key: "input", Value: "$msgs"}, + {Key: "as", Value: "item"}, + {Key: "cond", Value: bson.D{{Key: "$and", Value: condition}}}, + }}, }}, - }, - { - {"$unwind", bson.M{"path": "$msgs"}}, - }, - { - {"$sort", bson.M{"msgs.msg.send_time": -1}}, - }, + {Key: "doc_id", Value: 1}, + }}}, + {{"$unwind", bson.M{"path": "$msgs"}}}, + {{"$sort", bson.M{"msgs.msg.send_time": -1}}}, } cursor, err := m.MsgCollection.Aggregate(ctx, pipe) if err != nil { @@ -1160,12 +1109,12 @@ func (m *MsgMongoDriver) searchMessage(ctx context.Context, req *msg.SearchMessa var msgsDocs []docModel err = cursor.All(ctx, &msgsDocs) if err != nil { - return 0, nil, err + return 0, nil, errs.Wrap(err, "cursor.All msgsDocs") } log.ZDebug(ctx, "query mongoDB", "result", msgsDocs) msgs := make([]*table.MsgInfoModel, 0) - for index := range msgsDocs { - msgInfo := msgsDocs[index].Msg + for _, doc := range msgsDocs { + msgInfo := doc.Msg if msgInfo == nil || msgInfo.Msg == nil { continue } @@ -1185,14 +1134,12 @@ func (m *MsgMongoDriver) searchMessage(ctx context.Context, req *msg.SearchMessa } data, err := json.Marshal(&revokeContent) if err != nil { - return 0, nil, err - } - elem := sdkws.NotificationElem{ - Detail: string(data), + return 0, nil, errs.Wrap(err, "json.Marshal revokeContent") } + elem := sdkws.NotificationElem{Detail: string(data)} content, err := json.Marshal(&elem) if err != nil { - return 0, nil, err + return 0, nil, errs.Wrap(err, "json.Marshal elem") } msgInfo.Msg.ContentType = constant.MsgRevokeNotification msgInfo.Msg.Content = string(content) @@ -1203,7 +1150,8 @@ func (m *MsgMongoDriver) searchMessage(ctx context.Context, req *msg.SearchMessa n := int32(len(msgs)) if start >= n { return n, []*table.MsgInfoModel{}, nil - } else if start+req.Pagination.ShowNumber < n { + } + if start+req.Pagination.ShowNumber < n { msgs = msgs[start : start+req.Pagination.ShowNumber] } else { msgs = msgs[start:] diff --git a/pkg/common/db/unrelation/msg_convert.go b/pkg/common/db/unrelation/msg_convert.go index 373bc843e..30c74e927 100644 --- a/pkg/common/db/unrelation/msg_convert.go +++ b/pkg/common/db/unrelation/msg_convert.go @@ -19,10 +19,9 @@ import ( "fmt" "github.com/OpenIMSDK/tools/log" + table "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" - - table "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" ) func (m *MsgMongoDriver) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string) { diff --git a/pkg/common/db/unrelation/user.go b/pkg/common/db/unrelation/user.go index 4c882fc64..cbf395bf8 100644 --- a/pkg/common/db/unrelation/user.go +++ b/pkg/common/db/unrelation/user.go @@ -18,11 +18,10 @@ import ( "context" "github.com/OpenIMSDK/tools/errs" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" ) // prefixes and suffixes. diff --git a/pkg/common/discoveryregister/direct/directconn.go b/pkg/common/discoveryregister/direct/directconn.go index 3493a86bf..ced209602 100644 --- a/pkg/common/discoveryregister/direct/directconn.go +++ b/pkg/common/discoveryregister/direct/directconn.go @@ -20,10 +20,9 @@ import ( "fmt" "github.com/OpenIMSDK/tools/errs" + config2 "github.com/openimsdk/open-im-server/v3/pkg/common/config" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - - config2 "github.com/openimsdk/open-im-server/v3/pkg/common/config" ) type ServiceAddresses map[string][]int @@ -107,7 +106,7 @@ func (cd *ConnDirect) GetConns(ctx context.Context, } if len(connections) == 0 { - return nil, fmt.Errorf("no connections found for service: %s", serviceName) + return nil, errs.Wrap(errors.New("no connections found for service"), "serviceName", serviceName) } return connections, nil } @@ -157,10 +156,11 @@ func (cd *ConnDirect) dialService(ctx context.Context, address string, opts ...g conn, err := grpc.DialContext(ctx, cd.resolverDirect.Scheme()+":///"+address, options...) if err != nil { - return nil, err + return nil, errs.Wrap(err, "address", address) } return conn, nil } + func (cd *ConnDirect) dialServiceWithoutResolver(ctx context.Context, address string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { options := append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) conn, err := grpc.DialContext(ctx, address, options...) diff --git a/pkg/common/discoveryregister/discoveryregister.go b/pkg/common/discoveryregister/discoveryregister.go index c286d6b4a..c43583a80 100644 --- a/pkg/common/discoveryregister/discoveryregister.go +++ b/pkg/common/discoveryregister/discoveryregister.go @@ -19,12 +19,11 @@ import ( "github.com/openimsdk/open-im-server/v3/pkg/common/config" "os" + "github.com/OpenIMSDK/tools/discoveryregistry" + "github.com/OpenIMSDK/tools/errs" "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/direct" - "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/kubernetes" "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/zookeeper" - - "github.com/OpenIMSDK/tools/discoveryregistry" ) // NewDiscoveryRegister creates a new service discovery and registry client based on the provided environment type. @@ -42,6 +41,6 @@ func NewDiscoveryRegister(config *config.GlobalConfig) (discoveryregistry.SvcDis case "direct": return direct.NewConnDirect(config) default: - return nil, errors.New("envType not correct") + return nil, errs.Wrap(errors.New("envType not correct")) } } diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go index d11e4dd6d..b5d603fd1 100644 --- a/pkg/common/discoveryregister/kubernetes/kubernetes.go +++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go @@ -193,5 +193,5 @@ func (cli *K8sDR) GetClientLocalConns() map[string][]*grpc.ClientConn { return nil } func (cli *K8sDR) Close() { - return + } diff --git a/pkg/common/discoveryregister/zookeeper/zookeeper.go b/pkg/common/discoveryregister/zookeeper/zookeeper.go index 413a0a9e2..0aa40a907 100644 --- a/pkg/common/discoveryregister/zookeeper/zookeeper.go +++ b/pkg/common/discoveryregister/zookeeper/zookeeper.go @@ -20,12 +20,10 @@ import ( "strings" "time" - "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/discoveryregistry" openkeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper" + "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" ) diff --git a/pkg/common/http/http_client.go b/pkg/common/http/http_client.go index 7fc456a1d..83908b8d3 100644 --- a/pkg/common/http/http_client.go +++ b/pkg/common/http/http_client.go @@ -25,7 +25,6 @@ import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/log" - "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/openimsdk/open-im-server/v3/pkg/common/config" ) @@ -66,12 +65,12 @@ func Post(ctx context.Context, url string, header map[string]string, data any, t jsonStr, err := json.Marshal(data) if err != nil { - return nil, err + return nil, errs.Wrap(err, "Post: JSON marshal failed") } req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(jsonStr)) if err != nil { - return nil, err + return nil, errs.Wrap(err, "Post: NewRequestWithContext failed") } if operationID, _ := ctx.Value(constant.OperationID).(string); operationID != "" { @@ -84,13 +83,13 @@ func Post(ctx context.Context, url string, header map[string]string, data any, t resp, err := client.Do(req) if err != nil { - return nil, err + return nil, errs.Wrap(err, "Post: client.Do failed") } defer resp.Body.Close() result, err := io.ReadAll(resp.Body) if err != nil { - return nil, err + return nil, errs.Wrap(err, "Post: ReadAll failed") } return result, nil @@ -102,7 +101,10 @@ func PostReturn(ctx context.Context, url string, header map[string]string, input return err } err = json.Unmarshal(b, output) - return err + if err != nil { + return errs.Wrap(err, "PostReturn: JSON unmarshal failed") + } + return nil } func callBackPostReturn(ctx context.Context, url, command string, input interface{}, output callbackstruct.CallbackResp, callbackConfig config.CallBackConfig) error { @@ -127,7 +129,6 @@ func callBackPostReturn(ctx context.Context, url, command string, input interfac } if err := output.Parse(); err != nil { log.ZWarn(ctx, "callback parse failed", err, "url", url, "input", input, "response", string(b)) - return err } log.ZInfo(ctx, "callback success", "url", url, "input", input, "response", string(b)) return nil diff --git a/pkg/common/kafka/consumer.go b/pkg/common/kafka/consumer.go index 435b8b780..664e5d468 100644 --- a/pkg/common/kafka/consumer.go +++ b/pkg/common/kafka/consumer.go @@ -20,6 +20,7 @@ import ( "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/IBM/sarama" + "github.com/OpenIMSDK/tools/errs" ) type Consumer struct { @@ -30,7 +31,7 @@ type Consumer struct { Consumer sarama.Consumer } -func NewKafkaConsumer(addr []string, topic string, config *config.GlobalConfig) *Consumer { +func NewKafkaConsumer(addr []string, topic string, config *config.GlobalConfig) (*Consumer,error) { p := Consumer{} p.Topic = topic p.addr = addr @@ -50,18 +51,22 @@ func NewKafkaConsumer(addr []string, topic string, config *config.GlobalConfig) InsecureSkipVerify: false, } } - SetupTLSConfig(consumerConfig, tlsConfig) + err:=SetupTLSConfig(consumerConfig, tlsConfig) + if err!=nil{ + return nil,err + } consumer, err := sarama.NewConsumer(p.addr, consumerConfig) if err != nil { - panic(err.Error()) + return nil, errs.Wrap(err, "NewKafkaConsumer: creating consumer failed") } p.Consumer = consumer partitionList, err := consumer.Partitions(p.Topic) if err != nil { - panic(err.Error()) + return nil, errs.Wrap(err, "NewKafkaConsumer: getting partitions failed") } p.PartitionList = partitionList - return &p + return &p, nil + } diff --git a/pkg/common/kafka/producer.go b/pkg/common/kafka/producer.go index 217a22c97..afc53b35a 100644 --- a/pkg/common/kafka/producer.go +++ b/pkg/common/kafka/producer.go @@ -94,11 +94,10 @@ func NewKafkaProducer(addr []string, topic string, producerConfig *ProducerConfi for i := 0; i <= maxRetry; i++ { p.producer, err = sarama.NewSyncProducer(p.addr, p.config) if err == nil { - return &p, nil + return &p, errs.Wrap(err) } time.Sleep(1 * time.Second) // Wait before retrying } - // Panic if unable to create producer after retries if err != nil { return nil, errs.Wrap(errors.New("failed to create Kafka producer: " + err.Error())) @@ -123,7 +122,7 @@ func configureProducerAck(p *Producer, ackConfig string) { // configureCompression configures the message compression type for the producer. func configureCompression(p *Producer, compressType string) { - var compress sarama.CompressionCodec = sarama.CompressionNone + var compress = sarama.CompressionNone err := compress.UnmarshalText(bytes.ToLower([]byte(compressType))) if err != nil { fmt.Printf("Failed to configure compression: %v\n", err) @@ -183,7 +182,7 @@ func (p *Producer) SendMessage(ctx context.Context, key string, msg proto.Messag // Attach context metadata as headers header, err := GetMQHeaderWithContext(ctx) if err != nil { - return 0, 0, errs.Wrap(err) + return 0, 0, err } kMsg.Headers = header diff --git a/pkg/common/kafka/util.go b/pkg/common/kafka/util.go index 9eb2bfd68..4e2a02714 100644 --- a/pkg/common/kafka/util.go +++ b/pkg/common/kafka/util.go @@ -20,7 +20,6 @@ import ( "strings" "github.com/IBM/sarama" - "github.com/openimsdk/open-im-server/v3/pkg/common/tls" ) @@ -33,17 +32,22 @@ type TLSConfig struct { } // SetupTLSConfig set up the TLS config from config file. -func SetupTLSConfig(cfg *sarama.Config, tlsConfig *TLSConfig) { +func SetupTLSConfig(cfg *sarama.Config, tlsConfig *TLSConfig) error { if tlsConfig != nil { cfg.Net.TLS.Enable = true - cfg.Net.TLS.Config = tls.NewTLSConfig( + tlsConfig, err := tls.NewTLSConfig( tlsConfig.ClientCrt, tlsConfig.ClientKey, tlsConfig.CACrt, []byte(tlsConfig.ClientKeyPwd), tlsConfig.InsecureSkipVerify, ) + if err != nil { + return err + } + cfg.Net.TLS.Config = tlsConfig } + return nil } // getEnvOrConfig returns the value of the environment variable if it exists, diff --git a/pkg/common/prommetrics/prommetrics.go b/pkg/common/prommetrics/prommetrics.go index a4515c74f..9089e7b5f 100644 --- a/pkg/common/prommetrics/prommetrics.go +++ b/pkg/common/prommetrics/prommetrics.go @@ -16,15 +16,13 @@ package prommetrics import ( gp "github.com/grpc-ecosystem/go-grpc-prometheus" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/collectors" - config2 "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/ginprometheus" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/collectors" ) func NewGrpcPromObj(cusMetrics []prometheus.Collector) (*prometheus.Registry, *gp.ServerMetrics, error) { - //////////////////////////////////////////////////////// reg := prometheus.NewRegistry() grpcMetrics := gp.NewServerMetrics() grpcMetrics.EnableHandlingTimeHistogram() diff --git a/pkg/common/startrpc/start.go b/pkg/common/startrpc/start.go index 5109adcab..8af894ac0 100644 --- a/pkg/common/startrpc/start.go +++ b/pkg/common/startrpc/start.go @@ -72,7 +72,7 @@ func Start( defer listener.Close() client, err := kdisc.NewDiscoveryRegister(config) if err != nil { - return errs.Wrap(err) + return err } defer client.Close() diff --git a/pkg/common/tls/tls.go b/pkg/common/tls/tls.go index 00bc02788..736913758 100755 --- a/pkg/common/tls/tls.go +++ b/pkg/common/tls/tls.go @@ -20,6 +20,8 @@ import ( "encoding/pem" "errors" "os" + + "github.com/OpenIMSDK/tools/errs" ) // decryptPEM decrypts a PEM block using a password. @@ -47,37 +49,40 @@ func readEncryptablePEMBlock(path string, pwd []byte) ([]byte, error) { } // NewTLSConfig setup the TLS config from general config file. -func NewTLSConfig(clientCertFile, clientKeyFile, caCertFile string, keyPwd []byte, insecureSkipVerify bool) *tls.Config { +func NewTLSConfig(clientCertFile, clientKeyFile, caCertFile string, keyPwd []byte, insecureSkipVerify bool) (*tls.Config,error) { tlsConfig := tls.Config{} if clientCertFile != "" && clientKeyFile != "" { certPEMBlock, err := os.ReadFile(clientCertFile) if err != nil { - panic(err) + return nil, errs.Wrap(err, "NewTLSConfig: failed to read client cert file") } keyPEMBlock, err := readEncryptablePEMBlock(clientKeyFile, keyPwd) if err != nil { - panic(err) + return nil, err } + cert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock) if err != nil { - panic(err) + return nil, errs.Wrap(err, "NewTLSConfig: failed to create X509 key pair") } tlsConfig.Certificates = []tls.Certificate{cert} } - caCert, err := os.ReadFile(caCertFile) - if err != nil { - panic(err) - } - caCertPool := x509.NewCertPool() - ok := caCertPool.AppendCertsFromPEM(caCert) - if !ok { - panic(errors.New("not a valid CA cert")) + if caCertFile != "" { + caCert, err := os.ReadFile(caCertFile) + if err != nil { + return nil, errs.Wrap(err, "NewTLSConfig: failed to read CA cert file") + } + + caCertPool := x509.NewCertPool() + if ok := caCertPool.AppendCertsFromPEM(caCert); !ok { + return nil, errors.New("NewTLSConfig: not a valid CA cert") + } + tlsConfig.RootCAs = caCertPool } - tlsConfig.RootCAs = caCertPool tlsConfig.InsecureSkipVerify = insecureSkipVerify - return &tlsConfig + return &tlsConfig, nil } diff --git a/pkg/msgprocessor/conversation.go b/pkg/msgprocessor/conversation.go index 7477bea7a..e3ea89fad 100644 --- a/pkg/msgprocessor/conversation.go +++ b/pkg/msgprocessor/conversation.go @@ -20,6 +20,7 @@ import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/tools/errs" "google.golang.org/protobuf/proto" ) @@ -188,7 +189,7 @@ func (s MsgBySeq) Swap(i, j int) { func Pb2String(pb proto.Message) (string, error) { s, err := proto.Marshal(pb) if err != nil { - return "", err + return "", errs.Wrap(err) } return string(s), nil } diff --git a/pkg/rpcclient/auth.go b/pkg/rpcclient/auth.go index 5501a3faf..24597120f 100644 --- a/pkg/rpcclient/auth.go +++ b/pkg/rpcclient/auth.go @@ -17,18 +17,17 @@ package rpcclient import ( "context" - "google.golang.org/grpc" - "github.com/OpenIMSDK/protocol/auth" "github.com/OpenIMSDK/tools/discoveryregistry" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" + util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" + "google.golang.org/grpc" ) func NewAuth(discov discoveryregistry.SvcDiscoveryRegistry, config *config.GlobalConfig) *Auth { conn, err := discov.GetConn(context.Background(), config.RpcRegisterName.OpenImAuthName) if err != nil { - panic(err) + util.ExitWithError(err) } client := auth.NewAuthClient(conn) return &Auth{discov: discov, conn: conn, Client: client, Config: config} diff --git a/pkg/rpcclient/conversation.go b/pkg/rpcclient/conversation.go index bfe71b79d..6981844b6 100644 --- a/pkg/rpcclient/conversation.go +++ b/pkg/rpcclient/conversation.go @@ -18,13 +18,12 @@ import ( "context" "fmt" - "google.golang.org/grpc" - pbconversation "github.com/OpenIMSDK/protocol/conversation" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/errs" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" + util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" + "google.golang.org/grpc" ) type Conversation struct { @@ -37,7 +36,7 @@ type Conversation struct { func NewConversation(discov discoveryregistry.SvcDiscoveryRegistry, config *config.GlobalConfig) *Conversation { conn, err := discov.GetConn(context.Background(), config.RpcRegisterName.OpenImConversationName) if err != nil { - panic(err) + util.ExitWithError(err) } client := pbconversation.NewConversationClient(conn) return &Conversation{discov: discov, conn: conn, Client: client, Config: config} @@ -115,11 +114,7 @@ func (c *ConversationRpcClient) GetConversationsByConversationID(ctx context.Con return resp.Conversations, nil } -func (c *ConversationRpcClient) GetConversations( - ctx context.Context, - ownerUserID string, - conversationIDs []string, -) ([]*pbconversation.Conversation, error) { +func (c *ConversationRpcClient) GetConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*pbconversation.Conversation, error) { if len(conversationIDs) == 0 { return nil, nil } diff --git a/pkg/rpcclient/friend.go b/pkg/rpcclient/friend.go index 090b62ad9..e1f6ed076 100644 --- a/pkg/rpcclient/friend.go +++ b/pkg/rpcclient/friend.go @@ -17,13 +17,12 @@ package rpcclient import ( "context" - "google.golang.org/grpc" - "github.com/OpenIMSDK/protocol/friend" sdkws "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/discoveryregistry" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" + util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" + "google.golang.org/grpc" ) type Friend struct { @@ -36,7 +35,7 @@ type Friend struct { func NewFriend(discov discoveryregistry.SvcDiscoveryRegistry, config *config.GlobalConfig) *Friend { conn, err := discov.GetConn(context.Background(), config.RpcRegisterName.OpenImFriendName) if err != nil { - panic(err) + util.ExitWithError(err) } client := friend.NewFriendClient(conn) return &Friend{discov: discov, conn: conn, Client: client, Config: config} @@ -63,7 +62,7 @@ func (f *FriendRpcClient) GetFriendsInfo( return } -// possibleFriendUserID是否在userID的好友中. +// possibleFriendUserID Is PossibleFriendUserId's friends. func (f *FriendRpcClient) IsFriend(ctx context.Context, possibleFriendUserID, userID string) (bool, error) { resp, err := f.Client.IsFriend(ctx, &friend.IsFriendReq{UserID1: userID, UserID2: possibleFriendUserID}) if err != nil { diff --git a/pkg/rpcclient/group.go b/pkg/rpcclient/group.go index b61e5eb89..773637858 100644 --- a/pkg/rpcclient/group.go +++ b/pkg/rpcclient/group.go @@ -18,16 +18,15 @@ import ( "context" "strings" - "google.golang.org/grpc" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/group" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" + util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" + "google.golang.org/grpc" ) type Group struct { @@ -40,7 +39,7 @@ type Group struct { func NewGroup(discov discoveryregistry.SvcDiscoveryRegistry, config *config.GlobalConfig) *Group { conn, err := discov.GetConn(context.Background(), config.RpcRegisterName.OpenImGroupName) if err != nil { - panic(err) + util.ExitWithError(err) } client := group.NewGroupClient(conn) return &Group{discov: discov, conn: conn, Client: client, Config: config} diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go index 6c3c46a2f..3db39925e 100644 --- a/pkg/rpcclient/msg.go +++ b/pkg/rpcclient/msg.go @@ -20,18 +20,15 @@ import ( "fmt" "github.com/OpenIMSDK/tools/errs" - "google.golang.org/grpc" - "google.golang.org/protobuf/proto" - "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/msg" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/utils" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" - // "google.golang.org/protobuf/proto". + "google.golang.org/grpc" + "google.golang.org/protobuf/proto" ) func newContentTypeConf(conf *config.GlobalConfig) map[int32]config.NotificationConf { @@ -150,14 +147,24 @@ func NewMessageRpcClient(discov discoveryregistry.SvcDiscoveryRegistry, config * return MessageRpcClient(*NewMessage(discov, config)) } +// SendMsg sends a message through the gRPC client and returns the response. +// It wraps any encountered error for better error handling and context understanding. func (m *MessageRpcClient) SendMsg(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) { resp, err := m.Client.SendMsg(ctx, req) - return resp, err + if err != nil { + return nil, err + } + return resp, nil } +// GetMaxSeq retrieves the maximum sequence number from the gRPC client. +// Errors during the gRPC call are wrapped to provide additional context. func (m *MessageRpcClient) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqReq) (*sdkws.GetMaxSeqResp, error) { resp, err := m.Client.GetMaxSeq(ctx, req) - return resp, err + if err != nil { + return nil, err + } + return resp, nil } func (m *MessageRpcClient) GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) { @@ -184,9 +191,15 @@ func (m *MessageRpcClient) GetMsgByConversationIDs(ctx context.Context, docIDs [ return resp.MsgDatas, err } +// PullMessageBySeqList retrieves messages by their sequence numbers using the gRPC client. +// It directly forwards the request to the gRPC client and returns the response along with any error encountered. func (m *MessageRpcClient) PullMessageBySeqList(ctx context.Context, req *sdkws.PullMessageBySeqsReq) (*sdkws.PullMessageBySeqsResp, error) { resp, err := m.Client.PullMessageBySeqs(ctx, req) - return resp, err + if err != nil { + // Wrap the error to provide more context if the gRPC call fails. + return nil, err + } + return resp, nil } func (m *MessageRpcClient) GetConversationMaxSeq(ctx context.Context, conversationID string) (int64, error) { diff --git a/pkg/rpcclient/notification/conversation.go b/pkg/rpcclient/notification/conversation.go index b8d06423f..115fb81a2 100644 --- a/pkg/rpcclient/notification/conversation.go +++ b/pkg/rpcclient/notification/conversation.go @@ -20,7 +20,6 @@ import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/sdkws" - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) @@ -32,7 +31,7 @@ func NewConversationNotificationSender(config *config.GlobalConfig, msgRpcClient return &ConversationNotificationSender{rpcclient.NewNotificationSender(config, rpcclient.WithRpcClient(msgRpcClient))} } -// SetPrivate调用. +// SetPrivate invote. func (c *ConversationNotificationSender) ConversationSetPrivateNotification(ctx context.Context, sendID, recvID string, isPrivateChat bool, conversationID string, ) error { @@ -46,7 +45,6 @@ func (c *ConversationNotificationSender) ConversationSetPrivateNotification(ctx return c.Notification(ctx, sendID, recvID, constant.ConversationPrivateChatNotification, tips) } -// 会话改变. func (c *ConversationNotificationSender) ConversationChangeNotification(ctx context.Context, userID string, conversationIDs []string) error { tips := &sdkws.ConversationUpdateTips{ UserID: userID, @@ -56,7 +54,6 @@ func (c *ConversationNotificationSender) ConversationChangeNotification(ctx cont return c.Notification(ctx, userID, userID, constant.ConversationChangeNotification, tips) } -// 会话未读数同步. func (c *ConversationNotificationSender) ConversationUnreadChangeNotification( ctx context.Context, userID, conversationID string, diff --git a/pkg/rpcclient/notification/friend.go b/pkg/rpcclient/notification/friend.go index b40f2ba93..31426da31 100644 --- a/pkg/rpcclient/notification/friend.go +++ b/pkg/rpcclient/notification/friend.go @@ -18,12 +18,10 @@ import ( "context" "github.com/openimsdk/open-im-server/v3/pkg/common/config" - "github.com/OpenIMSDK/tools/mcontext" - "github.com/OpenIMSDK/protocol/constant" pbfriend "github.com/OpenIMSDK/protocol/friend" "github.com/OpenIMSDK/protocol/sdkws" - + "github.com/OpenIMSDK/tools/mcontext" "github.com/openimsdk/open-im-server/v3/pkg/common/convert" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" @@ -32,7 +30,7 @@ import ( type FriendNotificationSender struct { *rpcclient.NotificationSender - // 找不到报错 + // Target not found err getUsersInfo func(ctx context.Context, userIDs []string) ([]CommonUser, error) // db controller db controller.FriendDatabase diff --git a/pkg/rpcclient/notification/group.go b/pkg/rpcclient/notification/group.go old mode 100755 new mode 100644 index dd66b4637..5500f4f43 --- a/pkg/rpcclient/notification/group.go +++ b/pkg/rpcclient/notification/group.go @@ -19,8 +19,6 @@ import ( "fmt" "github.com/openimsdk/open-im-server/v3/pkg/common/config" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" - "github.com/OpenIMSDK/protocol/constant" pbgroup "github.com/OpenIMSDK/protocol/group" "github.com/OpenIMSDK/protocol/sdkws" @@ -28,7 +26,7 @@ import ( "github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/utils" - + "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" diff --git a/pkg/rpcclient/notification/msg.go b/pkg/rpcclient/notification/msg.go index 49db0ca94..19819e7b7 100644 --- a/pkg/rpcclient/notification/msg.go +++ b/pkg/rpcclient/notification/msg.go @@ -20,7 +20,6 @@ import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/sdkws" - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" ) diff --git a/pkg/rpcclient/notification/user.go b/pkg/rpcclient/notification/user.go index 53e07676d..204b13e61 100644 --- a/pkg/rpcclient/notification/user.go +++ b/pkg/rpcclient/notification/user.go @@ -20,7 +20,6 @@ import ( "github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/sdkws" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" diff --git a/pkg/rpcclient/push.go b/pkg/rpcclient/push.go index 3e5044b87..c0aa9efa4 100644 --- a/pkg/rpcclient/push.go +++ b/pkg/rpcclient/push.go @@ -17,12 +17,11 @@ package rpcclient import ( "context" - "google.golang.org/grpc" - "github.com/OpenIMSDK/protocol/push" "github.com/OpenIMSDK/tools/discoveryregistry" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" + util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" + "google.golang.org/grpc" ) type Push struct { @@ -34,7 +33,7 @@ type Push struct { func NewPush(discov discoveryregistry.SvcDiscoveryRegistry, config *config.GlobalConfig) *Push { conn, err := discov.GetConn(context.Background(), config.RpcRegisterName.OpenImPushName) if err != nil { - panic(err) + util.ExitWithError(err) } return &Push{ discov: discov, @@ -49,9 +48,6 @@ func NewPushRpcClient(discov discoveryregistry.SvcDiscoveryRegistry, config *con return PushRpcClient(*NewPush(discov, config)) } -func (p *PushRpcClient) DelUserPushToken( - ctx context.Context, - req *push.DelUserPushTokenReq, -) (*push.DelUserPushTokenResp, error) { +func (p *PushRpcClient) DelUserPushToken(ctx context.Context, req *push.DelUserPushTokenReq) (*push.DelUserPushTokenResp, error) { return p.Client.DelUserPushToken(ctx, req) } diff --git a/pkg/rpcclient/third.go b/pkg/rpcclient/third.go index 1faf1655b..50d545a64 100755 --- a/pkg/rpcclient/third.go +++ b/pkg/rpcclient/third.go @@ -16,16 +16,18 @@ package rpcclient import ( "context" + "github.com/OpenIMSDK/tools/errs" "net/url" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" - "google.golang.org/grpc" "github.com/OpenIMSDK/protocol/third" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/openimsdk/open-im-server/v3/pkg/common/config" + util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" + "google.golang.org/grpc" ) type Third struct { @@ -39,12 +41,12 @@ type Third struct { func NewThird(discov discoveryregistry.SvcDiscoveryRegistry, config *config.GlobalConfig) *Third { conn, err := discov.GetConn(context.Background(), config.RpcRegisterName.OpenImThirdName) if err != nil { - panic(err) + util.ExitWithError(err) } client := third.NewThirdClient(conn) minioClient, err := minioInit(config) if err != nil { - panic(err) + util.ExitWithError(err) } return &Third{discov: discov, Client: client, conn: conn, MinioClient: minioClient, Config: config} } @@ -54,7 +56,7 @@ func minioInit(config *config.GlobalConfig) (*minio.Client, error) { initUrl := config.Object.Minio.Endpoint minioUrl, err := url.Parse(initUrl) if err != nil { - return nil, err + return nil, errs.Wrap(err, "minioInit: failed to parse MinIO endpoint URL") } opts := &minio.Options{ Creds: credentials.NewStaticV4(config.Object.Minio.AccessKeyID, config.Object.Minio.SecretAccessKey, ""), @@ -67,7 +69,7 @@ func minioInit(config *config.GlobalConfig) (*minio.Client, error) { } minioClient, err = minio.New(minioUrl.Host, opts) if err != nil { - return nil, err + return nil, errs.Wrap(err, "minioInit: failed to create MinIO client") } return minioClient, nil } diff --git a/pkg/rpcclient/user.go b/pkg/rpcclient/user.go index 587e391e9..08ad41dc1 100644 --- a/pkg/rpcclient/user.go +++ b/pkg/rpcclient/user.go @@ -18,17 +18,15 @@ import ( "context" "strings" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" - - "google.golang.org/grpc" - "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/protocol/user" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/utils" - + "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/common/config" + util "github.com/openimsdk/open-im-server/v3/pkg/util/genutil" + "google.golang.org/grpc" ) // User represents a structure holding connection details for the User RPC client. @@ -43,7 +41,7 @@ type User struct { func NewUser(discov discoveryregistry.SvcDiscoveryRegistry, config *config.GlobalConfig) *User { conn, err := discov.GetConn(context.Background(), config.RpcRegisterName.OpenImUserName) if err != nil { - panic(err) + util.ExitWithError(err) } client := user.NewUserClient(conn) return &User{Discov: discov, Client: client, conn: conn, Config: config} diff --git a/pkg/util/genutil/genutil.go b/pkg/util/genutil/genutil.go index bd9376d58..95735485d 100644 --- a/pkg/util/genutil/genutil.go +++ b/pkg/util/genutil/genutil.go @@ -18,6 +18,8 @@ import ( "fmt" "os" "path/filepath" + + "github.com/OpenIMSDK/tools/errs" ) // OutDir creates the absolute path name from path and checks path exists. @@ -25,16 +27,16 @@ import ( func OutDir(path string) (string, error) { outDir, err := filepath.Abs(path) if err != nil { - return "", err + return "", errs.Wrap(err, "output directory %s does not exist", path) } stat, err := os.Stat(outDir) if err != nil { - return "", err + return "", errs.Wrap(err, "output directory %s does not exist", outDir) } if !stat.IsDir() { - return "", fmt.Errorf("output directory %s is not a directory", outDir) + return "", errs.Wrap(err, "output directory %s is not a directory", outDir) } outDir += "/" return outDir, nil diff --git a/scripts/build-all-service.sh b/scripts/build-all-service.sh index 6335b0e08..eea380b4f 100755 --- a/scripts/build-all-service.sh +++ b/scripts/build-all-service.sh @@ -23,9 +23,6 @@ # Example: `scripts/build-go.sh WHAT=cmd/kubelet`. - - - OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. source "${OPENIM_ROOT}/scripts/lib/init.sh" diff --git a/scripts/common.sh b/scripts/common.sh index 702f55588..f7155fca2 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -19,9 +19,6 @@ # Common utilities, variables and checks for all build scripts. - - - # Unset CDPATH, having it set messes up with script import paths unset CDPATH diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh index 896288775..64e76853d 100755 --- a/scripts/install/environment.sh +++ b/scripts/install/environment.sh @@ -332,7 +332,7 @@ def "OPENIM_CONVERSATION_NAME" "Conversation" # OpenIM对话服务名称 def "OPENIM_THIRD_NAME" "Third" # OpenIM第三方服务名称 ###################### Log Configuration Variables ###################### -def "LOG_STORAGE_LOCATION" "${OPENIM_ROOT}/logs/" # 日志存储位置 +def "LOG_STORAGE_LOCATION" "${OPENIM_ROOT}/_output/logs/" # 日志存储位置 def "LOG_ROTATION_TIME" "24" # 日志轮替时间 def "LOG_REMAIN_ROTATION_COUNT" "2" # 保留的日志轮替数量 def "LOG_REMAIN_LOG_LEVEL" "6" # 保留的日志级别 diff --git a/scripts/install/openim-rpc.sh b/scripts/install/openim-rpc.sh index 023cb6594..e7ee430d2 100755 --- a/scripts/install/openim-rpc.sh +++ b/scripts/install/openim-rpc.sh @@ -38,10 +38,6 @@ # Note: Before executing this script, ensure that the necessary permissions are granted and relevant environmental variables are set. # - - - - OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P) [[ -z ${COMMON_SOURCED} ]] && source "${OPENIM_ROOT}"/scripts/install/common.sh diff --git a/scripts/install/openim-tools.sh b/scripts/install/openim-tools.sh index 72005ed8e..4eb722c6e 100755 --- a/scripts/install/openim-tools.sh +++ b/scripts/install/openim-tools.sh @@ -39,9 +39,6 @@ # - - - OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P) [[ -z ${COMMON_SOURCED} ]] && source "${OPENIM_ROOT}"/scripts/install/common.sh @@ -103,14 +100,14 @@ function openim::tools::start_service() { printf "Specifying prometheus port: %s\n" "${prometheus_port}" cmd="${cmd} --prometheus_port ${prometheus_port}" fi - openim::log::status "Starting ${binary_name}..." + openim::log::status "Starting binary ${binary_name}..." ${cmd} | tee -a "${LOG_FILE}" } function openim::tools::start() { openim::log::info "Starting OpenIM Tools..." for tool in "${OPENIM_TOOLS_NAME_LISTARIES[@]}"; do - openim::log::info "Starting ${tool}..." + openim::log::info "Starting tool ${tool}..." # openim::tools::start_service ${tool} sleep 0.2 done @@ -120,7 +117,7 @@ function openim::tools::start() { function openim::tools::pre-start() { openim::log::info "Preparing to start OpenIM Tools..." for tool in "${OPENIM_TOOLS_PRE_START_NAME_LISTARIES[@]}"; do - openim::log::info "Starting ${tool}..." + openim::log::info "Starting tool ${tool}..." openim::tools::start_service ${tool} ${OPNEIM_CONFIG} done } @@ -128,7 +125,7 @@ function openim::tools::pre-start() { function openim::tools::post-start() { openim::log::info "Post-start actions for OpenIM Tools..." for tool in "${OPENIM_TOOLS_POST_START_NAME_LISTARIES[@]}"; do - openim::log::info "Starting ${tool}..." + openim::log::info "Starting tool ${tool}..." openim::tools::start_service ${tool} done } diff --git a/scripts/install/test.sh b/scripts/install/test.sh index 4a78e4504..4ea3f16ca 100755 --- a/scripts/install/test.sh +++ b/scripts/install/test.sh @@ -34,8 +34,8 @@ # # The root of the build/dist directory -IAM_ROOT=$(dirname "${BASH_SOURCE[0]}")/../.. -[[ -z ${COMMON_SOURCED} ]] && source ${IAM_ROOT}/scripts/install/common.sh +OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/../.. +[[ -z ${COMMON_SOURCED} ]] && source ${OPENIM_ROOT}/scripts/install/common.sh # API Server API Address:Port INSECURE_OPENIMAPI="http://${OPENIM_API_HOST}:${API_OPENIM_PORT}" @@ -72,7 +72,7 @@ function openim::test::auth() { # Define a function to get a token for a specific user openim::test::get_token() { - local user_id="${1:-openIM123456}" # Default user ID if not provided + local user_id="${1:-imAdmin}" # Default user ID if not provided token_response=$( ${CCURL} "${OperationID}" "${Header}" ${INSECURE_OPENIMAPI}/auth/user_token \ -d'{"secret": "'"$SECRET"'","platformID": 1,"userID": "'$user_id'"}' @@ -142,10 +142,7 @@ openim::test::check_user_account() { cat </dev/null + make build BINS="codescan" + popd >/dev/null +fi + +if [[ ! -f "${CODESCAN_BINARY}" ]]; then + echo "Failed to build codescan binary." + exit 1 +fi + +CONFIG_PATH="${OPENIM_ROOT}/tools/codescan/config.yaml" + +"${CODESCAN_BINARY}" -config "${CONFIG_PATH}" \ No newline at end of file diff --git a/scripts/verify-pkg-names.sh b/scripts/verify-pkg-names.sh index 7fce3d7ad..be1acd015 100755 --- a/scripts/verify-pkg-names.sh +++ b/scripts/verify-pkg-names.sh @@ -18,9 +18,6 @@ # Usage: `scripts/verify-pkg-names.sh`. - - - OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. source "${OPENIM_ROOT}/scripts/lib/init.sh" diff --git a/test/e2e/README.md b/test/e2e/README.md index 1e73dbaec..49215e811 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -128,6 +128,8 @@ Open issue: https://github.com/openimsdk/open-im-server/issues/new/choose, choos The E2E test suite is integrated with CI, which runs the tests automatically on each code commit. The results are reported back to the pull request or commit to provide immediate feedback on the impact of the changes. +[![OpenIM Linux System E2E Test](https://github.com/openimsdk/open-im-server/actions/workflows/e2e-test.yml/badge.svg)](https://github.com/openimsdk/open-im-server/actions/workflows/e2e-test.yml) + ## Contact diff --git a/test/e2e/api/token/token.go b/test/e2e/api/token/token.go index 88af72058..908f9b8a0 100644 --- a/test/e2e/api/token/token.go +++ b/test/e2e/api/token/token.go @@ -19,7 +19,6 @@ import ( "encoding/json" "fmt" "io" - "log" "net/http" ) @@ -58,7 +57,7 @@ type UserRegisterRequest struct { Users []User `json:"users"` } -func main() { +/* func main() { // Example usage of functions token, err := GetUserToken("openIM123456") if err != nil { @@ -70,7 +69,7 @@ func main() { if err != nil { log.Fatalf("Error registering user: %v", err) } -} +} */ // GetUserToken requests a user token from the API. func GetUserToken(userID string) (string, error) { diff --git a/test/e2e/framework/config/config_test.go b/test/e2e/framework/config/config_test.go index b7259bf37..66f845db3 100644 --- a/test/e2e/framework/config/config_test.go +++ b/test/e2e/framework/config/config_test.go @@ -76,7 +76,7 @@ func TestCopyFlags(t *testing.T) { }() CopyFlags(tt.args.source, tt.args.target) - // 验证复制的标记 + // Verify the replicated tag if !tt.wantErr { tt.args.source.VisitAll(func(f *flag.Flag) { if gotFlag := tt.args.target.Lookup(f.Name); gotFlag == nil || !reflect.DeepEqual(gotFlag, f) { diff --git a/test/e2e/framework/helpers/chat/chat.go b/test/e2e/framework/helpers/chat/chat.go index a4ead528b..aa37c34b5 100644 --- a/test/e2e/framework/helpers/chat/chat.go +++ b/test/e2e/framework/helpers/chat/chat.go @@ -38,6 +38,9 @@ func main() { // } latestVersion := defaultTemplateVersion + // getLatestVersion + // getLatestVersion + // Construct the download URL downloadURL := fmt.Sprintf("https://github.com/openimsdk/chat/releases/download/%s/chat_Linux_x86_64.tar.gz", latestVersion) @@ -99,22 +102,22 @@ func main() { } // getLatestVersion fetches the latest version number from a given URL. -func getLatestVersion(url string) (string, error) { +/* func getLatestVersion(url string) (string, error) { resp, err := http.Get(url) if err != nil { return "", err } defer resp.Body.Close() - location := resp.Header.Get("Location") - if location == "" { - return defaultTemplateVersion, nil - } +// location := resp.Header.Get("Location") +// if location == "" { +// return defaultTemplateVersion, nil +// } // Extract the version number from the URL latestVersion := filepath.Base(location) return latestVersion, nil -} +} */ // downloadAndExtract downloads a file from a URL and extracts it to a destination directory. func downloadAndExtract(url, destDir string) error { diff --git a/test/e2e/page/chat_page.go b/test/e2e/page/chat_page.go new file mode 100644 index 000000000..d92c7ec6e --- /dev/null +++ b/test/e2e/page/chat_page.go @@ -0,0 +1,15 @@ +// Copyright © 2024 OpenIM. All rights reserved. +// +// Licensed 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 page diff --git a/test/e2e/page/login_page.go b/test/e2e/page/login_page.go new file mode 100644 index 000000000..d92c7ec6e --- /dev/null +++ b/test/e2e/page/login_page.go @@ -0,0 +1,15 @@ +// Copyright © 2024 OpenIM. All rights reserved. +// +// Licensed 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 page diff --git a/test/e2e/web/.keep b/test/e2e/web/.keep deleted file mode 100644 index 4f07f1caf..000000000 --- a/test/e2e/web/.keep +++ /dev/null @@ -1 +0,0 @@ -.keep \ No newline at end of file diff --git a/test/e2e/web/Readme.md b/test/e2e/web/Readme.md new file mode 100644 index 000000000..741ca51d5 --- /dev/null +++ b/test/e2e/web/Readme.md @@ -0,0 +1,2 @@ +# OpenIM Web E2E + diff --git a/tools/codescan/checker/checker.go b/tools/codescan/checker/checker.go new file mode 100644 index 000000000..ad724dd5b --- /dev/null +++ b/tools/codescan/checker/checker.go @@ -0,0 +1,104 @@ +// Copyright © 2024 OpenIM. All rights reserved. +// +// Licensed 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 checker + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/openimsdk/open-im-server/tools/codescan/config" +) + +type CheckResult struct { + FilePath string + Lines []int +} + +func checkFileForChineseComments(filePath string) ([]CheckResult, error) { + file, err := os.Open(filePath) + if err != nil { + return nil, err + } + defer file.Close() + + var results []CheckResult + scanner := bufio.NewScanner(file) + reg := regexp.MustCompile(`[\p{Han}]+`) + lineNumber := 0 + + var linesWithChinese []int + for scanner.Scan() { + lineNumber++ + if reg.FindString(scanner.Text()) != "" { + linesWithChinese = append(linesWithChinese, lineNumber) + } + } + + if len(linesWithChinese) > 0 { + results = append(results, CheckResult{ + FilePath: filePath, + Lines: linesWithChinese, + }) + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return results, nil +} + +func WalkDirAndCheckComments(cfg config.Config) error { + var allResults []CheckResult + err := filepath.Walk(cfg.Directory, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + for _, fileType := range cfg.FileTypes { + if filepath.Ext(path) == fileType { + results, err := checkFileForChineseComments(path) + if err != nil { + return err + } + if len(results) > 0 { + allResults = append(allResults, results...) + } + } + } + return nil + }) + + if err != nil { + return err + } + + if len(allResults) > 0 { + var errMsg strings.Builder + errMsg.WriteString("Files containing Chinese comments:\n") + for _, result := range allResults { + errMsg.WriteString(fmt.Sprintf("%s: Lines %v\n", result.FilePath, result.Lines)) + } + return fmt.Errorf(errMsg.String()) + } + + return nil +} diff --git a/tools/codescan/codescan.go b/tools/codescan/codescan.go new file mode 100644 index 000000000..a83e895fc --- /dev/null +++ b/tools/codescan/codescan.go @@ -0,0 +1,34 @@ +// Copyright © 2024 OpenIM. All rights reserved. +// +// Licensed 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 main + +import ( + "log" + + "github.com/openimsdk/open-im-server/tools/codescan/checker" + "github.com/openimsdk/open-im-server/tools/codescan/config" +) + +func main() { + cfg, err := config.ParseConfig() + if err != nil { + log.Fatalf("Error parsing config: %v", err) + } + + err = checker.WalkDirAndCheckComments(cfg) + if err != nil { + panic(err) + } +} diff --git a/tools/codescan/config.yaml b/tools/codescan/config.yaml new file mode 100644 index 000000000..32a8c1f54 --- /dev/null +++ b/tools/codescan/config.yaml @@ -0,0 +1,21 @@ +# Copyright © 2024 OpenIM. All rights reserved. +# +# Licensed 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. + +directory: ./ +file_types: + - .go + - .yaml + - .yml +languages: + - Chinese \ No newline at end of file diff --git a/tools/codescan/config/config.go b/tools/codescan/config/config.go new file mode 100644 index 000000000..aebf0d4f7 --- /dev/null +++ b/tools/codescan/config/config.go @@ -0,0 +1,49 @@ +// Copyright © 2024 OpenIM. All rights reserved. +// +// Licensed 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 config + +import ( + "flag" + "log" + "os" + + "gopkg.in/yaml.v2" +) + +type Config struct { + Directory string `yaml:"directory"` + FileTypes []string `yaml:"file_types"` + Languages []string `yaml:"languages"` +} + +func ParseConfig() (Config, error) { + var configPath string + flag.StringVar(&configPath, "config", "./", "Path to config file") + flag.Parse() + + var config Config + if configPath != "" { + configFile, err := os.ReadFile(configPath) + if err != nil { + return Config{}, err + } + if err := yaml.Unmarshal(configFile, &config); err != nil { + return Config{}, err + } + } else { + log.Fatal("Config file must be provided") + } + return config, nil +} diff --git a/tools/codescan/go.mod b/tools/codescan/go.mod new file mode 100644 index 000000000..2ad132101 --- /dev/null +++ b/tools/codescan/go.mod @@ -0,0 +1,3 @@ +module github.com/openimsdk/open-im-server/tools/codescan + +go 1.19 diff --git a/tools/data-conversion/chat/cmd/conversion-chat/chat.go b/tools/data-conversion/chat/cmd/conversion-chat/chat.go index 0fc49c782..f68b71b16 100644 --- a/tools/data-conversion/chat/cmd/conversion-chat/chat.go +++ b/tools/data-conversion/chat/cmd/conversion-chat/chat.go @@ -28,20 +28,20 @@ import ( func main() { var ( - usernameV2 = "root" // v2版本mysql用户名 - passwordV2 = "openIM" // v2版本mysql密码 - addrV2 = "127.0.0.1:13306" // v2版本mysql地址 - databaseV2 = "admin_chat" // v2版本mysql数据库名字 + usernameV2 = "root" // Username for MySQL v2 version + passwordV2 = "openIM" // Password for MySQL v2 version + addrV2 = "127.0.0.1:13306" // Address for MySQL v2 version + databaseV2 = "admin_chat" // Database name for MySQL v2 version ) var ( - usernameV3 = "root" // v3版本mysql用户名 - passwordV3 = "openIM123" // v3版本mysql密码 - addrV3 = "127.0.0.1:13306" // v3版本mysql地址 - databaseV3 = "openim_enterprise" // v3版本mysql数据库名字 + usernameV3 = "root" // Username for MySQL v3 version + passwordV3 = "openIM123" // Password for MySQL v3 version + addrV3 = "127.0.0.1:13306" // Address for MySQL v3 version + databaseV3 = "openim_enterprise" // Database name for MySQL v3 version ) - var concurrency = 1 // 并发数量 + var concurrency = 1 // Concurrency quantity log.SetFlags(log.LstdFlags | log.Llongfile) dsnV2 := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", usernameV2, passwordV2, addrV2, databaseV2) diff --git a/tools/data-conversion/chat/v2/admin.go b/tools/data-conversion/chat/v2/admin.go index fec11ff5b..20cf22a36 100644 --- a/tools/data-conversion/chat/v2/admin.go +++ b/tools/data-conversion/chat/v2/admin.go @@ -18,7 +18,7 @@ import ( "time" ) -// AppVersion pc端版本管理 +// AppVersion manages PC client versions type AppVersion struct { Version string `gorm:"column:version;size:64" json:"version"` Type int `gorm:"column:type;primary_key" json:"type"` @@ -29,7 +29,7 @@ type AppVersion struct { UpdateLog string `gorm:"column:update_log" json:"update_log"` } -// Admin 后台管理员 +// Admin manages backend administrators type Admin struct { Account string `gorm:"column:account;primary_key;type:char(64)" json:"account"` Password string `gorm:"column:Password;type:char(64)" json:"password"` @@ -40,19 +40,19 @@ type Admin struct { CreateTime time.Time `gorm:"column:create_time" json:"createTime"` } -// RegisterAddFriend 注册时默认好友 +// RegisterAddFriend specifies default friends when registering type RegisterAddFriend struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)" json:"userID"` CreateTime time.Time `gorm:"column:create_time" json:"createTime"` } -// RegisterAddGroup 注册时默认群组 +// RegisterAddGroup specifies default groups when registering type RegisterAddGroup struct { GroupID string `gorm:"column:group_id;primary_key;type:char(64)" json:"userID"` CreateTime time.Time `gorm:"column:create_time" json:"createTime"` } -// ClientInitConfig 系统相关配置项 +// ClientInitConfig contains system-related configuration items type ClientInitConfig struct { DiscoverPageURL string `gorm:"column:discover_page_url;size:128" json:"discoverPageURL"` OrdinaryUserAddFriend int32 `gorm:"column:ordinary_user_add_friend; default:1" json:"ordinaryUserAddFriend"` diff --git a/tools/data-conversion/chat/v2/chat.go b/tools/data-conversion/chat/v2/chat.go index 15cc4797f..4e0a0c04a 100644 --- a/tools/data-conversion/chat/v2/chat.go +++ b/tools/data-conversion/chat/v2/chat.go @@ -18,7 +18,7 @@ import ( "time" ) -// Register 注册信息表 +// Register Registration information sheet type Register struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)" json:"userID"` DeviceID string `gorm:"column:device_id;type:varchar(255)" json:"deviceID"` @@ -29,7 +29,7 @@ type Register struct { CreateTime time.Time `gorm:"column:create_time" json:"createTime"` } -// Account 账号密码表 +// Account username and password table type Account struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)" json:"userID"` Password string `gorm:"column:password;type:varchar(255)" json:"password"` @@ -38,7 +38,7 @@ type Account struct { OperatorUserID string `gorm:"column:operator_user_id;type:varchar(64)" json:"operatorUserID"` } -// Attribute 用户属性表 +// Attribute user information table type Attribute struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)" json:"userID"` Account string `gorm:"column:account;type:char(64)" json:"account"` @@ -58,7 +58,7 @@ type Attribute struct { AllowAddFriend int32 `gorm:"column:allow_add_friend;default:1" json:"allowAddFriend"` } -// 封号表 +// User friend relationship table type ForbiddenAccount struct { UserID string `gorm:"column:user_id;index:userID;primary_key;type:char(64)" json:"userID"` CreateTime time.Time `gorm:"column:create_time" json:"createTime"` @@ -66,7 +66,7 @@ type ForbiddenAccount struct { OperatorUserID string `gorm:"column:operator_user_id;type:varchar(255)" json:"operatorUserID"` } -// 用户登录信息表 +// user login record table type UserLoginRecord struct { UserID string `gorm:"column:user_id;size:64" json:"userID"` LoginTime time.Time `gorm:"column:login_time" json:"loginTime"` @@ -75,7 +75,7 @@ type UserLoginRecord struct { Platform string `gorm:"column:platform;type:varchar(32)" json:"platform"` } -// 禁止ip登录 注册 +// ip login registration is prohibited type IPForbidden struct { IP string `gorm:"column:ip;primary_key;type:char(32)" json:"ip"` LimitRegister int32 `gorm:"column:limit_register" json:"limitRegister"` @@ -83,14 +83,14 @@ type IPForbidden struct { CreateTime time.Time `gorm:"column:create_time" json:"createTime"` } -// 限制userID只能在某些ip登录 +// Restrict userids to certain ip addresses type LimitUserLoginIP struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)" json:"userID"` IP string `gorm:"column:ip;primary_key;type:char(32)" json:"ip"` CreateTime time.Time `gorm:"column:create_time" json:"createTime"` } -// 邀请码被注册使用 +// The invitation code is registered for use type InvitationRegister struct { InvitationCode string `gorm:"column:invitation_code;primary_key;type:char(32)" json:"invitationCode"` CreateTime time.Time `gorm:"column:create_time" json:"createTime"` diff --git a/tools/data-conversion/chat/v3/admin/admin.go b/tools/data-conversion/chat/v3/admin/admin.go index 22a81a068..90bd7f8f7 100644 --- a/tools/data-conversion/chat/v3/admin/admin.go +++ b/tools/data-conversion/chat/v3/admin/admin.go @@ -18,7 +18,7 @@ import ( "time" ) -// Admin 后台管理员. +// Admin Background administrator. type Admin struct { Account string `gorm:"column:account;primary_key;type:varchar(64)"` Password string `gorm:"column:password;type:varchar(64)"` diff --git a/tools/data-conversion/chat/v3/admin/client_config.go b/tools/data-conversion/chat/v3/admin/client_config.go index ceccd5105..48869fceb 100644 --- a/tools/data-conversion/chat/v3/admin/client_config.go +++ b/tools/data-conversion/chat/v3/admin/client_config.go @@ -14,7 +14,7 @@ package admin -// ClientConfig 客户端相关配置项. +// ClientConfig Client related configuration items. type ClientConfig struct { Key string `gorm:"column:key;primary_key;type:varchar(255)"` Value string `gorm:"column:value;not null;type:text"` diff --git a/tools/data-conversion/chat/v3/admin/forbidden_account.go b/tools/data-conversion/chat/v3/admin/forbidden_account.go index 104e793b0..e08125699 100644 --- a/tools/data-conversion/chat/v3/admin/forbidden_account.go +++ b/tools/data-conversion/chat/v3/admin/forbidden_account.go @@ -18,7 +18,7 @@ import ( "time" ) -// ForbiddenAccount 封号表. +// ForbiddenAccount forbidden account. type ForbiddenAccount struct { UserID string `gorm:"column:user_id;index:userID;primary_key;type:char(64)"` Reason string `gorm:"column:reason;type:varchar(255)" ` diff --git a/tools/data-conversion/chat/v3/admin/invitation_register.go b/tools/data-conversion/chat/v3/admin/invitation_register.go index 60f9067e2..4b71ccfe0 100644 --- a/tools/data-conversion/chat/v3/admin/invitation_register.go +++ b/tools/data-conversion/chat/v3/admin/invitation_register.go @@ -18,7 +18,7 @@ import ( "time" ) -// 邀请码被注册使用. +// The invitation code is registered for use. type InvitationRegister struct { InvitationCode string `gorm:"column:invitation_code;primary_key;type:char(32)"` UsedByUserID string `gorm:"column:user_id;index:userID;type:char(64)"` diff --git a/tools/data-conversion/chat/v3/admin/ip_forbidden.go b/tools/data-conversion/chat/v3/admin/ip_forbidden.go index 40c9257ef..886924abb 100644 --- a/tools/data-conversion/chat/v3/admin/ip_forbidden.go +++ b/tools/data-conversion/chat/v3/admin/ip_forbidden.go @@ -18,7 +18,7 @@ import ( "time" ) -// 禁止ip登录 注册. +// ip login registration is prohibited. type IPForbidden struct { IP string `gorm:"column:ip;primary_key;type:char(32)"` LimitRegister bool `gorm:"column:limit_register"` diff --git a/tools/data-conversion/chat/v3/admin/limit_user_login_ip.go b/tools/data-conversion/chat/v3/admin/limit_user_login_ip.go index 8427eaf80..0eaa5bc1e 100644 --- a/tools/data-conversion/chat/v3/admin/limit_user_login_ip.go +++ b/tools/data-conversion/chat/v3/admin/limit_user_login_ip.go @@ -18,7 +18,7 @@ import ( "time" ) -// 限制userID只能在某些ip登录. +// Restrict userids to certain ip addresses. type LimitUserLoginIP struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)"` IP string `gorm:"column:ip;primary_key;type:char(32)"` diff --git a/tools/data-conversion/chat/v3/admin/register_add_friend.go b/tools/data-conversion/chat/v3/admin/register_add_friend.go index e21896d90..8281f6485 100644 --- a/tools/data-conversion/chat/v3/admin/register_add_friend.go +++ b/tools/data-conversion/chat/v3/admin/register_add_friend.go @@ -18,7 +18,7 @@ import ( "time" ) -// RegisterAddFriend 注册时默认好友. +// RegisterAddFriend Indicates the default friend when registering. type RegisterAddFriend struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)"` CreateTime time.Time `gorm:"column:create_time"` diff --git a/tools/data-conversion/chat/v3/admin/register_add_group.go b/tools/data-conversion/chat/v3/admin/register_add_group.go index e9c1317b9..1204ff97b 100644 --- a/tools/data-conversion/chat/v3/admin/register_add_group.go +++ b/tools/data-conversion/chat/v3/admin/register_add_group.go @@ -18,7 +18,7 @@ import ( "time" ) -// RegisterAddGroup 注册时默认群组. +// RegisterAddGroup Indicates the default group for registration. type RegisterAddGroup struct { GroupID string `gorm:"column:group_id;primary_key;type:char(64)"` CreateTime time.Time `gorm:"column:create_time"` diff --git a/tools/data-conversion/chat/v3/chat/account.go b/tools/data-conversion/chat/v3/chat/account.go index d2117e7ca..6d01c20e2 100644 --- a/tools/data-conversion/chat/v3/chat/account.go +++ b/tools/data-conversion/chat/v3/chat/account.go @@ -18,7 +18,7 @@ import ( "time" ) -// Account 账号密码表. +// Account Account password table. type Account struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)"` Password string `gorm:"column:password;type:varchar(32)"` diff --git a/tools/data-conversion/chat/v3/chat/attribute.go b/tools/data-conversion/chat/v3/chat/attribute.go index 6a6f975d1..23de217bd 100644 --- a/tools/data-conversion/chat/v3/chat/attribute.go +++ b/tools/data-conversion/chat/v3/chat/attribute.go @@ -18,7 +18,7 @@ import ( "time" ) -// Attribute 用户属性表. +// Attribute Indicates the user attribute table. type Attribute struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)"` Account string `gorm:"column:account;type:char(64)"` diff --git a/tools/data-conversion/chat/v3/chat/register.go b/tools/data-conversion/chat/v3/chat/register.go index 740159436..29e5cb698 100644 --- a/tools/data-conversion/chat/v3/chat/register.go +++ b/tools/data-conversion/chat/v3/chat/register.go @@ -18,7 +18,7 @@ import ( "time" ) -// Register 注册信息表. +// Register Indicates the registration information. type Register struct { UserID string `gorm:"column:user_id;primary_key;type:char(64)"` DeviceID string `gorm:"column:device_id;type:varchar(255)"` diff --git a/tools/data-conversion/chat/v3/chat/user_login_record.go b/tools/data-conversion/chat/v3/chat/user_login_record.go index 8db3699d6..31e57b6ce 100644 --- a/tools/data-conversion/chat/v3/chat/user_login_record.go +++ b/tools/data-conversion/chat/v3/chat/user_login_record.go @@ -18,7 +18,7 @@ import ( "time" ) -// 用户登录信息表. +// User login information table. type UserLoginRecord struct { UserID string `gorm:"column:user_id;size:64"` LoginTime time.Time `gorm:"column:login_time"` diff --git a/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go b/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go index f2b9623a6..416fdcb9f 100644 --- a/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go +++ b/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go @@ -38,11 +38,20 @@ import ( func main() { var ( - topic = "ws2ms_chat" // v2版本配置文件kafka.topic.ws2ms_chat - kafkaAddr = "127.0.0.1:9092" // v2版本配置文件kafka.topic.addr - rpcAddr = "127.0.0.1:10130" // v3版本配置文件rpcPort.openImMessagePort - adminUserID = "openIM123456" // v3版本管理员userID - concurrency = 1 // 并发数量 + // The Kafka topic for ws2ms_chat in version 2 configuration + topic = "ws2ms_chat" + + // The Kafka address in version 2 configuration + kafkaAddr = "127.0.0.1:9092" + + // The RPC address in version 3 configuration + rpcAddr = "127.0.0.1:10130" + + // The administrator userID in version 3 + adminUserID = "openIM123456" + + // The number of concurrent processes + concurrency = 1 ) getRpcConn := func() (*grpc.ClientConn, error) { @@ -99,7 +108,7 @@ func main() { ch := pc.Messages() for { select { - case <-time.After(time.Second * 10): // 10s读取不到就关闭 + case <-time.After(time.Second * 10): // 10s Shuts down when the data cannot be read return case message, ok := <-ch: if !ok { diff --git a/tools/data-conversion/openim/cmd/conversion-mysql/conversion-mysql.go b/tools/data-conversion/openim/cmd/conversion-mysql/conversion-mysql.go index 8a951e16f..08fa4ca55 100644 --- a/tools/data-conversion/openim/cmd/conversion-mysql/conversion-mysql.go +++ b/tools/data-conversion/openim/cmd/conversion-mysql/conversion-mysql.go @@ -27,21 +27,37 @@ import ( ) func main() { + var ( - usernameV2 = "root" // v2版本mysql用户名 - passwordV2 = "openIM" // v2版本mysql密码 - addrV2 = "127.0.0.1:13306" // v2版本mysql地址 - databaseV2 = "openIM_v2" // v2版本mysql数据库名字 + // MySQL username for version 2 + usernameV2 = "root" + + // MySQL password for version 2 + passwordV2 = "openIM" + + // MySQL address for version 2 + addrV2 = "127.0.0.1:13306" + + // MySQL database name for version 2 + databaseV2 = "openIM_v2" ) var ( - usernameV3 = "root" // v3版本mysql用户名 - passwordV3 = "openIM123" // v3版本mysql密码 - addrV3 = "127.0.0.1:13306" // v3版本mysql地址 - databaseV3 = "openim_v3" // v3版本mysql数据库名字 + // MySQL username for version 3 + usernameV3 = "root" + + // MySQL password for version 3 + passwordV3 = "openIM123" + + // MySQL address for version 3 + addrV3 = "127.0.0.1:13306" + + // MySQL database name for version 3 + databaseV3 = "openim_v3" ) - var concurrency = 1 // 并发数量 + // The number of concurrent processes + var concurrency = 1 log.SetFlags(log.LstdFlags | log.Llongfile) dsnV2 := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", usernameV2, passwordV2, addrV2, databaseV2) diff --git a/tools/data-conversion/openim/mysql/v3/friend.go b/tools/data-conversion/openim/mysql/v3/friend.go index 58d8d1d34..4f3fb6bdf 100644 --- a/tools/data-conversion/openim/mysql/v3/friend.go +++ b/tools/data-conversion/openim/mysql/v3/friend.go @@ -38,41 +38,30 @@ func (FriendModel) TableName() string { } type FriendModelInterface interface { - // 插入多条记录 - Create(ctx context.Context, friends []*FriendModel) (err error) - // 删除ownerUserID指定的好友 - Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error) - // 更新ownerUserID单个好友信息 更新零值 - UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) (err error) - // 更新好友信息的非零值 - Update(ctx context.Context, friends []*FriendModel) (err error) - // 更新好友备注(也支持零值 ) - UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error) - // 获取单个好友信息,如没找到 返回错误 - Take(ctx context.Context, ownerUserID, friendUserID string) (friend *FriendModel, err error) - // 查找好友关系,如果是双向关系,则都返回 - FindUserState(ctx context.Context, userID1, userID2 string) (friends []*FriendModel, err error) - // 获取 owner指定的好友列表 如果有friendUserIDs不存在,也不返回错误 - FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*FriendModel, err error) - // 获取哪些人添加了friendUserID 如果有ownerUserIDs不存在,也不返回错误 - FindReversalFriends( - ctx context.Context, - friendUserID string, - ownerUserIDs []string, - ) (friends []*FriendModel, err error) - // 获取ownerUserID好友列表 支持翻页 - FindOwnerFriends( - ctx context.Context, - ownerUserID string, - pageNumber, showNumber int32, - ) (friends []*FriendModel, total int64, err error) - // 获取哪些人添加了friendUserID 支持翻页 - FindInWhoseFriends( - ctx context.Context, - friendUserID string, - pageNumber, showNumber int32, - ) (friends []*FriendModel, total int64, err error) - // 获取好友UserID列表 - FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) + // Create inserts multiple friend records. + Create(ctx context.Context, friends []*FriendModel) error + // Delete removes specified friends for an owner user. + Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) error + // UpdateByMap updates a single friend's information for an owner user based on a map of arguments. Zero values are updated. + UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) error + // Update modifies the information of friends, excluding zero values. + Update(ctx context.Context, friends []*FriendModel) error + // UpdateRemark updates the remark for a friend, supporting zero values. + UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) error + // Take retrieves a single friend's information. Returns an error if not found. + Take(ctx context.Context, ownerUserID, friendUserID string) (*FriendModel, error) + // FindUserState finds the friendship status between two users, returning both if a mutual friendship exists. + FindUserState(ctx context.Context, userID1, userID2 string) ([]*FriendModel, error) + // FindFriends retrieves a list of friends for an owner, not returning an error for non-existent friendUserIDs. + FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) ([]*FriendModel, error) + // FindReversalFriends finds who has added the specified user as a friend, not returning an error for non-existent ownerUserIDs. + FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) ([]*FriendModel, error) + // FindOwnerFriends paginates through the friends list of an owner user. + FindOwnerFriends(ctx context.Context, ownerUserID string, pageNumber, showNumber int32) ([]*FriendModel, int64, error) + // FindInWhoseFriends paginates through users who have added the specified user as a friend. + FindInWhoseFriends(ctx context.Context, friendUserID string, pageNumber, showNumber int32) ([]*FriendModel, int64, error) + // FindFriendUserIDs retrieves a list of friend user IDs for an owner user. + FindFriendUserIDs(ctx context.Context, ownerUserID string) ([]string, error) + // NewTx creates a new transactional instance of the FriendModelInterface. NewTx(tx any) FriendModelInterface } diff --git a/tools/data-conversion/openim/mysql/v3/friend_request.go b/tools/data-conversion/openim/mysql/v3/friend_request.go index 51ea0ef6e..4fc5ba7c1 100644 --- a/tools/data-conversion/openim/mysql/v3/friend_request.go +++ b/tools/data-conversion/openim/mysql/v3/friend_request.go @@ -38,29 +38,33 @@ func (FriendRequestModel) TableName() string { } type FriendRequestModelInterface interface { - // 插入多条记录 + // Insert multiple records Create(ctx context.Context, friendRequests []*FriendRequestModel) (err error) - // 删除记录 + + // Delete a record Delete(ctx context.Context, fromUserID, toUserID string) (err error) - // 更新零值 - UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]interface{}) (err error) - // 更新多条记录 (非零值) + + // Update records with zero values based on a map of changes + UpdateByMap(ctx context.Context, formUserID, toUserID string, args map[string]interface{}) (err error) + + // Update multiple records (non-zero values) Update(ctx context.Context, friendRequest *FriendRequestModel) (err error) - // 获取来指定用户的好友申请 未找到 不返回错误 + + // Find a friend request sent to a specific user; does not return an error if not found Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error) + + // Alias for Find (retrieves a friend request between two users) Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error) - // 获取toUserID收到的好友申请列表 - FindToUserID( - ctx context.Context, - toUserID string, - pageNumber, showNumber int32, - ) (friendRequests []*FriendRequestModel, total int64, err error) - // 获取fromUserID发出去的好友申请列表 - FindFromUserID( - ctx context.Context, - fromUserID string, - pageNumber, showNumber int32, - ) (friendRequests []*FriendRequestModel, total int64, err error) + + // Get a list of friend requests received by `toUserID` + FindToUserID(ctx context.Context, toUserID string, pageNumber, showNumber int32) (friendRequests []*FriendRequestModel, total int64, err error) + + // Get a list of friend requests sent by `fromUserID` + FindFromUserID(ctx context.Context, fromUserID string, pageNumber, showNumber int32) (friendRequests []*FriendRequestModel, total int64, err error) + + // Find all friend requests between two users (both directions) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*FriendRequestModel, err error) + + // Create a new transaction NewTx(tx any) FriendRequestModelInterface } diff --git a/tools/data-conversion/openim/mysql/v3/group.go b/tools/data-conversion/openim/mysql/v3/group.go index 6759e0d35..ccf61266a 100644 --- a/tools/data-conversion/openim/mysql/v3/group.go +++ b/tools/data-conversion/openim/mysql/v3/group.go @@ -58,9 +58,10 @@ type GroupModelInterface interface { keyword string, pageNumber, showNumber int32, ) (total uint32, groups []*GroupModel, err error) + // GetGroupIDsByCreatorUserID retrieves a list of group IDs created by the specified user. GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error) - // 获取群总数 + // CountTotal retrieves the total number of groups. CountTotal(ctx context.Context, before *time.Time) (count int64, err error) - // 获取范围内群增量 + // CountRangeEverydayTotal retrieves the total number of groups created every day within the specified time range. CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) } diff --git a/tools/data-conversion/openim/mysql/v3/user.go b/tools/data-conversion/openim/mysql/v3/user.go index 10a715bda..409689933 100644 --- a/tools/data-conversion/openim/mysql/v3/user.go +++ b/tools/data-conversion/openim/mysql/v3/user.go @@ -53,20 +53,35 @@ func (UserModel) TableName() string { return UserModelTableName } +// UserModelInterface defines the operations available for managing user models. type UserModelInterface interface { + // Create inserts a new user or multiple users into the database. Create(ctx context.Context, users []*UserModel) (err error) + + // UpdateByMap updates a user's information based on a map of changes. UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error) + + // Update modifies a user's information in the database. Update(ctx context.Context, user *UserModel) (err error) - // 获取指定用户信息 不存在,也不返回错误 + + // Find retrieves information for a list of users by their IDs. If a user does not exist, it is simply skipped without returning an error. Find(ctx context.Context, userIDs []string) (users []*UserModel, err error) - // 获取某个用户信息 不存在,则返回错误 + + // Take retrieves a specific user's information by their ID. Returns an error if the user does not exist. Take(ctx context.Context, userID string) (user *UserModel, err error) - // 获取用户信息 不存在,不返回错误 + + // Page retrieves a paginated list of users and the total count of users. If no users exist, returns an empty list without an error. Page(ctx context.Context, pageNumber, showNumber int32) (users []*UserModel, count int64, err error) + + // GetAllUserID retrieves all user IDs in a paginated manner. GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) + + // GetUserGlobalRecvMsgOpt retrieves a user's global message receiving option. GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) - // 获取用户总数 + + // CountTotal returns the total number of users before a specified time. CountTotal(ctx context.Context, before *time.Time) (count int64, err error) - // 获取范围内用户增量 + + // CountRangeEverydayTotal calculates the daily increment of users within a specified time range. CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) } diff --git a/tools/formitychecker/checker/checker.go b/tools/formitychecker/checker/checker.go index c9ad8239f..b17cc5427 100644 --- a/tools/formitychecker/checker/checker.go +++ b/tools/formitychecker/checker/checker.go @@ -21,6 +21,8 @@ import ( "regexp" "strings" + "github.com/OpenIMSDK/tools/errs" + "github.com/openimsdk/open-im-server/tools/formitychecker/config" ) @@ -39,7 +41,7 @@ func CheckDirectory(cfg *config.Config) error { for _, targetDir := range cfg.TargetDirs { err := filepath.Walk(targetDir, func(path string, info os.FileInfo, err error) error { if err != nil { - return err + return errs.Wrap(err, fmt.Sprintf("error walking directory '%s'", targetDir)) } // Skip if the directory is in the ignore list diff --git a/tools/infra/infra.go b/tools/infra/infra.go index c14b92fa3..bc01a00eb 100644 --- a/tools/infra/infra.go +++ b/tools/infra/infra.go @@ -20,7 +20,7 @@ import ( "github.com/fatih/color" ) -// 定义一个函数以打印重要的链接信息 +// Define a function to print important link information func printLinks() { blue := color.New(color.FgBlue).SprintFunc() fmt.Printf("OpenIM Github: %s\n", blue("https://github.com/OpenIMSDK/Open-IM-Server")) @@ -47,5 +47,5 @@ Keep checking for updates! ` blue.Println(message) - printLinks() // 调用函数以打印链接信息 + printLinks() // Call the function to print the link information } diff --git a/tools/url2im/main.go b/tools/url2im/main.go index 8d6151b09..9e319932f 100644 --- a/tools/url2im/main.go +++ b/tools/url2im/main.go @@ -31,17 +31,38 @@ import ( */ func main() { - var conf pkg.Config // 后面带*的为必填项 - flag.StringVar(&conf.TaskPath, "task", "take.txt", "task path") // 任务日志文件* - flag.StringVar(&conf.ProgressPath, "progress", "", "progress path") // 进度日志文件 - flag.IntVar(&conf.Concurrency, "concurrency", 1, "concurrency num") // 并发数 - flag.IntVar(&conf.Retry, "retry", 1, "retry num") // 重试次数 - flag.StringVar(&conf.TempDir, "temp", "", "temp dir") // 临时文件夹 - flag.Int64Var(&conf.CacheSize, "cache", 1024*1024*100, "cache size") // 缓存大小(超过时,下载到磁盘) - flag.Int64Var((*int64)(&conf.Timeout), "timeout", 5000, "timeout") // 请求超时时间(毫秒) - flag.StringVar(&conf.Api, "api", "http://127.0.0.1:10002", "api") // im地址* - flag.StringVar(&conf.UserID, "userID", "openIM123456", "userID") // im管理员 - flag.StringVar(&conf.Secret, "secret", "openIM123", "secret") // im config secret + var conf pkg.Config // Configuration object, '*' denotes required fields + + // *Required*: Path for the task log file + flag.StringVar(&conf.TaskPath, "task", "take.txt", "Path for the task log file") + + // Optional: Path for the progress log file + flag.StringVar(&conf.ProgressPath, "progress", "", "Path for the progress log file") + + // Number of concurrent operations + flag.IntVar(&conf.Concurrency, "concurrency", 1, "Number of concurrent operations") + + // Number of retry attempts + flag.IntVar(&conf.Retry, "retry", 1, "Number of retry attempts") + + // Optional: Path for the temporary directory + flag.StringVar(&conf.TempDir, "temp", "", "Path for the temporary directory") + + // Cache size in bytes (downloads move to disk when exceeded) + flag.Int64Var(&conf.CacheSize, "cache", 1024*1024*100, "Cache size in bytes") + + // Request timeout in milliseconds + flag.Int64Var((*int64)(&conf.Timeout), "timeout", 5000, "Request timeout in milliseconds") + + // *Required*: API endpoint for the IM service + flag.StringVar(&conf.Api, "api", "http://127.0.0.1:10002", "API endpoint for the IM service") + + // IM administrator's user ID + flag.StringVar(&conf.UserID, "userID", "openIM123456", "IM administrator's user ID") + + // Secret for the IM configuration + flag.StringVar(&conf.Secret, "secret", "openIM123", "Secret for the IM configuration") + flag.Parse() if !filepath.IsAbs(conf.TaskPath) { var err error