diff --git a/.github/workflows/auto-invite.yml b/.github/workflows/auto-invite.yml index 40433ef5f..f37271f1e 100644 --- a/.github/workflows/auto-invite.yml +++ b/.github/workflows/auto-invite.yml @@ -41,7 +41,7 @@ jobs: + We also have Slack channels for you to communicate and discuss. To join, visit https://slack.com/ and join our [👀 Open-IM-Server slack](https://join.slack.com/t/openimsdk/shared_invite/zt-1tmoj26uf-_FDy3dowVHBiGvLk9e5Xkg) team channel. + Get in touch with us on [Gmail](https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=winxu81@gmail.com). If you have any questions or issues that need resolving, or any suggestions and feedback for our open source projects, please feel free to contact us via email. + Read our [blog](https://doc.rentsoft.cn/). Our blog is a great place to stay up-to-date with Open-IM-Server projects and trends. On the blog, we share our latest developments, tech trends, and other interesting information. - + Add [Wechat](https://github.com/OpenIMSDK/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of Open-IM-Server. We will process your request as soon as possible. + + Add [Wechat](https://github.com/openimsdk/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of Open-IM-Server. We will process your request as soon as possible. - name: Close Issue uses: peter-evans/close-issue@v3 diff --git a/.golangci.yml b/.golangci.yml index 7d1c82d6d..774fe29ad 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -176,7 +176,7 @@ linters-settings: # put imports beginning with prefix after 3rd-party packages; # only support one prefix # if not set, use goimports.local-prefixes - prefix: github.com/OpenIMSDK/openim-sdk-core + prefix: github.com/openimsdk/openim-sdk-core gocognit: # minimal code complexity to report, 30 by default (but we recommend 10-20) min-complexity: 30 @@ -333,7 +333,7 @@ linters-settings: goimports: # put imports beginning with prefix after 3rd-party packages; # it's a comma-separated list of prefixes - local-prefixes: github.com/OpenIMSDK/openim-sdk-core + local-prefixes: github.com/openimsdk/openim-sdk-core golint: # minimal confidence for issues, default is 0.8 min-confidence: 0.9 diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 6be41a5d4..9fa65aefb 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -58,8 +58,8 @@ builds: - amd64 - arm64 goarm: - - 6 - - 7 + - "6" + - "7" - id: openIM.wasm main: wasm/cmd/main.go # 指定 wasm 主文件路径 binary: openIM.wasm @@ -155,7 +155,7 @@ nfpms: - openIM.wasm # Your app's vendor. vendor: OpenIMSDK - homepage: https://github.com/OpenIMSDK/openim-sdk-core + homepage: https://github.com/openimsdk/openim-sdk-core maintainer: kubbot description: |- Auto sync github labels diff --git a/CHANGELOG/.chglog/config.yml b/CHANGELOG/.chglog/config.yml index c11e987cc..290193082 100644 --- a/CHANGELOG/.chglog/config.yml +++ b/CHANGELOG/.chglog/config.yml @@ -17,7 +17,7 @@ style: github template: CHANGELOG.tpl.md info: title: CHANGELOG - repository_url: https://github.com/OpenIMSDK/openim-sdk-core + repository_url: https://github.com/openimsdk/openim-sdk-core options: tag_filter_pattern: '^v' sort: "date" diff --git a/CHANGELOG/CHANGELOG-1.0.md b/CHANGELOG/CHANGELOG-1.0.md index b8539a901..52983b359 100644 --- a/CHANGELOG/CHANGELOG-1.0.md +++ b/CHANGELOG/CHANGELOG-1.0.md @@ -32,11 +32,11 @@ ## v1.0.0 - 2021-10-28 -[Unreleased]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.7...HEAD -[v1.0.7]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.6...v1.0.7 -[v1.0.6]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.5...v1.0.6 -[v1.0.5]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.4...v1.0.5 -[v1.0.4]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.3...v1.0.4 -[v1.0.3]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.2...v1.0.3 -[v1.0.2]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.1...v1.0.2 -[v1.0.1]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.0...v1.0.1 +[Unreleased]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.7...HEAD +[v1.0.7]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.6...v1.0.7 +[v1.0.6]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.5...v1.0.6 +[v1.0.5]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.4...v1.0.5 +[v1.0.4]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.3...v1.0.4 +[v1.0.3]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.2...v1.0.3 +[v1.0.2]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.1...v1.0.2 +[v1.0.1]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.0...v1.0.1 diff --git a/CHANGELOG/CHANGELOG-2.0.md b/CHANGELOG/CHANGELOG-2.0.md index 4d9cb747c..76bef9093 100644 --- a/CHANGELOG/CHANGELOG-2.0.md +++ b/CHANGELOG/CHANGELOG-2.0.md @@ -75,18 +75,18 @@ ## v2.0.0 - 2022-02-23 -[Unreleased]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.3.3...HEAD -[v2.3.3]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.3.2...v2.3.3 -[v2.3.2]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.3.0-rc0...v2.3.2 -[v2.3.0-rc0]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.2.0...v2.3.0-rc0 -[v2.2.0]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.1.0...v2.2.0 -[v2.1.0]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.9...v2.1.0 -[v2.0.9]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.8...v2.0.9 -[v2.0.8]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.7...v2.0.8 -[v2.0.7]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.6...v2.0.7 -[v2.0.6]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.5...v2.0.6 -[v2.0.5]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.4...v2.0.5 -[v2.0.4]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.3...v2.0.4 -[v2.0.3]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.2...v2.0.3 -[v2.0.2]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.1...v2.0.2 -[v2.0.1]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.0...v2.0.1 +[Unreleased]: https://github.com/openimsdk/openim-sdk-core/compare/v2.3.3...HEAD +[v2.3.3]: https://github.com/openimsdk/openim-sdk-core/compare/v2.3.2...v2.3.3 +[v2.3.2]: https://github.com/openimsdk/openim-sdk-core/compare/v2.3.0-rc0...v2.3.2 +[v2.3.0-rc0]: https://github.com/openimsdk/openim-sdk-core/compare/v2.2.0...v2.3.0-rc0 +[v2.2.0]: https://github.com/openimsdk/openim-sdk-core/compare/v2.1.0...v2.2.0 +[v2.1.0]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.9...v2.1.0 +[v2.0.9]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.8...v2.0.9 +[v2.0.8]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.7...v2.0.8 +[v2.0.7]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.6...v2.0.7 +[v2.0.6]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.5...v2.0.6 +[v2.0.5]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.4...v2.0.5 +[v2.0.4]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.3...v2.0.4 +[v2.0.3]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.2...v2.0.3 +[v2.0.2]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.1...v2.0.2 +[v2.0.1]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.0...v2.0.1 diff --git a/CHANGELOG/CHANGELOG-2.1.md b/CHANGELOG/CHANGELOG-2.1.md index 9a21ae247..83a4cda9d 100644 --- a/CHANGELOG/CHANGELOG-2.1.md +++ b/CHANGELOG/CHANGELOG-2.1.md @@ -20,4 +20,4 @@ - Merge branch 'tuoyun' -[Unreleased]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.1.0...HEAD +[Unreleased]: https://github.com/openimsdk/openim-sdk-core/compare/v2.1.0...HEAD diff --git a/CHANGELOG/CHANGELOG-2.2.md b/CHANGELOG/CHANGELOG-2.2.md index 42a0c8927..7cd31b116 100644 --- a/CHANGELOG/CHANGELOG-2.2.md +++ b/CHANGELOG/CHANGELOG-2.2.md @@ -21,4 +21,4 @@ - Merge branch 'tuoyun' -[Unreleased]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.2.0...HEAD +[Unreleased]: https://github.com/openimsdk/openim-sdk-core/compare/v2.2.0...HEAD diff --git a/CHANGELOG/CHANGELOG-2.3.md b/CHANGELOG/CHANGELOG-2.3.md index 9b06d6d0f..77833bf47 100644 --- a/CHANGELOG/CHANGELOG-2.3.md +++ b/CHANGELOG/CHANGELOG-2.3.md @@ -27,6 +27,6 @@ - Merge branch 'tuoyun' -[Unreleased]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.3.3...HEAD -[v2.3.3]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.3.2...v2.3.3 -[v2.3.2]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.3.0-rc0...v2.3.2 +[Unreleased]: https://github.com/openimsdk/openim-sdk-core/compare/v2.3.3...HEAD +[v2.3.3]: https://github.com/openimsdk/openim-sdk-core/compare/v2.3.2...v2.3.3 +[v2.3.2]: https://github.com/openimsdk/openim-sdk-core/compare/v2.3.0-rc0...v2.3.2 diff --git a/CHANGELOG/CHANGELOG-2.9.md b/CHANGELOG/CHANGELOG-2.9.md index b51212ba8..1463f52dc 100644 --- a/CHANGELOG/CHANGELOG-2.9.md +++ b/CHANGELOG/CHANGELOG-2.9.md @@ -38,15 +38,15 @@ ## v2.9.0 - 2023-07-04 ### Reverts -- update etcd to v3.5.2 ([#206](https://github.com/OpenIMSDK/Open-IM-Server/issues/206)) +- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/Open-IM-Server/issues/206)) ### Pull Requests - Merge branch 'tuoyun' -[Unreleased]: https://github.com/OpenIMSDK/Open-IM-Server/compare/v2.9.0+1.839643f...HEAD -[v2.9.0+1.839643f]: https://github.com/OpenIMSDK/Open-IM-Server/compare/v2.9.0+2.35f07fe...v2.9.0+1.839643f -[v2.9.0+2.35f07fe]: https://github.com/OpenIMSDK/Open-IM-Server/compare/v2.9.0+1.b5072b1...v2.9.0+2.35f07fe -[v2.9.0+1.b5072b1]: https://github.com/OpenIMSDK/Open-IM-Server/compare/v2.9.0+3.2667a3a...v2.9.0+1.b5072b1 -[v2.9.0+3.2667a3a]: https://github.com/OpenIMSDK/Open-IM-Server/compare/v2.9.0+7.04818ca...v2.9.0+3.2667a3a -[v2.9.0+7.04818ca]: https://github.com/OpenIMSDK/Open-IM-Server/compare/v2.9.0...v2.9.0+7.04818ca +[Unreleased]: https://github.com/openimsdk/Open-IM-Server/compare/v2.9.0+1.839643f...HEAD +[v2.9.0+1.839643f]: https://github.com/openimsdk/Open-IM-Server/compare/v2.9.0+2.35f07fe...v2.9.0+1.839643f +[v2.9.0+2.35f07fe]: https://github.com/openimsdk/Open-IM-Server/compare/v2.9.0+1.b5072b1...v2.9.0+2.35f07fe +[v2.9.0+1.b5072b1]: https://github.com/openimsdk/Open-IM-Server/compare/v2.9.0+3.2667a3a...v2.9.0+1.b5072b1 +[v2.9.0+3.2667a3a]: https://github.com/openimsdk/Open-IM-Server/compare/v2.9.0+7.04818ca...v2.9.0+3.2667a3a +[v2.9.0+7.04818ca]: https://github.com/openimsdk/Open-IM-Server/compare/v2.9.0...v2.9.0+7.04818ca diff --git a/CHANGELOG/CHANGELOG-3.0.md b/CHANGELOG/CHANGELOG-3.0.md index 6f342f515..4b1279302 100644 --- a/CHANGELOG/CHANGELOG-3.0.md +++ b/CHANGELOG/CHANGELOG-3.0.md @@ -102,27 +102,27 @@ ## v1.0.0 - 2021-10-28 -[Unreleased]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v3.0.0-rc.1...HEAD -[v3.0.0-rc.1]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.3.3...v3.0.0-rc.1 -[v2.3.3]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.3.2...v2.3.3 -[v2.3.2]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.3.0-rc0...v2.3.2 -[v2.3.0-rc0]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.2.0...v2.3.0-rc0 -[v2.2.0]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.1.0...v2.2.0 -[v2.1.0]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.9...v2.1.0 -[v2.0.9]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.8...v2.0.9 -[v2.0.8]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.7...v2.0.8 -[v2.0.7]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.6...v2.0.7 -[v2.0.6]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.5...v2.0.6 -[v2.0.5]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.4...v2.0.5 -[v2.0.4]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.3...v2.0.4 -[v2.0.3]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.2...v2.0.3 -[v2.0.2]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.1...v2.0.2 -[v2.0.1]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v2.0.0...v2.0.1 -[v2.0.0]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.7...v2.0.0 -[v1.0.7]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.6...v1.0.7 -[v1.0.6]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.5...v1.0.6 -[v1.0.5]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.4...v1.0.5 -[v1.0.4]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.3...v1.0.4 -[v1.0.3]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.2...v1.0.3 -[v1.0.2]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.1...v1.0.2 -[v1.0.1]: https://github.com/OpenIMSDK/openim-sdk-core/compare/v1.0.0...v1.0.1 +[Unreleased]: https://github.com/openimsdk/openim-sdk-core/compare/v3.0.0-rc.1...HEAD +[v3.0.0-rc.1]: https://github.com/openimsdk/openim-sdk-core/compare/v2.3.3...v3.0.0-rc.1 +[v2.3.3]: https://github.com/openimsdk/openim-sdk-core/compare/v2.3.2...v2.3.3 +[v2.3.2]: https://github.com/openimsdk/openim-sdk-core/compare/v2.3.0-rc0...v2.3.2 +[v2.3.0-rc0]: https://github.com/openimsdk/openim-sdk-core/compare/v2.2.0...v2.3.0-rc0 +[v2.2.0]: https://github.com/openimsdk/openim-sdk-core/compare/v2.1.0...v2.2.0 +[v2.1.0]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.9...v2.1.0 +[v2.0.9]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.8...v2.0.9 +[v2.0.8]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.7...v2.0.8 +[v2.0.7]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.6...v2.0.7 +[v2.0.6]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.5...v2.0.6 +[v2.0.5]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.4...v2.0.5 +[v2.0.4]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.3...v2.0.4 +[v2.0.3]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.2...v2.0.3 +[v2.0.2]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.1...v2.0.2 +[v2.0.1]: https://github.com/openimsdk/openim-sdk-core/compare/v2.0.0...v2.0.1 +[v2.0.0]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.7...v2.0.0 +[v1.0.7]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.6...v1.0.7 +[v1.0.6]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.5...v1.0.6 +[v1.0.5]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.4...v1.0.5 +[v1.0.4]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.3...v1.0.4 +[v1.0.3]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.2...v1.0.3 +[v1.0.2]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.1...v1.0.2 +[v1.0.1]: https://github.com/openimsdk/openim-sdk-core/compare/v1.0.0...v1.0.1 diff --git a/CHANGELOG/CHANGELOG.md b/CHANGELOG/CHANGELOG.md index 2d788d4c4..b9bafd1a1 100644 --- a/CHANGELOG/CHANGELOG.md +++ b/CHANGELOG/CHANGELOG.md @@ -13,7 +13,7 @@ All notable changes to this project will be documented in this file. -+ [https://github.com/OpenIMSDK/Open-IM-Server/releases](https://github.com/OpenIMSDK/Open-IM-Server/releases) ++ [https://github.com/openimsdk/Open-IM-Server/releases](https://github.com/openimsdk/Open-IM-Server/releases) ## command diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d63f6ce67..b42bdbaed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,7 +34,7 @@ The [Makefile](./Makefile) is for every developer, even if you don't know how to #### Code and doc contribution -Every action to make project OpenIM better is encouraged. On GitHub, every improvement for OpenIM could be via a [PR](https://github.com/OpenIMSDK/openim-sdk-core/pulls) (short for pull request). +Every action to make project OpenIM better is encouraged. On GitHub, every improvement for OpenIM could be via a [PR](https://github.com/openimsdk/openim-sdk-core/pulls) (short for pull request). + If you find a typo, try to fix it! + If you find a bug, try to fix it! @@ -49,22 +49,22 @@ Every action to make project OpenIM better is encouraged. On GitHub, every impro #### Where should I start? -Getting good at GitHub is the first step, we have a [list of labes](https://github.com/OpenIMSDK/openim-sdk-core/labels) and reading some of the [common tags](https://github.com/OpenIMSDK/openim-sdk-core/labels?sort=count-desc) helps us get involved in the community quickly.GitHub allows you to filter out types of issues and pull requests, which helps you discover items in need of triaging. This table includes some predetermined searches for convenience: +Getting good at GitHub is the first step, we have a [list of labes](https://github.com/openimsdk/openim-sdk-core/labels) and reading some of the [common tags](https://github.com/openimsdk/openim-sdk-core/labels?sort=count-desc) helps us get involved in the community quickly.GitHub allows you to filter out types of issues and pull requests, which helps you discover items in need of triaging. This table includes some predetermined searches for convenience: | Search | What it sorts | | ------------------------------------------------------------ | ------------------------------------------------------- | -| [created-asc](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Acreated-asc) | Untriaged issues by age | -| [needs-triage](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+no%3Alabel) | Issues that need to be assigned to a Labels | -| [`is:open is:issue`](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aopen+is%3Aissue+sort%3Aupdated-desc) | Newest incoming issues | -| [comments-desc](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Acomments-desc) | Busiest untriaged issues, sorted by # of comments | -| [comments-asc](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Acomments-asc) | Issues that need more attention, based on # of comments | +| [created-asc](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Acreated-asc) | Untriaged issues by age | +| [needs-triage](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+no%3Alabel) | Issues that need to be assigned to a Labels | +| [`is:open is:issue`](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aopen+is%3Aissue+sort%3Aupdated-desc) | Newest incoming issues | +| [comments-desc](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Acomments-desc) | Busiest untriaged issues, sorted by # of comments | +| [comments-asc](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Acomments-asc) | Issues that need more attention, based on # of comments | We suggest preparing your triage by filtering out the oldest, unlabelled issues and pull requests first. -1. If you are new to the project, don't know how to contribute OpenIM, please check out the [good first issue](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aopen+label%3A"good+first+issue"+sort%3Aupdated-desc) label and [help wanted](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aopen+is%3Aissue+label%3A"help+wanted"+sort%3Aupdated-desc). -2. You should be good at filtering the OpenIM issue tags and finding the ones you like, such as [RFC](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) for big initiatives, features for [feature](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+label%3Akind%2Ffeature+sort%3Aupdated-desc+) proposals, and [bug](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+label%3Akind%2Fbug+sort%3Aupdated-desc+) fixes. -3. If you are looking for something to work on, check out our [open issues](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc). -4. If you have an idea for a new feature, please [open an issue](https://github.com/OpenIMSDK/openim-sdk-core/issues/new/choose), and we can discuss it. +1. If you are new to the project, don't know how to contribute OpenIM, please check out the [good first issue](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aopen+label%3A"good+first+issue"+sort%3Aupdated-desc) label and [help wanted](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aopen+is%3Aissue+label%3A"help+wanted"+sort%3Aupdated-desc). +2. You should be good at filtering the OpenIM issue tags and finding the ones you like, such as [RFC](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) for big initiatives, features for [feature](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+label%3Akind%2Ffeature+sort%3Aupdated-desc+) proposals, and [bug](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+label%3Akind%2Fbug+sort%3Aupdated-desc+) fixes. +3. If you are looking for something to work on, check out our [open issues](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc). +4. If you have an idea for a new feature, please [open an issue](https://github.com/openimsdk/openim-sdk-core/issues/new/choose), and we can discuss it. > **Note** > Reply to `/assign` or `/assign @yourself` with a question you wish to resolve, and we'll assign the question to you and your name will be listed under `Assignees` @@ -73,7 +73,7 @@ We suggest preparing your triage by filtering out the oldest, unlabelled issues #### Design documents -For any substantial design, there should be a well-crafted design document. This document is not just a simple record, but also a detailed description and manifestation, which can help team members better understand the design thinking and grasp the design direction. In the process of writing the design document, we can choose to use tools such as `Google Docs` or `Notion`, and even mark **RFC** in [issues](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) or [discussions](https://github.com/OpenIMSDK/openim-sdk-core/discussions) for better collaboration. Of course, after completing the design document, we should also add it to our [Shared Drive](https://drive.google.com/drive/) and notify the appropriate working group to let everyone know of its existence. Only by doing so can we maximize the effectiveness of the design document and provide strong support for the smooth progress of the project. +For any substantial design, there should be a well-crafted design document. This document is not just a simple record, but also a detailed description and manifestation, which can help team members better understand the design thinking and grasp the design direction. In the process of writing the design document, we can choose to use tools such as `Google Docs` or `Notion`, and even mark **RFC** in [issues](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) or [discussions](https://github.com/openimsdk/openim-sdk-core/discussions) for better collaboration. Of course, after completing the design document, we should also add it to our [Shared Drive](https://drive.google.com/drive/) and notify the appropriate working group to let everyone know of its existence. Only by doing so can we maximize the effectiveness of the design document and provide strong support for the smooth progress of the project. Anybody can access the shared Drive for reading. To get access to comment. Once you've done that, head to the [shared Drive](https://drive.google.com/) and behold all the docs. @@ -104,10 +104,10 @@ To propose PR for the OpenIM item, we assume you have registered a GitHub ID. Th 2. **CLONE** your own repository to master locally. Use `git clone https://github.com//OpenIM.git` to clone repository to your local machine. Then you can create new branches to finish the change you wish to make. -3. **Set Remote** upstream to be `https://github.com/OpenIMSDK/openim-sdk-core.git` using the following two commands: +3. **Set Remote** upstream to be `https://github.com/openimsdk/openim-sdk-core.git` using the following two commands: ```bash - ❯ git remote add upstream https://github.com/OpenIMSDK/openim-sdk-core.git + ❯ git remote add upstream https://github.com/openimsdk/openim-sdk-core.git ❯ git remote set-url --push upstream no-pushing ``` @@ -117,7 +117,7 @@ To propose PR for the OpenIM item, we assume you have registered a GitHub ID. Th ❯ git remote -v origin https://github.com//OpenIM.git (fetch) origin https://github.com//OpenIM.git (push) - upstream https://github.com/OpenIMSDK/openim-sdk-core.git (fetch) + upstream https://github.com/openimsdk/openim-sdk-core.git (fetch) upstream no-pushing (push) ``` @@ -201,11 +201,11 @@ Instead we encourage you to send us a private email to 📮[winxu81@gmail.com](h #### Reporting general issues -To be honest, we regard every user of OpenIMas a very kind contributor. After experiencing OpenIM, you may have some feedback for the project. Then feel free to open an issue via [NEW ISSUE](https://github.com/OpenIMSDK/openim-sdk-core/issues/new/choose). +To be honest, we regard every user of OpenIMas a very kind contributor. After experiencing OpenIM, you may have some feedback for the project. Then feel free to open an issue via [NEW ISSUE](https://github.com/openimsdk/openim-sdk-core/issues/new/choose). Since we collaborate project OpenIM in a distributed way, we appreciate **WELL-WRITTEN**, **DETAILED**, **EXPLICIT** issue reports. To make the communication more efficient, we wish everyone could search if your issue is an existing one in the searching list. If you find it existing, please add your details in comments under the existing issue instead of opening a brand new one. -To make the issue details as standard as possible, we setup an [ISSUE TEMPLATE](https://github.com/OpenIMSDK/.github/tree/main/.github/ISSUE_TEMPLATE) for issue reporters. You can find three kinds of issue templates there: question, bug report and feature request. Please **BE SURE** to follow the instructions to fill fields in template. +To make the issue details as standard as possible, we setup an [ISSUE TEMPLATE](https://github.com/openimsdk/.github/tree/main/.github/ISSUE_TEMPLATE) for issue reporters. You can find three kinds of issue templates there: question, bug report and feature request. Please **BE SURE** to follow the instructions to fill fields in template. **There are a lot of cases when you could open an issue:** @@ -270,9 +270,9 @@ An example for this could be: #### PR Description -PR is the only way to make change to OpenIM project files. To help reviewers better get your purpose, **PR** description could not be too detailed. We encourage contributors to follow the [PR template](https://github.com/OpenIMSDK/.github/tree/main/.github/PULL_REQUEST_TEMPLATE.md) to finish the pull request. +PR is the only way to make change to OpenIM project files. To help reviewers better get your purpose, **PR** description could not be too detailed. We encourage contributors to follow the [PR template](https://github.com/openimsdk/.github/tree/main/.github/PULL_REQUEST_TEMPLATE.md) to finish the pull request. -You can find some very formal PR in [RFC](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) issues and learn about them. +You can find some very formal PR in [RFC](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) issues and learn about them. **📖 Opening PRs:** @@ -330,11 +330,11 @@ git() { #### CI actions -We host CI on [GitHub Actions](https://github.com/OpenIMSDK/openim-sdk-core/actions), we will make sure PR pass tests before we can merge it. +We host CI on [GitHub Actions](https://github.com/openimsdk/openim-sdk-core/actions), we will make sure PR pass tests before we can merge it. These two kind of tests: `lint` and `unit test` -`lint` tests if your code matches our code conventions, please consult [golangci-lint](https://golangci-lint.run/) and [lint config](https://github.com/OpenIMSDK/openim-sdk-core/blob/main/.golangci.yml) +`lint` tests if your code matches our code conventions, please consult [golangci-lint](https://golangci-lint.run/) and [lint config](https://github.com/openimsdk/openim-sdk-core/blob/main/.golangci.yml) > **Note** > @@ -354,9 +354,9 @@ Try your best to keep every function has been tested, it keeps the function beha **The documentation for OpenIM includes:** -+ [README.md](https://github.com/OpenIMSDK/openim-sdk-core/blob/main/README.md): This file includes the basic information and instructions for getting started with OpenIM. -+ [README_zh-CN.md](https://github.com/OpenIMSDK/openim-sdk-core/blob/main/README_zh-CN.md): This file includes the basic information and instructions for getting started with OpenIM in Chinese. -+ [CONTRIBUTING.md](https://github.com/OpenIMSDK/openim-sdk-core/blob/main/CONTRIBUTING.md): This file contains guidelines for contributing to OpenIM's codebase, such as how to submit issues, pull requests, and code reviews. ++ [README.md](https://github.com/openimsdk/openim-sdk-core/blob/main/README.md): This file includes the basic information and instructions for getting started with OpenIM. ++ [README_zh-CN.md](https://github.com/openimsdk/openim-sdk-core/blob/main/README_zh-CN.md): This file includes the basic information and instructions for getting started with OpenIM in Chinese. ++ [CONTRIBUTING.md](https://github.com/openimsdk/openim-sdk-core/blob/main/CONTRIBUTING.md): This file contains guidelines for contributing to OpenIM's codebase, such as how to submit issues, pull requests, and code reviews. + [Official Documentation](https://doc.rentsoft.cn): This is the official documentation for OpenIM, which includes comprehensive information on all of its features, configuration options, and troubleshooting tips. **Please obey the following rules to better format the docs, which would greatly improve the reading experience.** @@ -380,9 +380,9 @@ We integrated in the CICD actions [markdownlint](https://github.com/markdownlint We choose GitHub as the primary place for OpenIM to collaborate. So the latest updates of OpenIM are always here. Although contributions via **PR** is an explicit way to help, we still call for any other ways. -+ reply to other's [issues](https://github.com/OpenIMSDK/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) if you could; ++ reply to other's [issues](https://github.com/openimsdk/openim-sdk-core/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) if you could; + help solve other user's problems; -+ help review other's [PR](https://github.com/OpenIMSDK/openim-sdk-core/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc) design; ++ help review other's [PR](https://github.com/openimsdk/openim-sdk-core/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc) design; + discuss about OpenIM to make things clearer; + advocate [OpenIM](https://google.com/search?q=OpenIM) technology beyond GitHub; + write blogs on OpenIM and so on. @@ -430,6 +430,6 @@ In addition to Slack, we also offer the following ways to get in touch: + We also have Slack channels for you to communicate and discuss. To join, visit https://slack.com/ and join our [👀 openim-sdk-core slack](https://join.slack.com/t/openimsdk/shared_invite/zt-1tmoj26uf-_FDy3dowVHBiGvLk9e5Xkg) team channel. + Get in touch with us on [Gmail](https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=winxu81@gmail.com). If you have any questions or issues that need resolving, or any suggestions and feedback for our open source projects, please feel free to contact us via email. + Read our [blog](https://doc.rentsoft.cn/). Our blog is a great place to stay up-to-date with openim-sdk-core projects and trends. On the blog, we share our latest developments, tech trends, and other interesting information. -+ Add [Wechat](https://github.com/OpenIMSDK/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of openim-sdk-core. We will process your request as soon as possible. ++ Add [Wechat](https://github.com/openimsdk/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of openim-sdk-core. We will process your request as soon as possible. Whether you're looking to join our community or have any questions or suggestions, we welcome you to get in touch with us. diff --git a/Makefile b/Makefile index ced2e7cee..cdaf84c4e 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # define the default goal # -ROOT_PACKAGE=github.com/OpenIMSDK/Open-IM-SDK-Core +ROOT_PACKAGE=github.com/openimsdk/Open-IM-SDK-Core # Copyright 2023 OpenIM. All rights reserved. # Use of this source code is governed by a MIT style @@ -157,7 +157,7 @@ ifeq (${BINS},) $(error Could not determine BINS, set ROOT_DIR or run in source dir) endif -EXCLUDE_TESTS=github.com/OpenIMSDK/openim-sdk-core/test +EXCLUDE_TESTS=github.com/openimsdk/openim-sdk-core/test # ============================================================================== # Build diff --git a/README.md b/README.md index a3252f491..c04d17a95 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@

-A+ -good first - +A+ +good first + - +

@@ -85,60 +85,60 @@ $ make deploy ## Contributing & Development -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). +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). -If you'd like to contribute to this openim-sdk-core repository, please read our [contributor documentation](https://github.com/OpenIMSDK/openim-sdk-core/blob/main/CONTRIBUTING.md). +If you'd like to contribute to this openim-sdk-core repository, please read our [contributor documentation](https://github.com/openimsdk/openim-sdk-core/blob/main/CONTRIBUTING.md). ## community meeting We welcome everyone to join us and contribute to openim-sdk-core, whether you are new to open source or professional. We are committed to promoting an open source culture, so we offer community members neighborhood prizes and reward money in recognition of their contributions. We believe that by working together, we can build a strong community and make valuable open source tools and resources available to more people. So if you are interested in openim-sdk-core, please join our community and start contributing your ideas and skills! -We take notes of each [biweekly meeting](https://github.com/OpenIMSDK/Open-IM-Server/issues/381) in [GitHub discussions](https://github.com/OpenIMSDK/Open-IM-Server/discussions/categories/meeting), and our minutes are written in [Google Docs](https://docs.google.com/document/d/1nx8MDpuG74NASx081JcCpxPgDITNTpIIos0DS6Vr9GU/edit?usp=sharing). +We take notes of each [biweekly meeting](https://github.com/openimsdk/Open-IM-Server/issues/381) in [GitHub discussions](https://github.com/openimsdk/Open-IM-Server/discussions/categories/meeting), and our minutes are written in [Google Docs](https://docs.google.com/document/d/1nx8MDpuG74NASx081JcCpxPgDITNTpIIos0DS6Vr9GU/edit?usp=sharing). -openim-sdk-core maintains a [public roadmap](https://github.com/OpenIMSDK/community/tree/main/roadmaps). It gives a a high-level view of the main priorities for the project, the maturity of different features and projects, and how to influence the project direction. +openim-sdk-core maintains a [public roadmap](https://github.com/openimsdk/community/tree/main/roadmaps). It gives a a high-level view of the main priorities for the project, the maturity of different features and projects, and how to influence the project direction. ## about OpenIM ### common -+ https://github.com/OpenIMSDK/automation: OpenIM Automation, cicd, and actions, Robotics. -+ https://github.com/OpenIMSDK/community: Community Management for OpenIM ++ https://github.com/openimsdk/automation: OpenIM Automation, cicd, and actions, Robotics. ++ https://github.com/openimsdk/community: Community Management for OpenIM ### OpenIM **Links** Contains some common parts of the OpenIM community. -+ https://github.com/OpenIMSDK/automation: OpenIM Automation, cicd, and actions, Robotics. -+ https://github.com/OpenIMSDK/openim-sdk-core: The IMSDK implemented by golang can be used in IOS, Android, PC and other platforms. -+ https://github.com/OpenIMSDK/openim-sdk-core: Instant messaging IM server. -+ https://github.com/OpenIMSDK/community: Community Management for OpenIM. ++ https://github.com/openimsdk/automation: OpenIM Automation, cicd, and actions, Robotics. ++ https://github.com/openimsdk/openim-sdk-core: The IMSDK implemented by golang can be used in IOS, Android, PC and other platforms. ++ https://github.com/openimsdk/openim-sdk-core: Instant messaging IM server. ++ https://github.com/openimsdk/community: Community Management for OpenIM. ### SDKs -+ [openim-sdk-core](https://github.com/OpenIMSDK/openim-sdk-core): A cross-platform SDK implemented in golang that can be used in IOS, Android, PC, and other platforms. -+ [Open-IM-SDK-iOS](https://github.com/OpenIMSDK/Open-IM-SDK-iOS): An iOS SDK generated based on openim-sdk-core, available for developers to reference. -+ [Open-IM-SDK-Android](https://github.com/OpenIMSDK/Open-IM-SDK-Android): An Android SDK generated based on openim-sdk-core, available for developers to reference. -+ [Open-IM-SDK-Flutter](https://github.com/OpenIMSDK/Open-IM-SDK-Flutter): A Flutter SDK generated based on Open-IM-SDK-iOS and Open-IM-SDK-Android, available for developers to reference. -+ [Open-IM-SDK-Uniapp](https://github.com/OpenIMSDK/Open-IM-SDK-Uniapp): A uni-app SDK generated based on Open-IM-SDK-iOS and Open-IM-SDK-Android, available for developers to reference. ++ [openim-sdk-core](https://github.com/openimsdk/openim-sdk-core): A cross-platform SDK implemented in golang that can be used in IOS, Android, PC, and other platforms. ++ [Open-IM-SDK-iOS](https://github.com/openimsdk/Open-IM-SDK-iOS): An iOS SDK generated based on openim-sdk-core, available for developers to reference. ++ [Open-IM-SDK-Android](https://github.com/openimsdk/Open-IM-SDK-Android): An Android SDK generated based on openim-sdk-core, available for developers to reference. ++ [Open-IM-SDK-Flutter](https://github.com/openimsdk/Open-IM-SDK-Flutter): A Flutter SDK generated based on Open-IM-SDK-iOS and Open-IM-SDK-Android, available for developers to reference. ++ [Open-IM-SDK-Uniapp](https://github.com/openimsdk/Open-IM-SDK-Uniapp): A uni-app SDK generated based on Open-IM-SDK-iOS and Open-IM-SDK-Android, available for developers to reference. ### Demos -+ [Open-IM-iOS-Demo](https://github.com/OpenIMSDK/Open-IM-iOS-Demo): An iOS demo based on Open-IM-SDK-iOS, available for developers to reference. -+ [Open-IM-Android-Demo](https://github.com/OpenIMSDK/Open-IM-Android-Demo): An Android demo based on Open-IM-SDK-Android, available for developers to reference. -+ [Open-IM-Flutter-Demo](https://github.com/OpenIMSDK/Open-IM-Flutter-Demo): A Flutter demo based on Open-IM-SDK-Flutter, available for developers to reference. ++ [Open-IM-iOS-Demo](https://github.com/openimsdk/Open-IM-iOS-Demo): An iOS demo based on Open-IM-SDK-iOS, available for developers to reference. ++ [Open-IM-Android-Demo](https://github.com/openimsdk/Open-IM-Android-Demo): An Android demo based on Open-IM-SDK-Android, available for developers to reference. ++ [Open-IM-Flutter-Demo](https://github.com/openimsdk/Open-IM-Flutter-Demo): A Flutter demo based on Open-IM-SDK-Flutter, available for developers to reference. ## Used By -OpenIM is used by the following companies ,let's write it down in [ADOPTER](https://github.com/OpenIMSDK/community/blob/main/ADOPTERS.md). +OpenIM is used by the following companies ,let's write it down in [ADOPTER](https://github.com/openimsdk/community/blob/main/ADOPTERS.md). -Please leave your use cases in the comments [here](https://github.com/OpenIMSDK/Open-IM-Server/issues/379). +Please leave your use cases in the comments [here](https://github.com/openimsdk/Open-IM-Server/issues/379). ## License -[openim-sdk-core](https://github.com/OpenIMSDK/openim-sdk-core) is licensed under the Apache License, Version 2.0. See [LICENSE](https://github.com/OpenIMSDK/openim-sdk-core/tree/main/LICENSE) for the full license text. +[openim-sdk-core](https://github.com/openimsdk/openim-sdk-core) is licensed under the Apache License, Version 2.0. See [LICENSE](https://github.com/openimsdk/openim-sdk-core/tree/main/LICENSE) for the full license text. ## Thanks to our contributors! - + diff --git a/README_zh-CN.md b/README_zh-CN.md index a5bbfb2f6..3c7a22db4 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -8,11 +8,11 @@

-A+ -good first - +A+ +good first + - +

diff --git a/cmd/gordon_main.go b/cmd/gordon_main.go index 0d5349ec2..3db79a00f 100644 --- a/cmd/gordon_main.go +++ b/cmd/gordon_main.go @@ -18,11 +18,11 @@ import ( "context" "encoding/json" "errors" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/network" "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/test" + "github.com/openimsdk/tools/log" "time" ) @@ -93,7 +93,7 @@ func gRunGetToken(strMyUid string) string { return token } func main() { - uid := "1" + uid := "1695766238" //Gordon //uid:="1554321956297519104" //Gordon2 diff --git a/cmd/press_open_im.go b/cmd/press_open_im.go index 5a8bf1e7d..bf52fc3a1 100644 --- a/cmd/press_open_im.go +++ b/cmd/press_open_im.go @@ -17,8 +17,8 @@ package main import ( "errors" "flag" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/test" + "github.com/openimsdk/tools/log" ) func main() { diff --git a/cmd/reliability_open_im.go b/cmd/reliability_open_im.go index a670a036c..07a15d6fb 100644 --- a/cmd/reliability_open_im.go +++ b/cmd/reliability_open_im.go @@ -17,8 +17,8 @@ package main import ( "errors" "flag" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/test" + "github.com/openimsdk/tools/log" ) func main() { diff --git a/cmd/sk_main.go b/cmd/sk_main.go index 18f7a7dab..b797984ac 100644 --- a/cmd/sk_main.go +++ b/cmd/sk_main.go @@ -16,10 +16,10 @@ package main import ( "errors" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/db" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/test" + "github.com/openimsdk/tools/log" "time" ) diff --git a/docs/contrib/git_workflow.md b/docs/contrib/git_workflow.md index 22b658464..3b97b9590 100644 --- a/docs/contrib/git_workflow.md +++ b/docs/contrib/git_workflow.md @@ -18,7 +18,7 @@ OpenIM project uses the [GitHub flow](https://docs.github.com/en/get-started/qui ### Branch naming conventions -Every forked repository works independently, meaning that any contributor can create branches with the name they see fit. However, it is worth noting that OpenIM mirrors [OpenIM version skew policy](https://github.com/OpenIMSDK/openim-sdk-core/releases) by maintaining release branches for the most recent three minor releases. The only exception is that the main branch mirrors the latest OpenIM release (3.10) instead of using a `release-` prefixed one. +Every forked repository works independently, meaning that any contributor can create branches with the name they see fit. However, it is worth noting that OpenIM mirrors [OpenIM version skew policy](https://github.com/openimsdk/openim-sdk-core/releases) by maintaining release branches for the most recent three minor releases. The only exception is that the main branch mirrors the latest OpenIM release (3.10) instead of using a `release-` prefixed one. ```text main -------------------------------------------. (OpenIM 3.10) @@ -39,7 +39,7 @@ There are everyday tasks related to git that every contributor needs to perform, Creating a OpenIM fork, cloning it, and setting its upstream remote can be summarized on: -1. Visit +1. Visit 2. Click the `Fork` button (top right) to establish a cloud-based fork 3. Clone fork to local storage 4. Add to your fork OpenIM remote as upstream @@ -54,7 +54,7 @@ git clone https://github.com/$user/OpenIM.git ## Add OpenIM as upstream to your fork cd OpenIM -git remote add upstream https://github.com/OpenIMSDK/openim-sdk-core.git +git remote add upstream https://github.com/openimsdk/openim-sdk-core.git # or: git remote add upstream git@github.com:OpenIMSDK/openim-sdk-core.git ## Ensure to never push to upstream directly diff --git a/go.mod b/go.mod index 4910a6146..2b75a4296 100644 --- a/go.mod +++ b/go.mod @@ -1,41 +1,43 @@ module github.com/openimsdk/openim-sdk-core/v3 -go 1.18 +go 1.21 require ( - github.com/golang/protobuf v1.5.3 + github.com/golang/protobuf v1.5.4 github.com/gorilla/websocket v1.4.2 - github.com/jinzhu/copier v0.3.5 + github.com/jinzhu/copier v0.4.0 github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect github.com/pkg/errors v0.9.1 - google.golang.org/protobuf v1.31.0 // indirect - gorm.io/driver/sqlite v1.3.6 + google.golang.org/protobuf v1.33.0 // indirect + gorm.io/driver/sqlite v1.5.5 nhooyr.io/websocket v1.8.10 ) -require golang.org/x/net v0.19.0 +require golang.org/x/net v0.22.0 require ( - github.com/OpenIMSDK/protocol v0.0.45 - github.com/OpenIMSDK/tools v0.0.24 - github.com/google/go-cmp v0.5.9 + github.com/google/go-cmp v0.6.0 + github.com/openimsdk/protocol v0.0.69-alpha.16 + github.com/openimsdk/tools v0.0.49-alpha.12 github.com/patrickmn/go-cache v2.1.0+incompatible - golang.org/x/image v0.14.0 - gorm.io/gorm v1.23.8 + go.etcd.io/etcd/api/v3 v3.5.13 + golang.org/x/image v0.15.0 + gorm.io/gorm v1.25.10 ) require ( - github.com/bwmarrin/snowflake v0.3.0 // indirect + github.com/coreos/go-semver v0.3.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/lestrrat-go/strftime v1.0.6 // indirect - github.com/mattn/go-sqlite3 v1.14.12 // indirect - github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect + github.com/mattn/go-sqlite3 v1.14.22 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect - google.golang.org/grpc v1.56.2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/grpc v1.62.1 // indirect ) + +//replace github.com/openimsdk/protocol => /Users/chao/Desktop/project/protocol diff --git a/go.sum b/go.sum index d43e428d6..d0c5e2fd4 100644 --- a/go.sum +++ b/go.sum @@ -1,39 +1,36 @@ -github.com/OpenIMSDK/protocol v0.0.45 h1:0MxdGddw09k17xgR6Kn6ZLtcTrEosTCWXA/rhgSmbQQ= -github.com/OpenIMSDK/protocol v0.0.45/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= -github.com/OpenIMSDK/tools v0.0.24 h1:P8n7ZtsZEbm4W3dQAem29O+bigzy6YPXxFzd/D8Vh3U= -github.com/OpenIMSDK/tools v0.0.24/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= -github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= -github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= -github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0= -github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= -github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/openimsdk/protocol v0.0.69-alpha.16 h1:ciSqm2rjBdpScpkQm3wPjAFv0YbIRp8MITRkDZWVv6c= +github.com/openimsdk/protocol v0.0.69-alpha.16/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= +github.com/openimsdk/tools v0.0.49-alpha.12 h1:vsr63W1kHW1dEw9yelMhmr72WmsrjKfs2vXww3upfWI= +github.com/openimsdk/tools v0.0.49-alpha.12/go.mod h1:g7mkHXYUPi0/8aAX8VPMHpnb3hqdV69Jph+bXOGvvNM= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -42,36 +39,39 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4= +go.etcd.io/etcd/api/v3 v3.5.13/go.mod h1:gBqlqkcMMZMVTMm4NDZloEVJzxQOQIls8splbqBDa0c= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= -golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= +golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 h1:XUODHrpzJEUeWmVo/jfNTLj0YyVveOo28oE6vkFbkO4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= -google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= +google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gorm.io/driver/sqlite v1.3.6 h1:Fi8xNYCUplOqWiPa3/GuCeowRNBRGTf62DEmhMDHeQQ= -gorm.io/driver/sqlite v1.3.6/go.mod h1:Sg1/pvnKtbQ7jLXxfZa+jSHvoX8hoZA8cn4xllOMTgE= -gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE= -gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E= +gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE= +gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= +gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= diff --git a/internal/business/business.go b/internal/business/business.go index 614f6a7b4..ecc02cec9 100644 --- a/internal/business/business.go +++ b/internal/business/business.go @@ -21,9 +21,9 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" ) type Business struct { diff --git a/internal/common/common.go b/internal/common/common.go index 17da2935d..76250b5c0 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -17,8 +17,8 @@ package common import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" - "github.com/OpenIMSDK/protocol/sdkws" "github.com/golang/protobuf/proto" + "github.com/openimsdk/protocol/sdkws" ) func UnmarshalTips(msg *sdkws.MsgData, detail proto.Message) error { diff --git a/internal/conversation_msg/conversation.go b/internal/conversation_msg/conversation.go index e949b4228..bbd4da643 100644 --- a/internal/conversation_msg/conversation.go +++ b/internal/conversation_msg/conversation.go @@ -27,18 +27,19 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/utils/datautil" "sort" "strings" "time" "github.com/jinzhu/copier" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" - "github.com/OpenIMSDK/protocol/msg" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/msg" + "github.com/openimsdk/protocol/sdkws" - pbConversation "github.com/OpenIMSDK/protocol/conversation" + pbConversation "github.com/openimsdk/protocol/conversation" ) func (c *Conversation) setConversation(ctx context.Context, apiReq *pbConversation.SetConversationsReq, localConversation *model_struct.LocalConversation) error { @@ -58,7 +59,7 @@ func (c *Conversation) getServerConversationList(ctx context.Context) ([]*model_ if err != nil { return nil, err } - return util.Batch(ServerConversationToLocal, resp.Conversations), nil + return datautil.Batch(ServerConversationToLocal, resp.Conversations), nil } func (c *Conversation) getServerConversationsByIDs(ctx context.Context, conversations []string) ([]*model_struct.LocalConversation, error) { @@ -66,7 +67,7 @@ func (c *Conversation) getServerConversationsByIDs(ctx context.Context, conversa if err != nil { return nil, err } - return util.Batch(ServerConversationToLocal, resp.Conversations), nil + return datautil.Batch(ServerConversationToLocal, resp.Conversations), nil } func (c *Conversation) getServerHasReadAndMaxSeqs(ctx context.Context, conversationIDs ...string) (map[string]*msg.Seqs, error) { diff --git a/internal/conversation_msg/conversation_msg.go b/internal/conversation_msg/conversation_msg.go index b5b876b12..6648e7e76 100644 --- a/internal/conversation_msg/conversation_msg.go +++ b/internal/conversation_msg/conversation_msg.go @@ -18,8 +18,6 @@ import ( "context" "encoding/json" "errors" - "github.com/OpenIMSDK/tools/log" - utils2 "github.com/OpenIMSDK/tools/utils" "github.com/openimsdk/openim-sdk-core/v3/internal/business" "github.com/openimsdk/openim-sdk-core/v3/internal/cache" "github.com/openimsdk/openim-sdk-core/v3/internal/file" @@ -37,6 +35,8 @@ import ( sdk "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" "github.com/openimsdk/openim-sdk-core/v3/pkg/syncer" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" @@ -50,7 +50,7 @@ var SearchContentType = []int{constant.Text, constant.AtText, constant.File} type Conversation struct { *interaction.LongConnMgr - conversationSyncer *syncer.Syncer[*model_struct.LocalConversation, string] + conversationSyncer *syncer.Syncer[*model_struct.LocalConversation, syncer.NoResp, string] db db_interface.DataBase ConversationListener func() open_im_sdk_callback.OnConversationListener msgListener func() open_im_sdk_callback.OnAdvancedMsgListener @@ -115,7 +115,7 @@ func NewConversation(ctx context.Context, longConnMgr *interaction.LongConnMgr, } func (c *Conversation) initSyncer() { - c.conversationSyncer = syncer.New( + c.conversationSyncer = syncer.New[*model_struct.LocalConversation, syncer.NoResp, string]( func(ctx context.Context, value *model_struct.LocalConversation) error { return c.db.InsertConversation(ctx, value) }, @@ -992,7 +992,7 @@ func (c *Conversation) batchGetUserNameAndFaceURL(ctx context.Context, userIDs . log.ZWarn(ctx, "BatchGetUserNameAndFaceURL", err, "userIDs", userIDs) notInFriend = userIDs } else { - notInFriend = utils2.SliceSub(userIDs, utils2.Slice(friendList, func(e *model_struct.LocalFriend) string { + notInFriend = datautil.SliceSub(userIDs, datautil.Slice(friendList, func(e *model_struct.LocalFriend) string { return e.FriendUserID })) } @@ -1049,7 +1049,7 @@ func (c *Conversation) getUserNameAndFaceURL(ctx context.Context, userID string) return "", "", err } if len(users) == 0 { - return "", "", sdkerrs.ErrUserIDNotFound.Wrap(userID) + return "", "", sdkerrs.ErrUserIDNotFound.WrapMsg(userID) } c.user.UserBasicCache.Store(userID, &user.BasicInfo{FaceURL: users[0].FaceURL, Nickname: users[0].Nickname}) return users[0].FaceURL, users[0].Nickname, nil diff --git a/internal/conversation_msg/conversation_notification.go b/internal/conversation_msg/conversation_notification.go index 2c7738bd0..ea2a13509 100644 --- a/internal/conversation_msg/conversation_notification.go +++ b/internal/conversation_msg/conversation_notification.go @@ -17,39 +17,189 @@ package conversation_msg import ( "context" "encoding/json" + "fmt" "github.com/openimsdk/openim-sdk-core/v3/pkg/common" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/utils/datautil" + "reflect" + "runtime" "time" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" - utils2 "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) func (c *Conversation) Work(c2v common.Cmd2Value) { log.ZDebug(c2v.Ctx, "NotificationCmd start", "cmd", c2v.Cmd, "value", c2v.Value) defer log.ZDebug(c2v.Ctx, "NotificationCmd end", "cmd", c2v.Cmd, "value", c2v.Value) switch c2v.Cmd { - case constant.CmdDeleteConversation: - c.doDeleteConversation(c2v) case constant.CmdNewMsgCome: c.doMsgNew(c2v) - case constant.CmdSuperGroupMsgCome: - // c.doSuperGroupMsgNew(c2v) case constant.CmdUpdateConversation: c.doUpdateConversation(c2v) case constant.CmdUpdateMessage: c.doUpdateMessage(c2v) case constant.CmSyncReactionExtensions: - // c.doSyncReactionExtensions(c2v) case constant.CmdNotification: c.doNotificationNew(c2v) } } +func (c *Conversation) doNotificationNew(c2v common.Cmd2Value) { + ctx := c2v.Ctx + allMsg := c2v.Value.(sdk_struct.CmdNewMsgComeToConversation).Msgs + syncFlag := c2v.Value.(sdk_struct.CmdNewMsgComeToConversation).SyncFlag + switch syncFlag { + case constant.AppDataSyncStart: + log.ZDebug(ctx, "AppDataSyncStart") + c.startTime = time.Now() + c.ConversationListener().OnSyncServerStart(true) + syncFunctions := []func(c context.Context) error{ + c.SyncAllConversationHashReadSeqs, + c.user.SyncLoginUserInfoWithoutNotice, + c.friend.SyncAllBlackListWithoutNotice, + c.friend.SyncAllFriendApplicationWithoutNotice, + c.friend.SyncAllSelfFriendApplicationWithoutNotice, + c.group.SyncAllAdminGroupApplicationWithoutNotice, + c.group.SyncAllSelfGroupApplicationWithoutNotice, + c.user.SyncAllCommandWithoutNotice, + c.group.SyncAllJoinedGroupsAndMembers, + c.friend.IncrSyncFriends, + c.SyncAllConversationsWithoutNotice, + } + totalFunctions := len(syncFunctions) + for i, syncFunc := range syncFunctions { + funcName := runtime.FuncForPC(reflect.ValueOf(syncFunc).Pointer()).Name() + startTime := time.Now() + err := syncFunc(ctx) + duration := time.Since(startTime) + if err != nil { + log.ZWarn(ctx, fmt.Sprintf("%s sync err", funcName), err, "duration", duration.Seconds()) + } else { + log.ZDebug(ctx, fmt.Sprintf("%s completed successfully", funcName), "duration", duration.Seconds()) + } + progress := int(float64(i+1) / float64(totalFunctions) * 100) + if progress == 0 { + progress = 1 + } + c.ConversationListener().OnSyncServerProgress(progress) + } + case constant.AppDataSyncFinish: + log.ZDebug(ctx, "AppDataSyncFinish", "time", time.Since(c.startTime).Milliseconds()) + c.ConversationListener().OnSyncServerFinish(true) + case constant.MsgSyncBegin: + log.ZDebug(ctx, "MsgSyncBegin") + c.startTime = time.Now() + c.ConversationListener().OnSyncServerStart(false) + //clear SubscriptionStatusMap + c.user.OnlineStatusCache.DeleteAll() + + syncFunctions := []func(c context.Context) error{ + c.SyncAllConversationHashReadSeqs, + c.group.SyncAllJoinedGroupsAndMembers, + c.friend.IncrSyncFriends, + } + + for _, syncFunc := range syncFunctions { + funcName := runtime.FuncForPC(reflect.ValueOf(syncFunc).Pointer()).Name() + startTime := time.Now() + err := syncFunc(ctx) + duration := time.Since(startTime) + if err != nil { + log.ZWarn(ctx, fmt.Sprintf("%s sync err", funcName), err, "duration", duration.Seconds()) + } else { + log.ZDebug(ctx, fmt.Sprintf("%s completed successfully", funcName), "duration", duration.Seconds()) + } + } + for _, syncFunc := range []func(c context.Context) error{ + c.user.SyncLoginUserInfo, + c.friend.SyncAllBlackList, c.friend.SyncAllFriendApplication, c.friend.SyncAllSelfFriendApplication, + c.group.SyncAllAdminGroupApplication, c.group.SyncAllSelfGroupApplication, c.user.SyncAllCommand, c.SyncAllConversations, + } { + go func(syncFunc func(c context.Context) error) { + funcName := runtime.FuncForPC(reflect.ValueOf(syncFunc).Pointer()).Name() + startTime := time.Now() + err := syncFunc(ctx) + duration := time.Since(startTime) + if err != nil { + log.ZWarn(ctx, fmt.Sprintf("%s sync err", funcName), err, "duration", duration.Seconds()) + } else { + log.ZDebug(ctx, fmt.Sprintf("%s completed successfully", funcName), "duration", duration.Seconds()) + } + }(syncFunc) + } + + case constant.MsgSyncFailed: + c.ConversationListener().OnSyncServerFailed(false) + case constant.MsgSyncEnd: + log.ZDebug(ctx, "MsgSyncEnd", "time", time.Since(c.startTime).Milliseconds()) + c.ConversationListener().OnSyncServerFinish(false) + } + + for conversationID, msgs := range allMsg { + log.ZDebug(ctx, "notification handling", "conversationID", conversationID, "msgs", msgs) + if len(msgs.Msgs) != 0 { + lastMsg := msgs.Msgs[len(msgs.Msgs)-1] + log.ZDebug(ctx, "SetNotificationSeq", "conversationID", conversationID, "seq", lastMsg.Seq) + if lastMsg.Seq != 0 { + if err := c.db.SetNotificationSeq(ctx, conversationID, lastMsg.Seq); err != nil { + log.ZError(ctx, "SetNotificationSeq err", err, "conversationID", conversationID, "lastMsg", lastMsg) + } + } + } + for _, v := range msgs.Msgs { + switch { + case v.ContentType == constant.ConversationChangeNotification: + c.DoConversationChangedNotification(ctx, v) + case v.ContentType == constant.ConversationPrivateChatNotification: + c.DoConversationIsPrivateChangedNotification(ctx, v) + case v.ContentType == constant.ConversationUnreadNotification: + var tips sdkws.ConversationHasReadTips + _ = json.Unmarshal(v.Content, &tips) + c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{ConID: tips.ConversationID, Action: constant.UnreadCountSetZero}}) + c.db.DeleteConversationUnreadMessageList(ctx, tips.ConversationID, tips.UnreadCountTime) + c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{Action: constant.ConChange, Args: []string{tips.ConversationID}}}) + continue + case v.ContentType == constant.BusinessNotification: + c.business.DoNotification(ctx, v) + continue + case v.ContentType == constant.RevokeNotification: + c.doRevokeMsg(ctx, v) + case v.ContentType == constant.ClearConversationNotification: + c.doClearConversations(ctx, v) + case v.ContentType == constant.DeleteMsgsNotification: + c.doDeleteMsgs(ctx, v) + case v.ContentType == constant.HasReadReceipt: + c.doReadDrawing(ctx, v) + } + + switch v.SessionType { + case constant.SingleChatType: + if v.ContentType > constant.FriendNotificationBegin && v.ContentType < constant.FriendNotificationEnd { + c.friend.DoNotification(ctx, v) + } else if v.ContentType > constant.UserNotificationBegin && v.ContentType < constant.UserNotificationEnd { + c.user.DoNotification(ctx, v) + } else if datautil.Contain(v.ContentType, constant.GroupApplicationRejectedNotification, constant.GroupApplicationAcceptedNotification, constant.JoinGroupApplicationNotification) { + c.group.DoNotification(ctx, v) + } else if v.ContentType > constant.SignalingNotificationBegin && v.ContentType < constant.SignalingNotificationEnd { + + continue + } + case constant.GroupChatType, constant.SuperGroupChatType: + if v.ContentType > constant.GroupNotificationBegin && v.ContentType < constant.GroupNotificationEnd { + c.group.DoNotification(ctx, v) + } else if v.ContentType > constant.SignalingNotificationBegin && v.ContentType < constant.SignalingNotificationEnd { + continue + } + } + } + } + +} + func (c *Conversation) doDeleteConversation(c2v common.Cmd2Value) { node := c2v.Value.(common.DeleteConNode) ctx := c2v.Ctx @@ -606,94 +756,3 @@ func (c *Conversation) DoConversationIsPrivateChangedNotification(ctx context.Co c.SyncConversations(ctx, []string{tips.ConversationID}) } - -func (c *Conversation) doNotificationNew(c2v common.Cmd2Value) { - ctx := c2v.Ctx - allMsg := c2v.Value.(sdk_struct.CmdNewMsgComeToConversation).Msgs - syncFlag := c2v.Value.(sdk_struct.CmdNewMsgComeToConversation).SyncFlag - switch syncFlag { - case constant.MsgSyncBegin: - c.startTime = time.Now() - c.ConversationListener().OnSyncServerStart() - if err := c.SyncAllConversationHashReadSeqs(ctx); err != nil { - log.ZError(ctx, "SyncConversationHashReadSeqs err", err) - } - //clear SubscriptionStatusMap - c.user.OnlineStatusCache.DeleteAll() - for _, syncFunc := range []func(c context.Context) error{ - c.user.SyncLoginUserInfo, - c.friend.SyncAllBlackList, c.friend.SyncAllFriendList, c.friend.SyncAllFriendApplication, c.friend.SyncAllSelfFriendApplication, - c.group.SyncAllJoinedGroupsAndMembers, c.group.SyncAllAdminGroupApplication, c.group.SyncAllSelfGroupApplication, c.user.SyncAllCommand, - } { - go func(syncFunc func(c context.Context) error) { - _ = syncFunc(ctx) - }(syncFunc) - } - case constant.MsgSyncFailed: - c.ConversationListener().OnSyncServerFailed() - case constant.MsgSyncEnd: - log.ZDebug(ctx, "MsgSyncEnd", "time", time.Since(c.startTime).Milliseconds()) - defer c.ConversationListener().OnSyncServerFinish() - go c.SyncAllConversations(ctx) - } - - for conversationID, msgs := range allMsg { - log.ZDebug(ctx, "notification handling", "conversationID", conversationID, "msgs", msgs) - if len(msgs.Msgs) != 0 { - lastMsg := msgs.Msgs[len(msgs.Msgs)-1] - log.ZDebug(ctx, "SetNotificationSeq", "conversationID", conversationID, "seq", lastMsg.Seq) - if lastMsg.Seq != 0 { - if err := c.db.SetNotificationSeq(ctx, conversationID, lastMsg.Seq); err != nil { - log.ZError(ctx, "SetNotificationSeq err", err, "conversationID", conversationID, "lastMsg", lastMsg) - } - } - } - for _, v := range msgs.Msgs { - switch { - case v.ContentType == constant.ConversationChangeNotification: - c.DoConversationChangedNotification(ctx, v) - case v.ContentType == constant.ConversationPrivateChatNotification: - c.DoConversationIsPrivateChangedNotification(ctx, v) - case v.ContentType == constant.ConversationUnreadNotification: - var tips sdkws.ConversationHasReadTips - _ = json.Unmarshal(v.Content, &tips) - c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{ConID: tips.ConversationID, Action: constant.UnreadCountSetZero}}) - c.db.DeleteConversationUnreadMessageList(ctx, tips.ConversationID, tips.UnreadCountTime) - c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{Action: constant.ConChange, Args: []string{tips.ConversationID}}}) - continue - case v.ContentType == constant.BusinessNotification: - c.business.DoNotification(ctx, v) - continue - case v.ContentType == constant.RevokeNotification: - c.doRevokeMsg(ctx, v) - case v.ContentType == constant.ClearConversationNotification: - c.doClearConversations(ctx, v) - case v.ContentType == constant.DeleteMsgsNotification: - c.doDeleteMsgs(ctx, v) - case v.ContentType == constant.HasReadReceipt: - c.doReadDrawing(ctx, v) - } - - switch v.SessionType { - case constant.SingleChatType: - if v.ContentType > constant.FriendNotificationBegin && v.ContentType < constant.FriendNotificationEnd { - c.friend.DoNotification(ctx, v) - } else if v.ContentType > constant.UserNotificationBegin && v.ContentType < constant.UserNotificationEnd { - c.user.DoNotification(ctx, v) - } else if utils2.Contain(v.ContentType, constant.GroupApplicationRejectedNotification, constant.GroupApplicationAcceptedNotification, constant.JoinGroupApplicationNotification) { - c.group.DoNotification(ctx, v) - } else if v.ContentType > constant.SignalingNotificationBegin && v.ContentType < constant.SignalingNotificationEnd { - - continue - } - case constant.GroupChatType, constant.SuperGroupChatType: - if v.ContentType > constant.GroupNotificationBegin && v.ContentType < constant.GroupNotificationEnd { - c.group.DoNotification(ctx, v) - } else if v.ContentType > constant.SignalingNotificationBegin && v.ContentType < constant.SignalingNotificationEnd { - continue - } - } - } - } - -} diff --git a/internal/conversation_msg/convert.go b/internal/conversation_msg/convert.go index 535924086..78180d430 100644 --- a/internal/conversation_msg/convert.go +++ b/internal/conversation_msg/convert.go @@ -17,7 +17,7 @@ package conversation_msg import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - pbConversation "github.com/OpenIMSDK/protocol/conversation" + pbConversation "github.com/openimsdk/protocol/conversation" ) func ServerConversationToLocal(conversation *pbConversation.Conversation) *model_struct.LocalConversation { diff --git a/internal/conversation_msg/create_message.go b/internal/conversation_msg/create_message.go index db06d2fd9..ace457bea 100644 --- a/internal/conversation_msg/create_message.go +++ b/internal/conversation_msg/create_message.go @@ -17,8 +17,8 @@ package conversation_msg import ( "context" "errors" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" + "github.com/openimsdk/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" diff --git a/internal/conversation_msg/delete.go b/internal/conversation_msg/delete.go index 982efc987..8cfa3e22c 100644 --- a/internal/conversation_msg/delete.go +++ b/internal/conversation_msg/delete.go @@ -24,10 +24,10 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" - pbMsg "github.com/OpenIMSDK/protocol/msg" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" "github.com/jinzhu/copier" + pbMsg "github.com/openimsdk/protocol/msg" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) // Delete the local and server diff --git a/internal/conversation_msg/entering.go b/internal/conversation_msg/entering.go index 2b0ecd299..5db1055e4 100644 --- a/internal/conversation_msg/entering.go +++ b/internal/conversation_msg/entering.go @@ -3,15 +3,15 @@ package conversation_msg import ( "context" "encoding/json" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/log" - utils2 "github.com/OpenIMSDK/tools/utils" "github.com/jinzhu/copier" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/utils/datautil" "github.com/patrickmn/go-cache" "time" ) @@ -40,7 +40,7 @@ func newTyping(c *Conversation) *typing { e.platformIDSet[int32(id)] = struct{}{} e.platformIDs = append(e.platformIDs, int32(id)) } - utils2.Sort(e.platformIDs, true) + datautil.Sort(e.platformIDs, true) e.state.OnEvicted(func(key string, val interface{}) { var data inputStatesKey if err := json.Unmarshal([]byte(key), &data); err != nil { @@ -63,7 +63,7 @@ type typing struct { func (e *typing) ChangeInputStates(ctx context.Context, conversationID string, focus bool) error { if conversationID == "" { - return errs.ErrArgs.Wrap("conversationID can't be empty") + return errs.ErrArgs.WrapMsg("conversationID can't be empty") } conversation, err := e.conv.db.GetConversation(ctx, conversationID) if err != nil { diff --git a/internal/conversation_msg/image.go b/internal/conversation_msg/image.go index 4f87bb6f9..309776486 100644 --- a/internal/conversation_msg/image.go +++ b/internal/conversation_msg/image.go @@ -1,8 +1,8 @@ package conversation_msg import ( - "github.com/OpenIMSDK/tools/errs" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/errs" _ "golang.org/x/image/bmp" _ "golang.org/x/image/tiff" _ "golang.org/x/image/webp" @@ -16,7 +16,7 @@ import ( func getImageInfo(filePath string) (*sdk_struct.ImageInfo, error) { file, err := os.Open(filePath) if err != nil { - return nil, errs.Wrap(err, "image file open err") + return nil, errs.WrapMsg(err, "image file open err") } defer file.Close() info, err := file.Stat() @@ -25,7 +25,7 @@ func getImageInfo(filePath string) (*sdk_struct.ImageInfo, error) { } img, format, err := image.Decode(file) if err != nil { - return nil, errs.Wrap(err, "image file decode err") + return nil, errs.WrapMsg(err, "image file decode err") } size := img.Bounds().Max return &sdk_struct.ImageInfo{Width: int32(size.X), Height: int32(size.Y), Type: "image/" + format, Size: info.Size()}, nil diff --git a/internal/conversation_msg/message_check.go b/internal/conversation_msg/message_check.go index aa5cf086a..3dd820825 100644 --- a/internal/conversation_msg/message_check.go +++ b/internal/conversation_msg/message_check.go @@ -21,11 +21,11 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" sdk "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/utils/datautil" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" - "github.com/OpenIMSDK/protocol/sdkws" - utils2 "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/protocol/sdkws" ) // 检测其内部连续性,如果不连续,则向前补齐,获取这一组消息的最大最小seq,以及需要补齐的seq列表长度 @@ -326,14 +326,14 @@ func (c *Conversation) singleHandle(ctx context.Context, self, others []*model_s } func (c *Conversation) groupHandle(ctx context.Context, self, others []*model_struct.LocalChatLog, lc *model_struct.LocalConversation) { allMessage := append(self, others...) - localGroupMemberInfo, err := c.group.GetSpecifiedGroupMembersInfo(ctx, lc.GroupID, utils2.Slice(allMessage, func(e *model_struct.LocalChatLog) string { + localGroupMemberInfo, err := c.group.GetSpecifiedGroupMembersInfo(ctx, lc.GroupID, datautil.Slice(allMessage, func(e *model_struct.LocalChatLog) string { return e.SendID })) if err != nil { log.ZError(ctx, "get group member info err", err) return } - groupMap := utils2.SliceToMap(localGroupMemberInfo, func(e *model_struct.LocalGroupMember) string { + groupMap := datautil.SliceToMap(localGroupMemberInfo, func(e *model_struct.LocalGroupMember) string { return e.UserID }) for _, chatLog := range allMessage { diff --git a/internal/conversation_msg/message_controller.go b/internal/conversation_msg/message_controller.go index f836e9253..bf8f79d16 100644 --- a/internal/conversation_msg/message_controller.go +++ b/internal/conversation_msg/message_controller.go @@ -25,8 +25,8 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) type MessageController struct { @@ -50,7 +50,7 @@ func (m *MessageController) BatchUpdateMessageList(ctx context.Context, updateMs latestMsg := &sdk_struct.MsgStruct{} if err := json.Unmarshal([]byte(conversation.LatestMsg), latestMsg); err != nil { log.ZError(ctx, "Unmarshal err", err, "conversationID", - conversationID, "latestMsg", conversation.LatestMsg) + conversationID, "latestMsg", conversation.LatestMsg, "messages", messages) continue } for _, v := range messages { diff --git a/internal/conversation_msg/progress.go b/internal/conversation_msg/progress.go index dddc894d2..c19798231 100644 --- a/internal/conversation_msg/progress.go +++ b/internal/conversation_msg/progress.go @@ -21,7 +21,7 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" ) func NewUploadFileCallback(ctx context.Context, progress func(progress int), msg *sdk_struct.MsgStruct, conversationID string, db db_interface.DataBase) file.UploadFileCallback { diff --git a/internal/conversation_msg/read_drawing.go b/internal/conversation_msg/read_drawing.go index 61ff561c0..4ec825dbf 100644 --- a/internal/conversation_msg/read_drawing.go +++ b/internal/conversation_msg/read_drawing.go @@ -18,7 +18,6 @@ import ( "context" "encoding/json" "errors" - utils2 "github.com/OpenIMSDK/tools/utils" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/common" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" @@ -26,10 +25,11 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/utils/datautil" - pbMsg "github.com/OpenIMSDK/protocol/msg" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" + pbMsg "github.com/openimsdk/protocol/msg" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) func (c *Conversation) markMsgAsRead2Svr(ctx context.Context, conversationID string, seqs []int64) error { @@ -209,7 +209,7 @@ func (c *Conversation) doUnreadCount(ctx context.Context, conversation *model_st if err := json.Unmarshal([]byte(conversation.LatestMsg), latestMsg); err != nil { log.ZError(ctx, "Unmarshal err", err, "conversationID", conversation.ConversationID, "latestMsg", conversation.LatestMsg) } - if (!latestMsg.IsRead) && utils2.Contain(latestMsg.Seq, seqs...) { + if (!latestMsg.IsRead) && datautil.Contain(latestMsg.Seq, seqs...) { latestMsg.IsRead = true conversation.LatestMsg = utils.StructToJsonString(&latestMsg) _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{ConID: conversation.ConversationID, Action: constant.AddConOrUpLatMsg, Args: *conversation}, c.GetCh()) @@ -275,25 +275,6 @@ func (c *Conversation) doReadDrawing(ctx context.Context, msg *sdkws.MsgData) { SessionType: conversation.ConversationType, ReadTime: msg.SendTime}} c.msgListener().OnRecvC2CReadReceipt(utils.StructToJsonString(messageReceiptResp)) } - //else if conversation.ConversationType == constant.SuperGroupChatType { - // var successMsgIDs []string - // for _, message := range messages { - // attachInfo := sdk_struct.AttachedInfoElem{} - // _ = utils.JsonStringToStruct(message.AttachedInfo, &attachInfo) - // attachInfo.HasReadTime = msg.SendTime - // attachInfo.GroupHasReadInfo.HasReadUserIDList = utils.RemoveRepeatedStringInList(append(attachInfo.GroupHasReadInfo.HasReadUserIDList, tips.MarkAsReadUserID)) - // attachInfo.GroupHasReadInfo.HasReadCount = int32(len(attachInfo.GroupHasReadInfo.HasReadUserIDList)) - // message.AttachedInfo = utils.StructToJsonString(attachInfo) - // if err = c.db.UpdateMessage(ctx, tips.ConversationID, message); err != nil { - // log.ZError(ctx, "UpdateMessage err", err, "conversationID", tips.ConversationID, "message", message) - // } else { - // successMsgIDs = append(successMsgIDs, message.ClientMsgID) - // } - // } - // var messageReceiptResp = []*sdk_struct.MessageReceipt{{GroupID: conversation.GroupID, MsgIDList: successMsgIDs, - // SessionType: conversation.ConversationType, ReadTime: msg.SendTime}} - // c.msgListener.OnRecvGroupReadReceipt(utils.StructToJsonString(messageReceiptResp)) - //} } else { c.doUnreadCount(ctx, conversation, tips.HasReadSeq, tips.Seqs) } diff --git a/internal/conversation_msg/revoke.go b/internal/conversation_msg/revoke.go index 5e5a3b192..d2743a394 100644 --- a/internal/conversation_msg/revoke.go +++ b/internal/conversation_msg/revoke.go @@ -23,12 +23,12 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/utils/timeutil" - pbMsg "github.com/OpenIMSDK/protocol/msg" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" - utils2 "github.com/OpenIMSDK/tools/utils" "github.com/jinzhu/copier" + pbMsg "github.com/openimsdk/protocol/msg" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) func (c *Conversation) doRevokeMsg(ctx context.Context, msg *sdkws.MsgData) { @@ -195,7 +195,7 @@ func (c *Conversation) revokeOneMessage(ctx context.Context, conversationID, cli ConversationID: conversationID, Seq: message.Seq, RevokerUserID: c.loginUserID, - RevokeTime: utils2.GetCurrentTimestampBySecond(), + RevokeTime: timeutil.GetCurrentTimestampBySecond(), SesstionType: conversation.ConversationType, ClientMsgID: clientMsgID, }) diff --git a/internal/conversation_msg/sdk.go b/internal/conversation_msg/sdk.go index a44597e2b..4e6913b22 100644 --- a/internal/conversation_msg/sdk.go +++ b/internal/conversation_msg/sdk.go @@ -36,11 +36,11 @@ import ( "sync" "time" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" - pbConversation "github.com/OpenIMSDK/protocol/conversation" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/protocol/wrapperspb" + pbConversation "github.com/openimsdk/protocol/conversation" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/protocol/wrapperspb" "github.com/jinzhu/copier" ) @@ -331,6 +331,13 @@ func (c *Conversation) checkID(ctx context.Context, s *sdk_struct.MsgStruct, if gm.Nickname != "" { s.SenderNickname = gm.Nickname } + } else { //Maybe the group member information hasn't been pulled locally yet. + gm, err := c.group.GetSpecifiedGroupMembersInfo(ctx, groupID, []string{c.loginUserID}) + if err == nil && gm != nil { + if gm[0].Nickname != "" { + s.SenderNickname = gm[0].Nickname + } + } } var attachedInfo sdk_struct.AttachedInfoElem attachedInfo.GroupHasReadInfo.GroupMemberCount = g.MemberCount @@ -1126,7 +1133,7 @@ func (c *Conversation) GetMessageListReactionExtensions(ctx context.Context, con func (c *Conversation) SearchConversation(ctx context.Context, searchParam string) ([]*server_api_params.Conversation, error) { // Check if search parameter is empty if searchParam == "" { - return nil, sdkerrs.ErrArgs.Wrap("search parameter cannot be empty") + return nil, sdkerrs.ErrArgs.WrapMsg("search parameter cannot be empty") } // Perform the search in your database or data source diff --git a/internal/conversation_msg/sync.go b/internal/conversation_msg/sync.go index ca8ec86d6..bfb6261f7 100644 --- a/internal/conversation_msg/sync.go +++ b/internal/conversation_msg/sync.go @@ -16,17 +16,17 @@ package conversation_msg import ( "context" - utils2 "github.com/OpenIMSDK/tools/utils" "github.com/openimsdk/openim-sdk-core/v3/pkg/common" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/syncer" + "github.com/openimsdk/tools/utils/datautil" "time" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" ) -func (c *Conversation) SyncConversationsAndTriggerCallback(ctx context.Context, conversationsOnServer []*model_struct.LocalConversation) error { +func (c *Conversation) SyncConversationsAndTriggerCallback(ctx context.Context, conversationsOnServer []*model_struct.LocalConversation, skipNotice bool) error { conversationsOnLocal, err := c.db.GetAllConversations(ctx) if err != nil { return err @@ -39,7 +39,7 @@ func (c *Conversation) SyncConversationsAndTriggerCallback(ctx context.Context, c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{ConID: server.ConversationID, Action: constant.ConChange, Args: []string{server.ConversationID}}}) } return nil - }, true); err != nil { + }, true, skipNotice); err != nil { return err } return nil @@ -50,7 +50,7 @@ func (c *Conversation) SyncConversations(ctx context.Context, conversationIDs [] if err != nil { return err } - return c.SyncConversationsAndTriggerCallback(ctx, conversationsOnServer) + return c.SyncConversationsAndTriggerCallback(ctx, conversationsOnServer, false) } func (c *Conversation) SyncAllConversations(ctx context.Context) error { @@ -60,29 +60,48 @@ func (c *Conversation) SyncAllConversations(ctx context.Context) error { return err } log.ZDebug(ctx, "get server cost time", "cost time", time.Since(ccTime), "conversation on server", conversationsOnServer) - return c.SyncConversationsAndTriggerCallback(ctx, conversationsOnServer) + return c.SyncConversationsAndTriggerCallback(ctx, conversationsOnServer, false) +} + +func (c *Conversation) SyncAllConversationsWithoutNotice(ctx context.Context) error { + ccTime := time.Now() + conversationsOnServer, err := c.getServerConversationList(ctx) + if err != nil { + return err + } + log.ZDebug(ctx, "get server cost time", "cost time", time.Since(ccTime), "conversation on server", conversationsOnServer) + return c.SyncConversationsAndTriggerCallback(ctx, conversationsOnServer, true) } func (c *Conversation) SyncAllConversationHashReadSeqs(ctx context.Context) error { + startTime := time.Now() log.ZDebug(ctx, "start SyncConversationHashReadSeqs") + seqs, err := c.getServerHasReadAndMaxSeqs(ctx) if err != nil { return err } + log.ZDebug(ctx, "getServerHasReadAndMaxSeqs completed", "duration", time.Since(startTime).Seconds()) + if len(seqs) == 0 { return nil } var conversationChangedIDs []string var conversationIDsNeedSync []string + stepStartTime := time.Now() conversationsOnLocal, err := c.db.GetAllConversations(ctx) if err != nil { log.ZWarn(ctx, "get all conversations err", err) return err } - conversationsOnLocalMap := utils2.SliceToMap(conversationsOnLocal, func(e *model_struct.LocalConversation) string { + log.ZDebug(ctx, "GetAllConversations completed", "duration", time.Since(stepStartTime).Seconds()) + + conversationsOnLocalMap := datautil.SliceToMap(conversationsOnLocal, func(e *model_struct.LocalConversation) string { return e.ConversationID }) + + stepStartTime = time.Now() for conversationID, v := range seqs { var unreadCount int32 c.maxSeqRecorder.Set(conversationID, v.MaxSeq) @@ -104,18 +123,24 @@ func (c *Conversation) SyncAllConversationHashReadSeqs(ctx context.Context) erro } else { conversationIDsNeedSync = append(conversationIDsNeedSync, conversationID) } - } + log.ZDebug(ctx, "Process seqs completed", "duration", time.Since(stepStartTime).Seconds()) + if len(conversationIDsNeedSync) > 0 { + stepStartTime = time.Now() conversationsOnServer, err := c.getServerConversationsByIDs(ctx, conversationIDsNeedSync) if err != nil { log.ZWarn(ctx, "getServerConversationsByIDs err", err, "conversationIDs", conversationIDsNeedSync) return err } + log.ZDebug(ctx, "getServerConversationsByIDs completed", "duration", time.Since(stepStartTime).Seconds()) + + stepStartTime = time.Now() if err := c.batchAddFaceURLAndName(ctx, conversationsOnServer...); err != nil { log.ZWarn(ctx, "batchAddFaceURLAndName err", err, "conversationsOnServer", conversationsOnServer) return err } + log.ZDebug(ctx, "batchAddFaceURLAndName completed", "duration", time.Since(stepStartTime).Seconds()) for _, conversation := range conversationsOnServer { var unreadCount int32 @@ -132,17 +157,23 @@ func (c *Conversation) SyncAllConversationHashReadSeqs(ctx context.Context) erro conversation.UnreadCount = unreadCount conversation.HasReadSeq = v.HasReadSeq } + + stepStartTime = time.Now() err = c.db.BatchInsertConversationList(ctx, conversationsOnServer) if err != nil { log.ZWarn(ctx, "BatchInsertConversationList err", err, "conversationsOnServer", conversationsOnServer) } - + log.ZDebug(ctx, "BatchInsertConversationList completed", "duration", time.Since(stepStartTime).Seconds()) } log.ZDebug(ctx, "update conversations", "conversations", conversationChangedIDs) if len(conversationChangedIDs) > 0 { + stepStartTime = time.Now() common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.ConChange, Args: conversationChangedIDs}, c.GetCh()) common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.TotalUnreadMessageChanged}, c.GetCh()) + log.ZDebug(ctx, "TriggerCmdUpdateConversation completed", "duration", time.Since(stepStartTime).Seconds()) } + + log.ZDebug(ctx, "SyncAllConversationHashReadSeqs completed", "totalDuration", time.Since(startTime).Seconds()) return nil } diff --git a/internal/file/upload.go b/internal/file/upload.go index b693a4ad0..4c9714e4d 100644 --- a/internal/file/upload.go +++ b/internal/file/upload.go @@ -21,11 +21,11 @@ import ( "encoding/hex" "errors" "fmt" - "github.com/OpenIMSDK/tools/errs" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + "github.com/openimsdk/tools/errs" "io" "net/http" "net/url" @@ -34,8 +34,8 @@ import ( "sync/atomic" "time" - "github.com/OpenIMSDK/protocol/third" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/protocol/third" + "github.com/openimsdk/tools/log" ) type UploadFileReq struct { @@ -247,7 +247,7 @@ func (f *File) initiateMultipartUploadResp(ctx context.Context, req *third.Initi func (f *File) authSign(ctx context.Context, req *third.AuthSignReq) (*third.AuthSignResp, error) { if len(req.PartNumbers) == 0 { - return nil, errs.ErrArgs.Wrap("partNumbers is empty") + return nil, errs.ErrArgs.WrapMsg("partNumbers is empty") } return util.CallApi[third.AuthSignResp](ctx, constant.ObjectAuthSign, req) } @@ -412,7 +412,7 @@ func (u *UploadInfo) GetPartSign(ctx context.Context, partNumber int32) (*url.UR u.CreateTime = time.Now() index := u.getIndex(partNumber) if index < 0 { - return nil, nil, errs.ErrInternalServer.Wrap("server part sign invalid") + return nil, nil, errs.ErrInternalServer.WrapMsg("server part sign invalid") } return u.buildRequest(index) } diff --git a/internal/friend/conversion.go b/internal/friend/conversion.go index 52687e94f..0466bb449 100644 --- a/internal/friend/conversion.go +++ b/internal/friend/conversion.go @@ -16,8 +16,7 @@ package friend import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" ) func ServerFriendRequestToLocalFriendRequest(info *sdkws.FriendRequest) *model_struct.LocalFriendRequest { diff --git a/internal/friend/friend.go b/internal/friend/friend.go index 6c4056ad4..33fe3f4e9 100644 --- a/internal/friend/friend.go +++ b/internal/friend/friend.go @@ -16,18 +16,20 @@ package friend import ( "context" - "fmt" + "github.com/openimsdk/openim-sdk-core/v3/internal/user" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/common" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + "github.com/openimsdk/openim-sdk-core/v3/pkg/page" "github.com/openimsdk/openim-sdk-core/v3/pkg/syncer" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + friend "github.com/openimsdk/protocol/relation" + "github.com/openimsdk/tools/utils/datautil" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) func NewFriend(loginUserID string, db db_interface.DataBase, user *user.User, conversationCh chan common.Cmd2Value) *Friend { @@ -41,47 +43,81 @@ type Friend struct { loginUserID string db db_interface.DataBase user *user.User - friendSyncer *syncer.Syncer[*model_struct.LocalFriend, [2]string] - blockSyncer *syncer.Syncer[*model_struct.LocalBlack, [2]string] - requestRecvSyncer *syncer.Syncer[*model_struct.LocalFriendRequest, [2]string] - requestSendSyncer *syncer.Syncer[*model_struct.LocalFriendRequest, [2]string] + friendSyncer *syncer.Syncer[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string] + blockSyncer *syncer.Syncer[*model_struct.LocalBlack, syncer.NoResp, [2]string] + requestRecvSyncer *syncer.Syncer[*model_struct.LocalFriendRequest, syncer.NoResp, [2]string] + requestSendSyncer *syncer.Syncer[*model_struct.LocalFriendRequest, syncer.NoResp, [2]string] conversationCh chan common.Cmd2Value listenerForService open_im_sdk_callback.OnListenerForService } func (f *Friend) initSyncer() { - f.friendSyncer = syncer.New(func(ctx context.Context, value *model_struct.LocalFriend) error { - return f.db.InsertFriend(ctx, value) - }, func(ctx context.Context, value *model_struct.LocalFriend) error { - return f.db.DeleteFriendDB(ctx, value.FriendUserID) - }, func(ctx context.Context, server *model_struct.LocalFriend, local *model_struct.LocalFriend) error { - return f.db.UpdateFriend(ctx, server) - - }, func(value *model_struct.LocalFriend) [2]string { - return [...]string{value.OwnerUserID, value.FriendUserID} - }, nil, func(ctx context.Context, state int, server, local *model_struct.LocalFriend) error { - switch state { - case syncer.Insert: - f.friendListener.OnFriendAdded(*server) - case syncer.Delete: - log.ZDebug(ctx, "syncer OnFriendDeleted", "local", local) - f.friendListener.OnFriendDeleted(*local) - case syncer.Update: - f.friendListener.OnFriendInfoChanged(*server) - if local.Nickname != server.Nickname || local.FaceURL != server.FaceURL || local.Remark != server.Remark { - if server.Remark != "" { - server.Nickname = server.Remark + f.friendSyncer = syncer.New2[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string]( + syncer.WithInsert[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, value *model_struct.LocalFriend) error { + return f.db.InsertFriend(ctx, value) + }), + syncer.WithDelete[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, value *model_struct.LocalFriend) error { + return f.db.DeleteFriendDB(ctx, value.FriendUserID) + }), + syncer.WithUpdate[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, server, local *model_struct.LocalFriend) error { + return f.db.UpdateFriend(ctx, server) + }), + syncer.WithUUID[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(value *model_struct.LocalFriend) [2]string { + return [...]string{value.OwnerUserID, value.FriendUserID} + }), + syncer.WithNotice[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, state int, server, local *model_struct.LocalFriend) error { + switch state { + case syncer.Insert: + f.friendListener.OnFriendAdded(*server) + case syncer.Delete: + log.ZDebug(ctx, "syncer OnFriendDeleted", "local", local) + f.friendListener.OnFriendDeleted(*local) + case syncer.Update: + f.friendListener.OnFriendInfoChanged(*server) + if local.Nickname != server.Nickname || local.FaceURL != server.FaceURL || local.Remark != server.Remark { + if server.Remark != "" { + server.Nickname = server.Remark + } + _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{ + Action: constant.UpdateConFaceUrlAndNickName, + Args: common.SourceIDAndSessionType{ + SourceID: server.FriendUserID, + SessionType: constant.SingleChatType, + FaceURL: server.FaceURL, + Nickname: server.Nickname, + }, + }, f.conversationCh) + _ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{ + Action: constant.UpdateMsgFaceUrlAndNickName, + Args: common.UpdateMessageInfo{ + SessionType: constant.SingleChatType, + UserID: server.FriendUserID, + FaceURL: server.FaceURL, + Nickname: server.Nickname, + }, + }, f.conversationCh) } - _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.UpdateConFaceUrlAndNickName, - Args: common.SourceIDAndSessionType{SourceID: server.FriendUserID, SessionType: constant.SingleChatType, FaceURL: server.FaceURL, Nickname: server.Nickname}}, f.conversationCh) - _ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, - Args: common.UpdateMessageInfo{SessionType: constant.SingleChatType, UserID: server.FriendUserID, FaceURL: server.FaceURL, Nickname: server.Nickname}}, f.conversationCh) } - - } - return nil - }) - f.blockSyncer = syncer.New(func(ctx context.Context, value *model_struct.LocalBlack) error { + return nil + }), + syncer.WithBatchInsert[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, values []*model_struct.LocalFriend) error { + log.ZDebug(ctx, "BatchInsertFriend", "length", len(values)) + return f.db.BatchInsertFriend(ctx, values) + }), + syncer.WithDeleteAll[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, _ string) error { + return f.db.DeleteAllFriend(ctx) + }), + syncer.WithBatchPageReq[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(entityID string) page.PageReq { + return &friend.GetPaginationFriendsReq{UserID: entityID, + Pagination: &sdkws.RequestPagination{ShowNumber: 100}} + }), + syncer.WithBatchPageRespConvertFunc[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(resp *friend.GetPaginationFriendsResp) []*model_struct.LocalFriend { + return datautil.Batch(ServerFriendToLocalFriend, resp.FriendsInfo) + }), + syncer.WithReqApiRouter[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](constant.GetFriendListRouter), + ) + + f.blockSyncer = syncer.New[*model_struct.LocalBlack, syncer.NoResp, [2]string](func(ctx context.Context, value *model_struct.LocalBlack) error { return f.db.InsertBlack(ctx, value) }, func(ctx context.Context, value *model_struct.LocalBlack) error { return f.db.DeleteBlack(ctx, value.BlockUserID) @@ -98,7 +134,7 @@ func (f *Friend) initSyncer() { } return nil }) - f.requestRecvSyncer = syncer.New(func(ctx context.Context, value *model_struct.LocalFriendRequest) error { + f.requestRecvSyncer = syncer.New[*model_struct.LocalFriendRequest, syncer.NoResp, [2]string](func(ctx context.Context, value *model_struct.LocalFriendRequest) error { return f.db.InsertFriendRequest(ctx, value) }, func(ctx context.Context, value *model_struct.LocalFriendRequest) error { return f.db.DeleteFriendRequestBothUserID(ctx, value.FromUserID, value.ToUserID) @@ -124,7 +160,7 @@ func (f *Friend) initSyncer() { } return nil }) - f.requestSendSyncer = syncer.New(func(ctx context.Context, value *model_struct.LocalFriendRequest) error { + f.requestSendSyncer = syncer.New[*model_struct.LocalFriendRequest, syncer.NoResp, [2]string](func(ctx context.Context, value *model_struct.LocalFriendRequest) error { return f.db.InsertFriendRequest(ctx, value) }, func(ctx context.Context, value *model_struct.LocalFriendRequest) error { return f.db.DeleteFriendRequestBothUserID(ctx, value.FromUserID, value.ToUserID) @@ -161,114 +197,3 @@ func (f *Friend) SetListener(listener func() open_im_sdk_callback.OnFriendshipLi func (f *Friend) SetListenerForService(listener open_im_sdk_callback.OnListenerForService) { f.listenerForService = listener } - -func (f *Friend) DoNotification(ctx context.Context, msg *sdkws.MsgData) { - go func() { - if err := f.doNotification(ctx, msg); err != nil { - log.ZError(ctx, "doNotification error", err, "msg", msg) - } - }() -} - -func (f *Friend) doNotification(ctx context.Context, msg *sdkws.MsgData) error { - switch msg.ContentType { - case constant.FriendApplicationNotification: - tips := sdkws.FriendApplicationTips{} - if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { - return err - } - return f.SyncBothFriendRequest(ctx, - tips.FromToUserID.FromUserID, tips.FromToUserID.ToUserID) - case constant.FriendApplicationApprovedNotification: - var tips sdkws.FriendApplicationApprovedTips - err := utils.UnmarshalNotificationElem(msg.Content, &tips) - if err != nil { - return err - } - - if tips.FromToUserID.FromUserID == f.loginUserID { - err = f.SyncFriends(ctx, []string{tips.FromToUserID.ToUserID}) - } else if tips.FromToUserID.ToUserID == f.loginUserID { - err = f.SyncFriends(ctx, []string{tips.FromToUserID.FromUserID}) - } - if err != nil { - return err - } - return f.SyncBothFriendRequest(ctx, tips.FromToUserID.FromUserID, tips.FromToUserID.ToUserID) - case constant.FriendApplicationRejectedNotification: - var tips sdkws.FriendApplicationRejectedTips - if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { - return err - } - return f.SyncBothFriendRequest(ctx, tips.FromToUserID.FromUserID, tips.FromToUserID.ToUserID) - case constant.FriendAddedNotification: - var tips sdkws.FriendAddedTips - if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { - return err - } - if tips.Friend != nil && tips.Friend.FriendUser != nil { - if tips.Friend.FriendUser.UserID == f.loginUserID { - return f.SyncFriends(ctx, []string{tips.Friend.OwnerUserID}) - } else if tips.Friend.OwnerUserID == f.loginUserID { - return f.SyncFriends(ctx, []string{tips.Friend.FriendUser.UserID}) - } - } - case constant.FriendDeletedNotification: - var tips sdkws.FriendDeletedTips - if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { - return err - } - if tips.FromToUserID != nil { - if tips.FromToUserID.FromUserID == f.loginUserID { - return f.deleteFriend(ctx, tips.FromToUserID.ToUserID) - } - } - case constant.FriendRemarkSetNotification: - var tips sdkws.FriendInfoChangedTips - if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { - return err - } - if tips.FromToUserID != nil { - if tips.FromToUserID.FromUserID == f.loginUserID { - return f.SyncFriends(ctx, []string{tips.FromToUserID.ToUserID}) - } - } - case constant.FriendInfoUpdatedNotification: - var tips sdkws.UserInfoUpdatedTips - if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { - return err - } - if tips.UserID != f.loginUserID { - return f.SyncFriends(ctx, []string{tips.UserID}) - } - case constant.BlackAddedNotification: - var tips sdkws.BlackAddedTips - if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { - return err - } - if tips.FromToUserID.FromUserID == f.loginUserID { - return f.SyncAllBlackList(ctx) - } - case constant.BlackDeletedNotification: - var tips sdkws.BlackDeletedTips - if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { - return err - } - if tips.FromToUserID.FromUserID == f.loginUserID { - return f.SyncAllBlackList(ctx) - } - case constant.FriendsInfoUpdateNotification: - - var tips sdkws.FriendsInfoUpdateTips - - if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { - return err - } - if tips.FromToUserID.ToUserID == f.loginUserID { - return f.SyncFriends(ctx, tips.FriendIDs) - } - default: - return fmt.Errorf("type failed %d", msg.ContentType) - } - return nil -} diff --git a/internal/friend/hash.go b/internal/friend/hash.go new file mode 100644 index 000000000..7e5313802 --- /dev/null +++ b/internal/friend/hash.go @@ -0,0 +1,33 @@ +package friend + +import ( + "crypto/md5" + "encoding/binary" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + "github.com/openimsdk/protocol/constant" + "github.com/openimsdk/tools/utils/datautil" + "strconv" + "strings" +) + +func (f *Friend) CalculateHash(friends []*model_struct.LocalFriend) uint64 { + datautil.SortAny(friends, func(a, b *model_struct.LocalFriend) bool { + return a.CreateTime > b.CreateTime + }) + if len(friends) > constant.MaxSyncPullNumber { + friends = friends[:constant.MaxSyncPullNumber] + } + hashStr := strings.Join(datautil.Slice(friends, func(f *model_struct.LocalFriend) string { + return strings.Join([]string{ + f.FriendUserID, + f.Remark, + strconv.FormatInt(f.CreateTime, 10), + strconv.Itoa(int(f.AddSource)), + f.OperatorUserID, + f.Ex, + strconv.FormatBool(f.IsPinned), + }, ",") + }), ";") + sum := md5.Sum([]byte(hashStr)) + return binary.BigEndian.Uint64(sum[:]) +} diff --git a/internal/friend/notification.go b/internal/friend/notification.go index 54db0344c..743ecdc2d 100644 --- a/internal/friend/notification.go +++ b/internal/friend/notification.go @@ -13,3 +13,124 @@ // limitations under the License. package friend + +import ( + "context" + "fmt" + + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" + "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" +) + +func (f *Friend) DoNotification(ctx context.Context, msg *sdkws.MsgData) { + go func() { + if err := f.doNotification(ctx, msg); err != nil { + log.ZError(ctx, "doNotification error", err, "msg", msg) + } + }() +} + +func (f *Friend) doNotification(ctx context.Context, msg *sdkws.MsgData) error { + switch msg.ContentType { + case constant.FriendApplicationNotification: + tips := sdkws.FriendApplicationTips{} + if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { + return err + } + return f.SyncBothFriendRequest(ctx, + tips.FromToUserID.FromUserID, tips.FromToUserID.ToUserID) + case constant.FriendApplicationApprovedNotification: + var tips sdkws.FriendApplicationApprovedTips + err := utils.UnmarshalNotificationElem(msg.Content, &tips) + if err != nil { + return err + } + + if tips.FromToUserID.FromUserID == f.loginUserID { + err = f.SyncFriends(ctx, []string{tips.FromToUserID.ToUserID}) + } else if tips.FromToUserID.ToUserID == f.loginUserID { + err = f.SyncFriends(ctx, []string{tips.FromToUserID.FromUserID}) + } + if err != nil { + return err + } + return f.SyncBothFriendRequest(ctx, tips.FromToUserID.FromUserID, tips.FromToUserID.ToUserID) + case constant.FriendApplicationRejectedNotification: + var tips sdkws.FriendApplicationRejectedTips + if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { + return err + } + return f.SyncBothFriendRequest(ctx, tips.FromToUserID.FromUserID, tips.FromToUserID.ToUserID) + case constant.FriendAddedNotification: + var tips sdkws.FriendAddedTips + if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { + return err + } + if tips.Friend != nil && tips.Friend.FriendUser != nil { + if tips.Friend.FriendUser.UserID == f.loginUserID { + return f.SyncFriends(ctx, []string{tips.Friend.OwnerUserID}) + } else if tips.Friend.OwnerUserID == f.loginUserID { + return f.SyncFriends(ctx, []string{tips.Friend.FriendUser.UserID}) + } + } + case constant.FriendDeletedNotification: + var tips sdkws.FriendDeletedTips + if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { + return err + } + if tips.FromToUserID != nil { + if tips.FromToUserID.FromUserID == f.loginUserID { + return f.deleteFriend(ctx, tips.FromToUserID.ToUserID) + } + } + case constant.FriendRemarkSetNotification: + var tips sdkws.FriendInfoChangedTips + if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { + return err + } + if tips.FromToUserID != nil { + if tips.FromToUserID.FromUserID == f.loginUserID { + return f.SyncFriends(ctx, []string{tips.FromToUserID.ToUserID}) + } + } + case constant.FriendInfoUpdatedNotification: + var tips sdkws.UserInfoUpdatedTips + if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { + return err + } + if tips.UserID != f.loginUserID { + return f.SyncFriends(ctx, []string{tips.UserID}) + } + case constant.BlackAddedNotification: + var tips sdkws.BlackAddedTips + if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { + return err + } + if tips.FromToUserID.FromUserID == f.loginUserID { + return f.SyncAllBlackList(ctx) + } + case constant.BlackDeletedNotification: + var tips sdkws.BlackDeletedTips + if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { + return err + } + if tips.FromToUserID.FromUserID == f.loginUserID { + return f.SyncAllBlackList(ctx) + } + case constant.FriendsInfoUpdateNotification: + + var tips sdkws.FriendsInfoUpdateTips + + if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil { + return err + } + if tips.FromToUserID.ToUserID == f.loginUserID { + return f.SyncFriends(ctx, tips.FriendIDs) + } + default: + return fmt.Errorf("type failed %d", msg.ContentType) + } + return nil +} diff --git a/internal/friend/sdk.go b/internal/friend/sdk.go index d1fd837a3..ed74bff8d 100644 --- a/internal/friend/sdk.go +++ b/internal/friend/sdk.go @@ -16,24 +16,50 @@ package friend import ( "context" - "github.com/OpenIMSDK/protocol/wrapperspb" - "github.com/OpenIMSDK/tools/errs" + + friend "github.com/openimsdk/protocol/relation" + "github.com/openimsdk/protocol/wrapperspb" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/utils/datautil" + "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" + "github.com/openimsdk/openim-sdk-core/v3/pkg/datafetcher" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" sdk "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" - "github.com/OpenIMSDK/protocol/friend" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" ) func (f *Friend) GetSpecifiedFriendsInfo(ctx context.Context, friendUserIDList []string) ([]*server_api_params.FullUserInfo, error) { - localFriendList, err := f.db.GetFriendInfoList(ctx, friendUserIDList) + datafetcher := datafetcher.NewDataFetcher( + f.db, + f.friendListTableName(), + f.loginUserID, + func(localFriend *model_struct.LocalFriend) string { + return localFriend.FriendUserID + }, + func(ctx context.Context, values []*model_struct.LocalFriend) error { + return f.db.BatchInsertFriend(ctx, values) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) { + return f.db.GetFriendInfoList(ctx, userIDs) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) { + serverFriend, err := f.GetDesignatedFriends(ctx, userIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerFriendToLocalFriend, serverFriend), nil + }, + ) + localFriendList, err := datafetcher.FetchMissingAndFillLocal(ctx, friendUserIDList) if err != nil { return nil, err } + log.ZDebug(ctx, "GetDesignatedFriendsInfo", "localFriendList", localFriendList) blackList, err := f.db.GetBlackInfoList(ctx, friendUserIDList) if err != nil { @@ -93,7 +119,7 @@ func (f *Friend) RespondFriendApply(ctx context.Context, req *friend.RespondFrie } _ = f.SyncAllFriendApplication(ctx) return nil - //return f.SyncFriendApplication(ctx) + // return f.SyncFriendApplication(ctx) } func (f *Friend) CheckFriend(ctx context.Context, friendUserIDList []string) ([]*server_api_params.UserIDResult, error) { @@ -165,10 +191,34 @@ func (f *Friend) GetFriendList(ctx context.Context) ([]*server_api_params.FullUs } func (f *Friend) GetFriendListPage(ctx context.Context, offset, count int32) ([]*server_api_params.FullUserInfo, error) { - localFriendList, err := f.db.GetPageFriendList(ctx, int(offset), int(count)) + dataFetcher := datafetcher.NewDataFetcher( + f.db, + f.friendListTableName(), + f.loginUserID, + func(localFriend *model_struct.LocalFriend) string { + return localFriend.FriendUserID + }, + func(ctx context.Context, values []*model_struct.LocalFriend) error { + return f.db.BatchInsertFriend(ctx, values) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) { + return f.db.GetFriendInfoList(ctx, userIDs) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) { + serverFriend, err := f.GetDesignatedFriends(ctx, userIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerFriendToLocalFriend, serverFriend), nil + }, + ) + + localFriendList, err := dataFetcher.FetchWithPagination(ctx, int(offset), int(count)) if err != nil { return nil, err } + + // don't need extra handle. only full pull. localBlackList, err := f.db.GetBlackListDB(ctx) if err != nil { return nil, err @@ -188,9 +238,61 @@ func (f *Friend) GetFriendListPage(ctx context.Context, offset, count int32) ([] return res, nil } +func (f *Friend) GetFriendListPageV2(ctx context.Context, offset, count int32) (*GetFriendInfoListV2, error) { + datafetcher := datafetcher.NewDataFetcher( + f.db, + f.friendListTableName(), + f.loginUserID, + func(localFriend *model_struct.LocalFriend) string { + return localFriend.FriendUserID + }, + func(ctx context.Context, values []*model_struct.LocalFriend) error { + return f.db.BatchInsertFriend(ctx, values) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) { + return f.db.GetFriendInfoList(ctx, userIDs) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) { + serverFriend, err := f.GetDesignatedFriends(ctx, userIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerFriendToLocalFriend, serverFriend), nil + }, + ) + + localFriendList, isEnd, err := datafetcher.FetchWithPaginationV2(ctx, int(offset), int(count)) + if err != nil { + return nil, err + } + + // don't need extra handle. only full pull. + localBlackList, err := f.db.GetBlackListDB(ctx) + if err != nil { + return nil, err + } + m := make(map[string]*model_struct.LocalBlack) + for i, black := range localBlackList { + m[black.BlockUserID] = localBlackList[i] + } + fullUserInfo := make([]*server_api_params.FullUserInfo, 0, len(localFriendList)) + for _, localFriend := range localFriendList { + fullUserInfo = append(fullUserInfo, &server_api_params.FullUserInfo{ + PublicInfo: nil, + FriendInfo: localFriend, + BlackInfo: m[localFriend.FriendUserID], + }) + } + response := &GetFriendInfoListV2{ + FullUserInfoList: fullUserInfo, + IsEnd: isEnd, + } + return response, nil +} + func (f *Friend) SearchFriends(ctx context.Context, param *sdk.SearchFriendsParam) ([]*sdk.SearchFriendItem, error) { if len(param.KeywordList) == 0 || (!param.IsSearchNickname && !param.IsSearchUserID && !param.IsSearchRemark) { - return nil, sdkerrs.ErrArgs.Wrap("keyword is null or search field all false") + return nil, sdkerrs.ErrArgs.WrapMsg("keyword is null or search field all false") } localFriendList, err := f.db.SearchFriendList(ctx, param.KeywordList[0], param.IsSearchUserID, param.IsSearchNickname, param.IsSearchRemark) if err != nil { @@ -233,6 +335,7 @@ func (f *Friend) PinFriends(ctx context.Context, friends *sdk.SetFriendPinParams } return f.SyncFriends(ctx, friends.ToUserIDs) } + func (f *Friend) AddBlack(ctx context.Context, blackUserID string, ex string) error { if err := util.ApiPost(ctx, constant.AddBlackRouter, &friend.AddBlackReq{OwnerUserID: f.loginUserID, BlackUserID: blackUserID, Ex: ex}, nil); err != nil { return err @@ -250,6 +353,7 @@ func (f *Friend) RemoveBlack(ctx context.Context, blackUserID string) error { func (f *Friend) GetBlackList(ctx context.Context) ([]*model_struct.LocalBlack, error) { return f.db.GetBlackListDB(ctx) } + func (f *Friend) SetFriendsEx(ctx context.Context, friendIDs []string, ex string) error { if err := util.ApiPost(ctx, constant.UpdateFriends, &friend.UpdateFriendsReq{OwnerUserID: f.loginUserID, FriendUserIDs: friendIDs, Ex: &wrapperspb.StringValue{ Value: ex, @@ -259,7 +363,7 @@ func (f *Friend) SetFriendsEx(ctx context.Context, friendIDs []string, ex string // Check if the specified ID is a friend friendResults, err := f.CheckFriend(ctx, friendIDs) if err != nil { - return errs.Wrap(err, "Error checking friend status") + return errs.WrapMsg(err, "Error checking friend status") } // Determine if friendID is indeed a friend @@ -277,7 +381,7 @@ func (f *Friend) SetFriendsEx(ctx context.Context, friendIDs []string, ex string // If this friendID is not a friend, return an error if !isFriend { - return errs.ErrRecordNotFound.Wrap("Not friend") + return errs.ErrRecordNotFound.WrapMsg("Not friend") } } @@ -286,7 +390,7 @@ func (f *Friend) SetFriendsEx(ctx context.Context, friendIDs []string, ex string updateErr := f.db.UpdateColumnsFriend(ctx, friendIDs, map[string]interface{}{"Ex": ex}) if updateErr != nil { - return errs.Wrap(updateErr, "Error updating friend information") + return errs.WrapMsg(updateErr, "Error updating friend information") } return nil } diff --git a/internal/friend/sync.go b/internal/friend/sync.go index 87a009af0..4fd297995 100644 --- a/internal/friend/sync.go +++ b/internal/friend/sync.go @@ -16,13 +16,15 @@ package friend import ( "context" + "fmt" + "github.com/openimsdk/tools/utils/datautil" + "time" + "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" - "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" - - "github.com/OpenIMSDK/protocol/friend" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" + friend "github.com/openimsdk/protocol/relation" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) func (f *Friend) SyncBothFriendRequest(ctx context.Context, fromUserID, toUserID string) error { @@ -35,9 +37,9 @@ func (f *Friend) SyncBothFriendRequest(ctx context.Context, fromUserID, toUserID return err } if toUserID == f.loginUserID { - return f.requestRecvSyncer.Sync(ctx, util.Batch(ServerFriendRequestToLocalFriendRequest, resp.FriendRequests), localData, nil) + return f.requestRecvSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, resp.FriendRequests), localData, nil) } else if fromUserID == f.loginUserID { - return f.requestSendSyncer.Sync(ctx, util.Batch(ServerFriendRequestToLocalFriendRequest, resp.FriendRequests), localData, nil) + return f.requestSendSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, resp.FriendRequests), localData, nil) } return nil } @@ -56,7 +58,23 @@ func (f *Friend) SyncAllSelfFriendApplication(ctx context.Context) error { if err != nil { return err } - return f.requestSendSyncer.Sync(ctx, util.Batch(ServerFriendRequestToLocalFriendRequest, requests), localData, nil) + return f.requestSendSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, requests), localData, nil) +} + +func (f *Friend) SyncAllSelfFriendApplicationWithoutNotice(ctx context.Context) error { + req := &friend.GetPaginationFriendsApplyFromReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}} + fn := func(resp *friend.GetPaginationFriendsApplyFromResp) []*sdkws.FriendRequest { + return resp.FriendRequests + } + requests, err := util.GetPageAll(ctx, constant.GetSelfFriendApplicationListRouter, req, fn) + if err != nil { + return err + } + localData, err := f.db.GetSendFriendApplication(ctx) + if err != nil { + return err + } + return f.requestSendSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, requests), localData, nil, false, true) } // recv @@ -71,53 +89,118 @@ func (f *Friend) SyncAllFriendApplication(ctx context.Context) error { if err != nil { return err } - return f.requestRecvSyncer.Sync(ctx, util.Batch(ServerFriendRequestToLocalFriendRequest, requests), localData, nil) + return f.requestRecvSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, requests), localData, nil) } - -func (f *Friend) SyncAllFriendList(ctx context.Context) error { - req := &friend.GetPaginationFriendsReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}} - fn := func(resp *friend.GetPaginationFriendsResp) []*sdkws.FriendInfo { return resp.FriendsInfo } - friends, err := util.GetPageAll(ctx, constant.GetFriendListRouter, req, fn) +func (f *Friend) SyncAllFriendApplicationWithoutNotice(ctx context.Context) error { + req := &friend.GetPaginationFriendsApplyToReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}} + fn := func(resp *friend.GetPaginationFriendsApplyToResp) []*sdkws.FriendRequest { return resp.FriendRequests } + requests, err := util.GetPageAll(ctx, constant.GetFriendApplicationListRouter, req, fn) if err != nil { return err } - localData, err := f.db.GetAllFriendList(ctx) + localData, err := f.db.GetRecvFriendApplication(ctx) if err != nil { return err } - log.ZDebug(ctx, "sync friend", "data from server", friends, "data from local", localData) - return f.friendSyncer.Sync(ctx, util.Batch(ServerFriendToLocalFriend, friends), localData, nil) + return f.requestRecvSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, requests), localData, nil, false, true) +} + +func (f *Friend) SyncAllFriendList(ctx context.Context) error { + t := time.Now() + defer func(start time.Time) { + + elapsed := time.Since(start).Milliseconds() + log.ZDebug(ctx, "SyncAllFriendList fn call end", "cost time", fmt.Sprintf("%d ms", elapsed)) + + }(t) + return f.IncrSyncFriends(ctx) + //req := &friend.GetPaginationFriendsReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}} + //fn := func(resp *friend.GetPaginationFriendsResp) []*sdkws.FriendInfo { return resp.FriendsInfo } + //friends, err := util.GetPageAll(ctx, constant.GetFriendListRouter, req, fn) + //if err != nil { + // return err + //} + //localData, err := f.db.GetAllFriendList(ctx) + //if err != nil { + // return err + //} + //log.ZDebug(ctx, "sync friend", "data from server", friends, "data from local", localData) + //return f.friendSyncer.Sync(ctx, util.Batch(ServerFriendToLocalFriend, friends), localData, nil) } func (f *Friend) deleteFriend(ctx context.Context, friendUserID string) error { - friends, err := f.db.GetFriendInfoList(ctx, []string{friendUserID}) - if err != nil { - return err - } - if len(friends) == 0 { - return sdkerrs.ErrUserIDNotFound.Wrap("friendUserID not found") - } - if err := f.db.DeleteFriendDB(ctx, friendUserID); err != nil { - return err - } - f.friendListener.OnFriendDeleted(*friends[0]) - return nil + return f.IncrSyncFriends(ctx) + //friends, err := f.db.GetFriendInfoList(ctx, []string{friendUserID}) + //if err != nil { + // return err + //} + //if len(friends) == 0 { + // return sdkerrs.ErrUserIDNotFound.WrapMsg("friendUserID not found") + //} + //if err := f.db.DeleteFriendDB(ctx, friendUserID); err != nil { + // return err + //} + //f.friendListener.OnFriendDeleted(*friends[0]) + //return nil } func (f *Friend) SyncFriends(ctx context.Context, friendIDs []string) error { - var resp friend.GetDesignatedFriendsResp - if err := util.ApiPost(ctx, constant.GetDesignatedFriendsRouter, &friend.GetDesignatedFriendsReq{OwnerUserID: f.loginUserID, FriendUserIDs: friendIDs}, &resp); err != nil { + return f.IncrSyncFriends(ctx) + //var resp friend.GetDesignatedFriendsResp + //if err := util.ApiPost(ctx, constant.GetDesignatedFriendsRouter, &friend.GetDesignatedFriendsReq{OwnerUserID: f.loginUserID, FriendUserIDs: friendIDs}, &resp); err != nil { + // return err + //} + //localData, err := f.db.GetFriendInfoList(ctx, friendIDs) + //if err != nil { + // return err + //} + //log.ZDebug(ctx, "sync friend", "data from server", resp.FriendsInfo, "data from local", localData) + //return f.friendSyncer.Sync(ctx, util.Batch(ServerFriendToLocalFriend, resp.FriendsInfo), localData, nil) +} + +//func (f *Friend) SyncFriendPart(ctx context.Context) error { +// hashResp, err := util.CallApi[friend.GetFriendHashResp](ctx, constant.GetFriendHash, &friend.GetFriendHashReq{UserID: f.loginUserID}) +// if err != nil { +// return err +// } +// friends, err := f.db.GetAllFriendList(ctx) +// if err != nil { +// return err +// } +// hashCode := f.CalculateHash(friends) +// log.ZDebug(ctx, "SyncFriendPart", "serverHash", hashResp.Hash, "serverTotal", hashResp.Total, "localHash", hashCode, "localTotal", len(friends)) +// if hashCode == hashResp.Hash { +// return nil +// } +// req := &friend.GetPaginationFriendsReq{ +// UserID: f.loginUserID, +// Pagination: &sdkws.RequestPagination{PageNumber: pconstant.FirstPageNumber, ShowNumber: pconstant.MaxSyncPullNumber}, +// } +// resp, err := util.CallApi[friend.GetPaginationFriendsResp](ctx, constant.GetFriendListRouter, req) +// if err != nil { +// return err +// } +// serverFriends := util.Batch(ServerFriendToLocalFriend, resp.FriendsInfo) +// return f.friendSyncer.Sync(ctx, serverFriends, friends, nil) +//} + +func (f *Friend) SyncAllBlackList(ctx context.Context) error { + req := &friend.GetPaginationBlacksReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}} + fn := func(resp *friend.GetPaginationBlacksResp) []*sdkws.BlackInfo { return resp.Blacks } + serverData, err := util.GetPageAll(ctx, constant.GetBlackListRouter, req, fn) + if err != nil { return err } - localData, err := f.db.GetFriendInfoList(ctx, friendIDs) + log.ZDebug(ctx, "black from server", "data", serverData) + localData, err := f.db.GetBlackListDB(ctx) if err != nil { return err } - log.ZDebug(ctx, "sync friend", "data from server", resp.FriendsInfo, "data from local", localData) - return f.friendSyncer.Sync(ctx, util.Batch(ServerFriendToLocalFriend, resp.FriendsInfo), localData, nil) + log.ZDebug(ctx, "black from local", "data", localData) + return f.blockSyncer.Sync(ctx, datautil.Batch(ServerBlackToLocalBlack, serverData), localData, nil) } -func (f *Friend) SyncAllBlackList(ctx context.Context) error { +func (f *Friend) SyncAllBlackListWithoutNotice(ctx context.Context) error { req := &friend.GetPaginationBlacksReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}} fn := func(resp *friend.GetPaginationBlacksResp) []*sdkws.BlackInfo { return resp.Blacks } serverData, err := util.GetPageAll(ctx, constant.GetBlackListRouter, req, fn) @@ -130,5 +213,13 @@ func (f *Friend) SyncAllBlackList(ctx context.Context) error { return err } log.ZDebug(ctx, "black from local", "data", localData) - return f.blockSyncer.Sync(ctx, util.Batch(ServerBlackToLocalBlack, serverData), localData, nil) + return f.blockSyncer.Sync(ctx, datautil.Batch(ServerBlackToLocalBlack, serverData), localData, nil, false, true) +} + +func (f *Friend) GetDesignatedFriends(ctx context.Context, friendIDs []string) ([]*sdkws.FriendInfo, error) { + resp := &friend.GetDesignatedFriendsResp{} + if err := util.ApiPost(ctx, constant.GetDesignatedFriendsRouter, &friend.GetDesignatedFriendsReq{OwnerUserID: f.loginUserID, FriendUserIDs: friendIDs}, &resp); err != nil { + return nil, err + } + return resp.FriendsInfo, nil } diff --git a/internal/friend/sync2.go b/internal/friend/sync2.go new file mode 100644 index 000000000..58653e57a --- /dev/null +++ b/internal/friend/sync2.go @@ -0,0 +1,72 @@ +package friend + +import ( + "context" + "github.com/openimsdk/openim-sdk-core/v3/internal/incrversion" + "github.com/openimsdk/openim-sdk-core/v3/internal/util" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + friend "github.com/openimsdk/protocol/relation" + "github.com/openimsdk/tools/utils/datautil" +) + +const ( + LocalFriendSyncMaxNum = 1000 +) + +func (f *Friend) IncrSyncFriends(ctx context.Context) error { + friendSyncer := incrversion.VersionSynchronizer[*model_struct.LocalFriend, *friend.GetIncrementalFriendsResp]{ + Ctx: ctx, + DB: f.db, + TableName: f.friendListTableName(), + EntityID: f.loginUserID, + Key: func(localFriend *model_struct.LocalFriend) string { + return localFriend.FriendUserID + }, + Local: func() ([]*model_struct.LocalFriend, error) { + return f.db.GetAllFriendList(ctx) + }, + Server: func(version *model_struct.LocalVersionSync) (*friend.GetIncrementalFriendsResp, error) { + return util.CallApi[friend.GetIncrementalFriendsResp](ctx, constant.GetIncrementalFriends, &friend.GetIncrementalFriendsReq{ + UserID: f.loginUserID, + Version: version.Version, + VersionID: version.VersionID, + }) + }, + Full: func(resp *friend.GetIncrementalFriendsResp) bool { + return resp.Full + }, + Version: func(resp *friend.GetIncrementalFriendsResp) (string, uint64) { + return resp.VersionID, resp.Version + }, + Delete: func(resp *friend.GetIncrementalFriendsResp) []string { + return resp.Delete + }, + Update: func(resp *friend.GetIncrementalFriendsResp) []*model_struct.LocalFriend { + return datautil.Batch(ServerFriendToLocalFriend, resp.Update) + }, + Insert: func(resp *friend.GetIncrementalFriendsResp) []*model_struct.LocalFriend { + return datautil.Batch(ServerFriendToLocalFriend, resp.Insert) + }, + Syncer: func(server, local []*model_struct.LocalFriend) error { + return f.friendSyncer.Sync(ctx, server, local, nil) + }, + FullSyncer: func(ctx context.Context) error { + return f.friendSyncer.FullSync(ctx, f.loginUserID) + }, + FullID: func(ctx context.Context) ([]string, error) { + resp, err := util.CallApi[friend.GetFullFriendUserIDsResp](ctx, constant.GetFullFriendUserIDs, &friend.GetFullFriendUserIDsReq{ + UserID: f.loginUserID, + }) + if err != nil { + return nil, err + } + return resp.UserIDs, nil + }, + } + return friendSyncer.Sync() +} + +func (f *Friend) friendListTableName() string { + return model_struct.LocalFriend{}.TableName() +} diff --git a/internal/friend/sync2_test.go b/internal/friend/sync2_test.go new file mode 100644 index 000000000..d782b69b0 --- /dev/null +++ b/internal/friend/sync2_test.go @@ -0,0 +1,13 @@ +package friend + +import ( + "fmt" + "testing" +) + +func Test_main(t *testing.T) { + a := []int{1, 2, 3, 4, 5} + fmt.Println(a[:3]) + fmt.Println(a[3:]) + fmt.Println(a[2:4]) +} diff --git a/internal/friend/types.go b/internal/friend/types.go new file mode 100644 index 000000000..5429b5657 --- /dev/null +++ b/internal/friend/types.go @@ -0,0 +1,8 @@ +package friend + +import "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" + +type GetFriendInfoListV2 struct { + FullUserInfoList []*server_api_params.FullUserInfo + IsEnd bool `json:"isEnd"` +} diff --git a/internal/full/open_im_sdk_full.go b/internal/full/open_im_sdk_full.go index 5af5471dd..ca26b5d6a 100644 --- a/internal/full/open_im_sdk_full.go +++ b/internal/full/open_im_sdk_full.go @@ -16,12 +16,12 @@ package full import ( "context" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/common" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" api "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) func (u *Full) GetUsersInfo(ctx context.Context, userIDs []string) ([]*api.FullUserInfo, error) { diff --git a/internal/group/conversion.go b/internal/group/conversion.go index 2bd851d89..27d7be6fd 100644 --- a/internal/group/conversion.go +++ b/internal/group/conversion.go @@ -17,7 +17,7 @@ package group import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" ) func ServerGroupToLocalGroup(info *sdkws.GroupInfo) *model_struct.LocalGroup { diff --git a/internal/group/group.go b/internal/group/group.go index 150814d08..f661c7d9c 100644 --- a/internal/group/group.go +++ b/internal/group/group.go @@ -16,19 +16,21 @@ package group import ( "context" - "github.com/OpenIMSDK/protocol/group" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" - utils2 "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/common" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + "github.com/openimsdk/openim-sdk-core/v3/pkg/page" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" "github.com/openimsdk/openim-sdk-core/v3/pkg/syncer" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/protocol/group" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/utils/datautil" ) func NewGroup(loginUserID string, db db_interface.DataBase, @@ -47,10 +49,10 @@ type Group struct { listener func() open_im_sdk_callback.OnGroupListener loginUserID string db db_interface.DataBase - groupSyncer *syncer.Syncer[*model_struct.LocalGroup, string] - groupMemberSyncer *syncer.Syncer[*model_struct.LocalGroupMember, [2]string] - groupRequestSyncer *syncer.Syncer[*model_struct.LocalGroupRequest, [2]string] - groupAdminRequestSyncer *syncer.Syncer[*model_struct.LocalAdminGroupRequest, [2]string] + groupSyncer *syncer.Syncer[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string] + groupMemberSyncer *syncer.Syncer[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string] + groupRequestSyncer *syncer.Syncer[*model_struct.LocalGroupRequest, syncer.NoResp, [2]string] + groupAdminRequestSyncer *syncer.Syncer[*model_struct.LocalAdminGroupRequest, syncer.NoResp, [2]string] joinedSuperGroupCh chan common.Cmd2Value heartbeatCmdCh chan common.Cmd2Value @@ -61,81 +63,140 @@ type Group struct { } func (g *Group) initSyncer() { - g.groupSyncer = syncer.New(func(ctx context.Context, value *model_struct.LocalGroup) error { - return g.db.InsertGroup(ctx, value) - }, func(ctx context.Context, value *model_struct.LocalGroup) error { - if err := g.db.DeleteGroupAllMembers(ctx, value.GroupID); err != nil { - return err - } - return g.db.DeleteGroup(ctx, value.GroupID) - }, func(ctx context.Context, server, local *model_struct.LocalGroup) error { - log.ZInfo(ctx, "groupSyncer trigger update function", "groupID", server.GroupID, "server", server, "local", local) - return g.db.UpdateGroup(ctx, server) - }, func(value *model_struct.LocalGroup) string { - return value.GroupID - }, nil, func(ctx context.Context, state int, server, local *model_struct.LocalGroup) error { - switch state { - case syncer.Insert: - //when a user kicked to the group and invited to the group again, group info maybe updated,so conversation - //info need to be updated - g.listener().OnJoinedGroupAdded(utils.StructToJsonString(server)) - _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.UpdateConFaceUrlAndNickName, - Args: common.SourceIDAndSessionType{SourceID: server.GroupID, SessionType: constant.SuperGroupChatType, - FaceURL: server.FaceURL, Nickname: server.GroupName}}, g.conversationCh) - case syncer.Delete: - g.listener().OnJoinedGroupDeleted(utils.StructToJsonString(local)) - case syncer.Update: - log.ZInfo(ctx, "groupSyncer trigger update", "groupID", - server.GroupID, "data", server, "isDismissed", server.Status == constant.GroupStatusDismissed) - if server.Status == constant.GroupStatusDismissed { - if err := g.db.DeleteGroupAllMembers(ctx, server.GroupID); err != nil { - log.ZError(ctx, "delete group all members failed", err) - } - g.listener().OnGroupDismissed(utils.StructToJsonString(server)) - } else { - g.listener().OnGroupInfoChanged(utils.StructToJsonString(server)) - if server.GroupName != local.GroupName || local.FaceURL != server.FaceURL { - _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.UpdateConFaceUrlAndNickName, - Args: common.SourceIDAndSessionType{SourceID: server.GroupID, SessionType: constant.SuperGroupChatType, FaceURL: server.FaceURL, Nickname: server.GroupName}}, g.conversationCh) + g.groupSyncer = syncer.New2[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string]( + syncer.WithInsert[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](func(ctx context.Context, value *model_struct.LocalGroup) error { + return g.db.InsertGroup(ctx, value) + }), + syncer.WithDelete[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](func(ctx context.Context, value *model_struct.LocalGroup) error { + if err := g.db.DeleteGroupAllMembers(ctx, value.GroupID); err != nil { + return err + } + if err := g.db.DeleteVersionSync(ctx, g.groupAndMemberVersionTableName(), value.GroupID); err != nil { + return err + } + return g.db.DeleteGroup(ctx, value.GroupID) + }), + syncer.WithUpdate[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](func(ctx context.Context, server, local *model_struct.LocalGroup) error { + log.ZInfo(ctx, "groupSyncer trigger update function", "groupID", server.GroupID, "server", server, "local", local) + return g.db.UpdateGroup(ctx, server) + }), + syncer.WithUUID[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](func(value *model_struct.LocalGroup) string { + return value.GroupID + }), + syncer.WithNotice[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](func(ctx context.Context, state int, server, local *model_struct.LocalGroup) error { + switch state { + case syncer.Insert: + // when a user kicked to the group and invited to the group again, group info maybe updated, + // so conversation info need to be updated + g.listener().OnJoinedGroupAdded(utils.StructToJsonString(server)) + _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{ + Action: constant.UpdateConFaceUrlAndNickName, + Args: common.SourceIDAndSessionType{ + SourceID: server.GroupID, SessionType: constant.SuperGroupChatType, + FaceURL: server.FaceURL, Nickname: server.GroupName, + }, + }, g.conversationCh) + case syncer.Delete: + local.MemberCount = 0 + g.listener().OnJoinedGroupDeleted(utils.StructToJsonString(local)) + case syncer.Update: + log.ZInfo(ctx, "groupSyncer trigger update", "groupID", + server.GroupID, "data", server, "isDismissed", server.Status == constant.GroupStatusDismissed) + if server.Status == constant.GroupStatusDismissed { + if err := g.db.DeleteGroupAllMembers(ctx, server.GroupID); err != nil { + log.ZError(ctx, "delete group all members failed", err) + } + g.listener().OnGroupDismissed(utils.StructToJsonString(server)) + } else { + g.listener().OnGroupInfoChanged(utils.StructToJsonString(server)) + if server.GroupName != local.GroupName || local.FaceURL != server.FaceURL { + _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{ + Action: constant.UpdateConFaceUrlAndNickName, + Args: common.SourceIDAndSessionType{ + SourceID: server.GroupID, SessionType: constant.SuperGroupChatType, + FaceURL: server.FaceURL, Nickname: server.GroupName, + }, + }, g.conversationCh) + } } } - } - - return nil - }) + return nil + }), + syncer.WithBatchInsert[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](func(ctx context.Context, values []*model_struct.LocalGroup) error { + return g.db.BatchInsertGroup(ctx, values) + }), + syncer.WithDeleteAll[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](func(ctx context.Context, _ string) error { + return g.db.DeleteAllGroup(ctx) + }), + syncer.WithBatchPageReq[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](func(entityID string) page.PageReq { + return &group.GetJoinedGroupListReq{FromUserID: entityID, + Pagination: &sdkws.RequestPagination{ShowNumber: 100}} + }), + syncer.WithBatchPageRespConvertFunc[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](func(resp *group.GetJoinedGroupListResp) []*model_struct.LocalGroup { + return datautil.Batch(ServerGroupToLocalGroup, resp.Groups) + }), + syncer.WithReqApiRouter[*model_struct.LocalGroup, group.GetJoinedGroupListResp, string](constant.GetJoinedGroupListRouter), + ) - g.groupMemberSyncer = syncer.New(func(ctx context.Context, value *model_struct.LocalGroupMember) error { - return g.db.InsertGroupMember(ctx, value) - }, func(ctx context.Context, value *model_struct.LocalGroupMember) error { - return g.db.DeleteGroupMember(ctx, value.GroupID, value.UserID) - }, func(ctx context.Context, server, local *model_struct.LocalGroupMember) error { - return g.db.UpdateGroupMember(ctx, server) - }, func(value *model_struct.LocalGroupMember) [2]string { - return [...]string{value.GroupID, value.UserID} - }, nil, func(ctx context.Context, state int, server, local *model_struct.LocalGroupMember) error { - switch state { - case syncer.Insert: - g.listener().OnGroupMemberAdded(utils.StructToJsonString(server)) - //when a user kicked and invited to the group again, group member info will be updated - _ = common.TriggerCmdUpdateMessage(ctx, - common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, - Args: common.UpdateMessageInfo{SessionType: constant.SuperGroupChatType, UserID: server.UserID, FaceURL: server.FaceURL, - Nickname: server.Nickname, GroupID: server.GroupID}}, g.conversationCh) - case syncer.Delete: - g.listener().OnGroupMemberDeleted(utils.StructToJsonString(local)) - case syncer.Update: - g.listener().OnGroupMemberInfoChanged(utils.StructToJsonString(server)) - if server.Nickname != local.Nickname || server.FaceURL != local.FaceURL { + g.groupMemberSyncer = syncer.New2[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string]( + syncer.WithInsert[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](func(ctx context.Context, value *model_struct.LocalGroupMember) error { + return g.db.InsertGroupMember(ctx, value) + }), + syncer.WithDelete[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](func(ctx context.Context, value *model_struct.LocalGroupMember) error { + return g.db.DeleteGroupMember(ctx, value.GroupID, value.UserID) + }), + syncer.WithUpdate[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](func(ctx context.Context, server, local *model_struct.LocalGroupMember) error { + return g.db.UpdateGroupMember(ctx, server) + }), + syncer.WithUUID[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](func(value *model_struct.LocalGroupMember) [2]string { + return [...]string{value.GroupID, value.UserID} + }), + syncer.WithNotice[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](func(ctx context.Context, state int, server, local *model_struct.LocalGroupMember) error { + switch state { + case syncer.Insert: + g.listener().OnGroupMemberAdded(utils.StructToJsonString(server)) + // When a user is kicked and invited to the group again, group member info will be updated. _ = common.TriggerCmdUpdateMessage(ctx, - common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, - Args: common.UpdateMessageInfo{SessionType: constant.SuperGroupChatType, UserID: server.UserID, FaceURL: server.FaceURL, - Nickname: server.Nickname, GroupID: server.GroupID}}, g.conversationCh) + common.UpdateMessageNode{ + Action: constant.UpdateMsgFaceUrlAndNickName, + Args: common.UpdateMessageInfo{ + SessionType: constant.SuperGroupChatType, UserID: server.UserID, FaceURL: server.FaceURL, + Nickname: server.Nickname, GroupID: server.GroupID, + }, + }, g.conversationCh) + case syncer.Delete: + g.listener().OnGroupMemberDeleted(utils.StructToJsonString(local)) + case syncer.Update: + g.listener().OnGroupMemberInfoChanged(utils.StructToJsonString(server)) + if server.Nickname != local.Nickname || server.FaceURL != local.FaceURL { + _ = common.TriggerCmdUpdateMessage(ctx, + common.UpdateMessageNode{ + Action: constant.UpdateMsgFaceUrlAndNickName, + Args: common.UpdateMessageInfo{ + SessionType: constant.SuperGroupChatType, UserID: server.UserID, FaceURL: server.FaceURL, + Nickname: server.Nickname, GroupID: server.GroupID, + }, + }, g.conversationCh) + } } - } - return nil - }) + return nil + }), + syncer.WithBatchInsert[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](func(ctx context.Context, values []*model_struct.LocalGroupMember) error { + return g.db.BatchInsertGroupMember(ctx, values) + }), + syncer.WithDeleteAll[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](func(ctx context.Context, groupID string) error { + return g.db.DeleteGroupAllMembers(ctx, groupID) + }), + syncer.WithBatchPageReq[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](func(entityID string) page.PageReq { + return &group.GetGroupMemberListReq{GroupID: entityID, Pagination: &sdkws.RequestPagination{ShowNumber: 100}} + }), + syncer.WithBatchPageRespConvertFunc[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](func(resp *group.GetGroupMemberListResp) []*model_struct.LocalGroupMember { + return datautil.Batch(ServerGroupMemberToLocalGroupMember, resp.Members) + }), + syncer.WithReqApiRouter[*model_struct.LocalGroupMember, group.GetGroupMemberListResp, [2]string](constant.GetGroupMemberListRouter), + ) - g.groupRequestSyncer = syncer.New(func(ctx context.Context, value *model_struct.LocalGroupRequest) error { + g.groupRequestSyncer = syncer.New[*model_struct.LocalGroupRequest, syncer.NoResp, [2]string](func(ctx context.Context, value *model_struct.LocalGroupRequest) error { return g.db.InsertGroupRequest(ctx, value) }, func(ctx context.Context, value *model_struct.LocalGroupRequest) error { return g.db.DeleteGroupRequest(ctx, value.GroupID, value.UserID) @@ -160,7 +221,7 @@ func (g *Group) initSyncer() { return nil }) - g.groupAdminRequestSyncer = syncer.New(func(ctx context.Context, value *model_struct.LocalAdminGroupRequest) error { + g.groupAdminRequestSyncer = syncer.New[*model_struct.LocalAdminGroupRequest, syncer.NoResp, [2]string](func(ctx context.Context, value *model_struct.LocalAdminGroupRequest) error { return g.db.InsertAdminGroupRequest(ctx, value) }, func(ctx context.Context, value *model_struct.LocalAdminGroupRequest) error { return g.db.DeleteAdminGroupRequest(ctx, value.GroupID, value.UserID) @@ -217,7 +278,7 @@ func (g *Group) GetGroupInfoFromLocal2Svr(ctx context.Context, groupID string) ( return nil, err } if len(svrGroup) == 0 { - return nil, sdkerrs.ErrGroupIDNotFound.Wrap("server not this group") + return nil, sdkerrs.ErrGroupIDNotFound.WrapMsg("server not this group") } return ServerGroupToLocalGroup(svrGroup[0]), nil } @@ -232,11 +293,11 @@ func (g *Group) GetGroupsInfoFromLocal2Svr(ctx context.Context, groupIDs ...stri return nil, err } var groupIDsNeedSync []string - localGroupIDs := utils2.Slice(groups, func(group *model_struct.LocalGroup) string { + localGroupIDs := datautil.Slice(groups, func(group *model_struct.LocalGroup) string { return group.GroupID }) for _, groupID := range groupIDs { - if !utils2.Contain(groupID, localGroupIDs...) { + if !datautil.Contain(groupID, localGroupIDs...) { groupIDsNeedSync = append(groupIDsNeedSync, groupID) } } @@ -281,30 +342,3 @@ func (g *Group) GetJoinedDiffusionGroupIDListFromSvr(ctx context.Context) ([]str } return groupIDs, nil } - -func (g *Group) DeleteGroupAndMemberInfo(ctx context.Context) { - memberGroupIDs, err := g.db.GetGroupMemberAllGroupIDs(ctx) - if err != nil { - log.ZError(ctx, "GetGroupMemberAllGroupIDs failed", err) - return - } - if len(memberGroupIDs) > 0 { - groups, err := g.db.GetJoinedGroupListDB(ctx) - if err != nil { - log.ZError(ctx, "GetJoinedGroupListDB failed", err) - return - } - memberGroupIDMap := make(map[string]struct{}) - for _, groupID := range memberGroupIDs { - memberGroupIDMap[groupID] = struct{}{} - } - for _, info := range groups { - delete(memberGroupIDMap, info.GroupID) - } - for groupID := range memberGroupIDMap { - if err := g.db.DeleteGroupAllMembers(ctx, groupID); err != nil { - log.ZError(ctx, "DeleteGroupAllMembers failed", err, "groupID", groupID) - } - } - } -} diff --git a/internal/group/notification.go b/internal/group/notification.go index 79f5b3baf..c691069b4 100644 --- a/internal/group/notification.go +++ b/internal/group/notification.go @@ -16,14 +16,14 @@ package group import ( "context" - "encoding/json" - "errors" "fmt" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/utils/datautil" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) func (g *Group) DoNotification(ctx context.Context, msg *sdkws.MsgData) { @@ -41,16 +41,19 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - if err := g.SyncGroups(ctx, detail.Group.GroupID); err != nil { + + if err := g.IncrSyncJoinGroup(ctx); err != nil { return err } - return g.SyncAllGroupMember(ctx, detail.Group.GroupID) + return g.IncrSyncGroupAndMember(ctx, detail.Group.GroupID) + case constant.GroupInfoSetNotification: // 1502 var detail sdkws.GroupInfoSetTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - return g.SyncGroups(ctx, detail.Group.GroupID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, + nil, nil, detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.JoinGroupApplicationNotification: // 1503 var detail sdkws.JoinGroupApplicationTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { @@ -61,6 +64,17 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { } else { return g.SyncAdminGroupApplications(ctx, detail.Group.GroupID) } + case constant.MemberQuitNotification: // 1504 + var detail sdkws.MemberQuitTips + if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { + return err + } + if detail.QuitUser.UserID == g.loginUserID { + return g.IncrSyncJoinGroup(ctx) + } else { + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, []*sdkws.GroupMemberFullInfo{detail.QuitUser}, + nil, nil, detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) + } case constant.GroupApplicationAcceptedNotification: // 1505 var detail sdkws.GroupApplicationAcceptedTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { @@ -72,7 +86,7 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { case 1: return g.SyncAdminGroupApplications(ctx, detail.Group.GroupID) default: - return fmt.Errorf("GroupApplicationAcceptedNotification ReceiverAs unknown %d", detail.ReceiverAs) + return errs.New(fmt.Sprintf("GroupApplicationAcceptedNotification ReceiverAs unknown %d", detail.ReceiverAs)).Wrap() } case constant.GroupApplicationRejectedNotification: // 1506 var detail sdkws.GroupApplicationRejectedTips @@ -85,20 +99,19 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { case 1: return g.SyncAdminGroupApplications(ctx, detail.Group.GroupID) default: - return fmt.Errorf("GroupApplicationRejectedNotification ReceiverAs unknown %d", detail.ReceiverAs) + return errs.New(fmt.Sprintf("GroupApplicationRejectedNotification ReceiverAs unknown %d", detail.ReceiverAs)).Wrap() } case constant.GroupOwnerTransferredNotification: // 1507 var detail sdkws.GroupOwnerTransferredTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - if err := g.SyncGroups(ctx, detail.Group.GroupID); err != nil { - return err - } if detail.Group == nil { - return errors.New(fmt.Sprintf("group is nil, groupID: %s", detail.Group.GroupID)) + return errs.New(fmt.Sprintf("group is nil, groupID: %s", detail.Group.GroupID)).Wrap() } - return g.SyncAllGroupMember(ctx, detail.Group.GroupID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, + []*sdkws.GroupMemberFullInfo{detail.NewGroupOwner, detail.OldGroupOwnerInfo}, nil, + detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.MemberKickedNotification: // 1508 var detail sdkws.MemberKickedTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { @@ -112,96 +125,28 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { } } if self { - members, err := g.db.GetGroupMemberListSplit(ctx, detail.Group.GroupID, 0, 0, 999999) - if err != nil { - return err - } - if err := g.db.DeleteGroupAllMembers(ctx, detail.Group.GroupID); err != nil { - return err - } - for _, member := range members { - data, err := json.Marshal(member) - if err != nil { - return err - } - g.listener().OnGroupMemberDeleted(string(data)) - } - group, err := g.db.GetGroupInfoByGroupID(ctx, detail.Group.GroupID) - if err != nil { - return err - } - group.MemberCount = 0 - data, err := json.Marshal(group) - if err != nil { - return err - } - if err := g.db.DeleteGroup(ctx, detail.Group.GroupID); err != nil { - return err - } - g.listener().OnGroupInfoChanged(string(data)) - g.listener().OnJoinedGroupDeleted(string(data)) - return nil - } else { - var userIDs []string - for _, info := range detail.KickedUserList { - userIDs = append(userIDs, info.UserID) - } - return g.SyncGroupMembers(ctx, detail.Group.GroupID, userIDs...) - } - case constant.MemberQuitNotification: // 1504 - var detail sdkws.MemberQuitTips - if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { - return err - } - if detail.QuitUser.UserID == g.loginUserID { - members, err := g.db.GetGroupMemberListSplit(ctx, detail.Group.GroupID, 0, 0, 999999) - if err != nil { - return err - } - if err := g.db.DeleteGroupAllMembers(ctx, detail.Group.GroupID); err != nil { - return err - } - for _, member := range members { - data, err := json.Marshal(member) - if err != nil { - return err - } - g.listener().OnGroupMemberDeleted(string(data)) - } - group, err := g.db.GetGroupInfoByGroupID(ctx, detail.Group.GroupID) - if err != nil { - return err - } - group.MemberCount = 0 - data, err := json.Marshal(group) - if err != nil { - return err - } - if err := g.db.DeleteGroup(ctx, detail.Group.GroupID); err != nil { - return err - } - g.listener().OnGroupInfoChanged(string(data)) - return nil + return g.IncrSyncJoinGroup(ctx) } else { - return g.SyncGroupMembers(ctx, detail.Group.GroupID, detail.QuitUser.UserID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, detail.KickedUserList, nil, + nil, detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) } case constant.MemberInvitedNotification: // 1509 var detail sdkws.MemberInvitedTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - if err := g.SyncGroups(ctx, detail.Group.GroupID); err != nil { - return err - } - var userIDs []string - for _, info := range detail.InvitedUserList { - userIDs = append(userIDs, info.UserID) - } - - if utils.IsContain(g.loginUserID, userIDs) { - return g.SyncAllGroupMember(ctx, detail.Group.GroupID) + userIDMap := datautil.SliceSetAny(detail.InvitedUserList, func(e *sdkws.GroupMemberFullInfo) string { + return e.UserID + }) + //自己也是被邀请的一员 + if _, ok := userIDMap[g.loginUserID]; ok { + if err := g.IncrSyncJoinGroup(ctx); err != nil { + return err + } + return g.IncrSyncGroupAndMember(ctx, detail.Group.GroupID) } else { - return g.SyncGroupMembers(ctx, detail.Group.GroupID, userIDs...) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, nil, + detail.InvitedUserList, detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) } case constant.MemberEnterNotification: // 1510 var detail sdkws.MemberEnterTips @@ -209,12 +154,13 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { return err } if detail.EntrantUser.UserID == g.loginUserID { - if err := g.SyncGroups(ctx, detail.Group.GroupID); err != nil { + if err := g.IncrSyncJoinGroup(ctx); err != nil { return err } - return g.SyncAllGroupMember(ctx, detail.Group.GroupID) + return g.IncrSyncGroupAndMember(ctx, detail.Group.GroupID) } else { - return g.SyncGroupMembers(ctx, detail.Group.GroupID, detail.EntrantUser.UserID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, nil, + []*sdkws.GroupMemberFullInfo{detail.EntrantUser}, detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) } case constant.GroupDismissedNotification: // 1511 var detail sdkws.GroupDismissedTips @@ -222,61 +168,78 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { return err } g.listener().OnGroupDismissed(utils.StructToJsonString(detail.Group)) - if err := g.db.DeleteGroupAllMembers(ctx, detail.Group.GroupID); err != nil { - return err - } - if err := g.db.DeleteGroup(ctx, detail.Group.GroupID); err != nil { - return err - } - return g.SyncAllGroupMember(ctx, detail.Group.GroupID) + + return g.IncrSyncJoinGroup(ctx) case constant.GroupMemberMutedNotification: // 1512 var detail sdkws.GroupMemberMutedTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - return g.SyncGroupMembers(ctx, detail.Group.GroupID, detail.MutedUser.UserID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, + []*sdkws.GroupMemberFullInfo{detail.MutedUser}, nil, nil, + detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.GroupMemberCancelMutedNotification: // 1513 var detail sdkws.GroupMemberCancelMutedTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - return g.SyncGroupMembers(ctx, detail.Group.GroupID, detail.MutedUser.UserID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, + []*sdkws.GroupMemberFullInfo{detail.MutedUser}, nil, nil, + detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.GroupMutedNotification: // 1514 - return g.SyncGroups(ctx, msg.GroupID) + var detail sdkws.GroupMutedTips + if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { + return err + } + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, nil, + nil, detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.GroupCancelMutedNotification: // 1515 - return g.SyncGroups(ctx, msg.GroupID) + var detail sdkws.GroupCancelMutedTips + if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { + return err + } + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, nil, + nil, detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.GroupMemberInfoSetNotification: // 1516 var detail sdkws.GroupMemberInfoSetTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - return g.SyncGroupMembers(ctx, detail.Group.GroupID, detail.ChangedUser.UserID) //detail.ChangedUser.UserID + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, + []*sdkws.GroupMemberFullInfo{detail.ChangedUser}, nil, nil, + detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.GroupMemberSetToAdminNotification: // 1517 var detail sdkws.GroupMemberInfoSetTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - return g.SyncGroupMembers(ctx, detail.Group.GroupID, detail.ChangedUser.UserID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, + []*sdkws.GroupMemberFullInfo{detail.ChangedUser}, nil, nil, + detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.GroupMemberSetToOrdinaryUserNotification: // 1518 var detail sdkws.GroupMemberInfoSetTips if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - return g.SyncGroupMembers(ctx, detail.Group.GroupID, detail.ChangedUser.UserID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, + []*sdkws.GroupMemberFullInfo{detail.ChangedUser}, nil, nil, + detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.GroupInfoSetAnnouncementNotification: // 1519 var detail sdkws.GroupInfoSetAnnouncementTips // if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - return g.SyncGroups(ctx, detail.Group.GroupID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, nil, + nil, detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) case constant.GroupInfoSetNameNotification: // 1520 var detail sdkws.GroupInfoSetNameTips // if err := utils.UnmarshalNotificationElem(msg.Content, &detail); err != nil { return err } - return g.SyncGroups(ctx, detail.Group.GroupID) + return g.onlineSyncGroupAndMember(ctx, detail.Group.GroupID, nil, + nil, nil, detail.Group, detail.GroupMemberVersion, detail.GroupMemberVersionID) default: - return fmt.Errorf("unknown tips type: %d", msg.ContentType) + return errs.New("unknown tips type", "contentType", msg.ContentType).Wrap() } } diff --git a/internal/group/sdk.go b/internal/group/sdk.go index df3d0c538..e4d32554c 100644 --- a/internal/group/sdk.go +++ b/internal/group/sdk.go @@ -16,52 +16,25 @@ package group import ( "context" + "github.com/openimsdk/tools/errs" + "gorm.io/gorm" "time" + "github.com/openimsdk/tools/utils/datautil" + + "github.com/openimsdk/openim-sdk-core/v3/pkg/datafetcher" + "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" - "github.com/OpenIMSDK/tools/log" - - "github.com/OpenIMSDK/protocol/group" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/protocol/wrapperspb" - "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/protocol/group" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/protocol/wrapperspb" ) -// // deprecated use CreateGroup -// funcation (g *Group) CreateGroup(ctx context.Context, groupBaseInfo sdk_params_callback.CreateGroupBaseInfoParam, memberList sdk_params_callback.CreateGroupMemberRoleParam) (*sdkws.GroupInfo, error) { -// req := &group.CreateGroupReq{ -// GroupInfo: &sdkws.GroupInfo{ -// GroupName: groupBaseInfo.GroupName, -// Notification: groupBaseInfo.Notification, -// Introduction: groupBaseInfo.Introduction, -// FaceURL: groupBaseInfo.FaceURL, -// Ex: groupBaseInfo.Ex, -// GroupType: groupBaseInfo.GroupType, -// }, -// } -// if groupBaseInfo.NeedVerification != nil { -// req.GroupInfo.NeedVerification = *groupBaseInfo.NeedVerification -// } -// for _, info := range memberList { -// switch info.RoleLevel { -// case constant.GroupOrdinaryUsers: -// req.InitMembers = append(req.InitMembers, info.UserID) -// case constant.GroupOwner: -// req.OwnerUserID = info.UserID -// case constant.GroupAdmin: -// req.AdminUserIDs = append(req.AdminUserIDs, info.UserID) -// default: -// return nil, sdkerrs.ErrArgs.Wrap(fmt.Sprintf("CreateGroup: invalid role level %d", info.RoleLevel)) -// } -// } -// return g.CreateGroup(ctx, req) -// } - func (g *Group) CreateGroup(ctx context.Context, req *group.CreateGroupReq) (*sdkws.GroupInfo, error) { if req.OwnerUserID == "" { req.OwnerUserID = g.loginUserID @@ -74,10 +47,10 @@ func (g *Group) CreateGroup(ctx context.Context, req *group.CreateGroupReq) (*sd if err != nil { return nil, err } - if err := g.SyncGroups(ctx, resp.GroupInfo.GroupID); err != nil { + if err := g.IncrSyncJoinGroup(ctx); err != nil { return nil, err } - if err := g.SyncAllGroupMember(ctx, resp.GroupInfo.GroupID); err != nil { + if err := g.IncrSyncGroupAndMember(ctx, resp.GroupInfo.GroupID); err != nil { return nil, err } return resp.GroupInfo, nil @@ -90,12 +63,6 @@ func (g *Group) JoinGroup(ctx context.Context, groupID, reqMsg string, joinSourc if err := g.SyncSelfGroupApplications(ctx, groupID); err != nil { return err } - // if err := g.SyncJoinedGroup(ctx); err != nil { - // return err - // } - // if err := g.SyncGroupMember(ctx, groupID); err != nil { - // return err - // } return nil } @@ -103,15 +70,6 @@ func (g *Group) QuitGroup(ctx context.Context, groupID string) error { if err := util.ApiPost(ctx, constant.QuitGroupRouter, &group.QuitGroupReq{GroupID: groupID}, nil); err != nil { return err } - if err := g.db.DeleteGroupAllMembers(ctx, groupID); err != nil { - return err - } - if err := g.deleteGroup(ctx, groupID); err != nil { - return err - } - // if err := g.SyncGroupMember(ctx, groupID); err != nil { - // return err - // } return nil } @@ -119,15 +77,21 @@ func (g *Group) DismissGroup(ctx context.Context, groupID string) error { if err := util.ApiPost(ctx, constant.DismissGroupRouter, &group.DismissGroupReq{GroupID: groupID}, nil); err != nil { return err } - if err := g.deleteGroup(ctx, groupID); err != nil { - return err - } - if err := g.db.DeleteGroupAllMembers(ctx, groupID); err != nil { - return err - } return nil } +func (g *Group) SetGroupApplyMemberFriend(ctx context.Context, groupID string, rule int32) error { + return g.SetGroupInfo(ctx, &sdkws.GroupInfoForSet{GroupID: groupID, ApplyMemberFriend: wrapperspb.Int32(rule)}) +} + +func (g *Group) SetGroupLookMemberInfo(ctx context.Context, groupID string, rule int32) error { + return g.SetGroupInfo(ctx, &sdkws.GroupInfoForSet{GroupID: groupID, LookMemberInfo: wrapperspb.Int32(rule)}) +} + +func (g *Group) SetGroupVerification(ctx context.Context, groupID string, verification int32) error { + return g.SetGroupInfo(ctx, &sdkws.GroupInfoForSet{GroupID: groupID, NeedVerification: wrapperspb.Int32(verification)}) +} + func (g *Group) ChangeGroupMute(ctx context.Context, groupID string, isMute bool) (err error) { if isMute { err = util.ApiPost(ctx, constant.MuteGroupRouter, &group.MuteGroupReq{GroupID: groupID}, nil) @@ -137,7 +101,7 @@ func (g *Group) ChangeGroupMute(ctx context.Context, groupID string, isMute bool if err != nil { return err } - if err := g.SyncGroups(ctx, groupID); err != nil { + if err := g.IncrSyncGroupAndMember(ctx, groupID); err != nil { return err } return nil @@ -152,65 +116,140 @@ func (g *Group) ChangeGroupMemberMute(ctx context.Context, groupID, userID strin if err != nil { return err } - if err := g.SyncGroups(ctx, groupID); err != nil { + return nil +} + +func (g *Group) TransferGroupOwner(ctx context.Context, groupID, newOwnerUserID string) error { + if err := util.ApiPost(ctx, constant.TransferGroupRouter, &group.TransferGroupOwnerReq{GroupID: groupID, OldOwnerUserID: g.loginUserID, NewOwnerUserID: newOwnerUserID}, nil); err != nil { return err } - if err := g.SyncGroupMembers(ctx, groupID, userID); err != nil { + if err := g.IncrSyncGroupAndMember(ctx, groupID); err != nil { return err } return nil } -func (g *Group) SetGroupMemberRoleLevel(ctx context.Context, groupID, userID string, roleLevel int) error { - return g.SetGroupMemberInfo(ctx, &group.SetGroupMemberInfo{GroupID: groupID, UserID: userID, RoleLevel: wrapperspb.Int32(int32(roleLevel))}) +func (g *Group) KickGroupMember(ctx context.Context, groupID string, reason string, userIDList []string) error { + if err := util.ApiPost(ctx, constant.KickGroupMemberRouter, &group.KickGroupMemberReq{GroupID: groupID, KickedUserIDs: userIDList, Reason: reason}, nil); err != nil { + return err + } + return g.IncrSyncGroupAndMember(ctx, groupID) } -func (g *Group) SetGroupMemberNickname(ctx context.Context, groupID, userID string, groupMemberNickname string) error { - return g.SetGroupMemberInfo(ctx, &group.SetGroupMemberInfo{GroupID: groupID, UserID: userID, Nickname: wrapperspb.String(groupMemberNickname)}) +func (g *Group) SetGroupInfo(ctx context.Context, groupInfo *sdkws.GroupInfoForSet) error { + if err := util.ApiPost(ctx, constant.SetGroupInfoRouter, &group.SetGroupInfoReq{GroupInfoForSet: groupInfo}, nil); err != nil { + return err + } + return g.IncrSyncJoinGroup(ctx) } func (g *Group) SetGroupMemberInfo(ctx context.Context, groupMemberInfo *group.SetGroupMemberInfo) error { if err := util.ApiPost(ctx, constant.SetGroupMemberInfoRouter, &group.SetGroupMemberInfoReq{Members: []*group.SetGroupMemberInfo{groupMemberInfo}}, nil); err != nil { return err } - return g.SyncGroupMembers(ctx, groupMemberInfo.GroupID, groupMemberInfo.UserID) + return g.IncrSyncGroupAndMember(ctx, groupMemberInfo.GroupID) +} + +func (g *Group) SetGroupMemberRoleLevel(ctx context.Context, groupID, userID string, roleLevel int) error { + return g.SetGroupMemberInfo(ctx, &group.SetGroupMemberInfo{GroupID: groupID, UserID: userID, RoleLevel: wrapperspb.Int32(int32(roleLevel))}) +} + +func (g *Group) SetGroupMemberNickname(ctx context.Context, groupID, userID string, groupMemberNickname string) error { + return g.SetGroupMemberInfo(ctx, &group.SetGroupMemberInfo{GroupID: groupID, UserID: userID, Nickname: wrapperspb.String(groupMemberNickname)}) } func (g *Group) GetJoinedGroupList(ctx context.Context) ([]*model_struct.LocalGroup, error) { return g.db.GetJoinedGroupListDB(ctx) } +func (g *Group) GetJoinedGroupListPage(ctx context.Context, offset, count int32) ([]*model_struct.LocalGroup, error) { + dataFetcher := datafetcher.NewDataFetcher( + g.db, + g.groupTableName(), + g.loginUserID, + func(localGroup *model_struct.LocalGroup) string { + return localGroup.GroupID + }, + func(ctx context.Context, values []*model_struct.LocalGroup) error { + return g.db.BatchInsertGroup(ctx, values) + }, + func(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) { + return g.db.GetGroups(ctx, groupIDs) + }, + func(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) { + serverGroupInfo, err := g.getGroupsInfoFromSvr(ctx, groupIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerGroupToLocalGroup, serverGroupInfo), nil + }, + ) + return dataFetcher.FetchWithPagination(ctx, int(offset), int(count)) +} + func (g *Group) GetSpecifiedGroupsInfo(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) { - groupList, err := g.db.GetJoinedGroupListDB(ctx) + dataFetcher := datafetcher.NewDataFetcher( + g.db, + g.groupTableName(), + g.loginUserID, + func(localGroup *model_struct.LocalGroup) string { + return localGroup.GroupID + }, + func(ctx context.Context, values []*model_struct.LocalGroup) error { + return g.db.BatchInsertGroup(ctx, values) + }, + func(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) { + return g.db.GetGroups(ctx, groupIDs) + }, + func(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) { + serverGroupInfo, err := g.getGroupsInfoFromSvr(ctx, groupIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerGroupToLocalGroup, serverGroupInfo), nil + }, + ) + return dataFetcher.FetchMissingAndCombineLocal(ctx, groupIDs) +} + +func (g *Group) GetJoinedGroupListPageV2(ctx context.Context, offset, count int32) (*GetGroupListV2Response, error) { + dataFetcher := datafetcher.NewDataFetcher( + g.db, + g.groupTableName(), + g.loginUserID, + func(localGroup *model_struct.LocalGroup) string { + return localGroup.GroupID + }, + func(ctx context.Context, values []*model_struct.LocalGroup) error { + return g.db.BatchInsertGroup(ctx, values) + }, + func(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) { + return g.db.GetGroups(ctx, groupIDs) + }, + func(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) { + serverGroupInfo, err := g.getGroupsInfoFromSvr(ctx, groupIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerGroupToLocalGroup, serverGroupInfo), nil + }, + ) + + groupsList, isEnd, err := dataFetcher.FetchWithPaginationV2(ctx, int(offset), int(count)) if err != nil { return nil, err } - groupIDMap := utils.SliceSet(groupIDs) - res := make([]*model_struct.LocalGroup, 0, len(groupIDs)) - for i, v := range groupList { - if _, ok := groupIDMap[v.GroupID]; ok { - delete(groupIDMap, v.GroupID) - res = append(res, groupList[i]) - } - } - if len(groupIDMap) > 0 { - groups, err := util.CallApi[group.GetGroupsInfoResp](ctx, constant.GetGroupsInfoRouter, &group.GetGroupsInfoReq{GroupIDs: utils.Keys(groupIDMap)}) - if err != nil { - log.ZError(ctx, "Call GetGroupsInfoRouter", err) - } - if groups != nil && len(groups.GroupInfos) > 0 { - for i := range groups.GroupInfos { - groups.GroupInfos[i].MemberCount = 0 - } - res = append(res, util.Batch(ServerGroupToLocalGroup, groups.GroupInfos)...) - } + + resp := &GetGroupListV2Response{ + GroupsList: groupsList, + IsEnd: isEnd, } - return res, nil + return resp, nil } func (g *Group) SearchGroups(ctx context.Context, param sdk_params_callback.SearchGroupsParam) ([]*model_struct.LocalGroup, error) { if len(param.KeywordList) == 0 || (!param.IsSearchGroupName && !param.IsSearchGroupID) { - return nil, sdkerrs.ErrArgs.Wrap("keyword is null or search field all false") + return nil, sdkerrs.ErrArgs.WrapMsg("keyword is null or search field all false") } groups, err := g.db.GetAllGroupInfoByGroupIDOrGroupName(ctx, param.KeywordList[0], param.IsSearchGroupID, param.IsSearchGroupName) // todo param.KeywordList[0] if err != nil { @@ -231,89 +270,238 @@ func (g *Group) SearchGroups(ctx context.Context, param sdk_params_callback.Sear // }) // } -func (g *Group) SetGroupVerification(ctx context.Context, groupID string, verification int32) error { - return g.SetGroupInfo(ctx, &sdkws.GroupInfoForSet{GroupID: groupID, NeedVerification: wrapperspb.Int32(verification)}) -} - -func (g *Group) SetGroupLookMemberInfo(ctx context.Context, groupID string, rule int32) error { - return g.SetGroupInfo(ctx, &sdkws.GroupInfoForSet{GroupID: groupID, LookMemberInfo: wrapperspb.Int32(rule)}) -} - -func (g *Group) SetGroupApplyMemberFriend(ctx context.Context, groupID string, rule int32) error { - return g.SetGroupInfo(ctx, &sdkws.GroupInfoForSet{GroupID: groupID, ApplyMemberFriend: wrapperspb.Int32(rule)}) +func (g *Group) GetGroupMemberOwnerAndAdmin(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) { + return g.db.GetGroupMemberOwnerAndAdminDB(ctx, groupID) } -func (g *Group) SetGroupInfo(ctx context.Context, groupInfo *sdkws.GroupInfoForSet) error { - if err := util.ApiPost(ctx, constant.SetGroupInfoRouter, &group.SetGroupInfoReq{GroupInfoForSet: groupInfo}, nil); err != nil { - return err +func (g *Group) GetGroupMemberListByJoinTimeFilter(ctx context.Context, groupID string, offset, count int32, joinTimeBegin, joinTimeEnd int64, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + if joinTimeEnd == 0 { + joinTimeEnd = time.Now().UnixMilli() } - return g.SyncGroups(ctx, groupInfo.GroupID) -} -func (g *Group) GetGroupMemberList(ctx context.Context, groupID string, filter, offset, count int32) ([]*model_struct.LocalGroupMember, error) { - return g.db.GetGroupMemberListSplit(ctx, groupID, filter, int(offset), int(count)) -} + dataFetcher := datafetcher.NewDataFetcher( + g.db, + g.groupAndMemberVersionTableName(), + groupID, + func(localGroupMember *model_struct.LocalGroupMember) string { + return localGroupMember.UserID + }, + func(ctx context.Context, values []*model_struct.LocalGroupMember) error { + return g.db.BatchInsertGroupMember(ctx, values) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + return g.db.GetGroupMemberListSplitByJoinTimeFilter(ctx, groupID, int(offset), int(count), joinTimeBegin, joinTimeEnd, userIDs) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + serverGroupMember, err := g.GetDesignatedGroupMembers(ctx, groupID, userIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerGroupMemberToLocalGroupMember, serverGroupMember), nil + }, + ) -func (g *Group) GetGroupMemberOwnerAndAdmin(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) { - return g.db.GetGroupMemberOwnerAndAdminDB(ctx, groupID) + return dataFetcher.FetchWithPagination(ctx, int(offset), int(count)) } -func (g *Group) GetGroupMemberListByJoinTimeFilter(ctx context.Context, groupID string, offset, count int32, joinTimeBegin, joinTimeEnd int64, userIDs []string) ([]*model_struct.LocalGroupMember, error) { +func (g *Group) GetGroupMemberListByJoinTimeFilterV2(ctx context.Context, groupID string, offset, count int32, joinTimeBegin, joinTimeEnd int64, userIDs []string) (*GetGroupMemberListV2Response, error) { if joinTimeEnd == 0 { joinTimeEnd = time.Now().UnixMilli() } - return g.db.GetGroupMemberListSplitByJoinTimeFilter(ctx, groupID, int(offset), int(count), joinTimeBegin, joinTimeEnd, userIDs) + + dataFetcher := datafetcher.NewDataFetcher( + g.db, + g.groupAndMemberVersionTableName(), + groupID, + func(localGroupMember *model_struct.LocalGroupMember) string { + return localGroupMember.UserID + }, + func(ctx context.Context, values []*model_struct.LocalGroupMember) error { + return g.db.BatchInsertGroupMember(ctx, values) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + return g.db.GetGroupMemberListSplitByJoinTimeFilter(ctx, groupID, int(offset), int(count), joinTimeBegin, joinTimeEnd, userIDs) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + serverGroupMember, err := g.GetDesignatedGroupMembers(ctx, groupID, userIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerGroupMemberToLocalGroupMember, serverGroupMember), nil + }, + ) + + groupMembersList, isEnd, err := dataFetcher.FetchWithPaginationV2(ctx, int(offset), int(count)) + if err != nil { + return nil, err + } + resp := &GetGroupMemberListV2Response{ + GroupMembersList: groupMembersList, + IsEnd: isEnd, + } + return resp, nil } func (g *Group) GetSpecifiedGroupMembersInfo(ctx context.Context, groupID string, userIDList []string) ([]*model_struct.LocalGroupMember, error) { - return g.db.GetGroupSomeMemberInfo(ctx, groupID, userIDList) + lvs, err := g.db.GetVersionSync(ctx, g.groupTableName(), g.loginUserID) + if err != nil { + return nil, err + } + if datautil.Contain(groupID, lvs.UIDList...) { + + _, err := g.db.GetVersionSync(ctx, g.groupAndMemberVersionTableName(), groupID) + if err != nil { + if errs.Unwrap(err) != gorm.ErrRecordNotFound { + return nil, err + } + err := g.IncrSyncGroupAndMember(ctx, groupID) + if err != nil { + return nil, err + } + } + } else { // If the user is no longer in the group, return nil immediately + return nil, nil + } + dataFetcher := datafetcher.NewDataFetcher( + g.db, + g.groupAndMemberVersionTableName(), + groupID, + func(localGroupMember *model_struct.LocalGroupMember) string { + return localGroupMember.UserID + }, + func(ctx context.Context, values []*model_struct.LocalGroupMember) error { + return g.db.BatchInsertGroupMember(ctx, values) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + return g.db.GetGroupSomeMemberInfo(ctx, groupID, userIDList) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + serverGroupMember, err := g.GetDesignatedGroupMembers(ctx, groupID, userIDs) + if err != nil { + return nil, err + } + if len(serverGroupMember) == 0 { + return nil, nil + } + return datautil.Batch(ServerGroupMemberToLocalGroupMember, serverGroupMember), nil + }, + ) + return dataFetcher.FetchMissingAndFillLocal(ctx, userIDList) } -func (g *Group) KickGroupMember(ctx context.Context, groupID string, reason string, userIDList []string) error { - if err := util.ApiPost(ctx, constant.KickGroupMemberRouter, &group.KickGroupMemberReq{GroupID: groupID, KickedUserIDs: userIDList, Reason: reason}, nil); err != nil { - return err +func (g *Group) GetGroupMemberList(ctx context.Context, groupID string, filter, offset, count int32) ([]*model_struct.LocalGroupMember, error) { + lvs, err := g.db.GetVersionSync(ctx, g.groupTableName(), g.loginUserID) + if err != nil { + return nil, err } - return g.SyncGroupMembers(ctx, groupID, userIDList...) + if datautil.Contain(groupID, lvs.UIDList...) { + + _, err := g.db.GetVersionSync(ctx, g.groupAndMemberVersionTableName(), groupID) + if err != nil { + if errs.Unwrap(err) != gorm.ErrRecordNotFound { + return nil, err + } + err := g.IncrSyncGroupAndMember(ctx, groupID) + if err != nil { + return nil, err + } + } + } else { // If the user is no longer in the group, return nil immediately + return nil, nil + } + + dataFetcher := datafetcher.NewDataFetcher( + g.db, + g.groupAndMemberVersionTableName(), + groupID, + func(localGroupMember *model_struct.LocalGroupMember) string { + return localGroupMember.UserID + }, + func(ctx context.Context, values []*model_struct.LocalGroupMember) error { + return g.db.BatchInsertGroupMember(ctx, values) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + return g.db.GetGroupMemberListByUserIDs(ctx, groupID, filter, userIDs) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + serverGroupMember, err := g.GetDesignatedGroupMembers(ctx, groupID, userIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerGroupMemberToLocalGroupMember, serverGroupMember), nil + }, + ) + return dataFetcher.FetchWithPagination(ctx, int(offset), int(count)) } -func (g *Group) TransferGroupOwner(ctx context.Context, groupID, newOwnerUserID string) error { - oldOwner, err := g.db.GetGroupMemberOwner(ctx, groupID) +func (g *Group) GetGroupMemberListV2(ctx context.Context, groupID string, filter, offset, count int32) (*GetGroupMemberListV2Response, error) { + dataFetcher := datafetcher.NewDataFetcher( + g.db, + g.groupAndMemberVersionTableName(), + groupID, + func(localGroupMember *model_struct.LocalGroupMember) string { + return localGroupMember.UserID + }, + func(ctx context.Context, values []*model_struct.LocalGroupMember) error { + return g.db.BatchInsertGroupMember(ctx, values) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + return g.db.GetGroupMemberListByUserIDs(ctx, groupID, filter, userIDs) + }, + func(ctx context.Context, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + serverGroupMember, err := g.GetDesignatedGroupMembers(ctx, groupID, userIDs) + if err != nil { + return nil, err + } + return datautil.Batch(ServerGroupMemberToLocalGroupMember, serverGroupMember), nil + }, + ) + groupMembersList, isEnd, err := dataFetcher.FetchWithPaginationV2(ctx, int(offset), int(count)) if err != nil { - return err + return nil, err } - if err := util.ApiPost(ctx, constant.TransferGroupRouter, &group.TransferGroupOwnerReq{GroupID: groupID, OldOwnerUserID: g.loginUserID, NewOwnerUserID: newOwnerUserID}, nil); err != nil { - return err + resp := &GetGroupMemberListV2Response{ + GroupMembersList: groupMembersList, + IsEnd: isEnd, } - if err := g.SyncGroups(ctx, groupID); err != nil { - return err + + return resp, nil +} + +func (g *Group) GetGroupApplicationListAsRecipient(ctx context.Context) ([]*model_struct.LocalAdminGroupRequest, error) { + return g.db.GetAdminGroupApplication(ctx) +} + +func (g *Group) GetGroupApplicationListAsApplicant(ctx context.Context) ([]*model_struct.LocalGroupRequest, error) { + return g.db.GetSendGroupApplication(ctx) +} + +func (g *Group) SearchGroupMembers(ctx context.Context, searchParam *sdk_params_callback.SearchGroupMembersParam) ([]*model_struct.LocalGroupMember, error) { + return g.db.SearchGroupMembersDB(ctx, searchParam.KeywordList[0], searchParam.GroupID, searchParam.IsSearchMemberNickname, searchParam.IsSearchUserID, searchParam.Offset, searchParam.Count) +} + +func (g *Group) IsJoinGroup(ctx context.Context, groupID string) (bool, error) { + groupIDs, err := g.db.GetVersionSync(ctx, g.groupTableName(), g.loginUserID) + if err != nil { + return false, err } - if err := g.SyncGroupMembers(ctx, groupID, newOwnerUserID, oldOwner.UserID); err != nil { - return err + if datautil.Contain(groupID, groupIDs.UIDList...) { + return true, nil } - return nil + return false, nil } func (g *Group) InviteUserToGroup(ctx context.Context, groupID, reason string, userIDList []string) error { if err := util.ApiPost(ctx, constant.InviteUserToGroupRouter, &group.InviteUserToGroupReq{GroupID: groupID, Reason: reason, InvitedUserIDs: userIDList}, nil); err != nil { return err } - if err := g.SyncGroups(ctx, groupID); err != nil { - return err - } - if err := g.SyncGroupMembers(ctx, groupID, userIDList...); err != nil { + + if err := g.IncrSyncGroupAndMember(ctx, groupID); err != nil { return err } return nil } -func (g *Group) GetGroupApplicationListAsRecipient(ctx context.Context) ([]*model_struct.LocalAdminGroupRequest, error) { - return g.db.GetAdminGroupApplication(ctx) -} - -func (g *Group) GetGroupApplicationListAsApplicant(ctx context.Context) ([]*model_struct.LocalGroupRequest, error) { - return g.db.GetSendGroupApplication(ctx) -} - func (g *Group) AcceptGroupApplication(ctx context.Context, groupID, fromUserID, handleMsg string) error { return g.HandlerGroupApplication(ctx, &group.GroupApplicationResponseReq{GroupID: groupID, FromUserID: fromUserID, HandledMsg: handleMsg, HandleResult: constant.GroupResponseAgree}) } @@ -330,19 +518,38 @@ func (g *Group) HandlerGroupApplication(ctx context.Context, req *group.GroupApp return nil } -func (g *Group) SearchGroupMembers(ctx context.Context, searchParam *sdk_params_callback.SearchGroupMembersParam) ([]*model_struct.LocalGroupMember, error) { - return g.db.SearchGroupMembersDB(ctx, searchParam.KeywordList[0], searchParam.GroupID, searchParam.IsSearchMemberNickname, searchParam.IsSearchUserID, searchParam.Offset, searchParam.Count) -} - -func (g *Group) IsJoinGroup(ctx context.Context, groupID string) (bool, error) { - groupList, err := g.db.GetJoinedGroupListDB(ctx) - if err != nil { - return false, err - } - for _, localGroup := range groupList { - if localGroup.GroupID == groupID { - return true, nil - } +//func (g *Group) SearchGroupMembersV2(ctx context.Context, req *group.SearchGroupMemberReq) ([]*model_struct.LocalGroupMember, error) { +// if err := req.Check(); err != nil { +// return nil, err +// } +// info, err := g.db.GetGroupInfoByGroupID(ctx, req.GroupID) +// if err != nil { +// return nil, err +// } +// if info.MemberCount <= pconstant.MaxSyncPullNumber { +// return g.db.SearchGroupMembersDB(ctx, req.Keyword, req.GroupID, true, false, +// int((req.Pagination.PageNumber-1)*req.Pagination.ShowNumber), int(req.Pagination.ShowNumber)) +// } +// resp, err := util.CallApi[group.SearchGroupMemberResp](ctx, constant.SearchGroupMember, req) +// if err != nil { +// return nil, err +// } +// return datautil.Slice(resp.Members, g.pbGroupMemberToLocal), nil +//} + +func (g *Group) pbGroupMemberToLocal(pb *sdkws.GroupMemberFullInfo) *model_struct.LocalGroupMember { + return &model_struct.LocalGroupMember{ + GroupID: pb.GroupID, + UserID: pb.UserID, + Nickname: pb.Nickname, + FaceURL: pb.FaceURL, + RoleLevel: pb.RoleLevel, + JoinTime: pb.JoinTime, + JoinSource: pb.JoinSource, + InviterUserID: pb.InviterUserID, + MuteEndTime: pb.MuteEndTime, + OperatorUserID: pb.OperatorUserID, + Ex: pb.Ex, + // AttachedInfo: pb.AttachedInfo, } - return false, nil } diff --git a/internal/group/sync.go b/internal/group/sync.go index afeac3161..5ca7513f2 100644 --- a/internal/group/sync.go +++ b/internal/group/sync.go @@ -20,22 +20,22 @@ import ( "encoding/binary" "encoding/json" "errors" - "github.com/OpenIMSDK/protocol/group" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" - utils2 "github.com/OpenIMSDK/tools/utils" + "fmt" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" - "sync" + "github.com/openimsdk/protocol/group" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/utils/datautil" + "time" ) func (g *Group) getGroupHash(members []*model_struct.LocalGroupMember) uint64 { - userIDs := utils2.Slice(members, func(member *model_struct.LocalGroupMember) string { + userIDs := datautil.Slice(members, func(member *model_struct.LocalGroupMember) string { return member.UserID }) - utils2.Sort(userIDs, true) + datautil.Sort(userIDs, true) memberMap := make(map[string]*sdkws.GroupMemberFullInfo) for _, member := range members { memberMap[member.UserID] = &sdkws.GroupMemberFullInfo{ @@ -83,9 +83,13 @@ func (g *Group) SyncAllGroupMember(ctx context.Context, groupID string) error { return g.syncGroupMembers(ctx, groupID, members, localData) } +func (g *Group) SyncAllGroupMember2(ctx context.Context, groupID string) error { + return g.IncrSyncGroupAndMember(ctx, groupID) +} + func (g *Group) syncGroupMembers(ctx context.Context, groupID string, members []*sdkws.GroupMemberFullInfo, localData []*model_struct.LocalGroupMember) error { log.ZInfo(ctx, "SyncGroupMember Info", "groupID", groupID, "members", len(members), "localData", len(localData)) - err := g.groupMemberSyncer.Sync(ctx, util.Batch(ServerGroupMemberToLocalGroupMember, members), localData, nil) + err := g.groupMemberSyncer.Sync(ctx, datautil.Batch(ServerGroupMemberToLocalGroupMember, members), localData, nil) if err != nil { return err } @@ -127,66 +131,90 @@ func (g *Group) syncGroupMembers(ctx context.Context, groupID string, members [] } func (g *Group) SyncGroupMembers(ctx context.Context, groupID string, userIDs ...string) error { - members, err := g.GetDesignatedGroupMembers(ctx, groupID, userIDs) - if err != nil { - return err - } - localData, err := g.db.GetGroupSomeMemberInfo(ctx, groupID, userIDs) - if err != nil { - return err - } - return g.syncGroupMembers(ctx, groupID, members, localData) + return g.IncrSyncGroupAndMember(ctx, groupID) + //members, err := g.GetDesignatedGroupMembers(ctx, groupID, userIDs) + //if err != nil { + // return err + //} + //localData, err := g.db.GetGroupSomeMemberInfo(ctx, groupID, userIDs) + //if err != nil { + // return err + //} + //return g.syncGroupMembers(ctx, groupID, members, localData) } func (g *Group) SyncGroups(ctx context.Context, groupIDs ...string) error { - groups, err := g.getGroupsInfoFromSvr(ctx, groupIDs) - if err != nil { - return err - } - localData, err := g.db.GetGroups(ctx, groupIDs) - if err != nil { - return err - } - if err := g.groupSyncer.Sync(ctx, util.Batch(ServerGroupToLocalGroup, groups), localData, nil); err != nil { - return err - } - return nil + return g.IncrSyncJoinGroup(ctx) + //groups, err := g.getGroupsInfoFromSvr(ctx, groupIDs) + //if err != nil { + // return err + //} + //localData, err := g.db.GetGroups(ctx, groupIDs) + //if err != nil { + // return err + //} + //if err := g.groupSyncer.Sync(ctx, util.Batch(ServerGroupToLocalGroup, groups), localData, nil); err != nil { + // return err + //} + //return nil } func (g *Group) deleteGroup(ctx context.Context, groupID string) error { - groupInfo, err := g.db.GetGroupInfoByGroupID(ctx, groupID) - if err != nil { - return err - } - if err := g.db.DeleteGroup(ctx, groupID); err != nil { - return err - } - g.listener().OnJoinedGroupDeleted(utils.StructToJsonString(groupInfo)) - return nil + return g.IncrSyncJoinGroup(ctx) + //groupInfo, err := g.db.GetGroupInfoByGroupID(ctx, groupID) + //if err != nil { + // return err + //} + //if err := g.db.DeleteGroup(ctx, groupID); err != nil { + // return err + //} + //g.listener().OnJoinedGroupDeleted(utils.StructToJsonString(groupInfo)) + //return nil } +// func (g *Group) SyncAllJoinedGroupsAndMembers(ctx context.Context) error { +// t := time.Now() +// defer func(start time.Time) { +// +// elapsed := time.Since(start).Milliseconds() +// log.ZDebug(ctx, "SyncAllJoinedGroupsAndMembers fn call end", "cost time", fmt.Sprintf("%d ms", elapsed)) +// +// }(t) +// _, err := g.syncAllJoinedGroups(ctx) +// if err != nil { +// return err +// } +// groups, err := g.db.GetJoinedGroupListDB(ctx) +// if err != nil { +// return err +// } +// var wg sync.WaitGroup +// for _, group := range groups { +// wg.Add(1) +// go func(groupID string) { +// defer wg.Done() +// if err := g.SyncAllGroupMember(ctx, groupID); err != nil { +// log.ZError(ctx, "SyncGroupMember failed", err) +// } +// }(group.GroupID) +// } +// wg.Wait() +// return nil +// } func (g *Group) SyncAllJoinedGroupsAndMembers(ctx context.Context) error { - _, err := g.syncAllJoinedGroups(ctx) - if err != nil { - return err - } - groups, err := g.db.GetJoinedGroupListDB(ctx) - if err != nil { + t := time.Now() + defer func(start time.Time) { + + elapsed := time.Since(start).Milliseconds() + log.ZDebug(ctx, "SyncAllJoinedGroupsAndMembers fn call end", "cost time", fmt.Sprintf("%d ms", elapsed)) + + }(t) + if err := g.IncrSyncJoinGroup(ctx); err != nil { return err } - var wg sync.WaitGroup - for _, group := range groups { - wg.Add(1) - go func(groupID string) { - defer wg.Done() - if err := g.SyncAllGroupMember(ctx, groupID); err != nil { - log.ZError(ctx, "SyncGroupMember failed", err) - } - }(group.GroupID) - } - wg.Wait() - return nil + return g.IncrSyncJoinGroupMember(ctx) } + func (g *Group) syncAllJoinedGroups(ctx context.Context) ([]*sdkws.GroupInfo, error) { groups, err := g.GetServerJoinGroup(ctx) if err != nil { @@ -196,7 +224,7 @@ func (g *Group) syncAllJoinedGroups(ctx context.Context) ([]*sdkws.GroupInfo, er if err != nil { return nil, err } - if err := g.groupSyncer.Sync(ctx, util.Batch(ServerGroupToLocalGroup, groups), localData, nil); err != nil { + if err := g.groupSyncer.Sync(ctx, datautil.Batch(ServerGroupToLocalGroup, groups), localData, nil); err != nil { return nil, err } return groups, nil @@ -211,7 +239,23 @@ func (g *Group) SyncAllSelfGroupApplication(ctx context.Context) error { if err != nil { return err } - if err := g.groupRequestSyncer.Sync(ctx, util.Batch(ServerGroupRequestToLocalGroupRequest, list), localData, nil); err != nil { + if err := g.groupRequestSyncer.Sync(ctx, datautil.Batch(ServerGroupRequestToLocalGroupRequest, list), localData, nil); err != nil { + return err + } + // todo + return nil +} + +func (g *Group) SyncAllSelfGroupApplicationWithoutNotice(ctx context.Context) error { + list, err := g.GetServerSelfGroupApplication(ctx) + if err != nil { + return err + } + localData, err := g.db.GetSendGroupApplication(ctx) + if err != nil { + return err + } + if err := g.groupRequestSyncer.Sync(ctx, datautil.Batch(ServerGroupRequestToLocalGroupRequest, list), localData, nil, false, true); err != nil { return err } // todo @@ -231,7 +275,19 @@ func (g *Group) SyncAllAdminGroupApplication(ctx context.Context) error { if err != nil { return err } - return g.groupAdminRequestSyncer.Sync(ctx, util.Batch(ServerGroupRequestToLocalAdminGroupRequest, requests), localData, nil) + return g.groupAdminRequestSyncer.Sync(ctx, datautil.Batch(ServerGroupRequestToLocalAdminGroupRequest, requests), localData, nil) +} + +func (g *Group) SyncAllAdminGroupApplicationWithoutNotice(ctx context.Context) error { + requests, err := g.GetServerAdminGroupApplicationList(ctx) + if err != nil { + return err + } + localData, err := g.db.GetAdminGroupApplication(ctx) + if err != nil { + return err + } + return g.groupAdminRequestSyncer.Sync(ctx, datautil.Batch(ServerGroupRequestToLocalAdminGroupRequest, requests), localData, nil, false, true) } func (g *Group) SyncAdminGroupApplications(ctx context.Context, groupIDs ...string) error { diff --git a/internal/group/sync2.go b/internal/group/sync2.go new file mode 100644 index 000000000..a64a26c8b --- /dev/null +++ b/internal/group/sync2.go @@ -0,0 +1,347 @@ +package group + +import ( + "context" + "sync" + + "gorm.io/gorm" + + "github.com/openimsdk/openim-sdk-core/v3/internal/incrversion" + "github.com/openimsdk/openim-sdk-core/v3/internal/util" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + constantpb "github.com/openimsdk/protocol/constant" + "github.com/openimsdk/protocol/group" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/utils/datautil" +) + +type BatchIncrementalReq struct { + UserID string `json:"user_id"` + List []*group.GetIncrementalGroupMemberReq `json:"list"` +} +type BatchIncrementalResp struct { + List map[string]*group.GetIncrementalGroupMemberResp `json:"list"` +} + +func (g *Group) getIncrementalGroupMemberBatch(ctx context.Context, groups []*group.GetIncrementalGroupMemberReq) (map[string]*group.GetIncrementalGroupMemberResp, error) { + resp, err := util.CallApi[BatchIncrementalResp](ctx, constant.GetIncrementalGroupMemberBatch, &BatchIncrementalReq{UserID: g.loginUserID, List: groups}) + if err != nil { + return nil, err + } + return resp.List, nil +} + +func (g *Group) groupAndMemberVersionTableName() string { + return "local_group_entities_version" +} + +func (g *Group) groupTableName() string { + return model_struct.LocalGroup{}.TableName() +} + +func (g *Group) IncrSyncJoinGroupMember(ctx context.Context) error { + groups, err := g.db.GetJoinedGroupListDB(ctx) + if err != nil { + return err + } + groupIDs := datautil.Slice(groups, func(e *model_struct.LocalGroup) string { + return e.GroupID + }) + return g.IncrSyncGroupAndMember(ctx, groupIDs...) +} + +func (g *Group) IncrSyncGroupAndMember(ctx context.Context, groupIDs ...string) error { + var wg sync.WaitGroup + if len(groupIDs) == 0 { + return nil + } + const maxSyncNum = constantpb.MaxSyncPullNumber + groupIDSet := datautil.SliceSet(groupIDs) + var groups []*group.GetIncrementalGroupMemberReq + if len(groupIDs) > maxSyncNum { + groups = make([]*group.GetIncrementalGroupMemberReq, 0, maxSyncNum) + } else { + groups = make([]*group.GetIncrementalGroupMemberReq, 0, len(groupIDs)) + } + for { + if len(groupIDSet) == 0 { + return nil + } + for groupID := range groupIDSet { + if len(groups) == cap(groups) { + break + } + req := group.GetIncrementalGroupMemberReq{ + GroupID: groupID, + } + lvs, err := g.db.GetVersionSync(ctx, g.groupAndMemberVersionTableName(), groupID) + if err == nil { + req.VersionID = lvs.VersionID + req.Version = lvs.Version + } else if errs.Unwrap(err) != gorm.ErrRecordNotFound { + return err + } + groups = append(groups, &req) + } + groupVersion, err := g.getIncrementalGroupMemberBatch(ctx, groups) + if err != nil { + return err + } + groups = groups[:0] + for groupID, resp := range groupVersion { + tempResp := resp + tempGroupID := groupID + wg.Add(1) + go func() error { + if err := g.syncGroupAndMember(ctx, tempGroupID, tempResp); err != nil { + return err + } + wg.Done() + return nil + }() + delete(groupIDSet, tempGroupID) + } + wg.Wait() + num := len(groupIDSet) + _ = num + } +} + +func (g *Group) syncGroupAndMember(ctx context.Context, groupID string, resp *group.GetIncrementalGroupMemberResp) error { + groupMemberSyncer := incrversion.VersionSynchronizer[*model_struct.LocalGroupMember, *group.GetIncrementalGroupMemberResp]{ + Ctx: ctx, + DB: g.db, + TableName: g.groupAndMemberVersionTableName(), + EntityID: groupID, + Key: func(localGroupMember *model_struct.LocalGroupMember) string { + return localGroupMember.UserID + }, + Local: func() ([]*model_struct.LocalGroupMember, error) { + return g.db.GetGroupMemberListByGroupID(ctx, groupID) + }, + ServerVersion: func() *group.GetIncrementalGroupMemberResp { + return resp + }, + Full: func(resp *group.GetIncrementalGroupMemberResp) bool { + return resp.Full + }, + Version: func(resp *group.GetIncrementalGroupMemberResp) (string, uint64) { + return resp.VersionID, resp.Version + }, + Delete: func(resp *group.GetIncrementalGroupMemberResp) []string { + return resp.Delete + }, + Update: func(resp *group.GetIncrementalGroupMemberResp) []*model_struct.LocalGroupMember { + return datautil.Batch(ServerGroupMemberToLocalGroupMember, resp.Update) + }, + Insert: func(resp *group.GetIncrementalGroupMemberResp) []*model_struct.LocalGroupMember { + return datautil.Batch(ServerGroupMemberToLocalGroupMember, resp.Insert) + }, + ExtraData: func(resp *group.GetIncrementalGroupMemberResp) any { + return resp.Group + }, + ExtraDataProcessor: func(ctx context.Context, data any) error { + groupInfo, ok := data.(*sdkws.GroupInfo) + if !ok { + return errs.New("group info type error") + } + if groupInfo == nil { + return nil + } + local, err := g.db.GetJoinedGroupListDB(ctx) + if err != nil { + return err + } + log.ZDebug(ctx, "group info", "groupInfo", groupInfo) + changes := datautil.Batch(ServerGroupToLocalGroup, []*sdkws.GroupInfo{groupInfo}) + kv := datautil.SliceToMapAny(local, func(e *model_struct.LocalGroup) (string, *model_struct.LocalGroup) { + return e.GroupID, e + }) + for i, change := range changes { + key := change.GroupID + kv[key] = changes[i] + } + server := datautil.Values(kv) + return g.groupSyncer.Sync(ctx, server, local, nil) + }, + Syncer: func(server, local []*model_struct.LocalGroupMember) error { + return g.groupMemberSyncer.Sync(ctx, server, local, nil) + }, + FullSyncer: func(ctx context.Context) error { + return g.groupMemberSyncer.FullSync(ctx, groupID) + }, + FullID: func(ctx context.Context) ([]string, error) { + resp, err := util.CallApi[group.GetFullGroupMemberUserIDsResp](ctx, constant.GetFullGroupMemberUserIDs, &group.GetFullGroupMemberUserIDsReq{ + GroupID: groupID, + }) + if err != nil { + return nil, err + } + return resp.UserIDs, nil + }, + } + return groupMemberSyncer.Sync() +} + +func (g *Group) onlineSyncGroupAndMember(ctx context.Context, groupID string, deleteGroupMembers, updateGroupMembers, insertGroupMembers []*sdkws.GroupMemberFullInfo, + updateGroup *sdkws.GroupInfo, version uint64, versionID string) error { + groupMemberSyncer := incrversion.VersionSynchronizer[*model_struct.LocalGroupMember, *group.GetIncrementalGroupMemberResp]{ + Ctx: ctx, + DB: g.db, + TableName: g.groupAndMemberVersionTableName(), + EntityID: groupID, + Key: func(localGroupMember *model_struct.LocalGroupMember) string { + return localGroupMember.UserID + }, + Local: func() ([]*model_struct.LocalGroupMember, error) { + return g.db.GetGroupMemberListByGroupID(ctx, groupID) + }, + ServerVersion: func() *group.GetIncrementalGroupMemberResp { + return &group.GetIncrementalGroupMemberResp{ + Version: version, + VersionID: versionID, + Full: false, + Delete: datautil.Slice(deleteGroupMembers, func(e *sdkws.GroupMemberFullInfo) string { + return e.UserID + }), + Insert: insertGroupMembers, + Update: updateGroupMembers, + Group: updateGroup, + } + }, + Server: func(version *model_struct.LocalVersionSync) (*group.GetIncrementalGroupMemberResp, error) { + singleGroupReq := &group.GetIncrementalGroupMemberReq{ + GroupID: groupID, + VersionID: version.VersionID, + Version: version.Version, + } + resp, err := util.CallApi[BatchIncrementalResp](ctx, constant.GetIncrementalGroupMemberBatch, + &BatchIncrementalReq{UserID: g.loginUserID, List: []*group.GetIncrementalGroupMemberReq{singleGroupReq}}) + if err != nil { + return nil, err + } + if resp.List != nil { + if singleGroupResp, ok := resp.List[groupID]; ok { + return singleGroupResp, nil + } + } + return nil, errs.New("group member version record not found") + + }, + Full: func(resp *group.GetIncrementalGroupMemberResp) bool { + return resp.Full + }, + Version: func(resp *group.GetIncrementalGroupMemberResp) (string, uint64) { + return resp.VersionID, resp.Version + }, + Delete: func(resp *group.GetIncrementalGroupMemberResp) []string { + return resp.Delete + }, + Update: func(resp *group.GetIncrementalGroupMemberResp) []*model_struct.LocalGroupMember { + return datautil.Batch(ServerGroupMemberToLocalGroupMember, resp.Update) + }, + Insert: func(resp *group.GetIncrementalGroupMemberResp) []*model_struct.LocalGroupMember { + return datautil.Batch(ServerGroupMemberToLocalGroupMember, resp.Insert) + }, + ExtraData: func(resp *group.GetIncrementalGroupMemberResp) any { + return resp.Group + }, + ExtraDataProcessor: func(ctx context.Context, data any) error { + groupInfo, ok := data.(*sdkws.GroupInfo) + if !ok { + return errs.New("group info type error") + } + if groupInfo == nil { + return nil + } + local, err := g.db.GetJoinedGroupListDB(ctx) + if err != nil { + return err + } + log.ZDebug(ctx, "group info", "groupInfo", groupInfo) + changes := datautil.Batch(ServerGroupToLocalGroup, []*sdkws.GroupInfo{groupInfo}) + kv := datautil.SliceToMapAny(local, func(e *model_struct.LocalGroup) (string, *model_struct.LocalGroup) { + return e.GroupID, e + }) + for i, change := range changes { + key := change.GroupID + kv[key] = changes[i] + } + server := datautil.Values(kv) + return g.groupSyncer.Sync(ctx, server, local, nil) + }, + Syncer: func(server, local []*model_struct.LocalGroupMember) error { + return g.groupMemberSyncer.Sync(ctx, server, local, nil) + }, + FullSyncer: func(ctx context.Context) error { + return g.groupMemberSyncer.FullSync(ctx, groupID) + }, + FullID: func(ctx context.Context) ([]string, error) { + resp, err := util.CallApi[group.GetFullGroupMemberUserIDsResp](ctx, constant.GetFullGroupMemberUserIDs, &group.GetFullGroupMemberUserIDsReq{ + GroupID: groupID, + }) + if err != nil { + return nil, err + } + return resp.UserIDs, nil + }, + } + return groupMemberSyncer.CheckVersionSync() +} + +func (g *Group) IncrSyncJoinGroup(ctx context.Context) error { + opt := incrversion.VersionSynchronizer[*model_struct.LocalGroup, *group.GetIncrementalJoinGroupResp]{ + Ctx: ctx, + DB: g.db, + TableName: g.groupTableName(), + EntityID: g.loginUserID, + Key: func(LocalGroup *model_struct.LocalGroup) string { + return LocalGroup.GroupID + }, + Local: func() ([]*model_struct.LocalGroup, error) { + return g.db.GetJoinedGroupListDB(ctx) + }, + Server: func(version *model_struct.LocalVersionSync) (*group.GetIncrementalJoinGroupResp, error) { + return util.CallApi[group.GetIncrementalJoinGroupResp](ctx, constant.GetIncrementalJoinGroup, &group.GetIncrementalJoinGroupReq{ + UserID: g.loginUserID, + Version: version.Version, + VersionID: version.VersionID, + }) + }, + Full: func(resp *group.GetIncrementalJoinGroupResp) bool { + return resp.Full + }, + Version: func(resp *group.GetIncrementalJoinGroupResp) (string, uint64) { + return resp.VersionID, resp.Version + }, + Delete: func(resp *group.GetIncrementalJoinGroupResp) []string { + return resp.Delete + }, + Update: func(resp *group.GetIncrementalJoinGroupResp) []*model_struct.LocalGroup { + return datautil.Batch(ServerGroupToLocalGroup, resp.Update) + }, + Insert: func(resp *group.GetIncrementalJoinGroupResp) []*model_struct.LocalGroup { + return datautil.Batch(ServerGroupToLocalGroup, resp.Insert) + }, + Syncer: func(server, local []*model_struct.LocalGroup) error { + return g.groupSyncer.Sync(ctx, server, local, nil) + }, + FullSyncer: func(ctx context.Context) error { + return g.groupSyncer.FullSync(ctx, g.loginUserID) + }, + FullID: func(ctx context.Context) ([]string, error) { + resp, err := util.CallApi[group.GetFullJoinGroupIDsResp](ctx, constant.GetFullJoinedGroupIDs, &group.GetFullJoinGroupIDsReq{ + UserID: g.loginUserID, + }) + if err != nil { + return nil, err + } + return resp.GroupIDs, nil + + }, + } + return opt.Sync() +} diff --git a/internal/group/sync2_test.go b/internal/group/sync2_test.go new file mode 100644 index 000000000..654521e1a --- /dev/null +++ b/internal/group/sync2_test.go @@ -0,0 +1 @@ +package group diff --git a/internal/group/types.go b/internal/group/types.go new file mode 100644 index 000000000..2d7641a70 --- /dev/null +++ b/internal/group/types.go @@ -0,0 +1,13 @@ +package group + +import "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + +type GetGroupMemberListV2Response struct { + GroupMembersList []*model_struct.LocalGroupMember + IsEnd bool `json:"isEnd"` +} + +type GetGroupListV2Response struct { + GroupsList []*model_struct.LocalGroup + IsEnd bool `json:"isEnd"` +} diff --git a/internal/incrversion/option.go b/internal/incrversion/option.go new file mode 100644 index 000000000..9c7024143 --- /dev/null +++ b/internal/incrversion/option.go @@ -0,0 +1,265 @@ +package incrversion + +import ( + "context" + "reflect" + "sort" + + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/utils/datautil" + "gorm.io/gorm" +) + +type VersionSynchronizer[V, R any] struct { + Ctx context.Context + DB db_interface.VersionSyncModel + TableName string + EntityID string + Key func(V) string + Local func() ([]V, error) + ServerVersion func() R + Server func(version *model_struct.LocalVersionSync) (R, error) + Full func(resp R) bool + Version func(resp R) (string, uint64) + Delete func(resp R) []string + Update func(resp R) []V + Insert func(resp R) []V + ExtraData func(resp R) any + ExtraDataProcessor func(ctx context.Context, data any) error + Syncer func(server, local []V) error + FullSyncer func(ctx context.Context) error + FullID func(ctx context.Context) ([]string, error) +} + +func (o *VersionSynchronizer[V, R]) getVersionInfo() (*model_struct.LocalVersionSync, error) { + versionInfo, err := o.DB.GetVersionSync(o.Ctx, o.TableName, o.EntityID) + if err != nil && errs.Unwrap(err) != gorm.ErrRecordNotFound { + log.ZWarn(o.Ctx, "get version info", err) + return nil, err + + } + return versionInfo, nil +} + +func (o *VersionSynchronizer[V, R]) updateVersionInfo(lvs *model_struct.LocalVersionSync, resp R) error { + lvs.Table = o.TableName + lvs.EntityID = o.EntityID + lvs.VersionID, lvs.Version = o.Version(resp) + return o.DB.SetVersionSync(o.Ctx, lvs) +} +func judgeInterfaceIsNil(data any) bool { + return reflect.ValueOf(data).Kind() == reflect.Ptr && reflect.ValueOf(data).IsNil() +} + +func (o *VersionSynchronizer[V, R]) Sync() error { + var lvs *model_struct.LocalVersionSync + var resp R + var extraData any + if o.ServerVersion == nil { + var err error + lvs, err = o.getVersionInfo() + if err != nil { + return err + } + resp, err = o.Server(lvs) + if err != nil { + return err + } + } else { + var err error + lvs, err = o.getVersionInfo() + if err != nil { + return err + } + resp = o.ServerVersion() + } + delIDs := o.Delete(resp) + changes := o.Update(resp) + insert := o.Insert(resp) + if o.ExtraData != nil { + temp := o.ExtraData(resp) + if !judgeInterfaceIsNil(temp) { + extraData = temp + } + } + if len(delIDs) == 0 && len(changes) == 0 && len(insert) == 0 && !o.Full(resp) && extraData == nil { + log.ZDebug(o.Ctx, "no data to sync", "table", o.TableName, "entityID", o.EntityID) + return nil + } + + if o.Full(resp) { + err := o.FullSyncer(o.Ctx) + if err != nil { + return err + } + lvs.UIDList, err = o.FullID(o.Ctx) + if err != nil { + return err + } + } else { + if len(delIDs) > 0 { + lvs.UIDList = DeleteElements(lvs.UIDList, delIDs) + } + if len(insert) > 0 { + lvs.UIDList = append(lvs.UIDList, datautil.Slice(insert, o.Key)...) + + } + local, err := o.Local() + if err != nil { + return err + } + kv := datautil.SliceToMapAny(local, func(v V) (string, V) { + return o.Key(v), v + }) + + changes = append(changes, insert...) + + for i, change := range changes { + key := o.Key(change) + kv[key] = changes[i] + } + + for _, id := range delIDs { + delete(kv, id) + } + server := datautil.Values(kv) + if err := o.Syncer(server, local); err != nil { + return err + } + if extraData != nil && o.ExtraDataProcessor != nil { + if err := o.ExtraDataProcessor(o.Ctx, extraData); err != nil { + return err + } + + } + } + return o.updateVersionInfo(lvs, resp) +} + +func (o *VersionSynchronizer[V, R]) CheckVersionSync() error { + lvs, err := o.getVersionInfo() + if err != nil { + return err + } + var extraData any + resp := o.ServerVersion() + delIDs := o.Delete(resp) + changes := o.Update(resp) + insert := o.Insert(resp) + versionID, version := o.Version(resp) + if o.ExtraData != nil { + temp := o.ExtraData(resp) + if !judgeInterfaceIsNil(temp) { + extraData = temp + } + } + if len(delIDs) == 0 && len(changes) == 0 && len(insert) == 0 && !o.Full(resp) && extraData == nil { + log.ZWarn(o.Ctx, "exception no data to sync", errs.New("notification no data"), "table", o.TableName, "entityID", o.EntityID) + return nil + } + log.ZDebug(o.Ctx, "check version sync", "table", o.TableName, "entityID", o.EntityID, "versionID", versionID, "localVersionID", lvs.VersionID, "version", version, "localVersion", lvs.Version) + /// If the version unique ID cannot correspond with the local version, + // it indicates that the data might have been tampered with or an exception has occurred. + //Trigger the complete client-server incremental synchronization. + if versionID != lvs.VersionID { + log.ZDebug(o.Ctx, "version id not match", errs.New("version id not match"), "versionID", versionID, "localVersionID", lvs.VersionID) + o.ServerVersion = nil + return o.Sync() + } + if lvs.Version+1 == version { + if len(delIDs) > 0 { + lvs.UIDList = DeleteElements(lvs.UIDList, delIDs) + } + if len(insert) > 0 { + lvs.UIDList = append(lvs.UIDList, datautil.Slice(insert, o.Key)...) + + } + local, err := o.Local() + if err != nil { + return err + } + kv := datautil.SliceToMapAny(local, func(v V) (string, V) { + return o.Key(v), v + }) + changes = append(changes, insert...) + for i, change := range changes { + key := o.Key(change) + kv[key] = changes[i] + } + + for _, id := range delIDs { + delete(kv, id) + } + server := datautil.Values(kv) + if err := o.Syncer(server, local); err != nil { + return err + } + if extraData != nil && o.ExtraDataProcessor != nil { + if err := o.ExtraDataProcessor(o.Ctx, extraData); err != nil { + return err + } + + } + return o.updateVersionInfo(lvs, resp) + } else if version <= lvs.Version { + log.ZWarn(o.Ctx, "version less than local version", errs.New("version less than local version"), + "table", o.TableName, "entityID", o.EntityID, "version", version, "localVersion", lvs.Version) + return nil + } else { + // If the version number has a gap with the local version number, + //it indicates that some pushed data might be missing. + //Trigger the complete client-server incremental synchronization. + o.ServerVersion = nil + return o.Sync() + } +} + +// DeleteElements removes elements from a slice that are contained in another slice, while maintaining the order of the slice +func DeleteElements[E comparable](es []E, toDelete []E) []E { + // Store the elements to be deleted in a hash set + deleteSet := make(map[E]struct{}, len(toDelete)) + for _, e := range toDelete { + deleteSet[e] = struct{}{} + } + + // Use an index j to track the new slice position + j := 0 + for _, e := range es { + if _, found := deleteSet[e]; !found { + es[j] = e + j++ + } + } + return es[:j] +} + +// DeleteElement removes a specified element from a slice while maintaining the order of the slice +func DeleteElement[E comparable](es []E, element E) []E { + j := 0 + for _, e := range es { + if e != element { + es[j] = e + j++ + } + } + return es[:j] +} + +// Slice converts slice types in batches and sorts the resulting slice using a custom comparator +func Slice[E any, T any](es []E, fn func(e E) T, less func(a, b T) bool) []T { + // Convert the slice + v := make([]T, len(es)) + for i := 0; i < len(es); i++ { + v[i] = fn(es[i]) + } + + // Sort the slice + sort.Slice(v, func(i, j int) bool { + return less(v[i], v[j]) + }) + + return v +} diff --git a/internal/interaction/context.go b/internal/interaction/context.go index 841f5444a..9845010c1 100644 --- a/internal/interaction/context.go +++ b/internal/interaction/context.go @@ -17,7 +17,7 @@ package interaction import ( "time" - "github.com/OpenIMSDK/protocol/constant" + "github.com/openimsdk/protocol/constant" ) type ConnContext struct { diff --git a/internal/interaction/long_conn_mgr.go b/internal/interaction/long_conn_mgr.go index d437a343d..b89b608a0 100644 --- a/internal/interaction/long_conn_mgr.go +++ b/internal/interaction/long_conn_mgr.go @@ -33,11 +33,11 @@ import ( "sync" "time" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/log" "github.com/golang/protobuf/proto" "github.com/gorilla/websocket" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" ) const ( @@ -369,7 +369,7 @@ func (c *LongConnMgr) writeBinaryMsgAndRetry(msg *GeneralWsReq) (chan *GeneralWs msgIncr, tempChan := c.Syncer.AddCh(msg.SendID) msg.MsgIncr = msgIncr if c.GetConnectionStatus() != Connected && msg.ReqIdentifier == constant.GetNewestSeq { - return tempChan, sdkerrs.ErrNetwork.Wrap("connection closed,conning...") + return tempChan, sdkerrs.ErrNetwork.WrapMsg("connection closed,conning...") } for i := 0; i < maxReconnectAttempts; i++ { err := c.writeBinaryMsg(*msg) @@ -383,7 +383,7 @@ func (c *LongConnMgr) writeBinaryMsgAndRetry(msg *GeneralWsReq) (chan *GeneralWs return tempChan, nil } } - return nil, sdkerrs.ErrNetwork.Wrap("send binary message error") + return nil, sdkerrs.ErrNetwork.WrapMsg("send binary message error") } func (c *LongConnMgr) writeBinaryMsg(req GeneralWsReq) error { @@ -394,7 +394,7 @@ func (c *LongConnMgr) writeBinaryMsg(req GeneralWsReq) error { return err } if c.GetConnectionStatus() != Connected { - return sdkerrs.ErrNetwork.Wrap("connection closed,re conning...") + return sdkerrs.ErrNetwork.WrapMsg("connection closed,re conning...") } _ = c.conn.SetWriteDeadline(writeWait) if c.IsCompression { @@ -496,7 +496,6 @@ func (c *LongConnMgr) reConn(ctx context.Context, num *int) (needRecon bool, err } c.connWrite.Lock() defer c.connWrite.Unlock() - log.ZDebug(ctx, "conn start") c.listener.OnConnecting() c.SetConnectionStatus(Connecting) url := fmt.Sprintf("%s?sendID=%s&token=%s&platformID=%d&operationID=%s&isBackground=%t", @@ -505,6 +504,7 @@ func (c *LongConnMgr) reConn(ctx context.Context, num *int) (needRecon bool, err if c.IsCompression { url += fmt.Sprintf("&compression=%s", "gzip") } + log.ZDebug(ctx, "conn start", "url", url) resp, err := c.conn.Dial(url, nil) if err != nil { c.SetConnectionStatus(Closed) @@ -527,12 +527,9 @@ func (c *LongConnMgr) reConn(ctx context.Context, num *int) (needRecon bool, err switch apiResp.ErrCode { case errs.TokenExpiredError, - errs.TokenInvalidError, errs.TokenMalformedError, errs.TokenNotValidYetError, - errs.TokenUnknownError, - errs.TokenNotExistError, - errs.TokenKickedError: + errs.TokenUnknownError: return false, err default: return true, err diff --git a/internal/interaction/msg_sync.go b/internal/interaction/msg_sync.go index e24e0b86a..4f28dec24 100644 --- a/internal/interaction/msg_sync.go +++ b/internal/interaction/msg_sync.go @@ -16,14 +16,19 @@ package interaction import ( "context" + "strings" + "sync" + "time" + + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + "github.com/openimsdk/openim-sdk-core/v3/pkg/common" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" - "strings" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) const ( @@ -76,14 +81,51 @@ func (m *MsgSyncer) loadSeq(ctx context.Context) error { if len(conversationIDList) == 0 { m.reinstalled = true } + + // TODO With a large number of sessions, this could potentially cause blocking and needs optimization. + type SyncedSeq struct { + ConversationID string + MaxSyncedSeq int64 + Err error + } + concurrency := 10 + t2 := time.Now() + SyncedSeqs := make(chan SyncedSeq, len(conversationIDList)) + sem := make(chan struct{}, concurrency) + + var wg sync.WaitGroup for _, v := range conversationIDList { - maxSyncedSeq, err := m.db.GetConversationNormalMsgSeq(ctx, v) - if err != nil { - log.ZError(ctx, "get group normal seq failed", err, "conversationID", v) + wg.Add(1) + sem <- struct{}{} // Acquire a token + go func(conversationID string) { + defer wg.Done() + defer func() { <-sem }() // Release the token + + maxSyncedSeq, err := m.db.GetConversationNormalMsgSeq(ctx, conversationID) + SyncedSeqs <- SyncedSeq{ + ConversationID: conversationID, + MaxSyncedSeq: maxSyncedSeq, + Err: err, + } + }(v) + log.ZDebug(ctx, "goroutine done.", "goroutine cost time", time.Since(t2)) + } + + // Close the results channel once all goroutines have finished + go func() { + wg.Wait() + close(SyncedSeqs) + }() + + // Collect the results + for res := range SyncedSeqs { + if res.Err != nil { + log.ZError(ctx, "get group normal seq failed", res.Err, "conversationID", res.ConversationID) } else { - m.syncedMaxSeqs[v] = maxSyncedSeq + m.syncedMaxSeqs[res.ConversationID] = res.MaxSyncedSeq } } + notificationSeqs, err := m.db.GetNotificationAllSeqs(ctx) if err != nil { log.ZError(ctx, "get notification seq failed", err) @@ -146,15 +188,31 @@ func (m *MsgSyncer) compareSeqsAndBatchSync(ctx context.Context, maxSeqToSync ma messagesSeqMap[conversationID] = seq } } + + var notificationSeqs []*model_struct.NotificationSeqs + for conversationID, seq := range notificationsSeqMap { - err := m.db.SetNotificationSeq(ctx, conversationID, seq) - if err != nil { - log.ZWarn(ctx, "SetNotificationSeq err", err, "conversationID", conversationID, "seq", seq) - continue - } else { - m.syncedMaxSeqs[conversationID] = seq - } + notificationSeqs = append(notificationSeqs, &model_struct.NotificationSeqs{ + ConversationID: conversationID, + Seq: seq, + }) + m.syncedMaxSeqs[conversationID] = seq + } + + err := m.db.BatchInsertNotificationSeq(ctx, notificationSeqs) + if err != nil { + log.ZWarn(ctx, "BatchInsertNotificationSeq err", err) } + + //for conversationID, seq := range notificationsSeqMap { + // err := m.db.SetNotificationSeq(ctx, conversationID, seq) + // if err != nil { + // log.ZWarn(ctx, "SetNotificationSeq err", err, "conversationID", conversationID, "seq", seq) + // continue + // } else { + // m.syncedMaxSeqs[conversationID] = seq + // } + //} for conversationID, maxSeq := range messagesSeqMap { if syncedMaxSeq, ok := m.syncedMaxSeqs[conversationID]; ok { if maxSeq > syncedMaxSeq { @@ -215,17 +273,26 @@ func (m *MsgSyncer) pushTriggerAndSync(ctx context.Context, pullMsgs map[string] // Called after successful reconnection to synchronize the latest message func (m *MsgSyncer) doConnected(ctx context.Context) { - common.TriggerCmdNotification(m.ctx, sdk_struct.CmdNewMsgComeToConversation{SyncFlag: constant.MsgSyncBegin}, m.conversationCh) + reinstalled := m.reinstalled + if reinstalled { + common.TriggerCmdNotification(m.ctx, sdk_struct.CmdNewMsgComeToConversation{SyncFlag: constant.AppDataSyncStart}, m.conversationCh) + } else { + common.TriggerCmdNotification(m.ctx, sdk_struct.CmdNewMsgComeToConversation{SyncFlag: constant.MsgSyncBegin}, m.conversationCh) + } var resp sdkws.GetMaxSeqResp if err := m.longConnMgr.SendReqWaitResp(m.ctx, &sdkws.GetMaxSeqReq{UserID: m.loginUserID}, constant.GetNewestSeq, &resp); err != nil { log.ZError(m.ctx, "get max seq error", err) common.TriggerCmdNotification(m.ctx, sdk_struct.CmdNewMsgComeToConversation{SyncFlag: constant.MsgSyncFailed}, m.conversationCh) return } else { - log.ZDebug(m.ctx, "get max seq success", "resp", resp) + log.ZDebug(m.ctx, "get max seq success", "resp", resp.MaxSeqs) } m.compareSeqsAndBatchSync(ctx, resp.MaxSeqs, connectPullNums) - common.TriggerCmdNotification(m.ctx, sdk_struct.CmdNewMsgComeToConversation{SyncFlag: constant.MsgSyncEnd}, m.conversationCh) + if reinstalled { + common.TriggerCmdNotification(m.ctx, sdk_struct.CmdNewMsgComeToConversation{SyncFlag: constant.AppDataSyncFinish}, m.conversationCh) + } else { + common.TriggerCmdNotification(m.ctx, sdk_struct.CmdNewMsgComeToConversation{SyncFlag: constant.MsgSyncEnd}, m.conversationCh) + } } func IsNotification(conversationID string) bool { @@ -361,24 +428,24 @@ func (m *MsgSyncer) syncMsgBySeqs(ctx context.Context, conversationID string, se // triggers a conversation with a new message. func (m *MsgSyncer) triggerConversation(ctx context.Context, msgs map[string]*sdkws.PullMsgs) error { - if len(msgs) >= 0 { + if len(msgs) > 0 { err := common.TriggerCmdNewMsgCome(ctx, sdk_struct.CmdNewMsgComeToConversation{Msgs: msgs}, m.conversationCh) if err != nil { log.ZError(ctx, "triggerCmdNewMsgCome err", err, "msgs", msgs) } log.ZDebug(ctx, "triggerConversation", "msgs", msgs) return err + } else { + log.ZDebug(ctx, "triggerConversation is nil", "msgs", msgs) } return nil } func (m *MsgSyncer) triggerNotification(ctx context.Context, msgs map[string]*sdkws.PullMsgs) error { - if len(msgs) >= 0 { - err := common.TriggerCmdNotification(ctx, sdk_struct.CmdNewMsgComeToConversation{Msgs: msgs}, m.conversationCh) - if err != nil { - log.ZError(ctx, "triggerCmdNewMsgCome err", err, "msgs", msgs) - } - return err + if len(msgs) > 0 { + common.TriggerCmdNotification(ctx, sdk_struct.CmdNewMsgComeToConversation{Msgs: msgs}, m.conversationCh) + } else { + log.ZDebug(ctx, "triggerNotification is nil", "msgs", msgs) } return nil diff --git a/internal/interaction/ws_js.go b/internal/interaction/ws_js.go index 2b31f269c..1f2b243e4 100644 --- a/internal/interaction/ws_js.go +++ b/internal/interaction/ws_js.go @@ -22,7 +22,7 @@ import ( "context" "encoding/json" "fmt" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" "io" "net/http" "net/url" diff --git a/internal/interaction/ws_resp_asyn.go b/internal/interaction/ws_resp_asyn.go index d6018f5e5..b798cb06c 100644 --- a/internal/interaction/ws_resp_asyn.go +++ b/internal/interaction/ws_resp_asyn.go @@ -21,7 +21,7 @@ import ( "sync" "time" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" ) type GeneralWsResp struct { diff --git a/internal/third/log.go b/internal/third/log.go index 756b132e4..aff0b6e82 100644 --- a/internal/third/log.go +++ b/internal/third/log.go @@ -4,11 +4,11 @@ import ( "context" "errors" "fmt" - "github.com/OpenIMSDK/protocol/third" "github.com/openimsdk/openim-sdk-core/v3/internal/file" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/ccontext" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" + "github.com/openimsdk/protocol/third" "io" "math/rand" "os" diff --git a/internal/third/third.go b/internal/third/third.go index 7d7ae70a8..a7bf83545 100644 --- a/internal/third/third.go +++ b/internal/third/third.go @@ -16,9 +16,9 @@ package third import ( "context" - "github.com/OpenIMSDK/protocol/third" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" + "github.com/openimsdk/protocol/third" "github.com/openimsdk/openim-sdk-core/v3/internal/file" ) diff --git a/internal/user/convert.go b/internal/user/convert.go index 5993d3601..2f68844a3 100644 --- a/internal/user/convert.go +++ b/internal/user/convert.go @@ -15,10 +15,10 @@ package user import ( - "github.com/OpenIMSDK/protocol/user" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + "github.com/openimsdk/protocol/user" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" ) func ServerUserToLocalUser(user *sdkws.UserInfo) *model_struct.LocalUser { diff --git a/internal/user/sdk.go b/internal/user/sdk.go index 601a23e2a..6a97c913a 100644 --- a/internal/user/sdk.go +++ b/internal/user/sdk.go @@ -16,13 +16,13 @@ package user import ( "context" - pbUser "github.com/OpenIMSDK/protocol/user" - userPb "github.com/OpenIMSDK/protocol/user" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + pbUser "github.com/openimsdk/protocol/user" + userPb "github.com/openimsdk/protocol/user" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" ) func (u *User) GetUsersInfo(ctx context.Context, userIDs []string) ([]*model_struct.LocalUser, error) { diff --git a/internal/user/sync.go b/internal/user/sync.go index 25de3b1b5..90b6f405a 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -17,14 +17,14 @@ package user import ( "context" "errors" - userPb "github.com/OpenIMSDK/protocol/user" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" - - "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/log" + userPb "github.com/openimsdk/protocol/user" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/utils/datautil" "gorm.io/gorm" ) @@ -44,6 +44,22 @@ func (u *User) SyncLoginUserInfo(ctx context.Context) error { log.ZDebug(ctx, "SyncLoginUserInfo", "remoteUser", remoteUser, "localUser", localUser) return u.userSyncer.Sync(ctx, []*model_struct.LocalUser{remoteUser}, localUsers, nil) } +func (u *User) SyncLoginUserInfoWithoutNotice(ctx context.Context) error { + remoteUser, err := u.GetSingleUserFromSvr(ctx, u.loginUserID) + if err != nil { + return err + } + localUser, err := u.GetLoginUser(ctx, u.loginUserID) + if err != nil && errs.Unwrap(err) != gorm.ErrRecordNotFound { + log.ZError(ctx, "SyncLoginUserInfo", err) + } + var localUsers []*model_struct.LocalUser + if err == nil { + localUsers = []*model_struct.LocalUser{localUser} + } + log.ZDebug(ctx, "SyncLoginUserInfo", "remoteUser", remoteUser, "localUser", localUser) + return u.userSyncer.Sync(ctx, []*model_struct.LocalUser{remoteUser}, localUsers, nil, false, true) +} func (u *User) SyncUserStatus(ctx context.Context, fromUserID string, status int32, platformID int32) { userOnlineStatus := userPb.OnlineStatus{ @@ -92,5 +108,21 @@ func (u *User) SyncAllCommand(ctx context.Context) error { return err } log.ZDebug(ctx, "sync command", "data from server", serverData, "data from local", localData) - return u.commandSyncer.Sync(ctx, util.Batch(ServerCommandToLocalCommand, serverData.CommandResp), localData, nil) + return u.commandSyncer.Sync(ctx, datautil.Batch(ServerCommandToLocalCommand, serverData.CommandResp), localData, nil) +} + +func (u *User) SyncAllCommandWithoutNotice(ctx context.Context) error { + var serverData CommandInfoResponse + err := util.ApiPost(ctx, constant.ProcessUserCommandGetAll, userPb.ProcessUserCommandGetAllReq{ + UserID: u.loginUserID, + }, &serverData) + if err != nil { + return err + } + localData, err := u.DataBase.ProcessUserCommandGetAll(ctx) + if err != nil { + return err + } + log.ZDebug(ctx, "sync command", "data from server", serverData, "data from local", localData) + return u.commandSyncer.Sync(ctx, datautil.Batch(ServerCommandToLocalCommand, serverData.CommandResp), localData, nil, false, true) } diff --git a/internal/user/user.go b/internal/user/user.go index 00c5b41a6..181930984 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -17,22 +17,23 @@ package user import ( "context" "fmt" - authPb "github.com/OpenIMSDK/protocol/auth" - "github.com/OpenIMSDK/protocol/sdkws" - userPb "github.com/OpenIMSDK/protocol/user" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/internal/cache" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" "github.com/openimsdk/openim-sdk-core/v3/pkg/syncer" + authPb "github.com/openimsdk/protocol/auth" + "github.com/openimsdk/protocol/sdkws" + userPb "github.com/openimsdk/protocol/user" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/utils/datautil" - PbConstant "github.com/OpenIMSDK/protocol/constant" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/common" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + PbConstant "github.com/openimsdk/protocol/constant" ) type BasicInfo struct { @@ -45,8 +46,8 @@ type User struct { db_interface.DataBase loginUserID string listener func() open_im_sdk_callback.OnUserListener - userSyncer *syncer.Syncer[*model_struct.LocalUser, string] - commandSyncer *syncer.Syncer[*model_struct.LocalUserCommand, string] + userSyncer *syncer.Syncer[*model_struct.LocalUser, syncer.NoResp, string] + commandSyncer *syncer.Syncer[*model_struct.LocalUserCommand, syncer.NoResp, string] conversationCh chan common.Cmd2Value UserBasicCache *cache.Cache[string, *BasicInfo] OnlineStatusCache *cache.Cache[string, *userPb.OnlineStatus] @@ -67,7 +68,7 @@ func NewUser(dataBase db_interface.DataBase, loginUserID string, conversationCh } func (u *User) initSyncer() { - u.userSyncer = syncer.New( + u.userSyncer = syncer.New[*model_struct.LocalUser, syncer.NoResp, string]( func(ctx context.Context, value *model_struct.LocalUser) error { return u.InsertLoginUser(ctx, value) }, @@ -93,7 +94,7 @@ func (u *User) initSyncer() { return nil }, ) - u.commandSyncer = syncer.New( + u.commandSyncer = syncer.New[*model_struct.LocalUserCommand, syncer.NoResp, string]( func(ctx context.Context, command *model_struct.LocalUserCommand) error { // Logic to insert a command return u.DataBase.ProcessUserCommandAdd(ctx, command) @@ -260,9 +261,9 @@ func (u *User) userCommandUpdateNotification(ctx context.Context, msg *sdkws.Msg func (u *User) GetUsersInfoFromSvr(ctx context.Context, userIDs []string) ([]*model_struct.LocalUser, error) { resp, err := util.CallApi[userPb.GetDesignateUsersResp](ctx, constant.GetUsersInfoRouter, userPb.GetDesignateUsersReq{UserIDs: userIDs}) if err != nil { - return nil, sdkerrs.Warp(err, "GetUsersInfoFromSvr failed") + return nil, sdkerrs.WrapMsg(err, "GetUsersInfoFromSvr failed") } - return util.Batch(ServerUserToLocalUser, resp.UsersInfo), nil + return datautil.Batch(ServerUserToLocalUser, resp.UsersInfo), nil } // GetSingleUserFromSvr retrieves user information from the server. @@ -274,7 +275,7 @@ func (u *User) GetSingleUserFromSvr(ctx context.Context, userID string) (*model_ if len(users) > 0 { return users[0], nil } - return nil, sdkerrs.ErrUserIDNotFound.Wrap(fmt.Sprintf("getSelfUserInfo failed, userID: %s not exist", userID)) + return nil, sdkerrs.ErrUserIDNotFound.WrapMsg(fmt.Sprintf("getSelfUserInfo failed, userID: %s not exist", userID)) } // getSelfUserInfo retrieves the user's information. diff --git a/internal/util/conversion.go b/internal/util/conversion.go deleted file mode 100644 index d0ce7795e..000000000 --- a/internal/util/conversion.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright © 2023 OpenIM SDK. 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 util - -func Batch[T any, V any](fn func(T) V, ts []T) []V { - if ts == nil { - return nil - } - res := make([]V, 0, len(ts)) - for i := range ts { - res = append(res, fn(ts[i])) - } - return res -} diff --git a/internal/util/notice.go b/internal/util/notice.go index 085a4b9c7..06ec7f187 100644 --- a/internal/util/notice.go +++ b/internal/util/notice.go @@ -14,21 +14,15 @@ package util -import ( - "context" - "encoding/json" - "github.com/openimsdk/openim-sdk-core/v3/pkg/syncer" -) - -func NoticeChange[T any](fn func(data string)) func(ctx context.Context, state int, value T) error { - return func(ctx context.Context, state int, value T) error { - if state != syncer.Unchanged { - data, err := json.Marshal(value) - if err != nil { - return err - } - fn(string(data)) - } - return nil - } -} +//func NoticeChange[T any](fn func(data string)) func(ctx context.Context, state int, value T) error { +// return func(ctx context.Context, state int, value T) error { +// if state != syncer.Unchanged { +// data, err := json.Marshal(value) +// if err != nil { +// return err +// } +// fn(string(data)) +// } +// return nil +// } +//} diff --git a/internal/util/post.go b/internal/util/post.go index fcf48b391..49414546a 100644 --- a/internal/util/post.go +++ b/internal/util/post.go @@ -20,13 +20,15 @@ import ( "encoding/json" "fmt" "github.com/openimsdk/openim-sdk-core/v3/pkg/ccontext" + "github.com/openimsdk/openim-sdk-core/v3/pkg/page" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" + "github.com/openimsdk/tools/errs" "io" "net/http" "time" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) // apiClient is a global HTTP client with a timeout of one minute. @@ -54,7 +56,7 @@ func ApiPost(ctx context.Context, api string, req, resp any) (err error) { // Extract operationID from context and validate. operationID, _ := ctx.Value("operationID").(string) if operationID == "" { - err := sdkerrs.ErrArgs.Wrap("call api operationID is empty") + err := sdkerrs.ErrArgs.WrapMsg("call api operationID is empty") log.ZError(ctx, "ApiRequest", err, "type", "ctx not set operationID") return err } @@ -73,7 +75,7 @@ func ApiPost(ctx context.Context, api string, req, resp any) (err error) { reqBody, err := json.Marshal(req) if err != nil { log.ZError(ctx, "ApiRequest", err, "type", "json.Marshal(req) failed") - return sdkerrs.ErrSdkInternal.Wrap("json.Marshal(req) failed " + err.Error()) + return sdkerrs.ErrSdkInternal.WrapMsg("json.Marshal(req) failed " + err.Error()) } // Construct the full API URL and create a new HTTP request with context. @@ -82,7 +84,7 @@ func ApiPost(ctx context.Context, api string, req, resp any) (err error) { request, err := http.NewRequestWithContext(ctx, http.MethodPost, reqUrl, bytes.NewReader(reqBody)) if err != nil { log.ZError(ctx, "ApiRequest", err, "type", "http.NewRequestWithContext failed") - return sdkerrs.ErrSdkInternal.Wrap("sdk http.NewRequestWithContext failed " + err.Error()) + return sdkerrs.ErrSdkInternal.WrapMsg("sdk http.NewRequestWithContext failed " + err.Error()) } // Set headers for the request. @@ -96,7 +98,7 @@ func ApiPost(ctx context.Context, api string, req, resp any) (err error) { response, err := apiClient.Do(request) if err != nil { log.ZError(ctx, "ApiRequest", err, "type", "network error") - return sdkerrs.ErrNetwork.Wrap("ApiPost http.Client.Do failed " + err.Error()) + return sdkerrs.ErrNetwork.WrapMsg("ApiPost http.Client.Do failed " + err.Error()) } // Ensure the response body is closed after processing. @@ -106,7 +108,7 @@ func ApiPost(ctx context.Context, api string, req, resp any) (err error) { respBody, err := io.ReadAll(response.Body) if err != nil { log.ZError(ctx, "ApiResponse", err, "type", "read body", "status", response.Status) - return sdkerrs.ErrSdkInternal.Wrap("io.ReadAll(ApiResponse) failed " + err.Error()) + return sdkerrs.ErrSdkInternal.WrapMsg("io.ReadAll(ApiResponse) failed " + err.Error()) } // Log the response for debugging purposes. @@ -116,7 +118,7 @@ func ApiPost(ctx context.Context, api string, req, resp any) (err error) { var baseApi ApiResponse if err := json.Unmarshal(respBody, &baseApi); err != nil { log.ZError(ctx, "ApiResponse", err, "type", "api code parse") - return sdkerrs.ErrSdkInternal.Wrap(fmt.Sprintf("api %s json.Unmarshal(%q, %T) failed %s", api, string(respBody), &baseApi, err.Error())) + return sdkerrs.ErrSdkInternal.WrapMsg(fmt.Sprintf("api %s json.Unmarshal(%q, %T) failed %s", api, string(respBody), &baseApi, err.Error())) } // Check if the API returned an error code and handle it. @@ -135,7 +137,7 @@ func ApiPost(ctx context.Context, api string, req, resp any) (err error) { // Unmarshal the actual data part of the response into the provided response object. if err := json.Unmarshal(baseApi.Data, resp); err != nil { log.ZError(ctx, "ApiResponse", err, "type", "api data parse", "data", string(baseApi.Data), "bind", fmt.Sprintf("%T", resp)) - return sdkerrs.ErrSdkInternal.Wrap(fmt.Sprintf("json.Unmarshal(%q, %T) failed %s", string(baseApi.Data), resp, err.Error())) + return sdkerrs.ErrSdkInternal.WrapMsg(fmt.Sprintf("json.Unmarshal(%q, %T) failed %s", string(baseApi.Data), resp, err.Error())) } return nil @@ -174,3 +176,64 @@ func GetPageAll[A interface { } return res, nil } + +func GetPageAllWithMaxNum[A interface { + GetPagination() *sdkws.RequestPagination +}, B, C any](ctx context.Context, api string, req A, fn func(resp *B) []C, maxItems int) ([]C, error) { + if req.GetPagination().ShowNumber <= 0 { + req.GetPagination().ShowNumber = 50 + } + var res []C + totalFetched := 0 + for i := int32(0); ; i++ { + req.GetPagination().PageNumber = i + 1 + memberResp, err := CallApi[B](ctx, api, req) + if err != nil { + return nil, err + } + list := fn(memberResp) + res = append(res, list...) + totalFetched += len(list) + if len(list) < int(req.GetPagination().ShowNumber) || (maxItems > 0 && totalFetched >= maxItems) { + break + } + } + if maxItems > 0 && len(res) > maxItems { + res = res[:maxItems] + } + return res, nil +} + +func FetchAndInsertPagedData[RESP, L any](ctx context.Context, api string, req page.PageReq, fn func(resp *RESP) []L, batchInsertFn func(ctx context.Context, items []L) error, + insertFn func(ctx context.Context, item L) error, maxItems int) error { + if req.GetPagination().ShowNumber <= 0 { + req.GetPagination().ShowNumber = 50 + } + var errSingle error + var errList []error + totalFetched := 0 + for i := int32(0); ; i++ { + req.GetPagination().PageNumber = i + 1 + memberResp, err := CallApi[RESP](ctx, api, req) + if err != nil { + return err + } + list := fn(memberResp) + if err := batchInsertFn(ctx, list); err != nil { + for _, item := range list { + errSingle = insertFn(ctx, item) + if errSingle != nil { + errList = append(errList, errs.New(errSingle.Error(), "item", item)) + } + } + } + totalFetched += len(list) + if len(list) < int(req.GetPagination().ShowNumber) || (maxItems > 0 && totalFetched >= maxItems) { + break + } + } + if len(errList) > 0 { + return errs.WrapMsg(errList[0], "batch insert failed due to data exception") + } + return nil +} diff --git a/internal/work_moments/work_moments.go b/internal/work_moments/work_moments.go index 2a38e45f8..2eacd31fe 100644 --- a/internal/work_moments/work_moments.go +++ b/internal/work_moments/work_moments.go @@ -21,7 +21,7 @@ package workMoments // "open_im_sdk/pkg/db/model_struct" // "open_im_sdk/pkg/utils" // -// "github.com/OpenIMSDK/tools/log" +// "github.com/openimsdk/tools/log" //) // //type WorkMoments struct { diff --git a/msgtest/message_test.go b/msgtest/message_test.go index 5ef1a2e78..f4f7c5755 100644 --- a/msgtest/message_test.go +++ b/msgtest/message_test.go @@ -2,11 +2,11 @@ package msgtest import ( "context" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/msgtest/module" "github.com/openimsdk/openim-sdk-core/v3/msgtest/sdk_user_simulator" "github.com/openimsdk/openim-sdk-core/v3/pkg/ccontext" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/log" "testing" ) diff --git a/msgtest/module/api_msg_sender.go b/msgtest/module/api_msg_sender.go index 4b46e62a5..d16596597 100644 --- a/msgtest/module/api_msg_sender.go +++ b/msgtest/module/api_msg_sender.go @@ -6,8 +6,8 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" - "github.com/OpenIMSDK/protocol/msg" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/msg" + "github.com/openimsdk/protocol/sdkws" ) type ApiMsgSender struct { diff --git a/msgtest/module/friend_manager.go b/msgtest/module/friend_manager.go index 4f63b609b..675699f76 100644 --- a/msgtest/module/friend_manager.go +++ b/msgtest/module/friend_manager.go @@ -2,8 +2,7 @@ package module import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" - - "github.com/OpenIMSDK/protocol/friend" + "github.com/openimsdk/protocol/relation" ) type TestFriendManager struct { @@ -11,7 +10,7 @@ type TestFriendManager struct { } func (t *TestFriendManager) ImportFriends(ownerUserID string, friendUserIDs []string) error { - req := &friend.ImportFriendReq{ + req := &relation.ImportFriendReq{ OwnerUserID: ownerUserID, FriendUserIDs: friendUserIDs, } diff --git a/msgtest/module/group_manager.go b/msgtest/module/group_manager.go index 22cf6bfcd..3dc9033cf 100644 --- a/msgtest/module/group_manager.go +++ b/msgtest/module/group_manager.go @@ -6,8 +6,8 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "time" - "github.com/OpenIMSDK/protocol/group" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/group" + "github.com/openimsdk/protocol/sdkws" ) type TestGroupManager struct { diff --git a/msgtest/module/manager.go b/msgtest/module/manager.go index 4c18455cf..d99dcaf0f 100644 --- a/msgtest/module/manager.go +++ b/msgtest/module/manager.go @@ -5,14 +5,14 @@ import ( "context" "encoding/json" "fmt" - authPB "github.com/OpenIMSDK/protocol/auth" - "github.com/OpenIMSDK/protocol/msg" - "github.com/OpenIMSDK/tools/log" - "github.com/OpenIMSDK/tools/mcontext" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + authPB "github.com/openimsdk/protocol/auth" + "github.com/openimsdk/protocol/msg" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/mcontext" "io" "net/http" ) diff --git a/msgtest/module/msg_sender.go b/msgtest/module/msg_sender.go index 7460b5e84..8878766ac 100644 --- a/msgtest/module/msg_sender.go +++ b/msgtest/module/msg_sender.go @@ -12,9 +12,9 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" "time" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" - "github.com/OpenIMSDK/tools/mcontext" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/mcontext" ) type SendMsgUser struct { diff --git a/msgtest/module/user_manager.go b/msgtest/module/user_manager.go index 2af08b957..da98bf40b 100644 --- a/msgtest/module/user_manager.go +++ b/msgtest/module/user_manager.go @@ -5,8 +5,8 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "time" - "github.com/OpenIMSDK/protocol/sdkws" - userPB "github.com/OpenIMSDK/protocol/user" + "github.com/openimsdk/protocol/sdkws" + userPB "github.com/openimsdk/protocol/user" ) type TestUserManager struct { diff --git a/msgtest/pressure_test.go b/msgtest/pressure_test.go index 835128c24..d0cf5af6d 100644 --- a/msgtest/pressure_test.go +++ b/msgtest/pressure_test.go @@ -4,13 +4,14 @@ import ( "context" "flag" "fmt" - "github.com/openimsdk/openim-sdk-core/v3/msgtest/module" - "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" "sync" "testing" "time" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/openim-sdk-core/v3/msgtest/module" + "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + + "github.com/openimsdk/tools/log" ) const ( @@ -56,7 +57,7 @@ func init() { InitWithFlag() if err := log.InitFromConfig("sdk.log", "sdk", 4, - true, false, "./chat_log", 2, 24); err != nil { + true, false, "./chat_log", 2, 24, "v1.0.0"); err != nil { panic(err) } } diff --git a/msgtest/sdk_user_simulator/listener.go b/msgtest/sdk_user_simulator/listener.go index 412ae384b..7f652ed51 100644 --- a/msgtest/sdk_user_simulator/listener.go +++ b/msgtest/sdk_user_simulator/listener.go @@ -210,6 +210,8 @@ func (testGroupListener) OnGroupDismissed(callbackInfo string) { type testConnListener struct { } +func (t *testConnListener) OnUserTokenInvalid(errMsg string) {} + func (t *testConnListener) OnUserTokenExpired() { } diff --git a/msgtest/sdk_user_simulator/user.go b/msgtest/sdk_user_simulator/user.go index e0c8a66b5..a92a1cc87 100644 --- a/msgtest/sdk_user_simulator/user.go +++ b/msgtest/sdk_user_simulator/user.go @@ -3,12 +3,13 @@ package sdk_user_simulator import ( "context" "fmt" - "github.com/OpenIMSDK/tools/log" - "github.com/openimsdk/openim-sdk-core/v3/internal/login" + "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" "github.com/openimsdk/openim-sdk-core/v3/pkg/ccontext" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/log" + "go.etcd.io/etcd/api/v3/version" ) var ( @@ -33,7 +34,7 @@ func GetRelativeServerTime() int64 { } func InitSDKAndLogin(userID, token string) error { - userForSDK := login.NewLoginMgr() + userForSDK := open_im_sdk.NewLoginMgr() var cf sdk_struct.IMConfig cf.ApiAddr = APIADDR cf.PlatformID = int32(PLATFORMID) @@ -45,7 +46,7 @@ func InitSDKAndLogin(userID, token string) error { cf.LogFilePath = "" var testConnListener testConnListener userForSDK.InitSDK(cf, &testConnListener) - if err := log.InitFromConfig(userID+"_open-im-sdk-core", "", int(LogLevel), true, false, cf.DataDir, 0, 24); err != nil { + if err := log.InitFromConfig(userID+"_open-im-sdk-core", "", int(LogLevel), true, false, cf.DataDir, 0, 24, version.Version); err != nil { return err } ctx := ccontext.WithOperationID(userForSDK.BaseCtx(), utils.OperationIDGenerator()) @@ -58,7 +59,7 @@ func InitSDKAndLogin(userID, token string) error { return nil } -func SetListener(userForSDK *login.LoginMgr, userID string) { +func SetListener(userForSDK *open_im_sdk.LoginMgr, userID string) { var testConversation conversationCallBack userForSDK.SetConversationListener(&testConversation) diff --git a/open_im_sdk/apicb.go b/open_im_sdk/apicb.go index 392eee1da..c36b3126b 100644 --- a/open_im_sdk/apicb.go +++ b/open_im_sdk/apicb.go @@ -2,10 +2,10 @@ package open_im_sdk import ( "context" - "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/common" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" "sync/atomic" ) @@ -36,18 +36,14 @@ func (c *apiErrCallback) OnError(ctx context.Context, err error) { _ = common.TriggerCmdLogOut(ctx, c.loginMgrCh) } case - errs.TokenInvalidError, errs.TokenMalformedError, errs.TokenNotValidYetError, - errs.TokenUnknownError, - errs.TokenNotExistError: + errs.TokenUnknownError: if atomic.CompareAndSwapInt32(&c.tokenInvalidState, 0, 1) { log.ZError(ctx, "OnUserTokenInvalid callback", err) c.listener.OnUserTokenInvalid(err.Error()) _ = common.TriggerCmdLogOut(ctx, c.loginMgrCh) } - - case errs.TokenKickedError: if atomic.CompareAndSwapInt32(&c.kickedOfflineState, 0, 1) { log.ZError(ctx, "OnKickedOffline callback", err) c.listener.OnKickedOffline() diff --git a/open_im_sdk/caller.go b/open_im_sdk/caller.go index f638b702a..484aa080f 100644 --- a/open_im_sdk/caller.go +++ b/open_im_sdk/caller.go @@ -27,9 +27,9 @@ import ( "runtime/debug" "time" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" - "github.com/OpenIMSDK/tools/errs" + "github.com/openimsdk/tools/errs" ) func isNumeric(kind reflect.Kind) bool { @@ -91,10 +91,10 @@ func call_(operationID string, fn any, args ...any) (res any, err error) { funcPtr := reflect.ValueOf(fn).Pointer() funcName := runtime.FuncForPC(funcPtr).Name() if operationID == "" { - return nil, sdkerrs.ErrArgs.Wrap("call function operationID is empty") + return nil, sdkerrs.ErrArgs.WrapMsg("call function operationID is empty") } if err := CheckResourceLoad(UserForSDK, funcName); err != nil { - return nil, sdkerrs.ErrResourceLoad.Wrap("not load resource") + return nil, sdkerrs.ErrResourceLoad.WrapMsg("not load resource") } ctx := ccontext.WithOperationID(UserForSDK.BaseCtx(), operationID) defer func(start time.Time) { @@ -115,12 +115,12 @@ func call_(operationID string, fn any, args ...any) (res any, err error) { log.ZInfo(ctx, "func call req", "function name", funcName, "args", args) fnv := reflect.ValueOf(fn) if fnv.Kind() != reflect.Func { - return nil, sdkerrs.ErrSdkInternal.Wrap(fmt.Sprintf("call function fn is not function, is %T", fn)) + return nil, sdkerrs.ErrSdkInternal.WrapMsg(fmt.Sprintf("call function fn is not function, is %T", fn)) } fnt := fnv.Type() nin := fnt.NumIn() if len(args)+1 != nin { - return nil, sdkerrs.ErrSdkInternal.Wrap(fmt.Sprintf("go code error: fn in args num is not match")) + return nil, sdkerrs.ErrSdkInternal.WrapMsg(fmt.Sprintf("go code error: fn in args num is not match")) } ins := make([]reflect.Value, 0, nin) ins = append(ins, reflect.ValueOf(ctx)) @@ -141,7 +141,7 @@ func call_(operationID string, fn any, args ...any) (res any, err error) { case reflect.Struct, reflect.Slice, reflect.Array, reflect.Map: v := reflect.New(inFnField) if err := json.Unmarshal([]byte(args[i].(string)), v.Interface()); err != nil { - return nil, sdkerrs.ErrSdkInternal.Wrap(fmt.Sprintf("go call json.Unmarshal error: %s", err)) + return nil, sdkerrs.ErrSdkInternal.WrapMsg(fmt.Sprintf("go call json.Unmarshal error: %s", err)) } if ptr == 0 { v = v.Elem() @@ -162,7 +162,7 @@ func call_(operationID string, fn any, args ...any) (res any, err error) { // ins = append(ins, reflect.ValueOf(v)) // continue //} - return nil, sdkerrs.ErrSdkInternal.Wrap(fmt.Sprintf("go code error: fn in args type is not match")) + return nil, sdkerrs.ErrSdkInternal.WrapMsg(fmt.Sprintf("go code error: fn in args type is not match")) } outs := fnv.Call(ins) if len(outs) == 0 { @@ -361,7 +361,7 @@ func messageCall_(callback open_im_sdk_callback.SendMsgCallBack, operationID str } }() if operationID == "" { - callback.OnError(sdkerrs.ArgsError, sdkerrs.ErrArgs.Wrap("operationID is empty").Error()) + callback.OnError(sdkerrs.ArgsError, sdkerrs.ErrArgs.WrapMsg("operationID is empty").Error()) return } if err := CheckResourceLoad(UserForSDK, ""); err != nil { diff --git a/open_im_sdk/em.go b/open_im_sdk/em.go index de39cd358..e7f0e7f8b 100644 --- a/open_im_sdk/em.go +++ b/open_im_sdk/em.go @@ -17,8 +17,8 @@ package open_im_sdk import ( "context" "errors" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback" + "github.com/openimsdk/tools/log" ) var ErrNotImplemented = errors.New("not set listener") @@ -142,17 +142,21 @@ func newEmptyConversationListener(ctx context.Context) open_im_sdk_callback.OnCo return &emptyConversationListener{ctx: ctx} } -func (e *emptyConversationListener) OnSyncServerStart() { - +func (e *emptyConversationListener) OnSyncServerStart(reinstalled bool) { log.ZWarn(e.ctx, "ConversationListener is not implemented", nil) } -func (e *emptyConversationListener) OnSyncServerFinish() { +func (e *emptyConversationListener) OnSyncServerProgress(progress int) { + log.ZWarn(e.ctx, "ConversationListener is not implemented", nil, + "progress", progress) +} + +func (e *emptyConversationListener) OnSyncServerFinish(reinstalled bool) { log.ZWarn(e.ctx, "ConversationListener is not implemented", nil) } -func (e *emptyConversationListener) OnSyncServerFailed() { +func (e *emptyConversationListener) OnSyncServerFailed(reinstalled bool) { log.ZWarn(e.ctx, "ConversationListener is not implemented", nil) } diff --git a/open_im_sdk/friend.go b/open_im_sdk/friend.go index 575600ef3..a7f6bdb8c 100644 --- a/open_im_sdk/friend.go +++ b/open_im_sdk/friend.go @@ -28,6 +28,10 @@ func GetFriendListPage(callback open_im_sdk_callback.Base, operationID string, o call(callback, operationID, UserForSDK.Friend().GetFriendListPage, offset, count) } +func GetFriendListPageV2(callback open_im_sdk_callback.Base, operationID string, offset int32, count int32) { + call(callback, operationID, UserForSDK.Friend().GetFriendListPageV2, offset, count) +} + func SearchFriends(callback open_im_sdk_callback.Base, operationID string, searchParam string) { call(callback, operationID, UserForSDK.Friend().SearchFriends, searchParam) } diff --git a/open_im_sdk/group.go b/open_im_sdk/group.go index 3d614ce19..db82fa71b 100644 --- a/open_im_sdk/group.go +++ b/open_im_sdk/group.go @@ -36,6 +36,18 @@ func DismissGroup(callback open_im_sdk_callback.Base, operationID string, groupI call(callback, operationID, UserForSDK.Group().DismissGroup, groupID) } +func SetGroupVerification(callback open_im_sdk_callback.Base, operationID string, groupID string, verification int32) { + call(callback, operationID, UserForSDK.Group().SetGroupVerification, groupID, verification) +} + +func SetGroupApplyMemberFriend(callback open_im_sdk_callback.Base, operationID string, groupID string, rule int32) { + call(callback, operationID, UserForSDK.Group().SetGroupApplyMemberFriend, groupID, rule) +} + +func SetGroupLookMemberInfo(callback open_im_sdk_callback.Base, operationID string, groupID string, rule int32) { + call(callback, operationID, UserForSDK.Group().SetGroupLookMemberInfo, groupID, rule) +} + func ChangeGroupMute(callback open_im_sdk_callback.Base, operationID string, groupID string, isMute bool) { call(callback, operationID, UserForSDK.Group().ChangeGroupMute, groupID, isMute) } @@ -44,44 +56,48 @@ func ChangeGroupMemberMute(callback open_im_sdk_callback.Base, operationID strin call(callback, operationID, UserForSDK.Group().ChangeGroupMemberMute, groupID, userID, mutedSeconds) } -func SetGroupMemberRoleLevel(callback open_im_sdk_callback.Base, operationID string, groupID string, userID string, roleLevel int) { - call(callback, operationID, UserForSDK.Group().SetGroupMemberRoleLevel, groupID, userID, roleLevel) +func TransferGroupOwner(callback open_im_sdk_callback.Base, operationID string, groupID string, newOwnerUserID string) { + call(callback, operationID, UserForSDK.Group().TransferGroupOwner, groupID, newOwnerUserID) } -func SetGroupMemberInfo(callback open_im_sdk_callback.Base, operationID string, groupMemberInfo string) { - call(callback, operationID, UserForSDK.Group().SetGroupMemberInfo, groupMemberInfo) +func KickGroupMember(callback open_im_sdk_callback.Base, operationID string, groupID string, reason string, userIDList string) { + call(callback, operationID, UserForSDK.Group().KickGroupMember, groupID, reason, userIDList) } -func GetJoinedGroupList(callback open_im_sdk_callback.Base, operationID string) { - call(callback, operationID, UserForSDK.Group().GetJoinedGroupList) +func SetGroupInfo(callback open_im_sdk_callback.Base, operationID string, groupInfo string) { + call(callback, operationID, UserForSDK.Group().SetGroupInfo, groupInfo) } -func GetSpecifiedGroupsInfo(callback open_im_sdk_callback.Base, operationID string, groupIDList string) { - call(callback, operationID, UserForSDK.Group().GetSpecifiedGroupsInfo, groupIDList) +func SetGroupMemberInfo(callback open_im_sdk_callback.Base, operationID string, groupMemberInfo string) { + call(callback, operationID, UserForSDK.Group().SetGroupMemberInfo, groupMemberInfo) } -func SearchGroups(callback open_im_sdk_callback.Base, operationID string, searchParam string) { - call(callback, operationID, UserForSDK.Group().SearchGroups, searchParam) +func SetGroupMemberRoleLevel(callback open_im_sdk_callback.Base, operationID string, groupID string, userID string, roleLevel int) { + call(callback, operationID, UserForSDK.Group().SetGroupMemberRoleLevel, groupID, userID, roleLevel) } -func SetGroupInfo(callback open_im_sdk_callback.Base, operationID string, groupInfo string) { - call(callback, operationID, UserForSDK.Group().SetGroupInfo, groupInfo) +func SetGroupMemberNickname(callback open_im_sdk_callback.Base, operationID string, groupID string, userID string, groupMemberNickname string) { + call(callback, operationID, UserForSDK.Group().SetGroupMemberNickname, groupID, userID, groupMemberNickname) } -func SetGroupVerification(callback open_im_sdk_callback.Base, operationID string, groupID string, verification int32) { - call(callback, operationID, UserForSDK.Group().SetGroupVerification, groupID, verification) +func GetJoinedGroupList(callback open_im_sdk_callback.Base, operationID string) { + call(callback, operationID, UserForSDK.Group().GetJoinedGroupList) } -func SetGroupLookMemberInfo(callback open_im_sdk_callback.Base, operationID string, groupID string, rule int32) { - call(callback, operationID, UserForSDK.Group().SetGroupLookMemberInfo, groupID, rule) +func GetJoinedGroupListPage(callback open_im_sdk_callback.Base, operationID string, offset, count int32) { + call(callback, operationID, UserForSDK.Group().GetJoinedGroupListPage, offset, count) } -func SetGroupApplyMemberFriend(callback open_im_sdk_callback.Base, operationID string, groupID string, rule int32) { - call(callback, operationID, UserForSDK.Group().SetGroupApplyMemberFriend, groupID, rule) +func GetJoinedGroupListPageV2(callback open_im_sdk_callback.Base, operationID string, offset, count int32) { + call(callback, operationID, UserForSDK.Group().GetJoinedGroupListPageV2, offset, count) } -func GetGroupMemberList(callback open_im_sdk_callback.Base, operationID string, groupID string, filter int32, offset int32, count int32) { - call(callback, operationID, UserForSDK.Group().GetGroupMemberList, groupID, filter, offset, count) +func GetSpecifiedGroupsInfo(callback open_im_sdk_callback.Base, operationID string, groupIDList string) { + call(callback, operationID, UserForSDK.Group().GetSpecifiedGroupsInfo, groupIDList) +} + +func SearchGroups(callback open_im_sdk_callback.Base, operationID string, searchParam string) { + call(callback, operationID, UserForSDK.Group().SearchGroups, searchParam) } func GetGroupMemberOwnerAndAdmin(callback open_im_sdk_callback.Base, operationID string, groupID string) { @@ -92,20 +108,20 @@ func GetGroupMemberListByJoinTimeFilter(callback open_im_sdk_callback.Base, oper call(callback, operationID, UserForSDK.Group().GetGroupMemberListByJoinTimeFilter, groupID, offset, count, joinTimeBegin, joinTimeEnd, filterUserIDList) } -func GetSpecifiedGroupMembersInfo(callback open_im_sdk_callback.Base, operationID string, groupID string, userIDList string) { - call(callback, operationID, UserForSDK.Group().GetSpecifiedGroupMembersInfo, groupID, userIDList) +func GetGroupMemberListByJoinTimeFilterV2(callback open_im_sdk_callback.Base, operationID string, groupID string, offset int32, count int32, joinTimeBegin int64, joinTimeEnd int64, filterUserIDList string) { + call(callback, operationID, UserForSDK.Group().GetGroupMemberListByJoinTimeFilterV2, groupID, offset, count, joinTimeBegin, joinTimeEnd, filterUserIDList) } -func KickGroupMember(callback open_im_sdk_callback.Base, operationID string, groupID string, reason string, userIDList string) { - call(callback, operationID, UserForSDK.Group().KickGroupMember, groupID, reason, userIDList) +func GetSpecifiedGroupMembersInfo(callback open_im_sdk_callback.Base, operationID string, groupID string, userIDList string) { + call(callback, operationID, UserForSDK.Group().GetSpecifiedGroupMembersInfo, groupID, userIDList) } -func TransferGroupOwner(callback open_im_sdk_callback.Base, operationID string, groupID string, newOwnerUserID string) { - call(callback, operationID, UserForSDK.Group().TransferGroupOwner, groupID, newOwnerUserID) +func GetGroupMemberList(callback open_im_sdk_callback.Base, operationID string, groupID string, filter int32, offset int32, count int32) { + call(callback, operationID, UserForSDK.Group().GetGroupMemberList, groupID, filter, offset, count) } -func InviteUserToGroup(callback open_im_sdk_callback.Base, operationID string, groupID string, reason string, userIDList string) { - call(callback, operationID, UserForSDK.Group().InviteUserToGroup, groupID, reason, userIDList) +func GetGroupMemberListV2(callback open_im_sdk_callback.Base, operationID string, groupID string, filter int32, offset int32, count int32) { + call(callback, operationID, UserForSDK.Group().GetGroupMemberListV2, groupID, filter, offset, count) } func GetGroupApplicationListAsRecipient(callback open_im_sdk_callback.Base, operationID string) { @@ -116,22 +132,22 @@ func GetGroupApplicationListAsApplicant(callback open_im_sdk_callback.Base, oper call(callback, operationID, UserForSDK.Group().GetGroupApplicationListAsApplicant) } -func AcceptGroupApplication(callback open_im_sdk_callback.Base, operationID string, groupID string, fromUserID string, handleMsg string) { - call(callback, operationID, UserForSDK.Group().AcceptGroupApplication, groupID, fromUserID, handleMsg) +func SearchGroupMembers(callback open_im_sdk_callback.Base, operationID string, searchParam string) { + call(callback, operationID, UserForSDK.Group().SearchGroupMembers, searchParam) } -func RefuseGroupApplication(callback open_im_sdk_callback.Base, operationID string, groupID string, fromUserID string, handleMsg string) { - call(callback, operationID, UserForSDK.Group().RefuseGroupApplication, groupID, fromUserID, handleMsg) +func IsJoinGroup(callback open_im_sdk_callback.Base, operationID string, groupID string) { + call(callback, operationID, UserForSDK.Group().IsJoinGroup, groupID) } -func SetGroupMemberNickname(callback open_im_sdk_callback.Base, operationID string, groupID string, userID string, groupMemberNickname string) { - call(callback, operationID, UserForSDK.Group().SetGroupMemberNickname, groupID, userID, groupMemberNickname) +func InviteUserToGroup(callback open_im_sdk_callback.Base, operationID string, groupID string, reason string, userIDList string) { + call(callback, operationID, UserForSDK.Group().InviteUserToGroup, groupID, reason, userIDList) } -func SearchGroupMembers(callback open_im_sdk_callback.Base, operationID string, searchParam string) { - call(callback, operationID, UserForSDK.Group().SearchGroupMembers, searchParam) +func AcceptGroupApplication(callback open_im_sdk_callback.Base, operationID string, groupID string, fromUserID string, handleMsg string) { + call(callback, operationID, UserForSDK.Group().AcceptGroupApplication, groupID, fromUserID, handleMsg) } -func IsJoinGroup(callback open_im_sdk_callback.Base, operationID string, groupID string) { - call(callback, operationID, UserForSDK.Group().IsJoinGroup, groupID) +func RefuseGroupApplication(callback open_im_sdk_callback.Base, operationID string, groupID string, fromUserID string, handleMsg string) { + call(callback, operationID, UserForSDK.Group().RefuseGroupApplication, groupID, fromUserID, handleMsg) } diff --git a/open_im_sdk/init_login.go b/open_im_sdk/init_login.go index 20bb1f79d..cb95e4675 100644 --- a/open_im_sdk/init_login.go +++ b/open_im_sdk/init_login.go @@ -22,10 +22,11 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/ccontext" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "go.etcd.io/etcd/api/v3/version" "strings" - "github.com/OpenIMSDK/tools/log" - "github.com/OpenIMSDK/tools/mcontext" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/mcontext" ) func GetSdkVersion() string { @@ -54,7 +55,7 @@ func InitSDK(listener open_im_sdk_callback.OnConnListener, operationID string, c if configArgs.PlatformID == 0 { return false } - if err := log.InitFromConfig("open-im-sdk-core", "", int(configArgs.LogLevel), configArgs.IsLogStandardOutput, false, configArgs.LogFilePath, rotateCount, rotationTime); err != nil { + if err := log.InitFromConfig("open-im-sdk-core", "", int(configArgs.LogLevel), configArgs.IsLogStandardOutput, false, configArgs.LogFilePath, rotateCount, rotationTime, version.Version); err != nil { fmt.Println(operationID, "log init failed ", err.Error()) } fmt.Println("init log success") diff --git a/open_im_sdk/userRelated.go b/open_im_sdk/userRelated.go index 9d77afae7..c8110431c 100644 --- a/open_im_sdk/userRelated.go +++ b/open_im_sdk/userRelated.go @@ -19,9 +19,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/OpenIMSDK/protocol/push" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/internal/business" conv "github.com/openimsdk/openim-sdk-core/v3/internal/conversation_msg" "github.com/openimsdk/openim-sdk-core/v3/internal/file" @@ -41,6 +38,9 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/protocol/push" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" "strings" "sync" "time" @@ -335,7 +335,7 @@ func (u *LoginMgr) login(ctx context.Context, userID, token string) error { var err error u.db, err = db.NewDataBase(ctx, userID, u.info.DataDir, int(u.info.LogLevel)) if err != nil { - return sdkerrs.ErrSdkInternal.Wrap("init database " + err.Error()) + return sdkerrs.ErrSdkInternal.WrapMsg("init database " + err.Error()) } u.checkSendingMessage(ctx) log.ZDebug(ctx, "NewDataBase ok", "userID", userID, "dataDir", u.info.DataDir, "login cost time", time.Since(t1)) @@ -380,7 +380,6 @@ func (u *LoginMgr) run(ctx context.Context) { u.longConnMgr.Run(ctx) go u.msgSyncer.DoListener(ctx) go common.DoListener(u.conversation, u.ctx) - go u.group.DeleteGroupAndMemberInfo(ctx) go u.logoutListener(ctx) } diff --git a/open_im_sdk_callback/callback_client.go b/open_im_sdk_callback/callback_client.go index 27ba5e802..0a003ce4b 100644 --- a/open_im_sdk_callback/callback_client.go +++ b/open_im_sdk_callback/callback_client.go @@ -57,10 +57,10 @@ type OnFriendshipListener interface { OnBlackDeleted(blackInfo string) } type OnConversationListener interface { - OnSyncServerStart() - OnSyncServerFinish() - //OnSyncServerProgress(progress int) - OnSyncServerFailed() + OnSyncServerStart(reinstalled bool) + OnSyncServerFinish(reinstalled bool) + OnSyncServerProgress(progress int) + OnSyncServerFailed(reinstalled bool) OnNewConversation(conversationList string) OnConversationChanged(conversationList string) OnTotalUnreadMessageCountChanged(totalUnreadCount int32) @@ -150,3 +150,9 @@ type UploadFileCallback interface { type UploadLogProgress interface { OnProgress(current int64, size int64) } + +type AppDataSyncListener interface { + OnAppDataSyncStart() + OnAppDataSyncProgress(progress int) + OnAppDataSyncFinish() +} diff --git a/open_im_sdk_callback/callback_go_sdk.go b/open_im_sdk_callback/callback_go_sdk.go index ad9d778b8..b38005e6d 100644 --- a/open_im_sdk_callback/callback_go_sdk.go +++ b/open_im_sdk_callback/callback_go_sdk.go @@ -19,7 +19,7 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" ) type OnFriendshipListenerSdk interface { diff --git a/pkg/ccontext/context.go b/pkg/ccontext/context.go index 7c012899d..67855a596 100644 --- a/pkg/ccontext/context.go +++ b/pkg/ccontext/context.go @@ -20,7 +20,7 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" - "github.com/OpenIMSDK/tools/mcontext" + "github.com/openimsdk/tools/mcontext" ) const ( diff --git a/pkg/common/trigger_channel.go b/pkg/common/trigger_channel.go index 5d0ca4f0a..6ca38db53 100644 --- a/pkg/common/trigger_channel.go +++ b/pkg/common/trigger_channel.go @@ -22,9 +22,9 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" "time" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" ) func TriggerCmdJoinedSuperGroup(cmd sdk_struct.CmdJoinedSuperGroup, joinedSuperGroupCh chan Cmd2Value) error { @@ -44,22 +44,12 @@ func TriggerCmdNewMsgCome(ctx context.Context, msg sdk_struct.CmdNewMsgComeToCon return sendCmd(conversationCh, c2v, 100) } -func TriggerCmdSuperGroupMsgCome(msg sdk_struct.CmdNewMsgComeToConversation, conversationCh chan Cmd2Value) error { - if conversationCh == nil { - return utils.Wrap(errors.New("ch == nil"), "") - } - - c2v := Cmd2Value{Cmd: constant.CmdSuperGroupMsgCome, Value: msg} - return sendCmd(conversationCh, c2v, 100) -} - -func TriggerCmdNotification(ctx context.Context, msg sdk_struct.CmdNewMsgComeToConversation, conversationCh chan Cmd2Value) error { - if conversationCh == nil { - return utils.Wrap(errors.New("ch == nil"), "") - } - +func TriggerCmdNotification(ctx context.Context, msg sdk_struct.CmdNewMsgComeToConversation, conversationCh chan Cmd2Value) { c2v := Cmd2Value{Cmd: constant.CmdNotification, Value: msg, Ctx: ctx} - return sendCmd(conversationCh, c2v, 100) + err := sendCmd(conversationCh, c2v, 100) + if err != nil { + log.ZWarn(ctx, "TriggerCmdNotification error", err, "msg", msg) + } } func TriggerCmdWakeUp(ch chan Cmd2Value) error { @@ -70,18 +60,6 @@ func TriggerCmdWakeUp(ch chan Cmd2Value) error { return sendCmd(ch, c2v, 100) } -func TriggerCmdDeleteConversationAndMessage(sourceID, conversationID string, sessionType int, conversationCh chan Cmd2Value) error { - if conversationCh == nil { - return utils.Wrap(errors.New("ch == nil"), "") - } - c2v := Cmd2Value{ - Cmd: constant.CmdDeleteConversation, - Value: DeleteConNode{SourceID: sourceID, ConversationID: conversationID, SessionType: sessionType}, - } - - return sendCmd(conversationCh, c2v, 100) -} - func TriggerCmdSyncReactionExtensions(node SyncReactionExtensionsNode, conversationCh chan Cmd2Value) error { if conversationCh == nil { return utils.Wrap(errors.New("ch == nil"), "") diff --git a/pkg/constant/constant.go b/pkg/constant/constant.go index e46f4809a..aaa9068ce 100644 --- a/pkg/constant/constant.go +++ b/pkg/constant/constant.go @@ -403,6 +403,8 @@ const ( MsgSyncProcessing = 1002 // MsgSyncEnd = 1003 // MsgSyncFailed = 1004 + AppDataSyncStart = 1005 + AppDataSyncFinish = 1006 ) const ( diff --git a/pkg/constant/server_api_router.go b/pkg/constant/server_api_router.go index ae0875f10..b512dcc22 100644 --- a/pkg/constant/server_api_router.go +++ b/pkg/constant/server_api_router.go @@ -45,6 +45,8 @@ const ( AddFriendResponse = "/friend/add_friend_response" SetFriendRemark = "/friend/set_friend_remark" UpdateFriends = "/friend/update_friends" + GetIncrementalFriends = "/friend/get_incremental_friends" + GetFullFriendUserIDs = "/friend/get_full_friend_user_ids" AddBlackRouter = "/friend/add_black" RemoveBlackRouter = "/friend/remove_black" @@ -103,6 +105,11 @@ const ( SetGroupMemberNicknameRouter = RouterGroup + "/set_group_member_nickname" SetGroupMemberInfoRouter = RouterGroup + "/set_group_member_info" GetGroupAbstractInfoRouter = RouterGroup + "/get_group_abstract_info" + //SearchGroupMember = RouterGroup + "/search_group_member" + GetIncrementalJoinGroup = RouterGroup + "/get_incremental_join_group" + GetIncrementalGroupMemberBatch = RouterGroup + "/get_incremental_group_member_batch" + GetFullJoinedGroupIDs = RouterGroup + "/get_full_join_group_ids" + GetFullGroupMemberUserIDs = RouterGroup + "/get_full_group_member_user_ids" SetReceiveMessageOptRouter = "/conversation/set_receive_message_opt" GetReceiveMessageOptRouter = "/conversation/get_receive_message_opt" diff --git a/pkg/datafetcher/datafetcher.go b/pkg/datafetcher/datafetcher.go new file mode 100644 index 000000000..89f309951 --- /dev/null +++ b/pkg/datafetcher/datafetcher.go @@ -0,0 +1,185 @@ +package datafetcher + +import ( + "context" + + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/utils/datautil" +) + +// DataFetcher is a struct that handles data synchronization +type DataFetcher[T any] struct { + db db_interface.VersionSyncModel + TableName string + EntityID string + Key func(T) string + batchInsert func(ctx context.Context, servers []T) error + FetchFromLocal FetchDataFunc[T] + fetchFromServer FetchFromServerFunc[T] +} + +// FetchDataFunc is a function type for fetching data +type FetchDataFunc[T any] func(ctx context.Context, uids []string) ([]T, error) + +// FetchFromServerFunc is a function type for fetching data from server +type FetchFromServerFunc[T any] func(ctx context.Context, uids []string) ([]T, error) + +// NewDataFetcher creates a new NewDataFetcher +func NewDataFetcher[T any](db db_interface.VersionSyncModel, tableName string, entityID string, key func(T) string, + batchInsert func(ctx context.Context, servers []T) error, fetchFromLocal FetchDataFunc[T], fetchFromServer FetchFromServerFunc[T]) *DataFetcher[T] { + return &DataFetcher[T]{ + db: db, + TableName: tableName, + EntityID: entityID, + Key: key, + batchInsert: batchInsert, + FetchFromLocal: fetchFromLocal, + fetchFromServer: fetchFromServer, + } +} + +// FetchWithPagination fetches data with pagination and fills missing data from server +func (ds *DataFetcher[T]) FetchWithPagination(ctx context.Context, offset, limit int) ([]T, error) { + versionInfo, err := ds.db.GetVersionSync(ctx, ds.TableName, ds.EntityID) + if err != nil { + return nil, err + } + + if offset > len(versionInfo.UIDList) { + return nil, errs.New("offset exceeds the length of the UID list").Wrap() + } + + end := offset + limit + if end > len(versionInfo.UIDList) { + end = len(versionInfo.UIDList) + } + + paginatedUIDs := versionInfo.UIDList[offset:end] + + localData, err := ds.FetchMissingAndFillLocal(ctx, paginatedUIDs) + if err != nil { + return nil, err + } + + return localData, nil +} + +// FetchMissingAndFillLocal fetches missing data from server and fills local database +func (ds *DataFetcher[T]) FetchMissingAndFillLocal(ctx context.Context, uids []string) ([]T, error) { + localData, err := ds.FetchFromLocal(ctx, uids) + if err != nil { + return nil, err + } + + localUIDSet := datautil.SliceSetAny(localData, ds.Key) + + var missingUIDs []string + for _, uid := range uids { + if _, found := localUIDSet[uid]; !found { + missingUIDs = append(missingUIDs, uid) + } + } + + if len(missingUIDs) > 0 { + serverData, err := ds.fetchFromServer(ctx, missingUIDs) + if err != nil { + return nil, err + } + if len(serverData) > 0 { + if err := ds.batchInsert(ctx, serverData); err != nil { + return nil, err + } + + localData = append(localData, serverData...) + } + + } + + return localData, nil +} + +// FetchMissingAndCombineLocal fetches missing data from the server and combines it with local data without inserting it into the local database +func (ds *DataFetcher[T]) FetchMissingAndCombineLocal(ctx context.Context, uids []string) ([]T, error) { + localData, err := ds.FetchFromLocal(ctx, uids) + if err != nil { + return nil, err + } + + localUIDSet := datautil.SliceSetAny(localData, ds.Key) + + var missingUIDs []string + for _, uid := range uids { + if _, found := localUIDSet[uid]; !found { + missingUIDs = append(missingUIDs, uid) + } + } + + if len(missingUIDs) > 0 { + serverData, err := ds.fetchFromServer(ctx, missingUIDs) + if err != nil { + return nil, err + } + // Combine local data with server data + localData = append(localData, serverData...) + } + + return localData, nil +} + +func (ds *DataFetcher[T]) FetchWithPaginationV2(ctx context.Context, offset, limit int) ([]T, bool, error) { + var isEnd bool + versionInfo, err := ds.db.GetVersionSync(ctx, ds.TableName, ds.EntityID) + if err != nil { + return nil, isEnd, err + } + + if offset > len(versionInfo.UIDList) { + return nil, isEnd, errs.New("offset exceeds the length of the UID list").Wrap() + } + + end := offset + limit + if end >= len(versionInfo.UIDList) { + isEnd = true + end = len(versionInfo.UIDList) + } + + paginatedUIDs := versionInfo.UIDList[offset:end] + + localData, isEnd, err := ds.FetchMissingAndFillLocalV2(ctx, paginatedUIDs, isEnd) + if err != nil { + return nil, isEnd, err + } + return localData, isEnd, nil +} + +func (ds *DataFetcher[T]) FetchMissingAndFillLocalV2(ctx context.Context, uids []string, isEnd bool) ([]T, bool, error) { + localData, err := ds.FetchFromLocal(ctx, uids) + if err != nil { + return nil, false, err + } + + localUIDSet := datautil.SliceSetAny(localData, ds.Key) + + var missingUIDs []string + for _, uid := range uids { + if _, found := localUIDSet[uid]; !found { + missingUIDs = append(missingUIDs, uid) + } + } + + if len(missingUIDs) > 0 { + serverData, err := ds.fetchFromServer(ctx, missingUIDs) + if err != nil { + return localData, false, nil + } + + if err := ds.batchInsert(ctx, serverData); err != nil { + return nil, false, err + } + + localData = append(localData, serverData...) + } + + return localData, isEnd, nil +} diff --git a/pkg/db/admin_group_request_model.go b/pkg/db/admin_group_request_model.go index 263123d6b..54d554efe 100644 --- a/pkg/db/admin_group_request_model.go +++ b/pkg/db/admin_group_request_model.go @@ -20,20 +20,21 @@ package db import ( "context" "errors" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) InsertAdminGroupRequest(ctx context.Context, groupRequest *model_struct.LocalAdminGroupRequest) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(groupRequest).Error, "InsertAdminGroupRequest failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupRequest).Error, "InsertAdminGroupRequest failed") } func (d *DataBase) DeleteAdminGroupRequest(ctx context.Context, groupID, userID string) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Where("group_id=? and user_id=?", groupID, userID).Delete(&model_struct.LocalAdminGroupRequest{}).Error, "DeleteAdminGroupRequest failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Where("group_id=? and user_id=?", groupID, userID).Delete(&model_struct.LocalAdminGroupRequest{}).Error, "DeleteAdminGroupRequest failed") } func (d *DataBase) UpdateAdminGroupRequest(ctx context.Context, groupRequest *model_struct.LocalAdminGroupRequest) error { @@ -41,23 +42,18 @@ func (d *DataBase) UpdateAdminGroupRequest(ctx context.Context, groupRequest *mo defer d.groupMtx.Unlock() t := d.conn.WithContext(ctx).Model(groupRequest).Select("*").Updates(*groupRequest) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "") + return errs.Wrap(t.Error) } func (d *DataBase) GetAdminGroupApplication(ctx context.Context) ([]*model_struct.LocalAdminGroupRequest, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupRequestList []model_struct.LocalAdminGroupRequest - err := utils.Wrap(d.conn.WithContext(ctx).Order("create_time DESC").Find(&groupRequestList).Error, "") + var groupRequestList []*model_struct.LocalAdminGroupRequest + err := errs.Wrap(d.conn.WithContext(ctx).Order("create_time DESC").Find(&groupRequestList).Error) if err != nil { - return nil, utils.Wrap(err, "") - } - var transfer []*model_struct.LocalAdminGroupRequest - for _, v := range groupRequestList { - v1 := v - transfer = append(transfer, &v1) + return nil, errs.Wrap(err) } - return transfer, nil + return groupRequestList, nil } diff --git a/pkg/db/app_version.go b/pkg/db/app_version.go new file mode 100644 index 000000000..19d19888b --- /dev/null +++ b/pkg/db/app_version.go @@ -0,0 +1,34 @@ +package db + +import ( + "context" + + "github.com/openimsdk/tools/errs" + "gorm.io/gorm" + + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" +) + +func (d *DataBase) GetAppSDKVersion(ctx context.Context) (*model_struct.LocalAppSDKVersion, error) { + var appVersion model_struct.LocalAppSDKVersion + return &appVersion, errs.Wrap(d.conn.WithContext(ctx).Take(&appVersion).Error) +} + +func (d *DataBase) SetAppSDKVersion(ctx context.Context, appVersion *model_struct.LocalAppSDKVersion) error { + var exist model_struct.LocalAppSDKVersion + err := d.conn.WithContext(ctx).First(&exist).Error + if err == gorm.ErrRecordNotFound { + if createErr := d.conn.WithContext(ctx).Create(appVersion).Error; createErr != nil { + return errs.Wrap(createErr) + } + return nil + } else if err != nil { + return errs.Wrap(err) + } + + if updateErr := d.conn.WithContext(ctx).Model(&exist).Updates(appVersion).Error; updateErr != nil { + return errs.Wrap(updateErr) + } + + return nil +} diff --git a/pkg/db/black_model.go b/pkg/db/black_model.go index 363b78f6f..41e3ad9eb 100644 --- a/pkg/db/black_model.go +++ b/pkg/db/black_model.go @@ -20,61 +20,46 @@ package db import ( "context" "errors" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) GetBlackListDB(ctx context.Context) ([]*model_struct.LocalBlack, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - if d == nil { - return nil, errors.New("database is not open") - } - var blackList []model_struct.LocalBlack - - err := d.conn.WithContext(ctx).Find(&blackList).Error - var transfer []*model_struct.LocalBlack - for _, v := range blackList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, err + var blackList []*model_struct.LocalBlack + return blackList, errs.Wrap(d.conn.WithContext(ctx).Find(&blackList).Error) } func (d *DataBase) GetBlackListUserID(ctx context.Context) (blackListUid []string, err error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - return blackListUid, utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalBlack{}).Select("block_user_id").Find(&blackListUid).Error, "GetBlackList failed") + return blackListUid, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalBlack{}).Select("block_user_id").Find(&blackListUid).Error, "GetBlackList failed") } func (d *DataBase) GetBlackInfoByBlockUserID(ctx context.Context, blockUserID string) (*model_struct.LocalBlack, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() var black model_struct.LocalBlack - return &black, utils.Wrap(d.conn.WithContext(ctx).Where("owner_user_id = ? AND block_user_id = ? ", + return &black, errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id = ? AND block_user_id = ? ", d.loginUserID, blockUserID).Take(&black).Error, "GetBlackInfoByBlockUserID failed") } func (d *DataBase) GetBlackInfoList(ctx context.Context, blockUserIDList []string) ([]*model_struct.LocalBlack, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - var blackList []model_struct.LocalBlack - if t := d.conn.WithContext(ctx).Where("block_user_id IN ? ", blockUserIDList).Find(&blackList).Error; t != nil { - return nil, utils.Wrap(t, "GetBlackInfoList failed") - } - - var transfer []*model_struct.LocalBlack - for _, v := range blackList { - v1 := v - transfer = append(transfer, &v1) + var blackList []*model_struct.LocalBlack + if err := d.conn.WithContext(ctx).Where("block_user_id IN ? ", blockUserIDList).Find(&blackList).Error; err != nil { + return nil, errs.WrapMsg(err, "GetBlackInfoList failed") } - return transfer, nil + return blackList, nil } func (d *DataBase) InsertBlack(ctx context.Context, black *model_struct.LocalBlack) error { d.friendMtx.Lock() defer d.friendMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(black).Error, "InsertBlack failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(black).Error, "InsertBlack failed") } func (d *DataBase) UpdateBlack(ctx context.Context, black *model_struct.LocalBlack) error { @@ -82,13 +67,13 @@ func (d *DataBase) UpdateBlack(ctx context.Context, black *model_struct.LocalBla defer d.friendMtx.Unlock() t := d.conn.WithContext(ctx).Updates(black) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateBlack failed") + return errs.WrapMsg(t.Error, "UpdateBlack failed") } func (d *DataBase) DeleteBlack(ctx context.Context, blockUserID string) error { d.friendMtx.Lock() defer d.friendMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Where("owner_user_id=? and block_user_id=?", d.loginUserID, blockUserID).Delete(&model_struct.LocalBlack{}).Error, "DeleteBlack failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id=? and block_user_id=?", d.loginUserID, blockUserID).Delete(&model_struct.LocalBlack{}).Error, "DeleteBlack failed") } diff --git a/pkg/db/chat_log_model.go b/pkg/db/chat_log_model.go index f216c353f..f5c0fbcdd 100644 --- a/pkg/db/chat_log_model.go +++ b/pkg/db/chat_log_model.go @@ -20,10 +20,12 @@ package db import ( "context" "errors" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/errs" "gorm.io/gorm" ) @@ -246,7 +248,7 @@ func (d *DataBase) MessageIfExists(ctx context.Context, ClientMsgID string) (boo t := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("client_msg_id = ?", ClientMsgID).Count(&count) if t.Error != nil { - return false, utils.Wrap(t.Error, "MessageIfExists get failed") + return false, errs.WrapMsg(t.Error, "MessageIfExists get failed") } if count != 1 { return false, nil @@ -264,7 +266,7 @@ func (d *DataBase) MessageIfExistsBySeq(ctx context.Context, seq int64) (bool, e t := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("seq = ?", seq).Count(&count) if t.Error != nil { - return false, utils.Wrap(t.Error, "MessageIfExistsBySeq get failed") + return false, errs.WrapMsg(t.Error, "MessageIfExistsBySeq get failed") } if count != 1 { return false, nil @@ -289,15 +291,15 @@ func (d *DataBase) MessageIfExistsBySeq(ctx context.Context, seq int64) (bool, e func (d *DataBase) GetAllUnDeleteMessageSeqList(ctx context.Context) ([]uint32, error) { var seqList []uint32 - return seqList, utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("status != ?", constant.MsgStatusHasDeleted).Select("seq").Find(&seqList).Error, "") + return seqList, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("status != ?", constant.MsgStatusHasDeleted).Select("seq").Find(&seqList).Error, "") } func (d *DataBase) UpdateColumnsMessageList(ctx context.Context, clientMsgIDList []string, args map[string]interface{}) error { c := model_struct.LocalChatLog{} t := d.conn.WithContext(ctx).Model(&c).Where("client_msg_id IN", clientMsgIDList).Updates(args) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateColumnsConversation failed") + return errs.WrapMsg(t.Error, "UpdateColumnsConversation failed") } //funcation (d *DataBase) UpdateColumnsMessageController(ctx context.Context, ClientMsgID string, groupID string, sessionType int32, args map[string]interface{}) error { @@ -327,8 +329,7 @@ func (d *DataBase) UpdateColumnsMessageList(ctx context.Context, clientMsgIDList func (d *DataBase) DeleteAllMessage(ctx context.Context) error { m := model_struct.LocalChatLog{Status: constant.MsgStatusHasDeleted, Content: ""} - err := d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Select("status", "content").Updates(m).Error - return utils.Wrap(err, "delete all message error") + return errs.WrapMsg(d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Select("status", "content").Updates(m).Error, "delete all message error") } func (d *DataBase) UpdateMessageStatusBySourceID(ctx context.Context, sourceID string, status, sessionType int32) error { d.mRWMutex.Lock() @@ -341,9 +342,9 @@ func (d *DataBase) UpdateMessageStatusBySourceID(ctx context.Context, sourceID s } t := d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where(condition, sourceID, sourceID, sessionType).Updates(model_struct.LocalChatLog{Status: status}) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed") + return errs.WrapMsg(t.Error, "UpdateMessageStatusBySourceID failed") } func (d *DataBase) UpdateMessageStatusBySourceIDController(ctx context.Context, sourceID string, status, sessionType int32) error { switch sessionType { @@ -419,14 +420,8 @@ func (d *DataBase) UpdateMessageStatusBySourceIDController(ctx context.Context, func (d *DataBase) GetAllMessageForTest(ctx context.Context) (result []*model_struct.LocalChatLog, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - var messageList []model_struct.LocalChatLog - - err = utils.Wrap(d.conn.WithContext(ctx).Find(&messageList).Error, "GetMessageList failed") - for _, v := range messageList { - v1 := v - result = append(result, &v1) - } - return result, err + var messageList []*model_struct.LocalChatLog + return messageList, errs.WrapMsg(d.conn.WithContext(ctx).Find(&messageList).Error, "GetMessageList failed") } //funcation (d *DataBase) GetMessageListController(ctx context.Context, sourceID string, sessionType, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error) { @@ -487,14 +482,14 @@ func (d *DataBase) GetTestMessage(ctx context.Context, seq uint32) (*model_struc d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var c model_struct.LocalChatLog - return &c, utils.Wrap(d.conn.WithContext(ctx).Where("seq = ?", + return &c, errs.WrapMsg(d.conn.WithContext(ctx).Where("seq = ?", seq).Find(&c).Error, "GetTestMessage failed") } func (d *DataBase) UpdateMsgSenderNickname(ctx context.Context, sendID, nickname string, sType int) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where( + return errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where( "send_id = ? and session_type = ? and sender_nick_name != ? ", sendID, sType, nickname).Updates( map[string]interface{}{"sender_nick_name": nickname}).Error, utils.GetSelfFuncName()+" failed") } @@ -502,7 +497,7 @@ func (d *DataBase) UpdateMsgSenderNickname(ctx context.Context, sendID, nickname func (d *DataBase) UpdateMsgSenderFaceURL(ctx context.Context, sendID, faceURL string, sType int) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where( + return errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where( "send_id = ? and session_type = ? and sender_face_url != ? ", sendID, sType, faceURL).Updates( map[string]interface{}{"sender_face_url": faceURL}).Error, utils.GetSelfFuncName()+" failed") } @@ -527,8 +522,7 @@ func (d *DataBase) GetMsgSeqByClientMsgID(ctx context.Context, clientMsgID strin d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seq uint32 - err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("client_msg_id=?", clientMsgID).First(&seq).Error, utils.GetSelfFuncName()+" failed") - return seq, err + return seq, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("client_msg_id=?", clientMsgID).First(&seq).Error, utils.GetSelfFuncName()+" failed") } func (d *DataBase) GetMsgSeqByClientMsgIDController(ctx context.Context, m *sdk_struct.MsgStruct) (uint32, error) { @@ -544,22 +538,19 @@ func (d *DataBase) GetMsgSeqListByGroupID(ctx context.Context, groupID string) ( d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seqList []uint32 - err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=?", groupID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") - return seqList, err + return seqList, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=?", groupID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") } func (d *DataBase) GetMsgSeqListByPeerUserID(ctx context.Context, userID string) ([]uint32, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seqList []uint32 - err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? or send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") - return seqList, err + return seqList, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? or send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") } func (d *DataBase) GetMsgSeqListBySelfUserID(ctx context.Context, userID string) ([]uint32, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seqList []uint32 - err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? and send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") - return seqList, err + return seqList, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? and send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") } diff --git a/pkg/db/chat_log_model_v3.go b/pkg/db/chat_log_model_v3.go index d3d82ef6c..da69c056a 100644 --- a/pkg/db/chat_log_model_v3.go +++ b/pkg/db/chat_log_model_v3.go @@ -21,12 +21,14 @@ import ( "context" "errors" "fmt" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" ) func (d *DataBase) initChatLog(ctx context.Context, conversationID string) { @@ -47,15 +49,15 @@ func (d *DataBase) initChatLog(ctx context.Context, conversationID string) { func (d *DataBase) UpdateMessage(ctx context.Context, conversationID string, c *model_struct.LocalChatLog) error { t := d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Updates(c) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update ") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update ") } - return utils.Wrap(t.Error, "UpdateMessage failed") + return errs.WrapMsg(t.Error, "UpdateMessage failed") } func (d *DataBase) UpdateMessageBySeq(ctx context.Context, conversationID string, c *model_struct.LocalChatLog) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq=?", c.Seq).Updates(c).Error, "UpdateMessage failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq=?", c.Seq).Updates(c).Error, "UpdateMessage failed") } func (d *DataBase) BatchInsertMessageList(ctx context.Context, conversationID string, MessageList []*model_struct.LocalChatLog) error { @@ -64,32 +66,32 @@ func (d *DataBase) BatchInsertMessageList(ctx context.Context, conversationID st } d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Create(MessageList).Error, "BatchInsertMessageList failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Create(MessageList).Error, "BatchInsertMessageList failed") } func (d *DataBase) InsertMessage(ctx context.Context, conversationID string, Message *model_struct.LocalChatLog) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Create(Message).Error, "InsertMessage failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Create(Message).Error, "InsertMessage failed") } func (d *DataBase) GetMessage(ctx context.Context, conversationID string, clientMsgID string) (*model_struct.LocalChatLog, error) { d.initChatLog(ctx, conversationID) var c model_struct.LocalChatLog - return &c, utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("client_msg_id = ?", + return &c, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("client_msg_id = ?", clientMsgID).Take(&c).Error, "GetMessage failed") } func (d *DataBase) GetMessageBySeq(ctx context.Context, conversationID string, seq int64) (*model_struct.LocalChatLog, error) { d.initChatLog(ctx, conversationID) var c model_struct.LocalChatLog - return &c, utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq = ?", + return &c, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq = ?", seq).Take(&c).Error, "GetMessage failed") } func (d *DataBase) UpdateMessageTimeAndStatus(ctx context.Context, conversationID, clientMsgID string, serverMsgID string, sendTime int64, status int32) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Model(model_struct.LocalChatLog{}).Where("client_msg_id=? And seq=?", clientMsgID, 0). + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Model(model_struct.LocalChatLog{}).Where("client_msg_id=? And seq=?", clientMsgID, 0). Updates(model_struct.LocalChatLog{Status: status, SendTime: sendTime, ServerMsgID: serverMsgID}).Error, "UpdateMessageStatusBySourceID failed") } func (d *DataBase) GetMessageListNoTime(ctx context.Context, conversationID string, @@ -103,7 +105,7 @@ func (d *DataBase) GetMessageListNoTime(ctx context.Context, conversationID stri } else { timeOrder = "send_time DESC" } - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Order(timeOrder).Offset(0).Limit(count).Find(&result).Error, "GetMessageList failed") + err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Order(timeOrder).Offset(0).Limit(count).Find(&result).Error, "GetMessageList failed") if err != nil { return nil, err } @@ -122,7 +124,7 @@ func (d *DataBase) GetMessageList(ctx context.Context, conversationID string, co } condition = "send_time " + timeSymbol + " ?" - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, startTime). + err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, startTime). Order(timeOrder).Offset(0).Limit(count).Find(&result).Error, "GetMessageList failed") if err != nil { return nil, err @@ -133,30 +135,30 @@ func (d *DataBase) GetMessageList(ctx context.Context, conversationID string, co func (d *DataBase) DeleteConversationAllMessages(ctx context.Context, conversationID string) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("1 = 1").Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationAllMessages failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("1 = 1").Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationAllMessages failed") } func (d *DataBase) MarkDeleteConversationAllMessages(ctx context.Context, conversationID string) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("1 = 1").Updates(model_struct.LocalChatLog{Status: constant.MsgStatusHasDeleted}).Error, "DeleteConversationAllMessages failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("1 = 1").Updates(model_struct.LocalChatLog{Status: constant.MsgStatusHasDeleted}).Error, "DeleteConversationAllMessages failed") } func (d *DataBase) DeleteConversationMsgs(ctx context.Context, conversationID string, msgIDs []string) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("client_msg_id IN ?", msgIDs).Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationMsgs failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("client_msg_id IN ?", msgIDs).Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationMsgs failed") } func (d *DataBase) DeleteConversationMsgsBySeqs(ctx context.Context, conversationID string, seqs []int64) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq IN ?", seqs).Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationMsgs failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq IN ?", seqs).Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationMsgs failed") } func (d *DataBase) SearchMessageByContentType(ctx context.Context, contentType []int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) { condition := fmt.Sprintf("send_time between %d and %d AND status <=%d And content_type IN ?", startTime, endTime, constant.MsgStatusSendFailed) - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "SearchMessage failed") + err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "SearchMessage failed") return result, err } func (d *DataBase) SearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) { @@ -188,7 +190,7 @@ func (d *DataBase) SearchMessageByKeyword(ctx context.Context, contentType []int } condition = fmt.Sprintf(" send_time between %d and %d AND status <=%d And content_type IN ? ", startTime, endTime, constant.MsgStatusSendFailed) condition += subCondition - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "InsertMessage failed") + err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "InsertMessage failed") return result, err } // SearchMessageByContentTypeAndKeyword searches for messages in the database that match specified content types and keywords within a given time range. func (d *DataBase) SearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, conversationID string, keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error) { @@ -227,13 +229,13 @@ func (d *DataBase) SearchMessageByContentTypeAndKeyword(ctx context.Context, con condition += subCondition // Execute the query using the constructed condition and handle errors - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Find(&result).Error, "SearchMessage failed") + err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Find(&result).Error, "SearchMessage failed") return result, err } func (d *DataBase) UpdateMsgSenderFaceURLAndSenderNickname(ctx context.Context, conversationID, sendID, faceURL, nickname string) error { - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Model(model_struct.LocalChatLog{}).Where( + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Model(model_struct.LocalChatLog{}).Where( "send_id = ?", sendID).Updates( map[string]interface{}{"sender_face_url": faceURL, "sender_nick_name": nickname}).Error, utils.GetSelfFuncName()+" failed") } @@ -241,7 +243,7 @@ func (d *DataBase) UpdateMsgSenderFaceURLAndSenderNickname(ctx context.Context, func (d *DataBase) GetAlreadyExistSeqList(ctx context.Context, conversationID string, lostSeqList []int64) (seqList []int64, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("seq IN ?", lostSeqList).Pluck("seq", &seqList).Error, utils.GetSelfFuncName()+" failed") + err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("seq IN ?", lostSeqList).Pluck("seq", &seqList).Error, utils.GetSelfFuncName()+" failed") if err != nil { return nil, err } @@ -254,9 +256,9 @@ func (d *DataBase) UpdateColumnsMessage(ctx context.Context, conversationID, Cli c := model_struct.LocalChatLog{ClientMsgID: ClientMsgID} t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Model(&c).Updates(args) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateColumnsConversation failed") + return errs.WrapMsg(t.Error, "UpdateColumnsConversation failed") } func (d *DataBase) SearchAllMessageByContentType(ctx context.Context, conversationID string, contentType int) (result []*model_struct.LocalChatLog, err error) { err = d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Model(&model_struct.LocalChatLog{}).Where("content_type = ?", contentType).Find(&result).Error @@ -265,7 +267,7 @@ func (d *DataBase) SearchAllMessageByContentType(ctx context.Context, conversati func (d *DataBase) GetUnreadMessage(ctx context.Context, conversationID string) (msgs []*model_struct.LocalChatLog, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Debug().Where("send_id != ? AND is_read = ?", d.loginUserID, constant.NotRead).Find(&msgs).Error, "GetMessageList failed") + err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Debug().Where("send_id != ? AND is_read = ?", d.loginUserID, constant.NotRead).Find(&msgs).Error, "GetMessageList failed") return msgs, err } @@ -274,9 +276,9 @@ func (d *DataBase) MarkConversationMessageAsReadBySeqs(ctx context.Context, conv defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("seq in ? AND send_id != ?", seqs, d.loginUserID).Update("is_read", constant.HasRead) if t.RowsAffected == 0 { - return 0, utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return 0, errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return t.RowsAffected, utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed") + return t.RowsAffected, errs.WrapMsg(t.Error, "UpdateMessageStatusBySourceID failed") } func (d *DataBase) MarkConversationMessageAsReadDB(ctx context.Context, conversationID string, msgIDs []string) (rowsAffected int64, err error) { @@ -284,7 +286,7 @@ func (d *DataBase) MarkConversationMessageAsReadDB(ctx context.Context, conversa defer d.mRWMutex.Unlock() var msgs []*model_struct.LocalChatLog if err := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("client_msg_id in ? AND send_id != ?", msgIDs, d.loginUserID).Find(&msgs).Error; err != nil { - return 0, utils.Wrap(err, "MarkConversationMessageAsReadDB failed") + return 0, errs.WrapMsg(err, "MarkConversationMessageAsReadDB failed") } for _, msg := range msgs { var attachedInfo sdk_struct.AttachedInfoElem @@ -300,7 +302,7 @@ func (d *DataBase) MarkConversationMessageAsReadDB(ctx context.Context, conversa } // t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("client_msg_id in ? AND send_id != ?", msgIDs, d.loginUserID).Update("is_read", constant.HasRead) // if t.RowsAffected == 0 { - // return 0, utils.Wrap(errors.New("RowsAffected == 0"), "no update") + // return 0, errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") // } return rowsAffected, nil } @@ -310,18 +312,18 @@ func (d *DataBase) MarkConversationAllMessageAsRead(ctx context.Context, convers defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("send_id != ? AND is_read == ?", d.loginUserID, false).Update("is_read", constant.HasRead) if t.RowsAffected == 0 { - return 0, utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return 0, errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return t.RowsAffected, utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed") + return t.RowsAffected, errs.WrapMsg(t.Error, "UpdateMessageStatusBySourceID failed") } func (d *DataBase) GetMessagesByClientMsgIDs(ctx context.Context, conversationID string, msgIDs []string) (msgs []*model_struct.LocalChatLog, err error) { - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("client_msg_id IN ?", msgIDs).Order("send_time DESC").Find(&msgs).Error, "GetMessagesByClientMsgIDs error") + err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("client_msg_id IN ?", msgIDs).Order("send_time DESC").Find(&msgs).Error, "GetMessagesByClientMsgIDs error") return msgs, err } func (d *DataBase) GetMessagesBySeqs(ctx context.Context, conversationID string, seqs []int64) (msgs []*model_struct.LocalChatLog, err error) { - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("seq IN ?", seqs).Order("send_time DESC").Find(&msgs).Error, "GetMessagesBySeqs error") + err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("seq IN ?", seqs).Order("send_time DESC").Find(&msgs).Error, "GetMessagesBySeqs error") return msgs, err } @@ -329,11 +331,11 @@ func (d *DataBase) GetConversationNormalMsgSeq(ctx context.Context, conversation d.initChatLog(ctx, conversationID) var seq int64 err := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Select("IFNULL(max(seq),0)").Find(&seq).Error - return seq, utils.Wrap(err, "GetConversationNormalMsgSeq") + return seq, errs.WrapMsg(err, "GetConversationNormalMsgSeq") } func (d *DataBase) GetConversationPeerNormalMsgSeq(ctx context.Context, conversationID string) (int64, error) { var seq int64 err := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Select("IFNULL(max(seq),0)").Where("send_id != ?", d.loginUserID).Find(&seq).Error - return seq, utils.Wrap(err, "GetConversationPeerNormalMsgSeq") + return seq, errs.WrapMsg(err, "GetConversationPeerNormalMsgSeq") } diff --git a/pkg/db/chat_log_reaction_extension_model.go b/pkg/db/chat_log_reaction_extension_model.go index 56a40654e..cb679563a 100644 --- a/pkg/db/chat_log_reaction_extension_model.go +++ b/pkg/db/chat_log_reaction_extension_model.go @@ -20,31 +20,32 @@ package db import ( "context" "errors" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) GetMessageReactionExtension(ctx context.Context, msgID string) (result *model_struct.LocalChatLogReactionExtensions, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var l model_struct.LocalChatLogReactionExtensions - return &l, utils.Wrap(d.conn.WithContext(ctx).Where("client_msg_id = ?", + return &l, errs.WrapMsg(d.conn.WithContext(ctx).Where("client_msg_id = ?", msgID).Take(&l).Error, "GetMessageReactionExtension failed") } func (d *DataBase) InsertMessageReactionExtension(ctx context.Context, messageReactionExtension *model_struct.LocalChatLogReactionExtensions) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(messageReactionExtension).Error, "InsertMessageReactionExtension failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(messageReactionExtension).Error, "InsertMessageReactionExtension failed") } func (d *DataBase) UpdateMessageReactionExtension(ctx context.Context, c *model_struct.LocalChatLogReactionExtensions) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Updates(c) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateConversation failed") + return errs.WrapMsg(t.Error, "UpdateConversation failed") } // func (d *DataBase) GetAndUpdateMessageReactionExtension(ctx context.Context, msgID string, m map[string]*sdkws.KeyValue) error { @@ -70,7 +71,7 @@ func (d *DataBase) UpdateMessageReactionExtension(ctx context.Context, c *model_ // temp.LocalReactionExtensions = []byte(utils.StructToJsonString(oldKeyValue)) // t := d.conn.WithContext(ctx).Updates(temp) // if t.RowsAffected == 0 { -// return utils.Wrap(errors.New("RowsAffected == 0"), "no update") +// return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") // } // } // return nil @@ -102,7 +103,7 @@ func (d *DataBase) DeleteMessageReactionExtension(ctx context.Context, msgID str // temp.LocalReactionExtensions = []byte(utils.StructToJsonString(oldKeyValue)) // t := d.conn.WithContext(ctx).Updates(temp) // if t.RowsAffected == 0 { -// return utils.Wrap(errors.New("RowsAffected == 0"), "no update") +// return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") // } // } // return nil @@ -111,7 +112,7 @@ func (d *DataBase) DeleteMessageReactionExtension(ctx context.Context, msgID str // d.mRWMutex.Lock() // defer d.mRWMutex.Unlock() // var messageList []model_struct.LocalChatLogReactionExtensions -// err = utils.Wrap(d.conn.WithContext(ctx).Where("client_msg_id IN ?", msgIDList).Find(&messageList).Error, "GetMultipleMessageReactionExtension failed") +// err = errs.WrapMsg(d.conn.WithContext(ctx).Where("client_msg_id IN ?", msgIDList).Find(&messageList).Error, "GetMultipleMessageReactionExtension failed") // for _, v := range messageList { // v1 := v // result = append(result, &v1) diff --git a/pkg/db/conversation_model.go b/pkg/db/conversation_model.go index 7c5e6c427..f4324dabc 100644 --- a/pkg/db/conversation_model.go +++ b/pkg/db/conversation_model.go @@ -21,18 +21,19 @@ import ( "context" "errors" "fmt" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" - "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" "gorm.io/gorm" ) func (d *DataBase) GetConversationByUserID(ctx context.Context, userID string) (*model_struct.LocalConversation, error) { var conversation model_struct.LocalConversation - err := utils.Wrap(d.conn.WithContext(ctx).Where("user_id=?", userID).Find(&conversation).Error, "GetConversationByUserID error") + err := errs.WrapMsg(d.conn.WithContext(ctx).Where("user_id=?", userID).Find(&conversation).Error, "GetConversationByUserID error") return &conversation, err } @@ -40,7 +41,7 @@ func (d *DataBase) GetAllConversationListDB(ctx context.Context) ([]*model_struc d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var conversationList []*model_struct.LocalConversation - err := utils.Wrap(d.conn.WithContext(ctx).Where("latest_msg_send_time > ?", 0).Order("case when is_pinned=1 then 0 else 1 end,max(latest_msg_send_time,draft_text_time) DESC").Find(&conversationList).Error, + err := errs.WrapMsg(d.conn.WithContext(ctx).Where("latest_msg_send_time > ?", 0).Order("case when is_pinned=1 then 0 else 1 end,max(latest_msg_send_time,draft_text_time) DESC").Find(&conversationList).Error, "GetAllConversationList failed") if err != nil { return nil, err @@ -48,56 +49,41 @@ func (d *DataBase) GetAllConversationListDB(ctx context.Context) ([]*model_struc return conversationList, err } func (d *DataBase) FindAllConversationConversationID(ctx context.Context) (conversationIDs []string, err error) { - return conversationIDs, utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("latest_msg_send_time > ?", 0).Pluck("conversation_id", &conversationIDs).Error, "") + return conversationIDs, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("latest_msg_send_time > ?", 0).Pluck("conversation_id", &conversationIDs).Error, "") } func (d *DataBase) GetHiddenConversationList(ctx context.Context) ([]*model_struct.LocalConversation, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - var conversationList []model_struct.LocalConversation - err := utils.Wrap(d.conn.WithContext(ctx).Where("latest_msg_send_time = ?", 0).Find(&conversationList).Error, + var conversationList []*model_struct.LocalConversation + return conversationList, errs.WrapMsg(d.conn.WithContext(ctx).Where("latest_msg_send_time = ?", 0).Find(&conversationList).Error, "GetHiddenConversationList failed") - var transfer []*model_struct.LocalConversation - for _, v := range conversationList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, err } func (d *DataBase) GetAllConversations(ctx context.Context) ([]*model_struct.LocalConversation, error) { var conversationList []*model_struct.LocalConversation - err := utils.Wrap(d.conn.WithContext(ctx).Find(&conversationList).Error, "GetAllConversations failed") - return conversationList, err + return conversationList, errs.WrapMsg(d.conn.WithContext(ctx).Find(&conversationList).Error, "GetAllConversations failed") } func (d *DataBase) GetAllConversationIDList(ctx context.Context) (result []string, err error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() var c model_struct.LocalConversation - err = d.conn.WithContext(ctx).Model(&c).Pluck("conversation_id", &result).Error - return result, utils.Wrap(err, "GetAllConversationIDList failed ") + return result, errs.WrapMsg(d.conn.WithContext(ctx).Model(&c).Pluck("conversation_id", &result).Error, "GetAllConversationIDList failed ") } func (d *DataBase) GetAllSingleConversationIDList(ctx context.Context) (result []string, err error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() var c model_struct.LocalConversation - err = d.conn.WithContext(ctx).Model(&c).Where("conversation_type = ?", constant.SingleChatType).Pluck("conversation_id", &result).Error - return result, utils.Wrap(err, "GetAllConversationIDList failed ") + return result, errs.WrapMsg(d.conn.WithContext(ctx).Model(&c).Where("conversation_type = ?", constant.SingleChatType).Pluck("conversation_id", &result).Error, "GetAllConversationIDList failed ") } func (d *DataBase) GetConversationListSplitDB(ctx context.Context, offset, count int) ([]*model_struct.LocalConversation, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - var conversationList []model_struct.LocalConversation - err := utils.Wrap(d.conn.WithContext(ctx).Where("latest_msg_send_time > ?", 0).Order("case when is_pinned=1 then 0 else 1 end,max(latest_msg_send_time,draft_text_time) DESC").Offset(offset).Limit(count).Find(&conversationList).Error, + var conversationList []*model_struct.LocalConversation + return conversationList, errs.WrapMsg(d.conn.WithContext(ctx).Where("latest_msg_send_time > ?", 0).Order("case when is_pinned=1 then 0 else 1 end,max(latest_msg_send_time,draft_text_time) DESC").Offset(offset).Limit(count).Find(&conversationList).Error, "GetFriendList failed") - var transfer []*model_struct.LocalConversation - for _, v := range conversationList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, err } func (d *DataBase) BatchInsertConversationList(ctx context.Context, conversationList []*model_struct.LocalConversation) error { if conversationList == nil { @@ -106,7 +92,7 @@ func (d *DataBase) BatchInsertConversationList(ctx context.Context, conversation d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(conversationList).Error, "BatchInsertConversationList failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(conversationList).Error, "BatchInsertConversationList failed") } func (d *DataBase) UpdateOrCreateConversations(ctx context.Context, conversationList []*model_struct.LocalConversation) error { @@ -140,18 +126,18 @@ func (d *DataBase) UpdateOrCreateConversations(ctx context.Context, conversation func (d *DataBase) InsertConversation(ctx context.Context, conversationList *model_struct.LocalConversation) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(conversationList).Error, "InsertConversation failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(conversationList).Error, "InsertConversation failed") } func (d *DataBase) DeleteConversation(ctx context.Context, conversationID string) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Where("conversation_id = ?", conversationID).Delete(&model_struct.LocalConversation{}).Error, "DeleteConversation failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Where("conversation_id = ?", conversationID).Delete(&model_struct.LocalConversation{}).Error, "DeleteConversation failed") } func (d *DataBase) GetConversation(ctx context.Context, conversationID string) (*model_struct.LocalConversation, error) { var c model_struct.LocalConversation - return &c, utils.Wrap(d.conn.WithContext(ctx).Where("conversation_id = ?", + return &c, errs.WrapMsg(d.conn.WithContext(ctx).Where("conversation_id = ?", conversationID).Take(&c).Error, "GetConversation failed, conversationID: "+conversationID) } @@ -161,9 +147,9 @@ func (d *DataBase) UpdateConversation(ctx context.Context, c *model_struct.Local d.conn.WithContext(ctx).Logger.LogMode(6) t := d.conn.WithContext(ctx).Updates(c) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateConversation failed") + return errs.WrapMsg(t.Error, "UpdateConversation failed") } func (d *DataBase) UpdateConversationForSync(ctx context.Context, c *model_struct.LocalConversation) error { @@ -174,16 +160,16 @@ func (d *DataBase) UpdateConversationForSync(ctx context.Context, c *model_struc "group_at_type": c.GroupAtType, "is_not_in_group": c.IsNotInGroup, "update_unread_count_time": c.UpdateUnreadCountTime, "ex": c.Ex, "attached_info": c.AttachedInfo, "burn_duration": c.BurnDuration, "msg_destruct_time": c.MsgDestructTime, "is_msg_destruct": c.IsMsgDestruct}) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateConversation failed") + return errs.WrapMsg(t.Error, "UpdateConversation failed") } func (d *DataBase) BatchUpdateConversationList(ctx context.Context, conversationList []*model_struct.LocalConversation) error { for _, v := range conversationList { err := d.UpdateConversation(ctx, v) if err != nil { - return utils.Wrap(err, "BatchUpdateConversationList failed") + return errs.WrapMsg(err, "BatchUpdateConversationList failed") } } @@ -196,7 +182,7 @@ func (d *DataBase) ConversationIfExists(ctx context.Context, conversationID stri t := d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("conversation_id = ?", conversationID).Count(&count) if t.Error != nil { - return false, utils.Wrap(t.Error, "ConversationIfExists get failed") + return false, errs.WrapMsg(t.Error, "ConversationIfExists get failed") } if count != 1 { return false, nil @@ -213,9 +199,9 @@ func (d *DataBase) ResetConversation(ctx context.Context, conversationID string) c := model_struct.LocalConversation{ConversationID: conversationID, UnreadCount: 0, LatestMsg: "", LatestMsgSendTime: 0, DraftText: "", DraftTextTime: 0} t := d.conn.WithContext(ctx).Select("unread_count", "latest_msg", "latest_msg_send_time", "draft_text", "draft_text_time").Updates(c) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "ResetConversation failed") + return errs.WrapMsg(t.Error, "ResetConversation failed") } // ResetAllConversation Reset ALL conversation is equivalent to deleting the conversation, @@ -226,9 +212,9 @@ func (d *DataBase) ResetAllConversation(ctx context.Context) error { c := model_struct.LocalConversation{UnreadCount: 0, LatestMsg: "", LatestMsgSendTime: 0, DraftText: "", DraftTextTime: 0} t := d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Select("unread_count", "latest_msg", "latest_msg_send_time", "draft_text", "draft_text_time").Updates(c) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "ResetConversation failed") + return errs.WrapMsg(t.Error, "ResetConversation failed") } // Clear the conversation, which is used to delete the conversation history message and clear the conversation at the same time. @@ -240,9 +226,9 @@ func (d *DataBase) ClearConversation(ctx context.Context, conversationID string) c := model_struct.LocalConversation{ConversationID: conversationID, UnreadCount: 0, LatestMsg: "", DraftText: "", DraftTextTime: 0} t := d.conn.WithContext(ctx).Select("unread_count", "latest_msg", "draft_text", "draft_text_time").Updates(c) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "ClearConversation failed") + return errs.WrapMsg(t.Error, "ClearConversation failed") } func (d *DataBase) SetConversationDraftDB(ctx context.Context, conversationID, draftText string) error { @@ -252,9 +238,9 @@ func (d *DataBase) SetConversationDraftDB(ctx context.Context, conversationID, d t := d.conn.WithContext(ctx).Exec("update local_conversations set draft_text=?,draft_text_time=?,latest_msg_send_time=case when latest_msg_send_time=? then ? else latest_msg_send_time end where conversation_id=?", draftText, nowTime, 0, nowTime, conversationID) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "SetConversationDraft failed") + return errs.WrapMsg(t.Error, "SetConversationDraft failed") } func (d *DataBase) RemoveConversationDraft(ctx context.Context, conversationID, draftText string) error { d.mRWMutex.Lock() @@ -262,9 +248,9 @@ func (d *DataBase) RemoveConversationDraft(ctx context.Context, conversationID, c := model_struct.LocalConversation{ConversationID: conversationID, DraftText: draftText, DraftTextTime: 0} t := d.conn.WithContext(ctx).Select("draft_text", "draft_text_time").Updates(c) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "RemoveConversationDraft failed") + return errs.WrapMsg(t.Error, "RemoveConversationDraft failed") } func (d *DataBase) UnPinConversation(ctx context.Context, conversationID string, isPinned int) error { d.mRWMutex.Lock() @@ -272,9 +258,9 @@ func (d *DataBase) UnPinConversation(ctx context.Context, conversationID string, t := d.conn.WithContext(ctx).Exec("update local_conversations set is_pinned=?,draft_text_time=case when draft_text=? then ? else draft_text_time end where conversation_id=?", isPinned, "", 0, conversationID) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UnPinConversation failed") + return errs.WrapMsg(t.Error, "UnPinConversation failed") } func (d *DataBase) UpdateColumnsConversation(ctx context.Context, conversationID string, args map[string]interface{}) error { @@ -282,21 +268,21 @@ func (d *DataBase) UpdateColumnsConversation(ctx context.Context, conversationID defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Model(model_struct.LocalConversation{ConversationID: conversationID}).Updates(args) if t.RowsAffected == 0 { - return utils.Wrap(errs.ErrRecordNotFound, "no update") + return errs.WrapMsg(errs.ErrRecordNotFound, "no update") } - return utils.Wrap(t.Error, "UpdateColumnsConversation failed") + return errs.WrapMsg(t.Error, "UpdateColumnsConversation failed") } func (d *DataBase) UpdateAllConversation(ctx context.Context, conversation *model_struct.LocalConversation) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() if conversation.ConversationID != "" { - return utils.Wrap(errors.New("not update all conversation"), "UpdateAllConversation failed") + return errs.WrapMsg(errors.New("not update all conversation"), "UpdateAllConversation failed") } t := d.conn.WithContext(ctx).Model(conversation).Updates(conversation) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateColumnsConversation failed") + return errs.WrapMsg(t.Error, "UpdateColumnsConversation failed") } func (d *DataBase) IncrConversationUnreadCount(ctx context.Context, conversationID string) error { d.mRWMutex.Lock() @@ -304,9 +290,9 @@ func (d *DataBase) IncrConversationUnreadCount(ctx context.Context, conversation c := model_struct.LocalConversation{ConversationID: conversationID} t := d.conn.WithContext(ctx).Model(&c).Update("unread_count", gorm.Expr("unread_count+?", 1)) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "IncrConversationUnreadCount failed") + return errs.WrapMsg(t.Error, "IncrConversationUnreadCount failed") } func (d *DataBase) GetTotalUnreadMsgCountDB(ctx context.Context) (totalUnreadCount int32, err error) { d.mRWMutex.Lock() @@ -314,7 +300,7 @@ func (d *DataBase) GetTotalUnreadMsgCountDB(ctx context.Context) (totalUnreadCou var result []int64 err = d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("recv_msg_opt < ? and latest_msg_send_time > ?", constant.ReceiveNotNotifyMessage, 0).Pluck("unread_count", &result).Error if err != nil { - return totalUnreadCount, utils.Wrap(errors.New("GetTotalUnreadMsgCount err"), "GetTotalUnreadMsgCount err") + return totalUnreadCount, errs.WrapMsg(errors.New("GetTotalUnreadMsgCount err"), "GetTotalUnreadMsgCount err") } for _, v := range result { totalUnreadCount += int32(v) @@ -327,16 +313,16 @@ func (d *DataBase) SetMultipleConversationRecvMsgOpt(ctx context.Context, conver defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("conversation_id IN ?", conversationIDList).Updates(map[string]interface{}{"recv_msg_opt": opt}) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "SetMultipleConversationRecvMsgOpt failed") + return errs.WrapMsg(t.Error, "SetMultipleConversationRecvMsgOpt failed") } func (d *DataBase) GetMultipleConversationDB(ctx context.Context, conversationIDList []string) (result []*model_struct.LocalConversation, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var conversationList []model_struct.LocalConversation - err = utils.Wrap(d.conn.WithContext(ctx).Where("conversation_id IN ?", conversationIDList).Find(&conversationList).Error, "GetMultipleConversation failed") + err = errs.WrapMsg(d.conn.WithContext(ctx).Where("conversation_id IN ?", conversationIDList).Find(&conversationList).Error, "GetMultipleConversation failed") for _, v := range conversationList { v1 := v result = append(result, &v1) @@ -350,18 +336,18 @@ func (d *DataBase) DecrConversationUnreadCount(ctx context.Context, conversation c := model_struct.LocalConversation{ConversationID: conversationID} t := tx.Model(&c).Update("unread_count", gorm.Expr("unread_count-?", count)) if t.Error != nil { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } if err := tx.Where("conversation_id = ?", conversationID).Take(&c).Error; err != nil { tx.Rollback() - return utils.Wrap(errors.New("get conversation err"), "") + return errs.WrapMsg(errors.New("get conversation err"), "") } if c.UnreadCount < 0 { log.ZWarn(ctx, "decr unread count < 0", nil, "conversationID", conversationID, "count", count) if t = tx.Model(&c).Update("unread_count", 0); t.Error != nil { tx.Rollback() - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } } tx.Commit() @@ -370,14 +356,6 @@ func (d *DataBase) DecrConversationUnreadCount(ctx context.Context, conversation func (d *DataBase) SearchConversations(ctx context.Context, searchParam string) ([]*model_struct.LocalConversation, error) { // Define the search condition based on the searchParam condition := fmt.Sprintf("show_name like %q ", "%"+searchParam+"%") - - var conversationList []model_struct.LocalConversation - err := d.conn.WithContext(ctx).Where(condition).Order("latest_msg_send_time DESC").Find(&conversationList).Error - var transfer []*model_struct.LocalConversation - for _, v := range conversationList { - v1 := v // Create a copy to avoid referencing the loop variable - transfer = append(transfer, &v1) - } - - return transfer, utils.Wrap(err, "SearchConversation failed ") + var conversationList []*model_struct.LocalConversation + return conversationList, errs.WrapMsg(d.conn.WithContext(ctx).Where(condition).Order("latest_msg_send_time DESC").Find(&conversationList).Error, "SearchConversation failed ") } diff --git a/pkg/db/conversation_unread_message_model.go b/pkg/db/conversation_unread_message_model.go index 33242ccbe..e309fdde7 100644 --- a/pkg/db/conversation_unread_message_model.go +++ b/pkg/db/conversation_unread_message_model.go @@ -19,8 +19,9 @@ package db import ( "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) BatchInsertConversationUnreadMessageList(ctx context.Context, messageList []*model_struct.LocalConversationUnreadMessage) error { @@ -29,7 +30,7 @@ func (d *DataBase) BatchInsertConversationUnreadMessageList(ctx context.Context, } d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(messageList).Error, "BatchInsertConversationUnreadMessageList failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(messageList).Error, "BatchInsertConversationUnreadMessageList failed") } func (d *DataBase) DeleteConversationUnreadMessageList(ctx context.Context, conversationID string, sendTime int64) int64 { d.mRWMutex.Lock() diff --git a/pkg/db/db_init.go b/pkg/db/db_init.go index 76774dbf9..6f64d5b95 100644 --- a/pkg/db/db_init.go +++ b/pkg/db/db_init.go @@ -27,8 +27,10 @@ import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/openim-sdk-core/v3/version" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -42,11 +44,12 @@ type DataBase struct { groupMtx sync.RWMutex friendMtx sync.RWMutex userMtx sync.RWMutex + versionMtx sync.RWMutex superGroupMtx sync.RWMutex } func (d *DataBase) GetMultipleMessageReactionExtension(ctx context.Context, msgIDList []string) (result []*model_struct.LocalChatLogReactionExtensions, err error) { - //TODO implement me + // TODO implement me panic("implement me") } @@ -127,31 +130,15 @@ func (d *DataBase) initDB(ctx context.Context, logLevel int) error { sqlDB.SetConnMaxIdleTime(time.Minute * 10) d.conn = db - err = db.AutoMigrate( - &model_struct.LocalFriend{}, - &model_struct.LocalFriendRequest{}, - &model_struct.LocalGroup{}, - &model_struct.LocalGroupMember{}, - &model_struct.LocalGroupRequest{}, - &model_struct.LocalErrChatLog{}, - &model_struct.LocalUser{}, - &model_struct.LocalBlack{}, - &model_struct.LocalConversation{}, - &model_struct.NotificationSeqs{}, - &model_struct.LocalChatLog{}, - &model_struct.LocalAdminGroupRequest{}, - &model_struct.LocalWorkMomentsNotification{}, - &model_struct.LocalWorkMomentsNotificationUnreadCount{}, - &model_struct.TempCacheLocalChatLog{}, - &model_struct.LocalChatLogReactionExtensions{}, - &model_struct.LocalUpload{}, - &model_struct.LocalStranger{}, - &model_struct.LocalSendingMessages{}, - &model_struct.LocalUserCommand{}, - ) - if err != nil { + // base + if err = db.AutoMigrate(&model_struct.LocalAppSDKVersion{}); err != nil { return err } + + if err = d.versionDataMigrate(ctx); err != nil { + return err + } + //if err := db.Table(constant.SuperGroupTableName).AutoMigrate(superGroup); err != nil { // return err //} @@ -159,13 +146,55 @@ func (d *DataBase) initDB(ctx context.Context, logLevel int) error { return nil } -func (d *DataBase) versionDataFix(ctx context.Context) { - //todo some model auto migrate data conversion - //conversationIDs, err := d.FindAllConversationConversationID(ctx) - //if err != nil { - // log.ZError(ctx, "FindAllConversationConversationID err", err) - //} - //for _, conversationID := range conversationIDs { - // d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).AutoMigrate(&model_struct.LocalChatLog{}) - //} +func (d *DataBase) versionDataMigrate(ctx context.Context) error { + verModel, err := d.GetAppSDKVersion(ctx) + if errs.Unwrap(err) == gorm.ErrRecordNotFound { + err = d.conn.AutoMigrate( + &model_struct.LocalAppSDKVersion{}, + &model_struct.LocalFriend{}, + &model_struct.LocalFriendRequest{}, + &model_struct.LocalGroup{}, + &model_struct.LocalGroupMember{}, + &model_struct.LocalGroupRequest{}, + &model_struct.LocalErrChatLog{}, + &model_struct.LocalUser{}, + &model_struct.LocalBlack{}, + &model_struct.LocalConversation{}, + &model_struct.NotificationSeqs{}, + &model_struct.LocalChatLog{}, + &model_struct.LocalAdminGroupRequest{}, + &model_struct.LocalWorkMomentsNotification{}, + &model_struct.LocalWorkMomentsNotificationUnreadCount{}, + &model_struct.TempCacheLocalChatLog{}, + &model_struct.LocalChatLogReactionExtensions{}, + &model_struct.LocalUpload{}, + &model_struct.LocalStranger{}, + &model_struct.LocalSendingMessages{}, + &model_struct.LocalUserCommand{}, + &model_struct.LocalVersionSync{}, + ) + if err != nil { + return err + } + err = d.SetAppSDKVersion(ctx, &model_struct.LocalAppSDKVersion{Version: version.Version}) + if err != nil { + return err + } + + return nil + } else if err != nil { + return err + } + if verModel.Version != version.Version { + switch version.Version { + case "3.8.0": + d.conn.AutoMigrate(&model_struct.LocalAppSDKVersion{}) + } + err = d.SetAppSDKVersion(ctx, &model_struct.LocalAppSDKVersion{Version: version.Version}) + if err != nil { + return err + } + } + + return nil } diff --git a/pkg/db/db_interface/databse.go b/pkg/db/db_interface/databse.go index 8f0121599..3c92407b8 100644 --- a/pkg/db/db_interface/databse.go +++ b/pkg/db/db_interface/databse.go @@ -16,6 +16,7 @@ package db_interface import ( "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" ) @@ -24,6 +25,8 @@ type GroupModel interface { InsertGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error DeleteGroup(ctx context.Context, groupID string) error UpdateGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error + BatchInsertGroup(ctx context.Context, groupList []*model_struct.LocalGroup) error + DeleteAllGroup(ctx context.Context) error GetJoinedGroupListDB(ctx context.Context) ([]*model_struct.LocalGroup, error) GetGroups(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) GetGroupInfoByGroupID(ctx context.Context, groupID string) (*model_struct.LocalGroup, error) @@ -55,6 +58,7 @@ type GroupModel interface { GetGroupAdminID(ctx context.Context, groupID string) ([]string, error) GetGroupMemberListByGroupID(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) GetGroupMemberListSplit(ctx context.Context, groupID string, filter int32, offset, count int) ([]*model_struct.LocalGroupMember, error) + GetGroupMemberListByUserIDs(ctx context.Context, groupID string, filter int32, userIDs []string) ([]*model_struct.LocalGroupMember, error) GetGroupMemberOwnerAndAdminDB(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) GetGroupMemberOwner(ctx context.Context, groupID string) (*model_struct.LocalGroupMember, error) GetGroupMemberListSplitByJoinTimeFilter(ctx context.Context, groupID string, offset, count int, joinTimeBegin, joinTimeEnd int64, userIDList []string) ([]*model_struct.LocalGroupMember, error) @@ -73,38 +77,35 @@ type GroupModel interface { type MessageModel interface { BatchInsertMessageList(ctx context.Context, conversationID string, MessageList []*model_struct.LocalChatLog) error - //BatchInsertMessageListController(ctx context.Context, MessageList []*model_struct.LocalChatLog) error + // BatchInsertMessageListController(ctx context.Context, MessageList []*model_struct.LocalChatLog) error InsertMessage(ctx context.Context, conversationID string, Message *model_struct.LocalChatLog) error - //InsertMessageController(ctx context.Context, message *model_struct.LocalChatLog) error + // InsertMessageController(ctx context.Context, message *model_struct.LocalChatLog) error SearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) - //SearchMessageByKeywordController(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) + // SearchMessageByKeywordController(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) SearchMessageByContentType(ctx context.Context, contentType []int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) - //SearchMessageByContentTypeController(ctx context.Context, contentType []int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) + // SearchMessageByContentTypeController(ctx context.Context, contentType []int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) SearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, conversationID string, keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error) - //SearchMessageByContentTypeAndKeywordController(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error) - //BatchUpdateMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error - //BatchSpecialUpdateMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error MessageIfExists(ctx context.Context, ClientMsgID string) (bool, error) IsExistsInErrChatLogBySeq(ctx context.Context, seq int64) bool MessageIfExistsBySeq(ctx context.Context, seq int64) (bool, error) GetMessage(ctx context.Context, conversationID, clientMsgID string) (*model_struct.LocalChatLog, error) GetMessageBySeq(ctx context.Context, conversationID string, seq int64) (*model_struct.LocalChatLog, error) - //GetMessageController(ctx context.Context, conversationID, clientMsgID string) (*model_struct.LocalChatLog, error) + // GetMessageController(ctx context.Context, conversationID, clientMsgID string) (*model_struct.LocalChatLog, error) UpdateColumnsMessageList(ctx context.Context, clientMsgIDList []string, args map[string]interface{}) error UpdateColumnsMessage(ctx context.Context, conversationID string, ClientMsgID string, args map[string]interface{}) error - //UpdateColumnsMessageController(ctx context.Context, ClientMsgID string, groupID string, sessionType int32, args map[string]interface{}) error + // UpdateColumnsMessageController(ctx context.Context, ClientMsgID string, groupID string, sessionType int32, args map[string]interface{}) error UpdateMessage(ctx context.Context, conversationID string, c *model_struct.LocalChatLog) error UpdateMessageBySeq(ctx context.Context, conversationID string, c *model_struct.LocalChatLog) error - //UpdateMessageController(ctx context.Context, c *model_struct.LocalChatLog) error + // UpdateMessageController(ctx context.Context, c *model_struct.LocalChatLog) error DeleteAllMessage(ctx context.Context) error UpdateMessageStatusBySourceID(ctx context.Context, sourceID string, status, sessionType int32) error - //UpdateMessageStatusBySourceIDController(ctx context.Context, sourceID string, status, sessionType int32) error + // UpdateMessageStatusBySourceIDController(ctx context.Context, sourceID string, status, sessionType int32) error UpdateMessageTimeAndStatus(ctx context.Context, conversationID, clientMsgID string, serverMsgID string, sendTime int64, status int32) error - //UpdateMessageTimeAndStatusController(ctx context.Context, msg *sdk_struct.MsgStruct) error + // UpdateMessageTimeAndStatusController(ctx context.Context, msg *sdk_struct.MsgStruct) error GetMessageList(ctx context.Context, conversationID string, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error) - //GetMessageListController(ctx context.Context, sourceID string, sessionType, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error) + // GetMessageListController(ctx context.Context, sourceID string, sessionType, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error) GetMessageListNoTime(ctx context.Context, conversationID string, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error) - //GetMessageListNoTimeController(ctx context.Context, sourceID string, sessionType, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error) + // GetMessageListNoTimeController(ctx context.Context, sourceID string, sessionType, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error) MarkConversationMessageAsReadDB(ctx context.Context, conversationID string, msgIDs []string) (rowsAffected int64, err error) MarkConversationMessageAsReadBySeqs(ctx context.Context, conversationID string, seqs []int64) (rowsAffected int64, err error) GetUnreadMessage(ctx context.Context, conversationID string) (result []*model_struct.LocalChatLog, err error) @@ -117,10 +118,10 @@ type MessageModel interface { GetTestMessage(ctx context.Context, seq uint32) (*model_struct.LocalChatLog, error) UpdateMsgSenderNickname(ctx context.Context, sendID, nickname string, sType int) error UpdateMsgSenderFaceURL(ctx context.Context, sendID, faceURL string, sType int) error - //UpdateMsgSenderFaceURLAndSenderNicknameController(ctx context.Context, sendID, faceURL, nickname string, sessionType int) error + // UpdateMsgSenderFaceURLAndSenderNicknameController(ctx context.Context, sendID, faceURL, nickname string, sessionType int) error UpdateMsgSenderFaceURLAndSenderNickname(ctx context.Context, conversationID, sendID, faceURL, nickname string) error GetMsgSeqByClientMsgID(ctx context.Context, clientMsgID string) (uint32, error) - //GetMsgSeqByClientMsgIDController(ctx context.Context, m *sdk_struct.MsgStruct) (uint32, error) + // GetMsgSeqByClientMsgIDController(ctx context.Context, m *sdk_struct.MsgStruct) (uint32, error) GetMsgSeqListByGroupID(ctx context.Context, groupID string) ([]uint32, error) GetMsgSeqListByPeerUserID(ctx context.Context, userID string) ([]uint32, error) GetMsgSeqListBySelfUserID(ctx context.Context, userID string) ([]uint32, error) @@ -139,7 +140,7 @@ type MessageModel interface { DeleteConversationAllMessages(ctx context.Context, conversationID string) error MarkDeleteConversationAllMessages(ctx context.Context, conversationID string) error SuperGroupSearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) - //SuperGroupSearchMessageByContentType(ctx context.Context, contentType []int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) + // SuperGroupSearchMessageByContentType(ctx context.Context, contentType []int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) SuperGroupSearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, startTime, endTime int64, groupID string) (result []*model_struct.LocalChatLog, err error) SuperGroupBatchUpdateMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error @@ -156,7 +157,7 @@ type MessageModel interface { SuperGroupGetMessageListNoTime(ctx context.Context, sourceID string, sessionType, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error) SuperGroupGetSendingMessageList(ctx context.Context, groupID string) (result []*model_struct.LocalChatLog, err error) SuperGroupUpdateGroupMessageHasRead(ctx context.Context, msgIDList []string, groupID string) error - //SuperGroupUpdateGroupMessageFields(ctx context.Context, msgIDList []string, groupID string, args map[string]interface{}) error + // SuperGroupUpdateGroupMessageFields(ctx context.Context, msgIDList []string, groupID string, args map[string]interface{}) error SuperGroupUpdateMsgSenderNickname(ctx context.Context, sendID, nickname string, sType int) error SuperGroupUpdateMsgSenderFaceURL(ctx context.Context, sendID, faceURL string, sType int) error @@ -170,8 +171,9 @@ type MessageModel interface { BatchInsertConversationUnreadMessageList(ctx context.Context, messageList []*model_struct.LocalConversationUnreadMessage) error DeleteConversationUnreadMessageList(ctx context.Context, conversationID string, sendTime int64) int64 DeleteConversationMsgs(ctx context.Context, conversationID string, msgIDs []string) error - //DeleteConversationMsgsBySeqs(ctx context.Context, conversationID string, seqs []int64) error + // DeleteConversationMsgsBySeqs(ctx context.Context, conversationID string, seqs []int64) error SetNotificationSeq(ctx context.Context, conversationID string, seq int64) error + BatchInsertNotificationSeq(ctx context.Context, notificationSeqs []*model_struct.NotificationSeqs) error GetNotificationAllSeqs(ctx context.Context) ([]*model_struct.NotificationSeqs, error) } @@ -226,9 +228,13 @@ type UserModel interface { type FriendModel interface { InsertFriend(ctx context.Context, friend *model_struct.LocalFriend) error DeleteFriendDB(ctx context.Context, friendUserID string) error + GetFriendListCount(ctx context.Context) (int64, error) UpdateFriend(ctx context.Context, friend *model_struct.LocalFriend) error GetAllFriendList(ctx context.Context) ([]*model_struct.LocalFriend, error) GetPageFriendList(ctx context.Context, offset, count int) ([]*model_struct.LocalFriend, error) + BatchInsertFriend(ctx context.Context, friendList []*model_struct.LocalFriend) error + DeleteAllFriend(ctx context.Context) error + SearchFriendList(ctx context.Context, keyword string, isSearchUserID, isSearchNickname, isSearchRemark bool) ([]*model_struct.LocalFriend, error) GetFriendInfoByFriendUserID(ctx context.Context, FriendUserID string) (*model_struct.LocalFriend, error) GetFriendInfoList(ctx context.Context, friendUserIDList []string) ([]*model_struct.LocalFriend, error) @@ -273,6 +279,16 @@ type SendingMessagesModel interface { GetAllSendingMessages(ctx context.Context) (friendRequests []*model_struct.LocalSendingMessages, err error) } +type VersionSyncModel interface { + GetVersionSync(ctx context.Context, tableName, entityID string) (*model_struct.LocalVersionSync, error) + SetVersionSync(ctx context.Context, version *model_struct.LocalVersionSync) error + DeleteVersionSync(ctx context.Context, tableName, entityID string) error +} +type AppSDKVersion interface { + GetAppSDKVersion(ctx context.Context) (*model_struct.LocalAppSDKVersion, error) + SetAppSDKVersion(ctx context.Context, version *model_struct.LocalAppSDKVersion) error +} + type DataBase interface { Close(ctx context.Context) error InitDB(ctx context.Context, userID string, dataDir string) error @@ -284,4 +300,6 @@ type DataBase interface { ReactionModel S3Model SendingMessagesModel + VersionSyncModel + AppSDKVersion } diff --git a/pkg/db/err_chat_log_model.go b/pkg/db/err_chat_log_model.go index 47d39c876..9c2a88097 100644 --- a/pkg/db/err_chat_log_model.go +++ b/pkg/db/err_chat_log_model.go @@ -19,9 +19,11 @@ package db import ( "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) initSuperLocalErrChatLog(ctx context.Context, groupID string) { @@ -34,19 +36,17 @@ func (d *DataBase) SuperBatchInsertExceptionMsg(ctx context.Context, MessageList return nil } d.initSuperLocalErrChatLog(ctx, groupID) - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Create(MessageList).Error, "BatchInsertMessageList failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Create(MessageList).Error, "BatchInsertMessageList failed") } func (d *DataBase) GetAbnormalMsgSeq(ctx context.Context) (int64, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seq int64 - err := d.conn.WithContext(ctx).Model(model_struct.LocalErrChatLog{}).Select("IFNULL(max(seq),0)").Find(&seq).Error - return seq, utils.Wrap(err, "GetAbnormalMsgSeq") + return seq, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalErrChatLog{}).Select("IFNULL(max(seq),0)").Find(&seq).Error, "GetAbnormalMsgSeq") } func (d *DataBase) GetAbnormalMsgSeqList(ctx context.Context) ([]int64, error) { var seqList []int64 - err := d.conn.WithContext(ctx).Model(model_struct.LocalErrChatLog{}).Select("seq").Find(&seqList).Error - return seqList, utils.Wrap(err, "GetAbnormalMsgSeqList") + return seqList, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalErrChatLog{}).Select("seq").Find(&seqList).Error, "GetAbnormalMsgSeqList") } func (d *DataBase) BatchInsertExceptionMsg(ctx context.Context, messageList []*model_struct.LocalErrChatLog) error { if messageList == nil { @@ -54,7 +54,7 @@ func (d *DataBase) BatchInsertExceptionMsg(ctx context.Context, messageList []*m } d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(messageList).Error, "BatchInsertMessageList failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(messageList).Error, "BatchInsertMessageList failed") } func (d *DataBase) BatchInsertExceptionMsgController(ctx context.Context, messageList []*model_struct.LocalErrChatLog) error { if len(messageList) == 0 { @@ -72,6 +72,5 @@ func (d *DataBase) GetConversationAbnormalMsgSeq(ctx context.Context, conversati if !d.conn.WithContext(ctx).Migrator().HasTable(utils.GetErrTableName(conversationID)) { return 0, nil } - err := d.conn.WithContext(ctx).Table(utils.GetErrTableName(conversationID)).Select("IFNULL(max(seq),0)").Find(&seq).Error - return seq, utils.Wrap(err, "GetConversationNormalMsgSeq") + return seq, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetErrTableName(conversationID)).Select("IFNULL(max(seq),0)").Find(&seq).Error, "GetConversationNormalMsgSeq") } diff --git a/pkg/db/friend_model.go b/pkg/db/friend_model.go index d55b2298c..f43c6382c 100644 --- a/pkg/db/friend_model.go +++ b/pkg/db/friend_model.go @@ -21,20 +21,30 @@ import ( "context" "errors" "fmt" + + "gorm.io/gorm" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) InsertFriend(ctx context.Context, friend *model_struct.LocalFriend) error { d.friendMtx.Lock() defer d.friendMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(friend).Error, "InsertFriend failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(friend).Error, "InsertFriend failed") } func (d *DataBase) DeleteFriendDB(ctx context.Context, friendUserID string) error { d.friendMtx.Lock() defer d.friendMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Where("owner_user_id=? and friend_user_id=?", d.loginUserID, friendUserID).Delete(&model_struct.LocalFriend{}).Error, "DeleteFriend failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id=? and friend_user_id=?", d.loginUserID, friendUserID).Delete(&model_struct.LocalFriend{}).Error, "DeleteFriend failed") +} + +func (d *DataBase) GetFriendListCount(ctx context.Context) (int64, error) { + d.friendMtx.Lock() + defer d.friendMtx.Unlock() + var count int64 + return count, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalFriend{}).Count(&count).Error, "GetFriendListCount failed") } func (d *DataBase) UpdateFriend(ctx context.Context, friend *model_struct.LocalFriend) error { @@ -43,39 +53,48 @@ func (d *DataBase) UpdateFriend(ctx context.Context, friend *model_struct.LocalF t := d.conn.WithContext(ctx).Model(friend).Select("*").Updates(*friend) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "") + return errs.Wrap(t.Error) } func (d *DataBase) GetAllFriendList(ctx context.Context) ([]*model_struct.LocalFriend, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - var friendList []model_struct.LocalFriend - err := utils.Wrap(d.conn.WithContext(ctx).Where("owner_user_id = ?", d.loginUserID).Find(&friendList).Error, + var friendList []*model_struct.LocalFriend + return friendList, errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id = ?", d.loginUserID).Find(&friendList).Error, "GetFriendList failed") - var transfer []*model_struct.LocalFriend - for _, v := range friendList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, err } func (d *DataBase) GetPageFriendList(ctx context.Context, offset, count int) ([]*model_struct.LocalFriend, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() var friendList []*model_struct.LocalFriend - err := utils.Wrap(d.conn.WithContext(ctx).Where("owner_user_id = ?", d.loginUserID).Offset(offset).Limit(count).Order("name").Find(&friendList).Error, + err := errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id = ?", d.loginUserID).Offset(offset).Limit(count).Order("name").Find(&friendList).Error, "GetFriendList failed") return friendList, err } +func (d *DataBase) BatchInsertFriend(ctx context.Context, friendList []*model_struct.LocalFriend) error { + d.friendMtx.Lock() + defer d.friendMtx.Unlock() + if friendList == nil { + return errs.New("nil").Wrap() + } + return errs.WrapMsg(d.conn.WithContext(ctx).Create(friendList).Error, "BatchInsertFriendList failed") +} + +func (d *DataBase) DeleteAllFriend(ctx context.Context) error { + d.friendMtx.Lock() + defer d.friendMtx.Unlock() + return errs.WrapMsg(d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&model_struct.LocalFriend{}).Error, "DeleteAllFriend failed") +} + func (d *DataBase) SearchFriendList(ctx context.Context, keyword string, isSearchUserID, isSearchNickname, isSearchRemark bool) ([]*model_struct.LocalFriend, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() var count int - var friendList []model_struct.LocalFriend + var friendList []*model_struct.LocalFriend var condition string if isSearchUserID { condition = fmt.Sprintf("friend_user_id like %q ", "%"+keyword+"%") @@ -95,41 +114,26 @@ func (d *DataBase) SearchFriendList(ctx context.Context, keyword string, isSearc condition += fmt.Sprintf("remark like %q ", "%"+keyword+"%") } err := d.conn.WithContext(ctx).Where(condition).Order("create_time DESC").Find(&friendList).Error - var transfer []*model_struct.LocalFriend - for _, v := range friendList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "SearchFriendList failed ") - + return friendList, errs.WrapMsg(err, "SearchFriendList failed") } func (d *DataBase) GetFriendInfoByFriendUserID(ctx context.Context, FriendUserID string) (*model_struct.LocalFriend, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() var friend model_struct.LocalFriend - return &friend, utils.Wrap(d.conn.WithContext(ctx).Where("owner_user_id = ? AND friend_user_id = ?", + return &friend, errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id = ? AND friend_user_id = ?", d.loginUserID, FriendUserID).Take(&friend).Error, "GetFriendInfoByFriendUserID failed") } func (d *DataBase) GetFriendInfoList(ctx context.Context, friendUserIDList []string) ([]*model_struct.LocalFriend, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - var friendList []model_struct.LocalFriend - err := utils.Wrap(d.conn.WithContext(ctx).Where("friend_user_id IN ?", friendUserIDList).Find(&friendList).Error, "GetFriendInfoListByFriendUserID failed") - var transfer []*model_struct.LocalFriend - for _, v := range friendList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, err + var friendList []*model_struct.LocalFriend + err := errs.WrapMsg(d.conn.WithContext(ctx).Where("friend_user_id IN ?", friendUserIDList).Find(&friendList).Error, "GetFriendInfoListByFriendUserID failed") + return friendList, err } func (d *DataBase) UpdateColumnsFriend(ctx context.Context, friendIDs []string, args map[string]interface{}) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - - // Update records where FriendUserID is in the friendIDs slice - t := d.conn.WithContext(ctx).Model(&model_struct.LocalFriend{}).Where("friend_user_id IN ?", friendIDs).Updates(args) - - return utils.Wrap(t.Error, "UpdateColumnsFriend failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalFriend{}).Where("friend_user_id IN ?", friendIDs).Updates(args).Error, "UpdateColumnsFriend failed") } diff --git a/pkg/db/friend_request_model.go b/pkg/db/friend_request_model.go index a9620e012..2bf0dbbb6 100644 --- a/pkg/db/friend_request_model.go +++ b/pkg/db/friend_request_model.go @@ -20,20 +20,21 @@ package db import ( "context" "errors" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) InsertFriendRequest(ctx context.Context, friendRequest *model_struct.LocalFriendRequest) error { d.friendMtx.Lock() defer d.friendMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(friendRequest).Error, "InsertFriendRequest failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(friendRequest).Error, "InsertFriendRequest failed") } func (d *DataBase) DeleteFriendRequestBothUserID(ctx context.Context, fromUserID, toUserID string) error { d.friendMtx.Lock() defer d.friendMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Where("from_user_id=? and to_user_id=?", fromUserID, toUserID).Delete(&model_struct.LocalFriendRequest{}).Error, "DeleteFriendRequestBothUserID failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Where("from_user_id=? and to_user_id=?", fromUserID, toUserID).Delete(&model_struct.LocalFriendRequest{}).Error, "DeleteFriendRequestBothUserID failed") } func (d *DataBase) UpdateFriendRequest(ctx context.Context, friendRequest *model_struct.LocalFriendRequest) error { @@ -41,50 +42,35 @@ func (d *DataBase) UpdateFriendRequest(ctx context.Context, friendRequest *model defer d.friendMtx.Unlock() t := d.conn.WithContext(ctx).Model(friendRequest).Select("*").Updates(*friendRequest) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "") + return errs.Wrap(t.Error) } func (d *DataBase) GetRecvFriendApplication(ctx context.Context) ([]*model_struct.LocalFriendRequest, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - var friendRequestList []model_struct.LocalFriendRequest - err := utils.Wrap(d.conn.WithContext(ctx).Where("to_user_id = ?", d.loginUserID).Order("create_time DESC").Find(&friendRequestList).Error, "GetRecvFriendApplication failed") + var friendRequestList []*model_struct.LocalFriendRequest - var transfer []*model_struct.LocalFriendRequest - for _, v := range friendRequestList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "GetRecvFriendApplication failed") + return friendRequestList, errs.WrapMsg(d.conn.WithContext(ctx).Where("to_user_id = ?", d.loginUserID).Order("create_time DESC").Find(&friendRequestList).Error, "GetRecvFriendApplication failed") } func (d *DataBase) GetSendFriendApplication(ctx context.Context) ([]*model_struct.LocalFriendRequest, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - var friendRequestList []model_struct.LocalFriendRequest - err := utils.Wrap(d.conn.WithContext(ctx).Where("from_user_id = ?", d.loginUserID).Order("create_time DESC").Find(&friendRequestList).Error, "GetSendFriendApplication failed") - - var transfer []*model_struct.LocalFriendRequest - for _, v := range friendRequestList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "GetSendFriendApplication failed") + var friendRequestList []*model_struct.LocalFriendRequest + return friendRequestList, errs.WrapMsg(d.conn.WithContext(ctx).Where("from_user_id = ?", d.loginUserID).Order("create_time DESC").Find(&friendRequestList).Error, "GetSendFriendApplication failed") } func (d *DataBase) GetFriendApplicationByBothID(ctx context.Context, fromUserID, toUserID string) (*model_struct.LocalFriendRequest, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() var friendRequest model_struct.LocalFriendRequest - err := utils.Wrap(d.conn.WithContext(ctx).Where("from_user_id = ? AND to_user_id = ?", fromUserID, toUserID).Take(&friendRequest).Error, "GetFriendApplicationByBothID failed") - return &friendRequest, utils.Wrap(err, "GetFriendApplicationByBothID failed") + return &friendRequest, errs.WrapMsg(d.conn.WithContext(ctx).Where("from_user_id = ? AND to_user_id = ?", fromUserID, toUserID).Take(&friendRequest).Error, "GetFriendApplicationByBothID failed") } func (d *DataBase) GetBothFriendReq(ctx context.Context, fromUserID, toUserID string) (friendRequests []*model_struct.LocalFriendRequest, err error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - err = utils.Wrap(d.conn.WithContext(ctx).Where("(from_user_id = ? AND to_user_id = ?) OR (from_user_id = ? AND to_user_id = ?)", fromUserID, toUserID, toUserID, fromUserID).Find(&friendRequests).Error, "GetFriendApplicationByBothID failed") - return friendRequests, utils.Wrap(err, "GetFriendApplicationByBothID failed") + return friendRequests, errs.WrapMsg(d.conn.WithContext(ctx).Where("(from_user_id = ? AND to_user_id = ?) OR (from_user_id = ? AND to_user_id = ?)", fromUserID, toUserID, toUserID, fromUserID).Find(&friendRequests).Error, "GetFriendApplicationByBothID failed") } diff --git a/pkg/db/group_member_model.go b/pkg/db/group_member_model.go index 1d9bffc1e..33436ae2d 100644 --- a/pkg/db/group_member_model.go +++ b/pkg/db/group_member_model.go @@ -21,16 +21,17 @@ import ( "context" "errors" "fmt" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) GetGroupMemberInfoByGroupIDUserID(ctx context.Context, groupID, userID string) (*model_struct.LocalGroupMember, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() var groupMember model_struct.LocalGroupMember - return &groupMember, utils.Wrap(d.conn.WithContext(ctx).Where("group_id = ? AND user_id = ?", + return &groupMember, errs.WrapMsg(d.conn.WithContext(ctx).Where("group_id = ? AND user_id = ?", groupID, userID).Take(&groupMember).Error, "GetGroupMemberInfoByGroupIDUserID failed") } @@ -38,13 +39,13 @@ func (d *DataBase) GetAllGroupMemberList(ctx context.Context) ([]model_struct.Lo d.groupMtx.Lock() defer d.groupMtx.Unlock() var groupMemberList []model_struct.LocalGroupMember - return groupMemberList, utils.Wrap(d.conn.WithContext(ctx).Find(&groupMemberList).Error, "GetAllGroupMemberList failed") + return groupMemberList, errs.WrapMsg(d.conn.WithContext(ctx).Find(&groupMemberList).Error, "GetAllGroupMemberList failed") } func (d *DataBase) GetAllGroupMemberUserIDList(ctx context.Context) ([]model_struct.LocalGroupMember, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() var groupMemberList []model_struct.LocalGroupMember - return groupMemberList, utils.Wrap(d.conn.WithContext(ctx).Find(&groupMemberList).Error, "GetAllGroupMemberList failed") + return groupMemberList, errs.WrapMsg(d.conn.WithContext(ctx).Find(&groupMemberList).Error, "GetAllGroupMemberList failed") } func (d *DataBase) GetGroupMemberCount(ctx context.Context, groupID string) (int32, error) { @@ -52,44 +53,61 @@ func (d *DataBase) GetGroupMemberCount(ctx context.Context, groupID string) (int defer d.groupMtx.Unlock() var count int64 err := d.conn.WithContext(ctx).Model(&model_struct.LocalGroupMember{}).Where("group_id = ? ", groupID).Count(&count).Error - return int32(count), utils.Wrap(err, "GetGroupMemberCount failed") + return int32(count), errs.WrapMsg(err, "GetGroupMemberCount failed") } func (d *DataBase) GetGroupSomeMemberInfo(ctx context.Context, groupID string, userIDList []string) ([]*model_struct.LocalGroupMember, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupMemberList []model_struct.LocalGroupMember + var groupMemberList []*model_struct.LocalGroupMember err := d.conn.WithContext(ctx).Where("group_id = ? And user_id IN ? ", groupID, userIDList).Find(&groupMemberList).Error - var transfer []*model_struct.LocalGroupMember - for _, v := range groupMemberList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "GetGroupMemberListByGroupID failed ") + return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListByGroupID failed ") } func (d *DataBase) GetGroupAdminID(ctx context.Context, groupID string) ([]string, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() var adminIDList []string - return adminIDList, utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalGroupMember{}).Select("user_id").Where("group_id = ? And role_level = ?", groupID, constant.GroupAdmin).Find(&adminIDList).Error, "") + return adminIDList, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalGroupMember{}).Select("user_id").Where("group_id = ? And role_level = ?", groupID, constant.GroupAdmin).Find(&adminIDList).Error, "") } func (d *DataBase) GetGroupMemberListByGroupID(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupMemberList []model_struct.LocalGroupMember + var groupMemberList []*model_struct.LocalGroupMember err := d.conn.WithContext(ctx).Where("group_id = ? ", groupID).Find(&groupMemberList).Error - var transfer []*model_struct.LocalGroupMember - for _, v := range groupMemberList { - v1 := v - transfer = append(transfer, &v1) + return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListByGroupID failed ") +} + +func (d *DataBase) GetGroupMemberListByUserIDs(ctx context.Context, groupID string, filter int32, userIDs []string) ([]*model_struct.LocalGroupMember, error) { + d.groupMtx.Lock() + defer d.groupMtx.Unlock() + var groupMemberList []*model_struct.LocalGroupMember + var err error + switch filter { + case constant.GroupFilterAll: + err = d.conn.WithContext(ctx).Where("group_id = ? AND user_id IN ?", groupID, userIDs).Order("role_level DESC, join_time ASC").Find(&groupMemberList).Error + case constant.GroupFilterOwner: + err = d.conn.WithContext(ctx).Where("group_id = ? AND role_level = ? AND user_id IN ?", groupID, constant.GroupOwner, userIDs).Find(&groupMemberList).Error + case constant.GroupFilterAdmin: + err = d.conn.WithContext(ctx).Where("group_id = ? AND role_level = ? AND user_id IN ?", groupID, constant.GroupAdmin, userIDs).Find(&groupMemberList).Error + case constant.GroupFilterOrdinaryUsers: + err = d.conn.WithContext(ctx).Where("group_id = ? AND role_level = ? AND user_id IN ?", groupID, constant.GroupOrdinaryUsers, userIDs).Find(&groupMemberList).Error + case constant.GroupFilterAdminAndOrdinaryUsers: + err = d.conn.WithContext(ctx).Where("group_id = ? AND (role_level = ? OR role_level = ?) AND user_id IN ?", groupID, constant.GroupAdmin, constant.GroupOrdinaryUsers, userIDs).Find(&groupMemberList).Error + case constant.GroupFilterOwnerAndAdmin: + err = d.conn.WithContext(ctx).Where("group_id = ? AND (role_level = ? OR role_level = ?) AND user_id IN ?", groupID, constant.GroupOwner, constant.GroupAdmin, userIDs).Find(&groupMemberList).Error + default: + return nil, errs.New("filter args failed.", "filter", filter).Wrap() } - return transfer, utils.Wrap(err, "GetGroupMemberListByGroupID failed ") + + return groupMemberList, errs.Wrap(err) + } + func (d *DataBase) GetGroupMemberListSplit(ctx context.Context, groupID string, filter int32, offset, count int) ([]*model_struct.LocalGroupMember, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupMemberList []model_struct.LocalGroupMember + var groupMemberList []*model_struct.LocalGroupMember var err error switch filter { case constant.GroupFilterAll: @@ -105,27 +123,19 @@ func (d *DataBase) GetGroupMemberListSplit(ctx context.Context, groupID string, case constant.GroupFilterOwnerAndAdmin: err = d.conn.WithContext(ctx).Where("group_id = ? And (role_level = ? or role_level = ?)", groupID, constant.GroupOwner, constant.GroupAdmin).Order("role_level DESC,join_time ASC").Offset(offset).Limit(count).Find(&groupMemberList).Error default: - return nil, fmt.Errorf("filter args failed %d", filter) - } - var transfer []*model_struct.LocalGroupMember - for _, v := range groupMemberList { - v1 := v - transfer = append(transfer, &v1) + return nil, errs.New("filter args failed", "filter", filter).Wrap() } - return transfer, utils.Wrap(err, "GetGroupMemberListSplit failed ") + + return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListSplit failed ") } func (d *DataBase) GetGroupMemberOwnerAndAdminDB(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupMemberList []model_struct.LocalGroupMember + var groupMemberList []*model_struct.LocalGroupMember err := d.conn.WithContext(ctx).Where("group_id = ? And (role_level = ? OR role_level = ?)", groupID, constant.GroupOwner, constant.GroupAdmin).Order("join_time DESC").Find(&groupMemberList).Error - var transfer []*model_struct.LocalGroupMember - for _, v := range groupMemberList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "GetGroupMemberListSplit failed ") + + return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListSplit failed ") } func (d *DataBase) GetGroupMemberOwner(ctx context.Context, groupID string) (*model_struct.LocalGroupMember, error) { @@ -133,38 +143,28 @@ func (d *DataBase) GetGroupMemberOwner(ctx context.Context, groupID string) (*mo defer d.groupMtx.Unlock() var groupMember model_struct.LocalGroupMember err := d.conn.WithContext(ctx).Where("group_id = ? And role_level = ?", groupID, constant.GroupOwner).Find(&groupMember).Error - return &groupMember, utils.Wrap(err, "GetGroupMemberListSplit failed ") + return &groupMember, errs.WrapMsg(err, "GetGroupMemberListSplit failed ") } func (d *DataBase) GetGroupMemberListSplitByJoinTimeFilter(ctx context.Context, groupID string, offset, count int, joinTimeBegin, joinTimeEnd int64, userIDList []string) ([]*model_struct.LocalGroupMember, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupMemberList []model_struct.LocalGroupMember + var groupMemberList []*model_struct.LocalGroupMember var err error if len(userIDList) == 0 { err = d.conn.WithContext(ctx).Where("group_id = ? And join_time between ? and ? ", groupID, joinTimeBegin, joinTimeEnd).Order("join_time DESC").Offset(offset).Limit(count).Find(&groupMemberList).Error } else { err = d.conn.WithContext(ctx).Where("group_id = ? And join_time between ? and ? And user_id NOT IN ?", groupID, joinTimeBegin, joinTimeEnd, userIDList).Order("join_time DESC").Offset(offset).Limit(count).Find(&groupMemberList).Error } - var transfer []*model_struct.LocalGroupMember - for _, v := range groupMemberList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "GetGroupMemberListSplitByJoinTimeFilter failed ") + return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListSplitByJoinTimeFilter failed ") } func (d *DataBase) GetGroupOwnerAndAdminByGroupID(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupMemberList []model_struct.LocalGroupMember + var groupMemberList []*model_struct.LocalGroupMember err := d.conn.WithContext(ctx).Where("group_id = ? AND (role_level = ? Or role_level = ?)", groupID, constant.GroupOwner, constant.GroupAdmin).Find(&groupMemberList).Error - var transfer []*model_struct.LocalGroupMember - for _, v := range groupMemberList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "GetGroupMemberListByGroupID failed ") + return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListByGroupID failed ") } func (d *DataBase) GetGroupMemberUIDListByGroupID(ctx context.Context, groupID string) (result []string, err error) { @@ -173,13 +173,13 @@ func (d *DataBase) GetGroupMemberUIDListByGroupID(ctx context.Context, groupID s var g model_struct.LocalGroupMember g.GroupID = groupID err = d.conn.WithContext(ctx).Model(&g).Where("group_id = ?", groupID).Pluck("user_id", &result).Error - return result, utils.Wrap(err, "GetGroupMemberListByGroupID failed ") + return result, errs.WrapMsg(err, "GetGroupMemberListByGroupID failed ") } func (d *DataBase) InsertGroupMember(ctx context.Context, groupMember *model_struct.LocalGroupMember) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(groupMember).Error, "") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupMember).Error, "") } //funcation (d *DataBase) BatchInsertMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error { @@ -188,29 +188,26 @@ func (d *DataBase) InsertGroupMember(ctx context.Context, groupMember *model_str // } // d.mRWMutex.Lock() // defer d.mRWMutex.Unlock() -// return utils.Wrap(d.conn.WithContext(ctx).Create(MessageList).Error, "BatchInsertMessageList failed") +// return errs.WrapMsg(d.conn.WithContext(ctx).Create(MessageList).Error, "BatchInsertMessageList failed") //} func (d *DataBase) BatchInsertGroupMember(ctx context.Context, groupMemberList []*model_struct.LocalGroupMember) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() - if groupMemberList == nil { - return errors.New("nil") - } - return utils.Wrap(d.conn.WithContext(ctx).Create(groupMemberList).Error, "BatchInsertMessageList failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupMemberList).Error, "BatchInsertGroupMember failed") } func (d *DataBase) DeleteGroupMember(ctx context.Context, groupID, userID string) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() - groupMember := model_struct.LocalGroupMember{} + var groupMember model_struct.LocalGroupMember return d.conn.WithContext(ctx).Where("group_id=? and user_id=?", groupID, userID).Delete(&groupMember).Error } func (d *DataBase) DeleteGroupAllMembers(ctx context.Context, groupID string) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() - groupMember := model_struct.LocalGroupMember{} + var groupMember model_struct.LocalGroupMember return d.conn.WithContext(ctx).Where("group_id=? ", groupID).Delete(&groupMember).Error } @@ -219,9 +216,9 @@ func (d *DataBase) UpdateGroupMember(ctx context.Context, groupMember *model_str defer d.groupMtx.Unlock() t := d.conn.WithContext(ctx).Model(groupMember).Select("*").Updates(*groupMember) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "") + return errs.WrapMsg(t.Error, "") } func (d *DataBase) UpdateGroupMemberField(ctx context.Context, groupID, userID string, args map[string]interface{}) error { @@ -230,21 +227,21 @@ func (d *DataBase) UpdateGroupMemberField(ctx context.Context, groupID, userID s c := model_struct.LocalGroupMember{GroupID: groupID, UserID: userID} t := d.conn.WithContext(ctx).Model(&c).Updates(args) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateGroupMemberField failed") + return errs.WrapMsg(t.Error, "UpdateGroupMemberField failed") } func (d *DataBase) GetGroupMemberInfoIfOwnerOrAdmin(ctx context.Context) ([]*model_struct.LocalGroupMember, error) { var ownerAndAdminList []*model_struct.LocalGroupMember groupList, err := d.GetJoinedGroupListDB(ctx) if err != nil { - return nil, utils.Wrap(err, "") + return nil, errs.Wrap(err) } for _, v := range groupList { memberList, err := d.GetGroupOwnerAndAdminByGroupID(ctx, v.GroupID) if err != nil { - return nil, utils.Wrap(err, "") + return nil, errs.Wrap(err) } ownerAndAdminList = append(ownerAndAdminList, memberList...) } diff --git a/pkg/db/group_model.go b/pkg/db/group_model.go index bc2fe6651..4153c2674 100644 --- a/pkg/db/group_model.go +++ b/pkg/db/group_model.go @@ -21,8 +21,9 @@ import ( "context" "errors" "fmt" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" "gorm.io/gorm" ) @@ -30,13 +31,13 @@ import ( func (d *DataBase) InsertGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(groupInfo).Error, "InsertGroup failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupInfo).Error, "InsertGroup failed") } func (d *DataBase) DeleteGroup(ctx context.Context, groupID string) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() localGroup := model_struct.LocalGroup{GroupID: groupID} - return utils.Wrap(d.conn.WithContext(ctx).Delete(&localGroup).Error, "DeleteGroup failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Delete(&localGroup).Error, "DeleteGroup failed") } func (d *DataBase) UpdateGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error { d.groupMtx.Lock() @@ -44,48 +45,49 @@ func (d *DataBase) UpdateGroup(ctx context.Context, groupInfo *model_struct.Loca t := d.conn.WithContext(ctx).Model(groupInfo).Select("*").Updates(*groupInfo) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "") + return errs.Wrap(t.Error) +} +func (d *DataBase) BatchInsertGroup(ctx context.Context, groupList []*model_struct.LocalGroup) error { + d.groupMtx.Lock() + defer d.groupMtx.Unlock() + return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupList).Error, "BatchInsertGroup failed") +} +func (d *DataBase) DeleteAllGroup(ctx context.Context) error { + d.groupMtx.Lock() + defer d.groupMtx.Unlock() + return errs.WrapMsg(d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&model_struct.LocalGroup{}).Error, "DeleteAllGroup failed") } + func (d *DataBase) GetJoinedGroupListDB(ctx context.Context) ([]*model_struct.LocalGroup, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupList []model_struct.LocalGroup + var groupList []*model_struct.LocalGroup err := d.conn.WithContext(ctx).Find(&groupList).Error - var transfer []*model_struct.LocalGroup - for _, v := range groupList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "GetJoinedGroupList failed ") + return groupList, errs.WrapMsg(err, "GetJoinedGroupList failed ") } func (d *DataBase) GetGroups(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupList []model_struct.LocalGroup + var groupList []*model_struct.LocalGroup err := d.conn.WithContext(ctx).Where("group_id in (?)", groupIDs).Find(&groupList).Error - var transfer []*model_struct.LocalGroup - for _, v := range groupList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "GetGroups failed ") + return groupList, errs.WrapMsg(err, "GetGroups failed ") } func (d *DataBase) GetGroupInfoByGroupID(ctx context.Context, groupID string) (*model_struct.LocalGroup, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() var g model_struct.LocalGroup - return &g, utils.Wrap(d.conn.WithContext(ctx).Where("group_id = ?", groupID).Take(&g).Error, "GetGroupList failed") + return &g, errs.WrapMsg(d.conn.WithContext(ctx).Where("group_id = ?", groupID).Take(&g).Error, "GetGroupList failed") } func (d *DataBase) GetAllGroupInfoByGroupIDOrGroupName(ctx context.Context, keyword string, isSearchGroupID bool, isSearchGroupName bool) ([]*model_struct.LocalGroup, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupList []model_struct.LocalGroup + var groupList []*model_struct.LocalGroup var condition string if isSearchGroupID { if isSearchGroupName { @@ -97,24 +99,19 @@ func (d *DataBase) GetAllGroupInfoByGroupIDOrGroupName(ctx context.Context, keyw condition = fmt.Sprintf("name like %q ", "%"+keyword+"%") } err := d.conn.WithContext(ctx).Where(condition).Order("create_time DESC").Find(&groupList).Error - var transfer []*model_struct.LocalGroup - for _, v := range groupList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, utils.Wrap(err, "GetAllGroupInfoByGroupIDOrGroupName failed ") + return groupList, errs.WrapMsg(err, "GetAllGroupInfoByGroupIDOrGroupName failed ") } func (d *DataBase) AddMemberCount(ctx context.Context, groupID string) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() group := model_struct.LocalGroup{GroupID: groupID} - return utils.Wrap(d.conn.WithContext(ctx).Model(&group).Updates(map[string]interface{}{"member_count": gorm.Expr("member_count+1")}).Error, "") + return errs.WrapMsg(d.conn.WithContext(ctx).Model(&group).Updates(map[string]interface{}{"member_count": gorm.Expr("member_count+1")}).Error, "") } func (d *DataBase) SubtractMemberCount(ctx context.Context, groupID string) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() group := model_struct.LocalGroup{GroupID: groupID} - return utils.Wrap(d.conn.WithContext(ctx).Model(&group).Updates(map[string]interface{}{"member_count": gorm.Expr("member_count-1")}).Error, "") + return errs.WrapMsg(d.conn.WithContext(ctx).Model(&group).Updates(map[string]interface{}{"member_count": gorm.Expr("member_count-1")}).Error, "") } diff --git a/pkg/db/group_request_model.go b/pkg/db/group_request_model.go index 4e90b3e8d..856175f0b 100644 --- a/pkg/db/group_request_model.go +++ b/pkg/db/group_request_model.go @@ -20,42 +20,34 @@ package db import ( "context" "errors" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) InsertGroupRequest(ctx context.Context, groupRequest *model_struct.LocalGroupRequest) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(groupRequest).Error, "InsertGroupRequest failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupRequest).Error, "InsertGroupRequest failed") } func (d *DataBase) DeleteGroupRequest(ctx context.Context, groupID, userID string) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Where("group_id=? and user_id=?", groupID, userID).Delete(&model_struct.LocalGroupRequest{}).Error, "DeleteGroupRequest failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Where("group_id=? and user_id=?", groupID, userID).Delete(&model_struct.LocalGroupRequest{}).Error, "DeleteGroupRequest failed") } func (d *DataBase) UpdateGroupRequest(ctx context.Context, groupRequest *model_struct.LocalGroupRequest) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() t := d.conn.WithContext(ctx).Model(groupRequest).Select("*").Updates(*groupRequest) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "") + return errs.Wrap(t.Error) } func (d *DataBase) GetSendGroupApplication(ctx context.Context) ([]*model_struct.LocalGroupRequest, error) { d.groupMtx.Lock() defer d.groupMtx.Unlock() - var groupRequestList []model_struct.LocalGroupRequest - err := utils.Wrap(d.conn.WithContext(ctx).Order("create_time DESC").Find(&groupRequestList).Error, "") - if err != nil { - return nil, utils.Wrap(err, "") - } - var transfer []*model_struct.LocalGroupRequest - for _, v := range groupRequestList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, nil + var groupRequestList []*model_struct.LocalGroupRequest + return groupRequestList, errs.Wrap(d.conn.WithContext(ctx).Order("create_time DESC").Find(&groupRequestList).Error) } diff --git a/pkg/db/model_struct/data_model_struct.go b/pkg/db/model_struct/data_model_struct.go index b6aa075a6..300d00f1c 100644 --- a/pkg/db/model_struct/data_model_struct.go +++ b/pkg/db/model_struct/data_model_struct.go @@ -14,6 +14,13 @@ package model_struct +import ( + "database/sql/driver" + "encoding/json" + + "github.com/openimsdk/tools/errs" +) + // //message FriendInfo{ //string OwnerUserID = 1; @@ -51,13 +58,13 @@ type LocalFriend struct { OperatorUserID string `gorm:"column:operator_user_id;type:varchar(64)" json:"operatorUserID"` Nickname string `gorm:"column:name;type:varchar;type:varchar(255)" json:"nickname"` FaceURL string `gorm:"column:face_url;type:varchar;type:varchar(255)" json:"faceURL"` - //Gender int32 `gorm:"column:gender" json:"gender"` - //PhoneNumber string `gorm:"column:phone_number;type:varchar(32)" json:"phoneNumber"` - //Birth uint32 `gorm:"column:birth" json:"birth"` - //Email string `gorm:"column:email;type:varchar(64)" json:"email"` - Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"` - AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"` - IsPinned bool `gorm:"column:is_pinned;" json:"isPinned"` + Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"` + AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"` + IsPinned bool `gorm:"column:is_pinned;" json:"isPinned"` +} + +func (LocalFriend) TableName() string { + return "local_friends" } // message FriendRequest{ @@ -76,12 +83,12 @@ type LocalFriendRequest struct { FromUserID string `gorm:"column:from_user_id;primary_key;type:varchar(64)" json:"fromUserID"` FromNickname string `gorm:"column:from_nickname;type:varchar;type:varchar(255)" json:"fromNickname"` FromFaceURL string `gorm:"column:from_face_url;type:varchar;type:varchar(255)" json:"fromFaceURL"` - //FromGender int32 `gorm:"column:from_gender" json:"fromGender"` + // FromGender int32 `gorm:"column:from_gender" json:"fromGender"` ToUserID string `gorm:"column:to_user_id;primary_key;type:varchar(64)" json:"toUserID"` ToNickname string `gorm:"column:to_nickname;type:varchar;type:varchar(255)" json:"toNickname"` ToFaceURL string `gorm:"column:to_face_url;type:varchar;type:varchar(255)" json:"toFaceURL"` - //ToGender int32 `gorm:"column:to_gender" json:"toGender"` + // ToGender int32 `gorm:"column:to_gender" json:"toGender"` HandleResult int32 `gorm:"column:handle_result" json:"handleResult"` ReqMsg string `gorm:"column:req_msg;type:varchar(255)" json:"reqMsg"` @@ -143,6 +150,10 @@ type LocalGroup struct { NotificationUserID string `gorm:"column:notification_user_id;size:64" json:"notificationUserID"` } +func (LocalGroup) TableName() string { + return "local_groups" +} + //message GroupMemberFullInfo { //string GroupID = 1 ; //string UserID = 2 ; @@ -179,6 +190,10 @@ type LocalGroupMember struct { AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"` } +func (LocalGroupMember) TableName() string { + return "local_group_members" +} + // message GroupRequest{ // string UserID = 1; // string GroupID = 2; @@ -206,7 +221,7 @@ type LocalGroupRequest struct { UserID string `gorm:"column:user_id;primary_key;type:varchar(64)" json:"userID"` Nickname string `gorm:"column:nickname;type:varchar(255)" json:"nickname"` UserFaceURL string `gorm:"column:user_face_url;type:varchar(255)" json:"userFaceURL"` - //Gender int32 `gorm:"column:gender" json:"gender"` + // Gender int32 `gorm:"column:gender" json:"gender"` HandleResult int32 `gorm:"column:handle_result" json:"handleResult"` ReqMsg string `gorm:"column:req_msg;type:varchar(255)" json:"reqMsg"` @@ -256,7 +271,7 @@ type LocalBlack struct { BlockUserID string `gorm:"column:block_user_id;primary_key;type:varchar(64)" json:"userID"` Nickname string `gorm:"column:nickname;type:varchar(255)" json:"nickname"` FaceURL string `gorm:"column:face_url;type:varchar(255)" json:"faceURL"` - //Gender int32 `gorm:"column:gender" json:"gender"` + // Gender int32 `gorm:"column:gender" json:"gender"` CreateTime int64 `gorm:"column:create_time" json:"createTime"` AddSource int32 `gorm:"column:add_source" json:"addSource"` OperatorUserID string `gorm:"column:operator_user_id;type:varchar(64)" json:"operatorUserID"` @@ -535,3 +550,38 @@ type LocalUserCommand struct { func (LocalUserCommand) TableName() string { return "local_user_command" } + +type StringArray []string + +func (a StringArray) Value() (driver.Value, error) { + return json.Marshal(a) +} + +func (a *StringArray) Scan(value interface{}) error { + b, ok := value.([]byte) + if !ok { + return errs.New("type assertion to []byte failed").Wrap() + } + return json.Unmarshal(b, &a) +} + +type LocalVersionSync struct { + Table string `gorm:"column:table;type:varchar(255);primary_key" json:"table"` + EntityID string `gorm:"column:entity_id;type:varchar(255);primary_key" json:"entityID"` + VersionID string `gorm:"column:version_id" json:"versionID"` + Version uint64 `gorm:"column:version" json:"version"` + CreateTime int64 `gorm:"column:create_time" json:"createTime"` + UIDList StringArray `gorm:"column:id_list;type:text" json:"uidList"` +} + +func (LocalVersionSync) TableName() string { + return "local_sync_version" +} + +type LocalAppSDKVersion struct { + Version string `gorm:"column:version;type:varchar(255);primary_key" json:"version"` +} + +func (LocalAppSDKVersion) TableName() string { + return "local_app_sdk_version" +} diff --git a/pkg/db/notification_model.go b/pkg/db/notification_model.go index 70fc13853..a940338c9 100644 --- a/pkg/db/notification_model.go +++ b/pkg/db/notification_model.go @@ -19,8 +19,9 @@ package db import ( "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) SetNotificationSeq(ctx context.Context, conversationID string, seq int64) error { @@ -28,17 +29,23 @@ func (d *DataBase) SetNotificationSeq(ctx context.Context, conversationID string defer d.mRWMutex.Unlock() cursor := d.conn.WithContext(ctx).Model(&model_struct.NotificationSeqs{}).Where("conversation_id = ?", conversationID).Updates(map[string]interface{}{"seq": seq}) if cursor.Error != nil { - return utils.Wrap(cursor.Error, "Updates failed") + return errs.WrapMsg(cursor.Error, "Updates failed") } if cursor.RowsAffected == 0 { - return utils.Wrap(d.conn.WithContext(ctx).Create(&model_struct.NotificationSeqs{ConversationID: conversationID, Seq: seq}).Error, "Create failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(&model_struct.NotificationSeqs{ConversationID: conversationID, Seq: seq}).Error, "Create failed") } return nil } +func (d *DataBase) BatchInsertNotificationSeq(ctx context.Context, notificationSeqs []*model_struct.NotificationSeqs) error { + d.mRWMutex.Lock() + defer d.mRWMutex.Unlock() + return errs.WrapMsg(d.conn.WithContext(ctx).Create(notificationSeqs).Error, "BatchInsertNotificationSeq failed") +} + func (d *DataBase) GetNotificationAllSeqs(ctx context.Context) ([]*model_struct.NotificationSeqs, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seqs []*model_struct.NotificationSeqs - return seqs, utils.Wrap(d.conn.WithContext(ctx).Where("1=1").Find(&seqs).Error, "GetNotificationAllSeqs failed") + return seqs, errs.WrapMsg(d.conn.WithContext(ctx).Where("1=1").Find(&seqs).Error, "GetNotificationAllSeqs failed") } diff --git a/pkg/db/sending_messages_model.go b/pkg/db/sending_messages_model.go index 5065622fb..6947faded 100644 --- a/pkg/db/sending_messages_model.go +++ b/pkg/db/sending_messages_model.go @@ -19,25 +19,25 @@ package db import ( "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) InsertSendingMessage(ctx context.Context, message *model_struct.LocalSendingMessages) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(message).Error, "InsertSendingMessage failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(message).Error, "InsertSendingMessage failed") } func (d *DataBase) DeleteSendingMessage(ctx context.Context, conversationID, clientMsgID string) error { d.groupMtx.Lock() defer d.groupMtx.Unlock() localSendingMessage := model_struct.LocalSendingMessages{ConversationID: conversationID, ClientMsgID: clientMsgID} - return utils.Wrap(d.conn.WithContext(ctx).Delete(&localSendingMessage).Error, "DeleteSendingMessage failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Delete(&localSendingMessage).Error, "DeleteSendingMessage failed") } func (d *DataBase) GetAllSendingMessages(ctx context.Context) (friendRequests []*model_struct.LocalSendingMessages, err error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - err = utils.Wrap(d.conn.WithContext(ctx).Find(&friendRequests).Error, "GetAllSendingMessages failed") - return friendRequests, utils.Wrap(err, "GetAllSendingMessages failed") + return friendRequests, errs.WrapMsg(d.conn.WithContext(ctx).Find(&friendRequests).Error, "GetAllSendingMessages failed") } diff --git a/pkg/db/seq_data_model.go b/pkg/db/seq_data_model.go index 2e3561184..5c98468e4 100644 --- a/pkg/db/seq_data_model.go +++ b/pkg/db/seq_data_model.go @@ -19,22 +19,23 @@ package db import ( "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) GetMinSeq(ctx context.Context, ID string) (uint32, error) { var seqData model_struct.LocalSeq - return seqData.MinSeq, utils.Wrap(d.conn.WithContext(ctx).First(&seqData).Error, "GetMinSeq failed") + return seqData.MinSeq, errs.WrapMsg(d.conn.WithContext(ctx).First(&seqData).Error, "GetMinSeq failed") } func (d *DataBase) SetMinSeq(ctx context.Context, ID string, minSeq uint32) error { seqData := model_struct.LocalSeq{ID: ID, MinSeq: minSeq} t := d.conn.WithContext(ctx).Updates(&seqData) if t.RowsAffected == 0 { - return utils.Wrap(d.conn.WithContext(ctx).Create(seqData).Error, "Updates failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(seqData).Error, "Updates failed") } else { - return utils.Wrap(t.Error, "SetMinSeq failed") + return errs.WrapMsg(t.Error, "SetMinSeq failed") } } diff --git a/pkg/db/stranger_model.go b/pkg/db/stranger_model.go index b56b66707..af7242844 100644 --- a/pkg/db/stranger_model.go +++ b/pkg/db/stranger_model.go @@ -20,22 +20,17 @@ package db import ( "context" "errors" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" "gorm.io/gorm" ) func (d *DataBase) GetStrangerInfo(ctx context.Context, userIDs []string) ([]*model_struct.LocalStranger, error) { d.friendMtx.Lock() defer d.friendMtx.Unlock() - var friendList []model_struct.LocalStranger - err := utils.Wrap(d.conn.WithContext(ctx).Where("user_id IN ?", userIDs).Find(&friendList).Error, "GetFriendInfoListByFriendUserID failed") - var transfer []*model_struct.LocalStranger - for _, v := range friendList { - v1 := v - transfer = append(transfer, &v1) - } - return transfer, err + var friendList []*model_struct.LocalStranger + return friendList, errs.WrapMsg(d.conn.WithContext(ctx).Where("user_id IN ?", userIDs).Find(&friendList).Error, "GetFriendInfoListByFriendUserID failed") } func (d *DataBase) SetStrangerInfo(ctx context.Context, localStrangerList []*model_struct.LocalStranger) error { diff --git a/pkg/db/super_group_chat_log_model.go b/pkg/db/super_group_chat_log_model.go index ac80e294e..b7c81f672 100644 --- a/pkg/db/super_group_chat_log_model.go +++ b/pkg/db/super_group_chat_log_model.go @@ -21,10 +21,12 @@ import ( "context" "errors" "fmt" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/errs" "gorm.io/gorm" ) @@ -40,20 +42,20 @@ func (d *DataBase) SuperGroupBatchInsertMessageList(ctx context.Context, Message } d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Create(MessageList).Error, "SuperGroupBatchInsertMessageList failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Create(MessageList).Error, "SuperGroupBatchInsertMessageList failed") } func (d *DataBase) SuperGroupInsertMessage(ctx context.Context, Message *model_struct.LocalChatLog, groupID string) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Create(Message).Error, "SuperGroupInsertMessage failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Create(Message).Error, "SuperGroupInsertMessage failed") } func (d *DataBase) SuperGroupDeleteAllMessage(ctx context.Context, groupID string) error { - return utils.Wrap(d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Table(utils.GetConversationTableName(groupID)).Delete(&model_struct.LocalChatLog{}).Error, "SuperGroupDeleteAllMessage failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Table(utils.GetConversationTableName(groupID)).Delete(&model_struct.LocalChatLog{}).Error, "SuperGroupDeleteAllMessage failed") } func (d *DataBase) SuperGroupSearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - var messageList []model_struct.LocalChatLog + var messageList []*model_struct.LocalChatLog var condition string var subCondition string if keywordListMatchType == constant.KeywordMatchOr { @@ -81,15 +83,8 @@ func (d *DataBase) SuperGroupSearchMessageByKeyword(ctx context.Context, content } } condition = fmt.Sprintf("recv_id=%q And send_time between %d and %d AND status <=%d And content_type IN ? ", sourceID, startTime, endTime, constant.MsgStatusSendFailed) - condition += subCondition - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&messageList).Error, "InsertMessage failed") - - for _, v := range messageList { - v1 := v - result = append(result, &v1) - } - return result, err + return messageList, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&messageList).Error, "InsertMessage failed") } func (d *DataBase) SuperGroupSearchAllMessageByContentType(ctx context.Context, groupID string, contentType int32) (result []*model_struct.LocalChatLog, err error) { @@ -98,20 +93,13 @@ func (d *DataBase) SuperGroupSearchAllMessageByContentType(ctx context.Context, } func (d *DataBase) SuperGroupSearchMessageByContentType(ctx context.Context, contentType []int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) { - var messageList []model_struct.LocalChatLog - var condition string - condition = fmt.Sprintf("session_type=%d And recv_id==%q And send_time between %d and %d AND status <=%d And content_type IN ?", sessionType, sourceID, startTime, endTime, constant.MsgStatusSendFailed) - - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&messageList).Error, "SearchMessage failed") - for _, v := range messageList { - v1 := v - result = append(result, &v1) - } - return result, err + var messageList []*model_struct.LocalChatLog + condition := fmt.Sprintf("session_type=%d And recv_id==%q And send_time between %d and %d AND status <=%d And content_type IN ?", sessionType, sourceID, startTime, endTime, constant.MsgStatusSendFailed) + return messageList, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&messageList).Error, "SearchMessage failed") } func (d *DataBase) SuperGroupSearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, startTime, endTime int64, groupID string) (result []*model_struct.LocalChatLog, err error) { - var messageList []model_struct.LocalChatLog + var messageList []*model_struct.LocalChatLog var condition string var subCondition string if keywordListMatchType == constant.KeywordMatchOr { @@ -140,12 +128,7 @@ func (d *DataBase) SuperGroupSearchMessageByContentTypeAndKeyword(ctx context.Co } condition = fmt.Sprintf("send_time between %d and %d AND status <=%d And content_type IN ? ", startTime, endTime, constant.MsgStatusSendFailed) condition += subCondition - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where(condition, contentType).Order("send_time DESC").Find(&messageList).Error, "SearchMessage failed") - for _, v := range messageList { - v1 := v - result = append(result, &v1) - } - return result, err + return messageList, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where(condition, contentType).Order("send_time DESC").Find(&messageList).Error, "SearchMessage failed") } func (d *DataBase) SuperGroupBatchUpdateMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error { if MessageList == nil { @@ -159,7 +142,7 @@ func (d *DataBase) SuperGroupBatchUpdateMessageList(ctx context.Context, Message v1.Status = v.Status err := d.SuperGroupUpdateMessage(ctx, v1) if err != nil { - return utils.Wrap(err, "BatchUpdateMessageList failed") + return errs.WrapMsg(err, "BatchUpdateMessageList failed") } } @@ -173,7 +156,7 @@ func (d *DataBase) SuperGroupMessageIfExists(ctx context.Context, ClientMsgID st t := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("client_msg_id = ?", ClientMsgID).Count(&count) if t.Error != nil { - return false, utils.Wrap(t.Error, "MessageIfExists get failed") + return false, errs.WrapMsg(t.Error, "MessageIfExists get failed") } if count != 1 { return false, nil @@ -191,7 +174,7 @@ func (d *DataBase) SuperGroupMessageIfExistsBySeq(ctx context.Context, seq int64 t := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("seq = ?", seq).Count(&count) if t.Error != nil { - return false, utils.Wrap(t.Error, "MessageIfExistsBySeq get failed") + return false, errs.WrapMsg(t.Error, "MessageIfExistsBySeq get failed") } if count != 1 { return false, nil @@ -204,13 +187,13 @@ func (d *DataBase) SuperGroupGetMessage(ctx context.Context, msg *sdk_struct.Msg d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var c model_struct.LocalChatLog - return &c, utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(msg.GroupID)).Where("client_msg_id = ?", + return &c, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(msg.GroupID)).Where("client_msg_id = ?", msg.ClientMsgID).Take(&c).Error, "GetMessage failed") } func (d *DataBase) SuperGroupGetAllUnDeleteMessageSeqList(ctx context.Context) ([]uint32, error) { var seqList []uint32 - return seqList, utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("status != 4").Select("seq").Find(&seqList).Error, "") + return seqList, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("status != 4").Select("seq").Find(&seqList).Error, "") } func (d *DataBase) SuperGroupUpdateColumnsMessage(ctx context.Context, ClientMsgID, groupID string, args map[string]interface{}) error { @@ -219,34 +202,34 @@ func (d *DataBase) SuperGroupUpdateColumnsMessage(ctx context.Context, ClientMsg t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where( "client_msg_id = ? ", ClientMsgID).Updates(args) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateColumnsConversation failed") + return errs.WrapMsg(t.Error, "UpdateColumnsConversation failed") } func (d *DataBase) SuperGroupUpdateMessage(ctx context.Context, c *model_struct.LocalChatLog) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(c.RecvID)).Updates(c) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateMessage failed") + return errs.WrapMsg(t.Error, "UpdateMessage failed") } func (d *DataBase) SuperGroupUpdateSpecificContentTypeMessage(ctx context.Context, contentType int, groupID string, args map[string]interface{}) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where("content_type = ?", contentType).Updates(args) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateMessage failed") + return errs.WrapMsg(t.Error, "UpdateMessage failed") } //funcation (d *DataBase) SuperGroupDeleteAllMessage(ctx context.Context, ) error { // d.mRWMutex.Lock() // defer d.mRWMutex.Unlock() // err := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Exec("update local_chat_logs set status = ?,content = ? ", constant.MsgStatusHasDeleted, "").Error -// return utils.Wrap(err, "delete all message error") +// return errs.WrapMsg(err, "delete all message error") //} func (d *DataBase) SuperGroupUpdateMessageStatusBySourceID(ctx context.Context, sourceID string, status, sessionType int32) error { @@ -260,24 +243,24 @@ func (d *DataBase) SuperGroupUpdateMessageStatusBySourceID(ctx context.Context, } t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, sourceID, sourceID, sessionType).Updates(model_struct.LocalChatLog{Status: status}) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed") + return errs.WrapMsg(t.Error, "UpdateMessageStatusBySourceID failed") } func (d *DataBase) SuperGroupUpdateMessageTimeAndStatus(ctx context.Context, msg *sdk_struct.MsgStruct) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(msg.GroupID)).Where("client_msg_id=? And seq=?", msg.ClientMsgID, 0).Updates(model_struct.LocalChatLog{Status: msg.Status, SendTime: msg.SendTime, ServerMsgID: msg.ServerMsgID}) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "SuperGroupUpdateMessageTimeAndStatus failed") + return errs.WrapMsg(t.Error, "SuperGroupUpdateMessageTimeAndStatus failed") } func (d *DataBase) SuperGroupGetMessageList(ctx context.Context, sourceID string, sessionType, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - var messageList []model_struct.LocalChatLog + var messageList []*model_struct.LocalChatLog var condition, timeOrder, timeSymbol string if isReverse { timeOrder = "send_time ASC" @@ -288,17 +271,12 @@ func (d *DataBase) SuperGroupGetMessageList(ctx context.Context, sourceID string } condition = " recv_id = ? AND status <=? And session_type = ? And send_time " + timeSymbol + " ?" - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, sourceID, constant.MsgStatusSendFailed, sessionType, startTime). + return messageList, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, sourceID, constant.MsgStatusSendFailed, sessionType, startTime). Order(timeOrder).Offset(0).Limit(count).Find(&messageList).Error, "GetMessageList failed") - for _, v := range messageList { - v1 := v - result = append(result, &v1) - } - return result, err } func (d *DataBase) SuperGroupGetMessageListNoTime(ctx context.Context, sourceID string, sessionType, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error) { d.initSuperLocalChatLog(ctx, sourceID) - var messageList []model_struct.LocalChatLog + var messageList []*model_struct.LocalChatLog var condition, timeOrder string if isReverse { timeOrder = "send_time ASC" @@ -306,26 +284,15 @@ func (d *DataBase) SuperGroupGetMessageListNoTime(ctx context.Context, sourceID timeOrder = "send_time DESC" } condition = "recv_id = ? AND status <=? And session_type = ? " - - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, sourceID, constant.MsgStatusSendFailed, sessionType). + return messageList, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, sourceID, constant.MsgStatusSendFailed, sessionType). Order(timeOrder).Offset(0).Limit(count).Find(&messageList).Error, "GetMessageList failed") - for _, v := range messageList { - v1 := v - result = append(result, &v1) - } - return result, err } func (d *DataBase) SuperGroupGetSendingMessageList(ctx context.Context, groupID string) (result []*model_struct.LocalChatLog, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - var messageList []model_struct.LocalChatLog - err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where("status = ?", constant.MsgStatusSending).Find(&messageList).Error, "GetMessageList failed") - for _, v := range messageList { - v1 := v - result = append(result, &v1) - } - return result, err + var messageList []*model_struct.LocalChatLog + return messageList, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where("status = ?", constant.MsgStatusSending).Find(&messageList).Error, "GetMessageList failed") } func (d *DataBase) SuperGroupUpdateGroupMessageHasRead(ctx context.Context, msgIDList []string, groupID string) error { @@ -333,44 +300,42 @@ func (d *DataBase) SuperGroupUpdateGroupMessageHasRead(ctx context.Context, msgI defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where(" client_msg_id in ?", msgIDList).Update("is_read", constant.HasRead) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed") + return errs.WrapMsg(t.Error, "UpdateMessageStatusBySourceID failed") } func (d *DataBase) SuperGroupUpdateGroupMessageFields(ctx context.Context, msgIDList []string, groupID string, args map[string]interface{}) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where(" client_msg_id in ?", msgIDList).Updates(args) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed") + return errs.WrapMsg(t.Error, "UpdateMessageStatusBySourceID failed") } func (d *DataBase) SuperGroupGetNormalMsgSeq(ctx context.Context) (int64, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seq int64 - err := d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("IFNULL(max(seq),0)").Find(&seq).Error - return seq, utils.Wrap(err, "GetNormalMsgSeq") + return seq, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("IFNULL(max(seq),0)").Find(&seq).Error, "GetNormalMsgSeq") } func (d *DataBase) SuperGroupGetNormalMinSeq(ctx context.Context, groupID string) (int64, error) { var seq int64 - err := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Select("IFNULL(min(seq),0)").Where("seq >?", 0).Find(&seq).Error - return seq, utils.Wrap(err, "SuperGroupGetNormalMinSeq") + return seq, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Select("IFNULL(min(seq),0)").Where("seq >?", 0).Find(&seq).Error, "SuperGroupGetNormalMinSeq") } func (d *DataBase) SuperGroupGetTestMessage(ctx context.Context, seq int64) (*model_struct.LocalChatLog, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var c model_struct.LocalChatLog - return &c, utils.Wrap(d.conn.WithContext(ctx).Where("seq = ?", + return &c, errs.WrapMsg(d.conn.WithContext(ctx).Where("seq = ?", seq).Find(&c).Error, "GetTestMessage failed") } func (d *DataBase) SuperGroupUpdateMsgSenderNickname(ctx context.Context, sendID, nickname string, sType int) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where( + return errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where( "send_id = ? and session_type = ? and sender_nick_name != ? ", sendID, sType, nickname).Updates( map[string]interface{}{"sender_nick_name": nickname}).Error, utils.GetSelfFuncName()+" failed") } @@ -378,14 +343,14 @@ func (d *DataBase) SuperGroupUpdateMsgSenderNickname(ctx context.Context, sendID func (d *DataBase) SuperGroupUpdateMsgSenderFaceURL(ctx context.Context, sendID, faceURL string, sType int) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where( + return errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where( "send_id = ? and session_type = ? and sender_face_url != ? ", sendID, sType, faceURL).Updates( map[string]interface{}{"sender_face_url": faceURL}).Error, utils.GetSelfFuncName()+" failed") } func (d *DataBase) SuperGroupUpdateMsgSenderFaceURLAndSenderNickname(ctx context.Context, sendID, faceURL, nickname string, sessionType int, groupID string) error { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where( + return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where( "send_id = ? and session_type = ?", sendID, sessionType).Updates( map[string]interface{}{"sender_face_url": faceURL, "sender_nick_name": nickname}).Error, utils.GetSelfFuncName()+" failed") } @@ -394,30 +359,26 @@ func (d *DataBase) SuperGroupGetMsgSeqByClientMsgID(ctx context.Context, clientM d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seq uint32 - err := utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Select("seq").Where("client_msg_id=?", clientMsgID).Take(&seq).Error, utils.GetSelfFuncName()+" failed") - return seq, err + return seq, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Select("seq").Where("client_msg_id=?", clientMsgID).Take(&seq).Error, utils.GetSelfFuncName()+" failed") } func (d *DataBase) SuperGroupGetMsgSeqListByGroupID(ctx context.Context, groupID string) ([]uint32, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seqList []uint32 - err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=?", groupID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") - return seqList, err + return seqList, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=?", groupID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") } func (d *DataBase) SuperGroupGetMsgSeqListByPeerUserID(ctx context.Context, userID string) ([]uint32, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seqList []uint32 - err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? or send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") - return seqList, err + return seqList, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? or send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") } func (d *DataBase) SuperGroupGetMsgSeqListBySelfUserID(ctx context.Context, userID string) ([]uint32, error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() var seqList []uint32 - err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? and send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") - return seqList, err + return seqList, errs.WrapMsg(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? and send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed") } diff --git a/pkg/db/super_group_model.go b/pkg/db/super_group_model.go index 811a7ca1c..6b9813831 100644 --- a/pkg/db/super_group_model.go +++ b/pkg/db/super_group_model.go @@ -20,28 +20,29 @@ package db import ( "context" "errors" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) InsertSuperGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error { d.superGroupMtx.Lock() defer d.superGroupMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Create(groupInfo).Error, "InsertSuperGroup failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Create(groupInfo).Error, "InsertSuperGroup failed") } func (d *DataBase) DeleteAllSuperGroup(ctx context.Context) error { d.superGroupMtx.Lock() defer d.superGroupMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Delete(&model_struct.LocalGroup{}).Error, "DeleteAllSuperGroup failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Delete(&model_struct.LocalGroup{}).Error, "DeleteAllSuperGroup failed") } func (d *DataBase) GetSuperGroupInfoByGroupID(ctx context.Context, groupID string) (*model_struct.LocalGroup, error) { d.superGroupMtx.Lock() defer d.superGroupMtx.Unlock() var g model_struct.LocalGroup - return &g, utils.Wrap(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Where("group_id = ?", groupID).Take(&g).Error, "GetGroupList failed") + return &g, errs.WrapMsg(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Where("group_id = ?", groupID).Take(&g).Error, "GetGroupList failed") } func (d *DataBase) UpdateSuperGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error { @@ -50,14 +51,14 @@ func (d *DataBase) UpdateSuperGroup(ctx context.Context, groupInfo *model_struct t := d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Select("*").Updates(*groupInfo) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "") + return errs.WrapMsg(t.Error, "") } func (d *DataBase) DeleteSuperGroup(ctx context.Context, groupID string) error { d.superGroupMtx.Lock() defer d.superGroupMtx.Unlock() localGroup := model_struct.LocalGroup{GroupID: groupID} - return utils.Wrap(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Delete(&localGroup).Error, "DeleteSuperGroup failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Delete(&localGroup).Error, "DeleteSuperGroup failed") } diff --git a/pkg/db/temp_cache_chat_log_model.go b/pkg/db/temp_cache_chat_log_model.go index b837b9651..a6f6590e6 100644 --- a/pkg/db/temp_cache_chat_log_model.go +++ b/pkg/db/temp_cache_chat_log_model.go @@ -19,18 +19,19 @@ package db import ( "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) BatchInsertTempCacheMessageList(ctx context.Context, MessageList []*model_struct.TempCacheLocalChatLog) error { if MessageList == nil { return nil } - return utils.Wrap(d.conn.WithContext(ctx).Create(MessageList).Error, "BatchInsertTempCacheMessageList failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(MessageList).Error, "BatchInsertTempCacheMessageList failed") } func (d *DataBase) InsertTempCacheMessage(ctx context.Context, Message *model_struct.TempCacheLocalChatLog) error { - return utils.Wrap(d.conn.WithContext(ctx).Create(Message).Error, "InsertTempCacheMessage failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(Message).Error, "InsertTempCacheMessage failed") } diff --git a/pkg/db/upload_model.go b/pkg/db/upload_model.go index 9b3cd36ee..5a3a5fc44 100644 --- a/pkg/db/upload_model.go +++ b/pkg/db/upload_model.go @@ -19,10 +19,11 @@ package db import ( "context" - "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "time" - "github.com/OpenIMSDK/tools/errs" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + + "github.com/openimsdk/tools/errs" ) func (d *DataBase) GetUpload(ctx context.Context, partHash string) (*model_struct.LocalUpload, error) { diff --git a/pkg/db/user_command.go b/pkg/db/user_command.go index ae6057086..2153a9151 100644 --- a/pkg/db/user_command.go +++ b/pkg/db/user_command.go @@ -19,8 +19,9 @@ package db import ( "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" "github.com/pkg/errors" ) @@ -38,7 +39,7 @@ func (d *DataBase) ProcessUserCommandAdd(ctx context.Context, command *model_str Ex: command.Ex, } - return utils.Wrap(d.conn.WithContext(ctx).Create(&userCommand).Error, "ProcessUserCommandAdd failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(&userCommand).Error, "ProcessUserCommandAdd failed") } // ProcessUserCommandUpdate updates an existing user command in the database. @@ -48,9 +49,9 @@ func (d *DataBase) ProcessUserCommandUpdate(ctx context.Context, command *model_ t := d.conn.WithContext(ctx).Model(command).Select("*").Updates(*command) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "") + return errs.WrapMsg(t.Error, "") } @@ -58,8 +59,7 @@ func (d *DataBase) ProcessUserCommandUpdate(ctx context.Context, command *model_ func (d *DataBase) ProcessUserCommandDelete(ctx context.Context, command *model_struct.LocalUserCommand) error { d.userMtx.Lock() defer d.userMtx.Unlock() - - return utils.Wrap(d.conn.WithContext(ctx).Where("type = ? AND uuid = ?", command.Type, command.Uuid).Delete(&model_struct.LocalUserCommand{}).Error, + return errs.WrapMsg(d.conn.WithContext(ctx).Where("type = ? AND uuid = ?", command.Type, command.Uuid).Delete(&model_struct.LocalUserCommand{}).Error, "ProcessUserCommandDelete failed") } @@ -67,8 +67,6 @@ func (d *DataBase) ProcessUserCommandDelete(ctx context.Context, command *model_ func (d *DataBase) ProcessUserCommandGetAll(ctx context.Context) ([]*model_struct.LocalUserCommand, error) { d.userMtx.RLock() defer d.userMtx.RUnlock() - var commands []*model_struct.LocalUserCommand - err := d.conn.WithContext(ctx).Find(&commands).Error - return commands, utils.Wrap(err, "ProcessUserCommandGetAll failed") + return commands, errs.WrapMsg(d.conn.WithContext(ctx).Find(&commands).Error, "ProcessUserCommandGetAll failed") } diff --git a/pkg/db/user_model.go b/pkg/db/user_model.go index 4e23cc7cf..eddbfeb14 100644 --- a/pkg/db/user_model.go +++ b/pkg/db/user_model.go @@ -20,15 +20,16 @@ package db import ( "context" "errors" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) GetLoginUser(ctx context.Context, userID string) (*model_struct.LocalUser, error) { d.userMtx.RLock() defer d.userMtx.RUnlock() var user model_struct.LocalUser - return &user, utils.Wrap(d.conn.WithContext(ctx).Where("user_id = ? ", userID).Take(&user).Error, "GetLoginUserInfo failed") + return &user, errs.WrapMsg(d.conn.WithContext(ctx).Where("user_id = ? ", userID).Take(&user).Error, "GetLoginUserInfo failed") } func (d *DataBase) UpdateLoginUser(ctx context.Context, user *model_struct.LocalUser) error { @@ -36,21 +37,21 @@ func (d *DataBase) UpdateLoginUser(ctx context.Context, user *model_struct.Local defer d.userMtx.Unlock() t := d.conn.WithContext(ctx).Model(user).Select("*").Updates(user) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateLoginUser failed") + return errs.WrapMsg(t.Error, "UpdateLoginUser failed") } func (d *DataBase) UpdateLoginUserByMap(ctx context.Context, user *model_struct.LocalUser, args map[string]interface{}) error { d.userMtx.Lock() defer d.userMtx.Unlock() t := d.conn.WithContext(ctx).Model(&user).Updates(args) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "UpdateColumnsConversation failed") + return errs.WrapMsg(t.Error, "UpdateColumnsConversation failed") } func (d *DataBase) InsertLoginUser(ctx context.Context, user *model_struct.LocalUser) error { d.userMtx.Lock() defer d.userMtx.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Create(user).Error, "InsertLoginUser failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(user).Error, "InsertLoginUser failed") } diff --git a/pkg/db/version_sync.go b/pkg/db/version_sync.go new file mode 100644 index 000000000..07ff73e8a --- /dev/null +++ b/pkg/db/version_sync.go @@ -0,0 +1,45 @@ +package db + +import ( + "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + "github.com/openimsdk/tools/errs" + "gorm.io/gorm" +) + +func (d *DataBase) GetVersionSync(ctx context.Context, tableName, entityID string) (*model_struct.LocalVersionSync, error) { + d.versionMtx.RLock() + defer d.versionMtx.RUnlock() + var res model_struct.LocalVersionSync + return &res, errs.Wrap(d.conn.WithContext(ctx).Where("`table` = ? and `entity_id` = ?", tableName, entityID).Take(&res).Error) +} + +func (d *DataBase) SetVersionSync(ctx context.Context, lv *model_struct.LocalVersionSync) error { + d.versionMtx.Lock() + defer d.versionMtx.Unlock() + + var existing model_struct.LocalVersionSync + err := d.conn.WithContext(ctx).Where("`table` = ? AND `entity_id` = ?", lv.Table, lv.EntityID).First(&existing).Error + + if err == gorm.ErrRecordNotFound { + if createErr := d.conn.WithContext(ctx).Create(lv).Error; createErr != nil { + return errs.Wrap(createErr) + } + return nil + } else if err != nil { + return errs.Wrap(err) + } + + if updateErr := d.conn.WithContext(ctx).Model(&existing).Updates(lv).Error; updateErr != nil { + return errs.Wrap(updateErr) + } + + return nil +} + +func (d *DataBase) DeleteVersionSync(ctx context.Context, tableName, entityID string) error { + d.versionMtx.Lock() + defer d.versionMtx.Unlock() + localVersionSync := model_struct.LocalVersionSync{Table: tableName, EntityID: entityID} + return errs.WrapMsg(d.conn.WithContext(ctx).Delete(&localVersionSync).Error, "DeleteVersionSync failed") +} diff --git a/pkg/db/work_moments_model.go b/pkg/db/work_moments_model.go index ac7139e39..b1d2c44f3 100644 --- a/pkg/db/work_moments_model.go +++ b/pkg/db/work_moments_model.go @@ -20,10 +20,11 @@ package db import ( "context" "errors" + "time" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" "gorm.io/gorm" - "time" ) func (d *DataBase) InsertWorkMomentsNotification(ctx context.Context, jsonDetail string) error { @@ -33,32 +34,30 @@ func (d *DataBase) InsertWorkMomentsNotification(ctx context.Context, jsonDetail JsonDetail: jsonDetail, CreateTime: time.Now().Unix(), } - return utils.Wrap(d.conn.WithContext(ctx).Create(workMomentsNotification).Error, "") + return errs.WrapMsg(d.conn.WithContext(ctx).Create(workMomentsNotification).Error, "") } func (d *DataBase) GetWorkMomentsNotification(ctx context.Context, offset, count int) (WorkMomentsNotifications []*model_struct.LocalWorkMomentsNotification, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() WorkMomentsNotifications = []*model_struct.LocalWorkMomentsNotification{} - err = utils.Wrap(d.conn.WithContext(ctx).Table("local_work_moments_notification").Order("create_time DESC").Offset(offset).Limit(count).Find(&WorkMomentsNotifications).Error, "") - return WorkMomentsNotifications, err + return WorkMomentsNotifications, errs.WrapMsg(d.conn.WithContext(ctx).Table("local_work_moments_notification").Order("create_time DESC").Offset(offset).Limit(count).Find(&WorkMomentsNotifications).Error, "") } func (d *DataBase) GetWorkMomentsNotificationLimit(ctx context.Context, pageNumber, showNumber int) (WorkMomentsNotifications []*model_struct.LocalWorkMomentsNotification, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() WorkMomentsNotifications = []*model_struct.LocalWorkMomentsNotification{} - err = utils.Wrap(d.conn.WithContext(ctx).Table("local_work_moments_notification").Select("json_detail").Find(WorkMomentsNotifications).Error, "") - return WorkMomentsNotifications, err + return WorkMomentsNotifications, errs.WrapMsg(d.conn.WithContext(ctx).Table("local_work_moments_notification").Select("json_detail").Find(WorkMomentsNotifications).Error, "") } func (d *DataBase) InitWorkMomentsNotificationUnreadCount(ctx context.Context) error { var n int64 - err := utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).Count(&n).Error, "") + err := errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).Count(&n).Error, "") if err == nil { if n == 0 { c := model_struct.LocalWorkMomentsNotificationUnreadCount{UnreadCount: 0} - return utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).Create(c).Error, "IncrConversationUnreadCount failed") + return errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).Create(c).Error, "IncrConversationUnreadCount failed") } } return err @@ -70,27 +69,26 @@ func (d *DataBase) IncrWorkMomentsNotificationUnreadCount(ctx context.Context) e c := model_struct.LocalWorkMomentsNotificationUnreadCount{} t := d.conn.WithContext(ctx).Model(&c).Where("1=1").Update("unread_count", gorm.Expr("unread_count+?", 1)) if t.RowsAffected == 0 { - return utils.Wrap(errors.New("RowsAffected == 0"), "no update") + return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update") } - return utils.Wrap(t.Error, "IncrConversationUnreadCount failed") + return errs.WrapMsg(t.Error, "IncrConversationUnreadCount failed") } func (d *DataBase) MarkAllWorkMomentsNotificationAsRead(ctx context.Context) (err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).Where("1=1").Updates(map[string]interface{}{"unread_count": 0}).Error, "") + return errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).Where("1=1").Updates(map[string]interface{}{"unread_count": 0}).Error, "") } func (d *DataBase) GetWorkMomentsUnReadCount(ctx context.Context) (workMomentsNotificationUnReadCount model_struct.LocalWorkMomentsNotificationUnreadCount, err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() workMomentsNotificationUnReadCount = model_struct.LocalWorkMomentsNotificationUnreadCount{} - err = utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).First(&workMomentsNotificationUnReadCount).Error, "") - return workMomentsNotificationUnReadCount, err + return workMomentsNotificationUnReadCount, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).First(&workMomentsNotificationUnReadCount).Error, "") } func (d *DataBase) ClearWorkMomentsNotification(ctx context.Context) (err error) { d.mRWMutex.Lock() defer d.mRWMutex.Unlock() - return utils.Wrap(d.conn.WithContext(ctx).Table("local_work_moments_notification").Where("1=1").Delete(&model_struct.LocalWorkMomentsNotification{}).Error, "") + return errs.WrapMsg(d.conn.WithContext(ctx).Table("local_work_moments_notification").Where("1=1").Delete(&model_struct.LocalWorkMomentsNotification{}).Error, "") } diff --git a/pkg/db/working_group.go b/pkg/db/working_group.go index c4bf35658..5776fdda0 100644 --- a/pkg/db/working_group.go +++ b/pkg/db/working_group.go @@ -19,15 +19,16 @@ package db import ( "context" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" - "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" ) func (d *DataBase) GetJoinedWorkingGroupIDList(ctx context.Context) ([]string, error) { groupList, err := d.GetJoinedGroupListDB(ctx) if err != nil { - return nil, utils.Wrap(err, "") + return nil, errs.WrapMsg(err, "") } var groupIDList []string for _, v := range groupList { @@ -46,5 +47,5 @@ func (d *DataBase) GetJoinedWorkingGroupList(ctx context.Context) ([]*model_stru transfer = append(transfer, v) } } - return transfer, utils.Wrap(err, "GetJoinedSuperGroupList failed ") + return transfer, errs.WrapMsg(err, "GetJoinedSuperGroupList failed ") } diff --git a/pkg/page/pagereq.go b/pkg/page/pagereq.go new file mode 100644 index 000000000..b8887ab92 --- /dev/null +++ b/pkg/page/pagereq.go @@ -0,0 +1,7 @@ +package page + +import "github.com/openimsdk/protocol/sdkws" + +type PageReq interface { + GetPagination() *sdkws.RequestPagination +} diff --git a/pkg/sdk_params_callback/friend_sdk_struct.go b/pkg/sdk_params_callback/friend_sdk_struct.go index 6cee3f015..e58e0b24f 100644 --- a/pkg/sdk_params_callback/friend_sdk_struct.go +++ b/pkg/sdk_params_callback/friend_sdk_struct.go @@ -15,10 +15,10 @@ package sdk_params_callback import ( - "github.com/OpenIMSDK/protocol/wrapperspb" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" + "github.com/openimsdk/protocol/wrapperspb" ) // 1 diff --git a/pkg/sdk_params_callback/group_sdk_struct.go b/pkg/sdk_params_callback/group_sdk_struct.go index 3b5877ccd..200e296b1 100644 --- a/pkg/sdk_params_callback/group_sdk_struct.go +++ b/pkg/sdk_params_callback/group_sdk_struct.go @@ -60,9 +60,11 @@ type SearchGroupMembersParam struct { IsSearchUserID bool `json:"isSearchUserID"` IsSearchMemberNickname bool `json:"isSearchMemberNickname"` //offset, count int - Offset int `json:"offset"` - Count int `json:"count"` + Offset int `json:"offset"` + Count int `json:"count"` + PageNumber int `json:"pageNumber"` } + type SearchGroupMembersCallback []*model_struct.LocalGroupMember type SetGroupInfoParam struct { diff --git a/pkg/sdkerrs/error.go b/pkg/sdkerrs/error.go index 56e31b354..0470a72b9 100644 --- a/pkg/sdkerrs/error.go +++ b/pkg/sdkerrs/error.go @@ -14,10 +14,13 @@ package sdkerrs -import "github.com/OpenIMSDK/tools/errs" +import "github.com/openimsdk/tools/errs" func New(code int, msg string, dtl string) errs.CodeError { return errs.NewCodeError(code, msg).WithDetail(dtl) } -var Warp = errs.Wrap +var ( + Wrap = errs.Wrap + WrapMsg = errs.WrapMsg +) diff --git a/pkg/sdkerrs/predefine.go b/pkg/sdkerrs/predefine.go index bf0af003f..076d1fbdc 100644 --- a/pkg/sdkerrs/predefine.go +++ b/pkg/sdkerrs/predefine.go @@ -14,7 +14,7 @@ package sdkerrs -import "github.com/OpenIMSDK/tools/errs" +import "github.com/openimsdk/tools/errs" var ( ErrArgs = errs.NewCodeError(ArgsError, "ArgsError") diff --git a/pkg/server_api_params/auth_api_struct.go b/pkg/server_api_params/auth_api_struct.go index 44ea50de6..9868e3e0a 100644 --- a/pkg/server_api_params/auth_api_struct.go +++ b/pkg/server_api_params/auth_api_struct.go @@ -14,7 +14,7 @@ package server_api_params -import "github.com/OpenIMSDK/protocol/sdkws" +import "github.com/openimsdk/protocol/sdkws" //UserID string `protobuf:"bytes,1,opt,name=UserID" json:"UserID,omitempty"` // Nickname string `protobuf:"bytes,2,opt,name=Nickname" json:"Nickname,omitempty"` diff --git a/pkg/server_api_params/friend_api_struct.go b/pkg/server_api_params/friend_api_struct.go index d26bb0b93..7bfa3b871 100644 --- a/pkg/server_api_params/friend_api_struct.go +++ b/pkg/server_api_params/friend_api_struct.go @@ -14,7 +14,7 @@ package server_api_params -import "github.com/OpenIMSDK/protocol/sdkws" +import "github.com/openimsdk/protocol/sdkws" type ParamsCommFriend struct { OperationID string `json:"operationID" binding:"required"` diff --git a/pkg/server_api_params/group_api_struct.go b/pkg/server_api_params/group_api_struct.go index 381357ca6..4ff561227 100644 --- a/pkg/server_api_params/group_api_struct.go +++ b/pkg/server_api_params/group_api_struct.go @@ -14,7 +14,7 @@ package server_api_params -import "github.com/OpenIMSDK/protocol/sdkws" +import "github.com/openimsdk/protocol/sdkws" type CommResp struct { ErrCode int32 `json:"errCode"` diff --git a/pkg/server_api_params/user_api_struct.go b/pkg/server_api_params/user_api_struct.go index a4109b6b6..4db647f0e 100644 --- a/pkg/server_api_params/user_api_struct.go +++ b/pkg/server_api_params/user_api_struct.go @@ -15,7 +15,7 @@ package server_api_params import ( - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" ) type GetUsersInfoReq struct { diff --git a/pkg/syncer/syncer.go b/pkg/syncer/syncer.go index e4be19f01..a2ac0aaf2 100644 --- a/pkg/syncer/syncer.go +++ b/pkg/syncer/syncer.go @@ -16,11 +16,14 @@ package syncer import ( "context" - "reflect" - "github.com/google/go-cmp/cmp" + "github.com/openimsdk/openim-sdk-core/v3/internal/util" + "github.com/openimsdk/openim-sdk-core/v3/pkg/page" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/utils/datautil" + "reflect" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" ) // New creates a new Syncer instance with the provided synchronization functions. @@ -32,14 +35,14 @@ import ( // - equal: A function to check if two data items are equal. // - notice: A function to handle notifications during the sync process. // Panics if insert, delete, update, or uuid functions are not provided. -func New[T any, V comparable]( +func New[T, RESP any, V comparable]( insert func(ctx context.Context, value T) error, delete func(ctx context.Context, value T) error, update func(ctx context.Context, server T, local T) error, uuid func(value T) V, equal func(a T, b T) bool, notice func(ctx context.Context, state int, server, local T) error, -) *Syncer[T, V] { +) *Syncer[T, RESP, V] { if insert == nil || update == nil || delete == nil || uuid == nil { panic("invalid params") } @@ -52,7 +55,7 @@ func New[T any, V comparable]( } // Return a new Syncer instance with the provided functions and the type as a string. - return &Syncer[T, V]{ + return &Syncer[T, RESP, V]{ insert: insert, update: update, delete: delete, @@ -66,19 +69,143 @@ func New[T any, V comparable]( // Syncer is a struct that holds functions for synchronizing data. // It includes functions for inserting, updating, deleting, and notifying, // as well as functions for generating unique IDs and checking equality of data items. -type Syncer[T any, V comparable] struct { - insert func(ctx context.Context, server T) error - update func(ctx context.Context, server T, local T) error - delete func(ctx context.Context, local T) error - notice func(ctx context.Context, state int, server, local T) error - equal func(server T, local T) bool - uuid func(value T) V - ts string // Represents the type of T as a string. +type Syncer[T, RESP any, V comparable] struct { + insert func(ctx context.Context, server T) error + update func(ctx context.Context, server T, local T) error + delete func(ctx context.Context, local T) error + batchInsert func(ctx context.Context, servers []T) error + deleteAll func(ctx context.Context, entityID string) error + notice func(ctx context.Context, state int, server, local T) error + equal func(server T, local T) bool + uuid func(value T) V + batchPageReq func(entityID string) page.PageReq + batchPageRespConvertFunc func(resp *RESP) []T + reqApiRouter string + ts string // Represents the type of T as a string. + +} + +type NoResp struct{} + +func New2[T, RESP any, V comparable](opts ...Option[T, RESP, V]) *Syncer[T, RESP, V] { + // Create a new Syncer instance. + s := &Syncer[T, RESP, V]{} + + // Apply the options to the Syncer. + for _, opt := range opts { + opt(s) + } + + // Check required functions. + if s.insert == nil || s.update == nil || s.delete == nil || s.uuid == nil { + panic("invalid params") + } + + // Determine the type of T and remove pointer indirection if necessary. + var t T + tof := reflect.TypeOf(&t) + for tof.Kind() == reflect.Ptr { + tof = tof.Elem() + } + + // Set the type string. + s.ts = tof.String() + + return s +} + +// Option is a function that configures a Syncer. +type Option[T, RESP any, V comparable] func(*Syncer[T, RESP, V]) + +// WithInsert sets the insert function for the Syncer. +func WithInsert[T, RESP any, V comparable](f func(ctx context.Context, value T) error) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.insert = f + } +} + +// WithUpdate sets the update function for the Syncer. +func WithUpdate[T, RESP any, V comparable](f func(ctx context.Context, server T, local T) error) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.update = f + } +} + +// WithDelete sets the delete function for the Syncer. +func WithDelete[T, RESP any, V comparable](f func(ctx context.Context, local T) error) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.delete = f + } +} + +// WithBatchInsert sets the batchInsert function for the Syncer. +func WithBatchInsert[T, RESP any, V comparable](f func(ctx context.Context, values []T) error) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.batchInsert = f + } +} + +// WithDeleteAll sets the deleteAll function for the Syncer. +func WithDeleteAll[T, RESP any, V comparable](f func(ctx context.Context, entityID string) error) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.deleteAll = f + } +} + +// WithUUID sets the uuid function for the Syncer. +func WithUUID[T, RESP any, V comparable](f func(value T) V) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.uuid = f + } +} + +// WithEqual sets the equal function for the Syncer. +func WithEqual[T, RESP any, V comparable](f func(a T, b T) bool) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.equal = f + } +} + +// WithNotice sets the notice function for the Syncer. +func WithNotice[T, RESP any, V comparable](f func(ctx context.Context, state int, server, local T) error) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.notice = f + } +} + +// WithBatchPageReq sets the batchPageReq for the Syncer. +func WithBatchPageReq[T, RESP any, V comparable](f func(entityID string) page.PageReq) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.batchPageReq = f + } +} + +// WithBatchPageRespConvertFunc sets the batchPageRespConvertFunc function for the Syncer. +func WithBatchPageRespConvertFunc[T, RESP any, V comparable](f func(resp *RESP) []T) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.batchPageRespConvertFunc = f + } +} + +// WithReqApiRouter sets the reqApiRouter for the Syncer. +func WithReqApiRouter[T, RESP any, V comparable](router string) Option[T, RESP, V] { + return func(s *Syncer[T, RESP, V]) { + s.reqApiRouter = router + } +} + +// NewSyncer creates a new Syncer with the provided options. +func NewSyncer[T, RESP any, V comparable](opts ...Option[T, RESP, V]) *Syncer[T, RESP, V] { + syncer := &Syncer[T, RESP, V]{} + for _, opt := range opts { + opt(syncer) + } + return syncer } // eq is a helper function to check equality of two data items. // It uses the equal function if provided; otherwise, it falls back to the cmp.Equal function. -func (s *Syncer[T, V]) eq(server T, local T) bool { +func (s *Syncer[T, RESP, V]) eq(server T, local T) bool { if s.equal != nil { return s.equal(server, local) } @@ -87,7 +214,7 @@ func (s *Syncer[T, V]) eq(server T, local T) bool { // onNotice is a helper function to handle notifications. // It calls the Syncer's notice function and the provided notice function in sequence if they are not nil. -func (s *Syncer[T, V]) onNotice(ctx context.Context, state int, server, local T, fn func(ctx context.Context, state int, server, local T) error) error { +func (s *Syncer[T, RESP, V]) onNotice(ctx context.Context, state int, server, local T, fn func(ctx context.Context, state int, server, local T) error) error { if s.notice != nil { if err := s.notice(ctx, state, server, local); err != nil { return err @@ -105,8 +232,8 @@ func (s *Syncer[T, V]) onNotice(ctx context.Context, state int, server, local T, // Sync synchronizes the data between the server and local storage. // It takes a context, two slices of data (serverData and localData), // a notice function to handle notifications during the sync process, -// and a variadic parameter noDel to control deletion behavior. -func (s *Syncer[T, V]) Sync(ctx context.Context, serverData []T, localData []T, notice func(ctx context.Context, state int, server, local T) error, noDel ...bool) (err error) { +// and a variadic parameter skipDeletion to control deletion behavior. +func (s *Syncer[T, RESP, V]) Sync(ctx context.Context, serverData []T, localData []T, notice func(ctx context.Context, state int, server, local T) error, skipDeletionAndNotice ...bool) (err error) { defer func() { // Log the outcome of the synchronization process. if err == nil { @@ -115,6 +242,14 @@ func (s *Syncer[T, V]) Sync(ctx context.Context, serverData []T, localData []T, log.ZError(ctx, "sync failed", err, "type", s.ts) } }() + skipDeletion := false + skipNotice := false + if len(skipDeletionAndNotice) > 0 { + skipDeletion = skipDeletionAndNotice[0] + } + if len(skipDeletionAndNotice) > 1 { + skipNotice = skipDeletionAndNotice[1] + } // If both server and local data are empty, log and return. if len(serverData) == 0 && len(localData) == 0 { @@ -123,10 +258,9 @@ func (s *Syncer[T, V]) Sync(ctx context.Context, serverData []T, localData []T, } // Convert local data into a map for easier lookup. - localMap := make(map[V]T) - for i, item := range localData { - localMap[s.uuid(item)] = localData[i] - } + localMap := datautil.SliceToMap(localData, func(item T) V { + return s.uuid(item) + }) // Iterate through server data to sync with local data. for i := range serverData { @@ -136,46 +270,53 @@ func (s *Syncer[T, V]) Sync(ctx context.Context, serverData []T, localData []T, // If the item doesn't exist locally, insert it. if !ok { + log.ZDebug(ctx, "sync insert", "type", s.ts, "server", server) if err := s.insert(ctx, server); err != nil { log.ZError(ctx, "sync insert failed", err, "type", s.ts, "server", server, "local", local) return err } - if err := s.onNotice(ctx, Insert, server, local, notice); err != nil { - log.ZError(ctx, "sync notice insert failed", err, "type", s.ts, "server", server, "local", local) - return err + if !skipNotice { + if err := s.onNotice(ctx, Insert, server, local, notice); err != nil { + log.ZError(ctx, "sync notice insert failed", err, "type", s.ts, "server", server, "local", local) + return err + } } continue } // Remove the item from the local map as it's found. delete(localMap, id) - log.ZDebug(ctx, "syncer come", "type", s.ts, "server", server, "local", local, "isEq", s.eq(server, local)) // If the local and server items are equal, notify and continue. if s.eq(server, local) { - if err := s.onNotice(ctx, Unchanged, local, server, notice); err != nil { - log.ZError(ctx, "sync notice unchanged failed", err, "type", s.ts, "server", server, "local", local) - return err + if !skipNotice { + if err := s.onNotice(ctx, Unchanged, local, server, notice); err != nil { + log.ZError(ctx, "sync notice unchanged failed", err, "type", s.ts, "server", server, "local", local) + return err + } } continue } + log.ZDebug(ctx, "sync update", "type", s.ts, "server", server, "local", local) // Update the local item with server data. if err := s.update(ctx, server, local); err != nil { log.ZError(ctx, "sync update failed", err, "type", s.ts, "server", server, "local", local) return err } - if err := s.onNotice(ctx, Update, server, local, notice); err != nil { - log.ZError(ctx, "sync notice update failed", err, "type", s.ts, "server", server, "local", local) - return err + if !skipNotice { + if err := s.onNotice(ctx, Update, server, local, notice); err != nil { + log.ZError(ctx, "sync notice update failed", err, "type", s.ts, "server", server, "local", local) + return err + } } } - // Check the noDel flag; if set, skip deletion. - if len(noDel) > 0 && noDel[0] { + // Check the skipDeletion flag; if set, skip deletion. + if skipDeletion { return nil } - + log.ZDebug(ctx, "sync delete", "type", s.ts, "localMap", localMap) // Delete any local items not present in server data. for id := range localMap { local := localMap[id] @@ -184,10 +325,46 @@ func (s *Syncer[T, V]) Sync(ctx context.Context, serverData []T, localData []T, return err } var server T - if err := s.onNotice(ctx, Delete, server, local, notice); err != nil { - log.ZError(ctx, "sync notice delete failed", err, "type", s.ts, "local", local) - return err + if !skipNotice { + if err := s.onNotice(ctx, Delete, server, local, notice); err != nil { + log.ZError(ctx, "sync notice delete failed", err, "type", s.ts, "local", local) + return err + } } } return nil } + +func (s *Syncer[T, RESP, V]) FullSync(ctx context.Context, entityID string) (err error) { + defer func() { + // Log the outcome of the synchronization process. + if err == nil { + log.ZDebug(ctx, "full sync success", "type", s.ts) + } else { + log.ZError(ctx, "full sync failed", err, "type", s.ts) + } + }() + + //// If server data is empty, log and return + //if len(serverData) == 0 { + // log.ZDebug(ctx, "full sync server data is empty", "type", s.ts) + // return nil + //} + + // Clear local table data + if err = s.deleteAll(ctx, entityID); err != nil { + return errs.New("full sync delete all failed", "err", err.Error(), "type", s.ts) + } + + // Get batch req + batchReq := s.batchPageReq(entityID) + + // Batch page pull data and insert server data + if err = util.FetchAndInsertPagedData(ctx, s.reqApiRouter, batchReq, s.batchPageRespConvertFunc, + s.batchInsert, s.insert, 100); err != nil { + return errs.New("full sync batch insert failed", "err", err.Error(), "type", s.ts) + } + + return nil + +} diff --git a/scripts/template/head.md.tmpl b/scripts/template/head.md.tmpl index c759ef5c5..dd4f12c85 100644 --- a/scripts/template/head.md.tmpl +++ b/scripts/template/head.md.tmpl @@ -4,9 +4,9 @@ We are excited to release {{.Tag}}, Branch: https://github.com/{{ .Env.USERNAME Learn more about versions of OpenIM: -+ For information on versions of OpenIM and how to maintain branches, read [📚this article](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/version.md) ++ For information on versions of OpenIM and how to maintain branches, read [📚this article](https://github.com/openimsdk/Open-IM-Server/blob/main/docs/conversions/version.md) -+ If you wish to use mirroring, read OpenIM's [🤲image management policy](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/images.md) ++ If you wish to use mirroring, read OpenIM's [🤲image management policy](https://github.com/openimsdk/Open-IM-Server/blob/main/docs/conversions/images.md) **Want to be one of them 😘?** diff --git a/sdk_struct/sdk_struct.go b/sdk_struct/sdk_struct.go index 20a246afe..acd54a4d7 100644 --- a/sdk_struct/sdk_struct.go +++ b/sdk_struct/sdk_struct.go @@ -15,7 +15,7 @@ package sdk_struct import ( - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" ) ////////////////////////// message///////////////////////// @@ -364,3 +364,4 @@ type MsgDeleteNotificationElem struct { IsAllDelete bool `json:"isAllDelete"` SeqList []string `json:"seqList"` } + diff --git a/test/account.go b/test/account.go index e3456a53b..fd969d778 100644 --- a/test/account.go +++ b/test/account.go @@ -17,7 +17,6 @@ package test import ( "context" "errors" - "fmt" "github.com/openimsdk/openim-sdk-core/v3/internal/util" "github.com/openimsdk/openim-sdk-core/v3/pkg/ccontext" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" @@ -28,10 +27,10 @@ import ( "sync" "time" - authPB "github.com/OpenIMSDK/protocol/auth" - "github.com/OpenIMSDK/protocol/sdkws" - userPB "github.com/OpenIMSDK/protocol/user" - "github.com/OpenIMSDK/tools/log" + authPB "github.com/openimsdk/protocol/auth" + "github.com/openimsdk/protocol/sdkws" + userPB "github.com/openimsdk/protocol/user" + "github.com/openimsdk/tools/log" ) func GenUid(uid int, prefix string) string { @@ -86,9 +85,10 @@ var AdminToken = "" func init() { AdminToken = getToken("openIM123456") - if err := log.InitFromConfig("open-im-sdk-core", "", int(LogLevel), IsLogStandardOutput, false, LogFilePath, 0, 24); err != nil { - fmt.Println("123456", "log init failed ", err.Error()) + if err := log.InitFromConfig("open-im-sdk-core", "", int(LogLevel), IsLogStandardOutput, false, LogFilePath, 0, 24, "23432"); err != nil { + //fmt.Println("123456", "log init failed ", err.Error()) } + } var ctx context.Context diff --git a/test/login.go b/test/login.go index 46bf8b608..e457db619 100644 --- a/test/login.go +++ b/test/login.go @@ -18,11 +18,11 @@ import ( "encoding/json" "errors" "fmt" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/log" "time" ) diff --git a/test/reliability.go b/test/reliability.go index 2f05caa8b..5ddb760bf 100644 --- a/test/reliability.go +++ b/test/reliability.go @@ -17,8 +17,8 @@ package test import ( "errors" "fmt" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/log" "io/ioutil" "math/rand" "os" diff --git a/test/sendMessage.go b/test/sendMessage.go index 198a0c491..7472c7305 100644 --- a/test/sendMessage.go +++ b/test/sendMessage.go @@ -15,11 +15,11 @@ package test import ( - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" ) func init() { diff --git a/test/t_conversation_msg.go b/test/t_conversation_msg.go index 0a555076b..ae3dabff6 100644 --- a/test/t_conversation_msg.go +++ b/test/t_conversation_msg.go @@ -17,18 +17,19 @@ package test import ( "encoding/json" "fmt" - "github.com/OpenIMSDK/tools/log" + "sync" + "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" - "sync" + "github.com/openimsdk/tools/log" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" - "github.com/OpenIMSDK/tools/mcontext" + "github.com/openimsdk/tools/mcontext" ) //funcation DotestSetConversationRecvMessageOpt() { @@ -434,7 +435,7 @@ func (g GetHistoryCallBack) OnError(errCode int32, errMsg string) { func (g GetHistoryCallBack) OnSuccess(data string) { g.Data = data - log.ZInfo(ctx, "get History success ", "operationID", g.OperationID, "data", data) + log.ZInfo(ctx, "get History success. ", "operationID", g.OperationID, "data", g.Data) } type SetAppBadgeCallBack struct { @@ -506,7 +507,7 @@ func (g GetMessageListReactionExtensionsCallBack) OnError(errCode int32, errMsg } func (g GetMessageListReactionExtensionsCallBack) OnSuccess(data string) { - log.ZInfo(ctx, g.OperationID, "GetMessageListReactionExtensionsCallBack success", "data", data) + log.ZInfo(ctx, g.OperationID, "GetMessageListReactionExtensionsCallBack success. data", data) } type GetHistoryReverseCallBack struct { @@ -518,7 +519,7 @@ func (g GetHistoryReverseCallBack) OnError(errCode int32, errMsg string) { } func (g GetHistoryReverseCallBack) OnSuccess(data string) { - log.ZInfo(ctx, g.OperationID, "GetHistoryReverseCallBack success", "data", data) + log.ZInfo(ctx, g.OperationID, "GetHistoryReverseCallBack success. data", data) } type SearchLocalMessagesCallBack struct { @@ -530,7 +531,7 @@ func (g SearchLocalMessagesCallBack) OnError(errCode int32, errMsg string) { } func (g SearchLocalMessagesCallBack) OnSuccess(data string) { - fmt.Println(g.OperationID, "SearchLocalMessagesCallBack success", "data", data) + fmt.Println(g.OperationID, "SearchLocalMessagesCallBack success. data", data) } type MsgListenerCallBak struct { @@ -544,8 +545,8 @@ func (m *MsgListenerCallBak) OnRecvOfflineNewMessage(message string) { } func (m *MsgListenerCallBak) OnRecvMessageExtensionsAdded(msgID string, reactionExtensionList string) { - fmt.Printf("OnRecvMessageExtensionsAdded", msgID, reactionExtensionList) - log.ZInfo(ctx, "internal", "OnRecvMessageExtensionsAdded", "msgID", msgID, "reactionExtensionList", reactionExtensionList) + fmt.Printf("OnRecvMessageExtensionsAdded %v %v", msgID, reactionExtensionList) + log.ZInfo(ctx, "internal OnRecvMessageExtensionsAdded", "msgID", msgID, "reactionExtensionList", reactionExtensionList) } func (m *MsgListenerCallBak) OnRecvGroupReadReceipt(groupMsgReceiptList string) { @@ -557,11 +558,11 @@ func (m *MsgListenerCallBak) OnNewRecvMessageRevoked(messageRevoked string) { } func (m *MsgListenerCallBak) OnRecvMessageExtensionsChanged(msgID string, reactionExtensionList string) { - log.ZInfo(ctx, "internal", "OnRecvMessageExtensionsChanged", "msgID", msgID, "reactionExtensionList", reactionExtensionList) + log.ZInfo(ctx, "internal OnRecvMessageExtensionsChanged", "msgID", msgID, "reactionExtensionList", reactionExtensionList) } func (m *MsgListenerCallBak) OnRecvMessageExtensionsDeleted(msgID string, reactionExtensionKeyList string) { - log.ZInfo(ctx, "internal", "OnRecvMessageExtensionsDeleted", "msgID", msgID, "reactionExtensionKeyList", reactionExtensionKeyList) + log.ZInfo(ctx, "internal OnRecvMessageExtensionsDeleted", "msgID", msgID, "reactionExtensionKeyList", reactionExtensionKeyList) } func (m *MsgListenerCallBak) OnRecvOnlineOnlyMessage(message string) { @@ -598,11 +599,11 @@ type TestSearchLocalMessages struct { } func (t TestSearchLocalMessages) OnError(errCode int32, errMsg string) { - log.ZInfo(ctx, t.OperationID, "SearchLocalMessages , OnError", "errCode", errCode, "errMsg", errMsg) + log.ZInfo(ctx, "SearchLocalMessages , OnError", "operationID", t.OperationID, "errCode", errCode, "errMsg", errMsg) } func (t TestSearchLocalMessages) OnSuccess(data string) { - log.ZInfo(ctx, t.OperationID, "SearchLocalMessages , OnSuccess", "data", data) + log.ZInfo(ctx, "SearchLocalMessages , OnSuccess", "operationID", t.OperationID, "data", data) } //funcation DoTestSearchLocalMessages() { @@ -622,11 +623,11 @@ type TestDeleteConversation struct { } func (t TestDeleteConversation) OnError(errCode int32, errMsg string) { - log.ZInfo(ctx, t.OperationID, "TestDeleteConversation , OnError", "errCode", errCode, "errMsg", errMsg) + log.ZInfo(ctx, "TestDeleteConversation , OnError", "operationID", t.OperationID, "errCode", errCode, "errMsg", errMsg) } func (t TestDeleteConversation) OnSuccess(data string) { - log.ZInfo(ctx, t.OperationID, "TestDeleteConversation , OnSuccess", "data", data) + log.ZInfo(ctx, "TestDeleteConversation , OnSuccess", "operationID", t.OperationID, "data", data) } func (m MsgListenerCallBak) OnRecvC2CReadReceipt(data string) { @@ -652,29 +653,29 @@ func (c *conversationCallBack) OnSyncServerProgress(progress int) { log.ZInfo(ctx, utils.GetSelfFuncName(), "progress", progress) } -func (c *conversationCallBack) OnSyncServerStart() { +func (c *conversationCallBack) OnSyncServerStart(reinstalled bool) { } -func (c *conversationCallBack) OnSyncServerFinish() { +func (c *conversationCallBack) OnSyncServerFinish(reinstalled bool) { c.SyncFlag = 1 log.ZInfo(ctx, utils.GetSelfFuncName()) } -func (c *conversationCallBack) OnSyncServerFailed() { +func (c *conversationCallBack) OnSyncServerFailed(reinstalled bool) { log.ZInfo(ctx, utils.GetSelfFuncName()) } func (c *conversationCallBack) OnNewConversation(conversationList string) { - log.ZInfo(ctx, "OnNewConversation returnList is", conversationList) + log.ZInfo(ctx, "OnNewConversation.", "returnList is", conversationList) } func (c *conversationCallBack) OnConversationChanged(conversationList string) { - log.ZInfo(ctx, "OnConversationChanged returnList is", conversationList) + log.ZInfo(ctx, "OnConversationChanged. ", "returnList is", conversationList) } func (c *conversationCallBack) OnTotalUnreadMessageCountChanged(totalUnreadCount int32) { - log.ZInfo(ctx, "OnTotalUnreadMessageCountChanged returnTotalUnreadCount is", totalUnreadCount) + log.ZInfo(ctx, "OnTotalUnreadMessageCountChanged. ", "returnTotalUnreadCount is", totalUnreadCount) } func (c *conversationCallBack) OnConversationUserInputStatusChanged(change string) { @@ -736,7 +737,7 @@ func DoTestSendMsg2(sendId, recvID string) { o := sdkws.OfflinePushInfo{} o.Title = "121313" o.Desc = "45464" - open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(o), false) + open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(&o), false) log.ZInfo(ctx, utils.GetSelfFuncName(), "success", "sendId", sendId, "recvID", recvID) // 修改此行 } @@ -750,7 +751,7 @@ func DoTestSendMsg2Group(sendId, groupID string, index int) { o := sdkws.OfflinePushInfo{} o.Title = "Title" o.Desc = "Desc" - open_im_sdk.SendMessage(&testSendMsg, operationID, s, "", groupID, utils.StructToJsonString(o), false) + open_im_sdk.SendMessage(&testSendMsg, operationID, s, "", groupID, utils.StructToJsonString(&o), false) log.ZInfo(ctx, utils.GetSelfFuncName(), "success") // 修改此行 } @@ -763,7 +764,7 @@ func DoTestSendMsg2GroupWithMessage(sendId, groupID string, message string) { o := sdkws.OfflinePushInfo{} o.Title = "Title" o.Desc = "Desc" - open_im_sdk.SendMessage(&testSendMsg, operationID, s, "", groupID, utils.StructToJsonString(o), false) + open_im_sdk.SendMessage(&testSendMsg, operationID, s, "", groupID, utils.StructToJsonString(&o), false) log.ZInfo(ctx, utils.GetSelfFuncName(), "success") // 修改此行 } @@ -777,7 +778,7 @@ func DoTestSendMsg2c2c(sendId, recvID string, index int) { o := sdkws.OfflinePushInfo{} o.Title = "Title" o.Desc = "Desc" - open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(o), false) + open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(&o), false) log.ZInfo(ctx, utils.GetSelfFuncName(), "success") // 修改此行 } @@ -814,7 +815,7 @@ func DoTestSendMsg(index int, sendId, recvID string, groupID string, idx string) testSendMsg.recvID = recvID testSendMsg.groupID = groupID testSendMsg.msgID = s.ClientMsgID - log.ZInfo(ctx, "SendMessage", "operationID", operationID, "sendId", sendId, "recvID", recvID, "groupID", groupID, "msgID", + log.ZInfo(ctx, "SendMessage", "operationID", testSendMsg.OperationID, "sendId", testSendMsg.sendID, "recvID", testSendMsg.recvID, "groupID", testSendMsg.groupID, "msgID", testSendMsg.msgID, "index", index) if recvID != "" { allLoginMgr[index].mgr.Conversation().SendMessage(ctx, s, recvID, "", &o, false) @@ -823,7 +824,7 @@ func DoTestSendMsg(index int, sendId, recvID string, groupID string, idx string) } SendMsgMapLock.Lock() defer SendMsgMapLock.Unlock() - x := SendRecvTime{SendTime: utils.GetCurrentTimestampByMill()} + x := SendRecvTime{SendTime: testSendMsg.sendTime} SendSuccAllMsg[testSendMsg.msgID] = &x } @@ -857,7 +858,7 @@ func DoTestSendImageMsg(recvID string) { o := sdkws.OfflinePushInfo{} o.Title = "121313" o.Desc = "45464" - open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(o), false) + open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(&o), false) } //funcation DotestUploadFile() { @@ -874,7 +875,7 @@ func DoTestSendOtherMsg(sendId, recvID string) { o := sdkws.OfflinePushInfo{} o.Title = "121313" o.Desc = "45464" - open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(o), false) + open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(&o), false) } func DoTestSendVideo(sendId, recvID string) { @@ -886,7 +887,7 @@ func DoTestSendVideo(sendId, recvID string) { o.Title = "121313" o.Desc = "45464" log.ZInfo(ctx, "SendMessage", "operationID", operationID, "message", s) - open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(o), false) + open_im_sdk.SendMessage(&testSendMsg, operationID, s, recvID, "", utils.StructToJsonString(&o), false) } type TestClearMsg struct { diff --git a/test/t_friend_sdk.go b/test/t_friend_sdk.go index 14aeb2054..6a3859579 100644 --- a/test/t_friend_sdk.go +++ b/test/t_friend_sdk.go @@ -18,20 +18,20 @@ import ( "encoding/json" "errors" "fmt" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" "github.com/openimsdk/openim-sdk-core/v3/pkg/ccontext" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/tools/log" X "log" "os" "runtime" "time" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" - "github.com/OpenIMSDK/tools/mcontext" + "github.com/openimsdk/tools/mcontext" ) var loggerf *X.Logger diff --git a/test/t_group_sdk.go b/test/t_group_sdk.go index 294e39db6..e0d040661 100644 --- a/test/t_group_sdk.go +++ b/test/t_group_sdk.go @@ -22,8 +22,8 @@ import ( // "encoding/json" "fmt" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/log" //"open_im_sdk/internal/open_im_sdk" //"open_im_sdk/pkg/utils" // "open_im_sdk/internal/common" diff --git a/test/t_signaling.go b/test/t_signaling.go index b8c99dc95..052bf1ddf 100644 --- a/test/t_signaling.go +++ b/test/t_signaling.go @@ -17,7 +17,7 @@ package test import ( "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" "golang.org/x/net/context" ) diff --git a/test/work_group_create.go b/test/work_group_create.go index 2807fef8d..4bcca7958 100644 --- a/test/work_group_create.go +++ b/test/work_group_create.go @@ -17,15 +17,15 @@ package test import ( "encoding/json" "errors" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/network" "github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/log" "sync" "time" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" ) var ( diff --git a/testv2/config.go b/testv2/config.go index 94f24a22e..073dce8c4 100644 --- a/testv2/config.go +++ b/testv2/config.go @@ -15,14 +15,18 @@ package testv2 import ( - "github.com/OpenIMSDK/protocol/constant" "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/openimsdk/protocol/constant" ) const ( - APIADDR = "http://14.29.168.56:10002" - WSADDR = "ws://14.29.168.56:10001" - UserID = "3" + //APIADDR = "http://172.16.8.48:10002" + //WSADDR = "ws://172.16.8.48:10001" + + APIADDR = "http://127.0.0.1:10002" + WSADDR = "ws://127.0.0.1:10001" + + UserID = "6864873394" friendUserID = "3281432310" ) diff --git a/testv2/empty_test.go b/testv2/empty_test.go index 3824f62d7..fa94f1ae9 100644 --- a/testv2/empty_test.go +++ b/testv2/empty_test.go @@ -15,8 +15,8 @@ package testv2 import ( - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" + "github.com/openimsdk/tools/log" "testing" "time" ) diff --git a/testv2/friend_test.go b/testv2/friend_test.go index 56b8f2084..48292c6cb 100644 --- a/testv2/friend_test.go +++ b/testv2/friend_test.go @@ -15,13 +15,13 @@ package testv2 import ( - "github.com/OpenIMSDK/protocol/wrapperspb" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" + "github.com/openimsdk/protocol/wrapperspb" "testing" "time" - friend2 "github.com/OpenIMSDK/protocol/friend" + friend2 "github.com/openimsdk/protocol/relation" ) func Test_GetSpecifiedFriendsInfo(t *testing.T) { diff --git a/testv2/group_test.go b/testv2/group_test.go index 84c4ab300..73061fd9c 100644 --- a/testv2/group_test.go +++ b/testv2/group_test.go @@ -15,12 +15,12 @@ package testv2 import ( - "github.com/OpenIMSDK/protocol/group" - "github.com/OpenIMSDK/protocol/sdkws" - "github.com/OpenIMSDK/protocol/wrapperspb" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback" + "github.com/openimsdk/protocol/group" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/protocol/wrapperspb" "testing" ) diff --git a/testv2/init.go b/testv2/init.go index 9cc0afe4a..354cb7393 100644 --- a/testv2/init.go +++ b/testv2/init.go @@ -19,16 +19,16 @@ import ( "context" "encoding/json" "fmt" - "github.com/OpenIMSDK/protocol/constant" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" "github.com/openimsdk/openim-sdk-core/v3/pkg/ccontext" + "github.com/openimsdk/protocol/constant" "io" "math/rand" "net/http" "strconv" "time" - "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/tools/log" ) var ( diff --git a/testv2/listener.go b/testv2/listener.go index 792a75cbe..085552304 100644 --- a/testv2/listener.go +++ b/testv2/listener.go @@ -16,9 +16,7 @@ package testv2 type OnConnListener struct{} -func (c *OnConnListener) OnUserTokenInvalid(errMsg string) { - -} +func (c *OnConnListener) OnUserTokenInvalid(errMsg string) {} func (c *OnConnListener) OnConnecting() { // fmt.Println("OnConnecting") diff --git a/testv2/sync2_test.go b/testv2/sync2_test.go new file mode 100644 index 000000000..16e9a0b19 --- /dev/null +++ b/testv2/sync2_test.go @@ -0,0 +1,71 @@ +// Copyright © 2023 OpenIM SDK. 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 testv2 + +import ( + "fmt" + "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" + "github.com/openimsdk/protocol/constant" + "github.com/openimsdk/protocol/group" + "github.com/openimsdk/protocol/sdkws" + "github.com/openimsdk/tools/log" + "testing" + "time" +) + +func TestSyncFriend2(t *testing.T) { + for i := 0; ; i++ { + if err := open_im_sdk.UserForSDK.Friend().IncrSyncFriends(ctx); err != nil { + t.Log("IncrSyncFriends error-->", err) + continue + } + time.Sleep(time.Second) + } +} + +func TestSyncJoinGroup2(t *testing.T) { + for i := 0; ; i++ { + if err := open_im_sdk.UserForSDK.Group().IncrSyncJoinGroup(ctx); err != nil { + t.Log("IncrSyncJoinGroup error-->", err) + continue + } + time.Sleep(time.Second) + } +} + +func TestSyncGroupMember2(t *testing.T) { + for i := 0; ; i++ { + if err := open_im_sdk.UserForSDK.Group().IncrSyncJoinGroupMember(ctx); err != nil { + t.Log("IncrSyncGroupAndMember error-->", err) + continue + } + time.Sleep(time.Second) + } +} + +func TestName(t *testing.T) { + for i := 1; i <= 600; i++ { + _, err := open_im_sdk.UserForSDK.Group().CreateGroup(ctx, &group.CreateGroupReq{ + GroupInfo: &sdkws.GroupInfo{ + GroupType: constant.WorkingGroup, + GroupName: fmt.Sprintf("group_%d", i), + }, + MemberUserIDs: []string{"9556972319", "9719689061", "3872159645"}, + }) + if err != nil { + log.ZError(ctx, "group create failed", err, "index", i) + } + } +} diff --git a/testv2/user_test.go b/testv2/user_test.go index b77139911..229928f76 100644 --- a/testv2/user_test.go +++ b/testv2/user_test.go @@ -16,14 +16,14 @@ package testv2 import ( "fmt" - "github.com/OpenIMSDK/protocol/user" - "github.com/OpenIMSDK/protocol/wrapperspb" + "github.com/openimsdk/protocol/user" + "github.com/openimsdk/protocol/wrapperspb" "testing" "time" "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" - "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/protocol/sdkws" ) func Test_GetSelfUserInfo(t *testing.T) { diff --git a/version/version b/version/version new file mode 100644 index 000000000..240bba906 --- /dev/null +++ b/version/version @@ -0,0 +1 @@ +3.7.0 \ No newline at end of file diff --git a/version/version.go b/version/version.go new file mode 100644 index 000000000..23b3a82f5 --- /dev/null +++ b/version/version.go @@ -0,0 +1,6 @@ +package version + +import _ "embed" + +//go:embed version +var Version string diff --git a/wasm/event_listener/caller.go b/wasm/event_listener/caller.go index 992370353..efe71ea50 100644 --- a/wasm/event_listener/caller.go +++ b/wasm/event_listener/caller.go @@ -21,9 +21,9 @@ import ( "bytes" "context" "errors" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/wasm/exec" + "github.com/openimsdk/tools/log" "reflect" "strconv" "strings" diff --git a/wasm/exec/executor.go b/wasm/exec/executor.go index 983efd580..82d1d2d89 100644 --- a/wasm/exec/executor.go +++ b/wasm/exec/executor.go @@ -20,9 +20,9 @@ package exec import ( "context" "errors" - "github.com/OpenIMSDK/tools/errs" - "github.com/OpenIMSDK/tools/log" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" "runtime" "syscall/js" "time"