Compare commits

...

68 Commits

Author SHA1 Message Date
kubbot 6c6979e8b7 fix: make link->make lint
Signed-off-by: kubbot <3293172751ysy@gmail.com>
2023-08-11 11:34:18 +08:00
kubbot 84e02fa366 fix: make link->make lint
Signed-off-by: kubbot <3293172751ysy@gmail.com>
2023-08-11 11:32:51 +08:00
hanzhixiao f5081b7b61 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 11:04:25 +08:00
hanzhixiao f71bd11670 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 11:03:05 +08:00
hanzhixiao 62010f70cf 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 10:27:29 +08:00
hanzhixiao c3af2a3626 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 10:24:14 +08:00
hanzhixiao ec8238fd02 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 10:21:55 +08:00
hanzhixiao 3d3e3620e1 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 10:05:56 +08:00
hanzhixiao 00f179450b new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 09:58:38 +08:00
hanzhixiao 5a5259ad6c 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 09:58:38 +08:00
hanzhixiao ba65647e66 if [ -eq 1 ]; then
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 09:58:38 +08:00
hanzhixiao b01f66b54e new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 09:58:38 +08:00
hanzhixiao aacdcdeee7 new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 09:58:38 +08:00
hanzhixiao b670f305ae new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 09:58:38 +08:00
hanzhixiao 5cebde462f new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 09:58:38 +08:00
hanzhixiao 4af19ac64e new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 09:58:38 +08:00
hanzhixiao c1f6c448d0 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-11 09:58:35 +08:00
Gordon 71393da390 chore: network mode change to start server normally (#847)
* fix: to start im or chat, ZooKeeper must be started first.

* fix: msg gateway start output err info

Signed-off-by: Gordon <1432970085@qq.com>

* fix: msg gateway start output err info

Signed-off-by: Gordon <1432970085@qq.com>

* chore: package path changes

Signed-off-by: withchao <993506633@qq.com>

* fix: go mod update

Signed-off-by: Gordon <1432970085@qq.com>

* fix: token update

Signed-off-by: Gordon <1432970085@qq.com>

* chore: package path changes

Signed-off-by: withchao <993506633@qq.com>

* chore: package path changes

Signed-off-by: withchao <993506633@qq.com>

* fix: token update

Signed-off-by: Gordon <1432970085@qq.com>

* fix: token update

Signed-off-by: Gordon <1432970085@qq.com>

* fix: token update

Signed-off-by: Gordon <1432970085@qq.com>

* fix: token update

Signed-off-by: Gordon <1432970085@qq.com>

* fix: token update

Signed-off-by: Gordon <1432970085@qq.com>

* fix: token update

Signed-off-by: Gordon <1432970085@qq.com>

* fix: get all userID

Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>

* fix: msggateway add online status call

Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>

* refactor: log change

Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>

* refactor: log change

Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>

* chore: network mode change

Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>

---------

Signed-off-by: Gordon <1432970085@qq.com>
Signed-off-by: withchao <993506633@qq.com>
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
Co-authored-by: withchao <993506633@qq.com>
Co-authored-by: Xinwei Xiong <3293172751NSS@gmail.com>
2023-08-11 09:57:23 +08:00
WangchuXiao 825622fd99 Fix add friend (#845)
* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* MsgDestructTime

* fix bug: msg destruct sql

* fix bug: msg destruct

* fix bug: msg destruct

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* debug: print stack

* debug: print stack

* debug: print stack

* fix bug: msg destruct sql

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* fix bug: msg notification self 2 self push twice

* fix bug: heartbeat get self notification

* fix bug: init grpc conn in one process

* fix bug: grpc conn

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* fix bug: zk client recreate node when reconn

* fix bug: set friend mark args error

* fix bug: rpc client intercepter called twice

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* cicd: robot automated Change

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* test: document msg num set 100

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* merge code

* merge code

* fix bug: repeat add friend not effect

* cicd: robot automated Change

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix bug: refused friend

* fix bug: fix_add_friend

* fix bug: fix_add_friend

* fix bug: fix_add_friend

* fix bug: fix_add_friend

---------

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: wangchuxiao-dev <wangchuxiao-dev@users.noreply.github.com>
2023-08-10 12:25:54 +00:00
WangchuXiao 415d40f8c5 Fix bug: first time add friend (#844)
* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* MsgDestructTime

* fix bug: msg destruct sql

* fix bug: msg destruct

* fix bug: msg destruct

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* debug: print stack

* debug: print stack

* debug: print stack

* fix bug: msg destruct sql

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* fix bug: msg notification self 2 self push twice

* fix bug: heartbeat get self notification

* fix bug: init grpc conn in one process

* fix bug: grpc conn

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* fix bug: zk client recreate node when reconn

* fix bug: set friend mark args error

* fix bug: rpc client intercepter called twice

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* cicd: robot automated Change

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* test: document msg num set 100

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* merge code

* merge code

* fix bug: repeat add friend not effect

* fix bug: refused friend

* fix bug: fix_add_friend

* fix bug: fix_add_friend

* fix bug: fix_add_friend

---------

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: wangchuxiao-dev <wangchuxiao-dev@users.noreply.github.com>
2023-08-10 12:12:37 +00:00
hanzhixiao f12b18d8b0 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 18:05:57 +08:00
hanzhixiao 0cdea88393 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:44:00 +08:00
hanzhixiao df3e234a28 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:40:55 +08:00
dependabot[bot] bde3d98d0f feat(deps): bump golang from 1.20 to 1.21 (#831)
Bumps golang from 1.20 to 1.21.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-10 09:27:37 +00:00
hanzhixiao 87d132676b new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:20:24 +08:00
hanzhixiao d442573c66 815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:20:24 +08:00
hanzhixiao fa1f717f80 if [ -eq 1 ]; then
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:20:24 +08:00
hanzhixiao a604c69f1e new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:20:24 +08:00
hanzhixiao 18d5bbb51f new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:20:24 +08:00
hanzhixiao aec5dd5ac5 new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:20:24 +08:00
hanzhixiao 59c6c32707 new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:20:24 +08:00
hanzhixiao cab30e7311 new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 17:20:23 +08:00
dependabot[bot] d37796a58f feat(deps): bump the gomod-deps group with 2 updates (#840)
Bumps the gomod-deps group with 2 updates: [google.golang.org/api](https://github.com/googleapis/google-api-go-client) and [gorm.io/gorm](https://github.com/go-gorm/gorm).


Updates `google.golang.org/api` from 0.135.0 to 0.136.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.135.0...v0.136.0)

Updates `gorm.io/gorm` from 1.25.2 to 1.25.3
- [Release notes](https://github.com/go-gorm/gorm/releases)
- [Commits](https://github.com/go-gorm/gorm/compare/v1.25.2...v1.25.3)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-deps
- dependency-name: gorm.io/gorm
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-10 09:14:08 +00:00
WangchuXiao 4fcea57df0 Fix bug: where if the last message in the document is an expired message, it won't delete the message within that document. (#839)
* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* MsgDestructTime

* fix bug: msg destruct sql

* fix bug: msg destruct

* fix bug: msg destruct

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* debug: print stack

* debug: print stack

* debug: print stack

* fix bug: msg destruct sql

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* fix bug: msg notification self 2 self push twice

* fix bug: heartbeat get self notification

* fix bug: init grpc conn in one process

* fix bug: grpc conn

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* fix bug: zk client recreate node when reconn

* fix bug: set friend mark args error

* fix bug: rpc client intercepter called twice

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* cicd: robot automated Change

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* test: document msg num set 100

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* merge code

* merge code

* fix bug: repeat add friend not effect

* fix bug: cron del mongo msg

---------

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: wangchuxiao-dev <wangchuxiao-dev@users.noreply.github.com>
2023-08-10 08:02:42 +00:00
hanzhixiao d9c28dbbda new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 11:17:32 +08:00
hanzhixiao 45d003415c new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 11:14:28 +08:00
hanzhixiao c2061500ca new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 11:05:34 +08:00
hanzhixiao 08f96beb16 new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 11:01:21 +08:00
hanzhixiao 9df16eaf25 new_815
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-10 10:50:05 +08:00
withchao 1d98a9959c fix: MemberEnterNotification (#834)
* fix: create group type limit

* fix: group notification

* fix: group notification

* fix: group notification
2023-08-09 09:53:16 +00:00
Alan 3ecd33aded 744 (#766)
Signed-off-by: hanzhixiao <709674996@qq.com>
2023-08-09 02:53:48 +00:00
WangchuXiao 5615e47d99 new feature data convert (#819)
* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* new feature: add batch send msg

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* fix bug: multiple gateway kick user

* MsgDestructTime

* fix bug: msg destruct sql

* fix bug: msg destruct

* fix bug: msg destruct

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* fix bug: msg destruct sql

* debug: print stack

* debug: print stack

* debug: print stack

* fix bug: msg destruct sql

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* fix bug: msg notification self 2 self push twice

* fix bug: heartbeat get self notification

* fix bug: init grpc conn in one process

* fix bug: grpc conn

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* fix bug: zk client recreate node when reconn

* fix bug: set friend mark args error

* fix bug: rpc client intercepter called twice

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>

* cicd: robot automated Change

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* test: document msg num set 100

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* new feat: sync designated model

* merge code

* merge code

* fix bug: repeat add friend not effect

* feat: msg doc len changed

* feat: msg doc len changed

* feat: msg doc len changed

* feat: msg doc len changed

* feat: msg doc len changed

* feat: msg doc len changed

* feat: msg doc len changed

* feat: msg doc len changed

* feat: msg doc len changed

---------

Signed-off-by: wangchuxiao <wangchuxiao97@outlook.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: wangchuxiao-dev <wangchuxiao-dev@users.noreply.github.com>
2023-08-09 02:37:56 +00:00
withchao 04a97ac154 fix: create group type limit (#824) 2023-08-09 02:34:41 +00:00
dependabot[bot] 598938c13c feat(deps): bump the gomod-deps group with 1 update (#820)
Bumps the gomod-deps group with 1 update: [golang.org/x/image](https://github.com/golang/image).

- [Commits](https://github.com/golang/image/compare/v0.9.0...v0.11.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-09 01:41:49 +00:00
Xinwei Xiong d97c44ef99 Update stop_all.sh (#822) 2023-08-09 01:41:04 +00:00
withchao e706620f12 feat: server thumbnail (#818)
* feat: add get_group_member_user_id api

* feat: add SendBusinessNotification api

* feat: add GetFriendIDs api

* update pkg

* feat: cos oss thumbnail

* feat: cos video snapshot

* feat: oss video snapshot

* feat: minio video snapshot

* feat: minio video snapshot

* feat: minio

* feat: minio

* feat: minio

* feat: s3 AccessURL

* feat: s3 AccessURL

* fix: Minio AccessURL

* fix: Minio AccessURL

* fix: optimize thumbnails

* fix: optimize thumbnails

* fix: cos option

* fix: cos option

* fix: cos option

* docs: config

* docs: config

* minio: preview image cache

* minio: preview image cache

* minio: preview image cache

* go mod tidy

* cicd: robot automated Change

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: withchao <withchao@users.noreply.github.com>
2023-08-08 08:40:07 +00:00
Xinwei Xiong bd518365ea Update version.md (#816) 2023-08-08 07:07:58 +00:00
Xinwei Xiong 73effdf644 fix: fix bin tools path (#814)
Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>
2023-08-08 03:42:36 +00:00
dependabot[bot] c8971de833 feat(deps): bump the gomod-deps group with 1 update (#813)
Bumps the gomod-deps group with 1 update: [google.golang.org/api](https://github.com/googleapis/google-api-go-client).

- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.134.0...v0.135.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 03:33:03 +00:00
Xinwei Xiong b26a979378 feat: add scripts format (#811)
* feat: add scripts format

Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>

* feat: add go work

Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>

---------

Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>
2023-08-08 03:24:15 +00:00
Xinwei Xiong 3836bf19d6 Update docker-compose.yaml (#810) 2023-08-07 10:04:34 +00:00
dependabot[bot] f2f2448fe2 feat(deps): bump the gomod-deps group with 3 updates (#808)
Bumps the gomod-deps group with 3 updates: [github.com/go-playground/validator/v10](https://github.com/go-playground/validator), [google.golang.org/api](https://github.com/googleapis/google-api-go-client) and [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `github.com/go-playground/validator/v10` from 10.14.1 to 10.15.0
- [Release notes](https://github.com/go-playground/validator/releases)
- [Commits](https://github.com/go-playground/validator/compare/v10.14.1...v10.15.0)

Updates `google.golang.org/api` from 0.114.0 to 0.134.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.114.0...v0.134.0)

Updates `google.golang.org/grpc` from 1.56.2 to 1.57.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.56.2...v1.57.0)

---
updated-dependencies:
- dependency-name: github.com/go-playground/validator/v10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-deps
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-07 09:42:49 +00:00
Xinwei Xiong 969a9d8782 Update README.md (#807) 2023-08-07 07:36:18 +00:00
Xinwei Xiong 6f64b0a236 Update README.md (#806) 2023-08-07 07:32:42 +00:00
Xinwei Xiong 4d04c76cd7 docs: add png multi-terminal-synchronization (#805) 2023-08-07 07:26:23 +00:00
Xinwei Xiong 7a448b35d4 feat: fix scripts and build speed (#790)
* feat: fix scripts and build speed

Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>

* feat: add docker compose file

Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>

* fix: fix image

Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>

* feat: add chat scripts design

Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>

---------

Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>
2023-08-07 06:21:31 +00:00
Xinwei Xiong 594b16374b Update README.md (#803) 2023-08-07 02:22:48 +00:00
Xinwei Xiong 39275c0110 Update README.md (#802) 2023-08-07 02:07:33 +00:00
Xinwei Xiong 4ad81c363c Update README.md (#801) 2023-08-07 02:07:22 +00:00
Xinwei Xiong 10b56142d5 Update README.md (#800) 2023-08-07 02:05:22 +00:00
Xinwei Xiong 5ee54c9c2a docs: add png file (#799) 2023-08-07 02:04:27 +00:00
Xinwei Xiong 0b75c52a6e Create README.md (#798) 2023-08-07 02:01:55 +00:00
Xinwei Xiong 375105997f Update README.md (#797) 2023-08-06 07:39:06 +00:00
Xinwei Xiong 4e9179f309 Update README.md (#796) 2023-08-06 07:33:48 +00:00
Xinwei Xiong 863e925b30 Update README.md (#795) 2023-08-06 07:33:42 +00:00
Xinwei Xiong 8cb05d50c9 Update go_code.md (#794) 2023-08-06 07:13:13 +00:00
Xinwei Xiong 5d34e3f081 Update README.md (#793) 2023-08-06 07:08:11 +00:00
Xinwei Xiong d8fd4bfcf1 Update README.md (#792) 2023-08-06 05:37:16 +00:00
101 changed files with 2856 additions and 960 deletions
+5 -2
View File
@@ -40,10 +40,13 @@ jobs:
- name: Checkout code
uses: actions/checkout@v3
- name: Download Docker Compose
run: |
curl -o docker-compose.yaml https://gist.githubusercontent.com/cubxxw/b1d5cbd2edfa23fee911118aa3e8249e/raw/openim-server.sh
shell: bash
- name: Start Docker Compose
run: |
sudo docker compose stop
sudo sleep 30
sudo docker compose up -d
sudo sleep 60
continue-on-error: true
+1 -1
View File
@@ -156,7 +156,7 @@ flycheck_*.el
# vendor/
# Go workspace file
go.work
# go.work
### JetBrains ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+6 -7
View File
@@ -10,14 +10,14 @@ ENV GOPROXY=$GOPROXY
# Set up the working directory
WORKDIR /openim/openim-server
COPY go.mod go.sum ./
RUN go mod download
COPY go.mod go.sum go.work go.work.sum ./
#RUN go mod download
# Copy all files to the container
ADD . .
RUN /bin/sh -c "make clean"
RUN /bin/sh -c "make build"
RUN make clean
RUN make build
FROM ghcr.io/openim-sigs/openim-bash-image:latest
@@ -27,7 +27,6 @@ WORKDIR ${SERVER_WORKDIR}
COPY --from=builder ${OPENIM_SERVER_CMDDIR} /openim/openim-server/scripts
COPY --from=builder ${SERVER_WORKDIR}/config /openim/openim-server/config
COPY --from=builder ${SERVER_WORKDIR}/_output/bin/platforms /openim/openim-server/_output/bin/platforms
COPY --from=builder ${SERVER_WORKDIR}/_output/bin-tools/platforms /openim/openim-server/_output/bin-tools/platforms
VOLUME ["/openim/openim-server/logs","/openim/openim-server/config","/openim/openim-server/scripts"]
CMD ["bash","-c","${OPENIM_SERVER_CMDDIR}/docker_start_all.sh"]
CMD ["bash","-c","${OPENIM_SERVER_CMDDIR}/docker_start_all.sh"]
+157 -50
View File
@@ -22,42 +22,109 @@
<p align="center">
<a href="./README.md"><b> English </b></a> •
<a href="./README-zh_CN.md"><b> 中文 </b></a>
<a href="./README-zh_CN.md"><b> 简体中文 </b></a>
<a href="https://www.openim.online/en"><b> Docs </b></a>
</p>
</p>
## What is Open-IM-Server
## ✨ About OpenIM
Open-IM-Server is an instant messaging server developed using pure Golang, adopting JSON over WebSocket as the communication protocol. In Open-IM-Server, everything is a message, so you can easily extend custom messages without modifying the server code. With a microservice architecture, Open-IM-Server can be deployed using clusters. By deploying Open-IM-Server on a server, developers can quickly integrate instant messaging and real-time networking features into their applications, ensuring the security and privacy of business data.
Open-IM-Server, crafted meticulously using pure Golang, stands as a robust instant messaging server. Its unique approach to communication, via JSON over WebSocket, treats every interaction as a message. This simplifies customization and eliminates the need for tinkering with server code. Harnessing the power of microservice architecture, the server can be deployed via clusters, promising impressive performance and scalability.
Open-IM-Server is not a standalone product and does not include account registration and login services. For your convenience, we have open-sourced the [chat repository](https://github.com/OpenIMSDK/chat) which includes login and registration functionality. By deploying the chat business server alongside Open-IM-Server, a chat product can be set up.
Open-IM-Server is more than an instant messaging server; it's a powerful tool for incorporating real-time networking into your applications, positioning itself as your premier choice for integration! 🚀
## Features
Please be aware that Open-IM-Server does not function as a standalone product and does not offer built-in account registration or login services. To ease your implementation process, we've open-sourced the [chat repository](https://github.com/OpenIMSDK/chat), which comprises these features. Deploying this chat business server in conjunction with Open-IM-Server expedites the setup of a comprehensive chat product. 👥
- Open source
- Easy to integrate
- Excellent scalability
- High performance
- Lightweight
- Supports multiple protocols
Further enhancing your experience, we also provide an SDK client, wherein most complex logics are implemented. The [SDK repository](https://github.com/OpenIMSDK/openim-sdk-core) can be found at [this link](https://github.com/OpenIMSDK/openim-sdk-core). The [chat repository](https://github.com/OpenIMSDK/chat) is our business server while the 'core' represents the high-level encapsulation of the SDK, synergistically working together to deliver superior results. ✨
## Community
- Visit the official website: [OpenIM Developer Documentation](https://www.openim.online/)
## :star2: Why OpenIM
## Quick Start
**🔍 Function screenshot display**
### Deploying with docker-compose
<div align="center">
| 💻🔄📱 Multi Terminal Synchronization 🔄🖥️ | 📅⚡ Efficient Meetings 🚀💼 |
| :----------------------------------------------------------: | :---------------------------------------------------------: |
| ![multiple-message](./assets/demo/multi-terminal-synchronization.png) | ![efficient-meetings](./assets/demo/efficient-meetings.png) |
| 📲🔄 **One-to-one and Group Chats** 👥🗣️ | 🎁💻 **Special Features - Custom Messages** ✉️🎨|
| ![group-chat](./assets/demo/group-chat.png) | ![special-function](./assets/demo/special-function.png) |
</div>
1. **Comprehensive Message Type Support :speech_balloon:**
✅ Supports almost all types of messages, including text, images, emojis, voice, video, geographical location, files, quotes, business cards, system notifications, custom messages and more
✅ Supports one-on-one and multi-person audio and video calls
✅ Provides terminal support for multiple platforms such as iOS, Android, Flutter, uni-app, ReactNative, Electron, Web, H5
2. **Efficient Meetings Anytime, Anywhere :earth_americas:**
✅ Based on IM (Instant Messaging) with 100% reliable forced signaling capabilities, it paves the way for IM systems, deeply integrated with chat applications
✅ Supports hundreds of people in a single meeting, with subscription numbers reaching thousands, and server-side audio and video recording
3. **One-on-one and Group Chats for Various Social Scenarios :busts_in_silhouette:**
✅ OpenIM has four roles: application administrator, group owner, group administrator, and regular member
✅ Powerful group features such as muting, group announcements, group validation, unlimited group members, and loading group messages as needed
4. **Unique Features :star2:**
✅ Supports read-and-burn private chats, customizable duration
✅ Message editing function broadens social scenarios, making instant communication more diverse and interesting
5. **Open Source :open_hands:**
✅ The code of OpenIM is open source, self-controlled data, aimed at building a globally leading IM open source community, including client SDK and server
✅ Based on open source Server, many excellent open source projects have been developed, such as [OpenKF](https://github.com/OpenIMSDK/OpenKF) (Open source AI customer service system)
6. **Easy to Expand :wrench:**
✅ The OpenIM server is implemented in Golang, introducing an innovative "everything is a message" communication model, simplifying the implementation of custom messages and extended features
7. **High Performance :racing_car:**
✅ OpenIM supports a hierarchical governance architecture in the cluster, tested by a large number of users, and abstracts the storage model of online messages, offline messages, and historical messages
8. **Full Platform Support :tv:**
✅ Supports native iOS, Android; cross-platform Flutter, uni-app, ReactNative; major web front-end frameworks such as React, Vue; applets; and PC platforms supported by Electron
9. **The ultimate deployment experience 🤖**
✅ Supports [cluster deployment](https://github.com/OpenIMSDK/Open-IM-Server/edit/main/deployments/README.md)
✅ Supports multi-architecture mirroring, our Docker images are hosted not only on GitHub but also on Alibaba Cloud and Docker Hub supporting multiple architectures. Visit [our GitHub packages](https://github.com/orgs/OpenIMSDK/packages?repo_name=Open-IM-Server) and read our [version management document](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/version.md) for more information.
11. **A large ecosystem of open source communities 🤲**
✅ We have tens of thousands of users and many solutions to problems.
✅ We have a large open source community called [OpenIMSDK](https://github.com/OpenIMSDK) that runs the core modules, we have an open source community called [openim-sigs](https://github.com/openim-sigs) to explore more IM-based infrastructure products.
## :rocket: Quick Start
<details> <summary>Deploying with Docker Compose</summary>
1. Clone the project
```bash
# choose what you need
BRANCH=release-v3.0
BRANCH=release-v3.1
git clone -b $BRANCH https://github.com/OpenIMSDK/Open-IM-Server openim && export openim=$(pwd)/openim && cd $openim && make build
```
2. Modify .env
> **Note**
> Read our release policy: https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/version.md
2. Modify `.env`
```bash
USER=root #no need to modify
@@ -70,9 +137,9 @@ DATA_DIR=./ #designate large disk directory
3. Deploy and start
> **Note**
> This command can only be executed once. It will modify the component passwords in docker-compose based on the PASSWORD variable in .env, and modify the component passwords in config/config.yaml. If the password in .env changes, you need to first execute docker-compose down; rm components -rf and then execute this command.
> This command can only be executed once. It will modify the component passwords in docker-compose based on the `PASSWORD` variable in `.env`, and modify the component passwords in `config/config.yaml`. If the password in `.env` changes, you need to first execute `docker-compose down`; `rm components -rf` and then execute this command.
```
```bash
make install
```
@@ -84,9 +151,9 @@ make check
![https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/images/docker_build.png](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/images/docker_build.png)
</details>
### Compile from source
<details> <summary>Compile from Source</summary>
Ur need `Go 1.18` or higher version, and `make`.
@@ -97,6 +164,7 @@ Version Details: https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conv
BRANCH=release-v3.1
git clone -b $BRANCH https://github.com/OpenIMSDK/Open-IM-Server openim && export openim=$(pwd)/openim && cd $openim && make build
```
Read about the [OpenIM Version Policy](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/version.md)
`make help` to help you see the instructions supported by OpenIM.
@@ -105,7 +173,9 @@ All services have been successfully built as shown in the figure
![Successful Compilation](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/images/build.png)
### Component Configuration Instructions
</details>
<details> <summary>Component Configuration Instructions</summary>
The config/config.yaml file has detailed configuration instructions for the storage components.
@@ -113,7 +183,7 @@ The config/config.yaml file has detailed configuration instructions for the stor
- Used for RPC service discovery and registration, cluster support.
```
```bash
zookeeper:
schema: openim #Not recommended to modify
address: [ 127.0.0.1:2181 ] #address
@@ -125,7 +195,7 @@ The config/config.yaml file has detailed configuration instructions for the stor
- Used for storing users, relationships, and groups, supports master-slave database.
```
```bash
mysql:
address: [ 127.0.0.1:13306 ] #address
username: root #username
@@ -142,7 +212,7 @@ The config/config.yaml file has detailed configuration instructions for the stor
- Used for storing offline messages, supports mongo sharded clusters.
```
```bash
mongo:
uri: #Use this value directly if not empty
address: [ 127.0.0.1:37017 ] #address
@@ -156,7 +226,7 @@ The config/config.yaml file has detailed configuration instructions for the stor
- Used for storing message sequence numbers, latest messages, user tokens, and mysql cache, supports cluster deployment.
```
```bash
redis:
address: [ 127.0.0.1:16379 ] #address
username: #username
@@ -167,7 +237,7 @@ The config/config.yaml file has detailed configuration instructions for the stor
- Used for message queues, for message decoupling, supports cluster deployment.
```
```bash
kafka:
username: #username
password: #password
@@ -188,27 +258,31 @@ The config/config.yaml file has detailed configuration instructions for the stor
msgToModify: modify
```
### Start and Stop Services
</details>
<details> <summary>Start and Stop Services</summary>
Start services
```
./start_all.sh;
./scripts/start_all.sh;
```
Check services
```
./check_all.sh
./scripts/check_all.sh
```
Stop services
```
./stop_all.sh
./scripts/stop_all.sh
```
### Open IM Ports
</details>
<details> <summary>Open IM Ports</summary>
| TCP Port | Description | Operation |
| --------- | ------------------------------------------------------------ | ----------------------------------------------------- |
@@ -216,42 +290,75 @@ Stop services
| TCP:10002 | api port, such as user, friend, group, message interfaces. | Port release or nginx reverse proxy, and firewall off |
| TCP:10005 | Required when choosing minio storage (openIM uses minio storage by default) | Port release or nginx reverse proxy, and firewall off |
### Open Chat Ports
</details>
<details> <summary>Open Chat Ports</summary>
+ chat warehouse: https://github.com/OpenIMSDK/chat
| TCP Port | Description | Operation |
| --------- | --------------------------------------------------- | ----------------------------------------------------- |
| TCP:10008 | Business system, such as registration, login etc | Port release or nginx reverse proxy, and firewall off |
| TCP:10009 | Management backend, such as statistics, banning etc | Port release or nginx reverse proxy, and firewall off |
## Relationship Between APP and OpenIM
</details>
OpenIM is an open source instant messaging component, it is not an independent product. This image shows the relationship between AppServer, AppClient, Open-IM-Server and Open-IM-SDK.
## :link: Relationship Between APP and OpenIM
![https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/open-im-server.png](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/images/open-im-server.png)
OpenIM isn't just an open-source instant messaging component, it's an integral part of your application ecosystem. Check out this diagram to understand how AppServer, AppClient, Open-IM-Server, and Open-IM-SDK interact.
## Overall Architecture
![App-OpenIM Relationship](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/images/open-im-server.png)
![https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/Architecture.jpg](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/images/Architecture.jpg)
## :building_construction: Overall Architecture
## To start developing OpenIM
The [community repository](https://github.com/OpenIMSDK/community) hosts all information about building Kubernetes from source, how to contribute code and documentation, who to contact about what, etc.
Delve into the heart of Open-IM-Server's functionality with our architecture diagram.
![Overall Architecture](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/images/Architecture.jpg)
## Contributing
## :hammer_and_wrench: To start developing OpenIM
Contributions to this project are welcome! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for details.
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).
## Community Meetings
We want anyone to get involved in our community, we offer gifts and rewards, and we welcome you to join us every Thursday night.
If you'd like to contribute to this Open-IM-Server repository, please read our [contributor documentation](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/CONTRIBUTING.md).
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).
Before you start, please make sure your changes are in demand. The best for that is to create a [new discussion](https://github.com/OpenIMSDK/Open-IM-Server/discussions/new/choose) OR [Slack Communication](https://join.slack.com/t/openimsdk/shared_invite/zt-1tmoj26uf-_FDy3dowVHBiGvLk9e5Xkg), or if you find an issue, [report it](https://github.com/OpenIMSDK/Open-IM-Server/issues/new/choose) first.
- [Code Standards](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/go_code.md)
- [Docker Images Standards](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/images.md)
- [Directory Standards](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/directory.md)
- [Commit Standards](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/commit.md)
- [Versioning Standards](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/version.md)
- [Interface Standards](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/api.md)
- [Log Standards](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/log.md)
- [Error Code Standards](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/error_code.md)
## Who are using Open-IM-Server
The [user case studies](https://github.com/OpenIMSDK/community/blob/main/ADOPTERS.md) page includes the user list of the project. You can leave a [📝comment](https://github.com/OpenIMSDK/Open-IM-Server/issues/379) to let us know your use case.
## :busts_in_silhouette: Community
![avatar](https://openim-1253691595.cos.ap-nanjing.myqcloud.com/WechatIMG20.jpeg)
+ 📚 [OpenIM Community](https://github.com/OpenIMSDK/community)
+ 💕 [OpenIM Interest Group](https://github.com/Openim-sigs)
+ 🚀 [Join our Slack community](https://join.slack.com/t/openimsdk/shared_invite/zt-1tmoj26uf-_FDy3dowVHBiGvLk9e5Xkg)
+ :eyes: [Join our wechat (微信群)](https://openim-1253691595.cos.ap-nanjing.myqcloud.com/WechatIMG20.jpeg)
## License
## :calendar: Community Meetings
Open-IM-Server is under the Apache 2.0 license. See the [LICENSE](./LICENSE) file for details
We want anyone to get involved in our community and contributing code, we offer gifts and rewards, and we welcome you to join us every Thursday night.
Our conference is in the [OpenIM Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-1tmoj26uf-_FDy3dowVHBiGvLk9e5Xkg) 🎯, then you can search the Open-IM-Server pipeline to join
We take notes of each [biweekly meeting](https://github.com/orgs/OpenIMSDK/discussions/categories/meeting) in [GitHub discussions](https://github.com/OpenIMSDK/Open-IM-Server/discussions/categories/meeting), Our historical meeting notes, as well as replays of the meetings are available at [Google Docs :bookmark_tabs:](https://docs.google.com/document/d/1nx8MDpuG74NASx081JcCpxPgDITNTpIIos0DS6Vr9GU/edit?usp=sharing).
## :eyes: Who are using OpenIM
Check out our [user case studies](https://github.com/OpenIMSDK/community/blob/main/ADOPTERS.md) page for a list of the project users. Don't hesitate to leave a [📝comment](https://github.com/OpenIMSDK/Open-IM-Server/issues/379) and share your use case.
## :page_facing_up: License
OpenIM is licensed under the Apache 2.0 license. See [LICENSE](https://github.com/OpenIMSDK/Open-IM-Server/tree/main/LICENSE) for the full license text.
The OpenIM logo, including its variations and animated versions, displayed in this repository [OpenIM](https://github.com/OpenIMSDK/Open-IM-Server) under the [assets/logo](./assets/logo) and [assets/logo-gif](assets/logo-gif) directories, are protected by copyright laws.
## 🔮 Thanks to our contributors!
<a href="https://github.com/OpenIMSDK/Open-IM-Server/graphs/contributors">
<img src="https://contrib.rocks/image?repo=OpenIMSDK/Open-IM-Server" />
</a>
+14
View File
@@ -0,0 +1,14 @@
## :star2: Why OpenIM
**🔍 Function screenshot display**
<div align="center">
| multiple message | Efficient meetings |
| :---------------------------------------: | :---------------------------------------------: |
| ![multiple-message](./multiple-message.png) | ![efficient-meetings](./efficient-meetings.png) |
| **One-to-one and group chats** | **Special features - Custom messages** |
| ![group-chat](./group-chat.png) | ![special-function](./special-function.png) |
</div>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

+1 -1
View File
@@ -43,4 +43,4 @@ COPY --from=builder /openim/openim-server/config /openim/openim-server/config
EXPOSE ${10002}
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-api --port 10002 -c ${SERVER_WORKDIR}/config"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-api --port 10002 -c ${SERVER_WORKDIR}/config"]
+1 -1
View File
@@ -42,4 +42,4 @@ WORKDIR /openim/openim-server
COPY --from=builder ${SERVER_WORKDIR}/_output/bin/platforms /openim/openim-server/_output/bin/platforms
COPY --from=builder ${SERVER_WORKDIR}/config /openim/openim-server/config
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-cmdutils"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-cmdutils"]
+1 -1
View File
@@ -41,4 +41,4 @@ WORKDIR /openim/openim-server
COPY --from=builder /openim/openim-server/_output/bin/platforms /openim/openim-server/_output/bin/platforms
COPY --from=builder /openim/openim-server/config /openim/openim-server/config
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-crontask"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-crontask"]
+1 -1
View File
@@ -49,4 +49,4 @@ COPY --from=builder /openim/openim-server/config /openim/openim-server/config
EXPOSE 10160
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-auth --port 10160 -c ${SERVER_WORKDIR}/config"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-auth --port 10160 -c ${SERVER_WORKDIR}/config"]
@@ -56,4 +56,4 @@ COPY --from=builder /openim/openim-server/config /openim/openim-server/config
EXPOSE 10230
EXPOSE 20230
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-conversation --port 10230 --prometheus_port 20230 -c ${SERVER_WORKDIR}/config"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-conversation --port 10230 --prometheus_port 20230 -c ${SERVER_WORKDIR}/config"]
+1 -1
View File
@@ -56,4 +56,4 @@ COPY --from=builder /openim/openim-server/config /openim/openim-server/config
EXPOSE 10120
EXPOSE 20120
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-friend --port 10120 --prometheus_port 20120 -c ${SERVER_WORKDIR}/config"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-friend --port 10120 --prometheus_port 20120 -c ${SERVER_WORKDIR}/config"]
+1 -1
View File
@@ -56,4 +56,4 @@ COPY --from=builder /openim/openim-server/config /openim/openim-server/config
EXPOSE 10150
EXPOSE 20150
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-group --port 10150 --prometheus_port 20150 -c ${SERVER_WORKDIR}/config"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-group --port 10150 --prometheus_port 20150 -c ${SERVER_WORKDIR}/config"]
+1 -1
View File
@@ -56,4 +56,4 @@ COPY --from=builder /openim/openim-server/config /openim/openim-server/config
EXPOSE 10130
EXPOSE 20130
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-msg --port 10130 --prometheus_port 20130 -c ${SERVER_WORKDIR}/config"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-msg --port 10130 --prometheus_port 20130 -c ${SERVER_WORKDIR}/config"]
+1 -1
View File
@@ -55,4 +55,4 @@ COPY --from=builder /openim/openim-server/config /openim/openim-server/config
EXPOSE 10200
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-third --port 10200 -c ${SERVER_WORKDIR}/config"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-third --port 10200 -c ${SERVER_WORKDIR}/config"]
+1 -1
View File
@@ -55,4 +55,4 @@ COPY --from=builder /openim/openim-server/config /openim/openim-server/config
EXPOSE 10110
CMD ["sh","-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-user --port 10110 -c ${SERVER_WORKDIR}/config"]
CMD ["bash", "-c","${OPENIM_SERVER_BINDIR}/platforms/${OS}/${ARCH}/openim-rpc-user --port 10110 -c ${SERVER_WORKDIR}/config"]
+1 -1
View File
@@ -21,7 +21,7 @@ import (
func main() {
cronTaskCmd := cmd.NewCronTaskCmd()
if err := cronTaskCmd.Exec(tools.StartCronTask); err != nil {
if err := cronTaskCmd.Exec(tools.StartTask); err != nil {
panic(err.Error())
}
}
+43 -39
View File
@@ -24,10 +24,10 @@
# Zookeeper username
# Zookeeper password
zookeeper:
schema: openim
address: [ 127.0.0.1:2181 ]
username:
password:
schema: openim
address: [ 127.0.0.1:2181 ]
username:
password:
###################### Mysql ######################
# MySQL configuration
@@ -42,12 +42,12 @@ mysql:
address: [ 127.0.0.1:13306 ]
username: root
password: openIM123
database: openIM_v3
maxOpenConn: 1000
maxIdleConn: 100
maxLifeTime: 60
logLevel: 4
slowThreshold: 500
database: openIM_v3
maxOpenConn: 1000
maxIdleConn: 100
maxLifeTime: 60
logLevel: 4
slowThreshold: 500
###################### Mongo ######################
# MongoDB configuration
@@ -62,7 +62,7 @@ mongo:
database: openIM_v3
username: root
password: openIM123
maxPoolSize: 100
maxPoolSize: 100
###################### Redis ######################
# Redis configuration
@@ -70,7 +70,7 @@ mongo:
# Username is required only for Redis version 6.0+
redis:
address: [ 127.0.0.1:16379 ]
username:
username:
password: openIM123
###################### Kafka ######################
@@ -81,13 +81,13 @@ redis:
# It's not recommended to modify this topic name
# Consumer group ID, it's not recommended to modify
kafka:
username:
password:
username:
password:
addr: [ 127.0.0.1:9092 ]
latestMsgToRedis:
topic: "latestMsgToRedis"
topic: "latestMsgToRedis"
offlineMsgToMongo:
topic: "offlineMsgToMongoMysql"
topic: "offlineMsgToMongoMysql"
msgToPush:
topic: "msgToPush"
consumerGroupID:
@@ -111,8 +111,8 @@ rpc:
# API service port
# Default listen IP is 0.0.0.0
api:
openImApiPort: [ 10002 ]
listenIP: 0.0.0.0
openImApiPort: [ 10002 ]
listenIP: 0.0.0.0
###################### Gateway ######################
# Object storage configuration
@@ -124,25 +124,29 @@ api:
# Session token
# Configuration for Tencent COS
# Configuration for Aliyun OSS
# apiURL is the address of the api, the access address of the app, use s3 must be configured
# minio.endpoint can be configured as an intranet address,
# minio.signEndpoint is minio public network address
object:
enable: "minio"
apiURL: http://127.0.0.1:10002/object/
enable: "minio"
apiURL: "http://127.0.0.1:10002"
minio:
bucket: "openim"
endpoint: http://127.0.0.1:10005
accessKeyID: root
secretAccessKey: openIM123
sessionToken: ""
cos:
bucket: "openim"
endpoint: "http://127.0.0.1:10005"
accessKeyID: "root"
secretAccessKey: "openIM123"
sessionToken: ""
signEndpoint: "http://127.0.0.1:10005"
cos:
bucketURL: "https://temp-1252357374.cos.ap-chengdu.myqcloud.com"
secretID: ""
secretKey: ""
sessionToken: ""
oss:
oss:
endpoint: "https://oss-cn-chengdu.aliyuncs.com"
bucket: "demo-9999999"
bucketURL: "https://demo-9999999.oss-cn-chengdu.aliyuncs.com"
accessKeyID: root
accessKeyID: ""
accessKeySecret: ""
sessionToken: ""
@@ -150,7 +154,7 @@ object:
# These ports are passed into the program by the script and are not recommended to modify
# For launching multiple programs, just fill in multiple ports separated by commas
# For example, [10110, 10111]
rpcPort:
rpcPort:
openImUserPort: [ 10110 ]
openImFriendPort: [ 10120 ]
openImMessagePort: [ 10130 ]
@@ -183,12 +187,12 @@ rpcRegisterName:
# Whether to output in json format
# Whether to include stack trace in logs
log:
storageLocation: ../../../../../logs/
rotationTime: 24
remainRotationCount: 2
remainLogLevel: 6
isStdout: false
isJson: false
storageLocation: ../../../../../logs/
rotationTime: 24
remainRotationCount: 2
remainLogLevel: 6
isStdout: false
isJson: false
withStack: false
# Long connection server configuration
@@ -198,10 +202,10 @@ log:
# Maximum length of websocket request package
# Websocket connection handshake timeout
longConnSvr:
openImWsPort: [ 10001 ]
websocketMaxConnNum: 100000
websocketMaxMsgLen: 4096
websocketTimeout: 10
openImWsPort: [ 10001 ]
websocketMaxConnNum: 100000
websocketMaxMsgLen: 4096
websocketTimeout: 10
# Push notification service configuration
#
+12 -1
View File
@@ -2,6 +2,17 @@
OpenIM 支持很多种集群化部署方式,包括但不限于 helm, sealos, kubeam, kubesphere, kubeflow, kuboard, kubespray, k3s, k3d, k3c, k3sup, k3v, k3x
**目前还在开发这个模块,预计 v3.2.0 之前会有一个集群方案。**
目前各个贡献者,以及之前的官方有出过一些可以参考的方案:
- https://github.com/OpenIMSDK/k8s-jenkins
- https://github.com/OpenIMSDK/Open-IM-Server-k8s-deploy
- https://github.com/OpenIMSDK/openim-charts
- https://github.com/showurl/deploy-openim
### 依赖检查
```bash
@@ -23,4 +34,4 @@ $ cd ${OpenIM_ROOT}
### Helm安装
### Helm安装
+9 -9
View File
@@ -52,7 +52,6 @@ services:
net.core.somaxconn: 1024
command: redis-server --requirepass ${PASSWORD} --appendonly yes
zookeeper:
image: wurstmeister/zookeeper
ports:
@@ -63,7 +62,7 @@ services:
environment:
TZ: Asia/Shanghai
restart: always
network_mode: "host"
kafka:
image: wurstmeister/kafka
@@ -74,7 +73,7 @@ services:
environment:
TZ: Asia/Shanghai
KAFKA_BROKER_ID: 0
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ZOOKEEPER_CONNECT: 127.0.0.1:2181
KAFKA_CREATE_TOPICS: "latestMsgToRedis:8:1,msgToPush:8:1,offlineMsgToMongoMysql:8:1"
KAFKA_ADVERTISED_LISTENERS: INSIDE://127.0.0.1:9092,OUTSIDE://103.116.45.174:9092
KAFKA_LISTENERS: INSIDE://:9092,OUTSIDE://:9093
@@ -82,6 +81,7 @@ services:
KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
depends_on:
- zookeeper
network_mode: "host"
minio:
image: minio/minio
@@ -98,9 +98,9 @@ services:
restart: always
command: minio server /data --console-address ':9090'
openim_server:
image: ghcr.io/openim-sigs/openim-server:v1.0.0-debug.11 #ghcr.io/openimsdk/openim-server:main
openim-server:
image: ghcr.io/openimsdk/openim-server:latest
#build: .
container_name: openim-server
volumes:
- ./logs:/openim/openim-server/logs
@@ -122,7 +122,7 @@ services:
max-file: "2"
openim-chat:
image: ghcr.io/openim-sigs/openim-chat:v1.0.0-debug.11 # ghcr.io/openimsdk/openim-chat:main
image: ghcr.io/openimsdk/openim-chat:latest
container_name: openim-chat
volumes:
- ./_output/openim/openim-chat/logs:/openim/openim-chat/logs
@@ -134,7 +134,7 @@ services:
- mongodb
- redis
- minio
- openim_server
- openim-server
network_mode: "host"
logging:
driver: json-file
@@ -150,7 +150,7 @@ services:
# ports:
# - 9091:9091
depends_on:
- openim_server
- openim-server
command: --web.listen-address=:9091 --config.file="/etc/prometheus/prometheus.yml"
network_mode: "host"
+1 -4
View File
@@ -1,8 +1,5 @@
docs/.generated_docs
docs/guide/en-US/cmd/iam-apiserver.md
docs/guide/en-US/cmd/iam-authz-server.md
docs/guide/en-US/cmd/iam-pump.md
docs/guide/en-US/cmd/iam-watcher.md
docs/guide/en-US/cmd/openim/openim.md
docs/guide/en-US/cmd/openim/openim_color.md
docs/guide/en-US/cmd/openim/openim_completion.md
File diff suppressed because it is too large Load Diff
+54 -43
View File
@@ -1,76 +1,88 @@
# OpenIM Branch Management and Versioning
# OpenIM Branch Management and Versioning: A Blueprint for High-Grade Software Development
Our project, OpenIM, follows the [Semantic Versioning 2.0.0](https://semver.org/lang/zh-CN/) standards.
[📚 **OpenIM TOC**](#openim-branch-management-and-versioning-a-blueprint-for-high-grade-software-development)
- [Unfolding the Mechanism of OpenIM Version Maintenance](#unfolding-the-mechanism-of-openim-version-maintenance)
- [Main Branch: The Heart of OpenIM Development](#main-branch-the-heart-of-openim-development)
- [Release Branch: The Beacon of Stability](#release-branch-the-beacon-of-stability)
- [Tag Management: The Cornerstone of Version Control](#tag-management-the-cornerstone-of-version-control)
- [Release Management: A Guided Tour](#release-management-a-guided-tour)
- [Milestones, Branching, and Addressing Major Bugs](#milestones-branching-and-addressing-major-bugs)
- [Applying Principles: A Git Workflow Example](#applying-principles-a-git-workflow-example)
- [Docker Images Version Management](#docker-images-version-management)
OpenIM, the open source project, employs a comprehensive version management system to ensure the reliability and traceability of our software. Our version management consists of three main components: the `main` branch, the `release` branch, and `tag` management.
## Main Branch
At OpenIM, we acknowledge the profound impact of implementing a robust and efficient version management system, hence we abide by the established standards of [Semantic Versioning 2.0.0](https://semver.org/lang/zh-CN/).
The `main` branch is where all the latest code resides. It's the hub of activity, embodying all the cutting-edge features that are currently being developed or updated. However, since it's subject to frequent changes and updates, it may not always represent the most stable version of the software. Access the `main` branch [here](https://github.com/OpenIMSDK/Open-IM-Server/tree/main).
Our software blueprint orchestrates a tripartite version management system that integrates the `main` branch, the `release` branch, and `tag` management. These constituents operate in synchrony to preserve the reliability and traceability of our software across various stages of development.
## Release Branch
## Unfolding the Mechanism of OpenIM Version Maintenance
On the other hand, we have the `release` branch. For instance, in the context of version 3.1, we maintain a `release-v3.1` branch. Unlike the `main` branch, the release branch is designed to be a continuously stable and updated version of the software. This provides a reliable option for users who prefer stability over the latest, but potentially unstable, features. Access the `release-v3.1` branch [here](https://github.com/OpenIMSDK/Open-IM-Server/tree/release-v3.1).
Our version maintenance protocol revolves around two primary branches, namely: `main` and `release`. We resort to Semantic Versioning 2.0.0 for marking distinctive versions of our software, representing substantial milestones in its evolution.
## Tag Management
In the OpenIM repository, version identification strictly complies with the `MAJOR.MINOR.PATCH` protocol. Herein:
In addition to the `main` and `release` branches, `tag` also plays a pivotal role in version control. Tags are immutable, meaning once they're created, they remain unchanged. Therefore, if you need a specific version of the software, you can use the corresponding tag. All of our available tags can be viewed [here](https://github.com/OpenIMSDK/Open-IM-Server/tags).
- The `MAJOR` version indicates a shift arising from incompatible changes to the API.
- The `MINOR` version suggests the addition of features in a backward-compatible manner.
- The `PATCH` version flags backward-compatible bug fixes.
Moreover, our Docker image versions are closely tied with these three components. For example, a tag might correspond to the Docker image `ghcr.io/openimsdk/openim-server:v3.1.0`, a release might be represented as `ghcr.io/openimsdk/openim-server:release-v3.0`, and the main branch could be represented as `ghcr.io/openimsdk/openim-server:main` or `ghcr.io/openimsdk/openim-server:latest`.
## Main Branch: The Heart of OpenIM Development
Here is the specification of our version numbers:
The `main` branch is the operational heart of our development process. Housing the most recent and advanced features, this branch serves as the nerve center for all enhancements and updates. It encapsulates the freshest, though possibly unstable, facets of the software. Visit our `main` branch [here](https://github.com/OpenIMSDK/Open-IM-Server/tree/main).
- **Revision version number**: The third digit of the version number, representing bug fixes or code optimizations, usually no new features are added and it is backward compatible with older versions.
## Release Branch: The Beacon of Stability
- **Build version number**: Usually automatically generated by the system, every code submission will result in an automatic increment by 1.
For every major release, we curate a corresponding `release` branch, e.g., `release-v3.1`. This branch symbolizes an embodiment of stability and ensures an updated version of the software, providing a dependable option for users favoring stability over nascent, yet possibly unstable, features. Visit the `release-v3.1` branch [here](https://github.com/OpenIMSDK/Open-IM-Server/tree/release-v3.1).
- Version modifiers
## Tag Management: The Cornerstone of Version Control
: These can represent the development stage and stability of the software. Common ones include:
In OpenIM's version control system, the role of `tags` stands paramount. Owing to their immutable nature, tags can be effectively utilized to retrieve a specific version of the software. Explore our library of tags [here](https://github.com/OpenIMSDK/Open-IM-Server/tags).
- `alpha`: An internal testing version with many bugs, generally used for communication among developers.
- `beta`: A test version with many bugs, generally used for testing by eager community members, who provide feedback to the developers.
- `rc`: Release candidate, to be released as the official version, it's the last test version before the official version.
Our Docker image versions are intimately entwined with these tripartite components. For instance, a Docker image tag may correspond to `ghcr.io/openimsdk/openim-server:v3.1.0`, a release to `ghcr.io/openimsdk/openim-server:release-v3.0`, and the main branch to `ghcr.io/openimsdk/openim-server:main` or `ghcr.io/openimsdk/openim-server:latest`.
To further clarify, the semantics of our version numbers are as follows:
- **Revision version number**: This represents bug fixes or code optimizations. Typically, it entails no new feature additions and ensures backward compatibility.
- **Build version number**: Auto-generated by the system, each code submission prompts an automatic increment by 1.
- **Version modifiers**: These hint at the software's development stage and stability. Some commonly used modifiers are `alpha`, `beta`, `rc`, `ga`, `r/release/or nothing`, and `lts`.
- `alpha`: An internal testing version with numerous bugs, typically used for communication among developers.
- `beta`: A test version with numerous bugs, generally used for testing by eager community members, who provide feedback to the developers.
- `rc`: Release candidate, which is to be released as the official version. It's the last test version before the official version.
- `ga`: General Availability, the first stable release.
- `r/release/or nothing`: The final release version, intended for general users.
- `lts`: Long Term Support, the official will specify the maintenance year for this version and will fix all bugs found in this version.
- `lts`: Long Term Support, the official will specify the maintenance year for this version and will fix all bugs discovered in this version.
When adding partial functions to the project, the minor version number increases by 1, and the revision version number resets to 0. When there are major changes in the project, the major version number increases by 1. The build number is generally automatically generated by the compiler during the compilation process, only the format needs to be defined, and it does not need to be manually controlled.
Whenever a project undergoes a partial functional addition, the minor version number increments by 1, resetting the revision version number to 0. In contrast, any major project overhaul results in an increment by 1 in the major version number. The build number, typically auto-generated during the compilation process, only requires format definition, thereby eliminating manual control.
## OpenIM version
## Release Management: A Guided Tour
OpenIM manages two primary branches: `main` and `release`. The project uses Semantic Versioning 2.0.0 to tag different versions of the software, each indicating a significant milestone in the software's development.
Our GitHub repository at https://github.com/OpenIMSDK/Open-IM-Server/releases associates a release with each tag, with a distinction between Pre-release and Latest, determined by the branch source. Every significant feature launch prompts the issue of a `release` branch, such as `release-v3.2`, as a beacon of stability and Latest release.
In the OpenIM repository, the versioning adheres to the `MAJOR.MINOR.PATCH` format, where:
Pre-releases correspond to releases from the `main` branch, denoting tags with Version modifiers such as `v3.2.1-beta.0`, `v3.2.1-rc.1`, etc. If you are seeking the most recent, albeit possibly unstable, release with new features, these tags, originating from the latest `main` branch code, are your go-to.
- `MAJOR` version changes when there are incompatible changes to the API,
- `MINOR` version changes when features are added in a backward-compatible manner, and
- `PATCH` version changes when backward-compatible bugs are fixed.
Conversely, if stability is your primary concern, you should opt for the release tagged Latest, denoted by tags without Version modifiers, such as `v3.2.1`, `v3.2.2` etc. These tags are linked to the latest stable maintenance branch, like `release-v3.2`.
## Milestones and Branching
## Milestones, Branching, and Addressing Major Bugs
**About:**
+ [OpenIM Milestones](https://github.com/OpenIMSDK/Open-IM-Server/milestones)
+ [OpenIM Tags](https://github.com/OpenIMSDK/Open-IM-Server/tags)
+ [OpenIM Branches](https://github.com/OpenIMSDK/Open-IM-Server/branches)
When a significant milestone like v3.1.0 is achieved, a new branch `release-v3.1` is created. This branch contains all the code pertaining to this stable release. All bug fixes and features intended for the next version, v3.2.0, are merged into this branch.
We create a new branch, such as `release-v3.1`, for each significant milestone (e.g., v3.1.0), housing all relevant code for that release. All enhancements and bug fixes targeting the subsequent version (e.g., v3.2.0) are integrated into this branch.
The release of `PATCH` versions (Z in `X.Y.Z`) are driven by bug fixes, and these can be rolled out depending on the bug's priority or over a scheduled time. On the other hand, `MINOR` versions (Y in `X.Y.Z`) are released based on the project's roadmap, milestone completion, or on a scheduled timeline. Importantly, the API of minor versions is always backward-compatible.
`PATCH` versions (represented by Z in `X.Y.Z`) are primarily propelled by bug fixes, and their release may be either priority-driven or scheduled. In contrast, `MINOR` versions (represented by Y in `X.Y.Z`) are contingent upon the project's roadmap, milestone completion, or a pre-established timeline, always maintaining backward-compatible APIs.
## Dealing with Major Bugs
When dealing with major bugs, we selectively merge the fix into the affected version (e.g., v3.1 or the `release-v3.1` branch), as well as the `main` branch. This dual pronged strategy ensures that users on older versions receive crucial bug fixes, while also keeping the `main` branch updated.
In the event of a major bug discovery, the fix would selectively be merged into the previous version (e.g., v3.1 or the `release-v3.1` branch), as well as into the `main` branch. This is to ensure that users relying on the older version can still receive important bug fixes, while also keeping the main branch updated.
We reinforce our approach to branch management and versioning with stringent testing protocols. Automated tests and code review sessions form vital components of maintaining a robust and reliable codebase.
It's worth noting that a robust testing regime should be in place to ensure the integrity of all branches at any given time. Automated tests and code review sessions are crucial components of maintaining a healthy codebase.
## Applying Principles: A Git Workflow Example
To summarize, OpenIM's approach to branch management and versioning ensures a balance between introducing new features, fixing bugs, and maintaining backward compatibility. This strategy is vital for managing user expectations, supporting older versions, and paving the way for the project's continuous growth.
The workflow to address a bug fix might follow these steps:
## Git Workflow Example
To put the above principles into practice, here's a Git workflow example that you might follow when working on a bug fix:
```
bashCopy code# Checkout the branch for the version that needs the bug fix
```bash
bashCopy codebashCopy code# Checkout the branch for the version that needs the bug fix
git checkout release-v3.1
# Create a new branch for the bug fix
@@ -93,9 +105,8 @@ git merge release-v3.1
git push origin main
```
Remember, communication with your team is key throughout this process, keeping everyone up-to-date with the changes being made.
Throughout this process, active communication within the team is pivotal to maintaining transparency and consensus on changes.
## Docker Images Version Management
## Docker images version management
+ [OpenIM Docker Images Administration](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/images.md)
For more details on managing Docker image versions, visit [OpenIM Docker Images Administration](https://github.com/OpenIMSDK/Open-IM-Server/blob/main/docs/conversions/images.md).
+16 -16
View File
@@ -8,7 +8,7 @@ require (
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
github.com/go-playground/validator/v10 v10.14.1
github.com/go-playground/validator/v10 v10.15.0
github.com/gogo/protobuf v1.3.2
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang/protobuf v1.5.3
@@ -25,19 +25,19 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/stretchr/testify v1.8.4
go.mongodb.org/mongo-driver v1.12.1
golang.org/x/image v0.9.0 // indirect
google.golang.org/api v0.134.0
golang.org/x/image v0.11.0
google.golang.org/api v0.136.0
google.golang.org/grpc v1.57.0
google.golang.org/protobuf v1.31.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/mysql v1.5.1
gorm.io/gorm v1.25.2
gorm.io/gorm v1.25.3
)
require github.com/google/uuid v1.3.0
require (
github.com/OpenIMSDK/protocol v0.0.4
github.com/OpenIMSDK/protocol v0.0.6
github.com/OpenIMSDK/tools v0.0.13
github.com/aliyun/aliyun-oss-go-sdk v2.2.8+incompatible
github.com/go-redis/redis v6.15.9+incompatible
@@ -47,11 +47,11 @@ require (
)
require (
cloud.google.com/go v0.110.4 // indirect
cloud.google.com/go/compute v1.20.1 // indirect
cloud.google.com/go v0.110.6 // indirect
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/firestore v1.11.0 // indirect
cloud.google.com/go/iam v1.1.0 // indirect
cloud.google.com/go/iam v1.1.1 // indirect
cloud.google.com/go/longrunning v0.5.1 // indirect
cloud.google.com/go/storage v1.30.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
@@ -117,16 +117,17 @@ require (
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.11.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771 // indirect
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect
)
require (
@@ -137,7 +138,6 @@ require (
github.com/spf13/cobra v1.7.0
github.com/ugorji/go/codec v1.2.11 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
golang.org/x/crypto v0.12.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
+32 -32
View File
@@ -1,15 +1,15 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk=
cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go v0.110.6 h1:8uYAkj3YHTP/1iwReuHPxLSbdcyc+dSBbzFMrVwDR6Q=
cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/firestore v1.11.0 h1:PPgtwcYUOXV2jFe1bV3nda3RCrOa8cvBjTOn2MQVfW8=
cloud.google.com/go/firestore v1.11.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4=
cloud.google.com/go/iam v1.1.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94=
cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk=
cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y=
cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI=
cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
@@ -17,8 +17,8 @@ cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7Biccwk
firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4=
firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OpenIMSDK/protocol v0.0.4 h1:zEEAi677nog+k4u3e5h36nvYeb1XAwcKQ3Uc2tzxHYs=
github.com/OpenIMSDK/protocol v0.0.4/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/protocol v0.0.6 h1:KjaItOEww7vjrhwyxHnVzhw80pnjcNukpskadqW6gnA=
github.com/OpenIMSDK/protocol v0.0.6/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.13 h1:rcw4HS8S2DPZR9UOBxD8/ol9UBMzXBypzOVEytDRIMo=
github.com/OpenIMSDK/tools v0.0.13/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
@@ -100,8 +100,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k=
github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-playground/validator/v10 v10.15.0 h1:nDU5XeOKtB3GEa+uB7GNYwhVKsgjAR7VgKoNB6ryXfw=
github.com/go-playground/validator/v10 v10.15.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
@@ -361,11 +361,11 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.9.0 h1:QrzfX26snvCM20hIhBwuHI/ThTg18b/+kcKdXHvnR+g=
golang.org/x/image v0.9.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0=
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@@ -394,12 +394,12 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -430,8 +430,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -442,8 +442,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -463,8 +463,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.134.0 h1:ktL4Goua+UBgoP1eL1/60LwZJqa1sIzkLmvoR3hR6Gw=
google.golang.org/api v0.134.0/go.mod h1:sjRL3UnjTx5UqNQS9EWr9N8p7xbHpy1k0XGRLCf3Spk=
google.golang.org/api v0.136.0 h1:e/6enzUE1s4tGPa6Q3ZYShKTtvRc+1Jq0rrafhppmOs=
google.golang.org/api v0.136.0/go.mod h1:XtJfF+V2zgUxelOn5Zs3kECtluMxneJG8ZxUTlLNTPA=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
@@ -473,12 +473,12 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8=
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y=
google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU=
google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771 h1:Z8qdAF9GFsmcUuWQ5KVYIpP3PCKydn/YKORnghIalu4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g=
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:nIgk/EEq3/YlnmVVXVnm14rC2oxgs1o0ong4sD/rd44=
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -523,8 +523,8 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.3 h1:zi4rHZj1anhZS2EuEODMhDisGy+Daq9jtPrNGgbQYD8=
gorm.io/gorm v1.25.3/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+8
View File
@@ -0,0 +1,8 @@
go 1.20
use (
.
./tools/component
./tools/infra
./tools/ncpu
)
+6
View File
@@ -0,0 +1,6 @@
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
+8 -1
View File
@@ -83,7 +83,14 @@ func (o *ThirdApi) ObjectRedirect(c *gin.Context) {
operationID = strconv.Itoa(rand.Int())
}
ctx := mcontext.SetOperationID(c, operationID)
resp, err := o.Client.AccessURL(ctx, &third.AccessURLReq{Name: name})
query := make(map[string]string)
for key, values := range c.Request.URL.Query() {
if len(values) == 0 {
continue
}
query[key] = values[0]
}
resp, err := o.Client.AccessURL(ctx, &third.AccessURLReq{Name: name, Query: query})
if err != nil {
if errs.ErrArgs.Is(err) {
c.String(http.StatusBadRequest, err.Error())
+14 -2
View File
@@ -40,7 +40,13 @@ type Req struct {
}
func (r *Req) String() string {
return utils.StructToJsonString(r)
var tReq Req
tReq.ReqIdentifier = r.ReqIdentifier
tReq.Token = r.Token
tReq.SendID = r.SendID
tReq.OperationID = r.OperationID
tReq.MsgIncr = r.MsgIncr
return utils.StructToJsonString(tReq)
}
type Resp struct {
@@ -53,7 +59,13 @@ type Resp struct {
}
func (r *Resp) String() string {
return utils.StructToJsonString(r)
var tResp Resp
tResp.ReqIdentifier = r.ReqIdentifier
tResp.MsgIncr = r.MsgIncr
tResp.OperationID = r.OperationID
tResp.ErrCode = r.ErrCode
tResp.ErrMsg = r.ErrMsg
return utils.StructToJsonString(tResp)
}
type MessageHandler interface {
@@ -145,7 +145,7 @@ func (och *OnlineHistoryRedisConsumerHandler) Run(channelID int) {
len(modifyMsgList),
)
conversationIDMsg := msgprocessor.GetChatConversationIDByMsg(ctxMsgList[0].message)
conversationIDNotification := msgprocessor.GetNotificationConversationID(ctxMsgList[0].message)
conversationIDNotification := msgprocessor.GetNotificationConversationIDByMsg(ctxMsgList[0].message)
och.handleMsg(ctx, msgChannelValue.uniqueKey, conversationIDMsg, storageMsgList, notStorageMsgList)
och.handleNotification(
ctx,
+11 -6
View File
@@ -161,6 +161,9 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbGroup.CreateGroupR
if req.OwnerUserID == "" {
return nil, errs.ErrArgs.Wrap("no group owner")
}
if req.GroupInfo.GroupType != constant.WorkingGroup {
return nil, errs.ErrArgs.Wrap(fmt.Sprintf("group type %d not support", req.GroupInfo.GroupType))
}
if err := authverify.CheckAccessV3(ctx, req.OwnerUserID); err != nil {
return nil, err
}
@@ -690,8 +693,7 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbGroup
return nil, errs.ErrGroupRequestHandled.Wrap("group request already processed")
}
var inGroup bool
_, err = s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.FromUserID)
if err == nil {
if _, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.FromUserID); err == nil {
inGroup = true // 已经在群里了
} else if !s.IsNotFound(err) {
return nil, err
@@ -718,6 +720,7 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbGroup
return nil, err
}
}
log.ZDebug(ctx, "GroupApplicationResponse", "inGroup", inGroup, "HandleResult", req.HandleResult, "member", member)
if err := s.GroupDatabase.HandlerGroupRequest(ctx, req.GroupID, req.FromUserID, req.HandledMsg, req.HandleResult, member); err != nil {
return nil, err
}
@@ -727,12 +730,14 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbGroup
return nil, err
}
s.Notification.GroupApplicationAcceptedNotification(ctx, req)
if member == nil {
log.ZDebug(ctx, "GroupApplicationResponse", "member is nil")
} else {
s.Notification.MemberEnterNotification(ctx, req.GroupID, req.FromUserID)
}
case constant.GroupResponseRefuse:
s.Notification.GroupApplicationRejectedNotification(ctx, req)
}
if member != nil {
s.Notification.MemberEnterNotification(ctx, req)
}
return &pbGroup.GroupApplicationResponseResp{}, nil
}
@@ -778,7 +783,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbGroup.JoinGroupReq)
if err := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, []string{req.InviterUserID}); err != nil {
return nil, err
}
s.Notification.MemberEnterDirectlyNotification(ctx, req.GroupID, req.InviterUserID)
s.Notification.MemberEnterNotification(ctx, req.GroupID, req.InviterUserID)
return resp, nil
}
groupRequest := relationTb.GroupRequestModel{
+55 -21
View File
@@ -116,41 +116,75 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
if total, chatLogs, err = m.MsgDatabase.SearchMessage(ctx, req); err != nil {
return nil, err
}
var (
sendIDs []string
recvIDs []string
groupIDs []string
sendMap = make(map[string]string)
recvMap = make(map[string]string)
groupMap = make(map[string]*sdkws.GroupInfo)
)
for _, chatLog := range chatLogs {
if chatLog.SenderNickname == "" {
sendIDs = append(sendIDs, chatLog.SendID)
}
switch chatLog.SessionType {
case constant.SingleChatType:
recvIDs = append(recvIDs, chatLog.RecvID)
case constant.GroupChatType, constant.SuperGroupChatType:
groupIDs = append(groupIDs, chatLog.GroupID)
}
}
if len(sendIDs) != 0 {
sendInfos, err := m.User.GetUsersInfo(ctx, sendIDs)
if err != nil {
return nil, err
}
for _, sendInfo := range sendInfos {
sendMap[sendInfo.UserID] = sendInfo.Nickname
}
}
if len(recvIDs) != 0 {
recvInfos, err := m.User.GetUsersInfo(ctx, recvIDs)
if err != nil {
return nil, err
}
for _, recvInfo := range recvInfos {
recvMap[recvInfo.UserID] = recvInfo.Nickname
}
}
if len(groupIDs) != 0 {
groupInfos, err := m.Group.GetGroupInfos(ctx, groupIDs, true)
if err != nil {
return nil, err
}
for _, groupInfo := range groupInfos {
groupMap[groupInfo.GroupID] = groupInfo
}
}
for _, chatLog := range chatLogs {
pbChatLog := &msg.ChatLog{}
utils.CopyStructFields(pbChatLog, chatLog)
pbChatLog.SendTime = chatLog.SendTime
pbChatLog.CreateTime = chatLog.CreateTime
if chatLog.SenderNickname == "" {
sendUser, err := m.User.GetUserInfo(ctx, chatLog.SendID)
if err != nil {
return nil, err
}
pbChatLog.SenderNickname = sendUser.Nickname
pbChatLog.SenderNickname = sendMap[chatLog.SendID]
}
switch chatLog.SessionType {
case constant.SingleChatType:
recvUser, err := m.User.GetUserInfo(ctx, chatLog.RecvID)
if err != nil {
return nil, err
}
pbChatLog.RecvNickname = recvUser.Nickname
pbChatLog.RecvNickname = recvMap[chatLog.RecvID]
case constant.GroupChatType, constant.SuperGroupChatType:
group, err := m.Group.GetGroupInfo(ctx, chatLog.GroupID)
if err != nil {
return nil, err
}
pbChatLog.SenderFaceURL = group.FaceURL
pbChatLog.GroupMemberCount = group.MemberCount
pbChatLog.RecvID = group.GroupID
pbChatLog.GroupName = group.GroupName
pbChatLog.GroupOwner = group.OwnerUserID
pbChatLog.GroupType = group.GroupType
pbChatLog.SenderFaceURL = groupMap[chatLog.GroupID].FaceURL
pbChatLog.GroupMemberCount = groupMap[chatLog.GroupID].MemberCount
pbChatLog.RecvID = groupMap[chatLog.GroupID].GroupID
pbChatLog.GroupName = groupMap[chatLog.GroupID].GroupName
pbChatLog.GroupOwner = groupMap[chatLog.GroupID].OwnerUserID
pbChatLog.GroupType = groupMap[chatLog.GroupID].GroupType
}
resp.ChatLogs = append(resp.ChatLogs, pbChatLog)
}
resp.ChatLogsNum = total
return resp, nil
}
+18 -1
View File
@@ -16,8 +16,11 @@ package third
import (
"context"
"strconv"
"time"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/s3"
"github.com/OpenIMSDK/protocol/third"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
@@ -152,7 +155,21 @@ func (t *thirdServer) CompleteMultipartUpload(ctx context.Context, req *third.Co
}
func (t *thirdServer) AccessURL(ctx context.Context, req *third.AccessURLReq) (*third.AccessURLResp, error) {
expireTime, rawURL, err := t.s3dataBase.AccessURL(ctx, req.Name, t.defaultExpire)
opt := &s3.AccessURLOption{}
if len(req.Query) > 0 {
switch req.Query["type"] {
case "":
case "image":
opt.Image = &s3.Image{}
opt.Image.Format = req.Query["format"]
opt.Image.Width, _ = strconv.Atoi(req.Query["width"])
opt.Image.Height, _ = strconv.Atoi(req.Query["height"])
log.ZDebug(ctx, "AccessURL image", "name", req.Name, "option", opt.Image)
default:
return nil, errs.ErrArgs.Wrap("invalid query type")
}
}
expireTime, rawURL, err := t.s3dataBase.AccessURL(ctx, req.Name, t.defaultExpire, opt)
if err != nil {
return nil, err
}
+1
View File
@@ -49,6 +49,7 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
if apiURL[len(apiURL)-1] != '/' {
apiURL += "/"
}
apiURL += "object/"
rdb, err := cache.NewRedis()
if err != nil {
return err
+6 -7
View File
@@ -20,17 +20,16 @@ import (
"strings"
"time"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/Open-IM-Server/pkg/authverify"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/unrelation"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/sdkws"
pbuser "github.com/OpenIMSDK/protocol/user"
registry "github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/config"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/convert"
@@ -41,9 +40,9 @@ import (
"github.com/OpenIMSDK/Open-IM-Server/pkg/rpcclient"
"github.com/OpenIMSDK/Open-IM-Server/pkg/rpcclient/notification"
"google.golang.org/grpc"
pbuser "github.com/OpenIMSDK/protocol/user"
"github.com/OpenIMSDK/tools/utils"
"google.golang.org/grpc"
)
type userServer struct {
+2 -1
View File
@@ -26,12 +26,13 @@ import (
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/config"
)
func StartCronTask() error {
func StartTask() error {
fmt.Println("cron task start, config", config.Config.ChatRecordsClearTime)
msgTool, err := InitMsgTool()
if err != nil {
return err
}
msgTool.ConvertTools()
c := cron.New()
var wg sync.WaitGroup
wg.Add(1)
+33
View File
@@ -0,0 +1,33 @@
package tools
import (
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/Open-IM-Server/pkg/msgprocessor"
)
func (c *MsgTool) ConvertTools() {
ctx := mcontext.NewCtx("convert")
conversationIDs, err := c.conversationDatabase.GetAllConversationIDs(ctx)
if err != nil {
log.ZError(ctx, "get all conversation ids failed", err)
return
}
for _, conversationID := range conversationIDs {
conversationIDs = append(conversationIDs, msgprocessor.GetNotificationConversationIDByConversationID(conversationID))
}
userIDs, err := c.userDatabase.GetAllUserID(ctx, 0, 0)
if err != nil {
log.ZError(ctx, "get all user ids failed", err)
return
}
log.ZDebug(ctx, "all userIDs", "len userIDs", len(userIDs))
for _, userID := range userIDs {
conversationIDs = append(conversationIDs, msgprocessor.GetConversationIDBySessionType(constant.SingleChatType, userID, userID))
conversationIDs = append(conversationIDs, msgprocessor.GetNotificationConversationID(constant.SingleChatType, userID, userID))
}
log.ZDebug(ctx, "all conversationIDs", "len userIDs", len(conversationIDs))
c.msgDatabase.ConvertMsgsDocLen(ctx, conversationIDs)
}
+1
View File
@@ -120,6 +120,7 @@ type configStruct struct {
AccessKeyID string `yaml:"accessKeyID"`
SecretAccessKey string `yaml:"secretAccessKey"`
SessionToken string `yaml:"sessionToken"`
SignEndpoint string `yaml:"signEndpoint"`
} `yaml:"minio"`
Cos struct {
BucketURL string `yaml:"bucketURL"`
+1
View File
@@ -209,6 +209,7 @@ func (f *friendDatabase) RefuseFriendRequest(
if fr.HandleResult != 0 {
return errs.ErrArgs.Wrap("the friend request has been processed")
}
log.ZDebug(ctx, "refuse friend request", "friendRequest db", fr, "friendRequest arg", friendRequest)
friendRequest.HandleResult = constant.FriendResponseRefuse
friendRequest.HandleTime = time.Now()
err = f.friendRequest.Update(ctx, friendRequest)
+22 -7
View File
@@ -386,8 +386,24 @@ func (g *groupDatabase) HandlerGroupRequest(
handleResult int32,
member *relationTb.GroupMemberModel,
) error {
cache := g.cache.NewCache()
if err := g.tx.Transaction(func(tx any) error {
//cache := g.cache.NewCache()
//if err := g.tx.Transaction(func(tx any) error {
// if err := g.groupRequestDB.NewTx(tx).UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
// return err
// }
// if member != nil {
// if err := g.groupMemberDB.NewTx(tx).Create(ctx, []*relationTb.GroupMemberModel{member}); err != nil {
// return err
// }
// cache = cache.DelGroupMembersHash(groupID).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelJoinedGroupID(member.UserID)
// }
// return nil
//}); err != nil {
// return err
//}
//return cache.ExecDel(ctx)
return g.tx.Transaction(func(tx any) error {
if err := g.groupRequestDB.NewTx(tx).UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
return err
}
@@ -395,13 +411,12 @@ func (g *groupDatabase) HandlerGroupRequest(
if err := g.groupMemberDB.NewTx(tx).Create(ctx, []*relationTb.GroupMemberModel{member}); err != nil {
return err
}
cache = cache.DelGroupMembersHash(groupID).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelJoinedGroupID(member.UserID)
if err := g.cache.NewCache().DelGroupMembersHash(groupID).DelGroupMembersInfo(groupID, member.UserID).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelJoinedGroupID(member.UserID).ExecDel(ctx); err != nil {
return err
}
}
return nil
}); err != nil {
return err
}
return cache.ExecDel(ctx)
})
}
func (g *groupDatabase) DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error {
+14 -19
View File
@@ -118,6 +118,7 @@ type CommonMsgDatabase interface {
pageNumber int32,
showNumber int32,
) (msgCount int64, userCount int64, groups []*unRelationTb.GroupCount, dateCount map[string]int64, err error)
ConvertMsgsDocLen(ctx context.Context, conversationIDs []string)
}
func NewCommonMsgDatabase(msgDocModel unRelationTb.MsgDocModelInterface, cacheModel cache.MsgModel) CommonMsgDatabase {
@@ -730,34 +731,21 @@ func (db *commonMsgDatabase) deleteMsgRecursion(ctx context.Context, conversatio
delStruct.delDocIDs = append(delStruct.delDocIDs, msgDocModel.DocID)
delStruct.minSeq = msgDocModel.Msg[len(msgDocModel.Msg)-1].Msg.Seq
} else {
var hasMarkDelFlag bool
var delMsgIndexs []int
for i, MsgInfoModel := range msgDocModel.Msg {
if MsgInfoModel != nil && MsgInfoModel.Msg != nil {
if utils.GetCurrentTimestampByMill() > MsgInfoModel.Msg.SendTime+(remainTime*1000) {
delMsgIndexs = append(delMsgIndexs, i)
hasMarkDelFlag = true
} else {
// 到本条消息不需要删除, minSeq置为这条消息的seq
if len(delStruct.delDocIDs) > 0 {
log.ZDebug(ctx, "delete docs", "delDocIDs", delStruct.delDocIDs)
}
if err := db.msgDocDatabase.DeleteDocs(ctx, delStruct.delDocIDs); err != nil {
return 0, err
}
if hasMarkDelFlag {
log.ZDebug(ctx, "delete msg by index", "delMsgIndexs", delMsgIndexs, "docID", msgDocModel.DocID)
// mark del all delMsgIndexs
if err := db.msgDocDatabase.DeleteMsgsInOneDocByIndex(ctx, msgDocModel.DocID, delMsgIndexs); err != nil {
return delStruct.getSetMinSeq(), err
}
}
return MsgInfoModel.Msg.Seq, nil
}
}
}
if len(delMsgIndexs) > 0 {
if err := db.msgDocDatabase.DeleteMsgsInOneDocByIndex(ctx, msgDocModel.DocID, delMsgIndexs); err != nil {
log.ZError(ctx, "deleteMsgRecursion DeleteMsgsInOneDocByIndex failed", err, "conversationID", conversationID, "index", index)
}
delStruct.minSeq = int64(msgDocModel.Msg[delMsgIndexs[len(delMsgIndexs)-1]].Msg.Seq)
}
}
// 继续递归 index+1
seq, err := db.deleteMsgRecursion(ctx, conversationID, index+1, delStruct, remainTime)
return seq, err
}
@@ -961,7 +949,14 @@ func (db *commonMsgDatabase) SearchMessage(ctx context.Context, req *pbMsg.Searc
return 0, nil, err
}
for _, msg := range msgs {
if msg.IsRead {
msg.Msg.IsRead = true
}
totalMsgs = append(totalMsgs, convert.MsgDB2Pb(msg.Msg))
}
return total, totalMsgs, nil
}
func (db *commonMsgDatabase) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string) {
db.msgDocDatabase.ConvertMsgsDocLen(ctx, conversationIDs)
}
+10 -5
View File
@@ -30,7 +30,7 @@ type S3Database interface {
AuthSign(ctx context.Context, uploadID string, partNumbers []int) (*s3.AuthSignResult, error)
InitiateMultipartUpload(ctx context.Context, hash string, size int64, expire time.Duration, maxParts int) (*cont.InitiateUploadResult, error)
CompleteMultipartUpload(ctx context.Context, uploadID string, parts []string) (*cont.UploadResult, error)
AccessURL(ctx context.Context, name string, expire time.Duration) (time.Time, string, error)
AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error)
SetObject(ctx context.Context, info *relation.ObjectModel) error
}
@@ -70,14 +70,19 @@ func (s *s3Database) SetObject(ctx context.Context, info *relation.ObjectModel)
return s.obj.SetObject(ctx, info)
}
func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration) (time.Time, string, error) {
func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error) {
obj, err := s.obj.Take(ctx, name)
if err != nil {
return time.Time{}, "", err
}
opt := &s3.AccessURLOption{
ContentType: obj.ContentType,
Filename: filepath.Base(obj.Name),
if opt == nil {
opt = &s3.AccessURLOption{}
}
if opt.ContentType == "" {
opt.ContentType = obj.ContentType
}
if opt.Filename == "" {
opt.Filename = filepath.Base(obj.Name)
}
expireTime := time.Now().Add(expire)
rawURL, err := s.s3.AccessURL(ctx, obj.Key, expire, opt)
+2 -1
View File
@@ -16,7 +16,8 @@ package controller
import (
"context"
unRelationTb "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation"
"time"
"github.com/OpenIMSDK/protocol/user"
unRelationTb "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation"
@@ -71,10 +71,13 @@ func (f *FriendRequestGorm) UpdateByMap(
// 更新记录 (非零值).
func (f *FriendRequestGorm) Update(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
fr2 := *friendRequest
fr2.FromUserID = ""
fr2.ToUserID = ""
return utils.Wrap(
f.db(ctx).
Where("from_user_id = ? AND to_user_id =?", friendRequest.FromUserID, friendRequest.ToUserID).
Updates(friendRequest).
Updates(fr2).
Error,
"",
)
+2 -1
View File
@@ -33,5 +33,6 @@ func NewMetaDB(db *gorm.DB, table any) *MetaDB {
}
func (g *MetaDB) db(ctx context.Context) *gorm.DB {
return g.DB.WithContext(ctx).Model(g.table)
db := g.DB.WithContext(ctx).Model(g.table)
return db
}
+5 -1
View File
@@ -86,7 +86,11 @@ func (u *UserGorm) Page(
// 获取所有用户ID.
func (u *UserGorm) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) {
return userIDs, errs.Wrap(u.db(ctx).Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("user_id", &userIDs).Error)
if pageNumber == 0 || showNumber == 0 {
return userIDs, errs.Wrap(u.db(ctx).Pluck("user_id", &userIDs).Error)
} else {
return userIDs, errs.Wrap(u.db(ctx).Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("user_id", &userIDs).Error)
}
}
func (u *UserGorm) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) {
+4
View File
@@ -257,5 +257,9 @@ func (c *Controller) IsNotFound(err error) bool {
}
func (c *Controller) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (string, error) {
if opt.Image != nil {
opt.Filename = ""
opt.ContentType = ""
}
return c.impl.AccessURL(ctx, name, expire, opt)
}
+49 -7
View File
@@ -36,6 +36,19 @@ const (
maxNumSize = 1000
)
const (
imagePng = "png"
imageJpg = "jpg"
imageJpeg = "jpeg"
imageGif = "gif"
imageWebp = "webp"
)
const (
videoSnapshotImagePng = "png"
videoSnapshotImageJpg = "jpg"
)
func NewCos() (s3.Interface, error) {
conf := config.Config.Object.Cos
u, err := url.Parse(conf.BucketURL)
@@ -248,19 +261,44 @@ func (c *Cos) ListUploadedParts(ctx context.Context, uploadID string, name strin
}
func (c *Cos) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (string, error) {
var option *cos.PresignedURLOptions
var imageMogr string
var option cos.PresignedURLOptions
if opt != nil {
query := make(url.Values)
if opt.Image != nil {
// https://cloud.tencent.com/document/product/436/44880
style := make([]string, 0, 2)
wh := make([]string, 2)
if opt.Image.Width > 0 {
wh[0] = strconv.Itoa(opt.Image.Width)
}
if opt.Image.Height > 0 {
wh[1] = strconv.Itoa(opt.Image.Height)
}
if opt.Image.Width > 0 || opt.Image.Height > 0 {
style = append(style, strings.Join(wh, "x"))
}
switch opt.Image.Format {
case
imagePng,
imageJpg,
imageJpeg,
imageGif,
imageWebp:
style = append(style, "format/"+opt.Image.Format)
}
if len(style) > 0 {
imageMogr = "&imageMogr2/thumbnail/" + strings.Join(style, "/") + "/ignore-error/1"
}
}
if opt.ContentType != "" {
query.Set("response-content-type", opt.ContentType)
}
if opt.Filename != "" {
query.Set("response-content-disposition", `attachment; filename="`+opt.Filename+`"`)
query.Set("response-content-disposition", `attachment; filename=`+strconv.Quote(opt.Filename))
}
if len(query) > 0 {
option = &cos.PresignedURLOptions{
Query: &query,
}
option.Query = &query
}
}
if expire <= 0 {
@@ -268,9 +306,13 @@ func (c *Cos) AccessURL(ctx context.Context, name string, expire time.Duration,
} else if expire < time.Second {
expire = time.Second
}
rawURL, err := c.client.Object.GetPresignedURL(ctx, http.MethodGet, name, c.credential.SecretID, c.credential.SecretKey, expire, option)
rawURL, err := c.client.Object.GetPresignedURL(ctx, http.MethodGet, name, c.credential.SecretID, c.credential.SecretKey, expire, &option)
if err != nil {
return "", err
}
return rawURL.String(), nil
urlStr := rawURL.String()
if imageMogr != "" {
urlStr += imageMogr
}
return urlStr, nil
}
+106
View File
@@ -0,0 +1,106 @@
package minio
import (
"image"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"io"
_ "golang.org/x/image/bmp"
_ "golang.org/x/image/tiff"
_ "golang.org/x/image/webp"
)
const (
formatPng = "png"
formatJpeg = "jpeg"
formatJpg = "jpg"
formatGif = "gif"
)
func ImageStat(reader io.Reader) (image.Image, string, error) {
return image.Decode(reader)
}
func ImageWidthHeight(img image.Image) (int, int) {
bounds := img.Bounds().Max
return bounds.X, bounds.Y
}
func resizeImage(img image.Image, maxWidth, maxHeight int) image.Image {
bounds := img.Bounds()
imgWidth := bounds.Max.X
imgHeight := bounds.Max.Y
// 计算缩放比例
scaleWidth := float64(maxWidth) / float64(imgWidth)
scaleHeight := float64(maxHeight) / float64(imgHeight)
// 如果都为0,则不缩放,返回原始图片
if maxWidth == 0 && maxHeight == 0 {
return img
}
// 如果宽度和高度都大于0,则选择较小的缩放比例,以保持宽高比
if maxWidth > 0 && maxHeight > 0 {
scale := scaleWidth
if scaleHeight < scaleWidth {
scale = scaleHeight
}
// 计算缩略图尺寸
thumbnailWidth := int(float64(imgWidth) * scale)
thumbnailHeight := int(float64(imgHeight) * scale)
// 使用"image"库的Resample方法生成缩略图
thumbnail := image.NewRGBA(image.Rect(0, 0, thumbnailWidth, thumbnailHeight))
for y := 0; y < thumbnailHeight; y++ {
for x := 0; x < thumbnailWidth; x++ {
srcX := int(float64(x) / scale)
srcY := int(float64(y) / scale)
thumbnail.Set(x, y, img.At(srcX, srcY))
}
}
return thumbnail
}
// 如果只指定了宽度或高度,则根据最大不超过的规则生成缩略图
if maxWidth > 0 {
thumbnailWidth := maxWidth
thumbnailHeight := int(float64(imgHeight) * scaleWidth)
// 使用"image"库的Resample方法生成缩略图
thumbnail := image.NewRGBA(image.Rect(0, 0, thumbnailWidth, thumbnailHeight))
for y := 0; y < thumbnailHeight; y++ {
for x := 0; x < thumbnailWidth; x++ {
srcX := int(float64(x) / scaleWidth)
srcY := int(float64(y) / scaleWidth)
thumbnail.Set(x, y, img.At(srcX, srcY))
}
}
return thumbnail
}
if maxHeight > 0 {
thumbnailWidth := int(float64(imgWidth) * scaleHeight)
thumbnailHeight := maxHeight
// 使用"image"库的Resample方法生成缩略图
thumbnail := image.NewRGBA(image.Rect(0, 0, thumbnailWidth, thumbnailHeight))
for y := 0; y < thumbnailHeight; y++ {
for x := 0; x < thumbnailWidth; x++ {
srcX := int(float64(x) / scaleHeight)
srcY := int(float64(y) / scaleHeight)
thumbnail.Set(x, y, img.At(srcX, srcY))
}
}
return thumbnail
}
// 默认情况下,返回原始图片
return img
}
+195 -12
View File
@@ -15,16 +15,28 @@
package minio
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"image"
"image/gif"
"image/jpeg"
"image/png"
"io"
"net/http"
"net/url"
"path"
"path/filepath"
"reflect"
"strconv"
"strings"
"sync"
"time"
"unsafe"
"github.com/OpenIMSDK/tools/log"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/minio/minio-go/v7/pkg/signer"
@@ -43,6 +55,13 @@ const (
maxNumSize = 10000
)
const (
maxImageWidth = 1024
maxImageHeight = 1024
maxImageSize = 1024 * 1024 * 50
pathInfo = "openim/thumbnail"
)
func NewMinio() (s3.Interface, error) {
conf := config.Config.Object.Minio
u, err := url.Parse(conf.Endpoint)
@@ -60,11 +79,26 @@ func NewMinio() (s3.Interface, error) {
m := &Minio{
bucket: conf.Bucket,
bucketURL: conf.Endpoint + "/" + conf.Bucket + "/",
opts: opts,
core: &minio.Core{Client: client},
lock: &sync.Mutex{},
init: false,
}
if conf.SignEndpoint == "" || conf.SignEndpoint == conf.Endpoint {
m.sign = m.core.Client
} else {
su, err := url.Parse(conf.SignEndpoint)
if err != nil {
return nil, err
}
m.opts = &minio.Options{
Creds: credentials.NewStaticV4(conf.AccessKeyID, conf.SecretAccessKey, conf.SessionToken),
Secure: su.Scheme == "https",
}
m.sign, err = minio.New(su.Host, m.opts)
if err != nil {
return nil, err
}
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := m.initMinio(ctx); err != nil {
@@ -76,8 +110,10 @@ func NewMinio() (s3.Interface, error) {
type Minio struct {
bucket string
bucketURL string
location string
opts *minio.Options
core *minio.Core
sign *minio.Client
lock sync.Locker
init bool
}
@@ -91,15 +127,43 @@ func (m *Minio) initMinio(ctx context.Context) error {
if m.init {
return nil
}
exists, err := m.core.Client.BucketExists(ctx, config.Config.Object.Minio.Bucket)
conf := config.Config.Object.Minio
exists, err := m.core.Client.BucketExists(ctx, conf.Bucket)
if err != nil {
return fmt.Errorf("check bucket exists error: %w", err)
}
if !exists {
if err := m.core.Client.MakeBucket(ctx, config.Config.Object.Minio.Bucket, minio.MakeBucketOptions{}); err != nil {
if err := m.core.Client.MakeBucket(ctx, conf.Bucket, minio.MakeBucketOptions{}); err != nil {
return fmt.Errorf("make bucket error: %w", err)
}
}
m.location, err = m.core.Client.GetBucketLocation(ctx, conf.Bucket)
if err != nil {
return err
}
func() {
if conf.SignEndpoint == "" || conf.SignEndpoint == conf.Endpoint {
return
}
defer func() {
if r := recover(); r != nil {
m.sign = m.core.Client
log.ZWarn(
context.Background(),
"set sign bucket location cache panic",
errors.New("failed to get private field value"),
"recover",
fmt.Sprintf("%+v", r),
"development version",
"github.com/minio/minio-go/v7 v7.0.61",
)
}
}()
blc := reflect.ValueOf(m.sign).Elem().FieldByName("bucketLocCache")
vblc := reflect.New(reflect.PtrTo(blc.Type()))
*(*unsafe.Pointer)(vblc.UnsafePointer()) = unsafe.Pointer(blc.UnsafeAddr())
vblc.Elem().Elem().Interface().(interface{ Set(string, string) }).Set(conf.Bucket, m.location)
}()
m.init = true
return nil
}
@@ -191,7 +255,7 @@ func (m *Minio) AuthSign(ctx context.Context, uploadID string, name string, expi
return nil, err
}
request.Header.Set("X-Amz-Content-Sha256", unsignedPayload)
request = signer.SignV4Trailer(*request, creds.AccessKeyID, creds.SecretAccessKey, creds.SessionToken, "us-east-1", nil)
request = signer.SignV4Trailer(*request, creds.AccessKeyID, creds.SecretAccessKey, creds.SessionToken, m.location, nil)
result.Parts[i] = s3.SignPart{
PartNumber: partNumber,
URL: request.URL.String(),
@@ -206,7 +270,7 @@ func (m *Minio) PresignedPutObject(ctx context.Context, name string, expire time
if err := m.initMinio(ctx); err != nil {
return "", err
}
rawURL, err := m.core.Client.PresignedPutObject(ctx, m.bucket, name, expire)
rawURL, err := m.sign.PresignedPutObject(ctx, m.bucket, name, expire)
if err != nil {
return "", err
}
@@ -303,6 +367,19 @@ func (m *Minio) ListUploadedParts(ctx context.Context, uploadID string, name str
return res, nil
}
func (m *Minio) presignedGetObject(ctx context.Context, name string, expire time.Duration, query url.Values) (string, error) {
if expire <= 0 {
expire = time.Hour * 24 * 365 * 99 // 99 years
} else if expire < time.Second {
expire = time.Second
}
rawURL, err := m.sign.PresignedGetObject(ctx, m.bucket, name, expire, query)
if err != nil {
return "", err
}
return rawURL.String(), nil
}
func (m *Minio) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (string, error) {
if err := m.initMinio(ctx); err != nil {
return "", err
@@ -313,17 +390,123 @@ func (m *Minio) AccessURL(ctx context.Context, name string, expire time.Duration
reqParams.Set("response-content-type", opt.ContentType)
}
if opt.Filename != "" {
reqParams.Set("response-content-disposition", `attachment; filename="`+opt.Filename+`"`)
reqParams.Set("response-content-disposition", `attachment; filename=`+strconv.Quote(opt.Filename))
}
}
if expire <= 0 {
expire = time.Hour * 24 * 365 * 99 // 99 years
} else if expire < time.Second {
expire = time.Second
if opt.Image == nil || (opt.Image.Width < 0 && opt.Image.Height < 0 && opt.Image.Format == "") || (opt.Image.Width > maxImageWidth || opt.Image.Height > maxImageHeight) {
return m.presignedGetObject(ctx, name, expire, reqParams)
}
u, err := m.core.Client.PresignedGetObject(ctx, m.bucket, name, expire, reqParams)
fileInfo, err := m.StatObject(ctx, name)
if err != nil {
return "", err
}
return u.String(), nil
if fileInfo.Size > maxImageSize {
return "", errors.New("file size too large")
}
objectInfoPath := path.Join(pathInfo, fileInfo.ETag, "image.json")
var (
img image.Image
info minioImageInfo
)
data, err := m.getObjectData(ctx, objectInfoPath, 1024)
if err == nil {
if err := json.Unmarshal(data, &info); err != nil {
return "", fmt.Errorf("unmarshal minio image info.json error: %w", err)
}
if info.NotImage {
return "", errors.New("not image")
}
} else if m.IsNotFound(err) {
reader, err := m.core.Client.GetObject(ctx, m.bucket, name, minio.GetObjectOptions{})
if err != nil {
return "", err
}
defer reader.Close()
imageInfo, format, err := ImageStat(reader)
if err == nil {
info.NotImage = false
info.Format = format
info.Width, info.Height = ImageWidthHeight(imageInfo)
img = imageInfo
} else {
info.NotImage = true
}
data, err := json.Marshal(&info)
if err != nil {
return "", err
}
if _, err := m.core.Client.PutObject(ctx, m.bucket, objectInfoPath, bytes.NewReader(data), int64(len(data)), minio.PutObjectOptions{}); err != nil {
return "", err
}
} else {
return "", err
}
if opt.Image.Width > info.Width || opt.Image.Width <= 0 {
opt.Image.Width = info.Width
}
if opt.Image.Height > info.Height || opt.Image.Height <= 0 {
opt.Image.Height = info.Height
}
opt.Image.Format = strings.ToLower(opt.Image.Format)
if opt.Image.Format == formatJpg {
opt.Image.Format = formatJpeg
}
switch opt.Image.Format {
case formatPng:
case formatJpeg:
case formatGif:
default:
if info.Format == formatGif {
opt.Image.Format = formatGif
} else {
opt.Image.Format = formatJpeg
}
}
reqParams.Set("response-content-type", "image/"+opt.Image.Format)
if opt.Image.Width == info.Width && opt.Image.Height == info.Height && opt.Image.Format == info.Format {
return m.presignedGetObject(ctx, name, expire, reqParams)
}
cacheKey := filepath.Join(pathInfo, fileInfo.ETag, fmt.Sprintf("image_w%d_h%d.%s", opt.Image.Width, opt.Image.Height, opt.Image.Format))
if _, err := m.core.Client.StatObject(ctx, m.bucket, cacheKey, minio.StatObjectOptions{}); err == nil {
return m.presignedGetObject(ctx, cacheKey, expire, reqParams)
} else if !m.IsNotFound(err) {
return "", err
}
if img == nil {
reader, err := m.core.Client.GetObject(ctx, m.bucket, name, minio.GetObjectOptions{})
if err != nil {
return "", err
}
defer reader.Close()
img, _, err = ImageStat(reader)
if err != nil {
return "", err
}
}
thumbnail := resizeImage(img, opt.Image.Width, opt.Image.Height)
buf := bytes.NewBuffer(nil)
switch opt.Image.Format {
case formatPng:
err = png.Encode(buf, thumbnail)
case formatJpeg:
err = jpeg.Encode(buf, thumbnail, nil)
case formatGif:
err = gif.Encode(buf, thumbnail, nil)
}
if _, err := m.core.Client.PutObject(ctx, m.bucket, cacheKey, buf, int64(buf.Len()), minio.PutObjectOptions{}); err != nil {
return "", err
}
return m.presignedGetObject(ctx, cacheKey, expire, reqParams)
}
func (m *Minio) getObjectData(ctx context.Context, name string, limit int64) ([]byte, error) {
object, err := m.core.Client.GetObject(ctx, m.bucket, name, minio.GetObjectOptions{})
if err != nil {
return nil, err
}
defer object.Close()
if limit < 0 {
return io.ReadAll(object)
}
return io.ReadAll(io.LimitReader(object, 1024))
}
+8
View File
@@ -0,0 +1,8 @@
package minio
type minioImageInfo struct {
NotImage bool `json:"notImage,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Format string `json:"format,omitempty"`
}
+41 -8
View File
@@ -36,6 +36,19 @@ const (
maxNumSize = 10000
)
const (
imagePng = "png"
imageJpg = "jpg"
imageJpeg = "jpeg"
imageGif = "gif"
imageWebp = "webp"
)
const (
videoSnapshotImagePng = "png"
videoSnapshotImageJpg = "jpg"
)
func NewOSS() (s3.Interface, error) {
conf := config.Config.Object.Oss
if conf.BucketURL == "" {
@@ -139,7 +152,7 @@ func (o *OSS) AuthSign(ctx context.Context, uploadID string, name string, expire
}
for i, partNumber := range partNumbers {
rawURL := fmt.Sprintf(`%s%s?partNumber=%d&uploadId=%s`, o.bucketURL, name, partNumber, uploadID)
request, err := http.NewRequestWithContext(ctx, http.MethodPut, rawURL, nil)
request, err := http.NewRequest(http.MethodPut, rawURL, nil)
if err != nil {
return nil, err
}
@@ -150,12 +163,7 @@ func (o *OSS) AuthSign(ctx context.Context, uploadID string, name string, expire
request.Header.Set(oss.HTTPHeaderHost, request.Host)
request.Header.Set(oss.HTTPHeaderDate, now)
request.Header.Set(oss.HttpHeaderOssDate, now)
authorization := fmt.Sprintf(
`OSS %s:%s`,
o.credentials.GetAccessKeyID(),
o.getSignedStr(request, fmt.Sprintf(`/%s/%s?partNumber=%d&uploadId=%s`, o.bucket.BucketName, name, partNumber, uploadID), o.credentials.GetAccessKeySecret()),
)
request.Header.Set(oss.HTTPHeaderAuthorization, authorization)
ossSignHeader(o.bucket.Client.Conn, request, fmt.Sprintf(`/%s/%s?partNumber=%d&uploadId=%s`, o.bucket.BucketName, name, partNumber, uploadID))
delete(request.Header, oss.HTTPHeaderDate)
result.Parts[i] = s3.SignPart{
PartNumber: partNumber,
@@ -266,11 +274,36 @@ func (o *OSS) ListUploadedParts(ctx context.Context, uploadID string, name strin
func (o *OSS) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (string, error) {
var opts []oss.Option
if opt != nil {
if opt.Image != nil {
// 文档地址: https://help.aliyun.com/zh/oss/user-guide/resize-images-4?spm=a2c4g.11186623.0.0.4b3b1e4fWW6yji
var format string
switch opt.Image.Format {
case
imagePng,
imageJpg,
imageJpeg,
imageGif,
imageWebp:
format = opt.Image.Format
default:
opt.Image.Format = imageJpg
}
// https://oss-console-img-demo-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/example.jpg?x-oss-process=image/resize,h_100,m_lfit
process := "image/resize,m_lfit"
if opt.Image.Width > 0 {
process += ",w_" + strconv.Itoa(opt.Image.Width)
}
if opt.Image.Height > 0 {
process += ",h_" + strconv.Itoa(opt.Image.Height)
}
process += ",format," + format
opts = append(opts, oss.Process(process))
}
if opt.ContentType != "" {
opts = append(opts, oss.ResponseContentType(opt.ContentType))
}
if opt.Filename != "" {
opts = append(opts, oss.ResponseContentDisposition(`attachment; filename="`+opt.Filename+`"`))
opts = append(opts, oss.ResponseContentDisposition(`attachment; filename=`+strconv.Quote(opt.Filename)))
}
}
if expire <= 0 {
+3 -88
View File
@@ -1,96 +1,11 @@
// Copyright © 2023 OpenIM. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package oss
import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"encoding/base64"
"hash"
"io"
"net/http"
"sort"
"strings"
_ "unsafe"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func (o *OSS) getAdditionalHeaderKeys(req *http.Request) ([]string, map[string]string) {
var keysList []string
keysMap := make(map[string]string)
srcKeys := make(map[string]string)
for k := range req.Header {
srcKeys[strings.ToLower(k)] = ""
}
for _, v := range o.bucket.Client.Config.AdditionalHeaders {
if _, ok := srcKeys[strings.ToLower(v)]; ok {
keysMap[strings.ToLower(v)] = ""
}
}
for k := range keysMap {
keysList = append(keysList, k)
}
sort.Strings(keysList)
return keysList, keysMap
}
func (o *OSS) getSignedStr(req *http.Request, canonicalizedResource string, keySecret string) string {
// Find out the "x-oss-"'s address in header of the request
ossHeadersMap := make(map[string]string)
additionalList, additionalMap := o.getAdditionalHeaderKeys(req)
for k, v := range req.Header {
if strings.HasPrefix(strings.ToLower(k), "x-oss-") {
ossHeadersMap[strings.ToLower(k)] = v[0]
} else if o.bucket.Client.Config.AuthVersion == oss.AuthV2 {
if _, ok := additionalMap[strings.ToLower(k)]; ok {
ossHeadersMap[strings.ToLower(k)] = v[0]
}
}
}
hs := newHeaderSorter(ossHeadersMap)
// Sort the ossHeadersMap by the ascending order
hs.Sort()
// Get the canonicalizedOSSHeaders
canonicalizedOSSHeaders := ""
for i := range hs.Keys {
canonicalizedOSSHeaders += hs.Keys[i] + ":" + hs.Vals[i] + "\n"
}
// Give other parameters values
// when sign URL, date is expires
date := req.Header.Get(oss.HTTPHeaderDate)
contentType := req.Header.Get(oss.HTTPHeaderContentType)
contentMd5 := req.Header.Get(oss.HTTPHeaderContentMD5)
// default is v1 signature
signStr := req.Method + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedOSSHeaders + canonicalizedResource
h := hmac.New(func() hash.Hash { return sha1.New() }, []byte(keySecret))
// v2 signature
if o.bucket.Client.Config.AuthVersion == oss.AuthV2 {
signStr = req.Method + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedOSSHeaders + strings.Join(additionalList, ";") + "\n" + canonicalizedResource
h = hmac.New(func() hash.Hash { return sha256.New() }, []byte(keySecret))
}
_, _ = io.WriteString(h, signStr)
signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))
return signedStr
}
//go:linkname ossSignHeader github.com/aliyun/aliyun-oss-go-sdk/oss.(*Conn).signHeader
func ossSignHeader(c *oss.Conn, req *http.Request, canonicalizedResource string)
-61
View File
@@ -1,61 +0,0 @@
// Copyright © 2023 OpenIM. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package oss
import (
"bytes"
"sort"
)
// headerSorter defines the key-value structure for storing the sorted data in signHeader.
type headerSorter struct {
Keys []string
Vals []string
}
// newHeaderSorter is an additional function for function SignHeader.
func newHeaderSorter(m map[string]string) *headerSorter {
hs := &headerSorter{
Keys: make([]string, 0, len(m)),
Vals: make([]string, 0, len(m)),
}
for k, v := range m {
hs.Keys = append(hs.Keys, k)
hs.Vals = append(hs.Vals, v)
}
return hs
}
// Sort is an additional function for function SignHeader.
func (hs *headerSorter) Sort() {
sort.Sort(hs)
}
// Len is an additional function for function SignHeader.
func (hs *headerSorter) Len() int {
return len(hs.Vals)
}
// Less is an additional function for function SignHeader.
func (hs *headerSorter) Less(i, j int) bool {
return bytes.Compare([]byte(hs.Keys[i]), []byte(hs.Keys[j])) < 0
}
// Swap is an additional function for function SignHeader.
func (hs *headerSorter) Swap(i, j int) {
hs.Vals[i], hs.Vals[j] = hs.Vals[j], hs.Vals[i]
hs.Keys[i], hs.Keys[j] = hs.Keys[j], hs.Keys[i]
}
+7
View File
@@ -116,9 +116,16 @@ type ListUploadedPartsResult struct {
UploadedParts []UploadedPart `xml:"Part"`
}
type Image struct {
Format string `json:"format"`
Width int `json:"width"`
Height int `json:"height"`
}
type AccessURLOption struct {
ContentType string `json:"contentType"`
Filename string `json:"filename"`
Image *Image `json:"image"`
}
type Interface interface {
+10 -4
View File
@@ -27,10 +27,11 @@ import (
)
const (
singleGocMsgNum = 5000
Msg = "msg"
OldestList = 0
NewestList = -1
singleGocMsgNum = 100
singleGocMsgNum5000 = 5000
Msg = "msg"
OldestList = 0
NewestList = -1
)
type MsgDocModel struct {
@@ -128,6 +129,7 @@ type MsgDocModelInterface interface {
pageNumber int32,
showNumber int32,
) (msgCount int64, userCount int64, groups []*GroupCount, dateCount map[string]int64, err error)
ConvertMsgsDocLen(ctx context.Context, conversationIDs []string)
}
func (MsgDocModel) TableName() string {
@@ -138,6 +140,10 @@ func (MsgDocModel) GetSingleGocMsgNum() int64 {
return singleGocMsgNum
}
func (MsgDocModel) GetSingleGocMsgNum5000() int64 {
return singleGocMsgNum5000
}
func (m *MsgDocModel) IsFull() bool {
return m.Msg[len(m.Msg)-1].Msg != nil
}
+43 -41
View File
@@ -1073,11 +1073,6 @@ func (m *MsgMongoDriver) SearchMessage(ctx context.Context, req *msg.SearchMessa
if err != nil {
return 0, nil, err
}
for _, msg1 := range msgs {
if msg1.IsRead {
msg1.Msg.IsRead = true
}
}
return total, msgs, nil
}
@@ -1151,13 +1146,22 @@ func (m *MsgMongoDriver) searchMessage(ctx context.Context, req *msg.SearchMessa
{"doc_id", 1},
}},
},
{
{"$unwind", bson.M{"path": "$msgs"}},
},
{
{"$sort", bson.M{"msgs.msg.send_time": -1}},
},
}
cursor, err := m.MsgCollection.Aggregate(ctx, pipe)
if err != nil {
return 0, nil, err
}
var msgsDocs []table.MsgDocModel
type docModel struct {
DocID string `bson:"doc_id"`
Msg *table.MsgInfoModel `bson:"msgs"`
}
var msgsDocs []docModel
err = cursor.All(ctx, &msgsDocs)
if err != nil {
return 0, nil, err
@@ -1167,41 +1171,39 @@ func (m *MsgMongoDriver) searchMessage(ctx context.Context, req *msg.SearchMessa
}
msgs := make([]*table.MsgInfoModel, 0)
for index := range msgsDocs {
for i := range msgsDocs[index].Msg {
msg := msgsDocs[index].Msg[i]
if msg == nil || msg.Msg == nil {
continue
}
if msg.Revoke != nil {
revokeContent := sdkws.MessageRevokedContent{
RevokerID: msg.Revoke.UserID,
RevokerRole: msg.Revoke.Role,
ClientMsgID: msg.Msg.ClientMsgID,
RevokerNickname: msg.Revoke.Nickname,
RevokeTime: msg.Revoke.Time,
SourceMessageSendTime: msg.Msg.SendTime,
SourceMessageSendID: msg.Msg.SendID,
SourceMessageSenderNickname: msg.Msg.SenderNickname,
SessionType: msg.Msg.SessionType,
Seq: msg.Msg.Seq,
Ex: msg.Msg.Ex,
}
data, err := json.Marshal(&revokeContent)
if err != nil {
return 0, nil, err
}
elem := sdkws.NotificationElem{
Detail: string(data),
}
content, err := json.Marshal(&elem)
if err != nil {
return 0, nil, err
}
msg.Msg.ContentType = constant.MsgRevokeNotification
msg.Msg.Content = string(content)
}
msgs = append(msgs, msg)
msgInfo := msgsDocs[index].Msg
if msgInfo == nil || msgInfo.Msg == nil {
continue
}
if msgInfo.Revoke != nil {
revokeContent := sdkws.MessageRevokedContent{
RevokerID: msgInfo.Revoke.UserID,
RevokerRole: msgInfo.Revoke.Role,
ClientMsgID: msgInfo.Msg.ClientMsgID,
RevokerNickname: msgInfo.Revoke.Nickname,
RevokeTime: msgInfo.Revoke.Time,
SourceMessageSendTime: msgInfo.Msg.SendTime,
SourceMessageSendID: msgInfo.Msg.SendID,
SourceMessageSenderNickname: msgInfo.Msg.SenderNickname,
SessionType: msgInfo.Msg.SessionType,
Seq: msgInfo.Msg.Seq,
Ex: msgInfo.Msg.Ex,
}
data, err := json.Marshal(&revokeContent)
if err != nil {
return 0, nil, err
}
elem := sdkws.NotificationElem{
Detail: string(data),
}
content, err := json.Marshal(&elem)
if err != nil {
return 0, nil, err
}
msgInfo.Msg.ContentType = constant.MsgRevokeNotification
msgInfo.Msg.Content = string(content)
}
msgs = append(msgs, msgInfo)
}
start := (req.Pagination.PageNumber - 1) * req.Pagination.ShowNumber
n := int32(len(msgs))
+68
View File
@@ -0,0 +1,68 @@
package unrelation
import (
"context"
"fmt"
"github.com/OpenIMSDK/tools/log"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
table "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation"
)
func (m *MsgMongoDriver) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string) {
for _, conversationID := range conversationIDs {
regex := primitive.Regex{Pattern: fmt.Sprintf("^%s:", conversationID)}
cursor, err := m.MsgCollection.Find(ctx, bson.M{"doc_id": regex})
if err != nil {
log.ZError(ctx, "convertAll find msg doc failed", err, "conversationID", conversationID)
continue
}
var msgDocs []table.MsgDocModel
err = cursor.All(ctx, &msgDocs)
if err != nil {
log.ZError(ctx, "convertAll cursor all failed", err, "conversationID", conversationID)
continue
}
if len(msgDocs) < 1 {
continue
}
log.ZInfo(ctx, "msg doc convert", "conversationID", conversationID, "len(msgDocs)", len(msgDocs))
if len(msgDocs[0].Msg) == int(m.model.GetSingleGocMsgNum5000()) {
if _, err := m.MsgCollection.DeleteMany(ctx, bson.M{"doc_id": regex}); err != nil {
log.ZError(ctx, "convertAll delete many failed", err, "conversationID", conversationID)
continue
}
var newMsgDocs []interface{}
for _, msgDoc := range msgDocs {
if int64(len(msgDoc.Msg)) == m.model.GetSingleGocMsgNum() {
continue
}
var index int64
for index < int64(len(msgDoc.Msg)) {
msg := msgDoc.Msg[index]
if msg != nil && msg.Msg != nil {
msgDocModel := table.MsgDocModel{DocID: m.model.GetDocID(conversationID, msg.Msg.Seq)}
end := index + m.model.GetSingleGocMsgNum()
if int(end) >= len(msgDoc.Msg) {
msgDocModel.Msg = msgDoc.Msg[index:]
} else {
msgDocModel.Msg = msgDoc.Msg[index:end]
}
newMsgDocs = append(newMsgDocs, msgDocModel)
index = end
} else {
break
}
}
}
_, err = m.MsgCollection.InsertMany(ctx, newMsgDocs)
if err != nil {
log.ZError(ctx, "convertAll insert many failed", err, "conversationID", conversationID, "len(newMsgDocs)", len(newMsgDocs))
} else {
log.ZInfo(ctx, "msg doc convert", "conversationID", conversationID, "len(newMsgDocs)", len(newMsgDocs))
}
}
}
}
+3 -1
View File
@@ -16,12 +16,14 @@ package unrelation
import (
"context"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/utils"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation"
)
// prefixes and suffixes.
+25 -1
View File
@@ -23,7 +23,7 @@ import (
"google.golang.org/protobuf/proto"
)
func GetNotificationConversationID(msg *sdkws.MsgData) string {
func GetNotificationConversationIDByMsg(msg *sdkws.MsgData) string {
switch msg.SessionType {
case constant.SingleChatType:
l := []string{msg.SendID, msg.RecvID}
@@ -114,6 +114,30 @@ func GetConversationIDBySessionType(sessionType int, ids ...string) string {
return ""
}
func GetNotificationConversationIDByConversationID(conversationID string) string {
l := strings.Split(conversationID, "_")
if len(l) > 1 {
l[0] = "n"
return strings.Join(l, "_")
} else {
return ""
}
}
func GetNotificationConversationID(sessionType int, ids ...string) string {
sort.Strings(ids)
if len(ids) > 2 || len(ids) < 1 {
return ""
}
switch sessionType {
case constant.SingleChatType:
return "n_" + strings.Join(ids, "_") // single chat
case constant.SuperGroupChatType:
return "n_" + ids[0] // super group chat
}
return ""
}
func IsNotification(conversationID string) bool {
return strings.HasPrefix(conversationID, "n_")
}
+118 -23
View File
@@ -220,7 +220,13 @@ func (g *GroupNotificationSender) getUsersInfoMap(ctx context.Context, userIDs [
return result, nil
}
func (g *GroupNotificationSender) fillOpUser(ctx context.Context, opUser **sdkws.GroupMemberFullInfo, groupID string) error {
func (g *GroupNotificationSender) fillOpUser(ctx context.Context, opUser **sdkws.GroupMemberFullInfo, groupID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
if opUser == nil {
return errs.ErrInternalServer.Wrap("**sdkws.GroupMemberFullInfo is nil")
}
@@ -260,6 +266,12 @@ func (g *GroupNotificationSender) fillOpUser(ctx context.Context, opUser **sdkws
}
func (g *GroupNotificationSender) GroupCreatedNotification(ctx context.Context, tips *sdkws.GroupCreatedTips) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
return err
}
@@ -267,6 +279,12 @@ func (g *GroupNotificationSender) GroupCreatedNotification(ctx context.Context,
}
func (g *GroupNotificationSender) GroupInfoSetNotification(ctx context.Context, tips *sdkws.GroupInfoSetTips) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
return err
}
@@ -274,6 +292,12 @@ func (g *GroupNotificationSender) GroupInfoSetNotification(ctx context.Context,
}
func (g *GroupNotificationSender) GroupInfoSetNameNotification(ctx context.Context, tips *sdkws.GroupInfoSetNameTips) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
return err
}
@@ -281,6 +305,12 @@ func (g *GroupNotificationSender) GroupInfoSetNameNotification(ctx context.Conte
}
func (g *GroupNotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Context, tips *sdkws.GroupInfoSetAnnouncementTips) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
return err
}
@@ -288,6 +318,12 @@ func (g *GroupNotificationSender) GroupInfoSetAnnouncementNotification(ctx conte
}
func (g *GroupNotificationSender) JoinGroupApplicationNotification(ctx context.Context, req *pbGroup.JoinGroupReq) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, req.GroupID)
if err != nil {
return err
@@ -355,6 +391,12 @@ func (g *GroupNotificationSender) GroupApplicationAcceptedNotification(ctx conte
}
func (g *GroupNotificationSender) GroupApplicationRejectedNotification(ctx context.Context, req *pbGroup.GroupApplicationResponseReq) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, req.GroupID)
if err != nil {
return err
@@ -377,6 +419,12 @@ func (g *GroupNotificationSender) GroupApplicationRejectedNotification(ctx conte
}
func (g *GroupNotificationSender) GroupOwnerTransferredNotification(ctx context.Context, req *pbGroup.TransferGroupOwnerReq) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, req.GroupID)
if err != nil {
return err
@@ -394,6 +442,12 @@ func (g *GroupNotificationSender) GroupOwnerTransferredNotification(ctx context.
}
func (g *GroupNotificationSender) MemberKickedNotification(ctx context.Context, tips *sdkws.MemberKickedTips) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
return err
}
@@ -401,6 +455,12 @@ func (g *GroupNotificationSender) MemberKickedNotification(ctx context.Context,
}
func (g *GroupNotificationSender) MemberInvitedNotification(ctx context.Context, groupID, reason string, invitedUserIDList []string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
@@ -419,12 +479,18 @@ func (g *GroupNotificationSender) MemberInvitedNotification(ctx context.Context,
return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberInvitedNotification, tips)
}
func (g *GroupNotificationSender) MemberEnterNotification(ctx context.Context, req *pbGroup.GroupApplicationResponseReq) (err error) {
group, err := g.getGroupInfo(ctx, req.GroupID)
func (g *GroupNotificationSender) MemberEnterNotification(ctx context.Context, groupID string, entrantUserID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
}
user, err := g.getGroupMember(ctx, req.GroupID, req.FromUserID)
user, err := g.getGroupMember(ctx, groupID, entrantUserID)
if err != nil {
return err
}
@@ -433,6 +499,12 @@ func (g *GroupNotificationSender) MemberEnterNotification(ctx context.Context, r
}
func (g *GroupNotificationSender) GroupDismissedNotification(ctx context.Context, tips *sdkws.GroupDismissedTips) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
return err
}
@@ -440,6 +512,12 @@ func (g *GroupNotificationSender) GroupDismissedNotification(ctx context.Context
}
func (g *GroupNotificationSender) GroupMemberMutedNotification(ctx context.Context, groupID, groupMemberUserID string, mutedSeconds uint32) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
@@ -459,6 +537,12 @@ func (g *GroupNotificationSender) GroupMemberMutedNotification(ctx context.Conte
}
func (g *GroupNotificationSender) GroupMemberCancelMutedNotification(ctx context.Context, groupID, groupMemberUserID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
@@ -475,6 +559,12 @@ func (g *GroupNotificationSender) GroupMemberCancelMutedNotification(ctx context
}
func (g *GroupNotificationSender) GroupMutedNotification(ctx context.Context, groupID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
@@ -494,6 +584,12 @@ func (g *GroupNotificationSender) GroupMutedNotification(ctx context.Context, gr
}
func (g *GroupNotificationSender) GroupCancelMutedNotification(ctx context.Context, groupID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
@@ -513,6 +609,12 @@ func (g *GroupNotificationSender) GroupCancelMutedNotification(ctx context.Conte
}
func (g *GroupNotificationSender) GroupMemberInfoSetNotification(ctx context.Context, groupID, groupMemberUserID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
@@ -529,6 +631,12 @@ func (g *GroupNotificationSender) GroupMemberInfoSetNotification(ctx context.Con
}
func (g *GroupNotificationSender) GroupMemberSetToAdminNotification(ctx context.Context, groupID, groupMemberUserID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
@@ -545,6 +653,12 @@ func (g *GroupNotificationSender) GroupMemberSetToAdminNotification(ctx context.
}
func (g *GroupNotificationSender) GroupMemberSetToOrdinaryUserNotification(ctx context.Context, groupID, groupMemberUserID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
@@ -560,25 +674,6 @@ func (g *GroupNotificationSender) GroupMemberSetToOrdinaryUserNotification(ctx c
return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberSetToOrdinaryUserNotification, tips)
}
func (g *GroupNotificationSender) MemberEnterDirectlyNotification(ctx context.Context, groupID string, entrantUserID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
if err != nil {
log.ZError(ctx, utils.GetFuncName(1)+" failed", err)
}
}()
group, err := g.getGroupInfo(ctx, groupID)
if err != nil {
return err
}
user, err := g.getGroupMember(ctx, groupID, entrantUserID)
if err != nil {
return err
}
tips := &sdkws.MemberEnterTips{Group: group, EntrantUser: user}
return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberEnterNotification, tips)
}
func (g *GroupNotificationSender) SuperGroupNotification(ctx context.Context, sendID, recvID string) (err error) {
defer log.ZDebug(ctx, "return")
defer func() {
+1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
+1 -1
View File
@@ -61,7 +61,7 @@ check=$(ps aux | grep -w ./${openim_msgtransfer} | grep -v grep | wc -l)
if [ $check -eq ${msg_transfer_service_num} ]; then
echo -e ${GREEN_PREFIX}"none port has been listening,belongs service is openImMsgTransfer"${COLOR_SUFFIX}
else
echo $check ${msg_transfer_service_num}
echo $check ${msg_transfer_service_num}
echo -e ${RED_PREFIX}"openImMsgTransfer service does not start normally, num err"${COLOR_SUFFIX}
echo -e ${RED_PREFIX}"please check $OPENIM_ROOT/logs/openIM.log "${COLOR_SUFFIX}
exit -1
+2 -1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +19,7 @@
# Common utilities, variables and checks for all build scripts.
set -o errexit
set -o nounset
set +o nounset
set -o pipefail
# Unset CDPATH, having it set messes up with script import paths
+1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
+1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
+10
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,6 +30,15 @@ need_to_start_server_shell=(
${SCRIPTS_ROOT}/start_cron.sh
)
component_check=start_component_check.sh
chmod +x $SCRIPTS_ROOT/$component_check
$SCRIPTS_ROOT/$component_check
if [ $? -ne 0 ]; then
# Print error message and exit
echo "${BOLD_PREFIX}${RED_PREFIX}Error executing ${component_check}. Exiting...${COLOR_SUFFIX}"
exit -1
fi
#fixme The 10 second delay to start the project is for the docker-compose one-click to start openIM when the infrastructure dependencies are not started
sleep 10
+1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/env bash
# Copyright 2020 Lingfei Kong <colin404@foxmail.com>. All rights reserved.
# Use of this source code is governed by a MIT style
# license that can be found in the LICENSE file.
# OPENIM 项目源码根目录
IAM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
# 生成文件存放目录
LOCAL_OUTPUT_ROOT="${IAM_ROOT}/${OUT_DIR:-_output}"
# 设置统一的密码,方便记忆
readonly PASSWORD=${PASSWORD:-'iam59!z$'}
# Linux系统 going 用户
readonly LINUX_USERNAME=${LINUX_USERNAME:-going}
# Linux root & going 用户密码
readonly LINUX_PASSWORD=${LINUX_PASSWORD:-${PASSWORD}}
# 设置安装目录
readonly INSTALL_DIR=${INSTALL_DIR:-/tmp/installation}
mkdir -p ${INSTALL_DIR}
readonly ENV_FILE=${IAM_ROOT}/scripts/install/environment.sh
# MariaDB 配置信息
readonly MARIADB_ADMIN_USERNAME=${MARIADB_ADMIN_USERNAME:-root} # MariaDB root 用户
readonly MARIADB_ADMIN_PASSWORD=${MARIADB_ADMIN_PASSWORD:-${PASSWORD}} # MariaDB root 用户密码
readonly MARIADB_HOST=${MARIADB_HOST:-127.0.0.1:3306} # MariaDB 主机地址
readonly MARIADB_DATABASE=${MARIADB_DATABASE:-openim} # MariaDB openim 应用使用的数据库名
readonly MARIADB_USERNAME=${MARIADB_USERNAME:-openim} # openim 数据库用户名
readonly MARIADB_PASSWORD=${MARIADB_PASSWORD:-${PASSWORD}} # openim 数据库密码
# Redis 配置信息
readonly REDIS_HOST=${REDIS_HOST:-127.0.0.1} # Redis 主机地址
readonly REDIS_PORT=${REDIS_PORT:-6379} # Redis 监听端口
readonly REDIS_USERNAME=${REDIS_USERNAME:-''} # Redis 用户名
readonly REDIS_PASSWORD=${REDIS_PASSWORD:-${PASSWORD}} # Redis 密码
# MongoDB 配置
readonly MONGO_ADMIN_USERNAME=${MONGO_ADMIN_USERNAME:-root} # MongoDB root 用户
readonly MONGO_ADMIN_PASSWORD=${MONGO_ADMIN_PASSWORD:-${PASSWORD}} # MongoDB root 用户密码
readonly MONGO_HOST=${MONGO_HOST:-127.0.0.1} # MongoDB 地址
readonly MONGO_PORT=${MONGO_PORT:-27017} # MongoDB 端口
readonly MONGO_USERNAME=${MONGO_USERNAME:-openim} # MongoDB 用户名
readonly MONGO_PASSWORD=${MONGO_PASSWORD:-${PASSWORD}} # MongoDB 密码
# openim 配置
readonly IAM_DATA_DIR=${IAM_DATA_DIR:-/data/openim} # openim 各组件数据目录
readonly IAM_INSTALL_DIR=${IAM_INSTALL_DIR:-/opt/openim} # openim 安装文件存放目录
readonly IAM_CONFIG_DIR=${IAM_CONFIG_DIR:-/etc/openim} # openim 配置文件存放目录
readonly IAM_LOG_DIR=${IAM_LOG_DIR:-/var/log/openim} # openim 日志文件存放目录
readonly CA_FILE=${CA_FILE:-${IAM_CONFIG_DIR}/cert/ca.pem} # CA
# openim-apiserver 配置
readonly IAM_APISERVER_HOST=${IAM_APISERVER_HOST:-127.0.0.1} # openim-apiserver 部署机器 IP 地址
readonly IAM_APISERVER_GRPC_BIND_ADDRESS=${IAM_APISERVER_GRPC_BIND_ADDRESS:-0.0.0.0}
readonly IAM_APISERVER_GRPC_BIND_PORT=${IAM_APISERVER_GRPC_BIND_PORT:-8081}
readonly IAM_APISERVER_INSECURE_BIND_ADDRESS=${IAM_APISERVER_INSECURE_BIND_ADDRESS:-127.0.0.1}
readonly IAM_APISERVER_INSECURE_BIND_PORT=${IAM_APISERVER_INSECURE_BIND_PORT:-8080}
readonly IAM_APISERVER_SECURE_BIND_ADDRESS=${IAM_APISERVER_SECURE_BIND_ADDRESS:-0.0.0.0}
readonly IAM_APISERVER_SECURE_BIND_PORT=${IAM_APISERVER_SECURE_BIND_PORT:-8443}
readonly IAM_APISERVER_SECURE_TLS_CERT_KEY_CERT_FILE=${IAM_APISERVER_SECURE_TLS_CERT_KEY_CERT_FILE:-${IAM_CONFIG_DIR}/cert/openim-apiserver.pem}
readonly IAM_APISERVER_SECURE_TLS_CERT_KEY_PRIVATE_KEY_FILE=${IAM_APISERVER_SECURE_TLS_CERT_KEY_PRIVATE_KEY_FILE:-${IAM_CONFIG_DIR}/cert/openim-apiserver-key.pem}
# openim-authz-server 配置
readonly IAM_AUTHZ_SERVER_HOST=${IAM_AUTHZ_SERVER_HOST:-127.0.0.1} # openim-authz-server 部署机器 IP 地址
readonly IAM_AUTHZ_SERVER_INSECURE_BIND_ADDRESS=${IAM_AUTHZ_SERVER_INSECURE_BIND_ADDRESS:-127.0.0.1}
readonly IAM_AUTHZ_SERVER_INSECURE_BIND_PORT=${IAM_AUTHZ_SERVER_INSECURE_BIND_PORT:-9090}
readonly IAM_AUTHZ_SERVER_SECURE_BIND_ADDRESS=${IAM_AUTHZ_SERVER_SECURE_BIND_ADDRESS:-0.0.0.0}
readonly IAM_AUTHZ_SERVER_SECURE_BIND_PORT=${IAM_AUTHZ_SERVER_SECURE_BIND_PORT:-9443}
readonly IAM_AUTHZ_SERVER_SECURE_TLS_CERT_KEY_CERT_FILE=${IAM_AUTHZ_SERVER_SECURE_TLS_CERT_KEY_CERT_FILE:-${IAM_CONFIG_DIR}/cert/openim-authz-server.pem}
readonly IAM_AUTHZ_SERVER_SECURE_TLS_CERT_KEY_PRIVATE_KEY_FILE=${IAM_AUTHZ_SERVER_SECURE_TLS_CERT_KEY_PRIVATE_KEY_FILE:-${IAM_CONFIG_DIR}/cert/openim-authz-server-key.pem}
readonly IAM_AUTHZ_SERVER_CLIENT_CA_FILE=${IAM_AUTHZ_SERVER_CLIENT_CA_FILE:-${CA_FILE}}
readonly IAM_AUTHZ_SERVER_RPCSERVER=${IAM_AUTHZ_SERVER_RPCSERVER:-${IAM_APISERVER_HOST}:${IAM_APISERVER_GRPC_BIND_PORT}}
# openim-pump 配置
readonly IAM_PUMP_HOST=${IAM_PUMP_HOST:-127.0.0.1} # openim-pump 部署机器 IP 地址
readonly IAM_PUMP_COLLECTION_NAME=${IAM_PUMP_COLLECTION_NAME:-iam_analytics}
readonly IAM_PUMP_MONGO_URL=${IAM_PUMP_MONGO_URL:-mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOST}:${MONGO_PORT}/${IAM_PUMP_COLLECTION_NAME}?authSource=${IAM_PUMP_COLLECTION_NAME}}
# openim-watcher配置
readonly IAM_WATCHER_HOST=${IAM_WATCHER_HOST:-127.0.0.1} # openim-watcher 部署机器 IP 地址
# iamctl 配置
readonly CONFIG_USER_USERNAME=${CONFIG_USER_USERNAME:-admin}
readonly CONFIG_USER_PASSWORD=${CONFIG_USER_PASSWORD:-Admin@2021}
readonly CONFIG_USER_CLIENT_CERTIFICATE=${CONFIG_USER_CLIENT_CERTIFICATE:-${HOME}/.openim/cert/admin.pem}
readonly CONFIG_USER_CLIENT_KEY=${CONFIG_USER_CLIENT_KEY:-${HOME}/.openim/cert/admin-key.pem}
readonly CONFIG_SERVER_ADDRESS=${CONFIG_SERVER_ADDRESS:-${IAM_APISERVER_HOST}:${IAM_APISERVER_SECURE_BIND_PORT}}
readonly CONFIG_SERVER_CERTIFICATE_AUTHORITY=${CONFIG_SERVER_CERTIFICATE_AUTHORITY:-${CA_FILE}}
+1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
+42
View File
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Copyright 2020 Lingfei Kong <colin404@foxmail.com>. All rights reserved.
# Use of this source code is governed by a MIT style
# license that can be found in the LICENSE file.
# 本脚本功能:根据 scripts/environment.sh 配置,生成 OPENIM 组件 YAML 配置文件。
# 示例:genconfig.sh scripts/environment.sh configs/openim-apiserver.yaml
env_file="$1"
template_file="$2"
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${OPENIM_ROOT}/scripts/lib/init.sh"
if [ $# -ne 2 ];then
openim::log::error "Usage: genconfig.sh scripts/environment.sh configs/openim-apiserver.yaml"
exit 1
fi
source "${env_file}"
declare -A envs
set +u
for env in $(sed -n 's/^[^#].*${\(.*\)}.*/\1/p' ${template_file})
do
if [ -z "$(eval echo \$${env})" ];then
openim::log::error "environment variable '${env}' not set"
missing=true
fi
done
if [ "${missing}" ];then
openim::log::error 'You may run `source scripts/environment.sh` to set these environment'
exit 1
fi
eval "cat << EOF
$(cat ${template_file})
EOF"
+39
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -31,6 +32,44 @@ COLOR_BGREEN='\033[42m';COLOR_BYELLOW='\033[43m';
COLOR_BBLUE='\033[44m';COLOR_BMAGENTA='\033[45m';
COLOR_BCYAN='\033[46m';COLOR_BWHITE='\033[47m';
# Color definitions
COLOR_SUFFIX="\033[0m" # End all colors and special effects
BLACK_PREFIX="\033[30m" # Black prefix
RED_PREFIX="\033[31m" # Red prefix
GREEN_PREFIX="\033[32m" # Green prefix
YELLOW_PREFIX="\033[33m" # Yellow prefix
BLUE_PREFIX="\033[34m" # Blue prefix
SKY_BLUE_PREFIX="\033[36m" # Sky blue prefix
WHITE_PREFIX="\033[37m" # White prefix
BOLD_PREFIX="\033[1m" # Bold prefix
UNDERLINE_PREFIX="\033[4m" # Underline prefix
ITALIC_PREFIX="\033[3m" # Italic prefix
BRIGHT_GREEN_PREFIX='\033[1;32m' # Bright green prefix
CYAN_PREFIX="\033[0;36m" # Cyan prefix
# --- helper functions for logs ---
info()
{
echo -e "[${GREEN_PREFIX}INFO${COLOR_SUFFIX}] " "$@"
}
warn()
{
echo -e "[${YELLOW_PREFIX}WARN${COLOR_SUFFIX}] " "$@" >&2
}
fatal()
{
echo -e "[${RED_PREFIX}ERROR${COLOR_SUFFIX}] " "$@" >&2
exit 1
}
debug()
{
echo -e "[${BLUE_PREFIX}DEBUG${COLOR_SUFFIX}]===> " "$@"
}
success()
{
echo -e "${BRIGHT_GREEN_PREFIX}===> [SUCCESS] <===${COLOR_SUFFIX}\n=> " "$@"
}
# Print colors you can use
openim::color::print_color()
{
+20
View File
@@ -709,3 +709,23 @@ if [[ -z "${color_start-}" ]]; then
fi
# ex: ts=2 sw=2 et filetype=sh
# input: [10023, 2323, 3434]
# output: 10023 2323 3434
# Function function: Converts a list to a string, removing Spaces and parentheses
function list_to_string() {
ports_list=$* # 获取传入的参数列表
sub_s1=$(echo $ports_list | sed 's/ //g') # 去除空格
sub_s2=${sub_s1//,/ } # 将逗号替换为空格
sub_s3=${sub_s2#*[} # 去除左括号及其之前的内容
sub_s4=${sub_s3%]*} # 去除右括号及其之后的内容
ports_array=$sub_s4 # 将处理后的字符串赋值给变量 ports_array
}
# Function Function: Remove Spaces in the string
function remove_space() {
value=$* # 获取传入的参数
result=$(echo $value | sed 's/ //g') # 去除空格
}
+6
View File
@@ -46,6 +46,12 @@ BIN_DIR := $(OUTPUT_DIR)/bin
$(shell mkdir -p $(BIN_DIR))
endif
# BIN_TOOLS_DIR: Directory where executable files are stored.
ifeq ($(origin BIN_TOOLS_DIR),undefined)
BIN_TOOLS_DIR := $(OUTPUT_DIR)/bin-tools
$(shell mkdir -p $(BIN_TOOLS_DIR))
endif
# TOOLS_DIR: The directory where tools are stored for build and testing.
ifeq ($(origin TOOLS_DIR),undefined)
TOOLS_DIR := $(OUTPUT_DIR)/tools
+11 -6
View File
@@ -44,8 +44,8 @@ ifeq ($(origin GOBIN), undefined)
GOBIN := $(GOPATH)/bin
endif
# COMMANDS is Specify all files under ${ROOT_DIR}/cmd/ except those ending in.md
COMMANDS ?= $(filter-out %.md, $(wildcard ${ROOT_DIR}/cmd/*))
# COMMANDS is Specify all files under ${ROOT_DIR}/cmd/ and ${ROOT_DIR}/tools/ except those ending in.md
COMMANDS ?= $(filter-out %.md, $(wildcard ${ROOT_DIR}/cmd/* ${ROOT_DIR}/tools/*))
ifeq (${COMMANDS},)
$(error Could not determine COMMANDS, set ROOT_DIR or run in source dir)
endif
@@ -127,8 +127,13 @@ go.build.%:
$(BIN_DIR)/platforms/$(OS)/$(ARCH)/$$(basename $${d})$(GO_OUT_EXT) $${d}/main.go; \
done; \
else \
CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) $(GO) build $(GO_BUILD_FLAGS) -o \
$(BIN_DIR)/platforms/$(OS)/$(ARCH)/$(COMMAND)$(GO_OUT_EXT) $(ROOT_DIR)/cmd/$(COMMAND)/main.go; \
if [ -f $(ROOT_DIR)/cmd/$(COMMAND)/main.go ]; then \
CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) $(GO) build $(GO_BUILD_FLAGS) -o \
$(BIN_DIR)/platforms/$(OS)/$(ARCH)/$(COMMAND)$(GO_OUT_EXT) $(ROOT_DIR)/cmd/$(COMMAND)/main.go; \
elif [ -f $(ROOT_DIR)/tools/$(COMMAND)/main.go ]; then \
CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) $(GO) build $(GO_BUILD_FLAGS) -o \
$(BIN_TOOLS_DIR)/platforms/$(OS)/$(ARCH)/$(COMMAND)$(GO_OUT_EXT) $(ROOT_DIR)/tools/$(COMMAND)/main.go; \
fi \
fi
## go.install: Install deployment openim
@@ -197,8 +202,8 @@ go.updates: tools.verify.go-mod-outdated
## go.clean: Clean all builds directories and files
.PHONY: go.clean
go.clean:
@echo "===========> Cleaning all builds TMP_DIR($(TMP_DIR)) AND BIN_DIR($(BIN_DIR))"
@-rm -vrf $(TMP_DIR) $(BIN_DIR)
@echo "===========> Cleaning all builds TMP_DIR($(TMP_DIR)) AND BIN_DIR($(BIN_DIR)) AND BIN_TOOLS_DIR($(BIN_TOOLS_DIR))"
@-rm -vrf $(TMP_DIR) $(BIN_DIR) $(BIN_TOOLS_DIR)
@echo "===========> End clean..."
## copyright.help: Show copyright help
-1
View File
@@ -30,7 +30,6 @@ echo -e "${YELLOW_PREFIX}=======>pwd=$PWD${COLOR_SUFFIX}"
bin_dir="$BIN_DIR"
logs_dir="$OPENIM_ROOT/logs"
sdk_db_dir="$OPENIM_ROOT/sdk/db/"
ulimit -n 200000
-1
View File
@@ -28,7 +28,6 @@ echo -e "${YELLOW_PREFIX}=======>pwd=$PWD${COLOR_SUFFIX}"
bin_dir="$BIN_DIR"
logs_dir="$OPENIM_ROOT/logs"
sdk_db_dir="$OPENIM_ROOT/sdk/db/"
cd $OPENIM_ROOT
+19 -1
View File
@@ -40,6 +40,19 @@ declare -A supported_architectures=(
["darwin-x86_64"]="_output/bin/platforms/darwin/amd64" # Alias for darwin-amd64
)
declare -A supported_architectures_tools=(
["linux-amd64"]="_output/bin-tools/platforms/linux/amd64"
["linux-arm64"]="_output/bin-tools/platforms/linux/arm64"
["linux-mips64"]="_output/bin-tools/platforms/linux/mips64"
["linux-mips64le"]="_output/bin-tools/platforms/linux/mips64le"
["linux-ppc64le"]="_output/bin-tools/platforms/linux/ppc64le"
["linux-s390x"]="_output/bin-tools/platforms/linux/s390x"
["darwin-amd64"]="_output/bin-tools/platforms/darwin/amd64"
["windows-amd64"]="_output/bin-tools/platforms/windows/amd64"
["linux-x86_64"]="_output/bin-tools/platforms/linux/amd64" # Alias for linux-amd64
["darwin-x86_64"]="_output/bin-tools/platforms/darwin/amd64" # Alias for darwin-amd64
)
# Check if the architecture and version are supported
if [[ -z ${supported_architectures["$version-$architecture"]} ]]; then
echo -e "${BLUE_PREFIX}================> Unsupported architecture: $architecture or version: $version${COLOR_SUFFIX}"
@@ -50,6 +63,7 @@ echo -e "${BLUE_PREFIX}================> Architecture: $architecture${COLOR_SUFF
# Set the BIN_DIR based on the architecture and version
BIN_DIR=${supported_architectures["$version-$architecture"]}
BIN_DIR_TOOLS=${supported_architectures_tools["$version-$architecture"]}
echo -e "${BLUE_PREFIX}================> BIN_DIR: $OPENIM_ROOT/$BIN_DIR${COLOR_SUFFIX}"
@@ -84,6 +98,10 @@ config_path="$OPENIM_ROOT/config/config.yaml"
configfile_path="$OPENIM_ROOT/config"
log_path="$OPENIM_ROOT/log"
component_check="component"
component_check_binary_root="$OPENIM_ROOT/$BIN_DIR_TOOLS"
# servicefile dir path
service_source_root=(
# api service file
@@ -120,4 +138,4 @@ service_names=(
"${msg_name}"
"${push_name}"
# "${sdk_server_name}"
)
)
-1
View File
@@ -32,7 +32,6 @@ echo -e "${YELLOW_PREFIX}=======>pwd=$PWD${COLOR_SUFFIX}"
bin_dir="$BIN_DIR"
logs_dir="$OPENIM_ROOT/logs"
sdk_db_dir="$OPENIM_ROOT/sdk/db/"
cd "$OPENIM_ROOT/scripts/"
+12
View File
@@ -0,0 +1,12 @@
cd %~p0../_output/bin/platforms/windows
start api.exe -p 10002
start auth.exe -p 10060
start conversation.exe -p 10080
start friend.exe -p 10020
start group.exe -p 10050
start msg.exe -p 10030
start msggateway.exe -p 10040 -w 10001
start msgtransfer.exe
start third.exe -p 10090
start push.exe -p 10070
start user.exe -p 10010
+13 -1
View File
@@ -38,7 +38,6 @@ fi
bin_dir="$OPENIM_ROOT/_output/bin"
logs_dir="$OPENIM_ROOT/logs"
sdk_db_dir="$OPENIM_ROOT/sdk/db/"
if [ ! -d "$bin_dir" ]; then
mkdir -p "$bin_dir"
@@ -78,6 +77,19 @@ need_to_start_server_shell=(
start_cron.sh
)
component_check=start_component_check.sh
echo -e ""
chmod +x $component_check
echo -e "=========> ${BACKGROUND_GREEN}Executing ${component_check}...${COLOR_SUFFIX}"
echo -e ""
./$component_check
if [ $? -ne 0 ]; then
# Print error message and exit
echo -e "${BOLD_PREFIX}${RED_PREFIX}Error executing ${component_check}. Exiting...${COLOR_SUFFIX}"
exit -1
fi
# Loop through the script names and execute them
for i in ${need_to_start_server_shell[*]}; do
chmod +x $i
+42
View File
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#Include shell font styles and some basic information
SCRIPTS_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
#Include shell font styles and some basic information
source $SCRIPTS_ROOT/style_info.sh
source $SCRIPTS_ROOT/path_info.sh
source $SCRIPTS_ROOT/function.sh
echo -e "${YELLOW_PREFIX}=======>SCRIPTS_ROOT=$SCRIPTS_ROOT${COLOR_SUFFIX}"
echo -e "${YELLOW_PREFIX}=======>OPENIM_ROOT=$OPENIM_ROOT${COLOR_SUFFIX}"
echo -e "${YELLOW_PREFIX}=======>pwd=$PWD${COLOR_SUFFIX}"
bin_dir="$BIN_DIR"
logs_dir="$OPENIM_ROOT/logs"
cd ${component_check_binary_root}
echo -e "${YELLOW_PREFIX}=======>$PWD${COLOR_SUFFIX}"
cmd="./${component_check}"
echo "==========================start components checking===========================">>$OPENIM_ROOT/logs/openIM.log
$cmd
if [ $? -ne 0 ]; then
exit 1
fi
+1 -1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,7 +31,6 @@ echo -e "${YELLOW_PREFIX}=======>pwd=$PWD${COLOR_SUFFIX}"
bin_dir="$BIN_DIR"
logs_dir="$OPENIM_ROOT/logs"
sdk_db_dir="$OPENIM_ROOT/sdk/db/"
#Check if the service exists
#If it is exists,kill this process
+1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
+1 -1
View File
@@ -29,7 +29,7 @@ cd "$SCRIPTS_ROOT"
for i in ${service_names[*]}; do
#Check whether the service exists
name="ps |grep -w $i |grep -v grep"
name="ps -aux |grep -w $i |grep -v grep"
count="${name}| wc -l"
if [ $(eval ${count}) -gt 0 ]; then
pid="${name}| awk '{print \$2}'"
+1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
+186
View File
@@ -0,0 +1,186 @@
#!/usr/bin/env bash
# Copyright 2020 Lingfei Kong <colin404@foxmail.com>. All rights reserved.
# Use of this source code is governed by a MIT style
# license that can be found in the LICENSE file.
# Use this script to test if a given TCP host/port are available
WAITFORIT_cmdname=${0##*/}
openim_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
source "${openim_root}/scripts/lib/color.sh"
echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then info "$@" 1>&2; fi }
usage()
{
cat << USAGE >&2
Usage:
$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST Host or IP under test
-p PORT | --port=PORT TCP port under test
Alternatively, you specify the host and port as host:port
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGE
exit 1
}
function wait_for()
{
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
else
echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
fi
WAITFORIT_start_ts=$(date +%s)
while :
do
if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
nc -z $WAITFORIT_HOST $WAITFORIT_PORT
WAITFORIT_result=$?
else
(echo > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
WAITFORIT_result=$?
fi
if [[ $WAITFORIT_result -eq 0 ]]; then
WAITFORIT_end_ts=$(date +%s)
echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
break
fi
sleep 1
done
return $WAITFORIT_result
}
function wait_for_wrapper()
{
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
else
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
fi
WAITFORIT_PID=$!
trap "kill -INT -$WAITFORIT_PID" INT
wait $WAITFORIT_PID
WAITFORIT_RESULT=$?
if [[ $WAITFORIT_RESULT -ne 0 ]]; then
echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
fi
return $WAITFORIT_RESULT
}
# process arguments
while [[ $# -gt 0 ]]
do
case "$1" in
*:* )
WAITFORIT_hostport=(${1//:/ })
WAITFORIT_HOST=${WAITFORIT_hostport[0]}
WAITFORIT_PORT=${WAITFORIT_hostport[1]}
shift 1
;;
--child)
WAITFORIT_CHILD=1
shift 1
;;
-q | --quiet)
WAITFORIT_QUIET=1
shift 1
;;
-s | --strict)
WAITFORIT_STRICT=1
shift 1
;;
-h)
WAITFORIT_HOST="$2"
if [[ $WAITFORIT_HOST == "" ]]; then break; fi
shift 2
;;
--host=*)
WAITFORIT_HOST="${1#*=}"
shift 1
;;
-p)
WAITFORIT_PORT="$2"
if [[ $WAITFORIT_PORT == "" ]]; then break; fi
shift 2
;;
--port=*)
WAITFORIT_PORT="${1#*=}"
shift 1
;;
-t)
WAITFORIT_TIMEOUT="$2"
if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
shift 2
;;
--timeout=*)
WAITFORIT_TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
WAITFORIT_CLI=("$@")
break
;;
--help)
usage
;;
*)
warn "Unknown argument: $1"
usage
;;
esac
done
if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
echoerr "Error: you need to provide a host and port to test."
usage
fi
WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}
# check to see if timeout is from busybox?
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
WAITFORIT_ISBUSY=1
WAITFORIT_BUSYTIMEFLAG="-t"
else
WAITFORIT_ISBUSY=0
WAITFORIT_BUSYTIMEFLAG=""
fi
if [[ $WAITFORIT_CHILD -gt 0 ]]; then
wait_for
WAITFORIT_RESULT=$?
exit $WAITFORIT_RESULT
else
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
wait_for_wrapper
WAITFORIT_RESULT=$?
else
wait_for
WAITFORIT_RESULT=$?
fi
fi
if [[ $WAITFORIT_CLI != "" ]]; then
if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
exit $WAITFORIT_RESULT
fi
exec "${WAITFORIT_CLI[@]}"
else
exit $WAITFORIT_RESULT
fi
+274
View File
@@ -0,0 +1,274 @@
#!/bin/bash
# Copyright 2020 Lingfei Kong <colin404@foxmail.com>. All rights reserved.
# Use of this source code is governed by a MIT style
# license that can be found in the LICENSE file.
: << EOF
The API performance test script automatically executes wrk commands, collects data, analyzes it, and calls gnuplot to plot it
Usage (to test API performance) :
Start the openim-api(port 10002)
Execute the test script: ./wrktest.sh
The script will generate the data file.dat, each column meaning: concurrency QPS average response time success rate
Usage (Compare the results of 2 tests)
1. The performance test:. / wrktest. Sh openim apiserver - http://127.0.0.1:10002/healthz
Execute the command:./wrktest.sh diff apiserver.dat http.dat
&gt; Note: Make sure you have wrk and gnuplot installed on your system
EOF
openim_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
wrkdir="${openim_root}/_output/wrk"
jobname="openim-api"
duration="300s"
threads=$((3 * `grep -c processor /proc/cpuinfo`))
source "${openim_root}/scripts/lib/color.sh"
# Set wrk options
openim::wrk::setup() {
#concurrent="200 500 1000 3000 5000 10000 15000 20000 25000 50000 100000 200000 500000 1000000"
concurrent="200 500 1000 3000 5000 10000 15000 20000 25000 50000"
cmd="wrk -t${threads} -d${duration} -T30s --latency"
}
# Print usage infomation
openim::wrk::usage()
{
cat << EOF
Usage: $0 [OPTION] [diff] URL
Performance automation test script.
URL HTTP request url, like: http://127.0.0.1:10002/healthz
diff Compare two performance test results
OPTIONS:
-h Usage information
-n Performance test task name, default: apiserver
-d Directory used to store performance data and gnuplot graphic, default: _output/wrk
Reprot bugs to <3293172751nss@gmail.com>.
EOF
}
# Convert plot data to useable data
function openim::wrk::convert_plot_data()
{
echo "$1" | awk -v datfile="${wrkdir}/${datfile}" ' {
if ($0 ~ "Running") {
common_time=$2
}
if ($0 ~ "connections") {
connections=$4
common_threads=$1
}
if ($0 ~ "Latency ") {
avg_latency=convertLatency($2)
}
if ($0 ~ "50%") {
p50=convertLatency($2)
}
if ($0 ~ "75%") {
p75=convertLatency($2)
}
if ($0 ~ "90%") {
p90=convertLatency($2)
}
if ($0 ~ "99%") {
p99=convertLatency($2)
}
if ($0 ~ "Requests/sec") {
qps=$2
}
if ($0 ~ "requests in") {
allrequest=$1
}
if ($0 ~ "Socket errors") {
err=$4+$6+$8+$10
}
}
END {
rate=sprintf("%.2f", (allrequest-err)*100/allrequest)
print connections,qps,avg_latency,rate >> datfile
}
function convertLatency(s) {
if (s ~ "us") {
sub("us", "", s)
return s/1000
}
if (s ~ "ms") {
sub("ms", "", s)
return s
}
if (s ~ "s") {
sub("s", "", s)
return s * 1000
}
}'
}
# Remove existing data file
function openim::wrk::prepare()
{
rm -f ${wrkdir}/${datfile}
}
# Plot according to gunplot data file
function openim::wrk::plot() {
gnuplot << EOF
set terminal png enhanced #输出格式为png文件
set ylabel 'QPS'
set xlabel 'Concurrent'
set y2label 'Average Latency (ms)'
set key top left vertical noreverse spacing 1.2 box
set tics out nomirror
set border 3 front
set style line 1 linecolor rgb '#00ff00' linewidth 2 linetype 3 pointtype 2
set style line 2 linecolor rgb '#ff0000' linewidth 1 linetype 3 pointtype 2
set style data linespoints
set grid #显示网格
set xtics nomirror rotate #by 90#只需要一个x轴
set mxtics 5
set mytics 5 #可以增加分刻度
set ytics nomirror
set y2tics
set autoscale y
set autoscale y2
set output "${wrkdir}/${qpsttlb}" #指定数据文件名称
set title "QPS & TTLB\nRunning: ${duration}\nThreads: ${threads}"
plot "${wrkdir}/${datfile}" using 2:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE0000" axis x1y1 t "QPS","${wrkdir}/${datfile}" using 3:xticlabels(1) w lp pt 5 ps 1 lc rgbcolor "#0000CD" axis x2y2 t "Avg Latency (ms)"
unset y2tics
unset y2label
set ytics nomirror
set yrange[0:100]
set output "${wrkdir}/${successrate}" #指定数据文件名称
set title "Success Rate\nRunning: ${duration}\nThreads: ${threads}"
plot "${wrkdir}/${datfile}" using 4:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#F62817" t "Success Rate"
EOF
}
# Plot diff graphic
function openim::wrk::plot_diff()
{
gnuplot << EOF
set terminal png enhanced #输出格式为png文件
set xlabel 'Concurrent'
set ylabel 'QPS'
set y2label 'Average Latency (ms)'
set key below left vertical noreverse spacing 1.2 box autotitle columnheader
set tics out nomirror
set border 3 front
set style line 1 linecolor rgb '#00ff00' linewidth 2 linetype 3 pointtype 2
set style line 2 linecolor rgb '#ff0000' linewidth 1 linetype 3 pointtype 2
set style data linespoints
#set border 3 lt 3 lw 2 #这会让你的坐标图的border更好看
set grid #显示网格
set xtics nomirror rotate #by 90#只需要一个x轴
set mxtics 5
set mytics 5 #可以增加分刻度
set ytics nomirror
set y2tics
#set pointsize 0.4 #点的像素大小
#set datafile separator '\t' #数据文件的字段用\t分开
set autoscale y
set autoscale y2
#设置图像的大小 为标准大小的2倍
#set size 2.3,2
set output "${wrkdir}/${t1}_${t2}.qps.ttlb.diff.png" #指定数据文件名称
set title "QPS & TTLB\nRunning: ${duration}\nThreads: ${threads}"
plot "/tmp/plot_diff.dat" using 2:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE0000" axis x1y1 t "${t1} QPS","/tmp/plot_diff.dat" using 5:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE82EE" axis x1y1 t "${t2} QPS","/tmp/plot_diff.dat" using 3:xticlabels(1) w lp pt 5 ps 1 lc rgbcolor "#0000CD" axis x2y2 t "${t1} Avg Latency (ms)", "/tmp/plot_diff.dat" using 6:xticlabels(1) w lp pt 5 ps 1 lc rgbcolor "#6495ED" axis x2y2 t "${t2} Avg Latency (ms)"
unset y2tics
unset y2label
set ytics nomirror
set yrange[0:100]
set output "${wrkdir}/${t1}_${t2}.successrate.diff.png" #指定数据文件名称
set title "Success Rate\nRunning: ${duration}\nThreads: ${threads}"
plot "/tmp/plot_diff.dat" using 4:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE0000" t "${t1} Success Rate","/tmp/plot_diff.dat" using 7:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE82EE" t "${t2} Success Rate"
EOF
}
# Start API performance testing
openim::wrk::start_performance_test() {
openim::wrk::prepare
for c in ${concurrent}
do
wrkcmd="${cmd} -c ${c} $1"
echo "Running wrk command: ${wrkcmd}"
result=`eval ${wrkcmd}`
openim::wrk::convert_plot_data "${result}"
done
echo -e "\nNow plot according to ${COLOR_MAGENTA}${wrkdir}/${datfile}${COLOR_NORMAL}"
openim::wrk::plot &> /dev/null
echo -e "QPS graphic file is: ${COLOR_MAGENTA}${wrkdir}/${qpsttlb}${COLOR_NORMAL}
Success rate graphic file is: ${COLOR_MAGENTA}${wrkdir}/${successrate}${COLOR_NORMAL}"
}
while getopts "hd:n:" opt;do
case ${opt} in
d)
wrkdir=${OPTARG}
;;
n)
jobname=${OPTARG}
;;
?)
openim::wrk::usage
exit 0
;;
esac
done
shift $(($OPTIND-1))
mkdir -p ${wrkdir}
case $1 in
"diff")
if [ "$#" -lt 3 ];then
openim::wrk::usage
exit 0
fi
t1=$(basename $2|sed 's/.dat//g') # 对比图中红色线条名称
t2=$(basename $3|sed 's/.dat//g') # 对比图中粉色线条名称
join $2 $3 > /tmp/plot_diff.dat
openim::wrk::plot_diff `basename $2` `basename $3`
exit 0
;;
*)
if [ "$#" -lt 1 ];then
openim::wrk::usage
exit 0
fi
url="$1"
qpsttlb="${jobname}_qps_ttlb.png"
successrate="${jobname}_successrate.png"
datfile="${jobname}.dat"
openim::wrk::setup
openim::wrk::start_performance_test "${url}"
;;
esac
+45
View File
@@ -0,0 +1,45 @@
# Notes about go workspace
As openim is using go1.18's [workspace feature](https://go.dev/doc/tutorial/workspaces), once you add a new module, you need to run `go work use -r .` at root directory to update the workspace synced.
### Create a new extensions
1. Create your tools_name directory in pkg `/tools` first and cd into it.
2. Init the project.
3. Then `go work use -r .` at current directory to update the workspace.
4. Create your tools
You can execute the following commands to do things above:
```bash
# 4dd91a700d3f:/openim# tree
# .
# ├── LICENSE
# ├── README.md
# ├── openim-chat
# │ ├── bin
# │ ├── config
# │ ├── logs
# │ └── scripts
# ├── openim-server
# │ ├── bin
# │ ├── config
# │ ├── logs
# │ └── scripts
# ├── openkf
# │ ├── bin
# │ ├── config
# │ ├── logs
# │ └── scripts
# cd tools_code_dir
# edit the CRD_NAME and CRD_GROUP to your own
export OPENIM_TOOLS_NAME=<Changeme>
# copy and paste to create a new CRD and Controller
mkdir tools/${OPENIM_TOOLS_NAME}
cd tools/${OPENIM_TOOLS_NAME}
go mod init github.com/OpenIMSDK/Open-IM-Server/tools/${OPENIM_TOOLS_NAME}
go mod tidy
go work use -r .
cd ../..
```
+3
View File
@@ -0,0 +1,3 @@
module github.com/OpenIMSDK/Open-IM-Server/tools/component
go 1.19
+310
View File
@@ -0,0 +1,310 @@
package main
import (
"context"
"database/sql"
"fmt"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/config"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/utils"
"github.com/Shopify/sarama"
"github.com/go-zookeeper/zk"
"github.com/minio/minio-go/v7"
"github.com/redis/go-redis/v9"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
"gopkg.in/yaml.v3"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"net"
"net/url"
"os"
"strings"
"time"
"github.com/minio/minio-go/v7/pkg/credentials"
)
const (
cfgPath = "../../../../../config/config.yaml"
minioHealthCheckDuration = 1
maxRetry = 100
componentStartErrCode = 6000
configErrCode = 6001
)
var (
ErrComponentStart = errs.NewCodeError(componentStartErrCode, "ComponentStartErr")
ErrConfig = errs.NewCodeError(configErrCode, "Config file is incorrect")
)
func initCfg() error {
data, err := os.ReadFile(cfgPath)
if err != nil {
return err
}
if err = yaml.Unmarshal(data, &config.Config); err != nil {
return err
}
return nil
}
func main() {
err := initCfg()
if err != nil {
fmt.Printf("Read config failed: %v", err.Error())
}
for i := 0; i < maxRetry; i++ {
if i != 0 {
time.Sleep(3 * time.Second)
}
fmt.Printf("Checking components Round %v......\n", i+1)
// Check MySQL
if err := checkMysql(); err != nil {
errorPrint(fmt.Sprintf("Starting Mysql failed: %v. Please make sure your mysql service has started", err.Error()))
continue
} else {
successPrint(fmt.Sprint("Mysql starts successfully"))
}
// Check MongoDB
if err := checkMongo(); err != nil {
errorPrint(fmt.Sprintf("Starting Mongo failed: %v. Please make sure your monngo service has started", err.Error()))
continue
} else {
successPrint(fmt.Sprint("Mongo starts successfully"))
}
// Check Minio
if err := checkMinio(); err != nil {
if index := strings.Index(err.Error(), utils.IntToString(configErrCode)); index != -1 {
successPrint(fmt.Sprint("Minio starts successfully"))
warningPrint(fmt.Sprintf("%v. Please modify your config file", err.Error()))
} else {
errorPrint(fmt.Sprintf("Starting Minio failed: %v. Please make sure your Minio service has started", err.Error()))
continue
}
} else {
successPrint(fmt.Sprint("Minio starts successfully"))
}
// Check Redis
if err := checkRedis(); err != nil {
errorPrint(fmt.Sprintf("Starting Redis failed: %v.Please make sure your Redis service has started", err.Error()))
continue
} else {
successPrint(fmt.Sprint("Redis starts successfully"))
}
// Check Zookeeper
if err := checkZookeeper(); err != nil {
errorPrint(fmt.Sprintf("Starting Zookeeper failed: %v.Please make sure your Zookeeper service has started", err.Error()))
continue
} else {
successPrint(fmt.Sprint("Zookeeper starts successfully"))
}
// Check Kafka
if err := checkKafka(); err != nil {
errorPrint(fmt.Sprintf("Starting Kafka failed: %v.Please make sure your Kafka service has started", err.Error()))
continue
} else {
successPrint(fmt.Sprint("Kafka starts successfully"))
}
successPrint(fmt.Sprint("All components starts successfully"))
os.Exit(0)
}
os.Exit(1)
}
func exactIP(urll string) string {
u, _ := url.Parse(urll)
host, _, err := net.SplitHostPort(u.Host)
if err != nil {
host = u.Host
}
if strings.HasSuffix(host, ":") {
host = host[0 : len(host)-1]
}
return host
}
func checkMysql() error {
var sqlDB *sql.DB
defer func() {
if sqlDB != nil {
sqlDB.Close()
}
}()
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
config.Config.Mysql.Username, config.Config.Mysql.Password, config.Config.Mysql.Address[0], "mysql")
db, err := gorm.Open(mysql.Open(dsn), nil)
if err != nil {
return err
} else {
sqlDB, err = db.DB()
err = sqlDB.Ping()
if err != nil {
return err
}
}
return nil
}
func checkMongo() error {
var client *mongo.Client
defer func() {
if client != nil {
client.Disconnect(context.TODO())
}
}()
mongodbHosts := ""
for i, v := range config.Config.Mongo.Address {
if i == len(config.Config.Mongo.Address)-1 {
mongodbHosts += v
} else {
mongodbHosts += v + ","
}
}
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(
fmt.Sprintf("mongodb://%v:%v@%v/?authSource=admin",
config.Config.Mongo.Username, config.Config.Mongo.Password, mongodbHosts)))
if err != nil {
return err
} else {
err = client.Ping(context.TODO(), &readpref.ReadPref{})
if err != nil {
return err
}
}
return nil
}
func checkMinio() error {
if config.Config.Object.Enable == "minio" {
conf := config.Config.Object.Minio
u, _ := url.Parse(conf.Endpoint)
minioClient, err := minio.New(u.Host, &minio.Options{
Creds: credentials.NewStaticV4(conf.AccessKeyID, conf.SecretAccessKey, ""),
Secure: u.Scheme == "https",
})
if err != nil {
return err
}
cancel, err := minioClient.HealthCheck(time.Duration(minioHealthCheckDuration) * time.Second)
defer func() {
if cancel != nil {
cancel()
}
}()
if err != nil {
return err
} else {
if minioClient.IsOffline() {
return ErrComponentStart.Wrap("Minio server is offline")
}
}
if exactIP(config.Config.Object.ApiURL) == "127.0.0.1" || exactIP(config.Config.Object.Minio.Endpoint) == "127.0.0.1" {
return ErrConfig.Wrap("apiURL or Minio endpoint contain 127.0.0.1.")
}
}
return nil
}
func checkRedis() error {
var redisClient redis.UniversalClient
defer func() {
if redisClient != nil {
redisClient.Close()
}
}()
if len(config.Config.Redis.Address) > 1 {
redisClient = redis.NewClusterClient(&redis.ClusterOptions{
Addrs: config.Config.Redis.Address,
Username: config.Config.Redis.Username,
Password: config.Config.Redis.Password,
})
} else {
redisClient = redis.NewClient(&redis.Options{
Addr: config.Config.Redis.Address[0],
Username: config.Config.Redis.Username,
Password: config.Config.Redis.Password,
})
}
_, err := redisClient.Ping(context.Background()).Result()
if err != nil {
return err
}
return nil
}
func checkZookeeper() error {
var c *zk.Conn
defer func() {
if c != nil {
c.Close()
}
}()
c, _, err := zk.Connect(config.Config.Zookeeper.ZkAddr, time.Second)
if err != nil {
return err
} else {
if config.Config.Zookeeper.Username != "" && config.Config.Zookeeper.Password != "" {
if err := c.AddAuth("digest", []byte(config.Config.Zookeeper.Username+":"+config.Config.Zookeeper.Password)); err != nil {
return err
}
}
_, _, err = c.Get("/")
if err != nil {
return err
}
}
return nil
}
func checkKafka() error {
var kafkaClient sarama.Client
defer func() {
if kafkaClient != nil {
kafkaClient.Close()
}
}()
cfg := sarama.NewConfig()
if config.Config.Kafka.Username != "" && config.Config.Kafka.Password != "" {
cfg.Net.SASL.Enable = true
cfg.Net.SASL.User = config.Config.Kafka.Username
cfg.Net.SASL.Password = config.Config.Kafka.Password
}
kafkaClient, err := sarama.NewClient(config.Config.Kafka.Addr, cfg)
if err != nil {
return err
} else {
topics, err := kafkaClient.Topics()
if err != nil {
return err
}
if !utils.IsContain(config.Config.Kafka.MsgToMongo.Topic, topics) {
return ErrComponentStart.Wrap(fmt.Sprintf("kafka doesn't contain topic:%v", config.Config.Kafka.MsgToMongo.Topic))
}
if !utils.IsContain(config.Config.Kafka.MsgToPush.Topic, topics) {
return ErrComponentStart.Wrap(fmt.Sprintf("kafka doesn't contain topic:%v", config.Config.Kafka.MsgToPush.Topic))
}
if !utils.IsContain(config.Config.Kafka.LatestMsgToRedis.Topic, topics) {
return ErrComponentStart.Wrap(fmt.Sprintf("kafka doesn't contain topic:%v", config.Config.Kafka.LatestMsgToRedis.Topic))
}
}
return nil
}
func errorPrint(s string) {
fmt.Printf("\x1b[%dm%v\x1b[0m\n", 31, s)
}
func successPrint(s string) {
fmt.Printf("\x1b[%dm%v\x1b[0m\n", 32, s)
}
func warningPrint(s string) {
fmt.Printf("\x1b[%dmWarning: But %v\x1b[0m\n", 33, s)
}
+3
View File
@@ -0,0 +1,3 @@
module github.com/OpenIMSDK/Open-IM-Server/tools/infra
go 1.20
+26
View File
@@ -0,0 +1,26 @@
package main
import (
"fmt"
"log"
)
func main() {
log.Println("Current module is still under development.")
message := `
Current module is still under development.
____ _____ __ __
/ __ \ |_ _|| \/ |
| | | | _ __ ___ _ __ | | | \ / |
| | | || '_ \ / _ \| '_ \ | | | |\/| |
| |__| || |_) || __/| | | | _| |_ | | | |
\____/ | .__/ \___||_| |_||_____||_| |_|
| |
|_|
Keep checking for updates!
`
fmt.Println(message)
}
+5
View File
@@ -0,0 +1,5 @@
module github.com/OpenIMSDK/Open-IM-Server/tools/ncpu
go 1.20
require go.uber.org/automaxprocs v1.5.3
+7
View File
@@ -0,0 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

Some files were not shown because too many files have changed in this diff Show More