From 0efc235f45377d997d283557b1f61acf922f9ab3 Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Thu, 30 Nov 2023 10:10:48 +0800
Subject: [PATCH 001/110] add webhooks (#1465)
* add callback before join group
* fix bug
* fix deployments/templates/alertmanager.yml
* fix bug
* update callback after join group
* merge callback after join group
* update callback setrgoup info
* test
* test
* test
* update three functions in friend category
* test friend and blacklist
* test
* test
* test
* Update openim.yaml
* merge callback after join group
* merge callback after join group
* merge callback after join group
* fix callbackbeforesetgroupinfo
* fix eventtime
* update api request required
* update api request required
* update api request required
* delete unused code
* delete unused code
* fix
* Update .env
* Update .env
* Update callback.go
* Update callback.go
* Update .env
* Update .env
* fix: merge
* update
* fix: merge
* fix: fix bugs
* update callback enable
* update callback enable
* update callback enable
* update callback enable
* update callback enable
* update callback enable
* Update openim.yaml
* Update environment.sh
* Update environment.md
* Update environment.md
* Update environment.sh
---------
Co-authored-by: Gordon <1432970085@qq.com>
---
.env | 11 +-
cmd/openim-msggateway/main.go | 1 +
config/alertmanager.yml | 2 +-
config/config.yaml | 4 +
deployments/templates/alertmanager.yml | 4 +-
deployments/templates/openim.yaml | 67 ++++++++++-
docs/contrib/environment.md | 2 +-
go.mod | 2 +-
go.sum | 4 +-
internal/api/msg.go | 14 +--
internal/msggateway/n_ws_server.go | 1 +
internal/rpc/friend/black.go | 6 +
internal/rpc/friend/callback.go | 117 ++++++++++++++++++-
internal/rpc/friend/friend.go | 18 ++-
internal/rpc/group/callback.go | 156 ++++++++++++++++++++++++-
internal/rpc/group/group.go | 18 +++
internal/rpc/msg/callback.go | 26 ++++-
internal/rpc/msg/revoke.go | 4 +
internal/rpc/user/callback.go | 4 +-
pkg/apistruct/msg.go | 73 ++++++------
pkg/callbackstruct/constant.go | 18 ++-
pkg/callbackstruct/friend.go | 77 ++++++++++--
pkg/callbackstruct/group.go | 117 +++++++++++--------
pkg/callbackstruct/message.go | 20 ----
pkg/callbackstruct/revoke.go | 11 ++
pkg/common/config/config.go | 15 ++-
scripts/install/environment.sh | 3 +-
27 files changed, 642 insertions(+), 153 deletions(-)
create mode 100644 pkg/callbackstruct/revoke.go
diff --git a/.env b/.env
index ae76a0440..8213b9e3c 100644
--- a/.env
+++ b/.env
@@ -94,7 +94,7 @@ OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.10
# Address or hostname for the Prometheus network.
# Default: PROMETHEUS_NETWORK_ADDRESS=172.28.0.11
PROMETHEUS_NETWORK_ADDRESS=172.28.0.11
-
+
# Address or hostname for the Grafana network.
# Default: GRAFANA_NETWORK_ADDRESS=172.28.0.12
GRAFANA_NETWORK_ADDRESS=172.28.0.12
@@ -106,7 +106,10 @@ NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.13
# Address or hostname for the OpenIM admin network.
# Default: OPENIM_ADMIN_NETWORK_ADDRESS=172.28.0.14
OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=172.28.0.14
-
+
+# Address or hostname for the alertmanager network.
+# Default: ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.14
+ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.14
# ===============================================
# = Component Extension Configuration =
# ===============================================
@@ -306,3 +309,7 @@ GRAFANA_PORT=3000
# Port for the admin front.
# Default: OPENIM_ADMIN_FRONT_PORT=11002
OPENIM_ADMIN_FRONT_PORT=11002
+
+# Port for the alertmanager.
+# Default: ALERT_MANAGER_PORT=19093
+ALERT_MANAGER_PORT=19093
diff --git a/cmd/openim-msggateway/main.go b/cmd/openim-msggateway/main.go
index f6870694b..6d212e467 100644
--- a/cmd/openim-msggateway/main.go
+++ b/cmd/openim-msggateway/main.go
@@ -23,6 +23,7 @@ func main() {
msgGatewayCmd.AddWsPortFlag()
msgGatewayCmd.AddPortFlag()
msgGatewayCmd.AddPrometheusPortFlag()
+
if err := msgGatewayCmd.Exec(); err != nil {
panic(err.Error())
}
diff --git a/config/alertmanager.yml b/config/alertmanager.yml
index 71cdd2b8f..ee14b6464 100644
--- a/config/alertmanager.yml
+++ b/config/alertmanager.yml
@@ -26,7 +26,7 @@ route:
receivers:
- name: email
email_configs:
- - to: {EMAIL_TO:-'alert@example.com'}
+ - to: '{EMAIL_TO:-'alert@example.com'}'
html: '{{ template "email.to.html" . }}'
headers: { Subject: "[OPENIM-SERVER]Alarm" }
send_resolved: true
diff --git a/config/config.yaml b/config/config.yaml
index e8995c82b..b17d10073 100644
--- a/config/config.yaml
+++ b/config/config.yaml
@@ -375,6 +375,10 @@ callback:
enable: false
timeout: 5
failedContinue: true
+ beforeInviteUserToGroup:
+ enable: true
+ timeout: 5
+ failedContinue: true
beforeSetGroupMemberInfo:
enable: false
timeout: 5
diff --git a/deployments/templates/alertmanager.yml b/deployments/templates/alertmanager.yml
index 47090f148..ea99a9286 100644
--- a/deployments/templates/alertmanager.yml
+++ b/deployments/templates/alertmanager.yml
@@ -27,7 +27,7 @@ route:
receivers:
- name: email
email_configs:
- - to: ${ALERTMANAGER_EMAIL_TO}
+ - to: '${ALERTMANAGER_EMAIL_TO}'
html: '{{ template "email.to.html" . }}'
headers: { Subject: "[OPENIM-SERVER]Alarm" }
- send_resolved: true
\ No newline at end of file
+ send_resolved: true
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index fde05e86e..fc90bfc2f 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -320,7 +320,7 @@ iosPush:
# Timeout in seconds
# Whether to continue execution if callback fails
callback:
- url:
+ url: ""
beforeSendSingleMsg:
enable: ${CALLBACK_ENABLE}
timeout: ${CALLBACK_TIMEOUT}
@@ -389,6 +389,10 @@ callback:
enable: ${CALLBACK_ENABLE}
timeout: ${CALLBACK_TIMEOUT}
failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ afterSetGroupMemberInfo:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
setMessageReactionExtensions:
enable: ${CALLBACK_ENABLE}
timeout: ${CALLBACK_TIMEOUT}
@@ -441,7 +445,66 @@ callback:
enable: ${CALLBACK_ENABLE}
timeout: ${CALLBACK_TIMEOUT}
failedContinue: ${CALLBACK_FAILED_CONTINUE}
-
+ afterGroupMsgRead:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ afterGroupMsgRevoke:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ afterJoinGroup:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ beforeInviteUserToGroup:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ joinGroupAfter:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ setGroupInfoAfter:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ setGroupInfoBefore:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ revokeMsgAfter:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ addBlackBefore:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ addFriendAfter:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ addFriendAgreeBefore:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ deleteFriendAfter:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ importFriendsBefore:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ importFriendsAfter:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ removeBlackAfter:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
###################### Prometheus ######################
# Prometheus configuration for various services
# The number of Prometheus ports per service needs to correspond to rpcPort
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index 6450549e7..0279c750e 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -501,7 +501,7 @@ This section involves setting up additional configuration variables for Websocke
| TOKEN_EXPIRE | "90" | Token Expiry Time |
| FRIEND_VERIFY | "false" | Friend Verification Enable |
| IOS_PUSH_SOUND | "xxx" | iOS |
-| CALLBACK_ENABLE | "true" | Enable callback | | | |
+| CALLBACK_ENABLE | "false" | Enable callback |
| CALLBACK_TIMEOUT | "5" | Maximum timeout for callback call |
| CALLBACK_FAILED_CONTINUE| "true" | fails to continue to the next step |
### 2.20. Prometheus Configuration
diff --git a/go.mod b/go.mod
index fc7c615c6..8d767dbc1 100644
--- a/go.mod
+++ b/go.mod
@@ -38,7 +38,7 @@ require github.com/google/uuid v1.3.1
require (
github.com/IBM/sarama v1.41.3
github.com/OpenIMSDK/protocol v0.0.31
- github.com/OpenIMSDK/tools v0.0.16
+ github.com/OpenIMSDK/tools v0.0.17
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/go-redis/redis v6.15.9+incompatible
github.com/go-sql-driver/mysql v1.7.1
diff --git a/go.sum b/go.sum
index 10cb9ee8c..640b11e89 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,8 @@ github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
github.com/OpenIMSDK/protocol v0.0.31 h1:ax43x9aqA6EKNXNukS5MT5BSTqkUmwO4uTvbJLtzCgE=
github.com/OpenIMSDK/protocol v0.0.31/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.16 h1:te/GIq2imCMsrRPgU9OObYKbzZ3rT08Lih/o+3QFIz0=
-github.com/OpenIMSDK/tools v0.0.16/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/OpenIMSDK/tools v0.0.17 h1:1E1HUOL2W09YUHBb4wBwrXoTSZm5ONVwLxlEX1GhlKw=
+github.com/OpenIMSDK/tools v0.0.17/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
diff --git a/internal/api/msg.go b/internal/api/msg.go
index 38e207cfb..67b5f1eff 100644
--- a/internal/api/msg.go
+++ b/internal/api/msg.go
@@ -15,14 +15,6 @@
package api
import (
- "github.com/OpenIMSDK/tools/mcontext"
- "github.com/gin-gonic/gin"
- "github.com/go-playground/validator/v10"
- "github.com/mitchellh/mapstructure"
-
- "github.com/openimsdk/open-im-server/v3/pkg/authverify"
- "github.com/openimsdk/open-im-server/v3/pkg/common/config"
-
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
@@ -30,7 +22,13 @@ import (
"github.com/OpenIMSDK/tools/apiresp"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
+ "github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
+ "github.com/gin-gonic/gin"
+ "github.com/go-playground/validator/v10"
+ "github.com/mitchellh/mapstructure"
+ "github.com/openimsdk/open-im-server/v3/pkg/authverify"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/apistruct"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go
index 99a7a4805..5a061d7e1 100644
--- a/internal/msggateway/n_ws_server.go
+++ b/internal/msggateway/n_ws_server.go
@@ -121,6 +121,7 @@ func (ws *WsServer) UnRegister(c *Client) {
}
func (ws *WsServer) Validate(s interface{}) error {
+ //?question?
return nil
}
diff --git a/internal/rpc/friend/black.go b/internal/rpc/friend/black.go
index b1a5ea6b5..fee2d5480 100644
--- a/internal/rpc/friend/black.go
+++ b/internal/rpc/friend/black.go
@@ -74,6 +74,9 @@ func (s *friendServer) RemoveBlack(
return nil, err
}
s.notificationSender.BlackDeletedNotification(ctx, req)
+ if err := CallbackAfterRemoveBlack(ctx, req); err != nil {
+ return nil, err
+ }
return &pbfriend.RemoveBlackResp{}, nil
}
@@ -85,6 +88,9 @@ func (s *friendServer) AddBlack(ctx context.Context, req *pbfriend.AddBlackReq)
if err != nil {
return nil, err
}
+ if err := CallbackBeforeAddBlack(ctx, req); err != nil {
+ return nil, err
+ }
black := relation.BlackModel{
OwnerUserID: req.OwnerUserID,
BlockUserID: req.BlackUserID,
diff --git a/internal/rpc/friend/callback.go b/internal/rpc/friend/callback.go
index d3b853ef9..d541071f5 100644
--- a/internal/rpc/friend/callback.go
+++ b/internal/rpc/friend/callback.go
@@ -16,9 +16,8 @@ package friend
import (
"context"
- "github.com/OpenIMSDK/tools/utils"
-
pbfriend "github.com/OpenIMSDK/protocol/friend"
+ "github.com/OpenIMSDK/tools/utils"
cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/http"
@@ -33,6 +32,7 @@ func CallbackBeforeAddFriend(ctx context.Context, req *pbfriend.ApplyToAddFriend
FromUserID: req.FromUserID,
ToUserID: req.ToUserID,
ReqMsg: req.ReqMsg,
+ Ex: req.Ex,
}
resp := &cbapi.CallbackBeforeAddFriendResp{}
if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeAddFriend); err != nil {
@@ -75,3 +75,116 @@ func CallbackAfterSetFriendRemark(ctx context.Context, req *pbfriend.SetFriendRe
}
return nil
}
+func CallbackBeforeAddBlack(ctx context.Context, req *pbfriend.AddBlackReq) error {
+ if !config.Config.Callback.CallbackBeforeAddBlack.Enable {
+ return nil
+ }
+ cbReq := &cbapi.CallbackBeforeAddBlackReq{
+ CallbackCommand: cbapi.CallbackBeforeAddBlackCommand,
+ OwnerUserID: req.OwnerUserID,
+ BlackUserID: req.BlackUserID,
+ }
+ resp := &cbapi.CallbackBeforeAddBlackResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeAddBlack); err != nil {
+ return err
+ }
+ return nil
+}
+func CallbackAfterAddFriend(ctx context.Context, req *pbfriend.ApplyToAddFriendReq) error {
+ if !config.Config.Callback.CallbackAfterAddFriend.Enable {
+ return nil
+ }
+ cbReq := &cbapi.CallbackAfterAddFriendReq{
+ CallbackCommand: cbapi.CallbackAfterAddFriendCommand,
+ FromUserID: req.FromUserID,
+ ToUserID: req.ToUserID,
+ ReqMsg: req.ReqMsg,
+ }
+ resp := &cbapi.CallbackAfterAddFriendResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackAfterAddFriend); err != nil {
+ return err
+ }
+
+ return nil
+}
+func CallbackBeforeAddFriendAgree(ctx context.Context, req *pbfriend.RespondFriendApplyReq) error {
+ if !config.Config.Callback.CallbackBeforeAddFriendAgree.Enable {
+ return nil
+ }
+ cbReq := &cbapi.CallbackBeforeAddFriendAgreeReq{
+ CallbackCommand: cbapi.CallbackBeforeAddFriendAgreeCommand,
+ FromUserID: req.FromUserID,
+ ToUserID: req.ToUserID,
+ HandleMsg: req.HandleMsg,
+ HandleResult: req.HandleResult,
+ }
+ resp := &cbapi.CallbackBeforeAddFriendAgreeResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeAddFriendAgree); err != nil {
+ return err
+ }
+ return nil
+}
+func CallbackAfterDeleteFriend(ctx context.Context, req *pbfriend.DeleteFriendReq) error {
+ if !config.Config.Callback.CallbackAfterDeleteFriend.Enable {
+ return nil
+ }
+ cbReq := &cbapi.CallbackAfterDeleteFriendReq{
+ CallbackCommand: cbapi.CallbackAfterDeleteFriendCommand,
+ OwnerUserID: req.OwnerUserID,
+ FriendUserID: req.FriendUserID,
+ }
+ resp := &cbapi.CallbackAfterDeleteFriendResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackAfterDeleteFriend); err != nil {
+ return err
+ }
+ return nil
+}
+func CallbackBeforeImportFriends(ctx context.Context, req *pbfriend.ImportFriendReq) error {
+ if !config.Config.Callback.CallbackBeforeImportFriends.Enable {
+ return nil
+ }
+ cbReq := &cbapi.CallbackBeforeImportFriendsReq{
+ CallbackCommand: cbapi.CallbackBeforeImportFriendsCommand,
+ OwnerUserID: req.OwnerUserID,
+ FriendUserIDs: req.FriendUserIDs,
+ }
+ resp := &cbapi.CallbackBeforeImportFriendsResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeImportFriends); err != nil {
+ return err
+ }
+ if len(resp.FriendUserIDs) != 0 {
+ req.FriendUserIDs = resp.FriendUserIDs
+ }
+ return nil
+}
+func CallbackAfterImportFriends(ctx context.Context, req *pbfriend.ImportFriendReq) error {
+ if !config.Config.Callback.CallbackAfterImportFriends.Enable {
+ return nil
+ }
+ cbReq := &cbapi.CallbackAfterImportFriendsReq{
+ CallbackCommand: cbapi.CallbackAfterImportFriendsCommand,
+ OwnerUserID: req.OwnerUserID,
+ FriendUserIDs: req.FriendUserIDs,
+ }
+ resp := &cbapi.CallbackAfterImportFriendsResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackAfterImportFriends); err != nil {
+ return err
+ }
+ return nil
+}
+
+func CallbackAfterRemoveBlack(ctx context.Context, req *pbfriend.RemoveBlackReq) error {
+ if !config.Config.Callback.CallbackAfterRemoveBlack.Enable {
+ return nil
+ }
+ cbReq := &cbapi.CallbackAfterRemoveBlackReq{
+ CallbackCommand: cbapi.CallbackAfterRemoveBlackCommand,
+ OwnerUserID: req.OwnerUserID,
+ BlackUserID: req.BlackUserID,
+ }
+ resp := &cbapi.CallbackAfterRemoveBlackResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackAfterRemoveBlack); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index 24014ace1..6e6b6d377 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -103,7 +103,7 @@ func (s *friendServer) ApplyToAddFriend(
if req.ToUserID == req.FromUserID {
return nil, errs.ErrCanNotAddYourself.Wrap()
}
- if err := CallbackBeforeAddFriend(ctx, req); err != nil && err != errs.ErrCallbackContinue {
+ if err = CallbackBeforeAddFriend(ctx, req); err != nil && err != errs.ErrCallbackContinue {
return nil, err
}
if _, err := s.userRpcClient.GetUsersInfoMap(ctx, []string{req.ToUserID, req.FromUserID}); err != nil {
@@ -120,6 +120,9 @@ func (s *friendServer) ApplyToAddFriend(
return nil, err
}
s.notificationSender.FriendApplicationAddNotification(ctx, req)
+ if err = CallbackAfterAddFriend(ctx, req); err != nil && err != errs.ErrCallbackContinue {
+ return nil, err
+ }
return resp, nil
}
@@ -141,6 +144,10 @@ func (s *friendServer) ImportFriends(
if utils.Duplicate(req.FriendUserIDs) {
return nil, errs.ErrArgs.Wrap("friend userID repeated")
}
+ if err := CallbackBeforeImportFriends(ctx, req); err != nil {
+ return nil, err
+ }
+
if err := s.friendDatabase.BecomeFriends(ctx, req.OwnerUserID, req.FriendUserIDs, constant.BecomeFriendByImport); err != nil {
return nil, err
}
@@ -151,6 +158,9 @@ func (s *friendServer) ImportFriends(
HandleResult: constant.FriendResponseAgree,
})
}
+ if err := CallbackAfterImportFriends(ctx, req); err != nil {
+ return nil, err
+ }
return &pbfriend.ImportFriendResp{}, nil
}
@@ -172,6 +182,9 @@ func (s *friendServer) RespondFriendApply(
HandleResult: req.HandleResult,
}
if req.HandleResult == constant.FriendResponseAgree {
+ if err := CallbackBeforeAddFriendAgree(ctx, req); err != nil && err != errs.ErrCallbackContinue {
+ return nil, err
+ }
err := s.friendDatabase.AgreeFriendRequest(ctx, &friendRequest)
if err != nil {
return nil, err
@@ -208,6 +221,9 @@ func (s *friendServer) DeleteFriend(
return nil, err
}
s.notificationSender.FriendDeletedNotification(ctx, req)
+ if err := CallbackAfterDeleteFriend(ctx, req); err != nil {
+ return nil, err
+ }
return resp, nil
}
diff --git a/internal/rpc/group/callback.go b/internal/rpc/group/callback.go
index 13f9737b5..1599cc7b4 100644
--- a/internal/rpc/group/callback.go
+++ b/internal/rpc/group/callback.go
@@ -16,6 +16,7 @@ package group
import (
"context"
+ "github.com/OpenIMSDK/tools/log"
"time"
"github.com/OpenIMSDK/protocol/constant"
@@ -124,7 +125,14 @@ func CallbackBeforeMemberJoinGroup(
GroupEx: groupEx,
}
resp := &callbackstruct.CallbackBeforeMemberJoinGroupResp{}
- if err = http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackBeforeMemberJoinGroup); err != nil {
+ err = http.CallBackPostReturn(
+ ctx,
+ config.Config.Callback.CallbackUrl,
+ callbackReq,
+ resp,
+ config.Config.Callback.CallbackBeforeMemberJoinGroup,
+ )
+ if err != nil {
return err
}
if resp.MuteEndTime != nil {
@@ -159,7 +167,14 @@ func CallbackBeforeSetGroupMemberInfo(ctx context.Context, req *group.SetGroupMe
callbackReq.Ex = &req.Ex.Value
}
resp := &callbackstruct.CallbackBeforeSetGroupMemberInfoResp{}
- if err = http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackBeforeSetGroupMemberInfo); err != nil {
+ err = http.CallBackPostReturn(
+ ctx,
+ config.Config.Callback.CallbackUrl,
+ callbackReq,
+ resp,
+ config.Config.Callback.CallbackBeforeSetGroupMemberInfo,
+ )
+ if err != nil {
return err
}
if resp.FaceURL != nil {
@@ -176,13 +191,12 @@ func CallbackBeforeSetGroupMemberInfo(ctx context.Context, req *group.SetGroupMe
}
return nil
}
-
func CallbackAfterSetGroupMemberInfo(ctx context.Context, req *group.SetGroupMemberInfo) (err error) {
if !config.Config.Callback.CallbackBeforeSetGroupMemberInfo.Enable {
return nil
}
callbackReq := callbackstruct.CallbackAfterSetGroupMemberInfoReq{
- CallbackCommand: callbackstruct.CallbackBeforeSetGroupMemberInfoCommand,
+ CallbackCommand: callbackstruct.CallbackAfterSetGroupMemberInfoCommand,
GroupID: req.GroupID,
UserID: req.UserID,
}
@@ -199,7 +213,7 @@ func CallbackAfterSetGroupMemberInfo(ctx context.Context, req *group.SetGroupMem
callbackReq.Ex = &req.Ex.Value
}
resp := &callbackstruct.CallbackAfterSetGroupMemberInfoResp{}
- if err = http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackBeforeSetGroupMemberInfo); err != nil {
+ if err = http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackAfterSetGroupMemberInfo); err != nil {
return err
}
return nil
@@ -282,3 +296,135 @@ func CallbackTransferGroupOwnerAfter(ctx context.Context, req *pbgroup.TransferG
}
return nil
}
+func CallbackBeforeInviteUserToGroup(ctx context.Context, req *group.InviteUserToGroupReq) (err error) {
+ if !config.Config.Callback.CallbackBeforeInviteUserToGroup.Enable {
+ return nil
+ }
+
+ callbackReq := &callbackstruct.CallbackBeforeInviteUserToGroupReq{
+ CallbackCommand: callbackstruct.CallbackBeforeInviteJoinGroupCommand,
+ OperationID: mcontext.GetOperationID(ctx),
+ GroupID: req.GroupID,
+ Reason: req.Reason,
+ InvitedUserIDs: req.InvitedUserIDs,
+ }
+
+ resp := &callbackstruct.CallbackBeforeInviteUserToGroupResp{}
+ err = http.CallBackPostReturn(
+ ctx,
+ config.Config.Callback.CallbackUrl,
+ callbackReq,
+ resp,
+ config.Config.Callback.CallbackBeforeInviteUserToGroup,
+ )
+
+ if err != nil {
+ return err
+ }
+
+ if len(resp.RefusedMembersAccount) > 0 {
+ // Handle the scenario where certain members are refused
+ // You might want to update the req.Members list or handle it as per your business logic
+ }
+ utils.StructFieldNotNilReplace(req, resp)
+
+ return nil
+}
+
+func CallbackAfterJoinGroup(ctx context.Context, req *group.JoinGroupReq) error {
+ if !config.Config.Callback.CallbackAfterJoinGroup.Enable {
+ return nil
+ }
+ callbackReq := &callbackstruct.CallbackAfterJoinGroupReq{
+ CallbackCommand: callbackstruct.CallbackAfterJoinGroupCommand,
+ OperationID: mcontext.GetOperationID(ctx),
+ GroupID: req.GroupID,
+ ReqMessage: req.ReqMessage,
+ JoinSource: req.JoinSource,
+ InviterUserID: req.InviterUserID,
+ }
+ resp := &callbackstruct.CallbackAfterJoinGroupResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackAfterJoinGroup); err != nil {
+ return err
+ }
+ return nil
+}
+
+func CallbackBeforeSetGroupInfo(ctx context.Context, req *group.SetGroupInfoReq) error {
+ if !config.Config.Callback.CallbackBeforeSetGroupInfo.Enable {
+ return nil
+ }
+ callbackReq := &callbackstruct.CallbackBeforeSetGroupInfoReq{
+ CallbackCommand: callbackstruct.CallbackBeforeSetGroupInfoCommand,
+ GroupID: req.GroupInfoForSet.GroupID,
+ Notification: req.GroupInfoForSet.Notification,
+ Introduction: req.GroupInfoForSet.Introduction,
+ FaceURL: req.GroupInfoForSet.FaceURL,
+ GroupName: req.GroupInfoForSet.GroupName,
+ }
+
+ if req.GroupInfoForSet.Ex != nil {
+ callbackReq.Ex = req.GroupInfoForSet.Ex.Value
+ }
+ log.ZDebug(ctx, "debug CallbackBeforeSetGroupInfo", callbackReq.Ex)
+ if req.GroupInfoForSet.NeedVerification != nil {
+ callbackReq.NeedVerification = req.GroupInfoForSet.NeedVerification.Value
+ }
+ if req.GroupInfoForSet.LookMemberInfo != nil {
+ callbackReq.LookMemberInfo = req.GroupInfoForSet.LookMemberInfo.Value
+ }
+ if req.GroupInfoForSet.ApplyMemberFriend != nil {
+ callbackReq.ApplyMemberFriend = req.GroupInfoForSet.ApplyMemberFriend.Value
+ }
+ resp := &callbackstruct.CallbackBeforeSetGroupInfoResp{}
+
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackBeforeSetGroupInfo); err != nil {
+ return err
+ }
+
+ if resp.Ex != nil {
+ req.GroupInfoForSet.Ex = wrapperspb.String(*resp.Ex)
+ }
+ if resp.NeedVerification != nil {
+ req.GroupInfoForSet.NeedVerification = wrapperspb.Int32(*resp.NeedVerification)
+ }
+ if resp.LookMemberInfo != nil {
+ req.GroupInfoForSet.LookMemberInfo = wrapperspb.Int32(*resp.LookMemberInfo)
+ }
+ if resp.ApplyMemberFriend != nil {
+ req.GroupInfoForSet.ApplyMemberFriend = wrapperspb.Int32(*resp.ApplyMemberFriend)
+ }
+ utils.StructFieldNotNilReplace(req, resp)
+ return nil
+}
+func CallbackAfterSetGroupInfo(ctx context.Context, req *group.SetGroupInfoReq) error {
+ if !config.Config.Callback.CallbackAfterSetGroupInfo.Enable {
+ return nil
+ }
+ callbackReq := &callbackstruct.CallbackAfterSetGroupInfoReq{
+ CallbackCommand: callbackstruct.CallbackAfterSetGroupInfoCommand,
+ GroupID: req.GroupInfoForSet.GroupID,
+ Notification: req.GroupInfoForSet.Notification,
+ Introduction: req.GroupInfoForSet.Introduction,
+ FaceURL: req.GroupInfoForSet.FaceURL,
+ GroupName: req.GroupInfoForSet.GroupName,
+ }
+ if req.GroupInfoForSet.Ex != nil {
+ callbackReq.Ex = &req.GroupInfoForSet.Ex.Value
+ }
+ if req.GroupInfoForSet.NeedVerification != nil {
+ callbackReq.NeedVerification = &req.GroupInfoForSet.NeedVerification.Value
+ }
+ if req.GroupInfoForSet.LookMemberInfo != nil {
+ callbackReq.LookMemberInfo = &req.GroupInfoForSet.LookMemberInfo.Value
+ }
+ if req.GroupInfoForSet.ApplyMemberFriend != nil {
+ callbackReq.ApplyMemberFriend = &req.GroupInfoForSet.ApplyMemberFriend.Value
+ }
+ resp := &callbackstruct.CallbackAfterSetGroupInfoResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackAfterSetGroupInfo); err != nil {
+ return err
+ }
+ utils.StructFieldNotNilReplace(req, resp)
+ return nil
+}
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index 227b7959d..67cd70817 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -366,6 +366,7 @@ func (s *groupServer) GetJoinedGroupList(ctx context.Context, req *pbgroup.GetJo
func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.InviteUserToGroupReq) (*pbgroup.InviteUserToGroupResp, error) {
resp := &pbgroup.InviteUserToGroupResp{}
+
if len(req.InvitedUserIDs) == 0 {
return nil, errs.ErrArgs.Wrap("user empty")
}
@@ -376,6 +377,7 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
if err != nil {
return nil, err
}
+
if group.Status == constant.GroupStatusDismissed {
return nil, errs.ErrDismissedAlready.Wrap()
}
@@ -399,6 +401,10 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
}
groupMember = groupMembers[0]
}
+
+ if err := CallbackBeforeInviteUserToGroup(ctx, req); err != nil {
+ return nil, err
+ }
if group.NeedVerification == constant.AllNeedVerification {
if !authverify.IsAppManagerUid(ctx) {
if !(groupMember.RoleLevel == constant.GroupOwner || groupMember.RoleLevel == constant.GroupAdmin) {
@@ -413,6 +419,7 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
HandledTime: time.Unix(0, 0),
})
}
+
if err := s.GroupDatabase.CreateGroupRequest(ctx, requests); err != nil {
return nil, err
}
@@ -818,6 +825,7 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
case constant.GroupResponseRefuse:
s.Notification.GroupApplicationRejectedNotification(ctx, req)
}
+
return &pbgroup.GroupApplicationResponseResp{}, nil
}
@@ -872,10 +880,14 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
if err := s.GroupDatabase.CreateGroup(ctx, nil, []*relationtb.GroupMemberModel{groupMember}); err != nil {
return nil, err
}
+
if err := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, []string{req.InviterUserID}); err != nil {
return nil, err
}
s.Notification.MemberEnterNotification(ctx, req.GroupID, req.InviterUserID)
+ if err = CallbackAfterJoinGroup(ctx, req); err != nil {
+ return nil, err
+ }
return resp, nil
}
groupRequest := relationtb.GroupRequestModel{
@@ -957,6 +969,9 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
return nil, errs.ErrNoPermission.Wrap("no group owner or admin")
}
}
+ if err := CallbackBeforeSetGroupInfo(ctx, req); err != nil {
+ return nil, err
+ }
group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupInfoForSet.GroupID)
if err != nil {
return nil, err
@@ -1025,6 +1040,9 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
default:
s.Notification.GroupInfoSetNotification(ctx, tips)
}
+ if err := CallbackAfterSetGroupInfo(ctx, req); err != nil {
+ return nil, err
+ }
return resp, nil
}
diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go
index 85c002bf3..4ce5a5443 100644
--- a/internal/rpc/msg/callback.go
+++ b/internal/rpc/msg/callback.go
@@ -24,8 +24,8 @@ import (
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
-
cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
+
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/http"
)
@@ -98,10 +98,10 @@ func callbackAfterSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) err
}
func callbackBeforeSendGroupMsg(ctx context.Context, msg *pbchat.SendMsgReq) error {
- if !config.Config.Callback.CallbackAfterSendSingleMsg.Enable {
+ if !config.Config.Callback.CallbackBeforeSendSingleMsg.Enable {
return nil
}
- req := &cbapi.CallbackAfterSendGroupMsgReq{
+ req := &cbapi.CallbackBeforeSendGroupMsgReq{
CommonCallbackReq: toCommonCallback(ctx, msg, cbapi.CallbackBeforeSendGroupMsgCommand),
GroupID: msg.MsgData.GroupID,
}
@@ -160,7 +160,6 @@ func callbackMsgModify(ctx context.Context, msg *pbchat.SendMsgReq) error {
log.ZDebug(ctx, "callbackMsgModify", "msg", msg.MsgData)
return nil
}
-
func CallbackGroupMsgRead(ctx context.Context, req *cbapi.CallbackGroupMsgReadReq) error {
if !config.Config.Callback.CallbackGroupMsgRead.Enable || req.ContentType != constant.Text {
return nil
@@ -180,10 +179,27 @@ func CallbackSingleMsgRead(ctx context.Context, req *cbapi.CallbackSingleMsgRead
}
req.CallbackCommand = cbapi.CallbackSingleMsgRead
- resp := &cbapi.CallbackGroupMsgReadResp{}
+ resp := &cbapi.CallbackSingleMsgReadResp{}
if err := http.CallBackPostReturn(ctx, cbURL(), req, resp, config.Config.Callback.CallbackMsgModify); err != nil {
return err
}
return nil
}
+func CallbackAfterRevokeMsg(ctx context.Context, req *pbchat.RevokeMsgReq) error {
+ if !config.Config.Callback.CallbackAfterRevokeMsg.Enable {
+ return nil
+ }
+ callbackReq := &cbapi.CallbackAfterRevokeMsgReq{
+ CallbackCommand: cbapi.CallbackAfterRevokeMsgCommand,
+ ConversationID: req.ConversationID,
+ Seq: req.Seq,
+ UserID: req.UserID,
+ }
+ resp := &cbapi.CallbackAfterRevokeMsgResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackAfterRevokeMsg); err != nil {
+ return err
+ }
+ utils.StructFieldNotNilReplace(req, resp)
+ return nil
+}
diff --git a/internal/rpc/msg/revoke.go b/internal/rpc/msg/revoke.go
index 151d29fc1..d7362d339 100644
--- a/internal/rpc/msg/revoke.go
+++ b/internal/rpc/msg/revoke.go
@@ -61,6 +61,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
if msgs[0].ContentType == constant.MsgRevokeNotification {
return nil, errs.ErrMsgAlreadyRevoke.Wrap("msg already revoke")
}
+
data, _ := json.Marshal(msgs[0])
log.ZInfo(ctx, "GetMsgBySeqs", "conversationID", req.ConversationID, "seq", req.Seq, "msg", string(data))
var role int32
@@ -128,5 +129,8 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
if err := m.notificationSender.NotificationWithSesstionType(ctx, req.UserID, recvID, constant.MsgRevokeNotification, msgs[0].SessionType, &tips); err != nil {
return nil, err
}
+ if err = CallbackAfterRevokeMsg(ctx, req); err != nil {
+ return nil, err
+ }
return &msg.RevokeMsgResp{}, nil
}
diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go
index 01de2734d..e87b4674e 100644
--- a/internal/rpc/user/callback.go
+++ b/internal/rpc/user/callback.go
@@ -91,8 +91,8 @@ func CallbackAfterUserRegister(ctx context.Context, req *pbuser.UserRegisterReq)
Users: req.Users,
}
- resp := &cbapi.CallbackBeforeUserRegisterResp{}
- if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeUpdateUserInfo); err != nil {
+ resp := &cbapi.CallbackAfterUserRegisterResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackAfterUpdateUserInfo); err != nil {
return err
}
return nil
diff --git a/pkg/apistruct/msg.go b/pkg/apistruct/msg.go
index 12cf253a0..61b4d832b 100644
--- a/pkg/apistruct/msg.go
+++ b/pkg/apistruct/msg.go
@@ -16,56 +16,56 @@ package apistruct
type PictureBaseInfo struct {
UUID string `mapstructure:"uuid"`
- Type string `mapstructure:"type"`
+ Type string `mapstructure:"type" validate:"required"`
Size int64 `mapstructure:"size"`
- Width int32 `mapstructure:"width"`
- Height int32 `mapstructure:"height"`
- Url string `mapstructure:"url"`
+ Width int32 `mapstructure:"width" validate:"required"`
+ Height int32 `mapstructure:"height" validate:"required"`
+ Url string `mapstructure:"url" validate:"required"`
}
type PictureElem struct {
SourcePath string `mapstructure:"sourcePath"`
- SourcePicture PictureBaseInfo `mapstructure:"sourcePicture"`
- BigPicture PictureBaseInfo `mapstructure:"bigPicture"`
- SnapshotPicture PictureBaseInfo `mapstructure:"snapshotPicture"`
+ SourcePicture PictureBaseInfo `mapstructure:"sourcePicture" validate:"required"`
+ BigPicture PictureBaseInfo `mapstructure:"bigPicture" validate:"required"`
+ SnapshotPicture PictureBaseInfo `mapstructure:"snapshotPicture" validate:"required"`
}
type SoundElem struct {
UUID string `mapstructure:"uuid"`
SoundPath string `mapstructure:"soundPath"`
- SourceURL string `mapstructure:"sourceUrl"`
+ SourceURL string `mapstructure:"sourceUrl" validate:"required"`
DataSize int64 `mapstructure:"dataSize"`
- Duration int64 `mapstructure:"duration"`
+ Duration int64 `mapstructure:"duration" validate:"required,min=1"`
}
type VideoElem struct {
- VideoPath string `mapstructure:"videoPath"`
+ VideoPath string `mapstructure:"videoPath" `
VideoUUID string `mapstructure:"videoUUID"`
- VideoURL string `mapstructure:"videoUrl"`
- VideoType string `mapstructure:"videoType"`
- VideoSize int64 `mapstructure:"videoSize"`
- Duration int64 `mapstructure:"duration"`
+ VideoURL string `mapstructure:"videoUrl" validate:"required"`
+ VideoType string `mapstructure:"videoType" validate:"required"`
+ VideoSize int64 `mapstructure:"videoSize" validate:"required"`
+ Duration int64 `mapstructure:"duration" validate:"required"`
SnapshotPath string `mapstructure:"snapshotPath"`
SnapshotUUID string `mapstructure:"snapshotUUID"`
SnapshotSize int64 `mapstructure:"snapshotSize"`
- SnapshotURL string `mapstructure:"snapshotUrl"`
- SnapshotWidth int32 `mapstructure:"snapshotWidth"`
- SnapshotHeight int32 `mapstructure:"snapshotHeight"`
+ SnapshotURL string `mapstructure:"snapshotUrl" validate:"required"`
+ SnapshotWidth int32 `mapstructure:"snapshotWidth" validate:"required"`
+ SnapshotHeight int32 `mapstructure:"snapshotHeight" validate:"required"`
}
type FileElem struct {
- FilePath string `mapstructure:"filePath"`
+ FilePath string `mapstructure:"filePath" `
UUID string `mapstructure:"uuid"`
- SourceURL string `mapstructure:"sourceUrl"`
- FileName string `mapstructure:"fileName"`
- FileSize int64 `mapstructure:"fileSize"`
+ SourceURL string `mapstructure:"sourceUrl" validate:"required"`
+ FileName string `mapstructure:"fileName" validate:"required"`
+ FileSize int64 `mapstructure:"fileSize" validate:"required"`
}
type AtElem struct {
Text string `mapstructure:"text"`
- AtUserList []string `mapstructure:"atUserList"`
+ AtUserList []string `mapstructure:"atUserList" validate:"required,max=1000"`
IsAtSelf bool `mapstructure:"isAtSelf"`
}
type LocationElem struct {
- Description string `mapstructure:"description"`
- Longitude float64 `mapstructure:"longitude"`
- Latitude float64 `mapstructure:"latitude"`
+ Description string `mapstructure:"description" `
+ Longitude float64 `mapstructure:"longitude" validate:"required"`
+ Latitude float64 `mapstructure:"latitude" validate:"required"`
}
type CustomElem struct {
Data string `mapstructure:"data" validate:"required"`
@@ -80,18 +80,19 @@ type TextElem struct {
type RevokeElem struct {
RevokeMsgClientID string `mapstructure:"revokeMsgClientID" validate:"required"`
}
+
type OANotificationElem struct {
- NotificationName string `mapstructure:"notificationName" json:"notificationName" validate:"required"`
- NotificationFaceURL string `mapstructure:"notificationFaceURL" json:"notificationFaceURL"`
- NotificationType int32 `mapstructure:"notificationType" json:"notificationType" validate:"required"`
- Text string `mapstructure:"text" json:"text" validate:"required"`
- Url string `mapstructure:"url" json:"url"`
- MixType int32 `mapstructure:"mixType" json:"mixType"`
- PictureElem PictureElem `mapstructure:"pictureElem" json:"pictureElem"`
- SoundElem SoundElem `mapstructure:"soundElem" json:"soundElem"`
- VideoElem VideoElem `mapstructure:"videoElem" json:"videoElem"`
- FileElem FileElem `mapstructure:"fileElem" json:"fileElem"`
- Ex string `mapstructure:"ex" json:"ex"`
+ NotificationName string `mapstructure:"notificationName" json:"notificationName" validate:"required"`
+ NotificationFaceURL string `mapstructure:"notificationFaceURL" json:"notificationFaceURL"`
+ NotificationType int32 `mapstructure:"notificationType" json:"notificationType" validate:"required"`
+ Text string `mapstructure:"text" json:"text" validate:"required"`
+ Url string `mapstructure:"url" json:"url"`
+ MixType int32 `mapstructure:"mixType" json:"mixType" validate:"required"`
+ PictureElem *PictureElem `mapstructure:"pictureElem" json:"pictureElem"`
+ SoundElem *SoundElem `mapstructure:"soundElem" json:"soundElem"`
+ VideoElem *VideoElem `mapstructure:"videoElem" json:"videoElem"`
+ FileElem *FileElem `mapstructure:"fileElem" json:"fileElem"`
+ Ex string `mapstructure:"ex" json:"ex"`
}
type MessageRevoked struct {
RevokerID string `mapstructure:"revokerID" json:"revokerID" validate:"required"`
diff --git a/pkg/callbackstruct/constant.go b/pkg/callbackstruct/constant.go
index f029e3713..2af337ac6 100644
--- a/pkg/callbackstruct/constant.go
+++ b/pkg/callbackstruct/constant.go
@@ -1,5 +1,20 @@
package callbackstruct
+const CallbackBeforeInviteJoinGroupCommand = "callbackBeforeInviteJoinGroupCommand"
+const CallbackAfterJoinGroupCommand = "callbackAfterJoinGroupCommand"
+const CallbackAfterSetGroupInfoCommand = "callbackAfterSetGroupInfoCommand"
+const CallbackBeforeSetGroupInfoCommand = "callbackBeforeSetGroupInfoCommand"
+
+const CallbackAfterRevokeMsgCommand = "callbackBeforeAfterMsgCommand"
+const CallbackBeforeAddBlackCommand = "callbackBeforeAddBlackCommand"
+const CallbackAfterAddFriendCommand = "callbackAfterAddFriendCommand"
+const CallbackBeforeAddFriendAgreeCommand = "callbackBeforeAddFriendAgreeCommand"
+
+const CallbackAfterDeleteFriendCommand = "callbackAfterDeleteFriendCommand"
+const CallbackBeforeImportFriendsCommand = "callbackBeforeImportFriendsCommand"
+const CallbackAfterImportFriendsCommand = "callbackAfterImportFriendsCommand"
+const CallbackAfterRemoveBlackCommand = "callbackAfterRemoveBlackCommand"
+
const (
CallbackQuitGroupCommand = "callbackQuitGroupCommand"
CallbackKillGroupCommand = "callbackKillGroupCommand"
@@ -29,5 +44,6 @@ const (
CallbackBeforeCreateGroupCommand = "callbackBeforeCreateGroupCommand"
CallbackAfterCreateGroupCommand = "callbackAfterCreateGroupCommand"
CallbackBeforeMemberJoinGroupCommand = "callbackBeforeMemberJoinGroupCommand"
- CallbackBeforeSetGroupMemberInfoCommand = "CallbackBeforeSetGroupMemberInfoCommand"
+ CallbackBeforeSetGroupMemberInfoCommand = "callbackBeforeSetGroupMemberInfoCommand"
+ CallbackAfterSetGroupMemberInfoCommand = "callbackAfterSetGroupMemberInfoCommand"
)
diff --git a/pkg/callbackstruct/friend.go b/pkg/callbackstruct/friend.go
index ebbd08b19..3674a34da 100644
--- a/pkg/callbackstruct/friend.go
+++ b/pkg/callbackstruct/friend.go
@@ -19,6 +19,7 @@ type CallbackBeforeAddFriendReq struct {
FromUserID string `json:"fromUserID" `
ToUserID string `json:"toUserID"`
ReqMsg string `json:"reqMsg"`
+ Ex string `json:"ex"`
}
type CallbackBeforeAddFriendResp struct {
@@ -35,6 +36,28 @@ type CallBackAddFriendReplyBeforeResp struct {
CommonCallbackResp
}
+type CallbackBeforeSetFriendRemarkReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ OwnerUserID string `json:"ownerUserID"`
+ FriendUserID string `json:"friendUserID"`
+ Remark string `json:"remark"`
+}
+
+type CallbackBeforeSetFriendRemarkResp struct {
+ CommonCallbackResp
+ Remark string `json:"remark"`
+}
+
+type CallbackAfterSetFriendRemarkReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ OwnerUserID string `json:"ownerUserID"`
+ FriendUserID string `json:"friendUserID"`
+ Remark string `json:"remark"`
+}
+
+type CallbackAfterSetFriendRemarkResp struct {
+ CommonCallbackResp
+}
type CallbackAfterAddFriendReq struct {
CallbackCommand `json:"callbackCommand"`
FromUserID string `json:"fromUserID" `
@@ -45,26 +68,60 @@ type CallbackAfterAddFriendReq struct {
type CallbackAfterAddFriendResp struct {
CommonCallbackResp
}
+type CallbackBeforeAddBlackReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ OwnerUserID string `json:"ownerUserID" `
+ BlackUserID string `json:"blackUserID"`
+}
-type CallbackBeforeSetFriendRemarkReq struct {
+type CallbackBeforeAddBlackResp struct {
+ CommonCallbackResp
+}
+
+type CallbackBeforeAddFriendAgreeReq struct {
CallbackCommand `json:"callbackCommand"`
- OwnerUserID string `json:"ownerUserID"`
- FriendUserID string `json:"friendUserID"`
- Remark string `json:"remark"`
+ FromUserID string `json:"fromUserID" `
+ ToUserID string `json:"blackUserID"`
+ HandleResult int32 `json:"HandleResult"`
+ HandleMsg string `json:"HandleMsg"`
}
-type CallbackBeforeSetFriendRemarkResp struct {
+type CallbackBeforeAddFriendAgreeResp struct {
CommonCallbackResp
- Remark string `json:"remark"`
}
-type CallbackAfterSetFriendRemarkReq struct {
+type CallbackAfterDeleteFriendReq struct {
CallbackCommand `json:"callbackCommand"`
- OwnerUserID string `json:"ownerUserID"`
+ OwnerUserID string `json:"ownerUserID" `
FriendUserID string `json:"friendUserID"`
- Remark string `json:"remark"`
+}
+type CallbackAfterDeleteFriendResp struct {
+ CommonCallbackResp
}
-type CallbackAfterSetFriendRemarkResp struct {
+type CallbackBeforeImportFriendsReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ OwnerUserID string `json:"ownerUserID" `
+ FriendUserIDs []string `json:"friendUserIDs"`
+}
+type CallbackBeforeImportFriendsResp struct {
+ CommonCallbackResp
+ FriendUserIDs []string `json:"friendUserIDs"`
+}
+type CallbackAfterImportFriendsReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ OwnerUserID string `json:"ownerUserID" `
+ FriendUserIDs []string `json:"friendUserIDs"`
+}
+type CallbackAfterImportFriendsResp struct {
+ CommonCallbackResp
+}
+
+type CallbackAfterRemoveBlackReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ OwnerUserID string `json:"ownerUserID"`
+ BlackUserID string `json:"blackUserID"`
+}
+type CallbackAfterRemoveBlackResp struct {
CommonCallbackResp
}
diff --git a/pkg/callbackstruct/group.go b/pkg/callbackstruct/group.go
index 79e02ba0f..899b4312f 100644
--- a/pkg/callbackstruct/group.go
+++ b/pkg/callbackstruct/group.go
@@ -109,108 +109,127 @@ type CallbackAfterSetGroupMemberInfoResp struct {
CommonCallbackResp
}
-type CallbackAfterGroupMemberExitReq struct {
+type CallbackQuitGroupReq struct {
CallbackCommand `json:"callbackCommand"`
GroupID string `json:"groupID"`
UserID string `json:"userID"`
- GroupType *int32 `json:"groupType"`
- ExitType string `json:"exitType"`
}
-type CallbackAfterGroupMemberExitResp struct {
+type CallbackQuitGroupResp struct {
CommonCallbackResp
}
-type CallbackAfterUngroupReq struct {
+type CallbackKillGroupMemberReq struct {
CallbackCommand `json:"callbackCommand"`
GroupID string `json:"groupID"`
- GroupType *int32 `json:"groupType"`
- OwnerID string `json:"ownerID"`
- MemberList []string `json:"memberList"`
+ KickedUserIDs []string `json:"kickedUserIDs"`
+ Reason string `json:"reason"`
}
-type CallbackAfterUngroupResp struct {
+type CallbackKillGroupMemberResp struct {
CommonCallbackResp
}
-type CallbackAfterSetGroupInfoReq struct {
+type CallbackDisMissGroupReq struct {
CallbackCommand `json:"callbackCommand"`
- GroupID string `json:"groupID"`
- GroupType *int32 `json:"groupType"`
- UserID string `json:"userID"`
- Name string `json:"name"`
- Notification string `json:"notification"`
- GroupUrl string `json:"groupUrl"`
+ GroupID string `json:"groupID"`
+ OwnerID string `json:"ownerID"`
+ GroupType string `json:"groupType"`
+ MembersID []string `json:"membersID"`
}
-type CallbackAfterSetGroupInfoResp struct {
+type CallbackDisMissGroupResp struct {
CommonCallbackResp
}
-type CallbackAfterRevokeMsgReq struct {
+type CallbackJoinGroupReq struct {
CallbackCommand `json:"callbackCommand"`
GroupID string `json:"groupID"`
- GroupType *int32 `json:"groupType"`
- UserID string `json:"userID"`
- Content string `json:"content"`
+ GroupType string `json:"groupType"`
+ ApplyID string `json:"applyID"`
+ ReqMessage string `json:"reqMessage"`
}
-type CallbackAfterRevokeMsgResp struct {
+type CallbackJoinGroupResp struct {
CommonCallbackResp
}
-type CallbackQuitGroupReq struct {
+type CallbackTransferGroupOwnerReq struct {
CallbackCommand `json:"callbackCommand"`
GroupID string `json:"groupID"`
- UserID string `json:"userID"`
+ OldOwnerUserID string `json:"oldOwnerUserID"`
+ NewOwnerUserID string `json:"newOwnerUserID"`
}
-type CallbackQuitGroupResp struct {
+type CallbackTransferGroupOwnerResp struct {
CommonCallbackResp
}
-type CallbackKillGroupMemberReq struct {
+type CallbackBeforeInviteUserToGroupReq struct {
CallbackCommand `json:"callbackCommand"`
+ OperationID string `json:"operationID"`
GroupID string `json:"groupID"`
- KickedUserIDs []string `json:"kickedUserIDs"`
Reason string `json:"reason"`
+ InvitedUserIDs []string `json:"invitedUserIDs"`
}
-
-type CallbackKillGroupMemberResp struct {
+type CallbackBeforeInviteUserToGroupResp struct {
CommonCallbackResp
+ RefusedMembersAccount []string `json:"refusedMembersAccount,omitempty"` // Optional field to list members whose invitation is refused.
}
-type CallbackDisMissGroupReq struct {
+type CallbackAfterJoinGroupReq struct {
CallbackCommand `json:"callbackCommand"`
- GroupID string `json:"groupID"`
- OwnerID string `json:"ownerID"`
- GroupType string `json:"groupType"`
- MembersID []string `json:"membersID"`
+ OperationID string `json:"operationID"`
+ GroupID string `json:"groupID"`
+ ReqMessage string `json:"reqMessage"`
+ JoinSource int32 `json:"joinSource"`
+ InviterUserID string `json:"inviterUserID"`
}
-
-type CallbackDisMissGroupResp struct {
+type CallbackAfterJoinGroupResp struct {
CommonCallbackResp
}
-type CallbackJoinGroupReq struct {
- CallbackCommand `json:"callbackCommand"`
- GroupID string `json:"groupID"`
- GroupType string `json:"groupType"`
- ApplyID string `json:"applyID"`
- ReqMessage string `json:"reqMessage"`
+type CallbackBeforeSetGroupInfoReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ OperationID string `json:"operationID"`
+ GroupID string `json:"groupID"`
+ GroupName string `json:"groupName"`
+ Notification string `json:"notification"`
+ Introduction string `json:"introduction"`
+ FaceURL string `json:"faceURL"`
+ Ex string `json:"ex"`
+ NeedVerification int32 `json:"needVerification"`
+ LookMemberInfo int32 `json:"lookMemberInfo"`
+ ApplyMemberFriend int32 `json:"applyMemberFriend"`
}
-type CallbackJoinGroupResp struct {
+type CallbackBeforeSetGroupInfoResp struct {
CommonCallbackResp
+ GroupID string ` json:"groupID"`
+ GroupName string `json:"groupName"`
+ Notification string `json:"notification"`
+ Introduction string `json:"introduction"`
+ FaceURL string `json:"faceURL"`
+ Ex *string `json:"ex"`
+ NeedVerification *int32 `json:"needVerification"`
+ LookMemberInfo *int32 `json:"lookMemberInfo"`
+ ApplyMemberFriend *int32 `json:"applyMemberFriend"`
}
-type CallbackTransferGroupOwnerReq struct {
- CallbackCommand `json:"callbackCommand"`
- GroupID string `json:"groupID"`
- OldOwnerUserID string `json:"oldOwnerUserID"`
- NewOwnerUserID string `json:"newOwnerUserID"`
+type CallbackAfterSetGroupInfoReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ OperationID string `json:"operationID"`
+ GroupID string `json:"groupID"`
+ GroupName string `json:"groupName"`
+ Notification string `json:"notification"`
+ Introduction string `json:"introduction"`
+ FaceURL string `json:"faceURL"`
+ Ex *string `json:"ex"`
+ NeedVerification *int32 `json:"needVerification"`
+ LookMemberInfo *int32 `json:"lookMemberInfo"`
+ ApplyMemberFriend *int32 `json:"applyMemberFriend"`
}
-type CallbackTransferGroupOwnerResp struct {
+type CallbackAfterSetGroupInfoResp struct {
CommonCallbackResp
}
diff --git a/pkg/callbackstruct/message.go b/pkg/callbackstruct/message.go
index 3adee618b..ae36d7139 100644
--- a/pkg/callbackstruct/message.go
+++ b/pkg/callbackstruct/message.go
@@ -80,26 +80,6 @@ type CallbackMsgModifyCommandResp struct {
Ex *string `json:"ex"`
}
-type CallbackSendGroupMsgErrorReq struct {
- CommonCallbackReq
- GroupID string `json:"groupID"`
-}
-
-type CallbackSendGroupMsgErrorResp struct {
- CommonCallbackResp
-}
-
-type CallbackSingleMsgRevokeReq struct {
- CallbackCommand `json:"callbackCommand"`
- SendID string `json:"sendID"`
- ReceiveID string `json:"receiveID"`
- Content string `json:"content"`
-}
-
-type CallbackSingleMsgRevokeResp struct {
- CommonCallbackResp
-}
-
type CallbackGroupMsgReadReq struct {
CallbackCommand `json:"callbackCommand"`
SendID string `json:"sendID"`
diff --git a/pkg/callbackstruct/revoke.go b/pkg/callbackstruct/revoke.go
new file mode 100644
index 000000000..364c0162b
--- /dev/null
+++ b/pkg/callbackstruct/revoke.go
@@ -0,0 +1,11 @@
+package callbackstruct
+
+type CallbackAfterRevokeMsgReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ ConversationID string `json:"conversationID"`
+ Seq int64 `json:"seq"`
+ UserID string `json:"userID"`
+}
+type CallbackAfterRevokeMsgResp struct {
+ CommonCallbackResp
+}
diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go
index d8bee6af8..3c819ea2c 100644
--- a/pkg/common/config/config.go
+++ b/pkg/common/config/config.go
@@ -16,7 +16,6 @@ package config
import (
"bytes"
-
"github.com/OpenIMSDK/tools/discoveryregistry"
"gopkg.in/yaml.v3"
)
@@ -282,11 +281,25 @@ type configStruct struct {
CallbackAfterCreateGroup CallBackConfig `yaml:"afterCreateGroup"`
CallbackBeforeMemberJoinGroup CallBackConfig `yaml:"beforeMemberJoinGroup"`
CallbackBeforeSetGroupMemberInfo CallBackConfig `yaml:"beforeSetGroupMemberInfo"`
+ CallbackAfterSetGroupMemberInfo CallBackConfig `yaml:"afterSetGroupMemberInfo"`
CallbackQuitGroup CallBackConfig `yaml:"quitGroup"`
CallbackKillGroupMember CallBackConfig `yaml:"killGroupMember"`
CallbackDismissGroup CallBackConfig `yaml:"dismissGroup"`
CallbackBeforeJoinGroup CallBackConfig `yaml:"joinGroup"`
CallbackTransferGroupOwnerAfter CallBackConfig `yaml:"transferGroupOwner"`
+ CallbackBeforeInviteUserToGroup CallBackConfig `yaml:"beforeInviteUserToGroup"`
+ CallbackAfterJoinGroup CallBackConfig `yaml:"joinGroupAfter"`
+ CallbackAfterSetGroupInfo CallBackConfig `yaml:"setGroupInfoAfter"`
+ CallbackBeforeSetGroupInfo CallBackConfig `yaml:"setGroupInfoBefore"`
+ CallbackAfterRevokeMsg CallBackConfig `yaml:"revokeMsgAfter"`
+ CallbackBeforeAddBlack CallBackConfig `yaml:"addBlackBefore"`
+ CallbackAfterAddFriend CallBackConfig `yaml:"addFriendAfter"`
+ CallbackBeforeAddFriendAgree CallBackConfig `yaml:"addFriendAgreeBefore"`
+
+ CallbackAfterDeleteFriend CallBackConfig `yaml:"deleteFriendAfter"`
+ CallbackBeforeImportFriends CallBackConfig `yaml:"importFriendsBefore"`
+ CallbackAfterImportFriends CallBackConfig `yaml:"importFriendsAfter"`
+ CallbackAfterRemoveBlack CallBackConfig `yaml:"removeBlackAfter"`
} `yaml:"callback"`
Prometheus struct {
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index 98636bbde..b7c8a5dcb 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -386,10 +386,9 @@ def "IOS_PUSH_SOUND" "xxx" # IOS推送声音
def "IOS_BADGE_COUNT" "true" # IOS徽章计数
def "IOS_PRODUCTION" "false" # IOS生产
# callback 配置
-def "CALLBACK_ENABLE" "true" # 是否开启 Callback
+def "CALLBACK_ENABLE" "false" # 是否开启 Callback
def "CALLBACK_TIMEOUT" "5" # 最长超时时间
def "CALLBACK_FAILED_CONTINUE" "true" # 失败后是否继续
-
###################### Prometheus 配置信息 ######################
# 是否启用 Prometheus
readonly PROMETHEUS_ENABLE=${PROMETHEUS_ENABLE:-'false'}
From 5b697d5e95f54aaca7c199f283d19bf19745848a Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Thu, 30 Nov 2023 16:57:06 +0800
Subject: [PATCH 002/110] feat: update openim pull message by seq (#1498)
---
scripts/install/test.sh | 52 ++++++++++++++++++++++++++++++++++++++---
1 file changed, 49 insertions(+), 3 deletions(-)
diff --git a/scripts/install/test.sh b/scripts/install/test.sh
index eb3f6a200..049dc19c8 100755
--- a/scripts/install/test.sh
+++ b/scripts/install/test.sh
@@ -1202,6 +1202,40 @@ EOF
openim::test::check_error "$response"
}
+# Pulls messages by sequence.
+openim::test::pull_msg_by_seq() {
+ local userID="${1}"
+ local conversationID="${2}"
+ local beginSeq="${3}"
+ local endSeq="${4}"
+ local num="${5}"
+ local order="${6}" # Assuming 0 for ascending, 1 for descending
+
+ # Construct the request body
+ local request_body=$(cat <
Date: Thu, 30 Nov 2023 16:58:53 +0800
Subject: [PATCH 003/110] docs: add rfyiamcool to code_owners (#1491)
* docs: add rfyiamcool to code_owners
Signed-off-by: rfyiamcool
* Update CODEOWNERS
---------
Signed-off-by: rfyiamcool
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
docs/CODEOWNERS | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS
index 95babf0d1..d1119eb61 100644
--- a/docs/CODEOWNERS
+++ b/docs/CODEOWNERS
@@ -2,28 +2,28 @@
# Each line is a file pattern followed by one or more owners.
# README files
-README.md @openimsdk/openim @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+README.md @openimsdk/openim @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# Contributing guidelines
-CONTRIBUTING.md @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+CONTRIBUTING.md @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# License files
-LICENSE @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+LICENSE @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# Makefile
-Makefile @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+Makefile @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
# @cubxxw and @openimsdk/bot will be requested for
# review when someone opens a pull request.
-* @openimsdk/openim @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+* @openimsdk/openim @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# Order is important; the last matching pattern takes the most
# precedence. When someone opens a pull request that only
# modifies JS files, only @js-owner and not the global
# owner(s) will be requested for a review.
-*.js @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+*.js @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# You can also use email addresses if you prefer. They'll be
# used to look up users just like we do for commit author
@@ -35,7 +35,7 @@ Makefile @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangch
# be identified in the format @org/team-name. Teams must have
# explicit write access to the repository. In this example,
# the OpenIMSDK team in the github organization owns all .txt files.
-*.txt @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+*.txt @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# The `docs/*` pattern will match files like
# `docs/getting-started.md` but not further nested files like
From 4b192027aadebeb16a0190feb4ef5a4e726a463d Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Thu, 30 Nov 2023 18:25:38 +0800
Subject: [PATCH 004/110] =?UTF-8?q?=E2=93=82=EF=B8=8Ffeat:=20openim=20dock?=
=?UTF-8?q?er=20fix=20=20(#1502)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* fix: fix auto gen config
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add openim openim compatibility
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix ai fix git commit continue-on-error: true
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix ai fix git commit continue-on-error: true
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix ai fix git commit continue-on-error: true
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix ai fix git commit continue-on-error: true
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix ai fix git commit continue-on-error: true
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---
.dockerignore | 1 -
.env | 315 ------------------
.github/workflows/e2e-test.yml | 7 +-
.github/workflows/opencommit.yml | 3 +-
.github/workflows/openimci.yml | 6 +-
.gitignore | 1 +
Dockerfile | 5 +-
config/alertmanager.yml | 32 --
config/config.yaml | 409 ------------------------
deployments/templates/env_template.yaml | 44 +--
install.sh | 14 +-
install_guide.sh | 6 +-
scripts/init-pwd.sh | 70 ----
13 files changed, 28 insertions(+), 885 deletions(-)
delete mode 100644 .env
delete mode 100644 config/alertmanager.yml
delete mode 100644 config/config.yaml
delete mode 100755 scripts/init-pwd.sh
diff --git a/.dockerignore b/.dockerignore
index 705512401..263798e07 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -20,7 +20,6 @@ CHANGELOG/
# Ignore deployment-related files
docker-compose.yaml
-deployments/
# Ignore assets
assets/
diff --git a/.env b/.env
deleted file mode 100644
index 8213b9e3c..000000000
--- a/.env
+++ /dev/null
@@ -1,315 +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.
-
-# ======================================
-# ========= Basic Configuration ========
-# ======================================
-
-# The user for authentication or system operations.
-# Default: USER=root
-USER=root
-
-# Password associated with the specified user for authentication.
-# Default: PASSWORD=openIM123
-PASSWORD=openIM123
-
-# Endpoint for the MinIO object storage service.
-# Default: MINIO_ENDPOINT=http://172.28.0.1:10005
-MINIO_ENDPOINT=http://172.28.0.1:10005
-
-# Base URL for the application programming interface (API).
-# Default: API_URL=http://172.28.0.1:10002
-API_URL=http://172.28.0.1:10002
-
-# Directory path for storing data files or related information.
-# Default: DATA_DIR=./
-DATA_DIR=./
-
-# Choose the appropriate image address, the default is GITHUB image,
-# you can choose docker hub, for Chinese users can choose Ali Cloud
-# export IMAGE_REGISTRY="ghcr.io/openimsdk"
-# export IMAGE_REGISTRY="openim"
-# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
-IMAGE_REGISTRY=ghcr.io/openimsdk
-
-# ======================================
-# ========= Network Configuration ======
-# ======================================
-
-# Subnet for the Docker network.
-# Default: DOCKER_BRIDGE_SUBNET=172.28.0.0/16
-DOCKER_BRIDGE_SUBNET=172.28.0.0/16
-
-# Gateway for the Docker network.
-# Default: DOCKER_BRIDGE_GATEWAY=172.28.0.1
-DOCKER_BRIDGE_GATEWAY=172.28.0.1
-
-# Address or hostname for the MySQL network.
-# Default: MYSQL_NETWORK_ADDRESS=172.28.0.2
-MYSQL_NETWORK_ADDRESS=172.28.0.2
-
-# Address or hostname for the MongoDB network.
-# Default: MONGO_NETWORK_ADDRESS=172.28.0.3
-MONGO_NETWORK_ADDRESS=172.28.0.3
-
-# Address or hostname for the Redis network.
-# Default: REDIS_NETWORK_ADDRESS=172.28.0.4
-REDIS_NETWORK_ADDRESS=172.28.0.4
-
-# Address or hostname for the Kafka network.
-# Default: KAFKA_NETWORK_ADDRESS=172.28.0.5
-KAFKA_NETWORK_ADDRESS=172.28.0.5
-
-# Address or hostname for the ZooKeeper network.
-# Default: ZOOKEEPER_NETWORK_ADDRESS=172.28.0.6
-ZOOKEEPER_NETWORK_ADDRESS=172.28.0.6
-
-# Address or hostname for the MinIO network.
-# Default: MINIO_NETWORK_ADDRESS=172.28.0.7
-MINIO_NETWORK_ADDRESS=172.28.0.7
-
-# Address or hostname for the OpenIM web network.
-# Default: OPENIM_WEB_NETWORK_ADDRESS=172.28.0.8
-OPENIM_WEB_NETWORK_ADDRESS=172.28.0.8
-
-# Address or hostname for the OpenIM server network.
-# Default: OPENIM_SERVER_NETWORK_ADDRESS=172.28.0.9
-OPENIM_SERVER_NETWORK_ADDRESS=172.28.0.9
-
-# Address or hostname for the OpenIM chat network.
-# Default: OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.10
-OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.10
-
-# Address or hostname for the Prometheus network.
-# Default: PROMETHEUS_NETWORK_ADDRESS=172.28.0.11
-PROMETHEUS_NETWORK_ADDRESS=172.28.0.11
-
-# Address or hostname for the Grafana network.
-# Default: GRAFANA_NETWORK_ADDRESS=172.28.0.12
-GRAFANA_NETWORK_ADDRESS=172.28.0.12
-
-# Address or hostname for the node_exporter network.
-# Default: NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.13
-NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.13
-
-# Address or hostname for the OpenIM admin network.
-# Default: OPENIM_ADMIN_NETWORK_ADDRESS=172.28.0.14
-OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=172.28.0.14
-
-# Address or hostname for the alertmanager network.
-# Default: ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.14
-ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.14
-# ===============================================
-# = Component Extension Configuration =
-# ===============================================
-
-# ============ Component Extension Configuration ==========
-# ----- ZooKeeper Configuration -----
-# Address or hostname for the ZooKeeper service.
-# Default: ZOOKEEPER_ADDRESS=172.28.0.1
-ZOOKEEPER_ADDRESS=172.28.0.6
-
-# Port for ZooKeeper service.
-# Default: ZOOKEEPER_PORT=12181
-ZOOKEEPER_PORT=12181
-
-# ----- MySQL Configuration -----
-
-# Address or hostname for the MySQL service.
-# Default: MYSQL_ADDRESS=172.28.0.1
-MYSQL_ADDRESS=172.28.0.2
-
-# Port on which MySQL database service is running.
-# Default: MYSQL_PORT=13306
-MYSQL_PORT=13306
-
-# Password to authenticate with the MySQL database service.
-# Default: MYSQL_PASSWORD=openIM123
-MYSQL_PASSWORD=openIM123
-
-# ----- MongoDB Configuration -----
-# Address or hostname for the MongoDB service.
-# Default: MONGO_ADDRESS=172.28.0.1
-MONGO_ADDRESS=172.28.0.3
-
-# Port on which MongoDB service is running.
-# Default: MONGO_PORT=37017
-MONGO_PORT=37017
-
-# Username to authenticate with the MongoDB service.
-# Default: MONGO_USERNAME=root
-MONGO_USERNAME=root
-
-# Password to authenticate with the MongoDB service.
-# Default: MONGO_PASSWORD=openIM123
-MONGO_PASSWORD=openIM123
-
-# Name of the database in MongoDB to be used.
-# Default: MONGO_DATABASE=openIM_v3
-MONGO_DATABASE=openIM_v3
-
-# ----- Redis Configuration -----
-# Address or hostname for the Redis service.
-# Default: REDIS_ADDRESS=172.28.0.1
-REDIS_ADDRESS=172.28.0.4
-
-# Port on which Redis in-memory data structure store is running.
-# Default: REDIS_PORT=16379
-REDIS_PORT=16379
-
-# Password to authenticate with the Redis service.
-# Default: REDIS_PASSWORD=openIM123
-REDIS_PASSWORD=openIM123
-
-# ----- Kafka Configuration -----
-# Address or hostname for the Kafka service.
-# Default: KAFKA_ADDRESS=172.28.0.1
-KAFKA_ADDRESS=172.28.0.5
-
-# Port on which Kafka distributed streaming platform is running.
-# Default: KAFKA_PORT=19092
-KAFKA_PORT=19094
-
-# Topic in Kafka for storing the latest messages in Redis.
-# Default: KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis
-KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis
-
-# Topic in Kafka for pushing messages (e.g. notifications or updates).
-# Default: KAFKA_MSG_PUSH_TOPIC=msgToPush
-KAFKA_MSG_PUSH_TOPIC=msgToPush
-
-# Topic in Kafka for storing offline messages in MongoDB.
-# Default: KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql
-KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql
-
-# ----- MinIO Configuration ----
-# Address or hostname for the MinIO object storage service.
-# Default: MINIO_ADDRESS=172.28.0.1
-MINIO_ADDRESS=172.28.0.7
-
-# Port on which MinIO object storage service is running.
-# Default: MINIO_PORT=10005
-MINIO_PORT=10005
-
-# Access key to authenticate with the MinIO service.
-# Default: MINIO_ACCESS_KEY=root
-MINIO_ACCESS_KEY=root
-
-# Secret key corresponding to the access key for MinIO authentication.
-# Default: MINIO_SECRET_KEY=openIM123
-MINIO_SECRET_KEY=openIM123
-
-# ----- Prometheus Configuration -----
-# Address or hostname for the Prometheus service.
-# Default: PROMETHEUS_ADDRESS=172.28.0.1
-PROMETHEUS_ADDRESS=172.28.0.11
-
-# Port on which Prometheus service is running.
-# Default: PROMETHEUS_PORT=19090
-PROMETHEUS_PORT=19090
-
-# ----- Grafana Configuration -----
-# Address or hostname for the Grafana service.
-# Default: GRAFANA_ADDRESS=172.28.0.1
-GRAFANA_ADDRESS=172.28.0.12
-
-# Port on which Grafana service is running.
-# Default: GRAFANA_PORT=3000
-GRAFANA_PORT=3000
-
-# ======================================
-# ============ OpenIM Web ===============
-# ======================================
-
-# Path to the OpenIM web distribution.
-# Default: OPENIM_WEB_DIST_PATH=/app/dist
-OPENIM_WEB_DIST_PATH=/app/dist
-
-# Port on which OpenIM web service is running.
-# Default: OPENIM_WEB_PORT=11001
-OPENIM_WEB_PORT=11001
-
-# Address or hostname for the OpenIM web service.
-# Default: OPENIM_WEB_ADDRESS=172.28.0.1
-OPENIM_WEB_ADDRESS=172.28.0.8
-
-# ======================================
-# ========= OpenIM Server ==============
-# ======================================
-
-# Address or hostname for the OpenIM server.
-# Default: OPENIM_SERVER_ADDRESS=172.28.0.1
-OPENIM_SERVER_ADDRESS=172.28.0.9
-
-# Port for the OpenIM WebSockets.
-# Default: OPENIM_WS_PORT=10001
-OPENIM_WS_PORT=10001
-
-# Port for the OpenIM API.
-# Default: API_OPENIM_PORT=10002
-API_OPENIM_PORT=10002
-
-
-# ======================================
-# ========== OpenIM Chat ===============
-# ======================================
-
-# Branch name for OpenIM chat.
-# Default: CHAT_BRANCH=main
-CHAT_BRANCH=main
-
-# Address or hostname for the OpenIM chat service.
-# Default: OPENIM_CHAT_ADDRESS=172.28.0.1
-OPENIM_CHAT_ADDRESS=172.28.0.10
-
-# Port for the OpenIM chat API.
-# Default: OPENIM_CHAT_API_PORT=10008
-OPENIM_CHAT_API_PORT=10008
-
-# Directory path for storing data files or related information for OpenIM chat.
-# Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main
-OPENIM_CHAT_DATA_DIR=./openim-chat/main
-
-
-# ======================================
-# ========== OpenIM Admin ==============
-# ======================================
-
-# Branch name for OpenIM server.
-# Default: SERVER_BRANCH=main
-SERVER_BRANCH=main
-
-# Port for the OpenIM admin API.
-# Default: OPENIM_ADMIN_API_PORT=10009
-OPENIM_ADMIN_API_PORT=10009
-
-# Port for the node exporter.
-# Default: NODE_EXPORTER_PORT=19100
-NODE_EXPORTER_PORT=19100
-
-# Port for the prometheus.
-# Default: PROMETHEUS_PORT=19090
-PROMETHEUS_PORT=19090
-
-# Port for the grafana.
-# Default: GRAFANA_PORT=3000
-GRAFANA_PORT=3000
-
-# Port for the admin front.
-# Default: OPENIM_ADMIN_FRONT_PORT=11002
-OPENIM_ADMIN_FRONT_PORT=11002
-
-# Port for the alertmanager.
-# Default: ALERT_MANAGER_PORT=19093
-ALERT_MANAGER_PORT=19093
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index b16d614f6..2f6d7fe05 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -22,6 +22,9 @@ on:
# run e2e test every 4 hours
- cron: 0 */4 * * *
+env:
+ CALLBACK_ENABLE: true
+
jobs:
build:
name: Test
@@ -70,9 +73,9 @@ jobs:
- name: Docker Operations
run: |
- curl -o docker-compose.yml https://raw.githubusercontent.com/OpenIMSDK/openim-docker/main/example/basic-openim-server-dependency.yml
+ sudo make init
sudo docker compose up -d
- sudo sleep 60
+ sudo sleep 20
- name: Module Operations
run: |
diff --git a/.github/workflows/opencommit.yml b/.github/workflows/opencommit.yml
index 11bc00524..629a67aae 100644
--- a/.github/workflows/opencommit.yml
+++ b/.github/workflows/opencommit.yml
@@ -51,4 +51,5 @@ jobs:
OCO_EMOJI: false
OCO_MODEL: gpt-3.5-turbo-16k
OCO_LANGUAGE: en
- OCO_PROMPT_MODULE: conventional-commit
\ No newline at end of file
+ OCO_PROMPT_MODULE: conventional-commit
+ continue-on-error: true
\ No newline at end of file
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index 2e4cc9e24..707369379 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -127,6 +127,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run OpenIM make install start
run: |
+ sudo make init && \
sudo make install
execute-scripts:
@@ -156,9 +157,9 @@ jobs:
- name: Docker Operations
run: |
- curl -o docker-compose.yml https://raw.githubusercontent.com/OpenIMSDK/openim-docker/main/example/basic-openim-server-dependency.yml
+ sudo make init
sudo docker compose up -d
- sudo sleep 60
+ sudo sleep 20
- name: Module Operations
run: |
@@ -195,4 +196,5 @@ jobs:
- name: Test Docker Build
run: |
+ sudo make init
sudo make image
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index fa1818e2b..6b65697d9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -391,3 +391,4 @@ Sessionx.vim
dist/
.env
config/config.yaml
+config/alertmanager.yml
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index f738d4457..32639af7a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -25,7 +25,8 @@ WORKDIR ${SERVER_WORKDIR}
# Copy scripts and binary files to the production image
COPY --from=builder ${OPENIM_SERVER_BINDIR} /openim/openim-server/_output/bin
-# COPY --from=builder ${OPENIM_SERVER_CMDDIR} /openim/openim-server/scripts
-# COPY --from=builder ${SERVER_WORKDIR}/config /openim/openim-server/config
+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}/deployments /openim/openim-server/deployments
CMD ["/openim/openim-server/scripts/docker-start-all.sh"]
diff --git a/config/alertmanager.yml b/config/alertmanager.yml
deleted file mode 100644
index ee14b6464..000000000
--- a/config/alertmanager.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-###################### AlertManager Configuration ######################
-# AlertManager configuration using environment variables
-#
-# Resolve timeout
-# SMTP configuration for sending alerts
-# Templates for email notifications
-# Routing configurations for alerts
-# Receiver configurations
-global:
- resolve_timeout: 5m
- smtp_from: alert@openim.io
- smtp_smarthost: smtp.163.com:465
- smtp_auth_username: alert@openim.io
- smtp_auth_password: YOURAUTHPASSWORD
- smtp_require_tls: false
- smtp_hello: xxx监控告警
-
-templates:
- - /etc/alertmanager/email.tmpl
-
-route:
- group_wait: 5s
- group_interval: 5s
- repeat_interval: 5m
- receiver: email
-receivers:
- - name: email
- email_configs:
- - to: '{EMAIL_TO:-'alert@example.com'}'
- html: '{{ template "email.to.html" . }}'
- headers: { Subject: "[OPENIM-SERVER]Alarm" }
- send_resolved: true
diff --git a/config/config.yaml b/config/config.yaml
deleted file mode 100644
index b17d10073..000000000
--- a/config/config.yaml
+++ /dev/null
@@ -1,409 +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.
-
-# -----------------------------------------------------------------
-# TODO: This config file is the template file
-# --| source: deployments/templates/openim.yaml
-# --| env: scripts/install/environment
-# --| target: config/config.yaml
-# -----------------------------------------------------------------
-
-envs:
- discovery: zookeeper
-
-###################### Zookeeper ######################
-# Zookeeper configuration
-# It's not recommended to modify the schema
-#
-# Zookeeper address
-# Zookeeper username
-# Zookeeper password
-zookeeper:
- schema: openim
- address: [ 172.28.0.1:12181 ]
- username: ''
- password: ''
-
-###################### Mysql ######################
-# MySQL configuration
-# Currently, only single machine setup is supported
-#
-# Maximum number of open connections
-# Maximum number of idle connections
-# Maximum lifetime in seconds a connection can be reused
-# Log level: 1=slient, 2=error, 3=warn, 4=info
-# Slow query threshold in milliseconds
-mysql:
- address: [ 172.28.0.1:13306 ]
- username: root
- password: openIM123
- database: openIM_v3
- maxOpenConn: 1000
- maxIdleConn: 100
- maxLifeTime: 60
- logLevel: 4
- slowThreshold: 500
-
-###################### Mongo ######################
-# MongoDB configuration
-# If uri is not empty, it will be used directly
-#
-# MongoDB address for standalone setup, Mongos address for sharded cluster setup
-# Default MongoDB database name
-# Maximum connection pool size
-mongo:
- uri: ''
- address: [ 172.28.0.1:37017 ]
- database: openIM_v3
- username: root
- password: openIM123
- maxPoolSize: 100
-
-###################### Redis configuration information ######################
-# Redis configuration
-#
-# Username is required only for Redis version 6.0+
-redis:
- address: [ 172.28.0.1:16379 ]
- username: ''
- password: openIM123
-
-###################### Kafka configuration information ######################
-# Kafka configuration
-#
-# Kafka username
-# Kafka password
-# It's not recommended to modify this topic name
-# Consumer group ID, it's not recommended to modify
-kafka:
- username: ''
- password: ''
- addr: [ 172.28.0.1:19094 ]
- latestMsgToRedis:
- topic: "latestMsgToRedis"
- offlineMsgToMongo:
- topic: "offlineMsgToMongoMysql"
- msgToPush:
- topic: "msgToPush"
- consumerGroupID:
- msgToRedis: redis
- msgToMongo: mongo
- msgToMySql: mysql
- msgToPush: push
-
-###################### RPC configuration information ######################
-# RPC configuration
-#
-# IP address to register with zookeeper when starting RPC, the IP and corresponding rpcPort should be accessible by api/gateway
-# Default listen IP is 0.0.0.0
-rpc:
- registerIP: ''
- listenIP: 0.0.0.0
-
-###################### API configuration information ######################
-# API configuration
-#
-# API service port
-# Default listen IP is 0.0.0.0
-api:
- openImApiPort: [ 10002 ]
- listenIP: 0.0.0.0
-
-###################### Object configuration information ######################
-# Object storage configuration
-#
-# Use minio for object storage
-# API URL should be accessible by the app
-# It's not recommended to modify the bucket name
-# Endpoint should be accessible by the app
-# 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"
- minio:
- bucket: "openim"
- endpoint: "http://172.28.0.1:10005"
- accessKeyID: "root"
- secretAccessKey: "openIM123"
- sessionToken: ''
- signEndpoint: "http://127.0.0.1:10005"
- publicRead: false
- cos:
- bucketURL: https://temp-1252357374.cos.ap-chengdu.myqcloud.com
- secretID: ''
- secretKey: ''
- sessionToken: ''
- publicRead: false
- oss:
- endpoint: "https://oss-cn-chengdu.aliyuncs.com"
- bucket: "demo-9999999"
- bucketURL: "https://demo-9999999.oss-cn-chengdu.aliyuncs.com"
- accessKeyID: ''
- accessKeySecret: ''
- sessionToken: ''
- publicRead: false
- kodo:
- endpoint: "http://s3.cn-east-1.qiniucs.com"
- bucket: "demo-9999999"
- bucketURL: "http://your.domain.com"
- accessKeyID: ''
- accessKeySecret: ''
- sessionToken: ''
- publicRead: false
-###################### RPC Port Configuration ######################
-# RPC service ports
-# 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:
- openImUserPort: [ 10110 ]
- openImFriendPort: [ 10120 ]
- openImMessagePort: [ 10130 ]
- openImGroupPort: [ 10150 ]
- openImAuthPort: [ 10160 ]
- openImPushPort: [ 10170 ]
- openImConversationPort: [ 10180 ]
- openImThirdPort: [ 10190 ]
-
-###################### RPC Register Name Configuration ######################
-# RPC service names for registration, it's not recommended to modify these
-rpcRegisterName:
- openImUserName: User
- openImFriendName: Friend
- openImMsgName: Msg
- openImPushName: Push
- openImMessageGatewayName: MessageGateway
- openImGroupName: Group
- openImAuthName: Auth
- openImConversationName: Conversation
- openImThirdName: Third
-
-###################### Log Configuration ######################
-# Log configuration
-#
-# Storage directory
-# Log rotation time
-# Maximum number of logs to retain
-# Log level, 6 means all levels
-# Whether to output to stdout
-# 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
- withStack: false
-
-###################### Variables definition ######################
-# Long connection server configuration
-#
-# Websocket port for msg_gateway
-# Maximum number of websocket connections
-# Maximum length of websocket request package
-# Websocket connection handshake timeout
-longConnSvr:
- openImWsPort: [ 10001 ]
- websocketMaxConnNum: 100000
- openImMessageGatewayPort: [ 10140 ]
- websocketMaxMsgLen: 4096
- websocketTimeout: 10
-
-# Push notification service configuration
-#
-# Use GeTui for push notifications
-# GeTui offline push configuration
-# FCM offline push configuration
-# Account file, place it in the config directory
-# JPush configuration, modify these after applying in JPush backend
-push:
- enable: getui
- geTui:
- pushUrl: "https://restapi.getui.com/v2/$appId"
- masterSecret: ''
- appKey: ''
- intent: ''
- channelID: ''
- channelName: ''
- fcm:
- serviceAccount: "x.json"
- jpns:
- appKey: ''
- masterSecret: ''
- pushUrl: ''
- pushIntent: ''
-
-# App manager configuration
-#
-# Built-in app manager user IDs
-# Built-in app manager nicknames
-manager:
- userID: [ "openIM123456", "openIM654321", "openIMAdmin" ]
- nickname: [ "system1", "system2", "system3" ]
-
-# Multi-platform login policy
-# For each platform(Android, iOS, Windows, Mac, web), only one can be online at a time
-multiLoginPolicy: 1
-
-# Whether to store messages in MySQL, messages in MySQL are only used for management background
-chatPersistenceMysql: true
-
-# Message cache timeout in seconds, it's not recommended to modify
-msgCacheTimeout: 86400
-
-# Whether to enable read receipts for group chat
-groupMessageHasReadReceiptEnable: true
-
-# Whether to enable read receipts for single chat
-singleMessageHasReadReceiptEnable: true
-
-# MongoDB offline message retention period in days
-retainChatRecords: 365
-
-# Schedule to clear expired messages(older than retainChatRecords days) in MongoDB every Wednesday at 2am
-# This deletion is just for cleaning up disk usage according to previous configuration retainChatRecords, no notification will be sent
-chatRecordsClearTime: "0 2 * * 3"
-
-# Schedule to auto delete messages every day at 2am
-# This deletion is for messages that have been retained for more than msg_destruct_time (seconds) in the conversation field
-msgDestructTime: "0 2 * * *"
-
-# Secret key
-secret: openIM123
-
-# Token policy
-#
-# Token expiration period in days
-tokenPolicy:
- expire: 90
-
-# Message verification policy
-#
-# Whether to verify friendship when sending messages
-messageVerify:
- friendVerify: false
-
-# iOS push notification configuration
-#
-# iOS push notification sound
-# Whether to count badge
-# Whether it's production environment
-iosPush:
- pushSound: "xxx"
- badgeCount: true
- production: false
-
-###################### Third-party service configuration ######################
-# Callback configuration
-#
-# Callback URL
-# Whether to enable this callback event
-# Timeout in seconds
-# Whether to continue execution if callback fails
-callback:
- url:
- beforeSendSingleMsg:
- enable: false
- timeout: 5
- failedContinue: true
- afterSendSingleMsg:
- enable: false
- timeout: 5
- beforeSendGroupMsg:
- enable: false
- timeout: 5
- failedContinue: true
- afterSendGroupMsg:
- enable: false
- timeout: 5
- msgModify:
- enable: false
- timeout: 5
- failedContinue: true
- userOnline:
- enable: false
- timeout: 5
- userOffline:
- enable: false
- timeout: 5
- userKickOff:
- enable: false
- timeout: 5
- offlinePush:
- enable: false
- timeout: 5
- failedContinue: true
- onlinePush:
- enable: false
- timeout: 5
- failedContinue: true
- superGroupOnlinePush:
- enable: false
- timeout: 5
- failedContinue: true
- beforeAddFriend:
- enable: false
- timeout: 5
- failedContinue: true
- beforeUpdateUserInfo:
- enable: false
- timeout: 5
- failedContinue: true
- beforeCreateGroup:
- enable: false
- timeout: 5
- failedContinue: true
- beforeMemberJoinGroup:
- enable: false
- timeout: 5
- failedContinue: true
- beforeInviteUserToGroup:
- enable: true
- timeout: 5
- failedContinue: true
- beforeSetGroupMemberInfo:
- enable: false
- timeout: 5
- failedContinue: true
- setMessageReactionExtensions:
- enable: false
- timeout: 5
- failedContinue: true
-
-###################### Prometheus ######################
-# Prometheus configuration for various services
-# The number of Prometheus ports per service needs to correspond to rpcPort
-# The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh
-prometheus:
- enable: false
- prometheusUrl: "https://openim.prometheus"
- apiPrometheusPort: [20100]
- userPrometheusPort: [ 20110 ]
- friendPrometheusPort: [ 20120 ]
- messagePrometheusPort: [ 20130 ]
- messageGatewayPrometheusPort: [ 20140 ]
- groupPrometheusPort: [ 20150 ]
- authPrometheusPort: [ 20160 ]
- pushPrometheusPort: [ 20170 ]
- conversationPrometheusPort: [ 20230 ]
- rtcPrometheusPort: [ 21300 ]
- thirdPrometheusPort: [ 21301 ]
- messageTransferPrometheusPort: [ 21400, 21401, 21402, 21403 ] # List of ports
diff --git a/deployments/templates/env_template.yaml b/deployments/templates/env_template.yaml
index 954b2cf65..0ace53286 100644
--- a/deployments/templates/env_template.yaml
+++ b/deployments/templates/env_template.yaml
@@ -17,8 +17,8 @@
# ======================================
# The user for authentication or system operations.
-# Default: USER=root
-USER=${USER}
+# Default: OPENIM_USER=root
+USER=${OPENIM_USER}
# Password associated with the specified user for authentication.
# Default: PASSWORD=openIM123
@@ -58,58 +58,20 @@ DOCKER_BRIDGE_GATEWAY=${DOCKER_BRIDGE_GATEWAY}
# Address or hostname for the MySQL network.
# Default: MYSQL_NETWORK_ADDRESS=172.28.0.2
MYSQL_NETWORK_ADDRESS=${MYSQL_NETWORK_ADDRESS}
-
-# Address or hostname for the MongoDB network.
-# Default: MONGO_NETWORK_ADDRESS=172.28.0.3
MONGO_NETWORK_ADDRESS=${MONGO_NETWORK_ADDRESS}
-
-# Address or hostname for the Redis network.
-# Default: REDIS_NETWORK_ADDRESS=172.28.0.4
REDIS_NETWORK_ADDRESS=${REDIS_NETWORK_ADDRESS}
-
-# Address or hostname for the Kafka network.
-# Default: KAFKA_NETWORK_ADDRESS=172.28.0.5
KAFKA_NETWORK_ADDRESS=${KAFKA_NETWORK_ADDRESS}
-
-# Address or hostname for the ZooKeeper network.
-# Default: ZOOKEEPER_NETWORK_ADDRESS=172.28.0.6
ZOOKEEPER_NETWORK_ADDRESS=${ZOOKEEPER_NETWORK_ADDRESS}
-
-# Address or hostname for the MinIO network.
-# Default: MINIO_NETWORK_ADDRESS=172.28.0.7
MINIO_NETWORK_ADDRESS=${MINIO_NETWORK_ADDRESS}
-
-# Address or hostname for the OpenIM web network.
-# Default: OPENIM_WEB_NETWORK_ADDRESS=172.28.0.8
OPENIM_WEB_NETWORK_ADDRESS=${OPENIM_WEB_NETWORK_ADDRESS}
-
-# Address or hostname for the OpenIM server network.
-# Default: OPENIM_SERVER_NETWORK_ADDRESS=172.28.0.9
OPENIM_SERVER_NETWORK_ADDRESS=${OPENIM_SERVER_NETWORK_ADDRESS}
-
-# Address or hostname for the OpenIM chat network.
-# Default: OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.10
OPENIM_CHAT_NETWORK_ADDRESS=${OPENIM_CHAT_NETWORK_ADDRESS}
-
-# Address or hostname for the Prometheus network.
-# Default: PROMETHEUS_NETWORK_ADDRESS=172.28.0.11
PROMETHEUS_NETWORK_ADDRESS=${PROMETHEUS_NETWORK_ADDRESS}
-
-# Address or hostname for the Grafana network.
-# Default: GRAFANA_NETWORK_ADDRESS=172.28.0.12
GRAFANA_NETWORK_ADDRESS=${GRAFANA_NETWORK_ADDRESS}
-
-# Address or hostname for the node_exporter network.
-# Default: NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.13
NODE_EXPORTER_NETWORK_ADDRESS=${NODE_EXPORTER_NETWORK_ADDRESS}
-
-# Address or hostname for the OpenIM admin network.
-# Default: OPENIM_ADMIN_NETWORK_ADDRESS=172.28.0.14
OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS}
-
-# Address or hostname for the alertmanager network.
-# Default: ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.15
ALERT_MANAGER_NETWORK_ADDRESS=${ALERT_MANAGER_NETWORK_ADDRESS}
+
# ===============================================
# = Component Extension Configuration =
# ===============================================
diff --git a/install.sh b/install.sh
index 9318c33ba..7ff0f8739 100755
--- a/install.sh
+++ b/install.sh
@@ -63,7 +63,7 @@ PROXY=
GITHUB_TOKEN=
# Default user is "root". If you need to modify it, uncomment and replace accordingly.
-# USER=root
+# OPENIM_USER=root
# Default password for redis, mysql, mongo, as well as accessSecret in config/config.yaml.
# Remember, it should be a combination of 8 or more numbers and letters. If you want to set a different password, uncomment and replace "openIM123".
@@ -244,10 +244,10 @@ function download_source_code() {
function set_openim_env() {
warn "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."
# Set default values for user input
- # If the USER environment variable is not set, it defaults to 'root'
- if [ -z "$USER" ]; then
- USER="root"
- debug "USER is not set. Defaulting to 'root'."
+ # If the OPENIM_USER environment variable is not set, it defaults to 'root'
+ if [ -z "$OPENIM_USER" ]; then
+ OPENIM_USER="root"
+ debug "OPENIM_USER is not set. Defaulting to 'root'."
fi
# If the PASSWORD environment variable is not set, it defaults to 'openIM123'
@@ -321,7 +321,7 @@ function cmd_help() {
function parseinput() {
# set default values
- # USER=root
+ # OPENIM_USER=root
# PASSWORD=openIM123
# ENDPOINT=http://127.0.0.1:10005
# API=http://127.0.0.1:10002/object/
@@ -347,7 +347,7 @@ function parseinput() {
;;
-u|--user)
shift
- USER=$1
+ OPENIM_USER=$1
;;
-p|--password)
shift
diff --git a/install_guide.sh b/install_guide.sh
index b10ab2edd..c4323d6a8 100755
--- a/install_guide.sh
+++ b/install_guide.sh
@@ -110,7 +110,7 @@ install_docker_compose() {
read NEW_USER
is_empty $NEW_USER
if [ $? -eq 0 ]; then
- USER=$NEW_USER
+ OPENIM_USER=$NEW_USER
fi
echo "Please input the password, default is openIM123, press enter to use default"
@@ -131,12 +131,12 @@ install_docker_compose() {
fi
set -e
export MINIO_ENDPOINT
- export USER
+ export OPENIM_USER
export PASSWORD
export DATA_DIR
cat < .env
-USER=${USER}
+OPENIM_USER=${OPENIM_USER}
PASSWORD=${PASSWORD}
MINIO_ENDPOINT=${MINIO_ENDPOINT}
DATA_DIR=${DATA_DIR}
diff --git a/scripts/init-pwd.sh b/scripts/init-pwd.sh
deleted file mode 100755
index 5e2e162aa..000000000
--- a/scripts/init-pwd.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/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 "${SCRIPTS_ROOT}")/..
-
-#Include shell font styles and some basic information
-source $SCRIPTS_ROOT/lib/init.sh
-source $SCRIPTS_ROOT/path_info.sh
-
-cd $SCRIPTS_ROOT
-
-source $OPENIM_ROOT/.env
-
-# Check if PASSWORD only contains letters and numbers
-if [[ "$PASSWORD" =~ ^[a-zA-Z0-9]+$ ]]
-then
- echo "PASSWORD is valid."
-else
- echo "ERR: PASSWORD should only contain letters and numbers. " $PASSWORD
- exit
-fi
-
-echo ""
-echo -e "===> ${PURPLE_PREFIX} you user is:$USER ${COLOR_SUFFIX}"
-echo -e "===> ${PURPLE_PREFIX} you password is:$PASSWORD ${COLOR_SUFFIX}"
-echo -e "===> ${PURPLE_PREFIX} you minio endpoint is:$MINIO_ENDPOINT ${COLOR_SUFFIX}"
-echo -e "===> ${PURPLE_PREFIX} you api url is:$API_URL ${COLOR_SUFFIX}"
-echo ""
-
-# Specify the config file
-config_file="${OPENIM_ROOT}"/config/config.yaml
-
-# Load variables from .env file
-source "${OPENIM_ROOT}"/.env
-
-# Replace the password and username field for mysql
-sed -i "/mysql:/,/database:/ s/password:.*/password: $PASSWORD/" $config_file
-sed -i "/mysql:/,/database:/ s/username:.*/username: $USER/" $config_file
-
-# Replace the password and username field for mongo
-sed -i "/mongo:/,/maxPoolSize:/ s/password:.*/password: $PASSWORD/" $config_file
-sed -i "/mongo:/,/maxPoolSize:/ s/username:.*/username: $USER/" $config_file
-
-# Replace the password field for redis
-sed -i '/redis:/,/password:/s/password: .*/password: '${PASSWORD}'/' $config_file
-
-# Replace accessKeyID and secretAccessKey for minio
-sed -i "/minio:/,/isDistributedMod:/ s/accessKeyID:.*/accessKeyID: $USER/" $config_file
-sed -i "/minio:/,/isDistributedMod:/ s/secretAccessKey:.*/secretAccessKey: $PASSWORD/" $config_file
-sed -i '/minio:/,/endpoint:/s|endpoint: .*|endpoint: '${MINIO_ENDPOINT}'|' $config_file
-sed -i '/object:/,/apiURL:/s|apiURL: .*|apiURL: '${API_URL}'|' $config_file
-
-
-# Replace secret for token
-sed -i "s/secret: .*/secret: $PASSWORD/" $config_file
From 1c1322e3d2a220af47ef9ead8091d133905e6bad Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Tue, 5 Dec 2023 16:12:00 +0800
Subject: [PATCH 005/110] feat: Enhance Template Generation Logic in OPENIM
Deployment Scripts (#1510)
* feat: add init-config.sh
* feat: add helm charts test cicd
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add helm charts test cicd
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add helm charts test cicd
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add helm charts test cicd
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---
.github/workflows/openimci.yml | 1 -
config/prometheus.yml | 85 ----------------------------------
scripts/init-config.sh | 12 +++++
3 files changed, 12 insertions(+), 86 deletions(-)
delete mode 100644 config/prometheus.yml
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index 707369379..5f010db8a 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -127,7 +127,6 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run OpenIM make install start
run: |
- sudo make init && \
sudo make install
execute-scripts:
diff --git a/config/prometheus.yml b/config/prometheus.yml
deleted file mode 100644
index 7950c5d33..000000000
--- a/config/prometheus.yml
+++ /dev/null
@@ -1,85 +0,0 @@
-# my global config
-global:
- scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
- evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
- # scrape_timeout is set to the global default (10s).
-
-# Alertmanager configuration
-alerting:
- alertmanagers:
- - static_configs:
- - targets: ['172.28.0.1:19093']
-
-# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
-rule_files:
- - "instance-down-rules.yml"
-# - "first_rules.yml"
-# - "second_rules.yml"
-
-# A scrape configuration containing exactly one endpoint to scrape:
-# Here it's Prometheus itself.
-scrape_configs:
- # The job name is added as a label "job='job_name'"" to any timeseries scraped from this config.
- # Monitored information captured by prometheus
- - job_name: 'node-exporter'
- static_configs:
- - targets: [ '172.28.0.1:19100' ]
- labels:
- namespace: 'default'
-
- # prometheus fetches application services
- - job_name: 'openimserver-openim-api'
- static_configs:
- - targets: [ '172.28.0.1:20100' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-msggateway'
- static_configs:
- - targets: [ '172.28.0.1:20140' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-msgtransfer'
- static_configs:
- - targets: [ 172.28.0.1:21400, 172.28.0.1:21401, 172.28.0.1:21402, 172.28.0.1:21403 ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-push'
- static_configs:
- - targets: [ '172.28.0.1:20170' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-auth'
- static_configs:
- - targets: [ '172.28.0.1:20160' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-conversation'
- static_configs:
- - targets: [ '172.28.0.1:20230' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-friend'
- static_configs:
- - targets: [ '172.28.0.1:20120' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-group'
- static_configs:
- - targets: [ '172.28.0.1:20150' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-msg'
- static_configs:
- - targets: [ '172.28.0.1:20130' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-third'
- static_configs:
- - targets: [ '172.28.0.1:21301' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-user'
- static_configs:
- - targets: [ '172.28.0.1:20110' ]
- labels:
- namespace: 'default'
diff --git a/scripts/init-config.sh b/scripts/init-config.sh
index a4672c62d..3fcd2fdfd 100755
--- a/scripts/init-config.sh
+++ b/scripts/init-config.sh
@@ -35,6 +35,8 @@ declare -A TEMPLATES=(
["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/alertmanager.yml"
)
+openim::log::info "Read more configuration information: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md"
+
for template in "${!TEMPLATES[@]}"; do
if [[ ! -f "${template}" ]]; then
openim::log::error_exit "template file ${template} does not exist..."
@@ -42,6 +44,16 @@ for template in "${!TEMPLATES[@]}"; do
IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}"
for output_file in "${OUTPUT_FILES[@]}"; do
+ if [[ -f "${output_file}" ]]; then
+ read -p "File ${output_file} already exists. Overwrite? (Y/N): "
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
+ openim::log::info "Overwriting ${output_file}. Previous configuration will be lost."
+ else
+ openim::log::info "Skipping generation of ${output_file}."
+ continue
+ fi
+ fi
+
openim::log::info "⌚ Working with template file: ${template} to ${output_file}..."
"${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
openim::log::error "Error processing template file ${template}"
From c0194f6ef447f1a8cf87a520343e204dad9ff920 Mon Sep 17 00:00:00 2001
From: chao <48119764+withchao@users.noreply.github.com>
Date: Tue, 5 Dec 2023 20:53:02 +0800
Subject: [PATCH 006/110] feat: Remove MySQL and implement it all with Mongo
(#1508)
* fix: GetUserReqApplicationList error when there is a disbanded group chat
* fix: error when querying some information about disbanded group
* fix: GetUserReqApplicationList dismissed group error
* fix: the original message referenced by the pull message processing is withdrawn
* fix: the original message referenced by the pull message processing is withdrawn
* fix: the original message referenced by the pull message processing is withdrawn
* fix: the original message referenced by the pull message processing is withdrawn
* fix: the original message referenced by the pull message processing is withdrawn
* fix: the original message referenced by the pull message processing is withdrawn
* fix: the original message referenced by the pull message processing is withdrawn
* fix: the original message referenced by the pull message processing is withdrawn
* fix: the original message referenced by the pull message processing is withdrawn
* merge
* cicd: robot automated Change
* sdkws.MsgData
* user
* interface{} -> any
* user
* third
* group
* group
* group
* group
* group
* group
* conversation
* standalone mysql db model
* tx
* s3
* group
* mongo
* group
* group
* group
* group
* group
* group
* refactor: add openim mysql to mongo refactor
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* refactor: add openim mysql to mongo refactor
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* remove mysql
* remove mysql
* friend
* friend
* friend
* friend
* friend
* friend
* group
* convert
* index
* index
* all
* all
* mysql2mongo
* data conversion
* up35
* up35
* feat: add format set
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix scripts
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* merge main
* merge main
* Update init-config.sh
* fix: user args check
---------
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
Co-authored-by: withchao
Co-authored-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
docker-compose.yml | 123 +--
go.mod | 12 +-
go.sum | 4 +-
go.work | 1 +
internal/api/msg.go | 2 +-
internal/msggateway/encoder.go | 8 +-
internal/msggateway/n_ws_server.go | 12 +-
internal/msgtransfer/init.go | 28 +-
.../msgtransfer/online_history_msg_handler.go | 2 +-
.../msgtransfer/persistent_msg_handler.go | 119 ---
internal/push/offlinepush/getui/body.go | 6 +-
internal/push/offlinepush/getui/push.go | 4 +-
.../push/offlinepush/jpush/body/audience.go | 2 +-
.../push/offlinepush/jpush/body/message.go | 12 +-
.../push/offlinepush/jpush/body/platform.go | 2 +-
.../push/offlinepush/jpush/body/pushobj.go | 10 +-
internal/push/offlinepush/jpush/push.go | 4 +-
internal/push/push_to_client.go | 2 +-
internal/rpc/conversation/conversaion.go | 33 +-
internal/rpc/friend/black.go | 23 +-
internal/rpc/friend/friend.go | 108 +--
internal/rpc/group/cache.go | 4 +-
internal/rpc/group/db_map.go | 2 +-
internal/rpc/group/fill.go | 114 +--
internal/rpc/group/group.go | 900 ++++++++----------
internal/rpc/group/statistics.go | 6 +-
internal/rpc/group/super_group.go | 94 +-
internal/rpc/msg/utils.go | 7 +-
internal/rpc/third/log.go | 24 +-
internal/rpc/third/s3.go | 4 +-
internal/rpc/third/third.go | 40 +-
internal/rpc/user/user.go | 43 +-
internal/tools/conversation.go | 10 +-
internal/tools/msg.go | 53 +-
internal/tools/msg_doc_convert.go | 2 +-
pkg/apistruct/manage.go | 2 +-
pkg/authverify/token.go | 4 +-
pkg/common/cmd/rpc.go | 6 +-
pkg/common/config/config.go | 24 +-
pkg/common/config/parse.go | 2 +-
pkg/common/config/parse_test.go | 2 +-
pkg/common/convert/friend.go | 56 +-
pkg/common/convert/user.go | 62 +-
pkg/common/convert/user_test.go | 87 ++
pkg/common/db/cache/conversation.go | 69 +-
pkg/common/db/cache/friend.go | 24 +-
pkg/common/db/cache/group.go | 269 +++---
pkg/common/db/cache/meta_cache.go | 7 +-
pkg/common/db/cache/msg.go | 69 +-
pkg/common/db/cache/msg_test.go | 47 -
pkg/common/db/cache/s3.go | 18 +-
pkg/common/db/cache/user.go | 42 +-
pkg/common/db/controller/black.go | 17 +-
pkg/common/db/controller/chatlog.go | 37 -
pkg/common/db/controller/conversation.go | 122 ++-
pkg/common/db/controller/friend.go | 178 +---
pkg/common/db/controller/group.go | 467 +++------
pkg/common/db/controller/msg.go | 60 +-
pkg/common/db/controller/msg_test.go | 2 +-
pkg/common/db/controller/s3.go | 5 +-
pkg/common/db/controller/third.go | 32 +-
pkg/common/db/controller/user.go | 99 +-
pkg/common/db/mgo/black.go | 91 ++
pkg/common/db/mgo/conversation.go | 150 +++
pkg/common/db/mgo/friend.go | 131 +++
pkg/common/db/mgo/friend_request.go | 99 ++
pkg/common/db/mgo/group.go | 105 ++
pkg/common/db/mgo/group_member.go | 101 ++
pkg/common/db/mgo/group_request.go | 60 ++
pkg/common/db/mgo/log.go | 70 ++
pkg/common/db/mgo/object.go | 55 ++
pkg/common/db/mgo/user.go | 113 +++
pkg/common/db/relation/black_model.go | 111 ---
pkg/common/db/relation/chat_log_model.go | 63 --
pkg/common/db/relation/conversation_model.go | 250 -----
pkg/common/db/relation/doc.go | 15 -
pkg/common/db/relation/friend_model.go | 193 ----
.../db/relation/friend_request_model.go | 164 ----
pkg/common/db/relation/group_member_model.go | 197 ----
pkg/common/db/relation/group_model.go | 106 ---
pkg/common/db/relation/group_request_model.go | 118 ---
pkg/common/db/relation/log_model.go | 49 -
pkg/common/db/relation/mysql_init.go | 157 ---
pkg/common/db/relation/mysql_init_test.go | 121 ---
pkg/common/db/relation/object_model.go | 53 --
pkg/common/db/relation/user_model.go | 136 ---
pkg/common/db/s3/cont/controller.go | 4 +
pkg/common/db/s3/cos/internal.go | 2 +-
pkg/common/db/s3/kodo/internal.go | 1 -
pkg/common/db/s3/kodo/kodo.go | 323 -------
pkg/common/db/s3/oss/internal.go | 2 +-
pkg/common/db/s3/oss/oss.go | 0
pkg/common/db/table/relation/black.go | 26 +-
pkg/common/db/table/relation/conversation.go | 51 +-
pkg/common/db/table/relation/friend.go | 69 +-
.../db/table/relation/friend_request.go | 55 +-
pkg/common/db/table/relation/group.go | 51 +-
pkg/common/db/table/relation/group_member.go | 59 +-
pkg/common/db/table/relation/group_request.go | 45 +-
pkg/common/db/table/relation/log.go | 28 +-
pkg/common/db/table/relation/object.go | 29 +-
pkg/common/db/table/relation/user.go | 37 +-
pkg/common/db/table/relation/utils.go | 5 +-
pkg/common/db/table/unrelation/super_group.go | 74 +-
pkg/common/db/unrelation/mongo.go | 10 -
pkg/common/db/unrelation/msg.go | 0
pkg/common/db/unrelation/msg_convert.go | 2 +-
pkg/common/db/unrelation/super_group.go | 293 +++---
pkg/common/db/unrelation/user.go | 0
pkg/common/http/http_client.go | 4 +-
pkg/common/http/http_client_test.go | 8 +-
pkg/rpcclient/grouphash/grouphash.go | 88 ++
pkg/rpcclient/notification/group.go | 79 +-
scripts/install/openim-tools.sh | 1 +
test/e2e/api/token/token.go | 2 +-
test/e2e/api/user/user.go | 4 +-
test/jwt/main.go | 2 +-
test/typecheck/typecheck.go | 2 +-
tools/component/component.go | 5 +-
tools/component/component_test.go | 44 +
tools/data-conversion/README.md | 8 +-
.../openim/mysql/conversion/conversion.go | 2 +-
.../data-conversion/openim/mysql/v3/black.go | 49 +
.../openim/mysql/v3}/chatlog.go | 0
.../openim/mysql/v3/conversation.go | 73 ++
.../data-conversion/openim/mysql/v3}/doc.go | 0
.../data-conversion/openim/mysql/v3/friend.go | 78 ++
.../openim/mysql/v3/friend_request.go | 66 ++
.../data-conversion/openim/mysql/v3/group.go | 66 ++
.../openim/mysql/v3/group_member.go | 74 ++
.../openim/mysql/v3/group_request.go | 61 ++
tools/data-conversion/openim/mysql/v3/log.go | 29 +
.../data-conversion/openim/mysql/v3/object.go | 45 +
tools/data-conversion/openim/mysql/v3/user.go | 72 ++
.../data-conversion/openim/mysql/v3/utils.go | 24 +-
.../openim/proto/msg/msg.pb.go | 60 +-
.../openim/proto/sdk_ws/ws.pb.go | 8 +-
tools/up35/README.md | 67 ++
tools/up35/go.mod | 51 +
tools/up35/go.sum | 125 +++
tools/up35/up35.go | 367 +++++++
141 files changed, 4241 insertions(+), 4826 deletions(-)
delete mode 100644 internal/msgtransfer/persistent_msg_handler.go
create mode 100644 pkg/common/convert/user_test.go
delete mode 100644 pkg/common/db/controller/chatlog.go
create mode 100644 pkg/common/db/mgo/black.go
create mode 100644 pkg/common/db/mgo/conversation.go
create mode 100644 pkg/common/db/mgo/friend.go
create mode 100644 pkg/common/db/mgo/friend_request.go
create mode 100644 pkg/common/db/mgo/group.go
create mode 100644 pkg/common/db/mgo/group_member.go
create mode 100644 pkg/common/db/mgo/group_request.go
create mode 100644 pkg/common/db/mgo/log.go
create mode 100644 pkg/common/db/mgo/object.go
create mode 100644 pkg/common/db/mgo/user.go
delete mode 100644 pkg/common/db/relation/black_model.go
delete mode 100644 pkg/common/db/relation/chat_log_model.go
delete mode 100644 pkg/common/db/relation/conversation_model.go
delete mode 100644 pkg/common/db/relation/doc.go
delete mode 100644 pkg/common/db/relation/friend_model.go
delete mode 100644 pkg/common/db/relation/friend_request_model.go
delete mode 100644 pkg/common/db/relation/group_member_model.go
delete mode 100644 pkg/common/db/relation/group_model.go
delete mode 100644 pkg/common/db/relation/group_request_model.go
delete mode 100644 pkg/common/db/relation/log_model.go
delete mode 100644 pkg/common/db/relation/mysql_init.go
delete mode 100644 pkg/common/db/relation/mysql_init_test.go
delete mode 100644 pkg/common/db/relation/object_model.go
delete mode 100644 pkg/common/db/relation/user_model.go
delete mode 100644 pkg/common/db/s3/kodo/internal.go
delete mode 100644 pkg/common/db/s3/kodo/kodo.go
mode change 100755 => 100644 pkg/common/db/s3/oss/oss.go
mode change 100755 => 100644 pkg/common/db/unrelation/mongo.go
mode change 100755 => 100644 pkg/common/db/unrelation/msg.go
mode change 100755 => 100644 pkg/common/db/unrelation/user.go
create mode 100644 pkg/rpcclient/grouphash/grouphash.go
create mode 100644 tools/data-conversion/openim/mysql/v3/black.go
rename {pkg/common/db/table/relation => tools/data-conversion/openim/mysql/v3}/chatlog.go (100%)
create mode 100644 tools/data-conversion/openim/mysql/v3/conversation.go
rename {pkg/common/db/table/relation => tools/data-conversion/openim/mysql/v3}/doc.go (100%)
create mode 100644 tools/data-conversion/openim/mysql/v3/friend.go
create mode 100644 tools/data-conversion/openim/mysql/v3/friend_request.go
create mode 100644 tools/data-conversion/openim/mysql/v3/group.go
create mode 100644 tools/data-conversion/openim/mysql/v3/group_member.go
create mode 100644 tools/data-conversion/openim/mysql/v3/group_request.go
create mode 100644 tools/data-conversion/openim/mysql/v3/log.go
create mode 100644 tools/data-conversion/openim/mysql/v3/object.go
create mode 100644 tools/data-conversion/openim/mysql/v3/user.go
rename pkg/common/db/relation/meta_db.go => tools/data-conversion/openim/mysql/v3/utils.go (70%)
create mode 100644 tools/up35/README.md
create mode 100644 tools/up35/go.mod
create mode 100644 tools/up35/go.sum
create mode 100644 tools/up35/up35.go
diff --git a/docker-compose.yml b/docker-compose.yml
index 1a6626add..ebf6a3dc4 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -24,6 +24,7 @@ services:
restart: always
networks:
server:
+ # open-im-server_server
ipv4_address: ${MYSQL_NETWORK_ADDRESS}
mongodb:
@@ -142,68 +143,68 @@ services:
server:
ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS}
- openim-admin:
- image: ${IMAGE_REGISTRY}/openim-admin-front:v3.4.0
- # image: ghcr.io/openimsdk/openim-admin-front:v3.4.0
- # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:v3.4.0
- # image: openim/openim-admin-front:v3.4.0
- container_name: openim-admin
- restart: always
- ports:
- - "${OPENIM_ADMIN_FRONT_PORT}:80"
- networks:
- server:
- ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS}
+ # openim-admin:
+ # image: ${IMAGE_REGISTRY}/openim-admin-front:v3.4.0
+ # # image: ghcr.io/openimsdk/openim-admin-front:v3.4.0
+ # # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:v3.4.0
+ # # image: openim/openim-admin-front:v3.4.0
+ # container_name: openim-admin
+ # restart: always
+ # ports:
+ # - "${OPENIM_ADMIN_FRONT_PORT}:80"
+ # networks:
+ # server:
+ # ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS}
- prometheus:
- image: prom/prometheus
- container_name: prometheus
- hostname: prometheus
- restart: always
- volumes:
- - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
- - ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml
- ports:
- - "${PROMETHEUS_PORT}:9090"
- networks:
- server:
- ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS}
+ # prometheus:
+ # image: prom/prometheus
+ # container_name: prometheus
+ # hostname: prometheus
+ # restart: always
+ # volumes:
+ # - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
+ # - ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml
+ # ports:
+ # - "${PROMETHEUS_PORT}:9090"
+ # networks:
+ # server:
+ # ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS}
- alertmanager:
- image: prom/alertmanager
- container_name: alertmanager
- hostname: alertmanager
- restart: always
- volumes:
- - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
- - ./config/email.tmpl:/etc/alertmanager/email.tmpl
- ports:
- - "${ALERT_MANAGER_PORT}:9093"
- networks:
- server:
- ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS}
+ # alertmanager:
+ # image: prom/alertmanager
+ # container_name: alertmanager
+ # hostname: alertmanager
+ # restart: always
+ # volumes:
+ # - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
+ # - ./config/email.tmpl:/etc/alertmanager/email.tmpl
+ # ports:
+ # - "${ALERT_MANAGER_PORT}:9093"
+ # networks:
+ # server:
+ # ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS}
- grafana:
- image: grafana/grafana
- container_name: grafana
- hostname: grafana
- user: root
- restart: always
- ports:
- - "${GRAFANA_PORT}:3000"
- volumes:
- - ${DATA_DIR}/components/grafana:/var/lib/grafana
- networks:
- server:
- ipv4_address: ${GRAFANA_NETWORK_ADDRESS}
+ # grafana:
+ # image: grafana/grafana
+ # container_name: grafana
+ # hostname: grafana
+ # user: root
+ # restart: always
+ # ports:
+ # - "${GRAFANA_PORT}:3000"
+ # volumes:
+ # - ${DATA_DIR}/components/grafana:/var/lib/grafana
+ # networks:
+ # server:
+ # ipv4_address: ${GRAFANA_NETWORK_ADDRESS}
- node-exporter:
- image: quay.io/prometheus/node-exporter
- container_name: node-exporter
- hostname: node-exporter
- restart: always
- ports:
- - "${NODE_EXPORTER_PORT}:9100"
- networks:
- server:
- ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS}
+ # node-exporter:
+ # image: quay.io/prometheus/node-exporter
+ # container_name: node-exporter
+ # hostname: node-exporter
+ # restart: always
+ # ports:
+ # - "${NODE_EXPORTER_PORT}:9100"
+ # networks:
+ # server:
+ # ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS}
diff --git a/go.mod b/go.mod
index 8d767dbc1..bc84bf586 100644
--- a/go.mod
+++ b/go.mod
@@ -10,10 +10,8 @@ require (
github.com/go-playground/validator/v10 v10.15.5
github.com/gogo/protobuf v1.3.2
github.com/golang-jwt/jwt/v4 v4.5.0
- github.com/golang/protobuf v1.5.3
github.com/gorilla/websocket v1.5.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
- github.com/jinzhu/copier v0.4.0
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
github.com/minio/minio-go/v7 v7.0.63
github.com/mitchellh/mapstructure v1.5.0
@@ -29,8 +27,6 @@ require (
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.31.0
gopkg.in/yaml.v3 v3.0.1
- gorm.io/driver/mysql v1.5.2
- gorm.io/gorm v1.25.5
)
require github.com/google/uuid v1.3.1
@@ -38,10 +34,9 @@ require github.com/google/uuid v1.3.1
require (
github.com/IBM/sarama v1.41.3
github.com/OpenIMSDK/protocol v0.0.31
- github.com/OpenIMSDK/tools v0.0.17
+ github.com/OpenIMSDK/tools v0.0.18
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/go-redis/redis v6.15.9+incompatible
- github.com/go-sql-driver/mysql v1.7.1
github.com/redis/go-redis/v9 v9.2.1
github.com/tencentyun/cos-go-sdk-v5 v0.7.45
go.uber.org/automaxprocs v1.5.3
@@ -93,6 +88,7 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-zookeeper/zk v1.0.3 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
@@ -109,6 +105,7 @@ require (
github.com/jcmturner/gofork v1.7.6 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
+ github.com/jinzhu/copier v0.3.5 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@@ -152,7 +149,7 @@ require (
golang.org/x/arch v0.3.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
- golang.org/x/sys v0.13.0 // indirect
+ golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
@@ -162,6 +159,7 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
+ gorm.io/gorm v1.23.8 // indirect
)
require (
diff --git a/go.sum b/go.sum
index 640b11e89..063f7691e 100644
--- a/go.sum
+++ b/go.sum
@@ -498,8 +498,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/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.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
diff --git a/go.work b/go.work
index 1c819212c..63100b9f6 100644
--- a/go.work
+++ b/go.work
@@ -13,4 +13,5 @@ use (
./tools/component
./tools/url2im
./tools/data-conversion
+ ./tools/up35
)
diff --git a/internal/api/msg.go b/internal/api/msg.go
index 67b5f1eff..22182d985 100644
--- a/internal/api/msg.go
+++ b/internal/api/msg.go
@@ -150,7 +150,7 @@ func (m *MessageApi) DeleteMsgPhysical(c *gin.Context) {
}
func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendMsgReq *msg.SendMsgReq, err error) {
- var data interface{}
+ var data any
log.ZDebug(c, "getSendMsgReq", "req", req.Content)
switch req.ContentType {
case constant.Text:
diff --git a/internal/msggateway/encoder.go b/internal/msggateway/encoder.go
index 9791acb39..c5f1d00a8 100644
--- a/internal/msggateway/encoder.go
+++ b/internal/msggateway/encoder.go
@@ -22,8 +22,8 @@ import (
)
type Encoder interface {
- Encode(data interface{}) ([]byte, error)
- Decode(encodeData []byte, decodeData interface{}) error
+ Encode(data any) ([]byte, error)
+ Decode(encodeData []byte, decodeData any) error
}
type GobEncoder struct{}
@@ -32,7 +32,7 @@ func NewGobEncoder() *GobEncoder {
return &GobEncoder{}
}
-func (g *GobEncoder) Encode(data interface{}) ([]byte, error) {
+func (g *GobEncoder) Encode(data any) ([]byte, error) {
buff := bytes.Buffer{}
enc := gob.NewEncoder(&buff)
err := enc.Encode(data)
@@ -42,7 +42,7 @@ func (g *GobEncoder) Encode(data interface{}) ([]byte, error) {
return buff.Bytes(), nil
}
-func (g *GobEncoder) Decode(encodeData []byte, decodeData interface{}) error {
+func (g *GobEncoder) Decode(encodeData []byte, decodeData any) error {
buff := bytes.NewBuffer(encodeData)
dec := gob.NewDecoder(buff)
err := dec.Decode(decodeData)
diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go
index 5a061d7e1..737d5db14 100644
--- a/internal/msggateway/n_ws_server.go
+++ b/internal/msggateway/n_ws_server.go
@@ -49,7 +49,7 @@ type LongConnServer interface {
wsHandler(w http.ResponseWriter, r *http.Request)
GetUserAllCons(userID string) ([]*Client, bool)
GetUserPlatformCons(userID string, platform int) ([]*Client, bool, bool)
- Validate(s interface{}) error
+ Validate(s any) error
SetCacheHandler(cache cache.MsgModel)
SetDiscoveryRegistry(client discoveryregistry.SvcDiscoveryRegistry)
KickUserConn(client *Client) error
@@ -60,6 +60,12 @@ type LongConnServer interface {
MessageHandler
}
+var bufferPool = sync.Pool{
+ New: func() any {
+ return make([]byte, 1024)
+ },
+}
+
type WsServer struct {
port int
wsMaxConnNum int64
@@ -120,7 +126,7 @@ func (ws *WsServer) UnRegister(c *Client) {
ws.unregisterChan <- c
}
-func (ws *WsServer) Validate(s interface{}) error {
+func (ws *WsServer) Validate(s any) error {
//?question?
return nil
}
@@ -145,7 +151,7 @@ func NewWsServer(opts ...Option) (*WsServer, error) {
writeBufferSize: config.writeBufferSize,
handshakeTimeout: config.handshakeTimeout,
clientPool: sync.Pool{
- New: func() interface{} {
+ New: func() any {
return new(Client)
},
},
diff --git a/internal/msgtransfer/init.go b/internal/msgtransfer/init.go
index 8436317ee..a8d10799f 100644
--- a/internal/msgtransfer/init.go
+++ b/internal/msgtransfer/init.go
@@ -17,21 +17,20 @@ package msgtransfer
import (
"errors"
"fmt"
+ "log"
+ "net/http"
+ "sync"
+
"github.com/OpenIMSDK/tools/mw"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
- "log"
- "net/http"
- "sync"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
@@ -39,20 +38,12 @@ import (
)
type MsgTransfer struct {
- persistentCH *PersistentConsumerHandler // 聊天记录持久化到mysql的消费者 订阅的topic: ws2ms_chat
historyCH *OnlineHistoryRedisConsumerHandler // 这个消费者聚合消息, 订阅的topic:ws2ms_chat, 修改通知发往msg_to_modify topic, 消息存入redis后Incr Redis, 再发消息到ms2pschat topic推送, 发消息到msg_to_mongo topic持久化
historyMongoCH *OnlineHistoryMongoConsumerHandler // mongoDB批量插入, 成功后删除redis中消息,以及处理删除通知消息删除的 订阅的topic: msg_to_mongo
// modifyCH *ModifyMsgConsumerHandler // 负责消费修改消息通知的consumer, 订阅的topic: msg_to_modify
}
func StartTransfer(prometheusPort int) error {
- db, err := relation.NewGormDB()
- if err != nil {
- return err
- }
- if err := db.AutoMigrate(&relationtb.ChatLogModel{}); err != nil {
- fmt.Printf("gorm: AutoMigrate ChatLogModel err: %v\n", err)
- }
rdb, err := cache.NewRedis()
if err != nil {
return err
@@ -78,21 +69,16 @@ func StartTransfer(prometheusPort int) error {
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
msgModel := cache.NewMsgCacheModel(rdb)
msgDocModel := unrelation.NewMsgMongoDriver(mongo.GetDatabase())
- msgMysModel := relation.NewChatLogGorm(db)
- chatLogDatabase := controller.NewChatLogDatabase(msgMysModel)
msgDatabase := controller.NewCommonMsgDatabase(msgDocModel, msgModel)
conversationRpcClient := rpcclient.NewConversationRpcClient(client)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
- msgTransfer := NewMsgTransfer(chatLogDatabase, msgDatabase, &conversationRpcClient, &groupRpcClient)
+ msgTransfer := NewMsgTransfer(msgDatabase, &conversationRpcClient, &groupRpcClient)
return msgTransfer.Start(prometheusPort)
}
-func NewMsgTransfer(chatLogDatabase controller.ChatLogDatabase,
- msgDatabase controller.CommonMsgDatabase,
- conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient,
-) *MsgTransfer {
+func NewMsgTransfer(msgDatabase controller.CommonMsgDatabase, conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient) *MsgTransfer {
return &MsgTransfer{
- persistentCH: NewPersistentConsumerHandler(chatLogDatabase), historyCH: NewOnlineHistoryRedisConsumerHandler(msgDatabase, conversationRpcClient, groupRpcClient),
+ historyCH: NewOnlineHistoryRedisConsumerHandler(msgDatabase, conversationRpcClient, groupRpcClient),
historyMongoCH: NewOnlineHistoryMongoConsumerHandler(msgDatabase),
}
}
diff --git a/internal/msgtransfer/online_history_msg_handler.go b/internal/msgtransfer/online_history_msg_handler.go
index eb8e500fe..127cede71 100644
--- a/internal/msgtransfer/online_history_msg_handler.go
+++ b/internal/msgtransfer/online_history_msg_handler.go
@@ -61,7 +61,7 @@ type TriggerChannelValue struct {
type Cmd2Value struct {
Cmd int
- Value interface{}
+ Value any
}
type ContextMsg struct {
message *sdkws.MsgData
diff --git a/internal/msgtransfer/persistent_msg_handler.go b/internal/msgtransfer/persistent_msg_handler.go
deleted file mode 100644
index d105de2fe..000000000
--- a/internal/msgtransfer/persistent_msg_handler.go
+++ /dev/null
@@ -1,119 +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 msgtransfer
-
-import (
- "context"
-
- "github.com/OpenIMSDK/protocol/constant"
- pbmsg "github.com/OpenIMSDK/protocol/msg"
- "github.com/OpenIMSDK/tools/log"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/config"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- kfk "github.com/openimsdk/open-im-server/v3/pkg/common/kafka"
-
- "github.com/IBM/sarama"
- "google.golang.org/protobuf/proto"
-)
-
-type PersistentConsumerHandler struct {
- persistentConsumerGroup *kfk.MConsumerGroup
- chatLogDatabase controller.ChatLogDatabase
-}
-
-func NewPersistentConsumerHandler(database controller.ChatLogDatabase) *PersistentConsumerHandler {
- return &PersistentConsumerHandler{
- persistentConsumerGroup: kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{
- KafkaVersion: sarama.V2_0_0_0,
- OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
- }, []string{config.Config.Kafka.LatestMsgToRedis.Topic},
- config.Config.Kafka.Addr, config.Config.Kafka.ConsumerGroupID.MsgToMySql),
- chatLogDatabase: database,
- }
-}
-
-func (pc *PersistentConsumerHandler) handleChatWs2Mysql(
- ctx context.Context,
- cMsg *sarama.ConsumerMessage,
- msgKey string,
- _ sarama.ConsumerGroupSession,
-) {
- msg := cMsg.Value
- var tag bool
- msgFromMQ := pbmsg.MsgDataToMQ{}
- err := proto.Unmarshal(msg, &msgFromMQ)
- if err != nil {
- log.ZError(ctx, "msg_transfer Unmarshal msg err", err)
- return
- }
-
- log.ZDebug(ctx, "handleChatWs2Mysql", "msg", msgFromMQ.MsgData)
- // Control whether to store history messages (mysql)
- isPersist := utils.GetSwitchFromOptions(msgFromMQ.MsgData.Options, constant.IsPersistent)
- // Only process receiver data
- if isPersist {
- switch msgFromMQ.MsgData.SessionType {
- case constant.SingleChatType, constant.NotificationChatType:
- if msgKey == msgFromMQ.MsgData.RecvID {
- tag = true
- }
- case constant.GroupChatType:
- if msgKey == msgFromMQ.MsgData.SendID {
- tag = true
- }
- case constant.SuperGroupChatType:
- tag = true
- }
- if tag {
- log.ZInfo(ctx, "msg_transfer msg persisting", "msg", string(msg))
- if err = pc.chatLogDatabase.CreateChatLog(&msgFromMQ); err != nil {
- log.ZError(ctx, "Message insert failed", err, "msg", msgFromMQ.String())
- return
- }
- }
- }
-}
-func (PersistentConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
-func (PersistentConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
-
-func (pc *PersistentConsumerHandler) ConsumeClaim(
- sess sarama.ConsumerGroupSession,
- claim sarama.ConsumerGroupClaim,
-) error {
- for msg := range claim.Messages() {
- ctx := pc.persistentConsumerGroup.GetContextFromMsg(msg)
- log.ZDebug(
- ctx,
- "kafka get info to mysql",
- "msgTopic",
- msg.Topic,
- "msgPartition",
- msg.Partition,
- "msg",
- string(msg.Value),
- "key",
- string(msg.Key),
- )
- if len(msg.Value) != 0 {
- pc.handleChatWs2Mysql(ctx, msg, string(msg.Key), sess)
- } else {
- log.ZError(ctx, "msg get from kafka but is nil", nil, "key", msg.Key)
- }
- sess.MarkMessage(msg, "")
- }
- return nil
-}
diff --git a/internal/push/offlinepush/getui/body.go b/internal/push/offlinepush/getui/body.go
index 218ed67b4..01eb22e73 100644
--- a/internal/push/offlinepush/getui/body.go
+++ b/internal/push/offlinepush/getui/body.go
@@ -21,9 +21,9 @@ import (
)
type Resp struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
- Data interface{} `json:"data"`
+ Code int `json:"code"`
+ Msg string `json:"msg"`
+ Data any `json:"data"`
}
func (r *Resp) parseError() (err error) {
diff --git a/internal/push/offlinepush/getui/push.go b/internal/push/offlinepush/getui/push.go
index 1fd65647d..b657c9c23 100644
--- a/internal/push/offlinepush/getui/push.go
+++ b/internal/push/offlinepush/getui/push.go
@@ -159,7 +159,7 @@ func (g *Client) singlePush(ctx context.Context, token, userID string, pushReq P
return g.request(ctx, pushURL, pushReq, token, nil)
}
-func (g *Client) request(ctx context.Context, url string, input interface{}, token string, output interface{}) error {
+func (g *Client) request(ctx context.Context, url string, input any, token string, output any) error {
header := map[string]string{"token": token}
resp := &Resp{}
resp.Data = output
@@ -170,7 +170,7 @@ func (g *Client) postReturn(
ctx context.Context,
url string,
header map[string]string,
- input interface{},
+ input any,
output RespI,
timeout int,
) error {
diff --git a/internal/push/offlinepush/jpush/body/audience.go b/internal/push/offlinepush/jpush/body/audience.go
index f29930886..43a7148b8 100644
--- a/internal/push/offlinepush/jpush/body/audience.go
+++ b/internal/push/offlinepush/jpush/body/audience.go
@@ -23,7 +23,7 @@ const (
)
type Audience struct {
- Object interface{}
+ Object any
audience map[string][]string
}
diff --git a/internal/push/offlinepush/jpush/body/message.go b/internal/push/offlinepush/jpush/body/message.go
index 670cd4c78..e885d1d69 100644
--- a/internal/push/offlinepush/jpush/body/message.go
+++ b/internal/push/offlinepush/jpush/body/message.go
@@ -15,10 +15,10 @@
package body
type Message struct {
- MsgContent string `json:"msg_content"`
- Title string `json:"title,omitempty"`
- ContentType string `json:"content_type,omitempty"`
- Extras map[string]interface{} `json:"extras,omitempty"`
+ MsgContent string `json:"msg_content"`
+ Title string `json:"title,omitempty"`
+ ContentType string `json:"content_type,omitempty"`
+ Extras map[string]any `json:"extras,omitempty"`
}
func (m *Message) SetMsgContent(c string) {
@@ -33,9 +33,9 @@ func (m *Message) SetContentType(c string) {
m.ContentType = c
}
-func (m *Message) SetExtras(key string, value interface{}) {
+func (m *Message) SetExtras(key string, value any) {
if m.Extras == nil {
- m.Extras = make(map[string]interface{})
+ m.Extras = make(map[string]any)
}
m.Extras[key] = value
}
diff --git a/internal/push/offlinepush/jpush/body/platform.go b/internal/push/offlinepush/jpush/body/platform.go
index 9de2b8711..1ef136f2c 100644
--- a/internal/push/offlinepush/jpush/body/platform.go
+++ b/internal/push/offlinepush/jpush/body/platform.go
@@ -29,7 +29,7 @@ const (
)
type Platform struct {
- Os interface{}
+ Os any
osArry []string
}
diff --git a/internal/push/offlinepush/jpush/body/pushobj.go b/internal/push/offlinepush/jpush/body/pushobj.go
index c8c112f69..3dc133d0a 100644
--- a/internal/push/offlinepush/jpush/body/pushobj.go
+++ b/internal/push/offlinepush/jpush/body/pushobj.go
@@ -15,11 +15,11 @@
package body
type PushObj struct {
- Platform interface{} `json:"platform"`
- Audience interface{} `json:"audience"`
- Notification interface{} `json:"notification,omitempty"`
- Message interface{} `json:"message,omitempty"`
- Options interface{} `json:"options,omitempty"`
+ Platform any `json:"platform"`
+ Audience any `json:"audience"`
+ Notification any `json:"notification,omitempty"`
+ Message any `json:"message,omitempty"`
+ Options any `json:"options,omitempty"`
}
func (p *PushObj) SetPlatform(pf *Platform) {
diff --git a/internal/push/offlinepush/jpush/push.go b/internal/push/offlinepush/jpush/push.go
index 44de7ff65..567269f3c 100644
--- a/internal/push/offlinepush/jpush/push.go
+++ b/internal/push/offlinepush/jpush/push.go
@@ -69,11 +69,11 @@ func (j *JPush) Push(ctx context.Context, userIDs []string, title, content strin
pushObj.SetNotification(&no)
pushObj.SetMessage(&msg)
pushObj.SetOptions(&opt)
- var resp interface{}
+ var resp any
return j.request(ctx, pushObj, resp, 5)
}
-func (j *JPush) request(ctx context.Context, po body.PushObj, resp interface{}, timeout int) error {
+func (j *JPush) request(ctx context.Context, po body.PushObj, resp any, timeout int) error {
return http2.PostReturn(
ctx,
config.Config.Push.Jpns.PushUrl,
diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go
index 75a1c1380..2ee8c457f 100644
--- a/internal/push/push_to_client.go
+++ b/internal/push/push_to_client.go
@@ -133,7 +133,7 @@ func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.Msg
return nil
}
-func (p *Pusher) UnmarshalNotificationElem(bytes []byte, t interface{}) error {
+func (p *Pusher) UnmarshalNotificationElem(bytes []byte, t any) error {
var notification sdkws.NotificationElem
if err := json.Unmarshal(bytes, ¬ification); err != nil {
return err
diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go
index d39881b35..88c9ff7ff 100644
--- a/internal/rpc/conversation/conversaion.go
+++ b/internal/rpc/conversation/conversaion.go
@@ -16,6 +16,12 @@ package conversation
import (
"context"
+ "errors"
+
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"google.golang.org/grpc"
@@ -24,13 +30,11 @@ import (
"github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
- "github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
@@ -43,24 +47,24 @@ type conversationServer struct {
}
func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
- db, err := relation.NewGormDB()
+ rdb, err := cache.NewRedis()
if err != nil {
return err
}
- if err := db.AutoMigrate(&tablerelation.ConversationModel{}); err != nil {
+ mongo, err := unrelation.NewMongo()
+ if err != nil {
return err
}
- rdb, err := cache.NewRedis()
+ conversationDB, err := mgo.NewConversationMongo(mongo.GetDatabase())
if err != nil {
return err
}
- conversationDB := relation.NewConversationGorm(db)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)
pbconversation.RegisterConversationServer(server, &conversationServer{
conversationNotificationSender: notification.NewConversationNotificationSender(&msgRpcClient),
groupRpcClient: &groupRpcClient,
- conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx.NewGorm(db)),
+ conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx.NewMongo(mongo.GetClient())),
})
return nil
}
@@ -145,7 +149,7 @@ func (c *conversationServer) SetConversations(ctx context.Context,
conversation.ConversationType = req.Conversation.ConversationType
conversation.UserID = req.Conversation.UserID
conversation.GroupID = req.Conversation.GroupID
- m := make(map[string]interface{})
+ m := make(map[string]any)
if req.Conversation.RecvMsgOpt != nil {
m["recv_msg_opt"] = req.Conversation.RecvMsgOpt.Value
if req.Conversation.RecvMsgOpt.Value != conv.RecvMsgOpt {
@@ -229,11 +233,12 @@ func (c *conversationServer) SetConversations(ctx context.Context,
// 获取超级大群开启免打扰的用户ID.
func (c *conversationServer) GetRecvMsgNotNotifyUserIDs(ctx context.Context, req *pbconversation.GetRecvMsgNotNotifyUserIDsReq) (*pbconversation.GetRecvMsgNotNotifyUserIDsResp, error) {
- userIDs, err := c.conversationDatabase.FindRecvMsgNotNotifyUserIDs(ctx, req.GroupID)
- if err != nil {
- return nil, err
- }
- return &pbconversation.GetRecvMsgNotNotifyUserIDsResp{UserIDs: userIDs}, nil
+ //userIDs, err := c.conversationDatabase.FindRecvMsgNotNotifyUserIDs(ctx, req.GroupID)
+ //if err != nil {
+ // return nil, err
+ //}
+ //return &pbconversation.GetRecvMsgNotNotifyUserIDsResp{UserIDs: userIDs}, nil
+ return nil, errors.New("deprecated")
}
// create conversation without notification for msg redis transfer.
@@ -284,7 +289,7 @@ func (c *conversationServer) CreateGroupChatConversations(ctx context.Context, r
func (c *conversationServer) SetConversationMaxSeq(ctx context.Context, req *pbconversation.SetConversationMaxSeqReq) (*pbconversation.SetConversationMaxSeqResp, error) {
if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, req.OwnerUserID, req.ConversationID,
- map[string]interface{}{"max_seq": req.MaxSeq}); err != nil {
+ map[string]any{"max_seq": req.MaxSeq}); err != nil {
return nil, err
}
return &pbconversation.SetConversationMaxSeqResp{}, nil
diff --git a/internal/rpc/friend/black.go b/internal/rpc/friend/black.go
index fee2d5480..54cdbb2cc 100644
--- a/internal/rpc/friend/black.go
+++ b/internal/rpc/friend/black.go
@@ -27,19 +27,11 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
-func (s *friendServer) GetPaginationBlacks(
- ctx context.Context,
- req *pbfriend.GetPaginationBlacksReq,
-) (resp *pbfriend.GetPaginationBlacksResp, err error) {
+func (s *friendServer) GetPaginationBlacks(ctx context.Context, req *pbfriend.GetPaginationBlacksReq) (resp *pbfriend.GetPaginationBlacksResp, err error) {
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
- var pageNumber, showNumber int32
- if req.Pagination != nil {
- pageNumber = req.Pagination.PageNumber
- showNumber = req.Pagination.ShowNumber
- }
- blacks, total, err := s.blackDatabase.FindOwnerBlacks(ctx, req.UserID, pageNumber, showNumber)
+ total, blacks, err := s.blackDatabase.FindOwnerBlacks(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@@ -63,10 +55,7 @@ func (s *friendServer) IsBlack(ctx context.Context, req *pbfriend.IsBlackReq) (*
return resp, nil
}
-func (s *friendServer) RemoveBlack(
- ctx context.Context,
- req *pbfriend.RemoveBlackReq,
-) (*pbfriend.RemoveBlackResp, error) {
+func (s *friendServer) RemoveBlack(ctx context.Context, req *pbfriend.RemoveBlackReq) (*pbfriend.RemoveBlackResp, error) {
if err := s.userRpcClient.Access(ctx, req.OwnerUserID); err != nil {
return nil, err
}
@@ -74,9 +63,6 @@ func (s *friendServer) RemoveBlack(
return nil, err
}
s.notificationSender.BlackDeletedNotification(ctx, req)
- if err := CallbackAfterRemoveBlack(ctx, req); err != nil {
- return nil, err
- }
return &pbfriend.RemoveBlackResp{}, nil
}
@@ -88,9 +74,6 @@ func (s *friendServer) AddBlack(ctx context.Context, req *pbfriend.AddBlackReq)
if err != nil {
return nil, err
}
- if err := CallbackBeforeAddBlack(ctx, req); err != nil {
- return nil, err
- }
black := relation.BlackModel{
OwnerUserID: req.OwnerUserID,
BlockUserID: req.BlackUserID,
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index 6e6b6d377..7f22c9d0d 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -17,6 +17,8 @@ package friend
import (
"context"
+ "github.com/OpenIMSDK/tools/tx"
+
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
@@ -32,13 +34,13 @@ import (
pbfriend "github.com/OpenIMSDK/protocol/friend"
registry "github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
)
@@ -52,49 +54,65 @@ type friendServer struct {
}
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
- db, err := relation.NewGormDB()
+ // Initialize MongoDB
+ mongo, err := unrelation.NewMongo()
if err != nil {
return err
}
- if err := db.AutoMigrate(&tablerelation.FriendModel{}, &tablerelation.FriendRequestModel{}, &tablerelation.BlackModel{}); err != nil {
+
+ // Initialize Redis
+ rdb, err := cache.NewRedis()
+ if err != nil {
return err
}
- rdb, err := cache.NewRedis()
+
+ friendMongoDB, err := mgo.NewFriendMongo(mongo.GetDatabase())
if err != nil {
return err
}
- blackDB := relation.NewBlackGorm(db)
- friendDB := relation.NewFriendGorm(db)
+
+ friendRequestMongoDB, err := mgo.NewFriendRequestMongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
+
+ blackMongoDB, err := mgo.NewBlackMongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
+
+ // Initialize RPC clients
userRpcClient := rpcclient.NewUserRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)
+
+ // Initialize notification sender
notificationSender := notification.NewFriendNotificationSender(
&msgRpcClient,
notification.WithRpcFunc(userRpcClient.GetUsersInfo),
)
+ // Register Friend server with refactored MongoDB and Redis integrations
pbfriend.RegisterFriendServer(server, &friendServer{
friendDatabase: controller.NewFriendDatabase(
- friendDB,
- relation.NewFriendRequestGorm(db),
- cache.NewFriendCacheRedis(rdb, friendDB, cache.GetDefaultOpt()),
- tx.NewGorm(db),
+ friendMongoDB,
+ friendRequestMongoDB,
+ cache.NewFriendCacheRedis(rdb, friendMongoDB, cache.GetDefaultOpt()),
+ tx.NewMongo(mongo.GetClient()),
),
blackDatabase: controller.NewBlackDatabase(
- blackDB,
- cache.NewBlackCacheRedis(rdb, blackDB, cache.GetDefaultOpt()),
+ blackMongoDB,
+ cache.NewBlackCacheRedis(rdb, blackMongoDB, cache.GetDefaultOpt()),
),
userRpcClient: &userRpcClient,
notificationSender: notificationSender,
RegisterCenter: client,
conversationRpcClient: rpcclient.NewConversationRpcClient(client),
})
+
return nil
}
// ok.
-func (s *friendServer) ApplyToAddFriend(
- ctx context.Context,
- req *pbfriend.ApplyToAddFriendReq,
-) (resp *pbfriend.ApplyToAddFriendResp, err error) {
+func (s *friendServer) ApplyToAddFriend(ctx context.Context, req *pbfriend.ApplyToAddFriendReq) (resp *pbfriend.ApplyToAddFriendResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.ApplyToAddFriendResp{}
if err := authverify.CheckAccessV3(ctx, req.FromUserID); err != nil {
@@ -127,10 +145,7 @@ func (s *friendServer) ApplyToAddFriend(
}
// ok.
-func (s *friendServer) ImportFriends(
- ctx context.Context,
- req *pbfriend.ImportFriendReq,
-) (resp *pbfriend.ImportFriendResp, err error) {
+func (s *friendServer) ImportFriends(ctx context.Context, req *pbfriend.ImportFriendReq) (resp *pbfriend.ImportFriendResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := authverify.CheckAdmin(ctx); err != nil {
return nil, err
@@ -165,10 +180,7 @@ func (s *friendServer) ImportFriends(
}
// ok.
-func (s *friendServer) RespondFriendApply(
- ctx context.Context,
- req *pbfriend.RespondFriendApplyReq,
-) (resp *pbfriend.RespondFriendApplyResp, err error) {
+func (s *friendServer) RespondFriendApply(ctx context.Context, req *pbfriend.RespondFriendApplyReq) (resp *pbfriend.RespondFriendApplyResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.RespondFriendApplyResp{}
if err := authverify.CheckAccessV3(ctx, req.ToUserID); err != nil {
@@ -204,10 +216,7 @@ func (s *friendServer) RespondFriendApply(
}
// ok.
-func (s *friendServer) DeleteFriend(
- ctx context.Context,
- req *pbfriend.DeleteFriendReq,
-) (resp *pbfriend.DeleteFriendResp, err error) {
+func (s *friendServer) DeleteFriend(ctx context.Context, req *pbfriend.DeleteFriendReq) (resp *pbfriend.DeleteFriendResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.DeleteFriendResp{}
if err := s.userRpcClient.Access(ctx, req.OwnerUserID); err != nil {
@@ -228,10 +237,7 @@ func (s *friendServer) DeleteFriend(
}
// ok.
-func (s *friendServer) SetFriendRemark(
- ctx context.Context,
- req *pbfriend.SetFriendRemarkReq,
-) (resp *pbfriend.SetFriendRemarkResp, err error) {
+func (s *friendServer) SetFriendRemark(ctx context.Context, req *pbfriend.SetFriendRemarkReq) (resp *pbfriend.SetFriendRemarkResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err = CallbackBeforeSetFriendRemark(ctx, req); err != nil && err != errs.ErrCallbackContinue {
@@ -256,10 +262,7 @@ func (s *friendServer) SetFriendRemark(
}
// ok.
-func (s *friendServer) GetDesignatedFriends(
- ctx context.Context,
- req *pbfriend.GetDesignatedFriendsReq,
-) (resp *pbfriend.GetDesignatedFriendsResp, err error) {
+func (s *friendServer) GetDesignatedFriends(ctx context.Context, req *pbfriend.GetDesignatedFriendsReq) (resp *pbfriend.GetDesignatedFriendsResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.GetDesignatedFriendsResp{}
if utils.Duplicate(req.FriendUserIDs) {
@@ -290,15 +293,12 @@ func (s *friendServer) GetDesignatedFriendsApply(ctx context.Context,
}
// ok 获取接收到的好友申请(即别人主动申请的).
-func (s *friendServer) GetPaginationFriendsApplyTo(
- ctx context.Context,
- req *pbfriend.GetPaginationFriendsApplyToReq,
-) (resp *pbfriend.GetPaginationFriendsApplyToResp, err error) {
+func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context, req *pbfriend.GetPaginationFriendsApplyToReq) (resp *pbfriend.GetPaginationFriendsApplyToResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
- friendRequests, total, err := s.friendDatabase.PageFriendRequestToMe(ctx, req.UserID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, friendRequests, err := s.friendDatabase.PageFriendRequestToMe(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@@ -312,16 +312,13 @@ func (s *friendServer) GetPaginationFriendsApplyTo(
}
// ok 获取主动发出去的好友申请列表.
-func (s *friendServer) GetPaginationFriendsApplyFrom(
- ctx context.Context,
- req *pbfriend.GetPaginationFriendsApplyFromReq,
-) (resp *pbfriend.GetPaginationFriendsApplyFromResp, err error) {
+func (s *friendServer) GetPaginationFriendsApplyFrom(ctx context.Context, req *pbfriend.GetPaginationFriendsApplyFromReq) (resp *pbfriend.GetPaginationFriendsApplyFromResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.GetPaginationFriendsApplyFromResp{}
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
- friendRequests, total, err := s.friendDatabase.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, friendRequests, err := s.friendDatabase.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@@ -334,10 +331,7 @@ func (s *friendServer) GetPaginationFriendsApplyFrom(
}
// ok.
-func (s *friendServer) IsFriend(
- ctx context.Context,
- req *pbfriend.IsFriendReq,
-) (resp *pbfriend.IsFriendResp, err error) {
+func (s *friendServer) IsFriend(ctx context.Context, req *pbfriend.IsFriendReq) (resp *pbfriend.IsFriendResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.IsFriendResp{}
resp.InUser1Friends, resp.InUser2Friends, err = s.friendDatabase.CheckIn(ctx, req.UserID1, req.UserID2)
@@ -347,15 +341,12 @@ func (s *friendServer) IsFriend(
return resp, nil
}
-func (s *friendServer) GetPaginationFriends(
- ctx context.Context,
- req *pbfriend.GetPaginationFriendsReq,
-) (resp *pbfriend.GetPaginationFriendsResp, err error) {
+func (s *friendServer) GetPaginationFriends(ctx context.Context, req *pbfriend.GetPaginationFriendsReq) (resp *pbfriend.GetPaginationFriendsResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
- friends, total, err := s.friendDatabase.PageOwnerFriends(ctx, req.UserID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, friends, err := s.friendDatabase.PageOwnerFriends(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@@ -368,10 +359,7 @@ func (s *friendServer) GetPaginationFriends(
return resp, nil
}
-func (s *friendServer) GetFriendIDs(
- ctx context.Context,
- req *pbfriend.GetFriendIDsReq,
-) (resp *pbfriend.GetFriendIDsResp, err error) {
+func (s *friendServer) GetFriendIDs(ctx context.Context, req *pbfriend.GetFriendIDsReq) (resp *pbfriend.GetFriendIDsResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
diff --git a/internal/rpc/group/cache.go b/internal/rpc/group/cache.go
index 23c57ff89..fc387736d 100644
--- a/internal/rpc/group/cache.go
+++ b/internal/rpc/group/cache.go
@@ -26,7 +26,7 @@ func (s *groupServer) GetGroupInfoCache(
ctx context.Context,
req *pbgroup.GetGroupInfoCacheReq,
) (resp *pbgroup.GetGroupInfoCacheResp, err error) {
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -38,7 +38,7 @@ func (s *groupServer) GetGroupMemberCache(
ctx context.Context,
req *pbgroup.GetGroupMemberCacheReq,
) (resp *pbgroup.GetGroupMemberCacheResp, err error) {
- members, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.GroupMemberID)
+ members, err := s.db.TakeGroupMember(ctx, req.GroupID, req.GroupMemberID)
if err != nil {
return nil, err
}
diff --git a/internal/rpc/group/db_map.go b/internal/rpc/group/db_map.go
index f793582f8..07084873c 100644
--- a/internal/rpc/group/db_map.go
+++ b/internal/rpc/group/db_map.go
@@ -27,7 +27,7 @@ import (
func UpdateGroupInfoMap(ctx context.Context, group *sdkws.GroupInfoForSet) map[string]any {
m := make(map[string]any)
if group.GroupName != "" {
- m["name"] = group.GroupName
+ m["group_name"] = group.GroupName
}
if group.Notification != "" {
m["notification"] = group.Notification
diff --git a/internal/rpc/group/fill.go b/internal/rpc/group/fill.go
index cb47d9f6e..ac539de19 100644
--- a/internal/rpc/group/fill.go
+++ b/internal/rpc/group/fill.go
@@ -17,119 +17,9 @@ package group
import (
"context"
- "github.com/OpenIMSDK/tools/utils"
-
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
-func (s *groupServer) FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
- members, err := s.GroupDatabase.FindGroupMember(ctx, groupIDs, userIDs, roleLevels)
- if err != nil {
- return nil, err
- }
- emptyUserIDs := make(map[string]struct{})
- for _, member := range members {
- if member.Nickname == "" || member.FaceURL == "" {
- emptyUserIDs[member.UserID] = struct{}{}
- }
- }
- if len(emptyUserIDs) > 0 {
- users, err := s.User.GetPublicUserInfoMap(ctx, utils.Keys(emptyUserIDs), true)
- if err != nil {
- return nil, err
- }
- for i, member := range members {
- user, ok := users[member.UserID]
- if !ok {
- continue
- }
- if member.Nickname == "" {
- members[i].Nickname = user.Nickname
- }
- if member.FaceURL == "" {
- members[i].FaceURL = user.FaceURL
- }
- }
- }
- return members, nil
-}
-
-func (s *groupServer) TakeGroupMember(
- ctx context.Context,
- groupID string,
- userID string,
-) (*relationtb.GroupMemberModel, error) {
- member, err := s.GroupDatabase.TakeGroupMember(ctx, groupID, userID)
- if err != nil {
- return nil, err
- }
- if member.Nickname == "" || member.FaceURL == "" {
- user, err := s.User.GetPublicUserInfo(ctx, userID)
- if err != nil {
- return nil, err
- }
- if member.Nickname == "" {
- member.Nickname = user.Nickname
- }
- if member.FaceURL == "" {
- member.FaceURL = user.FaceURL
- }
- }
- return member, nil
-}
-
-func (s *groupServer) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
- owner, err := s.GroupDatabase.TakeGroupOwner(ctx, groupID)
- if err != nil {
- return nil, err
- }
- if owner.Nickname == "" || owner.FaceURL == "" {
- user, err := s.User.GetUserInfo(ctx, owner.UserID)
- if err != nil {
- return nil, err
- }
- if owner.Nickname == "" {
- owner.Nickname = user.Nickname
- }
- if owner.FaceURL == "" {
- owner.FaceURL = user.FaceURL
- }
- }
- return owner, nil
-}
-
-func (s *groupServer) PageGetGroupMember(
- ctx context.Context,
- groupID string,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupMemberModel, error) {
- total, members, err := s.GroupDatabase.PageGetGroupMember(ctx, groupID, pageNumber, showNumber)
- if err != nil {
- return 0, nil, err
- }
- emptyUserIDs := make(map[string]struct{})
- for _, member := range members {
- if member.Nickname == "" || member.FaceURL == "" {
- emptyUserIDs[member.UserID] = struct{}{}
- }
- }
- if len(emptyUserIDs) > 0 {
- users, err := s.User.GetPublicUserInfoMap(ctx, utils.Keys(emptyUserIDs), true)
- if err != nil {
- return 0, nil, err
- }
- for i, member := range members {
- user, ok := users[member.UserID]
- if !ok {
- continue
- }
- if member.Nickname == "" {
- members[i].Nickname = user.Nickname
- }
- if member.FaceURL == "" {
- members[i].FaceURL = user.FaceURL
- }
- }
- }
- return total, members, nil
+func (s *groupServer) PopulateGroupMember(ctx context.Context, members ...*relationtb.GroupMemberModel) error {
+ return s.Notification.PopulateGroupMember(ctx, members...)
}
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index 67cd70817..5992ed031 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -16,24 +16,24 @@ package group
import (
"context"
- "crypto/md5"
- "encoding/binary"
- "encoding/json"
"fmt"
+ "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"math/big"
"math/rand"
"strconv"
"strings"
"time"
- "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
+ pbconversation "github.com/OpenIMSDK/protocol/conversation"
+ "github.com/OpenIMSDK/protocol/wrapperspb"
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+ "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/grouphash"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
- pbconversation "github.com/OpenIMSDK/protocol/conversation"
- "github.com/OpenIMSDK/protocol/wrapperspb"
-
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
"github.com/OpenIMSDK/tools/mw/specialerror"
@@ -54,24 +54,28 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
)
func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
- db, err := relation.NewGormDB()
+ mongo, err := unrelation.NewMongo()
if err != nil {
return err
}
- if err := db.AutoMigrate(&relationtb.GroupModel{}, &relationtb.GroupMemberModel{}, &relationtb.GroupRequestModel{}); err != nil {
+ rdb, err := cache.NewRedis()
+ if err != nil {
return err
}
- mongo, err := unrelation.NewMongo()
+ groupDB, err := mgo.NewGroupMongo(mongo.GetDatabase())
if err != nil {
return err
}
- rdb, err := cache.NewRedis()
+ groupMemberDB, err := mgo.NewGroupMember(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
+ groupRequestDB, err := mgo.NewGroupRequestMgo(mongo.GetDatabase())
if err != nil {
return err
}
@@ -79,8 +83,8 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
msgRpcClient := rpcclient.NewMessageRpcClient(client)
conversationRpcClient := rpcclient.NewConversationRpcClient(client)
var gs groupServer
- database := controller.InitGroupDatabase(db, rdb, mongo.GetDatabase(), gs.groupMemberHashCode)
- gs.GroupDatabase = database
+ database := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, tx.NewMongo(mongo.GetClient()), grouphash.NewGroupHashFromGroupServer(&gs))
+ gs.db = database
gs.User = userRpcClient
gs.Notification = notification.NewGroupNotificationSender(database, &msgRpcClient, &userRpcClient, func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error) {
users, err := userRpcClient.GetUsersInfo(ctx, userIDs)
@@ -92,24 +96,11 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
gs.conversationRpcClient = conversationRpcClient
gs.msgRpcClient = msgRpcClient
pbgroup.RegisterGroupServer(server, &gs)
- //pbgroup.RegisterGroupServer(server, &groupServer{
- // GroupDatabase: database,
- // User: userRpcClient,
- // Notification: notification.NewGroupNotificationSender(database, &msgRpcClient, &userRpcClient, func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error) {
- // users, err := userRpcClient.GetUsersInfo(ctx, userIDs)
- // if err != nil {
- // return nil, err
- // }
- // return utils.Slice(users, func(e *sdkws.UserInfo) notification.CommonUser { return e }), nil
- // }),
- // conversationRpcClient: conversationRpcClient,
- // msgRpcClient: msgRpcClient,
- //})
return nil
}
type groupServer struct {
- GroupDatabase controller.GroupDatabase
+ db controller.GroupDatabase
User rpcclient.UserRpcClient
Notification *notification.GroupNotificationSender
conversationRpcClient rpcclient.ConversationRpcClient
@@ -118,11 +109,13 @@ type groupServer struct {
func (s *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgroup.NotificationUserInfoUpdateReq) (*pbgroup.NotificationUserInfoUpdateResp, error) {
defer log.ZDebug(ctx, "return")
-
- members, err := s.GroupDatabase.FindGroupMember(ctx, nil, []string{req.UserID}, nil)
+ members, err := s.db.FindGroupMemberUser(ctx, nil, req.UserID)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
groupIDs := make([]string, 0, len(members))
for _, member := range members {
if member.Nickname != "" && member.FaceURL != "" {
@@ -136,7 +129,7 @@ func (s *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgro
log.ZError(ctx, "NotificationUserInfoUpdate setGroupMemberInfo notification failed", err, "groupID", groupID)
}
}
- if err := s.GroupDatabase.DeleteGroupMemberHash(ctx, groupIDs); err != nil {
+ if err := s.db.DeleteGroupMemberHash(ctx, groupIDs); err != nil {
log.ZError(ctx, "NotificationUserInfoUpdate DeleteGroupMemberHash", err, "groupID", groupIDs)
}
@@ -145,7 +138,7 @@ func (s *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgro
func (s *groupServer) CheckGroupAdmin(ctx context.Context, groupID string) error {
if !authverify.IsAppManagerUid(ctx) {
- groupMember, err := s.GroupDatabase.TakeGroupMember(ctx, groupID, mcontext.GetOpUserID(ctx))
+ groupMember, err := s.db.TakeGroupMember(ctx, groupID, mcontext.GetOpUserID(ctx))
if err != nil {
return err
}
@@ -175,7 +168,7 @@ func (s *groupServer) IsNotFound(err error) bool {
func (s *groupServer) GenGroupID(ctx context.Context, groupID *string) error {
if *groupID != "" {
- _, err := s.GroupDatabase.TakeGroup(ctx, *groupID)
+ _, err := s.db.TakeGroup(ctx, *groupID)
if err == nil {
return errs.ErrGroupIDExisted.Wrap("group id existed " + *groupID)
} else if s.IsNotFound(err) {
@@ -189,7 +182,7 @@ func (s *groupServer) GenGroupID(ctx context.Context, groupID *string) error {
bi := big.NewInt(0)
bi.SetString(id[0:8], 16)
id = bi.String()
- _, err := s.GroupDatabase.TakeGroup(ctx, id)
+ _, err := s.db.TakeGroup(ctx, id)
if err == nil {
continue
} else if s.IsNotFound(err) {
@@ -203,12 +196,12 @@ func (s *groupServer) GenGroupID(ctx context.Context, groupID *string) error {
}
func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupReq) (*pbgroup.CreateGroupResp, error) {
+ if req.GroupInfo.GroupType != constant.WorkingGroup {
+ return nil, errs.ErrArgs.Wrap(fmt.Sprintf("group type only supports %d", constant.WorkingGroup))
+ }
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
}
@@ -256,28 +249,36 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
if err := joinGroup(req.OwnerUserID, constant.GroupOwner); err != nil {
return nil, err
}
- if req.GroupInfo.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.CreateSuperGroup(ctx, group.GroupID, userIDs); err != nil {
+ for _, userID := range req.AdminUserIDs {
+ if err := joinGroup(userID, constant.GroupAdmin); err != nil {
return nil, err
}
- } else {
- for _, userID := range req.AdminUserIDs {
- if err := joinGroup(userID, constant.GroupAdmin); err != nil {
- return nil, err
- }
- }
- for _, userID := range req.MemberUserIDs {
- if err := joinGroup(userID, constant.GroupOrdinaryUsers); err != nil {
- return nil, err
- }
+ }
+ for _, userID := range req.MemberUserIDs {
+ if err := joinGroup(userID, constant.GroupOrdinaryUsers); err != nil {
+ return nil, err
}
}
- if err := s.GroupDatabase.CreateGroup(ctx, []*relationtb.GroupModel{group}, groupMembers); err != nil {
+ if err := s.db.CreateGroup(ctx, []*relationtb.GroupModel{group}, groupMembers); err != nil {
return nil, err
}
resp := &pbgroup.CreateGroupResp{GroupInfo: &sdkws.GroupInfo{}}
resp.GroupInfo = convert.Db2PbGroupInfo(group, req.OwnerUserID, uint32(len(userIDs)))
resp.GroupInfo.MemberCount = uint32(len(userIDs))
+ tips := &sdkws.GroupCreatedTips{
+ Group: resp.GroupInfo,
+ OperationTime: group.CreateTime.UnixMilli(),
+ GroupOwnerUser: s.groupMemberDB2PB(groupMembers[0], userMap[groupMembers[0].UserID].AppMangerLevel),
+ }
+ for _, member := range groupMembers {
+ member.Nickname = userMap[member.UserID].Nickname
+ tips.MemberList = append(tips.MemberList, s.groupMemberDB2PB(member, userMap[member.UserID].AppMangerLevel))
+ if member.UserID == opUserID {
+ tips.OpUser = s.groupMemberDB2PB(member, userMap[member.UserID].AppMangerLevel)
+ break
+ }
+ }
+ s.Notification.GroupCreatedNotification(ctx, tips)
if req.GroupInfo.GroupType == constant.SuperGroup {
go func() {
for _, userID := range userIDs {
@@ -320,35 +321,32 @@ func (s *groupServer) GetJoinedGroupList(ctx context.Context, req *pbgroup.GetJo
if err := authverify.CheckAccessV3(ctx, req.FromUserID); err != nil {
return nil, err
}
- var pageNumber, showNumber int32
- if req.Pagination != nil {
- pageNumber = req.Pagination.PageNumber
- showNumber = req.Pagination.ShowNumber
- }
- // total, members, err := s.GroupDatabase.PageGroupMember(ctx, nil, []string{req.FromUserID}, nil, pageNumber, showNumber)
- total, members, err := s.GroupDatabase.PageGetJoinGroup(ctx, req.FromUserID, pageNumber, showNumber)
+ total, members, err := s.db.PageGetJoinGroup(ctx, req.FromUserID, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
+ resp.Total = uint32(total)
if len(members) == 0 {
return resp, nil
}
groupIDs := utils.Slice(members, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
- groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
+ groups, err := s.db.FindGroup(ctx, groupIDs)
if err != nil {
return nil, err
}
- groupMemberNum, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
@@ -373,7 +371,7 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
if utils.Duplicate(req.InvitedUserIDs) {
return nil, errs.ErrArgs.Wrap("userID duplicate")
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -392,14 +390,14 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
var opUserID string
if !authverify.IsAppManagerUid(ctx) {
opUserID = mcontext.GetOpUserID(ctx)
- groupMembers, err := s.FindGroupMember(ctx, []string{req.GroupID}, []string{opUserID}, nil)
+ var err error
+ groupMember, err = s.db.TakeGroupMember(ctx, req.GroupID, opUserID)
if err != nil {
return nil, err
}
- if len(groupMembers) <= 0 {
- return nil, errs.ErrNoPermission.Wrap("not in group")
+ if err := s.PopulateGroupMember(ctx, groupMember); err != nil {
+ return nil, err
}
- groupMember = groupMembers[0]
}
if err := CallbackBeforeInviteUserToGroup(ctx, req); err != nil {
@@ -419,8 +417,7 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
HandledTime: time.Unix(0, 0),
})
}
-
- if err := s.GroupDatabase.CreateGroupRequest(ctx, requests); err != nil {
+ if err := s.db.CreateGroupRequest(ctx, requests); err != nil {
return nil, err
}
for _, request := range requests {
@@ -435,75 +432,43 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
}
}
}
-
- if group.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.CreateSuperGroupMember(ctx, req.GroupID, req.InvitedUserIDs); err != nil {
- return nil, err
- }
- if err := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, req.InvitedUserIDs); err != nil {
- return nil, err
- }
- for _, userID := range req.InvitedUserIDs {
- s.Notification.SuperGroupNotification(ctx, userID, userID)
- }
- } else {
- opUserID := mcontext.GetOpUserID(ctx)
- var groupMembers []*relationtb.GroupMemberModel
- for _, userID := range req.InvitedUserIDs {
- member := &relationtb.GroupMemberModel{
- GroupID: req.GroupID,
- UserID: userID,
- RoleLevel: constant.GroupOrdinaryUsers,
- OperatorUserID: opUserID,
- InviterUserID: opUserID,
- JoinSource: constant.JoinByInvitation,
- JoinTime: time.Now(),
- MuteEndTime: time.UnixMilli(0),
- }
- if err := CallbackBeforeMemberJoinGroup(ctx, member, group.Ex); err != nil {
- return nil, err
- }
- groupMembers = append(groupMembers, member)
- }
- if err := s.GroupDatabase.CreateGroup(ctx, nil, groupMembers); err != nil {
- return nil, err
+ var groupMembers []*relationtb.GroupMemberModel
+ for _, userID := range req.InvitedUserIDs {
+ member := &relationtb.GroupMemberModel{
+ GroupID: req.GroupID,
+ UserID: userID,
+ RoleLevel: constant.GroupOrdinaryUsers,
+ OperatorUserID: opUserID,
+ InviterUserID: opUserID,
+ JoinSource: constant.JoinByInvitation,
+ JoinTime: time.Now(),
+ MuteEndTime: time.UnixMilli(0),
}
- if err := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, req.InvitedUserIDs); err != nil {
+ if err := CallbackBeforeMemberJoinGroup(ctx, member, group.Ex); err != nil {
return nil, err
}
- s.Notification.MemberInvitedNotification(ctx, req.GroupID, req.Reason, req.InvitedUserIDs)
+ groupMembers = append(groupMembers, member)
}
+ if err := s.db.CreateGroup(ctx, nil, groupMembers); err != nil {
+ return nil, err
+ }
+ if err := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, req.InvitedUserIDs); err != nil {
+ return nil, err
+ }
+ s.Notification.MemberInvitedNotification(ctx, req.GroupID, req.Reason, req.InvitedUserIDs)
return resp, nil
}
func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGroupAllMemberReq) (*pbgroup.GetGroupAllMemberResp, error) {
- resp := &pbgroup.GetGroupAllMemberResp{}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
- if err != nil {
- return nil, err
- }
- if group.GroupType == constant.SuperGroup {
- return nil, errs.ErrArgs.Wrap("unsupported super group")
- }
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, nil, nil)
+ members, err := s.db.FindGroupMemberAll(ctx, req.GroupID)
if err != nil {
return nil, err
}
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
+ resp := &pbgroup.GetGroupAllMemberResp{}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
@@ -511,20 +476,21 @@ func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGro
func (s *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGroupMemberListReq) (*pbgroup.GetGroupMemberListResp, error) {
resp := &pbgroup.GetGroupMemberListResp{}
- total, members, err := s.PageGetGroupMember(ctx, req.GroupID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
- log.ZDebug(ctx, "GetGroupMemberList", "total", total, "members", members, "length", len(members))
+ total, members, err := s.db.PageGetGroupMember(ctx, req.GroupID, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
+ resp.Total = uint32(total)
resp.Members = utils.Batch(convert.Db2PbGroupMember, members)
- log.ZDebug(ctx, "GetGroupMemberList", "resp", resp, "length", len(resp.Members))
return resp, nil
}
func (s *groupServer) KickGroupMember(ctx context.Context, req *pbgroup.KickGroupMemberReq) (*pbgroup.KickGroupMemberResp, error) {
resp := &pbgroup.KickGroupMemberResp{}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -538,92 +504,85 @@ func (s *groupServer) KickGroupMember(ctx context.Context, req *pbgroup.KickGrou
if utils.IsContain(opUserID, req.KickedUserIDs) {
return nil, errs.ErrArgs.Wrap("opUserID in KickedUserIDs")
}
- if group.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.DeleteSuperGroupMember(ctx, req.GroupID, req.KickedUserIDs); err != nil {
- return nil, err
- }
- go func() {
- for _, userID := range req.KickedUserIDs {
- s.Notification.SuperGroupNotification(ctx, userID, userID)
- }
- }()
- } else {
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, append(req.KickedUserIDs, opUserID), nil)
- if err != nil {
- return nil, err
- }
- memberMap := make(map[string]*relationtb.GroupMemberModel)
- for i, member := range members {
- memberMap[member.UserID] = members[i]
+ members, err := s.db.FindGroupMembers(ctx, req.GroupID, append(req.KickedUserIDs, opUserID))
+ if err != nil {
+ return nil, err
+ }
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
+ memberMap := make(map[string]*relationtb.GroupMemberModel)
+ for i, member := range members {
+ memberMap[member.UserID] = members[i]
+ }
+ isAppManagerUid := authverify.IsAppManagerUid(ctx)
+ opMember := memberMap[opUserID]
+ for _, userID := range req.KickedUserIDs {
+ member, ok := memberMap[userID]
+ if !ok {
+ return nil, errs.ErrUserIDNotFound.Wrap(userID)
}
- isAppManagerUid := authverify.IsAppManagerUid(ctx)
- opMember := memberMap[opUserID]
- for _, userID := range req.KickedUserIDs {
- member, ok := memberMap[userID]
- if !ok {
- return nil, errs.ErrUserIDNotFound.Wrap(userID)
+ if !isAppManagerUid {
+ if opMember == nil {
+ return nil, errs.ErrNoPermission.Wrap("opUserID no in group")
}
- if !isAppManagerUid {
- if opMember == nil {
- return nil, errs.ErrNoPermission.Wrap("opUserID no in group")
- }
- switch opMember.RoleLevel {
- case constant.GroupOwner:
- case constant.GroupAdmin:
- if member.RoleLevel == constant.GroupOwner || member.RoleLevel == constant.GroupAdmin {
- return nil, errs.ErrNoPermission.Wrap("group admins cannot remove the group owner and other admins")
- }
- case constant.GroupOrdinaryUsers:
- return nil, errs.ErrNoPermission.Wrap("opUserID no permission")
- default:
- return nil, errs.ErrNoPermission.Wrap("opUserID roleLevel unknown")
+ switch opMember.RoleLevel {
+ case constant.GroupOwner:
+ case constant.GroupAdmin:
+ if member.RoleLevel == constant.GroupOwner || member.RoleLevel == constant.GroupAdmin {
+ return nil, errs.ErrNoPermission.Wrap("group admins cannot remove the group owner and other admins")
}
+ case constant.GroupOrdinaryUsers:
+ return nil, errs.ErrNoPermission.Wrap("opUserID no permission")
+ default:
+ return nil, errs.ErrNoPermission.Wrap("opUserID roleLevel unknown")
}
}
- num, err := s.GroupDatabase.FindGroupMemberNum(ctx, req.GroupID)
- if err != nil {
- return nil, err
- }
- owner, err := s.FindGroupMember(ctx, []string{req.GroupID}, nil, []int32{constant.GroupOwner})
- if err != nil {
- return nil, err
- }
- if err := s.GroupDatabase.DeleteGroupMember(ctx, group.GroupID, req.KickedUserIDs); err != nil {
- return nil, err
- }
- tips := &sdkws.MemberKickedTips{
- Group: &sdkws.GroupInfo{
- GroupID: group.GroupID,
- GroupName: group.GroupName,
- Notification: group.Notification,
- Introduction: group.Introduction,
- FaceURL: group.FaceURL,
- // OwnerUserID: owner[0].UserID,
- CreateTime: group.CreateTime.UnixMilli(),
- MemberCount: num,
- Ex: group.Ex,
- Status: group.Status,
- CreatorUserID: group.CreatorUserID,
- GroupType: group.GroupType,
- NeedVerification: group.NeedVerification,
- LookMemberInfo: group.LookMemberInfo,
- ApplyMemberFriend: group.ApplyMemberFriend,
- NotificationUpdateTime: group.NotificationUpdateTime.UnixMilli(),
- NotificationUserID: group.NotificationUserID,
- },
- KickedUserList: []*sdkws.GroupMemberFullInfo{},
- }
- if len(owner) > 0 {
- tips.Group.OwnerUserID = owner[0].UserID
- }
- if opMember, ok := memberMap[opUserID]; ok {
- tips.OpUser = convert.Db2PbGroupMember(opMember)
- }
- for _, userID := range req.KickedUserIDs {
- tips.KickedUserList = append(tips.KickedUserList, convert.Db2PbGroupMember(memberMap[userID]))
- }
- s.Notification.MemberKickedNotification(ctx, tips)
}
+ num, err := s.db.FindGroupMemberNum(ctx, req.GroupID)
+ if err != nil {
+ return nil, err
+ }
+ ownerUserIDs, err := s.db.GetGroupRoleLevelMemberIDs(ctx, req.GroupID, constant.GroupOwner)
+ if err != nil {
+ return nil, err
+ }
+ var ownerUserID string
+ if len(ownerUserIDs) > 0 {
+ ownerUserID = ownerUserIDs[0]
+ }
+ if err := s.db.DeleteGroupMember(ctx, group.GroupID, req.KickedUserIDs); err != nil {
+ return nil, err
+ }
+ tips := &sdkws.MemberKickedTips{
+ Group: &sdkws.GroupInfo{
+ GroupID: group.GroupID,
+ GroupName: group.GroupName,
+ Notification: group.Notification,
+ Introduction: group.Introduction,
+ FaceURL: group.FaceURL,
+ OwnerUserID: ownerUserID,
+ CreateTime: group.CreateTime.UnixMilli(),
+ MemberCount: num,
+ Ex: group.Ex,
+ Status: group.Status,
+ CreatorUserID: group.CreatorUserID,
+ GroupType: group.GroupType,
+ NeedVerification: group.NeedVerification,
+ LookMemberInfo: group.LookMemberInfo,
+ ApplyMemberFriend: group.ApplyMemberFriend,
+ NotificationUpdateTime: group.NotificationUpdateTime.UnixMilli(),
+ NotificationUserID: group.NotificationUserID,
+ },
+ KickedUserList: []*sdkws.GroupMemberFullInfo{},
+ }
+ if opMember, ok := memberMap[opUserID]; ok {
+ tips.OpUser = convert.Db2PbGroupMember(opMember)
+ }
+ for _, userID := range req.KickedUserIDs {
+ tips.KickedUserList = append(tips.KickedUserList, convert.Db2PbGroupMember(memberMap[userID]))
+ }
+ s.Notification.MemberKickedNotification(ctx, tips)
if err := s.deleteMemberAndSetConversationSeq(ctx, req.GroupID, req.KickedUserIDs); err != nil {
return nil, err
}
@@ -642,32 +601,21 @@ func (s *groupServer) GetGroupMembersInfo(ctx context.Context, req *pbgroup.GetG
if req.GroupID == "" {
return nil, errs.ErrArgs.Wrap("groupID empty")
}
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, req.UserIDs, nil)
+ members, err := s.db.FindGroupMembers(ctx, req.GroupID, req.UserIDs)
if err != nil {
return nil, err
}
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
}
func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.GetGroupApplicationListReq) (*pbgroup.GetGroupApplicationListResp, error) {
- groupIDs, err := s.GroupDatabase.FindUserManagedGroupID(ctx, req.FromUserID)
+ groupIDs, err := s.db.FindUserManagedGroupID(ctx, req.FromUserID)
if err != nil {
return nil, err
}
@@ -675,11 +623,11 @@ func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
if len(groupIDs) == 0 {
return resp, nil
}
- total, groupRequests, err := s.GroupDatabase.PageGroupRequest(ctx, groupIDs, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, groupRequests, err := s.db.PageGroupRequest(ctx, groupIDs, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
+ resp.Total = uint32(total)
if len(groupRequests) == 0 {
return resp, nil
}
@@ -693,7 +641,7 @@ func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
if err != nil {
return nil, err
}
- groups, err := s.GroupDatabase.FindGroup(ctx, utils.Distinct(groupIDs))
+ groups, err := s.db.FindGroup(ctx, utils.Distinct(groupIDs))
if err != nil {
return nil, err
}
@@ -703,14 +651,17 @@ func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
if ids := utils.Single(utils.Keys(groupMap), groupIDs); len(ids) > 0 {
return nil, errs.ErrGroupIDNotFound.Wrap(strings.Join(ids, ","))
}
- groupMemberNumMap, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNumMap, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, owners...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
@@ -729,18 +680,21 @@ func (s *groupServer) GetGroupsInfo(ctx context.Context, req *pbgroup.GetGroupsI
if len(req.GroupIDs) == 0 {
return nil, errs.ErrArgs.Wrap("groupID is empty")
}
- groups, err := s.GroupDatabase.FindGroup(ctx, req.GroupIDs)
+ groups, err := s.db.FindGroup(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
- groupMemberNumMap, err := s.GroupDatabase.MapGroupMemberNum(ctx, req.GroupIDs)
+ groupMemberNumMap, err := s.db.MapGroupMemberNum(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
- owners, err := s.FindGroupMember(ctx, req.GroupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, owners...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
@@ -760,7 +714,7 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
return nil, errs.ErrArgs.Wrap("HandleResult unknown")
}
if !authverify.IsAppManagerUid(ctx) {
- groupMember, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
+ groupMember, err := s.db.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
if err != nil {
return nil, err
}
@@ -768,11 +722,11 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
return nil, errs.ErrNoPermission.Wrap("no group owner or admin")
}
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
- groupRequest, err := s.GroupDatabase.TakeGroupRequest(ctx, req.GroupID, req.FromUserID)
+ groupRequest, err := s.db.TakeGroupRequest(ctx, req.GroupID, req.FromUserID)
if err != nil {
return nil, err
}
@@ -780,7 +734,7 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
return nil, errs.ErrGroupRequestHandled.Wrap("group request already processed")
}
var inGroup bool
- if _, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.FromUserID); err == nil {
+ if _, err := s.db.TakeGroupMember(ctx, req.GroupID, req.FromUserID); err == nil {
inGroup = true // 已经在群里了
} else if !s.IsNotFound(err) {
return nil, err
@@ -808,7 +762,7 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
}
}
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 {
+ if err := s.db.HandlerGroupRequest(ctx, req.GroupID, req.FromUserID, req.HandledMsg, req.HandleResult, member); err != nil {
return nil, err
}
switch req.HandleResult {
@@ -835,7 +789,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
if err != nil {
return nil, err
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -853,7 +807,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
if err = CallbackApplyJoinGroupBefore(ctx, reqCall); err != nil {
return nil, err
}
- _, err = s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.InviterUserID)
+ _, err = s.db.TakeGroupMember(ctx, req.GroupID, req.InviterUserID)
if err == nil {
return nil, errs.ErrArgs.Wrap("already in group")
} else if !s.IsNotFound(err) && utils.Unwrap(err) != errs.ErrRecordNotFound {
@@ -862,9 +816,6 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
log.ZInfo(ctx, "JoinGroup.groupInfo", "group", group, "eq", group.NeedVerification == constant.Directly)
resp = &pbgroup.JoinGroupResp{}
if group.NeedVerification == constant.Directly {
- if group.GroupType == constant.SuperGroup {
- return nil, errs.ErrGroupTypeNotSupport.Wrap()
- }
groupMember := &relationtb.GroupMemberModel{
GroupID: group.GroupID,
UserID: user.UserID,
@@ -877,7 +828,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
if err := CallbackBeforeMemberJoinGroup(ctx, groupMember, group.Ex); err != nil {
return nil, err
}
- if err := s.GroupDatabase.CreateGroup(ctx, nil, []*relationtb.GroupMemberModel{groupMember}); err != nil {
+ if err := s.db.CreateGroup(ctx, nil, []*relationtb.GroupMemberModel{groupMember}); err != nil {
return nil, err
}
@@ -898,7 +849,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
ReqTime: time.Now(),
HandledTime: time.Unix(0, 0),
}
- if err := s.GroupDatabase.CreateGroupRequest(ctx, []*relationtb.GroupRequestModel{&groupRequest}); err != nil {
+ if err := s.db.CreateGroupRequest(ctx, []*relationtb.GroupRequestModel{&groupRequest}); err != nil {
return nil, err
}
s.Notification.JoinGroupApplicationNotification(ctx, req)
@@ -914,29 +865,21 @@ func (s *groupServer) QuitGroup(ctx context.Context, req *pbgroup.QuitGroupReq)
return nil, err
}
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ member, err := s.db.TakeGroupMember(ctx, req.GroupID, req.UserID)
if err != nil {
return nil, err
}
- if group.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.DeleteSuperGroupMember(ctx, req.GroupID, []string{req.UserID}); err != nil {
- return nil, err
- }
- _ = s.Notification.SuperGroupNotification(ctx, req.UserID, req.UserID)
- } else {
- info, err := s.TakeGroupMember(ctx, req.GroupID, req.UserID)
- if err != nil {
- return nil, err
- }
- if info.RoleLevel == constant.GroupOwner {
- return nil, errs.ErrNoPermission.Wrap("group owner can't quit")
- }
- err = s.GroupDatabase.DeleteGroupMember(ctx, req.GroupID, []string{req.UserID})
- if err != nil {
- return nil, err
- }
- _ = s.Notification.MemberQuitNotification(ctx, s.groupMemberDB2PB(info, 0))
+ if member.RoleLevel == constant.GroupOwner {
+ return nil, errs.ErrNoPermission.Wrap("group owner can't quit")
}
+ if err := s.PopulateGroupMember(ctx, member); err != nil {
+ return nil, err
+ }
+ err = s.db.DeleteGroupMember(ctx, req.GroupID, []string{req.UserID})
+ if err != nil {
+ return nil, err
+ }
+ _ = s.Notification.MemberQuitNotification(ctx, s.groupMemberDB2PB(member, 0))
if err := s.deleteMemberAndSetConversationSeq(ctx, req.GroupID, []string{req.UserID}); err != nil {
return nil, err
}
@@ -961,18 +904,21 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
var opMember *relationtb.GroupMemberModel
if !authverify.IsAppManagerUid(ctx) {
var err error
- opMember, err = s.TakeGroupMember(ctx, req.GroupInfoForSet.GroupID, mcontext.GetOpUserID(ctx))
+ opMember, err = s.db.TakeGroupMember(ctx, req.GroupInfoForSet.GroupID, mcontext.GetOpUserID(ctx))
if err != nil {
return nil, err
}
if !(opMember.RoleLevel == constant.GroupOwner || opMember.RoleLevel == constant.GroupAdmin) {
return nil, errs.ErrNoPermission.Wrap("no group owner or admin")
}
+ if err := s.PopulateGroupMember(ctx, opMember); err != nil {
+ return nil, err
+ }
}
if err := CallbackBeforeSetGroupInfo(ctx, req); err != nil {
return nil, err
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupInfoForSet.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupInfoForSet.GroupID)
if err != nil {
return nil, err
}
@@ -980,22 +926,25 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
return nil, utils.Wrap(errs.ErrDismissedAlready, "")
}
resp := &pbgroup.SetGroupInfoResp{}
- count, err := s.GroupDatabase.FindGroupMemberNum(ctx, group.GroupID)
+ count, err := s.db.FindGroupMemberNum(ctx, group.GroupID)
if err != nil {
return nil, err
}
- owner, err := s.TakeGroupOwner(ctx, group.GroupID)
+ owner, err := s.db.TakeGroupOwner(ctx, group.GroupID)
if err != nil {
return nil, err
}
- data := UpdateGroupInfoMap(ctx, req.GroupInfoForSet)
- if len(data) == 0 {
+ if err := s.PopulateGroupMember(ctx, owner); err != nil {
+ return nil, err
+ }
+ update := UpdateGroupInfoMap(ctx, req.GroupInfoForSet)
+ if len(update) == 0 {
return resp, nil
}
- if err := s.GroupDatabase.UpdateGroup(ctx, group.GroupID, data); err != nil {
+ if err := s.db.UpdateGroup(ctx, group.GroupID, update); err != nil {
return nil, err
}
- group, err = s.GroupDatabase.TakeGroup(ctx, req.GroupInfoForSet.GroupID)
+ group, err = s.db.TakeGroup(ctx, req.GroupInfoForSet.GroupID)
if err != nil {
return nil, err
}
@@ -1007,38 +956,33 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
if opMember != nil {
tips.OpUser = s.groupMemberDB2PB(opMember, 0)
}
- var num int
+ num := len(update)
if req.GroupInfoForSet.Notification != "" {
- go func() {
- nctx := mcontext.NewCtx("@@@" + mcontext.GetOperationID(ctx))
+ num--
+ func() {
conversation := &pbconversation.ConversationReq{
ConversationID: msgprocessor.GetConversationIDBySessionType(constant.SuperGroupChatType, req.GroupInfoForSet.GroupID),
ConversationType: constant.SuperGroupChatType,
GroupID: req.GroupInfoForSet.GroupID,
}
- resp, err := s.GetGroupMemberUserIDs(nctx, &pbgroup.GetGroupMemberUserIDsReq{GroupID: req.GroupInfoForSet.GroupID})
+ resp, err := s.GetGroupMemberUserIDs(ctx, &pbgroup.GetGroupMemberUserIDsReq{GroupID: req.GroupInfoForSet.GroupID})
if err != nil {
log.ZWarn(ctx, "GetGroupMemberIDs", err)
return
}
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.GroupNotification}
- if err := s.conversationRpcClient.SetConversations(nctx, resp.UserIDs, conversation); err != nil {
+ if err := s.conversationRpcClient.SetConversations(ctx, resp.UserIDs, conversation); err != nil {
log.ZWarn(ctx, "SetConversations", err, resp.UserIDs, conversation)
}
}()
- num++
- s.Notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{Group: tips.Group, OpUser: tips.OpUser})
- }
- switch len(data) - num {
- case 0:
- case 1:
- if req.GroupInfoForSet.GroupName == "" {
- s.Notification.GroupInfoSetNotification(ctx, tips)
- } else {
- s.Notification.GroupInfoSetNameNotification(ctx, &sdkws.GroupInfoSetNameTips{Group: tips.Group, OpUser: tips.OpUser})
- }
- default:
- s.Notification.GroupInfoSetNotification(ctx, tips)
+ _ = s.Notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{Group: tips.Group, OpUser: tips.OpUser})
+ }
+ if req.GroupInfoForSet.GroupName != "" {
+ num--
+ _ = s.Notification.GroupInfoSetNameNotification(ctx, &sdkws.GroupInfoSetNameTips{Group: tips.Group, OpUser: tips.OpUser})
+ }
+ if num > 0 {
+ _ = s.Notification.GroupInfoSetNotification(ctx, tips)
}
if err := CallbackAfterSetGroupInfo(ctx, req); err != nil {
return nil, err
@@ -1048,7 +992,7 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) (*pbgroup.TransferGroupOwnerResp, error) {
resp := &pbgroup.TransferGroupOwnerResp{}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -1058,10 +1002,13 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
if req.OldOwnerUserID == req.NewOwnerUserID {
return nil, errs.ErrArgs.Wrap("OldOwnerUserID == NewOwnerUserID")
}
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, []string{req.OldOwnerUserID, req.NewOwnerUserID}, nil)
+ members, err := s.db.FindGroupMembers(ctx, req.GroupID, []string{req.OldOwnerUserID, req.NewOwnerUserID})
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
memberMap := utils.SliceToMap(members, func(e *relationtb.GroupMemberModel) string { return e.UserID })
if ids := utils.Single([]string{req.OldOwnerUserID, req.NewOwnerUserID}, utils.Keys(memberMap)); len(ids) > 0 {
return nil, errs.ErrArgs.Wrap("user not in group " + strings.Join(ids, ","))
@@ -1079,7 +1026,7 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
return nil, errs.ErrNoPermission.Wrap("no permission transfer group owner")
}
}
- if err := s.GroupDatabase.TransferGroupOwner(ctx, req.GroupID, req.OldOwnerUserID, req.NewOwnerUserID, newOwner.RoleLevel); err != nil {
+ if err := s.db.TransferGroupOwner(ctx, req.GroupID, req.OldOwnerUserID, req.NewOwnerUserID, newOwner.RoleLevel); err != nil {
return nil, err
}
@@ -1097,10 +1044,12 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
err error
)
if req.GroupID != "" {
- groups, err = s.GroupDatabase.FindGroup(ctx, []string{req.GroupID})
+ groups, err = s.db.FindGroup(ctx, []string{req.GroupID})
resp.Total = uint32(len(groups))
} else {
- resp.Total, groups, err = s.GroupDatabase.SearchGroup(ctx, req.GroupName, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ var total int64
+ total, groups, err = s.db.SearchGroup(ctx, req.GroupName, req.Pagination)
+ resp.Total = uint32(total)
}
if err != nil {
return nil, err
@@ -1108,14 +1057,14 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
groupIDs := utils.Slice(groups, func(e *relationtb.GroupModel) string {
return e.GroupID
})
- ownerMembers, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ ownerMembers, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
ownerMemberMap := utils.SliceToMap(ownerMembers, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
- groupMemberNumMap, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNumMap, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
@@ -1135,26 +1084,15 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
func (s *groupServer) GetGroupMembersCMS(ctx context.Context, req *pbgroup.GetGroupMembersCMSReq) (*pbgroup.GetGroupMembersCMSResp, error) {
resp := &pbgroup.GetGroupMembersCMSResp{}
- total, members, err := s.GroupDatabase.SearchGroupMember(ctx, req.UserName, []string{req.GroupID}, nil, nil, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, members, err := s.db.SearchGroupMember(ctx, req.UserName, req.GroupID, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ resp.Total = uint32(total)
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
@@ -1166,37 +1104,35 @@ func (s *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou
if err != nil {
return nil, err
}
- var pageNumber, showNumber int32
- if req.Pagination != nil {
- pageNumber = req.Pagination.PageNumber
- showNumber = req.Pagination.ShowNumber
- }
- total, requests, err := s.GroupDatabase.PageGroupRequestUser(ctx, req.UserID, pageNumber, showNumber)
+ total, requests, err := s.db.PageGroupRequestUser(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
+ resp.Total = uint32(total)
if len(requests) == 0 {
return resp, nil
}
groupIDs := utils.Distinct(utils.Slice(requests, func(e *relationtb.GroupRequestModel) string {
return e.GroupID
}))
- groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
+ groups, err := s.db.FindGroup(ctx, groupIDs)
if err != nil {
return nil, err
}
groupMap := utils.SliceToMap(groups, func(e *relationtb.GroupModel) string {
return e.GroupID
})
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, owners...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
- groupMemberNum, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
@@ -1213,7 +1149,7 @@ func (s *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou
func (s *groupServer) DismissGroup(ctx context.Context, req *pbgroup.DismissGroupReq) (*pbgroup.DismissGroupResp, error) {
defer log.ZInfo(ctx, "DismissGroup.return")
resp := &pbgroup.DismissGroupResp{}
- owner, err := s.TakeGroupOwner(ctx, req.GroupID)
+ owner, err := s.db.TakeGroupOwner(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -1222,41 +1158,34 @@ func (s *groupServer) DismissGroup(ctx context.Context, req *pbgroup.DismissGrou
return nil, errs.ErrNoPermission.Wrap("not group owner")
}
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ if err := s.PopulateGroupMember(ctx, owner); err != nil {
+ return nil, err
+ }
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
if req.DeleteMember == false && group.Status == constant.GroupStatusDismissed {
return nil, errs.ErrDismissedAlready.Wrap("group status is dismissed")
}
- //if group.Status == constant.GroupStatusDismissed {
- // return nil, errs.ErrArgs.Wrap("group status is dismissed")
- //}
- if err := s.GroupDatabase.DismissGroup(ctx, req.GroupID, req.DeleteMember); err != nil {
+ if err := s.db.DismissGroup(ctx, req.GroupID, req.DeleteMember); err != nil {
return nil, err
}
- if group.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.DeleteSuperGroup(ctx, group.GroupID); err != nil {
+ if !req.DeleteMember {
+ num, err := s.db.FindGroupMemberNum(ctx, req.GroupID)
+ if err != nil {
return nil, err
}
- } else {
- if !req.DeleteMember {
- num, err := s.GroupDatabase.FindGroupMemberNum(ctx, req.GroupID)
- if err != nil {
- return nil, err
- }
- // s.Notification.GroupDismissedNotification(ctx, req)
- tips := &sdkws.GroupDismissedTips{
- Group: s.groupDB2PB(group, owner.UserID, num),
- OpUser: &sdkws.GroupMemberFullInfo{},
- }
- if mcontext.GetOpUserID(ctx) == owner.UserID {
- tips.OpUser = s.groupMemberDB2PB(owner, 0)
- }
- s.Notification.GroupDismissedNotification(ctx, tips)
+ tips := &sdkws.GroupDismissedTips{
+ Group: s.groupDB2PB(group, owner.UserID, num),
+ OpUser: &sdkws.GroupMemberFullInfo{},
}
+ if mcontext.GetOpUserID(ctx) == owner.UserID {
+ tips.OpUser = s.groupMemberDB2PB(owner, 0)
+ }
+ s.Notification.GroupDismissedNotification(ctx, tips)
}
- membersID, err := s.GroupDatabase.FindGroupMemberUserID(ctx, group.GroupID)
+ membersID, err := s.db.FindGroupMemberUserID(ctx, group.GroupID)
if err != nil {
return nil, err
}
@@ -1275,15 +1204,15 @@ func (s *groupServer) DismissGroup(ctx context.Context, req *pbgroup.DismissGrou
func (s *groupServer) MuteGroupMember(ctx context.Context, req *pbgroup.MuteGroupMemberReq) (*pbgroup.MuteGroupMemberResp, error) {
resp := &pbgroup.MuteGroupMemberResp{}
- //if err := tokenverify.CheckAccessV3(ctx, req.UserID); err != nil {
- // return nil, err
- //}
- member, err := s.TakeGroupMember(ctx, req.GroupID, req.UserID)
+ member, err := s.db.TakeGroupMember(ctx, req.GroupID, req.UserID)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, member); err != nil {
+ return nil, err
+ }
if !authverify.IsAppManagerUid(ctx) {
- opMember, err := s.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
+ opMember, err := s.db.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
if err != nil {
return nil, err
}
@@ -1301,7 +1230,7 @@ func (s *groupServer) MuteGroupMember(ctx context.Context, req *pbgroup.MuteGrou
}
}
data := UpdateGroupMemberMutedTimeMap(time.Now().Add(time.Second * time.Duration(req.MutedSeconds)))
- if err := s.GroupDatabase.UpdateGroupMember(ctx, member.GroupID, member.UserID, data); err != nil {
+ if err := s.db.UpdateGroupMember(ctx, member.GroupID, member.UserID, data); err != nil {
return nil, err
}
s.Notification.GroupMemberMutedNotification(ctx, req.GroupID, req.UserID, req.MutedSeconds)
@@ -1309,29 +1238,15 @@ func (s *groupServer) MuteGroupMember(ctx context.Context, req *pbgroup.MuteGrou
}
func (s *groupServer) CancelMuteGroupMember(ctx context.Context, req *pbgroup.CancelMuteGroupMemberReq) (*pbgroup.CancelMuteGroupMemberResp, error) {
- resp := &pbgroup.CancelMuteGroupMemberResp{}
- //member, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.UserID)
- //if err != nil {
- // return nil, err
- //}
- //if !(mcontext.GetOpUserID(ctx) == req.UserID || tokenverify.IsAppManagerUid(ctx)) {
- // opMember, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
- // if err != nil {
- // return nil, err
- // }
- // if opMember.RoleLevel <= member.RoleLevel {
- // return nil, errs.ErrNoPermission.Wrap(fmt.Sprintf("self RoleLevel %d target %d", opMember.RoleLevel, member.RoleLevel))
- // }
- //}
- //if err := tokenverify.CheckAccessV3(ctx, req.UserID); err != nil {
- // return nil, err
- //}
- member, err := s.TakeGroupMember(ctx, req.GroupID, req.UserID)
+ member, err := s.db.TakeGroupMember(ctx, req.GroupID, req.UserID)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, member); err != nil {
+ return nil, err
+ }
if !authverify.IsAppManagerUid(ctx) {
- opMember, err := s.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
+ opMember, err := s.db.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
if err != nil {
return nil, err
}
@@ -1349,11 +1264,11 @@ func (s *groupServer) CancelMuteGroupMember(ctx context.Context, req *pbgroup.Ca
}
}
data := UpdateGroupMemberMutedTimeMap(time.Unix(0, 0))
- if err := s.GroupDatabase.UpdateGroupMember(ctx, member.GroupID, member.UserID, data); err != nil {
+ if err := s.db.UpdateGroupMember(ctx, member.GroupID, member.UserID, data); err != nil {
return nil, err
}
s.Notification.GroupMemberCancelMutedNotification(ctx, req.GroupID, req.UserID)
- return resp, nil
+ return &pbgroup.CancelMuteGroupMemberResp{}, nil
}
func (s *groupServer) MuteGroup(ctx context.Context, req *pbgroup.MuteGroupReq) (*pbgroup.MuteGroupResp, error) {
@@ -1361,7 +1276,7 @@ func (s *groupServer) MuteGroup(ctx context.Context, req *pbgroup.MuteGroupReq)
if err := s.CheckGroupAdmin(ctx, req.GroupID); err != nil {
return nil, err
}
- if err := s.GroupDatabase.UpdateGroup(ctx, req.GroupID, UpdateGroupStatusMap(constant.GroupStatusMuted)); err != nil {
+ if err := s.db.UpdateGroup(ctx, req.GroupID, UpdateGroupStatusMap(constant.GroupStatusMuted)); err != nil {
return nil, err
}
s.Notification.GroupMutedNotification(ctx, req.GroupID)
@@ -1373,7 +1288,7 @@ func (s *groupServer) CancelMuteGroup(ctx context.Context, req *pbgroup.CancelMu
if err := s.CheckGroupAdmin(ctx, req.GroupID); err != nil {
return nil, err
}
- if err := s.GroupDatabase.UpdateGroup(ctx, req.GroupID, UpdateGroupStatusMap(constant.GroupOk)); err != nil {
+ if err := s.db.UpdateGroup(ctx, req.GroupID, UpdateGroupStatusMap(constant.GroupOk)); err != nil {
return nil, err
}
s.Notification.GroupCancelMutedNotification(ctx, req.GroupID)
@@ -1385,97 +1300,90 @@ func (s *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbgroup.SetGr
if len(req.Members) == 0 {
return nil, errs.ErrArgs.Wrap("members empty")
}
+ opUserID := mcontext.GetOpUserID(ctx)
+ if opUserID == "" {
+ return nil, errs.ErrNoPermission.Wrap("no op user id")
+ }
+ isAppManagerUid := authverify.IsAppManagerUid(ctx)
for i := range req.Members {
req.Members[i].FaceURL = nil
}
- duplicateMap := make(map[[2]string]struct{})
- userIDMap := make(map[string]struct{})
- groupIDMap := make(map[string]struct{})
- for _, member := range req.Members {
- key := [...]string{member.GroupID, member.UserID}
- if _, ok := duplicateMap[key]; ok {
- return nil, errs.ErrArgs.Wrap("group user duplicate")
+ groupMembers := make(map[string][]*pbgroup.SetGroupMemberInfo)
+ for i, member := range req.Members {
+ if member.RoleLevel != nil {
+ switch member.RoleLevel.Value {
+ case constant.GroupOwner:
+ return nil, errs.ErrNoPermission.Wrap("cannot set ungroup owner")
+ case constant.GroupAdmin, constant.GroupOrdinaryUsers:
+ default:
+ return nil, errs.ErrArgs.Wrap("invalid role level")
+ }
}
- duplicateMap[key] = struct{}{}
- userIDMap[member.UserID] = struct{}{}
- groupIDMap[member.GroupID] = struct{}{}
- }
- groupIDs := utils.Keys(groupIDMap)
- userIDs := utils.Keys(userIDMap)
- members, err := s.FindGroupMember(ctx, groupIDs, append(userIDs, mcontext.GetOpUserID(ctx)), nil)
- if err != nil {
- return nil, err
- }
- for _, member := range members {
- delete(duplicateMap, [...]string{member.GroupID, member.UserID})
- }
- if len(duplicateMap) > 0 {
- return nil, errs.ErrArgs.Wrap("user not found" + strings.Join(utils.Slice(utils.Keys(duplicateMap), func(e [2]string) string {
- return fmt.Sprintf("[group: %s user: %s]", e[0], e[1])
- }), ","))
+ groupMembers[member.GroupID] = append(groupMembers[member.GroupID], req.Members[i])
}
- memberMap := utils.SliceToMap(members, func(e *relationtb.GroupMemberModel) [2]string {
- return [...]string{e.GroupID, e.UserID}
- })
- if !authverify.IsAppManagerUid(ctx) {
- opUserID := mcontext.GetOpUserID(ctx)
- for _, member := range req.Members {
- if member.RoleLevel != nil {
- switch member.RoleLevel.Value {
- case constant.GroupOrdinaryUsers, constant.GroupAdmin:
- default:
- return nil, errs.ErrArgs.Wrap("invalid role level")
- }
- }
- opMember, ok := memberMap[[...]string{member.GroupID, opUserID}]
- if !ok {
- return nil, errs.ErrArgs.Wrap(fmt.Sprintf("user %s not in group %s", opUserID, member.GroupID))
+ for groupID, members := range groupMembers {
+ temp := make(map[string]struct{})
+ userIDs := make([]string, 0, len(members)+1)
+ for _, member := range members {
+ if _, ok := temp[member.UserID]; ok {
+ return nil, errs.ErrArgs.Wrap(fmt.Sprintf("repeat group %s user %s", member.GroupID, member.UserID))
}
+ temp[member.UserID] = struct{}{}
+ userIDs = append(userIDs, member.UserID)
+ }
+ if _, ok := temp[opUserID]; !ok {
+ userIDs = append(userIDs, opUserID)
+ }
+ dbMembers, err := s.db.FindGroupMembers(ctx, groupID, userIDs)
+ if err != nil {
+ return nil, err
+ }
+ opUserIndex := -1
+ for i, member := range dbMembers {
if member.UserID == opUserID {
- if member.RoleLevel != nil {
- return nil, errs.ErrNoPermission.Wrap("can not change self role level")
- }
- continue
+ opUserIndex = i
+ break
}
- if opMember.RoleLevel == constant.GroupOrdinaryUsers {
- return nil, errs.ErrNoPermission.Wrap("ordinary users can not change other role level")
+ }
+ switch len(userIDs) - len(dbMembers) {
+ case 0:
+ if !isAppManagerUid {
+ roleLevel := dbMembers[opUserIndex].RoleLevel
+ if roleLevel != constant.GroupOwner {
+ switch roleLevel {
+ case constant.GroupAdmin:
+ for _, member := range dbMembers {
+ if member.RoleLevel == constant.GroupOwner {
+ return nil, errs.ErrNoPermission.Wrap("admin can not change group owner")
+ }
+ if member.RoleLevel == constant.GroupAdmin && member.UserID != opUserID {
+ return nil, errs.ErrNoPermission.Wrap("admin can not change other group admin")
+ }
+ }
+ case constant.GroupOrdinaryUsers:
+ for _, member := range dbMembers {
+ if !(member.RoleLevel == constant.GroupOrdinaryUsers && member.UserID == opUserID) {
+ return nil, errs.ErrNoPermission.Wrap("ordinary users can not change other role level")
+ }
+ }
+ default:
+ for _, member := range dbMembers {
+ if member.RoleLevel >= roleLevel {
+ return nil, errs.ErrNoPermission.Wrap("can not change higher role level")
+ }
+ }
+ }
+ }
}
- dbMember, ok := memberMap[[...]string{member.GroupID, member.UserID}]
- if !ok {
- return nil, errs.ErrRecordNotFound.Wrap(fmt.Sprintf("user %s not in group %s", member.UserID, member.GroupID))
+ case 1:
+ if opUserIndex >= 0 {
+ return nil, errs.ErrArgs.Wrap("user not in group")
}
- //if opMember.RoleLevel == constant.GroupOwner {
- // continue
- //}
- //if dbMember.RoleLevel == constant.GroupOwner {
- // return nil, errs.ErrNoPermission.Wrap("change group owner")
- //}
- //if opMember.RoleLevel == constant.GroupAdmin && dbMember.RoleLevel == constant.GroupAdmin {
- // return nil, errs.ErrNoPermission.Wrap("admin can not change other admin role info")
- //}
- switch opMember.RoleLevel {
- case constant.GroupOrdinaryUsers:
- return nil, errs.ErrNoPermission.Wrap("ordinary users can not change other role level")
- case constant.GroupAdmin:
- if dbMember.RoleLevel != constant.GroupOrdinaryUsers {
- return nil, errs.ErrNoPermission.Wrap("admin can not change other role level")
- }
- if member.RoleLevel != nil {
- return nil, errs.ErrNoPermission.Wrap("admin can not change other role level")
- }
- case constant.GroupOwner:
- //if member.RoleLevel != nil && member.RoleLevel.Value == constant.GroupOwner {
- // return nil, errs.ErrNoPermission.Wrap("owner only one")
- //}
+ if !isAppManagerUid {
+ return nil, errs.ErrNoPermission.Wrap("user not in group")
}
- }
- }
- for _, member := range req.Members {
- if member.RoleLevel == nil {
- continue
- }
- if memberMap[[...]string{member.GroupID, member.UserID}].RoleLevel == constant.GroupOwner {
- return nil, errs.ErrArgs.Wrap(fmt.Sprintf("group %s user %s is owner", member.GroupID, member.UserID))
+ default:
+ return nil, errs.ErrArgs.Wrap("user not in group")
}
}
for i := 0; i < len(req.Members); i++ {
@@ -1483,7 +1391,7 @@ func (s *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbgroup.SetGr
return nil, err
}
}
- if err = s.GroupDatabase.UpdateGroupMembers(ctx, utils.Slice(req.Members, func(e *pbgroup.SetGroupMemberInfo) *relationtb.BatchUpdateGroupMember {
+ if err := s.db.UpdateGroupMembers(ctx, utils.Slice(req.Members, func(e *pbgroup.SetGroupMemberInfo) *relationtb.BatchUpdateGroupMember {
return &relationtb.BatchUpdateGroupMember{
GroupID: e.GroupID,
UserID: e.UserID,
@@ -1502,10 +1410,7 @@ func (s *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbgroup.SetGr
}
}
if member.Nickname != nil || member.FaceURL != nil || member.Ex != nil {
- log.ZDebug(ctx, "setGroupMemberInfo notification", "member", member.UserID)
- if err := s.Notification.GroupMemberInfoSetNotification(ctx, member.GroupID, member.UserID); err != nil {
- log.ZError(ctx, "setGroupMemberInfo notification failed", err, "member", member.UserID, "groupID", member.GroupID)
- }
+ s.Notification.GroupMemberInfoSetNotification(ctx, member.GroupID, member.UserID)
}
}
for i := 0; i < len(req.Members); i++ {
@@ -1525,7 +1430,7 @@ func (s *groupServer) GetGroupAbstractInfo(ctx context.Context, req *pbgroup.Get
if utils.Duplicate(req.GroupIDs) {
return nil, errs.ErrArgs.Wrap("groupIDs duplicate")
}
- groups, err := s.GroupDatabase.FindGroup(ctx, req.GroupIDs)
+ groups, err := s.db.FindGroup(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
@@ -1534,7 +1439,7 @@ func (s *groupServer) GetGroupAbstractInfo(ctx context.Context, req *pbgroup.Get
})); len(ids) > 0 {
return nil, errs.ErrGroupIDNotFound.Wrap("not found group " + strings.Join(ids, ","))
}
- groupUserMap, err := s.GroupDatabase.MapGroupMemberUserID(ctx, req.GroupIDs)
+ groupUserMap, err := s.db.MapGroupMemberUserID(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
@@ -1553,25 +1458,14 @@ func (s *groupServer) GetUserInGroupMembers(ctx context.Context, req *pbgroup.Ge
if len(req.GroupIDs) == 0 {
return nil, errs.ErrArgs.Wrap("groupIDs empty")
}
- members, err := s.FindGroupMember(ctx, []string{req.UserID}, req.GroupIDs, nil)
+ members, err := s.db.FindGroupMemberUser(ctx, req.GroupIDs, req.UserID)
if err != nil {
return nil, err
}
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
@@ -1579,7 +1473,7 @@ func (s *groupServer) GetUserInGroupMembers(ctx context.Context, req *pbgroup.Ge
func (s *groupServer) GetGroupMemberUserIDs(ctx context.Context, req *pbgroup.GetGroupMemberUserIDsReq) (resp *pbgroup.GetGroupMemberUserIDsResp, err error) {
resp = &pbgroup.GetGroupMemberUserIDsResp{}
- resp.UserIDs, err = s.GroupDatabase.FindGroupMemberUserID(ctx, req.GroupID)
+ resp.UserIDs, err = s.db.FindGroupMemberUserID(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -1591,25 +1485,14 @@ func (s *groupServer) GetGroupMemberRoleLevel(ctx context.Context, req *pbgroup.
if len(req.RoleLevels) == 0 {
return nil, errs.ErrArgs.Wrap("RoleLevels empty")
}
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, nil, req.RoleLevels)
+ members, err := s.db.FindGroupMemberRoleLevels(ctx, req.GroupID, req.RoleLevels)
if err != nil {
return nil, err
}
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
@@ -1617,7 +1500,7 @@ func (s *groupServer) GetGroupMemberRoleLevel(ctx context.Context, req *pbgroup.
func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *pbgroup.GetGroupUsersReqApplicationListReq) (*pbgroup.GetGroupUsersReqApplicationListResp, error) {
resp := &pbgroup.GetGroupUsersReqApplicationListResp{}
- total, requests, err := s.GroupDatabase.FindGroupRequests(ctx, req.GroupID, req.UserIDs)
+ requests, err := s.db.FindGroupRequests(ctx, req.GroupID, req.UserIDs)
if err != nil {
return nil, err
}
@@ -1627,7 +1510,7 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
groupIDs := utils.Distinct(utils.Slice(requests, func(e *relationtb.GroupRequestModel) string {
return e.GroupID
}))
- groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
+ groups, err := s.db.FindGroup(ctx, groupIDs)
if err != nil {
return nil, err
}
@@ -1637,14 +1520,17 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
if ids := utils.Single(groupIDs, utils.Keys(groupMap)); len(ids) > 0 {
return nil, errs.ErrGroupIDNotFound.Wrap(strings.Join(ids, ","))
}
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, owners...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
- groupMemberNum, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
@@ -1655,40 +1541,6 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
}
return convert.Db2PbGroupRequest(e, nil, convert.Db2PbGroupInfo(groupMap[e.GroupID], ownerUserID, groupMemberNum[e.GroupID]))
})
- resp.Total = total
+ resp.Total = int64(len(resp.GroupRequests))
return resp, nil
}
-
-func (s *groupServer) groupMemberHashCode(ctx context.Context, groupID string) (uint64, error) {
- userIDs, err := s.GroupDatabase.FindGroupMemberUserID(ctx, groupID)
- if err != nil {
- return 0, err
- }
- var members []*sdkws.GroupMemberFullInfo
- if len(userIDs) > 0 {
- resp, err := s.GetGroupMembersInfo(ctx, &pbgroup.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs})
- if err != nil {
- return 0, err
- }
- members = resp.Members
- utils.Sort(userIDs, true)
- }
- memberMap := utils.SliceToMap(members, func(e *sdkws.GroupMemberFullInfo) string {
- return e.UserID
- })
- res := make([]*sdkws.GroupMemberFullInfo, 0, len(members))
- for _, userID := range userIDs {
- member, ok := memberMap[userID]
- if !ok {
- continue
- }
- member.AppMangerLevel = 0
- res = append(res, member)
- }
- data, err := json.Marshal(res)
- if err != nil {
- return 0, err
- }
- sum := md5.Sum(data)
- return binary.BigEndian.Uint64(sum[:]), nil
-}
diff --git a/internal/rpc/group/statistics.go b/internal/rpc/group/statistics.go
index 8aeefbee3..d909e9503 100644
--- a/internal/rpc/group/statistics.go
+++ b/internal/rpc/group/statistics.go
@@ -26,16 +26,16 @@ func (s *groupServer) GroupCreateCount(ctx context.Context, req *group.GroupCrea
if req.Start > req.End {
return nil, errs.ErrArgs.Wrap("start > end")
}
- total, err := s.GroupDatabase.CountTotal(ctx, nil)
+ total, err := s.db.CountTotal(ctx, nil)
if err != nil {
return nil, err
}
start := time.UnixMilli(req.Start)
- before, err := s.GroupDatabase.CountTotal(ctx, &start)
+ before, err := s.db.CountTotal(ctx, &start)
if err != nil {
return nil, err
}
- count, err := s.GroupDatabase.CountRangeEverydayTotal(ctx, start, time.UnixMilli(req.End))
+ count, err := s.db.CountRangeEverydayTotal(ctx, start, time.UnixMilli(req.End))
if err != nil {
return nil, err
}
diff --git a/internal/rpc/group/super_group.go b/internal/rpc/group/super_group.go
index 6cd1a2943..f893a79c2 100644
--- a/internal/rpc/group/super_group.go
+++ b/internal/rpc/group/super_group.go
@@ -16,99 +16,15 @@ package group
import (
"context"
- "fmt"
- "strings"
+ "errors"
- "github.com/OpenIMSDK/protocol/constant"
pbgroup "github.com/OpenIMSDK/protocol/group"
- sdkws "github.com/OpenIMSDK/protocol/sdkws"
- "github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/convert"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
)
-func (s *groupServer) GetJoinedSuperGroupList(
- ctx context.Context,
- req *pbgroup.GetJoinedSuperGroupListReq,
-) (*pbgroup.GetJoinedSuperGroupListResp, error) {
- resp := &pbgroup.GetJoinedSuperGroupListResp{}
- groupIDs, err := s.GroupDatabase.FindJoinSuperGroup(ctx, req.UserID)
- if err != nil {
- return nil, err
- }
- if len(groupIDs) == 0 {
- return resp, nil
- }
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
- if err != nil {
- return nil, err
- }
- ownerMap := utils.SliceToMap(owners, func(e *relation.GroupMemberModel) string {
- return e.GroupID
- })
- if ids := utils.Single(groupIDs, utils.Keys(ownerMap)); len(ids) > 0 {
- return nil, errs.ErrData.Wrap(fmt.Sprintf("super group %s not owner", strings.Join(ids, ",")))
- }
- groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
- if err != nil {
- return nil, err
- }
- groupMap := utils.SliceToMap(groups, func(e *relation.GroupModel) string {
- return e.GroupID
- })
- if ids := utils.Single(groupIDs, utils.Keys(groupMap)); len(ids) > 0 {
- return nil, errs.ErrData.Wrap(fmt.Sprintf("super group info %s not found", strings.Join(ids, ",")))
- }
- superGroupMembers, err := s.GroupDatabase.FindSuperGroup(ctx, groupIDs)
- if err != nil {
- return nil, err
- }
- superGroupMemberMap := utils.SliceToMapAny(
- superGroupMembers,
- func(e *unrelation.SuperGroupModel) (string, []string) {
- return e.GroupID, e.MemberIDs
- },
- )
- resp.Groups = utils.Slice(groupIDs, func(groupID string) *sdkws.GroupInfo {
- return convert.Db2PbGroupInfo(groupMap[groupID], ownerMap[groupID].UserID, uint32(len(superGroupMemberMap)))
- })
- return resp, nil
+func (s *groupServer) GetJoinedSuperGroupList(context.Context, *pbgroup.GetJoinedSuperGroupListReq) (*pbgroup.GetJoinedSuperGroupListResp, error) {
+ return nil, errors.New("deprecated")
}
-func (s *groupServer) GetSuperGroupsInfo(
- ctx context.Context,
- req *pbgroup.GetSuperGroupsInfoReq,
-) (resp *pbgroup.GetSuperGroupsInfoResp, err error) {
- resp = &pbgroup.GetSuperGroupsInfoResp{}
- if len(req.GroupIDs) == 0 {
- return nil, errs.ErrArgs.Wrap("groupIDs empty")
- }
- groups, err := s.GroupDatabase.FindGroup(ctx, req.GroupIDs)
- if err != nil {
- return nil, err
- }
- superGroupMembers, err := s.GroupDatabase.FindSuperGroup(ctx, req.GroupIDs)
- if err != nil {
- return nil, err
- }
- superGroupMemberMap := utils.SliceToMapAny(
- superGroupMembers,
- func(e *unrelation.SuperGroupModel) (string, []string) {
- return e.GroupID, e.MemberIDs
- },
- )
- owners, err := s.FindGroupMember(ctx, req.GroupIDs, nil, []int32{constant.GroupOwner})
- if err != nil {
- return nil, err
- }
- ownerMap := utils.SliceToMap(owners, func(e *relation.GroupMemberModel) string {
- return e.GroupID
- })
- resp.GroupInfos = utils.Slice(groups, func(e *relation.GroupModel) *sdkws.GroupInfo {
- return convert.Db2PbGroupInfo(e, ownerMap[e.GroupID].UserID, uint32(len(superGroupMemberMap[e.GroupID])))
- })
- return resp, nil
+func (s *groupServer) GetSuperGroupsInfo(context.Context, *pbgroup.GetSuperGroupsInfoReq) (resp *pbgroup.GetSuperGroupsInfoResp, err error) {
+ return nil, errors.New("deprecated")
}
diff --git a/internal/rpc/msg/utils.go b/internal/rpc/msg/utils.go
index 115df9946..e45d7b395 100644
--- a/internal/rpc/msg/utils.go
+++ b/internal/rpc/msg/utils.go
@@ -15,12 +15,11 @@
package msg
import (
- "github.com/redis/go-redis/v9"
- "gorm.io/gorm"
-
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
+ "github.com/redis/go-redis/v9"
+ "go.mongodb.org/mongo-driver/mongo"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
)
@@ -45,7 +44,7 @@ func isMessageHasReadEnabled(msgData *sdkws.MsgData) bool {
func IsNotFound(err error) bool {
switch utils.Unwrap(err) {
- case redis.Nil, gorm.ErrRecordNotFound:
+ case redis.Nil, mongo.ErrNoDocuments:
return true
default:
return false
diff --git a/internal/rpc/third/log.go b/internal/rpc/third/log.go
index aa83f58f7..57d4f536e 100644
--- a/internal/rpc/third/log.go
+++ b/internal/rpc/third/log.go
@@ -32,11 +32,11 @@ func genLogID() string {
}
func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq) (*third.UploadLogsResp, error) {
- var DBlogs []*relationtb.Log
+ var DBlogs []*relationtb.LogModel
userID := ctx.Value(constant.OpUserID).(string)
platform := constant.PlatformID2Name[int(req.Platform)]
for _, fileURL := range req.FileURLs {
- log := relationtb.Log{
+ log := relationtb.LogModel{
Version: req.Version,
SystemType: req.SystemType,
Platform: platform,
@@ -57,7 +57,7 @@ func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq)
}
}
if log.LogID == "" {
- return nil, errs.ErrData.Wrap("Log id gen error")
+ return nil, errs.ErrData.Wrap("LogModel id gen error")
}
DBlogs = append(DBlogs, &log)
}
@@ -92,8 +92,8 @@ func (t *thirdServer) DeleteLogs(ctx context.Context, req *third.DeleteLogsReq)
return &third.DeleteLogsResp{}, nil
}
-func dbToPbLogInfos(logs []*relationtb.Log) []*third.LogInfo {
- db2pbForLogInfo := func(log *relationtb.Log) *third.LogInfo {
+func dbToPbLogInfos(logs []*relationtb.LogModel) []*third.LogInfo {
+ db2pbForLogInfo := func(log *relationtb.LogModel) *third.LogInfo {
return &third.LogInfo{
Filename: log.FileName,
UserID: log.UserID,
@@ -120,7 +120,7 @@ func (t *thirdServer) SearchLogs(ctx context.Context, req *third.SearchLogsReq)
if req.StartTime > req.EndTime {
return nil, errs.ErrArgs.Wrap("startTime>endTime")
}
- total, logs, err := t.thirdDatabase.SearchLogs(ctx, req.Keyword, time.UnixMilli(req.StartTime), time.UnixMilli(req.EndTime), req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, logs, err := t.thirdDatabase.SearchLogs(ctx, req.Keyword, time.UnixMilli(req.StartTime), time.UnixMilli(req.EndTime), req.Pagination)
if err != nil {
return nil, err
}
@@ -128,18 +128,16 @@ func (t *thirdServer) SearchLogs(ctx context.Context, req *third.SearchLogsReq)
for _, log := range logs {
userIDs = append(userIDs, log.UserID)
}
- users, err := t.thirdDatabase.FindUsers(ctx, userIDs)
+ userMap, err := t.userRpcClient.GetUsersInfoMap(ctx, userIDs)
if err != nil {
return nil, err
}
- IDtoName := make(map[string]string)
- for _, user := range users {
- IDtoName[user.UserID] = user.Nickname
- }
for _, pbLog := range pbLogs {
- pbLog.Nickname = IDtoName[pbLog.UserID]
+ if user, ok := userMap[pbLog.UserID]; ok {
+ pbLog.Nickname = user.Nickname
+ }
}
resp.LogsInfos = pbLogs
- resp.Total = total
+ resp.Total = uint32(total)
return &resp, nil
}
diff --git a/internal/rpc/third/s3.go b/internal/rpc/third/s3.go
index 984af88e1..ca826e805 100644
--- a/internal/rpc/third/s3.go
+++ b/internal/rpc/third/s3.go
@@ -64,7 +64,7 @@ func (t *thirdServer) InitiateMultipartUpload(ctx context.Context, req *third.In
Key: haErr.Object.Key,
Size: haErr.Object.Size,
ContentType: req.ContentType,
- Cause: req.Cause,
+ Group: req.Cause,
CreateTime: time.Now(),
}
if err := t.s3dataBase.SetObject(ctx, obj); err != nil {
@@ -143,7 +143,7 @@ func (t *thirdServer) CompleteMultipartUpload(ctx context.Context, req *third.Co
Key: result.Key,
Size: result.Size,
ContentType: req.ContentType,
- Cause: req.Cause,
+ Group: req.Cause,
CreateTime: time.Now(),
}
if err := t.s3dataBase.SetObject(ctx, obj); err != nil {
diff --git a/internal/rpc/third/third.go b/internal/rpc/third/third.go
index eed3d4802..7a63d3526 100644
--- a/internal/rpc/third/third.go
+++ b/internal/rpc/third/third.go
@@ -17,15 +17,17 @@ package third
import (
"context"
"fmt"
-
"net/url"
"time"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
+
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/cos"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/kodo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/minio"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/oss"
+
"google.golang.org/grpc"
"github.com/OpenIMSDK/protocol/third"
@@ -34,13 +36,22 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
)
func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
+ mongo, err := unrelation.NewMongo()
+ if err != nil {
+ return err
+ }
+ logdb, err := mgo.NewLogMongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
+ s3db, err := mgo.NewS3Mongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
apiURL := config.Config.Object.ApiURL
if apiURL == "" {
return fmt.Errorf("api url is empty")
@@ -56,13 +67,6 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
if err != nil {
return err
}
- db, err := relation.NewGormDB()
- if err != nil {
- return err
- }
- if err := db.AutoMigrate(&relationtb.ObjectModel{}); err != nil {
- return err
- }
// 根据配置文件策略选择 oss 方式
enable := config.Config.Object.Enable
var o s3.Interface
@@ -73,25 +77,17 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
o, err = cos.NewCos()
case "oss":
o, err = oss.NewOSS()
- case "kodo":
- o, err = kodo.NewKodo()
default:
err = fmt.Errorf("invalid object enable: %s", enable)
}
if err != nil {
return err
}
- //specialerror.AddErrHandler(func(err error) errs.CodeError {
- // if o.IsNotFound(err) {
- // return errs.ErrRecordNotFound
- // }
- // return nil
- //})
third.RegisterThirdServer(server, &thirdServer{
apiURL: apiURL,
- thirdDatabase: controller.NewThirdDatabase(cache.NewMsgCacheModel(rdb), db),
+ thirdDatabase: controller.NewThirdDatabase(cache.NewMsgCacheModel(rdb), logdb),
userRpcClient: rpcclient.NewUserRpcClient(client),
- s3dataBase: controller.NewS3Database(rdb, o, relation.NewObjectInfo(db)),
+ s3dataBase: controller.NewS3Database(rdb, o, s3db),
defaultExpire: time.Hour * 24 * 7,
})
return nil
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index f4164dbf2..77da408aa 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -20,11 +20,14 @@ import (
"strings"
"time"
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+
"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/v3/pkg/authverify"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
@@ -35,7 +38,6 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
@@ -55,10 +57,6 @@ type userServer struct {
}
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
- db, err := relation.NewGormDB()
- if err != nil {
- return err
- }
rdb, err := cache.NewRedis()
if err != nil {
return err
@@ -67,9 +65,6 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
if err != nil {
return err
}
- if err := db.AutoMigrate(&tablerelation.UserModel{}); err != nil {
- return err
- }
users := make([]*tablerelation.UserModel, 0)
if len(config.Config.Manager.UserID) != len(config.Config.Manager.Nickname) {
return errors.New("len(config.Config.Manager.AppManagerUid) != len(config.Config.Manager.Nickname)")
@@ -77,10 +72,13 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
for k, v := range config.Config.Manager.UserID {
users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.Manager.Nickname[k], AppMangerLevel: constant.AppAdmin})
}
- userDB := relation.NewUserGorm(db)
+ userDB, err := mgo.NewUserMongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
cache := cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
- database := controller.NewUserDatabase(userDB, cache, tx.NewGorm(db), userMongoDB)
+ database := controller.NewUserDatabase(userDB, cache, tx.NewMongo(mongo.GetClient()), userMongoDB)
friendRpcClient := rpcclient.NewFriendRpcClient(client)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)
@@ -118,12 +116,8 @@ func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserI
if err := CallbackBeforeUpdateUserInfo(ctx, req); err != nil {
return nil, err
}
- user := convert.UserPb2DB(req.UserInfo)
- if err != nil {
- return nil, err
- }
- err = s.Update(ctx, user)
- if err != nil {
+ data := convert.UserPb2DBMap(req.UserInfo)
+ if err := s.UpdateByMap(ctx, req.UserInfo.UserID, data); err != nil {
return nil, err
}
_ = s.friendNotificationSender.UserInfoUpdatedNotification(ctx, req.UserInfo.UserID)
@@ -153,7 +147,7 @@ func (s *userServer) SetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.Se
if _, err := s.FindWithError(ctx, []string{req.UserID}); err != nil {
return nil, err
}
- m := make(map[string]interface{}, 1)
+ m := make(map[string]any, 1)
m["global_recv_msg_opt"] = req.GlobalRecvMsgOpt
if err := s.UpdateByMap(ctx, req.UserID, m); err != nil {
return nil, err
@@ -175,7 +169,7 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
if err != nil {
return nil, err
}
- userIDs := make(map[string]interface{}, 0)
+ userIDs := make(map[string]any, 0)
for _, v := range users {
userIDs[v.UserID] = nil
}
@@ -192,12 +186,7 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
}
func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPaginationUsersReq) (resp *pbuser.GetPaginationUsersResp, err error) {
- var pageNumber, showNumber int32
- if req.Pagination != nil {
- pageNumber = req.Pagination.PageNumber
- showNumber = req.Pagination.ShowNumber
- }
- users, total, err := s.Page(ctx, pageNumber, showNumber)
+ total, users, err := s.Page(ctx, req.Pagination)
if err != nil {
return nil, err
}
@@ -269,11 +258,11 @@ func (s *userServer) GetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.Ge
// GetAllUserID Get user account by page.
func (s *userServer) GetAllUserID(ctx context.Context, req *pbuser.GetAllUserIDReq) (resp *pbuser.GetAllUserIDResp, err error) {
- userIDs, err := s.UserDatabase.GetAllUserID(ctx, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, userIDs, err := s.UserDatabase.GetAllUserID(ctx, req.Pagination)
if err != nil {
return nil, err
}
- return &pbuser.GetAllUserIDResp{UserIDs: userIDs}, nil
+ return &pbuser.GetAllUserIDResp{Total: int32(total), UserIDs: userIDs}, nil
}
// SubscribeOrCancelUsersStatus Subscribe online or cancel online users.
diff --git a/internal/tools/conversation.go b/internal/tools/conversation.go
index 05d963a17..0d0275339 100644
--- a/internal/tools/conversation.go
+++ b/internal/tools/conversation.go
@@ -19,6 +19,8 @@ import (
"math/rand"
"time"
+ "github.com/OpenIMSDK/protocol/sdkws"
+
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
@@ -91,7 +93,11 @@ func (c *MsgTool) ConversationsDestructMsgs() {
}
for i := 0; i < count; i++ {
pageNumber := rand.Int63() % maxPage
- conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, int32(pageNumber), batchNum)
+ pagination := &sdkws.RequestPagination{
+ PageNumber: int32(pageNumber),
+ ShowNumber: batchNum,
+ }
+ conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination)
if err != nil {
log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber)
continue
@@ -133,7 +139,7 @@ func (c *MsgTool) ConversationsDestructMsgs() {
continue
}
if len(seqs) > 0 {
- if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]interface{}{"latest_msg_destruct_time": now}); err != nil {
+ if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]any{"latest_msg_destruct_time": now}); err != nil {
log.ZError(ctx, "updateUsersConversationFiled failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID)
continue
}
diff --git a/internal/tools/msg.go b/internal/tools/msg.go
index ad8f5c471..97bb2988e 100644
--- a/internal/tools/msg.go
+++ b/internal/tools/msg.go
@@ -19,6 +19,11 @@ import (
"fmt"
"math"
+ "github.com/OpenIMSDK/protocol/sdkws"
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+
"github.com/redis/go-redis/v9"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
@@ -31,13 +36,11 @@ import (
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/mw"
- "github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
@@ -72,33 +75,45 @@ func InitMsgTool() (*MsgTool, error) {
if err != nil {
return nil, err
}
- db, err := relation.NewGormDB()
+ discov, err := kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery)
if err != nil {
return nil, err
}
- discov, err := kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery)
- /*
- discov, err := zookeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema,
- zookeeper.WithFreq(time.Hour), zookeeper.WithRoundRobin(), zookeeper.WithUserNameAndPassword(config.Config.Zookeeper.Username,
- config.Config.Zookeeper.Password), zookeeper.WithTimeout(10), zookeeper.WithLogger(log.NewZkLogger()))*/
+ discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
+ userDB, err := mgo.NewUserMongo(mongo.GetDatabase())
if err != nil {
return nil, err
}
- discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
- userDB := relation.NewUserGorm(db)
msgDatabase := controller.InitCommonMsgDatabase(rdb, mongo.GetDatabase())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
+ ctxTx := tx.NewMongo(mongo.GetClient())
userDatabase := controller.NewUserDatabase(
userDB,
- cache.NewUserCacheRedis(rdb, relation.NewUserGorm(db), cache.GetDefaultOpt()),
- tx.NewGorm(db),
+ cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt()),
+ ctxTx,
userMongoDB,
)
- groupDatabase := controller.InitGroupDatabase(db, rdb, mongo.GetDatabase(), nil)
+ groupDB, err := mgo.NewGroupMongo(mongo.GetDatabase())
+ if err != nil {
+ return nil, err
+ }
+ groupMemberDB, err := mgo.NewGroupMember(mongo.GetDatabase())
+ if err != nil {
+ return nil, err
+ }
+ groupRequestDB, err := mgo.NewGroupRequestMgo(mongo.GetDatabase())
+ if err != nil {
+ return nil, err
+ }
+ conversationDB, err := mgo.NewConversationMongo(mongo.GetDatabase())
+ if err != nil {
+ return nil, err
+ }
+ groupDatabase := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, ctxTx, nil)
conversationDatabase := controller.NewConversationDatabase(
- relation.NewConversationGorm(db),
- cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), relation.NewConversationGorm(db)),
- tx.NewGorm(db),
+ conversationDB,
+ cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB),
+ ctxTx,
)
msgRpcClient := rpcclient.NewMessageRpcClient(discov)
msgNotificationSender := notification.NewMsgNotificationSender(rpcclient.WithRpcClient(&msgRpcClient))
@@ -144,7 +159,11 @@ func (c *MsgTool) AllConversationClearMsgAndFixSeq() {
}
for i := 0; i < count; i++ {
pageNumber := rand.Int63() % maxPage
- conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, int32(pageNumber), batchNum)
+ pagination := &sdkws.RequestPagination{
+ PageNumber: int32(pageNumber),
+ ShowNumber: batchNum,
+ }
+ conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination)
if err != nil {
log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber)
continue
diff --git a/internal/tools/msg_doc_convert.go b/internal/tools/msg_doc_convert.go
index 758625be1..b9150c362 100644
--- a/internal/tools/msg_doc_convert.go
+++ b/internal/tools/msg_doc_convert.go
@@ -32,7 +32,7 @@ func (c *MsgTool) convertTools() {
for _, conversationID := range conversationIDs {
conversationIDs = append(conversationIDs, msgprocessor.GetNotificationConversationIDByConversationID(conversationID))
}
- userIDs, err := c.userDatabase.GetAllUserID(ctx, 0, 0)
+ _, userIDs, err := c.userDatabase.GetAllUserID(ctx, nil)
if err != nil {
log.ZError(ctx, "get all user ids failed", err)
return
diff --git a/pkg/apistruct/manage.go b/pkg/apistruct/manage.go
index 1e0ab3214..a48f5253c 100644
--- a/pkg/apistruct/manage.go
+++ b/pkg/apistruct/manage.go
@@ -36,7 +36,7 @@ type SendMsg struct {
SenderPlatformID int32 `json:"senderPlatformID"`
// Content is the actual content of the message, required and excluded from Swagger documentation.
- Content map[string]interface{} `json:"content" binding:"required" swaggerignore:"true"`
+ Content map[string]any `json:"content" binding:"required" swaggerignore:"true"`
// ContentType is an integer that represents the type of the content.
ContentType int32 `json:"contentType" binding:"required"`
diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go
index a8e577fde..fd01e8c5a 100644
--- a/pkg/authverify/token.go
+++ b/pkg/authverify/token.go
@@ -28,7 +28,7 @@ import (
)
func Secret() jwt.Keyfunc {
- return func(token *jwt.Token) (interface{}, error) {
+ return func(token *jwt.Token) (any, error) {
return []byte(config.Config.Secret), nil
}
}
@@ -55,7 +55,7 @@ func CheckAdmin(ctx context.Context) error {
return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx)))
}
-func ParseRedisInterfaceToken(redisToken interface{}) (*tokenverify.Claims, error) {
+func ParseRedisInterfaceToken(redisToken any) (*tokenverify.Claims, error) {
return tokenverify.GetClaimFromToken(string(redisToken.([]uint8)), Secret())
}
diff --git a/pkg/common/cmd/rpc.go b/pkg/common/cmd/rpc.go
index 6266c03b2..ea2a00b07 100644
--- a/pkg/common/cmd/rpc.go
+++ b/pkg/common/cmd/rpc.go
@@ -46,15 +46,13 @@ func (a *RpcCmd) Exec() error {
return a.Execute()
}
-func (a *RpcCmd) StartSvr(
- name string,
- rpcFn func(discov discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error,
-) error {
+func (a *RpcCmd) StartSvr(name string, rpcFn func(discov discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error) error {
if a.GetPortFlag() == 0 {
return errors.New("port is required")
}
return startrpc.Start(a.GetPortFlag(), name, a.GetPrometheusPortFlag(), rpcFn)
}
+
func (a *RpcCmd) GetPortFromConfig(portType string) int {
switch a.Name {
case RpcPushServer:
diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go
index 3c819ea2c..5fb8fe7e2 100644
--- a/pkg/common/config/config.go
+++ b/pkg/common/config/config.go
@@ -44,6 +44,18 @@ type POfflinePush struct {
Ext string `yaml:"ext"`
}
+type MYSQL struct {
+ Address []string `yaml:"address"`
+ Username string `yaml:"username"`
+ Password string `yaml:"password"`
+ Database string `yaml:"database"`
+ MaxOpenConn int `yaml:"maxOpenConn"`
+ MaxIdleConn int `yaml:"maxIdleConn"`
+ MaxLifeTime int `yaml:"maxLifeTime"`
+ LogLevel int `yaml:"logLevel"`
+ SlowThreshold int `yaml:"slowThreshold"`
+}
+
type configStruct struct {
Envs struct {
Discovery string `yaml:"discovery"`
@@ -55,17 +67,7 @@ type configStruct struct {
Password string `yaml:"password"`
} `yaml:"zookeeper"`
- Mysql struct {
- Address []string `yaml:"address"`
- Username string `yaml:"username"`
- Password string `yaml:"password"`
- Database string `yaml:"database"`
- MaxOpenConn int `yaml:"maxOpenConn"`
- MaxIdleConn int `yaml:"maxIdleConn"`
- MaxLifeTime int `yaml:"maxLifeTime"`
- LogLevel int `yaml:"logLevel"`
- SlowThreshold int `yaml:"slowThreshold"`
- } `yaml:"mysql"`
+ Mysql *MYSQL `yaml:"mysql"`
Mongo struct {
Uri string `yaml:"uri"`
diff --git a/pkg/common/config/parse.go b/pkg/common/config/parse.go
index f2ea962ee..22e458e00 100644
--- a/pkg/common/config/parse.go
+++ b/pkg/common/config/parse.go
@@ -71,7 +71,7 @@ func GetOptionsByNotification(cfg NotificationConf) msgprocessor.Options {
return opts
}
-func initConfig(config interface{}, configName, configFolderPath string) error {
+func initConfig(config any, configName, configFolderPath string) error {
configFolderPath = filepath.Join(configFolderPath, configName)
_, err := os.Stat(configFolderPath)
if err != nil {
diff --git a/pkg/common/config/parse_test.go b/pkg/common/config/parse_test.go
index e34aa5b7f..38171ec08 100644
--- a/pkg/common/config/parse_test.go
+++ b/pkg/common/config/parse_test.go
@@ -76,7 +76,7 @@ func TestGetOptionsByNotification(t *testing.T) {
func Test_initConfig(t *testing.T) {
type args struct {
- config interface{}
+ config any
configName string
configFolderPath string
}
diff --git a/pkg/common/convert/friend.go b/pkg/common/convert/friend.go
index 7003c8aa6..c81cd98d6 100644
--- a/pkg/common/convert/friend.go
+++ b/pkg/common/convert/friend.go
@@ -16,6 +16,7 @@ package convert
import (
"context"
+ "fmt"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
@@ -31,23 +32,22 @@ func FriendPb2DB(friend *sdkws.FriendInfo) *relation.FriendModel {
return dbFriend
}
-func FriendDB2Pb(
- ctx context.Context,
- friendDB *relation.FriendModel,
+func FriendDB2Pb(ctx context.Context, friendDB *relation.FriendModel,
getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error),
) (*sdkws.FriendInfo, error) {
- pbfriend := &sdkws.FriendInfo{FriendUser: &sdkws.UserInfo{}}
- utils.CopyStructFields(pbfriend, friendDB)
users, err := getUsers(ctx, []string{friendDB.FriendUserID})
if err != nil {
return nil, err
}
- pbfriend.FriendUser.UserID = users[friendDB.FriendUserID].UserID
- pbfriend.FriendUser.Nickname = users[friendDB.FriendUserID].Nickname
- pbfriend.FriendUser.FaceURL = users[friendDB.FriendUserID].FaceURL
- pbfriend.FriendUser.Ex = users[friendDB.FriendUserID].Ex
- pbfriend.CreateTime = friendDB.CreateTime.Unix()
- return pbfriend, nil
+ user, ok := users[friendDB.FriendUserID]
+ if !ok {
+ return nil, fmt.Errorf("user not found: %s", friendDB.FriendUserID)
+ }
+
+ return &sdkws.FriendInfo{
+ FriendUser: user,
+ CreateTime: friendDB.CreateTime.Unix(),
+ }, nil
}
func FriendsDB2Pb(
@@ -118,3 +118,37 @@ func FriendRequestDB2Pb(
}
return res, nil
}
+
+// FriendPb2DBMap converts a FriendInfo protobuf object to a map suitable for database operations.
+// It only includes non-zero or non-empty fields in the map.
+func FriendPb2DBMap(friend *sdkws.FriendInfo) map[string]any {
+ if friend == nil {
+ return nil
+ }
+
+ val := make(map[string]any)
+
+ // Assuming FriendInfo has similar fields to those in FriendModel.
+ // Add or remove fields based on your actual FriendInfo and FriendModel structures.
+ if friend.FriendUser != nil {
+ if friend.FriendUser.UserID != "" {
+ val["friend_user_id"] = friend.FriendUser.UserID
+ }
+ if friend.FriendUser.Nickname != "" {
+ val["nickname"] = friend.FriendUser.Nickname
+ }
+ if friend.FriendUser.FaceURL != "" {
+ val["face_url"] = friend.FriendUser.FaceURL
+ }
+ if friend.FriendUser.Ex != "" {
+ val["ex"] = friend.FriendUser.Ex
+ }
+ }
+ if friend.CreateTime != 0 {
+ val["create_time"] = friend.CreateTime // You might need to convert this to a proper time format.
+ }
+
+ // Include other fields from FriendInfo as needed, similar to the above pattern.
+
+ return val
+}
diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go
index 4ca1899be..0c71aac22 100644
--- a/pkg/common/convert/user.go
+++ b/pkg/common/convert/user.go
@@ -16,32 +16,58 @@ package convert
import (
"github.com/OpenIMSDK/protocol/sdkws"
+ "time"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
-func UsersDB2Pb(users []*relationtb.UserModel) (result []*sdkws.UserInfo) {
+func UsersDB2Pb(users []*relationtb.UserModel) []*sdkws.UserInfo {
+ result := make([]*sdkws.UserInfo, 0, len(users))
for _, user := range users {
- var userPb sdkws.UserInfo
- userPb.UserID = user.UserID
- userPb.Nickname = user.Nickname
- userPb.FaceURL = user.FaceURL
- userPb.Ex = user.Ex
- userPb.CreateTime = user.CreateTime.UnixMilli()
- userPb.AppMangerLevel = user.AppMangerLevel
- userPb.GlobalRecvMsgOpt = user.GlobalRecvMsgOpt
- result = append(result, &userPb)
+ userPb := &sdkws.UserInfo{
+ UserID: user.UserID,
+ Nickname: user.Nickname,
+ FaceURL: user.FaceURL,
+ Ex: user.Ex,
+ CreateTime: user.CreateTime.UnixMilli(),
+ AppMangerLevel: user.AppMangerLevel,
+ GlobalRecvMsgOpt: user.GlobalRecvMsgOpt,
+ }
+ result = append(result, userPb)
}
return result
}
func UserPb2DB(user *sdkws.UserInfo) *relationtb.UserModel {
- var userDB relationtb.UserModel
- userDB.UserID = user.UserID
- userDB.Nickname = user.Nickname
- userDB.FaceURL = user.FaceURL
- userDB.Ex = user.Ex
- userDB.AppMangerLevel = user.AppMangerLevel
- userDB.GlobalRecvMsgOpt = user.GlobalRecvMsgOpt
- return &userDB
+ return &relationtb.UserModel{
+ UserID: user.UserID,
+ Nickname: user.Nickname,
+ FaceURL: user.FaceURL,
+ Ex: user.Ex,
+ CreateTime: time.UnixMilli(user.CreateTime),
+ AppMangerLevel: user.AppMangerLevel,
+ GlobalRecvMsgOpt: user.GlobalRecvMsgOpt,
+ }
+}
+
+func UserPb2DBMap(user *sdkws.UserInfo) map[string]any {
+ if user == nil {
+ return nil
+ }
+ val := make(map[string]any)
+ fields := map[string]any{
+ "nickname": user.Nickname,
+ "face_url": user.FaceURL,
+ "ex": user.Ex,
+ "app_manager_level": user.AppMangerLevel,
+ "global_recv_msg_opt": user.GlobalRecvMsgOpt,
+ }
+ for key, value := range fields {
+ if v, ok := value.(string); ok && v != "" {
+ val[key] = v
+ } else if v, ok := value.(int32); ok && v != 0 {
+ val[key] = v
+ }
+ }
+ return val
}
diff --git a/pkg/common/convert/user_test.go b/pkg/common/convert/user_test.go
new file mode 100644
index 000000000..a24efb53c
--- /dev/null
+++ b/pkg/common/convert/user_test.go
@@ -0,0 +1,87 @@
+// 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 convert
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/OpenIMSDK/protocol/sdkws"
+
+ relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func TestUsersDB2Pb(t *testing.T) {
+ type args struct {
+ users []*relationtb.UserModel
+ }
+ tests := []struct {
+ name string
+ args args
+ wantResult []*sdkws.UserInfo
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if gotResult := UsersDB2Pb(tt.args.users); !reflect.DeepEqual(gotResult, tt.wantResult) {
+ t.Errorf("UsersDB2Pb() = %v, want %v", gotResult, tt.wantResult)
+ }
+ })
+ }
+}
+
+func TestUserPb2DB(t *testing.T) {
+ type args struct {
+ user *sdkws.UserInfo
+ }
+ tests := []struct {
+ name string
+ args args
+ want *relationtb.UserModel
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := UserPb2DB(tt.args.user); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("UserPb2DB() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestUserPb2DBMap(t *testing.T) {
+ user := &sdkws.UserInfo{
+ Nickname: "TestUser",
+ FaceURL: "http://openim.io/logo.jpg",
+ Ex: "Extra Data",
+ AppMangerLevel: 1,
+ GlobalRecvMsgOpt: 2,
+ }
+
+ expected := map[string]any{
+ "nickname": "TestUser",
+ "face_url": "http://openim.io/logo.jpg",
+ "ex": "Extra Data",
+ "app_manager_level": int32(1),
+ "global_recv_msg_opt": int32(2),
+ }
+
+ result := UserPb2DBMap(user)
+ if !reflect.DeepEqual(result, expected) {
+ t.Errorf("UserPb2DBMap returned unexpected map. Got %v, want %v", result, expected)
+ }
+}
diff --git a/pkg/common/db/cache/conversation.go b/pkg/common/db/cache/conversation.go
index 9c0bcfae4..a7018bc18 100644
--- a/pkg/common/db/cache/conversation.go
+++ b/pkg/common/db/cache/conversation.go
@@ -26,7 +26,6 @@ import (
"github.com/OpenIMSDK/tools/utils"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
@@ -67,10 +66,10 @@ type ConversationCache interface {
GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
DelUserRecvMsgOpt(ownerUserID, conversationID string) ConversationCache
// get one super group recv msg but do not notification userID list
- GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error)
+ //GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error)
DelSuperGroupRecvMsgNotNotifyUserIDs(groupID string) ConversationCache
// get one super group recv msg but do not notification userID list hash
- GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error)
+ //GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error)
DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache
//GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
@@ -101,20 +100,20 @@ type ConversationRedisCache struct {
expireTime time.Duration
}
-func NewNewConversationRedis(
- rdb redis.UniversalClient,
- conversationDB *relation.ConversationGorm,
- options rockscache.Options,
-) ConversationCache {
- rcClient := rockscache.NewClient(rdb, options)
-
- return &ConversationRedisCache{
- rcClient: rcClient,
- metaCache: NewMetaCacheRedis(rcClient),
- conversationDB: conversationDB,
- expireTime: conversationExpireTime,
- }
-}
+//func NewNewConversationRedis(
+// rdb redis.UniversalClient,
+// conversationDB *relation.ConversationGorm,
+// options rockscache.Options,
+//) ConversationCache {
+// rcClient := rockscache.NewClient(rdb, options)
+//
+// return &ConversationRedisCache{
+// rcClient: rcClient,
+// metaCache: NewMetaCacheRedis(rcClient),
+// conversationDB: conversationDB,
+// expireTime: conversationExpireTime,
+// }
+//}
func (c *ConversationRedisCache) NewCache() ConversationCache {
return &ConversationRedisCache{
@@ -282,11 +281,11 @@ func (c *ConversationRedisCache) GetUserRecvMsgOpt(ctx context.Context, ownerUse
})
}
-func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error) {
- return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsKey(groupID), c.expireTime, func(ctx context.Context) (userIDs []string, err error) {
- return c.conversationDB.FindSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
- })
-}
+//func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error) {
+// return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsKey(groupID), c.expireTime, func(ctx context.Context) (userIDs []string, err error) {
+// return c.conversationDB.FindSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
+// })
+//}
func (c *ConversationRedisCache) DelUsersConversation(conversationID string, ownerUserIDs ...string) ConversationCache {
keys := make([]string, 0, len(ownerUserIDs))
@@ -313,19 +312,19 @@ func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDs(groupID st
return cache
}
-func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error) {
- return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsHashKey(groupID), c.expireTime, func(ctx context.Context) (hash uint64, err error) {
- userIDs, err := c.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
- if err != nil {
- return 0, err
- }
- utils.Sort(userIDs, true)
- bi := big.NewInt(0)
- bi.SetString(utils.Md5(strings.Join(userIDs, ";"))[0:8], 16)
- return bi.Uint64(), nil
- },
- )
-}
+//func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error) {
+// return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsHashKey(groupID), c.expireTime, func(ctx context.Context) (hash uint64, err error) {
+// userIDs, err := c.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
+// if err != nil {
+// return 0, err
+// }
+// utils.Sort(userIDs, true)
+// bi := big.NewInt(0)
+// bi.SetString(utils.Md5(strings.Join(userIDs, ";"))[0:8], 16)
+// return bi.Uint64(), nil
+// },
+// )
+//}
func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache {
cache := c.NewCache()
diff --git a/pkg/common/db/cache/friend.go b/pkg/common/db/cache/friend.go
index 64a358984..1708f7664 100644
--- a/pkg/common/db/cache/friend.go
+++ b/pkg/common/db/cache/friend.go
@@ -33,19 +33,20 @@ const (
friendKey = "FRIEND_INFO:"
)
-// args fn will exec when no data in msgCache.
+// FriendCache is an interface for caching friend-related data.
type FriendCache interface {
metaCache
NewCache() FriendCache
GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error)
- // call when friendID List changed
+ // Called when friendID list changed
DelFriendIDs(ownerUserID ...string) FriendCache
- // get single friendInfo from msgCache
+ // Get single friendInfo from the cache
GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error)
- // del friend when friend info changed
+ // Delete friend when friend info changed
DelFriend(ownerUserID, friendUserID string) FriendCache
}
+// FriendCacheRedis is an implementation of the FriendCache interface using Redis.
type FriendCacheRedis struct {
metaCache
friendDB relationtb.FriendModelInterface
@@ -53,6 +54,7 @@ type FriendCacheRedis struct {
rcClient *rockscache.Client
}
+// NewFriendCacheRedis creates a new instance of FriendCacheRedis.
func NewFriendCacheRedis(rdb redis.UniversalClient, friendDB relationtb.FriendModelInterface,
options rockscache.Options) FriendCache {
rcClient := rockscache.NewClient(rdb, options)
@@ -64,6 +66,7 @@ func NewFriendCacheRedis(rdb redis.UniversalClient, friendDB relationtb.FriendMo
}
}
+// NewCache creates a new instance of FriendCacheRedis with the same configuration.
func (f *FriendCacheRedis) NewCache() FriendCache {
return &FriendCacheRedis{
rcClient: f.rcClient,
@@ -73,24 +76,29 @@ func (f *FriendCacheRedis) NewCache() FriendCache {
}
}
+// getFriendIDsKey returns the key for storing friend IDs in the cache.
func (f *FriendCacheRedis) getFriendIDsKey(ownerUserID string) string {
return friendIDsKey + ownerUserID
}
+// getTwoWayFriendsIDsKey returns the key for storing two-way friend IDs in the cache.
func (f *FriendCacheRedis) getTwoWayFriendsIDsKey(ownerUserID string) string {
return TwoWayFriendsIDsKey + ownerUserID
}
+// getFriendKey returns the key for storing friend info in the cache.
func (f *FriendCacheRedis) getFriendKey(ownerUserID, friendUserID string) string {
return friendKey + ownerUserID + "-" + friendUserID
}
+// GetFriendIDs retrieves friend IDs from the cache or the database if not found.
func (f *FriendCacheRedis) GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error) {
return getCache(ctx, f.rcClient, f.getFriendIDsKey(ownerUserID), f.expireTime, func(ctx context.Context) ([]string, error) {
return f.friendDB.FindFriendUserIDs(ctx, ownerUserID)
})
}
+// DelFriendIDs deletes friend IDs from the cache.
func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) FriendCache {
newGroupCache := f.NewCache()
keys := make([]string, 0, len(ownerUserIDs))
@@ -102,7 +110,7 @@ func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) FriendCache {
return newGroupCache
}
-// todo.
+// GetTwoWayFriendIDs retrieves two-way friend IDs from the cache.
func (f *FriendCacheRedis) GetTwoWayFriendIDs(ctx context.Context, ownerUserID string) (twoWayFriendIDs []string, err error) {
friendIDs, err := f.GetFriendIDs(ctx, ownerUserID)
if err != nil {
@@ -121,6 +129,7 @@ func (f *FriendCacheRedis) GetTwoWayFriendIDs(ctx context.Context, ownerUserID s
return twoWayFriendIDs, nil
}
+// DelTwoWayFriendIDs deletes two-way friend IDs from the cache.
func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, ownerUserID string) FriendCache {
newFriendCache := f.NewCache()
newFriendCache.AddKeys(f.getTwoWayFriendsIDsKey(ownerUserID))
@@ -128,14 +137,15 @@ func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, ownerUserID s
return newFriendCache
}
-func (f *FriendCacheRedis) GetFriend(ctx context.Context, ownerUserID,
- friendUserID string) (friend *relationtb.FriendModel, err error) {
+// GetFriend retrieves friend info from the cache or the database if not found.
+func (f *FriendCacheRedis) GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error) {
return getCache(ctx, f.rcClient, f.getFriendKey(ownerUserID,
friendUserID), f.expireTime, func(ctx context.Context) (*relationtb.FriendModel, error) {
return f.friendDB.Take(ctx, ownerUserID, friendUserID)
})
}
+// DelFriend deletes friend info from the cache.
func (f *FriendCacheRedis) DelFriend(ownerUserID, friendUserID string) FriendCache {
newFriendCache := f.NewCache()
newFriendCache.AddKeys(f.getFriendKey(ownerUserID, friendUserID))
diff --git a/pkg/common/db/cache/group.go b/pkg/common/db/cache/group.go
index 6a4b57813..603d8e534 100644
--- a/pkg/common/db/cache/group.go
+++ b/pkg/common/db/cache/group.go
@@ -16,8 +16,13 @@ package cache
import (
"context"
+ "fmt"
+ "strconv"
"time"
+ "github.com/OpenIMSDK/protocol/constant"
+ "github.com/OpenIMSDK/tools/errs"
+
"github.com/OpenIMSDK/tools/log"
"github.com/dtm-labs/rockscache"
@@ -26,21 +31,24 @@ import (
"github.com/OpenIMSDK/tools/utils"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
- unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
)
const (
- groupExpireTime = time.Second * 60 * 60 * 12
- groupInfoKey = "GROUP_INFO:"
- groupMemberIDsKey = "GROUP_MEMBER_IDS:"
- groupMembersHashKey = "GROUP_MEMBERS_HASH2:"
- groupMemberInfoKey = "GROUP_MEMBER_INFO:"
- joinedSuperGroupsKey = "JOIN_SUPER_GROUPS:"
- SuperGroupMemberIDsKey = "SUPER_GROUP_MEMBER_IDS:"
- joinedGroupsKey = "JOIN_GROUPS_KEY:"
- groupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:"
+ groupExpireTime = time.Second * 60 * 60 * 12
+ groupInfoKey = "GROUP_INFO:"
+ groupMemberIDsKey = "GROUP_MEMBER_IDS:"
+ groupMembersHashKey = "GROUP_MEMBERS_HASH2:"
+ groupMemberInfoKey = "GROUP_MEMBER_INFO:"
+ //groupOwnerInfoKey = "GROUP_OWNER_INFO:"
+ joinedGroupsKey = "JOIN_GROUPS_KEY:"
+ groupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:"
+ groupRoleLevelMemberIDsKey = "GROUP_ROLE_LEVEL_MEMBER_IDS:"
)
+type GroupHash interface {
+ GetGroupHash(ctx context.Context, groupID string) (uint64, error)
+}
+
type GroupCache interface {
metaCache
NewCache() GroupCache
@@ -48,11 +56,6 @@ type GroupCache interface {
GetGroupInfo(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error)
DelGroupsInfo(groupIDs ...string) GroupCache
- GetJoinedSuperGroupIDs(ctx context.Context, userID string) (joinedSuperGroupIDs []string, err error)
- DelJoinedSuperGroupIDs(userIDs ...string) GroupCache
- GetSuperGroupMemberIDs(ctx context.Context, groupIDs ...string) (models []*unrelationtb.SuperGroupModel, err error)
- DelSuperGroupMemberIDs(groupIDs ...string) GroupCache
-
GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error)
GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error)
DelGroupMembersHash(groupID string) GroupCache
@@ -69,9 +72,16 @@ type GroupCache interface {
GetGroupMembersInfo(ctx context.Context, groupID string, userID []string) (groupMembers []*relationtb.GroupMemberModel, err error)
GetAllGroupMembersInfo(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error)
GetGroupMembersPage(ctx context.Context, groupID string, userID []string, showNumber, pageNumber int32) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error)
+ FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*relationtb.GroupMemberModel, error)
+ GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
+ GetGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error)
+ GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error)
+ DelGroupRoleLevel(groupID string, roleLevel []int32) GroupCache
+ DelGroupAllRoleLevel(groupID string) GroupCache
DelGroupMembersInfo(groupID string, userID ...string) GroupCache
-
+ GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*relationtb.GroupMemberModel, error)
+ GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error)
GetGroupMemberNum(ctx context.Context, groupID string) (memberNum int64, err error)
DelGroupsMemberNum(groupID ...string) GroupCache
}
@@ -81,10 +91,9 @@ type GroupCacheRedis struct {
groupDB relationtb.GroupModelInterface
groupMemberDB relationtb.GroupMemberModelInterface
groupRequestDB relationtb.GroupRequestModelInterface
- mongoDB unrelationtb.SuperGroupModelInterface
expireTime time.Duration
rcClient *rockscache.Client
- hashCode func(ctx context.Context, groupID string) (uint64, error)
+ groupHash GroupHash
}
func NewGroupCacheRedis(
@@ -92,8 +101,7 @@ func NewGroupCacheRedis(
groupDB relationtb.GroupModelInterface,
groupMemberDB relationtb.GroupMemberModelInterface,
groupRequestDB relationtb.GroupRequestModelInterface,
- mongoClient unrelationtb.SuperGroupModelInterface,
- hashCode func(ctx context.Context, groupID string) (uint64, error),
+ hashCode GroupHash,
opts rockscache.Options,
) GroupCache {
rcClient := rockscache.NewClient(rdb, opts)
@@ -101,8 +109,7 @@ func NewGroupCacheRedis(
return &GroupCacheRedis{
rcClient: rcClient, expireTime: groupExpireTime,
groupDB: groupDB, groupMemberDB: groupMemberDB, groupRequestDB: groupRequestDB,
- mongoDB: mongoClient,
- hashCode: hashCode,
+ groupHash: hashCode,
metaCache: NewMetaCacheRedis(rcClient),
}
}
@@ -114,7 +121,6 @@ func (g *GroupCacheRedis) NewCache() GroupCache {
groupDB: g.groupDB,
groupMemberDB: g.groupMemberDB,
groupRequestDB: g.groupRequestDB,
- mongoDB: g.mongoDB,
metaCache: NewMetaCacheRedis(g.rcClient, g.metaCache.GetPreDelKeys()...),
}
}
@@ -123,18 +129,10 @@ func (g *GroupCacheRedis) getGroupInfoKey(groupID string) string {
return groupInfoKey + groupID
}
-func (g *GroupCacheRedis) getJoinedSuperGroupsIDKey(userID string) string {
- return joinedSuperGroupsKey + userID
-}
-
func (g *GroupCacheRedis) getJoinedGroupsKey(userID string) string {
return joinedGroupsKey + userID
}
-func (g *GroupCacheRedis) getSuperGroupMemberIDsKey(groupID string) string {
- return SuperGroupMemberIDsKey + groupID
-}
-
func (g *GroupCacheRedis) getGroupMembersHashKey(groupID string) string {
return groupMembersHashKey + groupID
}
@@ -151,6 +149,10 @@ func (g *GroupCacheRedis) getGroupMemberNumKey(groupID string) string {
return groupMemberNumKey + groupID
}
+func (g *GroupCacheRedis) getGroupRoleLevelMemberIDsKey(groupID string, roleLevel int32) string {
+ return groupRoleLevelMemberIDsKey + groupID + "-" + strconv.Itoa(int(roleLevel))
+}
+
func (g *GroupCacheRedis) GetGroupIndex(group *relationtb.GroupModel, keys []string) (int, error) {
key := g.getGroupInfoKey(group.GroupID)
for i, _key := range keys {
@@ -173,15 +175,7 @@ func (g *GroupCacheRedis) GetGroupMemberIndex(groupMember *relationtb.GroupMembe
return 0, errIndex
}
-// / groupInfo.
func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) {
- //var keys []string
- //for _, group := range groupIDs {
- // keys = append(keys, g.getGroupInfoKey(group))
- //}
- //return batchGetCache(ctx, g.rcClient, keys, g.expireTime, g.GetGroupIndex, func(ctx context.Context) ([]*relationtb.GroupModel, error) {
- // return g.groupDB.Find(ctx, groupIDs)
- //})
return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
return g.getGroupInfoKey(groupID)
}, func(ctx context.Context, groupID string) (*relationtb.GroupModel, error) {
@@ -206,123 +200,44 @@ func (g *GroupCacheRedis) DelGroupsInfo(groupIDs ...string) GroupCache {
return newGroupCache
}
-func (g *GroupCacheRedis) GetJoinedSuperGroupIDs(ctx context.Context, userID string) (joinedSuperGroupIDs []string, err error) {
- return getCache(ctx, g.rcClient, g.getJoinedSuperGroupsIDKey(userID), g.expireTime, func(ctx context.Context) ([]string, error) {
- userGroup, err := g.mongoDB.GetSuperGroupByUserID(ctx, userID)
- if err != nil {
- return nil, err
- }
- return userGroup.GroupIDs, nil
- },
- )
-}
-
-func (g *GroupCacheRedis) GetSuperGroupMemberIDs(ctx context.Context, groupIDs ...string) (models []*unrelationtb.SuperGroupModel, err error) {
- //var keys []string
- //for _, group := range groupIDs {
- // keys = append(keys, g.getSuperGroupMemberIDsKey(group))
- //}
- //return batchGetCache(ctx, g.rcClient, keys, g.expireTime, func(model *unrelationtb.SuperGroupModel, keys []string) (int, error) {
- // for i, key := range keys {
- // if g.getSuperGroupMemberIDsKey(model.GroupID) == key {
- // return i, nil
- // }
- // }
- // return 0, errIndex
- //},
- // func(ctx context.Context) ([]*unrelationtb.SuperGroupModel, error) {
- // return g.mongoDB.FindSuperGroup(ctx, groupIDs)
- // })
- return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
- return g.getSuperGroupMemberIDsKey(groupID)
- }, func(ctx context.Context, groupID string) (*unrelationtb.SuperGroupModel, error) {
- return g.mongoDB.TakeSuperGroup(ctx, groupID)
- })
-}
-
-// userJoinSuperGroup.
-func (g *GroupCacheRedis) DelJoinedSuperGroupIDs(userIDs ...string) GroupCache {
+func (g *GroupCacheRedis) DelGroupsOwner(groupIDs ...string) GroupCache {
newGroupCache := g.NewCache()
- keys := make([]string, 0, len(userIDs))
- for _, userID := range userIDs {
- keys = append(keys, g.getJoinedSuperGroupsIDKey(userID))
+ keys := make([]string, 0, len(groupIDs))
+ for _, groupID := range groupIDs {
+ keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, constant.GroupOwner))
}
newGroupCache.AddKeys(keys...)
return newGroupCache
}
-func (g *GroupCacheRedis) DelSuperGroupMemberIDs(groupIDs ...string) GroupCache {
+func (g *GroupCacheRedis) DelGroupRoleLevel(groupID string, roleLevels []int32) GroupCache {
newGroupCache := g.NewCache()
- keys := make([]string, 0, len(groupIDs))
- for _, groupID := range groupIDs {
- keys = append(keys, g.getSuperGroupMemberIDsKey(groupID))
+ keys := make([]string, 0, len(roleLevels))
+ for _, roleLevel := range roleLevels {
+ keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, roleLevel))
}
newGroupCache.AddKeys(keys...)
-
return newGroupCache
}
-// groupMembersHash.
+func (g *GroupCacheRedis) DelGroupAllRoleLevel(groupID string) GroupCache {
+ return g.DelGroupRoleLevel(groupID, []int32{constant.GroupOwner, constant.GroupAdmin, constant.GroupOrdinaryUsers})
+}
+
func (g *GroupCacheRedis) GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error) {
+ if g.groupHash == nil {
+ return 0, errs.ErrInternalServer.Wrap("group hash is nil")
+ }
return getCache(ctx, g.rcClient, g.getGroupMembersHashKey(groupID), g.expireTime, func(ctx context.Context) (uint64, error) {
- return g.hashCode(ctx, groupID)
+ return g.groupHash.GetGroupHash(ctx, groupID)
})
-
- //return getCache(ctx, g.rcClient, g.getGroupMembersHashKey(groupID), g.expireTime,
- // func(ctx context.Context) (uint64, error) {
- // userIDs, err := g.GetGroupMemberIDs(ctx, groupID)
- // if err != nil {
- // return 0, err
- // }
- // log.ZInfo(ctx, "GetGroupMembersHash", "groupID", groupID, "userIDs", userIDs)
- // var members []*relationtb.GroupMemberModel
- // if len(userIDs) > 0 {
- // members, err = g.GetGroupMembersInfo(ctx, groupID, userIDs)
- // if err != nil {
- // return 0, err
- // }
- // utils.Sort(userIDs, true)
- // }
- // memberMap := make(map[string]*relationtb.GroupMemberModel)
- // for i, member := range members {
- // memberMap[member.UserID] = members[i]
- // }
- // data := make([]string, 0, len(members)*11)
- // for _, userID := range userIDs {
- // member, ok := memberMap[userID]
- // if !ok {
- // continue
- // }
- // data = append(data,
- // member.GroupID,
- // member.UserID,
- // member.Nickname,
- // member.FaceURL,
- // strconv.Itoa(int(member.RoleLevel)),
- // strconv.FormatInt(member.JoinTime.UnixMilli(), 10),
- // strconv.Itoa(int(member.JoinSource)),
- // member.InviterUserID,
- // member.OperatorUserID,
- // strconv.FormatInt(member.MuteEndTime.UnixMilli(), 10),
- // member.Ex,
- // )
- // }
- // log.ZInfo(ctx, "hash data info", "userIDs.len", len(userIDs), "hash.data.len", len(data))
- // log.ZInfo(ctx, "json hash data", "groupID", groupID, "data", data)
- // val, err := json.Marshal(data)
- // if err != nil {
- // return 0, err
- // }
- // sum := md5.Sum(val)
- // code := binary.BigEndian.Uint64(sum[:])
- // log.ZInfo(ctx, "GetGroupMembersHash", "groupID", groupID, "hashCode", code, "num", len(members))
- // return code, nil
- // },
- //)
}
func (g *GroupCacheRedis) GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) {
+ if g.groupHash == nil {
+ return nil, errs.ErrInternalServer.Wrap("group hash is nil")
+ }
res := make(map[string]*relationtb.GroupSimpleUserID)
for _, groupID := range groupIDs {
hash, err := g.GetGroupMembersHash(ctx, groupID)
@@ -347,7 +262,6 @@ func (g *GroupCacheRedis) DelGroupMembersHash(groupID string) GroupCache {
return cache
}
-// groupMemberIDs.
func (g *GroupCacheRedis) GetGroupMemberIDs(ctx context.Context, groupID string) (groupMemberIDs []string, err error) {
return getCache(ctx, g.rcClient, g.getGroupMemberIDsKey(groupID), g.expireTime, func(ctx context.Context) ([]string, error) {
return g.groupMemberDB.FindMemberUserID(ctx, groupID)
@@ -398,13 +312,6 @@ func (g *GroupCacheRedis) GetGroupMemberInfo(ctx context.Context, groupID, userI
}
func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupMemberModel, error) {
- //var keys []string
- //for _, userID := range userIDs {
- // keys = append(keys, g.getGroupMemberInfoKey(groupID, userID))
- //}
- //return batchGetCache(ctx, g.rcClient, keys, g.expireTime, g.GetGroupMemberIndex, func(ctx context.Context) ([]*relationtb.GroupMemberModel, error) {
- // return g.groupMemberDB.Find(ctx, []string{groupID}, userIDs, nil)
- //})
return batchGetCache2(ctx, g.rcClient, g.expireTime, userIDs, func(userID string) string {
return g.getGroupMemberInfoKey(groupID, userID)
}, func(ctx context.Context, userID string) (*relationtb.GroupMemberModel, error) {
@@ -446,13 +353,6 @@ func (g *GroupCacheRedis) GetAllGroupMemberInfo(ctx context.Context, groupID str
if err != nil {
return nil, err
}
- //var keys []string
- //for _, groupMemberID := range groupMemberIDs {
- // keys = append(keys, g.getGroupMemberInfoKey(groupID, groupMemberID))
- //}
- //return batchGetCache(ctx, g.rcClient, keys, g.expireTime, g.GetGroupMemberIndex, func(ctx context.Context) ([]*relationtb.GroupMemberModel, error) {
- // return g.groupMemberDB.Find(ctx, []string{groupID}, groupMemberIDs, nil)
- //})
return g.GetGroupMembersInfo(ctx, groupID, groupMemberIDs)
}
@@ -483,3 +383,68 @@ func (g *GroupCacheRedis) DelGroupsMemberNum(groupID ...string) GroupCache {
return cache
}
+
+func (g *GroupCacheRedis) GetGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
+ members, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
+ if err != nil {
+ return nil, err
+ }
+ if len(members) == 0 {
+ return nil, errs.ErrRecordNotFound.Wrap(fmt.Sprintf("group %s owner not found", groupID))
+ }
+ return members[0], nil
+}
+
+func (g *GroupCacheRedis) GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error) {
+ members := make([]*relationtb.GroupMemberModel, 0, len(groupIDs))
+ for _, groupID := range groupIDs {
+ items, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
+ if err != nil {
+ return nil, err
+ }
+ if len(items) > 0 {
+ members = append(members, items[0])
+ }
+ }
+ return members, nil
+}
+
+func (g *GroupCacheRedis) GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) {
+ return getCache(ctx, g.rcClient, g.getGroupRoleLevelMemberIDsKey(groupID, roleLevel), g.expireTime, func(ctx context.Context) ([]string, error) {
+ return g.groupMemberDB.FindRoleLevelUserIDs(ctx, groupID, roleLevel)
+ })
+}
+
+func (g *GroupCacheRedis) GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*relationtb.GroupMemberModel, error) {
+ userIDs, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
+ if err != nil {
+ return nil, err
+ }
+ return g.GetGroupMembersInfo(ctx, groupID, userIDs)
+}
+
+func (g *GroupCacheRedis) GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
+ var userIDs []string
+ for _, roleLevel := range roleLevels {
+ ids, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
+ if err != nil {
+ return nil, err
+ }
+ userIDs = append(userIDs, ids...)
+ }
+ return g.GetGroupMembersInfo(ctx, groupID, userIDs)
+}
+
+func (g *GroupCacheRedis) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (_ []*relationtb.GroupMemberModel, err error) {
+ if len(groupIDs) == 0 {
+ groupIDs, err = g.GetJoinedGroupIDs(ctx, userID)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
+ return g.getGroupMemberInfoKey(groupID, userID)
+ }, func(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
+ return g.groupMemberDB.Take(ctx, groupID, userID)
+ })
+}
diff --git a/pkg/common/db/cache/meta_cache.go b/pkg/common/db/cache/meta_cache.go
index ccac88d68..4bc2a046a 100644
--- a/pkg/common/db/cache/meta_cache.go
+++ b/pkg/common/db/cache/meta_cache.go
@@ -38,7 +38,7 @@ const (
var errIndex = errors.New("err index")
type metaCache interface {
- ExecDel(ctx context.Context) error
+ ExecDel(ctx context.Context, distinct ...bool) error
// delete key rapid
DelKey(ctx context.Context, key string) error
AddKeys(keys ...string)
@@ -57,7 +57,10 @@ type metaCacheRedis struct {
retryInterval time.Duration
}
-func (m *metaCacheRedis) ExecDel(ctx context.Context) error {
+func (m *metaCacheRedis) ExecDel(ctx context.Context, distinct ...bool) error {
+ if len(distinct) > 0 && distinct[0] {
+ m.keys = utils.Distinct(m.keys)
+ }
if len(m.keys) > 0 {
log.ZDebug(ctx, "delete cache", "keys", m.keys)
for _, key := range m.keys {
diff --git a/pkg/common/db/cache/msg.go b/pkg/common/db/cache/msg.go
index f86b44d9b..5cd3cb22c 100644
--- a/pkg/common/db/cache/msg.go
+++ b/pkg/common/db/cache/msg.go
@@ -173,20 +173,7 @@ func (c *msgCache) getSeqs(ctx context.Context, items []string, getkey func(s st
}
func (c *msgCache) SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error {
- var retErr error
- for {
- select {
- case <-ctx.Done():
- return errs.Wrap(retErr, "SetMaxSeq redis retry too many amount")
- default:
- retErr = c.setSeq(ctx, conversationID, maxSeq, c.getMaxSeqKey)
- if retErr != nil {
- time.Sleep(time.Second * 2)
- continue
- }
- return nil
- }
- }
+ return c.setSeq(ctx, conversationID, maxSeq, c.getMaxSeqKey)
}
func (c *msgCache) GetMaxSeqs(ctx context.Context, conversationIDs []string) (m map[string]int64, err error) {
@@ -194,21 +181,7 @@ func (c *msgCache) GetMaxSeqs(ctx context.Context, conversationIDs []string) (m
}
func (c *msgCache) GetMaxSeq(ctx context.Context, conversationID string) (int64, error) {
- var retErr error
- var retData int64
- for {
- select {
- case <-ctx.Done():
- return -1, errs.Wrap(retErr, "GetMaxSeq redis retry too many amount")
- default:
- retData, retErr = c.getSeq(ctx, conversationID, c.getMaxSeqKey)
- if retErr != nil && errs.Unwrap(retErr) != redis.Nil {
- time.Sleep(time.Second * 2)
- continue
- }
- return retData, retErr
- }
- }
+ return c.getSeq(ctx, conversationID, c.getMaxSeqKey)
}
func (c *msgCache) SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error {
@@ -314,7 +287,7 @@ func (c *msgCache) GetTokensWithoutError(ctx context.Context, userID string, pla
func (c *msgCache) SetTokenMapByUidPid(ctx context.Context, userID string, platform int, m map[string]int) error {
key := uidPidToken + userID + ":" + constant.PlatformIDToName(platform)
- mm := make(map[string]interface{})
+ mm := make(map[string]any)
for k, v := range m {
mm[k] = v
}
@@ -672,35 +645,19 @@ func (c *msgCache) PipeDeleteMessages(ctx context.Context, conversationID string
}
func (c *msgCache) CleanUpOneConversationAllMsg(ctx context.Context, conversationID string) error {
- var (
- cursor uint64
- keys []string
- err error
-
- key = c.allMessageCacheKey(conversationID)
- )
-
- for {
- // scan up to 10000 at a time, the count (10000) param refers to the number of scans on redis server.
- // if the count is too small, needs to be run scan on redis frequently.
- var limit int64 = 10000
- keys, cursor, err = c.rdb.Scan(ctx, cursor, key, limit).Result()
- if err != nil {
+ vals, err := c.rdb.Keys(ctx, c.allMessageCacheKey(conversationID)).Result()
+ if errors.Is(err, redis.Nil) {
+ return nil
+ }
+ if err != nil {
+ return errs.Wrap(err)
+ }
+ for _, v := range vals {
+ if err := c.rdb.Del(ctx, v).Err(); err != nil {
return errs.Wrap(err)
}
-
- for _, key := range keys {
- err := c.rdb.Del(ctx, key).Err()
- if err != nil {
- return errs.Wrap(err)
- }
- }
-
- // scan end
- if cursor == 0 {
- return nil
- }
}
+ return nil
}
func (c *msgCache) DelMsgFromCache(ctx context.Context, userID string, seqs []int64) error {
diff --git a/pkg/common/db/cache/msg_test.go b/pkg/common/db/cache/msg_test.go
index a5be018ed..3fddf5965 100644
--- a/pkg/common/db/cache/msg_test.go
+++ b/pkg/common/db/cache/msg_test.go
@@ -385,50 +385,3 @@ func testParallelDeleteMessagesMix(t *testing.T, cid string, seqs []int64, input
assert.EqualValues(t, 1, val) // exists
}
}
-
-func TestCleanUpOneConversationAllMsg(t *testing.T) {
- rdb := redis.NewClient(&redis.Options{})
- defer rdb.Close()
-
- cacher := msgCache{rdb: rdb}
- count := 1000
- prefix := fmt.Sprintf("%v", rand.Int63())
-
- ids := []string{}
- for i := 0; i < count; i++ {
- id := fmt.Sprintf("%v-cid-%v", prefix, rand.Int63())
- ids = append(ids, id)
-
- key := cacher.allMessageCacheKey(id)
- rdb.Set(context.Background(), key, "openim", 0)
- }
-
- // delete 100 keys with scan.
- for i := 0; i < 100; i++ {
- pickedKey := ids[i]
- err := cacher.CleanUpOneConversationAllMsg(context.Background(), pickedKey)
- assert.Nil(t, err)
-
- ls, err := rdb.Keys(context.Background(), pickedKey).Result()
- assert.Nil(t, err)
- assert.Equal(t, 0, len(ls))
-
- rcode, err := rdb.Exists(context.Background(), pickedKey).Result()
- assert.Nil(t, err)
- assert.EqualValues(t, 0, rcode) // non-exists
- }
-
- sid := fmt.Sprintf("%v-cid-*", prefix)
- ls, err := rdb.Keys(context.Background(), cacher.allMessageCacheKey(sid)).Result()
- assert.Nil(t, err)
- assert.Equal(t, count-100, len(ls))
-
- // delete fuzzy matching keys.
- err = cacher.CleanUpOneConversationAllMsg(context.Background(), sid)
- assert.Nil(t, err)
-
- // don't contains keys matched `{prefix}-cid-{random}` on redis
- ls, err = rdb.Keys(context.Background(), cacher.allMessageCacheKey(sid)).Result()
- assert.Nil(t, err)
- assert.Equal(t, 0, len(ls))
-}
diff --git a/pkg/common/db/cache/s3.go b/pkg/common/db/cache/s3.go
index 3520ba2ec..ba40ceacc 100644
--- a/pkg/common/db/cache/s3.go
+++ b/pkg/common/db/cache/s3.go
@@ -14,8 +14,8 @@ import (
type ObjectCache interface {
metaCache
- GetName(ctx context.Context, name string) (*relationtb.ObjectModel, error)
- DelObjectName(names ...string) ObjectCache
+ GetName(ctx context.Context, engine string, name string) (*relationtb.ObjectModel, error)
+ DelObjectName(engine string, names ...string) ObjectCache
}
func NewObjectCacheRedis(rdb redis.UniversalClient, objDB relationtb.ObjectInfoModelInterface) ObjectCache {
@@ -44,23 +44,23 @@ func (g *objectCacheRedis) NewCache() ObjectCache {
}
}
-func (g *objectCacheRedis) DelObjectName(names ...string) ObjectCache {
+func (g *objectCacheRedis) DelObjectName(engine string, names ...string) ObjectCache {
objectCache := g.NewCache()
keys := make([]string, 0, len(names))
for _, name := range names {
- keys = append(keys, g.getObjectKey(name))
+ keys = append(keys, g.getObjectKey(name, engine))
}
objectCache.AddKeys(keys...)
return objectCache
}
-func (g *objectCacheRedis) getObjectKey(name string) string {
- return "OBJECT:" + name
+func (g *objectCacheRedis) getObjectKey(engine string, name string) string {
+ return "OBJECT:" + engine + ":" + name
}
-func (g *objectCacheRedis) GetName(ctx context.Context, name string) (*relationtb.ObjectModel, error) {
- return getCache(ctx, g.rcClient, g.getObjectKey(name), g.expireTime, func(ctx context.Context) (*relationtb.ObjectModel, error) {
- return g.objDB.Take(ctx, name)
+func (g *objectCacheRedis) GetName(ctx context.Context, engine string, name string) (*relationtb.ObjectModel, error) {
+ return getCache(ctx, g.rcClient, g.getObjectKey(name, engine), g.expireTime, func(ctx context.Context) (*relationtb.ObjectModel, error) {
+ return g.objDB.Take(ctx, engine, name)
})
}
diff --git a/pkg/common/db/cache/user.go b/pkg/common/db/cache/user.go
index d1164f2c0..979bd06e4 100644
--- a/pkg/common/db/cache/user.go
+++ b/pkg/common/db/cache/user.go
@@ -22,6 +22,8 @@ import (
"strconv"
"time"
+ relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/protocol/constant"
@@ -31,8 +33,6 @@ import (
"github.com/dtm-labs/rockscache"
"github.com/redis/go-redis/v9"
-
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
const (
@@ -59,7 +59,8 @@ type UserCache interface {
type UserCacheRedis struct {
metaCache
- rdb redis.UniversalClient
+ rdb redis.UniversalClient
+ //userDB relationtb.UserModelInterface
userDB relationtb.UserModelInterface
expireTime time.Duration
rcClient *rockscache.Client
@@ -100,39 +101,13 @@ func (u *UserCacheRedis) getUserGlobalRecvMsgOptKey(userID string) string {
}
func (u *UserCacheRedis) GetUserInfo(ctx context.Context, userID string) (userInfo *relationtb.UserModel, err error) {
- return getCache(
- ctx,
- u.rcClient,
- u.getUserInfoKey(userID),
- u.expireTime,
- func(ctx context.Context) (*relationtb.UserModel, error) {
- return u.userDB.Take(ctx, userID)
- },
+ return getCache(ctx, u.rcClient, u.getUserInfoKey(userID), u.expireTime, func(ctx context.Context) (*relationtb.UserModel, error) {
+ return u.userDB.Take(ctx, userID)
+ },
)
}
func (u *UserCacheRedis) GetUsersInfo(ctx context.Context, userIDs []string) ([]*relationtb.UserModel, error) {
- //var keys []string
- //for _, userID := range userIDs {
- // keys = append(keys, u.getUserInfoKey(userID))
- //}
- //return batchGetCache(
- // ctx,
- // u.rcClient,
- // keys,
- // u.expireTime,
- // func(user *relationtb.UserModel, keys []string) (int, error) {
- // for i, key := range keys {
- // if key == u.getUserInfoKey(user.UserID) {
- // return i, nil
- // }
- // }
- // return 0, errIndex
- // },
- // func(ctx context.Context) ([]*relationtb.UserModel, error) {
- // return u.userDB.Find(ctx, userIDs)
- // },
- //)
return batchGetCache2(ctx, u.rcClient, u.expireTime, userIDs, func(userID string) string {
return u.getUserInfoKey(userID)
}, func(ctx context.Context, userID string) (*relationtb.UserModel, error) {
@@ -214,8 +189,7 @@ func (u *UserCacheRedis) SetUserStatus(ctx context.Context, userID string, statu
UserIDNum := crc32.ChecksumIEEE([]byte(userID))
modKey := strconv.Itoa(int(UserIDNum % statusMod))
key := olineStatusKey + modKey
- log.ZDebug(ctx, "SetUserStatus args", "userID", userID, "status", status,
- "platformID", platformID, "modKey", modKey, "key", key)
+ log.ZDebug(ctx, "SetUserStatus args", "userID", userID, "status", status, "platformID", platformID, "modKey", modKey, "key", key)
isNewKey, err := u.rdb.Exists(ctx, key).Result()
if err != nil {
return errs.Wrap(err)
diff --git a/pkg/common/db/controller/black.go b/pkg/common/db/controller/black.go
index 70e942a77..e68d06b01 100644
--- a/pkg/common/db/controller/black.go
+++ b/pkg/common/db/controller/black.go
@@ -17,6 +17,8 @@ package controller
import (
"context"
+ "github.com/OpenIMSDK/tools/pagination"
+
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/utils"
@@ -30,12 +32,7 @@ type BlackDatabase interface {
// Delete 删除黑名单
Delete(ctx context.Context, blacks []*relation.BlackModel) (err error)
// FindOwnerBlacks 获取黑名单列表
- FindOwnerBlacks(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
- ) (blacks []*relation.BlackModel, total int64, err error)
- FindBlackIDs(ctx context.Context, ownerUserID string) (blackIDs []string, err error)
+ FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error)
FindBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error)
// CheckIn 检查user2是否在user1的黑名单列表中(inUser1Blacks==true) 检查user1是否在user2的黑名单列表中(inUser2Blacks==true)
CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Blacks bool, inUser2Blacks bool, err error)
@@ -75,12 +72,8 @@ func (b *blackDatabase) deleteBlackIDsCache(ctx context.Context, blacks []*relat
}
// FindOwnerBlacks 获取黑名单列表.
-func (b *blackDatabase) FindOwnerBlacks(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
-) (blacks []*relation.BlackModel, total int64, err error) {
- return b.black.FindOwnerBlacks(ctx, ownerUserID, pageNumber, showNumber)
+func (b *blackDatabase) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) {
+ return b.black.FindOwnerBlacks(ctx, ownerUserID, pagination)
}
// CheckIn 检查user2是否在user1的黑名单列表中(inUser1Blacks==true) 检查user1是否在user2的黑名单列表中(inUser2Blacks==true).
diff --git a/pkg/common/db/controller/chatlog.go b/pkg/common/db/controller/chatlog.go
deleted file mode 100644
index def490265..000000000
--- a/pkg/common/db/controller/chatlog.go
+++ /dev/null
@@ -1,37 +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 controller
-
-import (
- pbmsg "github.com/OpenIMSDK/protocol/msg"
-
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type ChatLogDatabase interface {
- CreateChatLog(msg *pbmsg.MsgDataToMQ) error
-}
-
-func NewChatLogDatabase(chatLogModelInterface relationtb.ChatLogModelInterface) ChatLogDatabase {
- return &chatLogDatabase{chatLogModel: chatLogModelInterface}
-}
-
-type chatLogDatabase struct {
- chatLogModel relationtb.ChatLogModelInterface
-}
-
-func (c *chatLogDatabase) CreateChatLog(msg *pbmsg.MsgDataToMQ) error {
- return c.chatLogModel.Create(msg)
-}
diff --git a/pkg/common/db/controller/conversation.go b/pkg/common/db/controller/conversation.go
index 0aaa95880..2a0cb63e4 100644
--- a/pkg/common/db/controller/conversation.go
+++ b/pkg/common/db/controller/conversation.go
@@ -18,6 +18,8 @@ import (
"context"
"time"
+ "github.com/OpenIMSDK/tools/pagination"
+
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
"github.com/OpenIMSDK/protocol/constant"
@@ -31,7 +33,7 @@ import (
type ConversationDatabase interface {
// UpdateUserConversationFiled 更新用户该会话的属性信息
- UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) error
+ UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error
// CreateConversation 创建一批新的会话
CreateConversation(ctx context.Context, conversations []*relationtb.ConversationModel) error
// SyncPeerUserPrivateConversation 同步对端私聊会话内部保证事务操作
@@ -39,26 +41,26 @@ type ConversationDatabase interface {
// FindConversations 根据会话ID获取某个用户的多个会话
FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error)
// FindRecvMsgNotNotifyUserIDs 获取超级大群开启免打扰的用户ID
- FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
+ //FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
// GetUserAllConversation 获取一个用户在服务器上所有的会话
GetUserAllConversation(ctx context.Context, ownerUserID string) ([]*relationtb.ConversationModel, error)
// SetUserConversations 设置用户多个会话属性,如果会话不存在则创建,否则更新,内部保证原子性
SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error
// SetUsersConversationFiledTx 设置多个用户会话关于某个字段的更新操作,如果会话不存在则创建,否则更新,内部保证事务操作
- SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]interface{}) error
+ SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]any) error
CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error
GetConversationIDs(ctx context.Context, userID string) ([]string, error)
GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error)
GetAllConversationIDs(ctx context.Context) ([]string, error)
GetAllConversationIDsNumber(ctx context.Context) (int64, error)
- PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error)
+ PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
//GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error)
GetConversationIDsNeedDestruct(ctx context.Context) ([]*relationtb.ConversationModel, error)
GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
}
-func NewConversationDatabase(conversation relationtb.ConversationModelInterface, cache cache.ConversationCache, tx tx.Tx) ConversationDatabase {
+func NewConversationDatabase(conversation relationtb.ConversationModelInterface, cache cache.ConversationCache, tx tx.CtxTx) ConversationDatabase {
return &conversationDatabase{
conversationDB: conversation,
cache: cache,
@@ -69,22 +71,21 @@ func NewConversationDatabase(conversation relationtb.ConversationModelInterface,
type conversationDatabase struct {
conversationDB relationtb.ConversationModelInterface
cache cache.ConversationCache
- tx tx.Tx
+ tx tx.CtxTx
}
-func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]interface{}) (err error) {
- cache := c.cache.NewCache()
- if conversation.GroupID != "" {
- cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(conversation.GroupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(conversation.GroupID)
- }
- if err := c.tx.Transaction(func(tx any) error {
- conversationTx := c.conversationDB.NewTx(tx)
- haveUserIDs, err := conversationTx.FindUserID(ctx, userIDs, []string{conversation.ConversationID})
+func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]any) (err error) {
+ return c.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := c.cache.NewCache()
+ if conversation.GroupID != "" {
+ cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(conversation.GroupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(conversation.GroupID)
+ }
+ haveUserIDs, err := c.conversationDB.FindUserID(ctx, userIDs, []string{conversation.ConversationID})
if err != nil {
return err
}
if len(haveUserIDs) > 0 {
- _, err = conversationTx.UpdateByMap(ctx, haveUserIDs, conversation.ConversationID, filedMap)
+ _, err = c.conversationDB.UpdateByMap(ctx, haveUserIDs, conversation.ConversationID, filedMap)
if err != nil {
return err
}
@@ -112,20 +113,17 @@ func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context,
conversations = append(conversations, temp)
}
if len(conversations) > 0 {
- err = conversationTx.Create(ctx, conversations)
+ err = c.conversationDB.Create(ctx, conversations)
if err != nil {
return err
}
cache = cache.DelConversationIDs(NotUserIDs...).DelUserConversationIDsHash(NotUserIDs...).DelConversations(conversation.ConversationID, NotUserIDs...)
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
+ })
}
-func (c *conversationDatabase) UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) error {
+func (c *conversationDatabase) UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error {
_, err := c.conversationDB.UpdateByMap(ctx, userIDs, conversationID, args)
if err != nil {
return err
@@ -153,19 +151,18 @@ func (c *conversationDatabase) CreateConversation(ctx context.Context, conversat
}
func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Context, conversations []*relationtb.ConversationModel) error {
- cache := c.cache.NewCache()
- if err := c.tx.Transaction(func(tx any) error {
- conversationTx := c.conversationDB.NewTx(tx)
+ return c.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := c.cache.NewCache()
for _, conversation := range conversations {
for _, v := range [][2]string{{conversation.OwnerUserID, conversation.UserID}, {conversation.UserID, conversation.OwnerUserID}} {
ownerUserID := v[0]
userID := v[1]
- haveUserIDs, err := conversationTx.FindUserID(ctx, []string{ownerUserID}, []string{conversation.ConversationID})
+ haveUserIDs, err := c.conversationDB.FindUserID(ctx, []string{ownerUserID}, []string{conversation.ConversationID})
if err != nil {
return err
}
if len(haveUserIDs) > 0 {
- _, err := conversationTx.UpdateByMap(ctx, []string{ownerUserID}, conversation.ConversationID, map[string]interface{}{"is_private_chat": conversation.IsPrivateChat})
+ _, err := c.conversationDB.UpdateByMap(ctx, []string{ownerUserID}, conversation.ConversationID, map[string]any{"is_private_chat": conversation.IsPrivateChat})
if err != nil {
return err
}
@@ -176,18 +173,15 @@ func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Con
newConversation.UserID = userID
newConversation.ConversationID = conversation.ConversationID
newConversation.IsPrivateChat = conversation.IsPrivateChat
- if err := conversationTx.Create(ctx, []*relationtb.ConversationModel{&newConversation}); err != nil {
+ if err := c.conversationDB.Create(ctx, []*relationtb.ConversationModel{&newConversation}); err != nil {
return err
}
cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID)
}
}
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
+ })
}
func (c *conversationDatabase) FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
@@ -203,28 +197,26 @@ func (c *conversationDatabase) GetUserAllConversation(ctx context.Context, owner
}
func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error {
- cache := c.cache.NewCache()
-
- groupIDs := utils.Distinct(utils.Filter(conversations, func(e *relationtb.ConversationModel) (string, bool) {
- return e.GroupID, e.GroupID != ""
- }))
- for _, groupID := range groupIDs {
- cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(groupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID)
- }
- if err := c.tx.Transaction(func(tx any) error {
+ return c.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := c.cache.NewCache()
+ groupIDs := utils.Distinct(utils.Filter(conversations, func(e *relationtb.ConversationModel) (string, bool) {
+ return e.GroupID, e.GroupID != ""
+ }))
+ for _, groupID := range groupIDs {
+ cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(groupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID)
+ }
var conversationIDs []string
for _, conversation := range conversations {
conversationIDs = append(conversationIDs, conversation.ConversationID)
cache = cache.DelConversations(conversation.OwnerUserID, conversation.ConversationID)
}
- conversationTx := c.conversationDB.NewTx(tx)
- existConversations, err := conversationTx.Find(ctx, ownerUserID, conversationIDs)
+ existConversations, err := c.conversationDB.Find(ctx, ownerUserID, conversationIDs)
if err != nil {
return err
}
if len(existConversations) > 0 {
for _, conversation := range conversations {
- err = conversationTx.Update(ctx, conversation)
+ err = c.conversationDB.Update(ctx, conversation)
if err != nil {
return err
}
@@ -246,23 +238,22 @@ func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUs
if err != nil {
return err
}
- cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID).DelConversationNotReceiveMessageUserIDs(utils.Slice(notExistConversations, func(e *relationtb.ConversationModel) string { return e.ConversationID })...)
+ cache = cache.DelConversationIDs(ownerUserID).
+ DelUserConversationIDsHash(ownerUserID).
+ DelConversationNotReceiveMessageUserIDs(utils.Slice(notExistConversations, func(e *relationtb.ConversationModel) string { return e.ConversationID })...)
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
+ })
}
-func (c *conversationDatabase) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) {
- return c.cache.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
-}
+//func (c *conversationDatabase) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) {
+// return c.cache.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
+//}
func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error {
- cache := c.cache.NewCache()
- conversationID := msgprocessor.GetConversationIDBySessionType(constant.SuperGroupChatType, groupID)
- if err := c.tx.Transaction(func(tx any) error {
+ return c.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := c.cache.NewCache()
+ conversationID := msgprocessor.GetConversationIDBySessionType(constant.SuperGroupChatType, groupID)
existConversationUserIDs, err := c.conversationDB.FindUserID(ctx, userIDs, []string{conversationID})
if err != nil {
return err
@@ -281,18 +272,15 @@ func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context,
return err
}
}
- _, err = c.conversationDB.UpdateByMap(ctx, existConversationUserIDs, conversationID, map[string]interface{}{"max_seq": 0})
+ _, err = c.conversationDB.UpdateByMap(ctx, existConversationUserIDs, conversationID, map[string]any{"max_seq": 0})
if err != nil {
return err
}
for _, v := range existConversationUserIDs {
cache = cache.DelConversations(v, conversationID)
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return c.cache.ExecDel(ctx)
+ })
}
func (c *conversationDatabase) GetConversationIDs(ctx context.Context, userID string) ([]string, error) {
@@ -311,14 +299,10 @@ func (c *conversationDatabase) GetAllConversationIDsNumber(ctx context.Context)
return c.conversationDB.GetAllConversationIDsNumber(ctx)
}
-func (c *conversationDatabase) PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) ([]string, error) {
- return c.conversationDB.PageConversationIDs(ctx, pageNumber, showNumber)
+func (c *conversationDatabase) PageConversationIDs(ctx context.Context, pagination pagination.Pagination) ([]string, error) {
+ return c.conversationDB.PageConversationIDs(ctx, pagination)
}
-//func (c *conversationDatabase) GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error) {
-// return c.cache.GetUserAllHasReadSeqs(ctx, ownerUserID)
-//}
-
func (c *conversationDatabase) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
return c.conversationDB.GetConversationsByConversationID(ctx, conversationIDs)
}
diff --git a/pkg/common/db/controller/friend.go b/pkg/common/db/controller/friend.go
index 7816ef935..29b2ef9b1 100644
--- a/pkg/common/db/controller/friend.go
+++ b/pkg/common/db/controller/friend.go
@@ -18,7 +18,7 @@ import (
"context"
"time"
- "gorm.io/gorm"
+ "github.com/OpenIMSDK/tools/pagination"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/errs"
@@ -47,35 +47,15 @@ type FriendDatabase interface {
// 更新好友备注
UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
// 获取ownerUserID的好友列表
- PageOwnerFriends(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
- ) (friends []*relation.FriendModel, total int64, err error)
+ PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
// friendUserID在哪些人的好友列表中
- PageInWhoseFriends(
- ctx context.Context,
- friendUserID string,
- pageNumber, showNumber int32,
- ) (friends []*relation.FriendModel, total int64, err error)
+ PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
// 获取我发出去的好友申请
- PageFriendRequestFromMe(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
- ) (friends []*relation.FriendRequestModel, total int64, err error)
+ PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
// 获取我收到的的好友申请
- PageFriendRequestToMe(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
- ) (friends []*relation.FriendRequestModel, total int64, err error)
+ PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
// 获取某人指定好友的信息
- FindFriendsWithError(
- ctx context.Context,
- ownerUserID string,
- friendUserIDs []string,
- ) (friends []*relation.FriendModel, err error)
+ FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error)
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error)
}
@@ -83,24 +63,16 @@ type FriendDatabase interface {
type friendDatabase struct {
friend relation.FriendModelInterface
friendRequest relation.FriendRequestModelInterface
- tx tx.Tx
+ tx tx.CtxTx
cache cache.FriendCache
}
-func NewFriendDatabase(
- friend relation.FriendModelInterface,
- friendRequest relation.FriendRequestModelInterface,
- cache cache.FriendCache,
- tx tx.Tx,
-) FriendDatabase {
+func NewFriendDatabase(friend relation.FriendModelInterface, friendRequest relation.FriendRequestModelInterface, cache cache.FriendCache, tx tx.CtxTx) FriendDatabase {
return &friendDatabase{friend: friend, friendRequest: friendRequest, cache: cache, tx: tx}
}
// ok 检查user2是否在user1的好友列表中(inUser1Friends==true) 检查user1是否在user2的好友列表中(inUser2Friends==true).
-func (f *friendDatabase) CheckIn(
- ctx context.Context,
- userID1, userID2 string,
-) (inUser1Friends bool, inUser2Friends bool, err error) {
+func (f *friendDatabase) CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Friends bool, inUser2Friends bool, err error) {
userID1FriendIDs, err := f.cache.GetFriendIDs(ctx, userID1)
if err != nil {
return
@@ -113,50 +85,35 @@ func (f *friendDatabase) CheckIn(
}
// 增加或者更新好友申请 如果之前有记录则更新,没有记录则新增.
-func (f *friendDatabase) AddFriendRequest(
- ctx context.Context,
- fromUserID, toUserID string,
- reqMsg string,
- ex string,
-) (err error) {
- return f.tx.Transaction(func(tx any) error {
- _, err := f.friendRequest.NewTx(tx).Take(ctx, fromUserID, toUserID)
- // 有db错误
- if err != nil && errs.Unwrap(err) != gorm.ErrRecordNotFound {
- return err
- }
- // 无错误 则更新
- if err == nil {
- m := make(map[string]interface{}, 1)
+func (f *friendDatabase) AddFriendRequest(ctx context.Context, fromUserID, toUserID string, reqMsg string, ex string) (err error) {
+ return f.tx.Transaction(ctx, func(ctx context.Context) error {
+ _, err := f.friendRequest.Take(ctx, fromUserID, toUserID)
+ switch {
+ case err == nil:
+ m := make(map[string]any, 1)
m["handle_result"] = 0
m["handle_msg"] = ""
m["req_msg"] = reqMsg
m["ex"] = ex
m["create_time"] = time.Now()
- if err := f.friendRequest.NewTx(tx).UpdateByMap(ctx, fromUserID, toUserID, m); err != nil {
- return err
- }
- return nil
- }
- // gorm.ErrRecordNotFound 错误,则新增
- if err := f.friendRequest.NewTx(tx).Create(ctx, []*relation.FriendRequestModel{{FromUserID: fromUserID, ToUserID: toUserID, ReqMsg: reqMsg, Ex: ex, CreateTime: time.Now(), HandleTime: time.Unix(0, 0)}}); err != nil {
+ return f.friendRequest.UpdateByMap(ctx, fromUserID, toUserID, m)
+ case relation.IsNotFound(err):
+ return f.friendRequest.Create(
+ ctx,
+ []*relation.FriendRequestModel{{FromUserID: fromUserID, ToUserID: toUserID, ReqMsg: reqMsg, Ex: ex, CreateTime: time.Now(), HandleTime: time.Unix(0, 0)}},
+ )
+ default:
return err
}
- return nil
})
}
// (1)先判断是否在好友表 (在不在都不返回错误) (2)对于不在好友列表的 插入即可.
-func (f *friendDatabase) BecomeFriends(
- ctx context.Context,
- ownerUserID string,
- friendUserIDs []string,
- addSource int32,
-) (err error) {
- cache := f.cache.NewCache()
- if err := f.tx.Transaction(func(tx any) error {
+func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error) {
+ return f.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := f.cache.NewCache()
// 先find 找出重复的 去掉重复的
- fs1, err := f.friend.NewTx(tx).FindFriends(ctx, ownerUserID, friendUserIDs)
+ fs1, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return err
}
@@ -168,11 +125,11 @@ func (f *friendDatabase) BecomeFriends(
return e.FriendUserID
})
- err = f.friend.NewTx(tx).Create(ctx, fs11)
+ err = f.friend.Create(ctx, fs11)
if err != nil {
return err
}
- fs2, err := f.friend.NewTx(tx).FindReversalFriends(ctx, ownerUserID, friendUserIDs)
+ fs2, err := f.friend.FindReversalFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return err
}
@@ -184,24 +141,19 @@ func (f *friendDatabase) BecomeFriends(
fs22 := utils.DistinctAny(fs2, func(e *relation.FriendModel) string {
return e.OwnerUserID
})
- err = f.friend.NewTx(tx).Create(ctx, fs22)
+ err = f.friend.Create(ctx, fs22)
if err != nil {
return err
}
newFriendIDs = append(newFriendIDs, ownerUserID)
cache = cache.DelFriendIDs(newFriendIDs...)
- return nil
- }); err != nil {
- return nil
- }
- return cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
+
+ })
}
// 拒绝好友申请 (1)检查是否有申请记录且为未处理状态 (没有记录返回错误) (2)修改申请记录 已拒绝.
-func (f *friendDatabase) RefuseFriendRequest(
- ctx context.Context,
- friendRequest *relation.FriendRequestModel,
-) (err error) {
+func (f *friendDatabase) RefuseFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
if err != nil {
return err
@@ -220,14 +172,11 @@ func (f *friendDatabase) RefuseFriendRequest(
}
// AgreeFriendRequest 同意好友申请 (1)检查是否有申请记录且为未处理状态 (没有记录返回错误) (2)检查是否好友(不返回错误) (3) 建立双向好友关系(存在的忽略).
-func (f *friendDatabase) AgreeFriendRequest(
- ctx context.Context,
- friendRequest *relation.FriendRequestModel,
-) (err error) {
- return f.tx.Transaction(func(tx any) error {
+func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
+ return f.tx.Transaction(ctx, func(ctx context.Context) error {
defer log.ZDebug(ctx, "return line")
now := time.Now()
- fr, err := f.friendRequest.NewTx(tx).Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
+ fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
if err != nil {
return err
}
@@ -237,25 +186,25 @@ func (f *friendDatabase) AgreeFriendRequest(
friendRequest.HandlerUserID = mcontext.GetOpUserID(ctx)
friendRequest.HandleResult = constant.FriendResponseAgree
friendRequest.HandleTime = now
- err = f.friendRequest.NewTx(tx).Update(ctx, friendRequest)
+ err = f.friendRequest.Update(ctx, friendRequest)
if err != nil {
return err
}
- fr2, err := f.friendRequest.NewTx(tx).Take(ctx, friendRequest.ToUserID, friendRequest.FromUserID)
+ fr2, err := f.friendRequest.Take(ctx, friendRequest.ToUserID, friendRequest.FromUserID)
if err == nil && fr2.HandleResult == constant.FriendResponseNotHandle {
fr2.HandlerUserID = mcontext.GetOpUserID(ctx)
fr2.HandleResult = constant.FriendResponseAgree
fr2.HandleTime = now
- err = f.friendRequest.NewTx(tx).Update(ctx, fr2)
+ err = f.friendRequest.Update(ctx, fr2)
if err != nil {
return err
}
- } else if err != nil && errs.Unwrap(err) != gorm.ErrRecordNotFound {
+ } else if err != nil && (!relation.IsNotFound(err)) {
return err
}
- exists, err := f.friend.NewTx(tx).FindUserState(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
+ exists, err := f.friend.FindUserState(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
if err != nil {
return err
}
@@ -286,7 +235,7 @@ func (f *friendDatabase) AgreeFriendRequest(
)
}
if len(adds) > 0 {
- if err := f.friend.NewTx(tx).Create(ctx, adds); err != nil {
+ if err := f.friend.Create(ctx, adds); err != nil {
return err
}
}
@@ -311,47 +260,27 @@ func (f *friendDatabase) UpdateRemark(ctx context.Context, ownerUserID, friendUs
}
// 获取ownerUserID的好友列表 无结果不返回错误.
-func (f *friendDatabase) PageOwnerFriends(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendModel, total int64, err error) {
- return f.friend.FindOwnerFriends(ctx, ownerUserID, pageNumber, showNumber)
+func (f *friendDatabase) PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) {
+ return f.friend.FindOwnerFriends(ctx, ownerUserID, pagination)
}
// friendUserID在哪些人的好友列表中.
-func (f *friendDatabase) PageInWhoseFriends(
- ctx context.Context,
- friendUserID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendModel, total int64, err error) {
- return f.friend.FindInWhoseFriends(ctx, friendUserID, pageNumber, showNumber)
+func (f *friendDatabase) PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) {
+ return f.friend.FindInWhoseFriends(ctx, friendUserID, pagination)
}
// 获取我发出去的好友申请 无结果不返回错误.
-func (f *friendDatabase) PageFriendRequestFromMe(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendRequestModel, total int64, err error) {
- return f.friendRequest.FindFromUserID(ctx, userID, pageNumber, showNumber)
+func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) {
+ return f.friendRequest.FindFromUserID(ctx, userID, pagination)
}
// 获取我收到的的好友申请 无结果不返回错误.
-func (f *friendDatabase) PageFriendRequestToMe(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendRequestModel, total int64, err error) {
- return f.friendRequest.FindToUserID(ctx, userID, pageNumber, showNumber)
+func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) {
+ return f.friendRequest.FindToUserID(ctx, userID, pagination)
}
// 获取某人指定好友的信息 如果有好友不存在,也返回错误.
-func (f *friendDatabase) FindFriendsWithError(
- ctx context.Context,
- ownerUserID string,
- friendUserIDs []string,
-) (friends []*relation.FriendModel, err error) {
+func (f *friendDatabase) FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error) {
friends, err = f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return
@@ -362,10 +291,7 @@ func (f *friendDatabase) FindFriendsWithError(
return
}
-func (f *friendDatabase) FindFriendUserIDs(
- ctx context.Context,
- ownerUserID string,
-) (friendUserIDs []string, err error) {
+func (f *friendDatabase) FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) {
return f.cache.GetFriendIDs(ctx, ownerUserID)
}
diff --git a/pkg/common/db/controller/group.go b/pkg/common/db/controller/group.go
index 194f3e8b2..4147d59c0 100644
--- a/pkg/common/db/controller/group.go
+++ b/pkg/common/db/controller/group.go
@@ -16,23 +16,18 @@ package controller
import (
"context"
- "fmt"
"time"
+ "github.com/OpenIMSDK/tools/pagination"
"github.com/dtm-labs/rockscache"
- "github.com/redis/go-redis/v9"
- "go.mongodb.org/mongo-driver/mongo"
- "gorm.io/gorm"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
+ "github.com/redis/go-redis/v9"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
- unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
)
type GroupDatabase interface {
@@ -40,23 +35,26 @@ type GroupDatabase interface {
CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error
TakeGroup(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error)
FindGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error)
- FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error)
- SearchGroup(ctx context.Context, keyword string, pageNumber, showNumber int32) (uint32, []*relationtb.GroupModel, error)
+ SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*relationtb.GroupModel, error)
UpdateGroup(ctx context.Context, groupID string, data map[string]any) error
DismissGroup(ctx context.Context, groupID string, deleteMember bool) error // 解散群,并删除群成员
- GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error)
- // GroupMember
+
TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *relationtb.GroupMemberModel, err error)
TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error)
- FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error)
+ FindGroupMembers(ctx context.Context, groupID string, userIDs []string) (groupMembers []*relationtb.GroupMemberModel, err error) // *
+ FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (groupMembers []*relationtb.GroupMemberModel, err error) // *
+ FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) (groupMembers []*relationtb.GroupMemberModel, err error) // *
+ FindGroupMemberAll(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error) // *
+ FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error)
FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error)
FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error)
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
- PageGroupRequest(ctx context.Context, groupIDs []string, pageNumber, showNumber int32) (uint32, []*relationtb.GroupRequestModel, error)
+ PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error)
+ GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
- PageGetJoinGroup(ctx context.Context, userID string, pageNumber, showNumber int32) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error)
- PageGetGroupMember(ctx context.Context, groupID string, pageNumber, showNumber int32) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error)
- SearchGroupMember(ctx context.Context, keyword string, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32) (uint32, []*relationtb.GroupMemberModel, error)
+ PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error)
+ PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error)
+ SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*relationtb.GroupMemberModel, error)
HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error
DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error
MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error)
@@ -67,15 +65,8 @@ type GroupDatabase interface {
// GroupRequest
CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error
TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationtb.GroupRequestModel, error)
- FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*relationtb.GroupRequestModel, error)
- PageGroupRequestUser(ctx context.Context, userID string, pageNumber, showNumber int32) (uint32, []*relationtb.GroupRequestModel, error)
- // SuperGroupModelInterface
- FindSuperGroup(ctx context.Context, groupIDs []string) ([]*unrelationtb.SuperGroupModel, error)
- FindJoinSuperGroup(ctx context.Context, userID string) ([]string, error)
- CreateSuperGroup(ctx context.Context, groupID string, initMemberIDList []string) error
- DeleteSuperGroup(ctx context.Context, groupID string) error
- DeleteSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error
- CreateSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error
+ FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupRequestModel, error)
+ PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error)
// 获取群总数
CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
@@ -85,126 +76,115 @@ type GroupDatabase interface {
}
func NewGroupDatabase(
- group relationtb.GroupModelInterface,
- member relationtb.GroupMemberModelInterface,
- request relationtb.GroupRequestModelInterface,
- tx tx.Tx,
+ rdb redis.UniversalClient,
+ groupDB relationtb.GroupModelInterface,
+ groupMemberDB relationtb.GroupMemberModelInterface,
+ groupRequestDB relationtb.GroupRequestModelInterface,
ctxTx tx.CtxTx,
- superGroup unrelationtb.SuperGroupModelInterface,
- cache cache.GroupCache,
+ groupHash cache.GroupHash,
) GroupDatabase {
- database := &groupDatabase{
- groupDB: group,
- groupMemberDB: member,
- groupRequestDB: request,
- tx: tx,
- ctxTx: ctxTx,
- cache: cache,
- mongoDB: superGroup,
- }
- return database
-}
-
-func InitGroupDatabase(db *gorm.DB, rdb redis.UniversalClient, database *mongo.Database, hashCode func(ctx context.Context, groupID string) (uint64, error)) GroupDatabase {
rcOptions := rockscache.NewDefaultOptions()
rcOptions.StrongConsistency = true
rcOptions.RandomExpireAdjustment = 0.2
- return NewGroupDatabase(
- relation.NewGroupDB(db),
- relation.NewGroupMemberDB(db),
- relation.NewGroupRequest(db),
- tx.NewGorm(db),
- tx.NewMongo(database.Client()),
- unrelation.NewSuperGroupMongoDriver(database),
- cache.NewGroupCacheRedis(
- rdb,
- relation.NewGroupDB(db),
- relation.NewGroupMemberDB(db),
- relation.NewGroupRequest(db),
- unrelation.NewSuperGroupMongoDriver(database),
- hashCode,
- rcOptions,
- ),
- )
+ return &groupDatabase{
+ groupDB: groupDB,
+ groupMemberDB: groupMemberDB,
+ groupRequestDB: groupRequestDB,
+ ctxTx: ctxTx,
+ cache: cache.NewGroupCacheRedis(rdb, groupDB, groupMemberDB, groupRequestDB, groupHash, rcOptions),
+ }
}
type groupDatabase struct {
groupDB relationtb.GroupModelInterface
groupMemberDB relationtb.GroupMemberModelInterface
groupRequestDB relationtb.GroupRequestModelInterface
- tx tx.Tx
ctxTx tx.CtxTx
cache cache.GroupCache
- mongoDB unrelationtb.SuperGroupModelInterface
}
-func (g *groupDatabase) GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error) {
- return g.groupDB.GetGroupIDsByGroupType(ctx, groupType)
+func (g *groupDatabase) FindGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.GetGroupMembersInfo(ctx, groupID, userIDs)
}
-func (g *groupDatabase) FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) {
- return g.cache.GetGroupMemberIDs(ctx, groupID)
+func (g *groupDatabase) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.FindGroupMemberUser(ctx, groupIDs, userID)
}
-func (g *groupDatabase) FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error) {
- num, err := g.cache.GetGroupMemberNum(ctx, groupID)
- if err != nil {
- return 0, err
- }
- return uint32(num), nil
+func (g *groupDatabase) FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.GetGroupRolesLevelMemberInfo(ctx, groupID, roleLevels)
}
-func (g *groupDatabase) CreateGroup(
- ctx context.Context,
- groups []*relationtb.GroupModel,
- groupMembers []*relationtb.GroupMemberModel,
-) error {
- cache := g.cache.NewCache()
- if err := g.tx.Transaction(func(tx any) error {
+func (g *groupDatabase) FindGroupMemberAll(ctx context.Context, groupID string) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.GetAllGroupMembersInfo(ctx, groupID)
+}
+
+func (g *groupDatabase) FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.GetGroupsOwner(ctx, groupIDs)
+}
+
+func (g *groupDatabase) GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) {
+ return g.cache.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
+}
+
+func (g *groupDatabase) CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error {
+ if len(groups)+len(groupMembers) == 0 {
+ return nil
+ }
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ c := g.cache.NewCache()
if len(groups) > 0 {
- if err := g.groupDB.NewTx(tx).Create(ctx, groups); err != nil {
+ if err := g.groupDB.Create(ctx, groups); err != nil {
return err
}
+ for _, group := range groups {
+ c = c.DelGroupsInfo(group.GroupID).
+ DelGroupMembersHash(group.GroupID).
+ DelGroupMembersHash(group.GroupID).
+ DelGroupsMemberNum(group.GroupID).
+ DelGroupMemberIDs(group.GroupID).
+ DelGroupAllRoleLevel(group.GroupID)
+ }
}
if len(groupMembers) > 0 {
- if err := g.groupMemberDB.NewTx(tx).Create(ctx, groupMembers); err != nil {
+ if err := g.groupMemberDB.Create(ctx, groupMembers); err != nil {
return err
}
- }
- createGroupIDs := utils.DistinctAnyGetComparable(groups, func(group *relationtb.GroupModel) string {
- return group.GroupID
- })
- m := make(map[string]struct{})
-
- for _, groupMember := range groupMembers {
- if _, ok := m[groupMember.GroupID]; !ok {
- m[groupMember.GroupID] = struct{}{}
- cache = cache.DelGroupMemberIDs(groupMember.GroupID).DelGroupMembersHash(groupMember.GroupID).DelGroupsMemberNum(groupMember.GroupID)
+ for _, groupMember := range groupMembers {
+ c = c.DelGroupMembersHash(groupMember.GroupID).
+ DelGroupsMemberNum(groupMember.GroupID).
+ DelGroupMemberIDs(groupMember.GroupID).
+ DelJoinedGroupID(groupMember.UserID).
+ DelGroupMembersInfo(groupMember.GroupID, groupMember.UserID).
+ DelGroupAllRoleLevel(groupMember.GroupID)
}
- cache = cache.DelJoinedGroupID(groupMember.UserID).DelGroupMembersInfo(groupMember.GroupID, groupMember.UserID)
}
- cache = cache.DelGroupsInfo(createGroupIDs...)
- return nil
- }); err != nil {
- return err
+ return c.ExecDel(ctx, true)
+ })
+}
+
+func (g *groupDatabase) FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) {
+ return g.cache.GetGroupMemberIDs(ctx, groupID)
+}
+
+func (g *groupDatabase) FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error) {
+ num, err := g.cache.GetGroupMemberNum(ctx, groupID)
+ if err != nil {
+ return 0, err
}
- return cache.ExecDel(ctx)
+ return uint32(num), nil
}
-func (g *groupDatabase) TakeGroup(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error) {
+func (g *groupDatabase) TakeGroup(ctx context.Context, groupID string) (*relationtb.GroupModel, error) {
return g.cache.GetGroupInfo(ctx, groupID)
}
-func (g *groupDatabase) FindGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) {
+func (g *groupDatabase) FindGroup(ctx context.Context, groupIDs []string) ([]*relationtb.GroupModel, error) {
return g.cache.GetGroupsInfo(ctx, groupIDs)
}
-func (g *groupDatabase) SearchGroup(
- ctx context.Context,
- keyword string,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupModel, error) {
- return g.groupDB.Search(ctx, keyword, pageNumber, showNumber)
+func (g *groupDatabase) SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*relationtb.GroupModel, error) {
+ return g.groupDB.Search(ctx, keyword, pagination)
}
func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data map[string]any) error {
@@ -215,166 +195,97 @@ func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data ma
}
func (g *groupDatabase) DismissGroup(ctx context.Context, groupID string, deleteMember bool) error {
- cache := g.cache.NewCache()
- if err := g.tx.Transaction(func(tx any) error {
- if err := g.groupDB.NewTx(tx).UpdateStatus(ctx, groupID, constant.GroupStatusDismissed); err != nil {
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ c := g.cache.NewCache()
+ if err := g.groupDB.UpdateState(ctx, groupID, constant.GroupStatusDismissed); err != nil {
return err
}
if deleteMember {
- if err := g.groupMemberDB.NewTx(tx).DeleteGroup(ctx, []string{groupID}); err != nil {
- return err
- }
userIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID)
if err != nil {
return err
}
- cache = cache.DelJoinedGroupID(userIDs...).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelGroupMembersHash(groupID)
+ if err := g.groupMemberDB.Delete(ctx, groupID, nil); err != nil {
+ return err
+ }
+ c = c.DelJoinedGroupID(userIDs...).
+ DelGroupMemberIDs(groupID).
+ DelGroupsMemberNum(groupID).
+ DelGroupMembersHash(groupID).
+ DelGroupAllRoleLevel(groupID).
+ DelGroupMembersInfo(groupID, userIDs...)
}
- cache = cache.DelGroupsInfo(groupID)
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return c.DelGroupsInfo(groupID).ExecDel(ctx)
+ })
}
-func (g *groupDatabase) TakeGroupMember(
- ctx context.Context,
- groupID string,
- userID string,
-) (groupMember *relationtb.GroupMemberModel, err error) {
+func (g *groupDatabase) TakeGroupMember(ctx context.Context, groupID string, userID string) (*relationtb.GroupMemberModel, error) {
return g.cache.GetGroupMemberInfo(ctx, groupID, userID)
}
func (g *groupDatabase) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
- return g.groupMemberDB.TakeOwner(ctx, groupID) // todo cache group owner
+ return g.cache.GetGroupOwner(ctx, groupID)
}
func (g *groupDatabase) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
return g.groupMemberDB.FindUserManagedGroupID(ctx, userID)
}
-func (g *groupDatabase) PageGroupRequest(
- ctx context.Context,
- groupIDs []string,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupRequestModel, error) {
- return g.groupRequestDB.PageGroup(ctx, groupIDs, pageNumber, showNumber)
-}
-
-func (g *groupDatabase) FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) (totalGroupMembers []*relationtb.GroupMemberModel, err error) {
- if len(groupIDs) == 0 && len(roleLevels) == 0 && len(userIDs) == 1 {
- gIDs, err := g.cache.GetJoinedGroupIDs(ctx, userIDs[0])
- if err != nil {
- return nil, err
- }
- var res []*relationtb.GroupMemberModel
- for _, groupID := range gIDs {
- v, err := g.cache.GetGroupMemberInfo(ctx, groupID, userIDs[0])
- if err != nil {
- return nil, err
- }
- res = append(res, v)
- }
- return res, nil
- }
- if len(roleLevels) == 0 {
- for _, groupID := range groupIDs {
- groupMembers, err := g.cache.GetGroupMembersInfo(ctx, groupID, userIDs)
- if err != nil {
- return nil, err
- }
- totalGroupMembers = append(totalGroupMembers, groupMembers...)
- }
- return totalGroupMembers, nil
- }
- return g.groupMemberDB.Find(ctx, groupIDs, userIDs, roleLevels)
+func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) {
+ return g.groupRequestDB.PageGroup(ctx, groupIDs, pagination)
}
-func (g *groupDatabase) PageGetJoinGroup(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
+func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
groupIDs, err := g.cache.GetJoinedGroupIDs(ctx, userID)
if err != nil {
return 0, nil, err
}
- for _, groupID := range utils.Paginate(groupIDs, int(pageNumber), int(showNumber)) {
+ for _, groupID := range utils.Paginate(groupIDs, int(pagination.GetPageNumber()), int(pagination.GetShowNumber())) {
groupMembers, err := g.cache.GetGroupMembersInfo(ctx, groupID, []string{userID})
if err != nil {
return 0, nil, err
}
totalGroupMembers = append(totalGroupMembers, groupMembers...)
}
- return uint32(len(groupIDs)), totalGroupMembers, nil
+ return int64(len(groupIDs)), totalGroupMembers, nil
}
-func (g *groupDatabase) PageGetGroupMember(
- ctx context.Context,
- groupID string,
- pageNumber, showNumber int32,
-) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
+func (g *groupDatabase) PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
groupMemberIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID)
if err != nil {
return 0, nil, err
}
- pageIDs := utils.Paginate(groupMemberIDs, int(pageNumber), int(showNumber))
+ pageIDs := utils.Paginate(groupMemberIDs, int(pagination.GetPageNumber()), int(pagination.GetShowNumber()))
if len(pageIDs) == 0 {
- return uint32(len(groupMemberIDs)), nil, nil
+ return int64(len(groupMemberIDs)), nil, nil
}
members, err := g.cache.GetGroupMembersInfo(ctx, groupID, pageIDs)
if err != nil {
return 0, nil, err
}
- return uint32(len(groupMemberIDs)), members, nil
+ return int64(len(groupMemberIDs)), members, nil
}
-func (g *groupDatabase) SearchGroupMember(
- ctx context.Context,
- keyword string,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupMemberModel, error) {
- return g.groupMemberDB.SearchMember(ctx, keyword, groupIDs, userIDs, roleLevels, pageNumber, showNumber)
+func (g *groupDatabase) SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*relationtb.GroupMemberModel, error) {
+ return g.groupMemberDB.SearchMember(ctx, keyword, groupID, pagination)
}
-func (g *groupDatabase) HandlerGroupRequest(
- ctx context.Context,
- groupID string,
- userID string,
- handledMsg string,
- handleResult int32,
- member *relationtb.GroupMemberModel,
-) 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 {
+func (g *groupDatabase) HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error {
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ if err := g.groupRequestDB.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 {
+ if err := g.groupMemberDB.Create(ctx, []*relationtb.GroupMemberModel{member}); err != nil {
return err
}
- if err := g.cache.NewCache().DelGroupMembersHash(groupID).DelGroupMembersInfo(groupID, member.UserID).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelJoinedGroupID(member.UserID).ExecDel(ctx); err != nil {
+ c := g.cache.DelGroupMembersHash(groupID).
+ DelGroupMembersInfo(groupID, member.UserID).
+ DelGroupMemberIDs(groupID).
+ DelGroupsMemberNum(groupID).
+ DelJoinedGroupID(member.UserID).
+ DelGroupRoleLevel(groupID, []int32{member.RoleLevel})
+ if err := c.ExecDel(ctx); err != nil {
return err
}
}
@@ -391,13 +302,11 @@ func (g *groupDatabase) DeleteGroupMember(ctx context.Context, groupID string, u
DelGroupsMemberNum(groupID).
DelJoinedGroupID(userIDs...).
DelGroupMembersInfo(groupID, userIDs...).
+ DelGroupAllRoleLevel(groupID).
ExecDel(ctx)
}
-func (g *groupDatabase) MapGroupMemberUserID(
- ctx context.Context,
- groupIDs []string,
-) (map[string]*relationtb.GroupSimpleUserID, error) {
+func (g *groupDatabase) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) {
return g.cache.GetGroupMemberHashMap(ctx, groupIDs)
}
@@ -414,62 +323,54 @@ func (g *groupDatabase) MapGroupMemberNum(ctx context.Context, groupIDs []string
}
func (g *groupDatabase) TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error {
- return g.tx.Transaction(func(tx any) error {
- rowsAffected, err := g.groupMemberDB.NewTx(tx).UpdateRoleLevel(ctx, groupID, oldOwnerUserID, roleLevel)
- if err != nil {
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ if err := g.groupMemberDB.UpdateRoleLevel(ctx, groupID, oldOwnerUserID, roleLevel); err != nil {
return err
}
- if rowsAffected != 1 {
- return utils.Wrap(fmt.Errorf("oldOwnerUserID %s rowsAffected = %d", oldOwnerUserID, rowsAffected), "")
- }
- rowsAffected, err = g.groupMemberDB.NewTx(tx).UpdateRoleLevel(ctx, groupID, newOwnerUserID, constant.GroupOwner)
- if err != nil {
+ if err := g.groupMemberDB.UpdateRoleLevel(ctx, groupID, newOwnerUserID, constant.GroupOwner); err != nil {
return err
}
- if rowsAffected != 1 {
- return utils.Wrap(fmt.Errorf("newOwnerUserID %s rowsAffected = %d", newOwnerUserID, rowsAffected), "")
- }
- return g.cache.DelGroupMembersInfo(groupID, oldOwnerUserID, newOwnerUserID).DelGroupMembersHash(groupID).ExecDel(ctx)
+ return g.cache.DelGroupMembersInfo(groupID, oldOwnerUserID, newOwnerUserID).
+ DelGroupAllRoleLevel(groupID).
+ DelGroupMembersHash(groupID).ExecDel(ctx)
})
}
-func (g *groupDatabase) UpdateGroupMember(
- ctx context.Context,
- groupID string,
- userID string,
- data map[string]any,
-) error {
+func (g *groupDatabase) UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error {
if err := g.groupMemberDB.Update(ctx, groupID, userID, data); err != nil {
return err
}
- return g.cache.DelGroupMembersInfo(groupID, userID).ExecDel(ctx)
+ c := g.cache.DelGroupMembersInfo(groupID, userID)
+ if g.groupMemberDB.IsUpdateRoleLevel(data) {
+ c = c.DelGroupAllRoleLevel(groupID)
+ }
+ return c.ExecDel(ctx)
}
func (g *groupDatabase) UpdateGroupMembers(ctx context.Context, data []*relationtb.BatchUpdateGroupMember) error {
- cache := g.cache.NewCache()
- if err := g.tx.Transaction(func(tx any) error {
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ c := g.cache.NewCache()
for _, item := range data {
- if err := g.groupMemberDB.NewTx(tx).Update(ctx, item.GroupID, item.UserID, item.Map); err != nil {
+ if err := g.groupMemberDB.Update(ctx, item.GroupID, item.UserID, item.Map); err != nil {
return err
}
- cache = cache.DelGroupMembersInfo(item.GroupID, item.UserID)
+ if g.groupMemberDB.IsUpdateRoleLevel(item.Map) {
+ c = c.DelGroupAllRoleLevel(item.GroupID)
+ }
+ c = c.DelGroupMembersInfo(item.GroupID, item.UserID).DelGroupMembersHash(item.GroupID)
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return c.ExecDel(ctx, true)
+ })
}
func (g *groupDatabase) CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error {
- return g.tx.Transaction(func(tx any) error {
- db := g.groupRequestDB.NewTx(tx)
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
for _, request := range requests {
- if err := db.Delete(ctx, request.GroupID, request.UserID); err != nil {
+ if err := g.groupRequestDB.Delete(ctx, request.GroupID, request.UserID); err != nil {
return err
}
}
- return db.Create(ctx, requests)
+ return g.groupRequestDB.Create(ctx, requests)
})
}
@@ -481,65 +382,8 @@ func (g *groupDatabase) TakeGroupRequest(
return g.groupRequestDB.Take(ctx, groupID, userID)
}
-func (g *groupDatabase) PageGroupRequestUser(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupRequestModel, error) {
- return g.groupRequestDB.Page(ctx, userID, pageNumber, showNumber)
-}
-
-func (g *groupDatabase) FindSuperGroup(
- ctx context.Context,
- groupIDs []string,
-) (models []*unrelationtb.SuperGroupModel, err error) {
- return g.cache.GetSuperGroupMemberIDs(ctx, groupIDs...)
-}
-
-func (g *groupDatabase) FindJoinSuperGroup(ctx context.Context, userID string) ([]string, error) {
- return g.cache.GetJoinedSuperGroupIDs(ctx, userID)
-}
-
-func (g *groupDatabase) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error {
- if err := g.mongoDB.CreateSuperGroup(ctx, groupID, initMemberIDs); err != nil {
- return err
- }
- return g.cache.DelSuperGroupMemberIDs(groupID).DelJoinedSuperGroupIDs(initMemberIDs...).ExecDel(ctx)
-}
-
-func (g *groupDatabase) DeleteSuperGroup(ctx context.Context, groupID string) error {
- cache := g.cache.NewCache()
- if err := g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
- if err := g.mongoDB.DeleteSuperGroup(ctx, groupID); err != nil {
- return err
- }
- models, err := g.cache.GetSuperGroupMemberIDs(ctx, groupID)
- if err != nil {
- return err
- }
- cache = cache.DelSuperGroupMemberIDs(groupID)
- if len(models) > 0 {
- cache = cache.DelJoinedSuperGroupIDs(models[0].MemberIDs...)
- }
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
-}
-
-func (g *groupDatabase) DeleteSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error {
- if err := g.mongoDB.RemoverUserFromSuperGroup(ctx, groupID, userIDs); err != nil {
- return err
- }
- return g.cache.DelSuperGroupMemberIDs(groupID).DelJoinedSuperGroupIDs(userIDs...).ExecDel(ctx)
-}
-
-func (g *groupDatabase) CreateSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error {
- if err := g.mongoDB.AddUserToSuperGroup(ctx, groupID, userIDs); err != nil {
- return err
- }
- return g.cache.DelSuperGroupMemberIDs(groupID).DelJoinedSuperGroupIDs(userIDs...).ExecDel(ctx)
+func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) {
+ return g.groupRequestDB.Page(ctx, userID, pagination)
}
func (g *groupDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
@@ -550,14 +394,10 @@ func (g *groupDatabase) CountRangeEverydayTotal(ctx context.Context, start time.
return g.groupDB.CountRangeEverydayTotal(ctx, start, end)
}
-func (g *groupDatabase) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*relationtb.GroupRequestModel, error) {
+func (g *groupDatabase) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupRequestModel, error) {
return g.groupRequestDB.FindGroupRequests(ctx, groupID, userIDs)
}
-func (g *groupDatabase) FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) {
- return g.groupDB.FindNotDismissedGroup(ctx, groupIDs)
-}
-
func (g *groupDatabase) DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error {
if len(groupIDs) == 0 {
return nil
@@ -566,6 +406,5 @@ func (g *groupDatabase) DeleteGroupMemberHash(ctx context.Context, groupIDs []st
for _, groupID := range groupIDs {
c = c.DelGroupMembersHash(groupID)
}
-
return c.ExecDel(ctx)
}
diff --git a/pkg/common/db/controller/msg.go b/pkg/common/db/controller/msg.go
index cba0a6bbd..fb0a9c702 100644
--- a/pkg/common/db/controller/msg.go
+++ b/pkg/common/db/controller/msg.go
@@ -357,9 +357,7 @@ func (db *commonMsgDatabase) DelUserDeleteMsgsList(ctx context.Context, conversa
}
func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNew bool, err error) {
- cancelCtx, cancel := context.WithTimeout(ctx, 1*time.Minute)
- defer cancel()
- currentMaxSeq, err := db.cache.GetMaxSeq(cancelCtx, conversationID)
+ currentMaxSeq, err := db.cache.GetMaxSeq(ctx, conversationID)
if err != nil && errs.Unwrap(err) != redis.Nil {
log.ZError(ctx, "db.cache.GetMaxSeq", err)
return 0, false, err
@@ -386,21 +384,19 @@ func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversa
prommetrics.MsgInsertRedisFailedCounter.Add(float64(failedNum))
log.ZError(ctx, "setMessageToCache error", err, "len", len(msgs), "conversationID", conversationID)
} else {
- prommetrics.MsgInsertRedisSuccessCounter.Add(float64(len(msgs)))
+ prommetrics.MsgInsertRedisSuccessCounter.Inc()
}
- cancelCtx, cancel = context.WithTimeout(ctx, 1*time.Minute)
- defer cancel()
- err = db.cache.SetMaxSeq(cancelCtx, conversationID, currentMaxSeq)
+ err = db.cache.SetMaxSeq(ctx, conversationID, currentMaxSeq)
if err != nil {
log.ZError(ctx, "db.cache.SetMaxSeq error", err, "conversationID", conversationID)
prommetrics.SeqSetFailedCounter.Inc()
}
err2 := db.cache.SetHasReadSeqs(ctx, conversationID, userSeqMap)
- if err2 != nil {
+ if err != nil {
log.ZError(ctx, "SetHasReadSeqs error", err2, "userSeqMap", userSeqMap, "conversationID", conversationID)
prommetrics.SeqSetFailedCounter.Inc()
}
- return lastMaxSeq, isNew, errs.Wrap(err, "redis SetMaxSeq error")
+ return lastMaxSeq, isNew, utils.Wrap(err, "")
}
func (db *commonMsgDatabase) getMsgBySeqs(ctx context.Context, userID, conversationID string, seqs []int64) (totalMsgs []*sdkws.MsgData, err error) {
@@ -658,26 +654,16 @@ func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID strin
func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) (int64, int64, []*sdkws.MsgData, error) {
userMinSeq, err := db.cache.GetConversationUserMinSeq(ctx, conversationID, userID)
- if err != nil {
- log.ZError(ctx, "cache.GetConversationUserMinSeq error", err)
- if errs.Unwrap(err) != redis.Nil {
- return 0, 0, nil, err
- }
+ if err != nil && errs.Unwrap(err) != redis.Nil {
+ return 0, 0, nil, err
}
minSeq, err := db.cache.GetMinSeq(ctx, conversationID)
- if err != nil {
- log.ZError(ctx, "cache.GetMinSeq error", err)
- if errs.Unwrap(err) != redis.Nil {
- return 0, 0, nil, err
- }
+ if err != nil && errs.Unwrap(err) != redis.Nil {
+ return 0, 0, nil, err
}
maxSeq, err := db.cache.GetMaxSeq(ctx, conversationID)
- if err != nil {
- log.ZError(ctx, "cache.GetMaxSeq error", err)
- if errs.Unwrap(err) != redis.Nil {
- return 0, 0, nil, err
- }
-
+ if err != nil && errs.Unwrap(err) != redis.Nil {
+ return 0, 0, nil, err
}
if userMinSeq < minSeq {
minSeq = userMinSeq
@@ -690,16 +676,34 @@ func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, co
}
successMsgs, failedSeqs, err := db.cache.GetMessagesBySeq(ctx, conversationID, newSeqs)
if err != nil {
- log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID)
+ if err != redis.Nil {
+ log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID)
+ }
}
- log.ZInfo(ctx, "db.cache.GetMessagesBySeq", "userID", userID, "conversationID", conversationID, "seqs", seqs, "successMsgs",
- len(successMsgs), "failedSeqs", failedSeqs, "conversationID", conversationID)
+ log.ZInfo(
+ ctx,
+ "db.cache.GetMessagesBySeq",
+ "userID",
+ userID,
+ "conversationID",
+ conversationID,
+ "seqs",
+ seqs,
+ "successMsgs",
+ len(successMsgs),
+ "failedSeqs",
+ failedSeqs,
+ "conversationID",
+ conversationID,
+ )
if len(failedSeqs) > 0 {
mongoMsgs, err := db.getMsgBySeqs(ctx, userID, conversationID, failedSeqs)
if err != nil {
+
return 0, 0, nil, err
}
+
successMsgs = append(successMsgs, mongoMsgs...)
}
return minSeq, maxSeq, successMsgs, nil
diff --git a/pkg/common/db/controller/msg_test.go b/pkg/common/db/controller/msg_test.go
index ba5aecd25..cfb969b3e 100644
--- a/pkg/common/db/controller/msg_test.go
+++ b/pkg/common/db/controller/msg_test.go
@@ -235,7 +235,7 @@ func Test_FindBySeq(t *testing.T) {
func TestName(t *testing.T) {
db := GetDB()
var seqs []int64
- for i := int64(1); i <= 4; i++ {
+ for i := int64(1); i <= 50; i++ {
seqs = append(seqs, i)
}
msgs, err := db.getMsgBySeqsRange(context.Background(), "4931176757", "si_3866692501_4931176757", seqs, seqs[0], seqs[len(seqs)-1])
diff --git a/pkg/common/db/controller/s3.go b/pkg/common/db/controller/s3.go
index ddbd5d27f..6916a7d30 100644
--- a/pkg/common/db/controller/s3.go
+++ b/pkg/common/db/controller/s3.go
@@ -72,14 +72,15 @@ func (s *s3Database) CompleteMultipartUpload(ctx context.Context, uploadID strin
}
func (s *s3Database) SetObject(ctx context.Context, info *relation.ObjectModel) error {
+ info.Engine = s.s3.Engine()
if err := s.db.SetObject(ctx, info); err != nil {
return err
}
- return s.cache.DelObjectName(info.Name).ExecDel(ctx)
+ return s.cache.DelObjectName(info.Engine, info.Name).ExecDel(ctx)
}
func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error) {
- obj, err := s.cache.GetName(ctx, name)
+ obj, err := s.cache.GetName(ctx, s.s3.Engine(), name)
if err != nil {
return time.Time{}, "", err
}
diff --git a/pkg/common/db/controller/third.go b/pkg/common/db/controller/third.go
index 971719b1f..fb5b0ccbe 100644
--- a/pkg/common/db/controller/third.go
+++ b/pkg/common/db/controller/third.go
@@ -18,10 +18,9 @@ import (
"context"
"time"
- "gorm.io/gorm"
+ "github.com/OpenIMSDK/tools/pagination"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
- dbimpl "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
@@ -29,22 +28,15 @@ type ThirdDatabase interface {
FcmUpdateToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) error
SetAppBadge(ctx context.Context, userID string, value int) error
// about log for debug
- UploadLogs(ctx context.Context, logs []*relation.Log) error
+ UploadLogs(ctx context.Context, logs []*relation.LogModel) error
DeleteLogs(ctx context.Context, logID []string, userID string) error
- SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relation.Log, error)
- GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.Log, error)
- FindUsers(ctx context.Context, userIDs []string) ([]*relation.UserModel, error)
+ SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error)
+ GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.LogModel, error)
}
type thirdDatabase struct {
- cache cache.MsgModel
- logdb relation.LogInterface
- userdb relation.UserModelInterface
-}
-
-// FindUsers implements ThirdDatabase.
-func (t *thirdDatabase) FindUsers(ctx context.Context, userIDs []string) ([]*relation.UserModel, error) {
- return t.userdb.Find(ctx, userIDs)
+ cache cache.MsgModel
+ logdb relation.LogInterface
}
// DeleteLogs implements ThirdDatabase.
@@ -53,22 +45,22 @@ func (t *thirdDatabase) DeleteLogs(ctx context.Context, logID []string, userID s
}
// GetLogs implements ThirdDatabase.
-func (t *thirdDatabase) GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.Log, error) {
+func (t *thirdDatabase) GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.LogModel, error) {
return t.logdb.Get(ctx, LogIDs, userID)
}
// SearchLogs implements ThirdDatabase.
-func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relation.Log, error) {
- return t.logdb.Search(ctx, keyword, start, end, pageNumber, showNumber)
+func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error) {
+ return t.logdb.Search(ctx, keyword, start, end, pagination)
}
// UploadLogs implements ThirdDatabase.
-func (t *thirdDatabase) UploadLogs(ctx context.Context, logs []*relation.Log) error {
+func (t *thirdDatabase) UploadLogs(ctx context.Context, logs []*relation.LogModel) error {
return t.logdb.Create(ctx, logs)
}
-func NewThirdDatabase(cache cache.MsgModel, db *gorm.DB) ThirdDatabase {
- return &thirdDatabase{cache: cache, logdb: dbimpl.NewLogGorm(db), userdb: dbimpl.NewUserGorm(db)}
+func NewThirdDatabase(cache cache.MsgModel, logdb relation.LogInterface) ThirdDatabase {
+ return &thirdDatabase{cache: cache, logdb: logdb}
}
func (t *thirdDatabase) FcmUpdateToken(
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index 9c6fdc5c4..ca703b729 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -18,16 +18,19 @@ import (
"context"
"time"
+ "github.com/OpenIMSDK/tools/pagination"
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+
"github.com/OpenIMSDK/protocol/user"
unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
"github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
type UserDatabase interface {
@@ -38,15 +41,15 @@ type UserDatabase interface {
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db
Create(ctx context.Context, users []*relation.UserModel) (err error)
// Update update (non-zero value) external guarantee userID exists
- Update(ctx context.Context, user *relation.UserModel) (err error)
+ //Update(ctx context.Context, user *relation.UserModel) (err error)
// UpdateByMap update (zero value) external guarantee userID exists
- UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error)
+ UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
// Page If not found, no error is returned
- Page(ctx context.Context, pageNumber, showNumber int32) (users []*relation.UserModel, count int64, err error)
+ Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
// IsExist true as long as one exists
IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
// GetAllUserID Get all user IDs
- GetAllUserID(ctx context.Context, pageNumber, showNumber int32) ([]string, error)
+ GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error)
// InitOnce Inside the function, first query whether it exists in the db, if it exists, do nothing; if it does not exist, insert it
InitOnce(ctx context.Context, users []*relation.UserModel) (err error)
// CountTotal Get the total number of users
@@ -68,28 +71,40 @@ type UserDatabase interface {
}
type userDatabase struct {
+ tx tx.CtxTx
userDB relation.UserModelInterface
cache cache.UserCache
- tx tx.Tx
mongoDB unrelationtb.UserModelInterface
}
-func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache, tx tx.Tx, mongoDB unrelationtb.UserModelInterface) UserDatabase {
+func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache, tx tx.CtxTx, mongoDB unrelationtb.UserModelInterface) UserDatabase {
return &userDatabase{userDB: userDB, cache: cache, tx: tx, mongoDB: mongoDB}
}
-func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel) (err error) {
+func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel) error {
+ // Extract user IDs from the given user models.
userIDs := utils.Slice(users, func(e *relation.UserModel) string {
return e.UserID
})
- result, err := u.userDB.Find(ctx, userIDs)
+
+ // Find existing users in the database.
+ existingUsers, err := u.userDB.Find(ctx, userIDs)
if err != nil {
return err
}
- miss := utils.SliceAnySub(users, result, func(e *relation.UserModel) string { return e.UserID })
- if len(miss) > 0 {
- _ = u.userDB.Create(ctx, miss)
+
+ // Determine which users are missing from the database.
+ missingUsers := utils.SliceAnySub(users, existingUsers, func(e *relation.UserModel) string {
+ return e.UserID
+ })
+
+ // Create records for missing users.
+ if len(missingUsers) > 0 {
+ if err := u.userDB.Create(ctx, missingUsers); err != nil {
+ return err
+ }
}
+
return nil
}
@@ -107,50 +122,42 @@ func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (use
// Find Get the information of the specified user. If the userID is not found, no error will be returned.
func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
- users, err = u.cache.GetUsersInfo(ctx, userIDs)
- return
+ return u.cache.GetUsersInfo(ctx, userIDs)
}
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db.
func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) {
- if err := u.tx.Transaction(func(tx any) error {
- err = u.userDB.Create(ctx, users)
- if err != nil {
+ return u.tx.Transaction(ctx, func(ctx context.Context) error {
+ if err = u.userDB.Create(ctx, users); err != nil {
return err
}
- return nil
- }); err != nil {
- return err
- }
- var userIDs []string
- for _, user := range users {
- userIDs = append(userIDs, user.UserID)
- }
- return u.cache.DelUsersInfo(userIDs...).ExecDel(ctx)
+ return u.cache.DelUsersInfo(utils.Slice(users, func(e *relation.UserModel) string {
+ return e.UserID
+ })...).ExecDel(ctx)
+ })
}
-// Update (non-zero value) externally guarantees that userID exists.
-func (u *userDatabase) Update(ctx context.Context, user *relation.UserModel) (err error) {
- if err := u.userDB.Update(ctx, user); err != nil {
- return err
- }
- return u.cache.DelUsersInfo(user.UserID).ExecDel(ctx)
-}
+//// Update (non-zero value) externally guarantees that userID exists.
+//func (u *userDatabase) Update(ctx context.Context, user *relation.UserModel) (err error) {
+// if err := u.userDB.Update(ctx, user); err != nil {
+// return err
+// }
+// return u.cache.DelUsersInfo(user.UserID).ExecDel(ctx)
+//}
// UpdateByMap update (zero value) externally guarantees that userID exists.
-func (u *userDatabase) UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error) {
- if err := u.userDB.UpdateByMap(ctx, userID, args); err != nil {
- return err
- }
- return u.cache.DelUsersInfo(userID).ExecDel(ctx)
+func (u *userDatabase) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error) {
+ return u.tx.Transaction(ctx, func(ctx context.Context) error {
+ if err := u.userDB.UpdateByMap(ctx, userID, args); err != nil {
+ return err
+ }
+ return u.cache.DelUsersInfo(userID).ExecDel(ctx)
+ })
}
// Page Gets, returns no error if not found.
-func (u *userDatabase) Page(
- ctx context.Context,
- pageNumber, showNumber int32,
-) (users []*relation.UserModel, count int64, err error) {
- return u.userDB.Page(ctx, pageNumber, showNumber)
+func (u *userDatabase) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return u.userDB.Page(ctx, pagination)
}
// IsExist Does userIDs exist? As long as there is one, it will be true.
@@ -166,8 +173,8 @@ func (u *userDatabase) IsExist(ctx context.Context, userIDs []string) (exist boo
}
// GetAllUserID Get all user IDs.
-func (u *userDatabase) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) {
- return u.userDB.GetAllUserID(ctx, pageNumber, showNumber)
+func (u *userDatabase) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (total int64, userIDs []string, err error) {
+ return u.userDB.GetAllUserID(ctx, pagination)
}
// CountTotal Get the total number of users.
diff --git a/pkg/common/db/mgo/black.go b/pkg/common/db/mgo/black.go
new file mode 100644
index 000000000..6235639aa
--- /dev/null
+++ b/pkg/common/db/mgo/black.go
@@ -0,0 +1,91 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewBlackMongo(db *mongo.Database) (relation.BlackModelInterface, error) {
+ coll := db.Collection("black")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "owner_user_id", Value: 1},
+ {Key: "block_user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &BlackMgo{coll: coll}, nil
+}
+
+type BlackMgo struct {
+ coll *mongo.Collection
+}
+
+func (b *BlackMgo) blackFilter(ownerUserID, blockUserID string) bson.M {
+ return bson.M{
+ "owner_user_id": ownerUserID,
+ "block_user_id": blockUserID,
+ }
+}
+
+func (b *BlackMgo) blacksFilter(blacks []*relation.BlackModel) bson.M {
+ if len(blacks) == 0 {
+ return nil
+ }
+ or := make(bson.A, 0, len(blacks))
+ for _, black := range blacks {
+ or = append(or, b.blackFilter(black.OwnerUserID, black.BlockUserID))
+ }
+ return bson.M{"$or": or}
+}
+
+func (b *BlackMgo) Create(ctx context.Context, blacks []*relation.BlackModel) (err error) {
+ return mgoutil.InsertMany(ctx, b.coll, blacks)
+}
+
+func (b *BlackMgo) Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) {
+ if len(blacks) == 0 {
+ return nil
+ }
+ return mgoutil.DeleteMany(ctx, b.coll, b.blacksFilter(blacks))
+}
+
+func (b *BlackMgo) UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]any) (err error) {
+ if len(args) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, b.coll, b.blackFilter(ownerUserID, blockUserID), bson.M{"$set": args}, false)
+}
+
+func (b *BlackMgo) Find(ctx context.Context, blacks []*relation.BlackModel) (blackList []*relation.BlackModel, err error) {
+ return mgoutil.Find[*relation.BlackModel](ctx, b.coll, b.blacksFilter(blacks))
+}
+
+func (b *BlackMgo) Take(ctx context.Context, ownerUserID, blockUserID string) (black *relation.BlackModel, err error) {
+ return mgoutil.FindOne[*relation.BlackModel](ctx, b.coll, b.blackFilter(ownerUserID, blockUserID))
+}
+
+func (b *BlackMgo) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) {
+ return mgoutil.FindPage[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID}, pagination)
+}
+
+func (b *BlackMgo) FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) {
+ if len(userIDs) == 0 {
+ return mgoutil.Find[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID})
+ }
+ return mgoutil.Find[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID, "block_user_id": bson.M{"$in": userIDs}})
+}
+
+func (b *BlackMgo) FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error) {
+ return mgoutil.Find[string](ctx, b.coll, bson.M{"owner_user_id": ownerUserID}, options.Find().SetProjection(bson.M{"_id": 0, "block_user_id": 1}))
+}
diff --git a/pkg/common/db/mgo/conversation.go b/pkg/common/db/mgo/conversation.go
new file mode 100644
index 000000000..72d04ebb3
--- /dev/null
+++ b/pkg/common/db/mgo/conversation.go
@@ -0,0 +1,150 @@
+package mgo
+
+import (
+ "context"
+ "time"
+
+ "github.com/OpenIMSDK/protocol/constant"
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewConversationMongo(db *mongo.Database) (*ConversationMgo, error) {
+ coll := db.Collection("conversation")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "owner_user_id", Value: 1},
+ {Key: "conversation_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &ConversationMgo{coll: coll}, nil
+}
+
+type ConversationMgo struct {
+ coll *mongo.Collection
+}
+
+func (c *ConversationMgo) Create(ctx context.Context, conversations []*relation.ConversationModel) (err error) {
+ return mgoutil.InsertMany(ctx, c.coll, conversations)
+}
+
+func (c *ConversationMgo) Delete(ctx context.Context, groupIDs []string) (err error) {
+ return mgoutil.DeleteMany(ctx, c.coll, bson.M{"group_id": bson.M{"$in": groupIDs}})
+}
+
+func (c *ConversationMgo) UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]any) (rows int64, err error) {
+ res, err := mgoutil.UpdateMany(ctx, c.coll, bson.M{"owner_user_id": bson.M{"$in": userIDs}, "conversation_id": conversationID}, bson.M{"$set": args})
+ if err != nil {
+ return 0, err
+ }
+ return res.ModifiedCount, nil
+}
+
+func (c *ConversationMgo) Update(ctx context.Context, conversation *relation.ConversationModel) (err error) {
+ return mgoutil.UpdateOne(ctx, c.coll, bson.M{"owner_user_id": conversation.OwnerUserID, "conversation_id": conversation.ConversationID}, bson.M{"$set": conversation}, true)
+}
+
+func (c *ConversationMgo) Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*relation.ConversationModel, err error) {
+ return mgoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": ownerUserID, "conversation_id": bson.M{"$in": conversationIDs}})
+}
+
+func (c *ConversationMgo) FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error) {
+ return mgoutil.Find[string](
+ ctx,
+ c.coll,
+ bson.M{"owner_user_id": bson.M{"$in": userIDs}, "conversation_id": bson.M{"$in": conversationIDs}},
+ options.Find().SetProjection(bson.M{"_id": 0, "owner_user_id": 1}),
+ )
+}
+
+func (c *ConversationMgo) FindUserIDAllConversationID(ctx context.Context, userID string) ([]string, error) {
+ return mgoutil.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
+}
+
+func (c *ConversationMgo) Take(ctx context.Context, userID, conversationID string) (conversation *relation.ConversationModel, err error) {
+ return mgoutil.FindOne[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": conversationID})
+}
+
+func (c *ConversationMgo) FindConversationID(ctx context.Context, userID string, conversationIDs []string) (existConversationID []string, err error) {
+ return mgoutil.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": bson.M{"$in": conversationIDs}}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
+}
+
+func (c *ConversationMgo) FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*relation.ConversationModel, err error) {
+ return mgoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": userID})
+}
+
+func (c *ConversationMgo) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) {
+ return mgoutil.Find[string](ctx, c.coll, bson.M{"group_id": groupID, "recv_msg_opt": constant.ReceiveNotNotifyMessage}, options.Find().SetProjection(bson.M{"_id": 0, "owner_user_id": 1}))
+}
+
+func (c *ConversationMgo) GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error) {
+ return mgoutil.FindOne[int](ctx, c.coll, bson.M{"owner_user_id": ownerUserID, "conversation_id": conversationID}, options.FindOne().SetProjection(bson.M{"recv_msg_opt": 1}))
+}
+
+func (c *ConversationMgo) GetAllConversationIDs(ctx context.Context) ([]string, error) {
+ return mgoutil.Aggregate[string](ctx, c.coll, []bson.M{
+ {"$group": bson.M{"_id": "$conversation_id"}},
+ {"$project": bson.M{"_id": 0, "conversation_id": "$_id"}},
+ })
+}
+
+func (c *ConversationMgo) GetAllConversationIDsNumber(ctx context.Context) (int64, error) {
+ counts, err := mgoutil.Aggregate[int64](ctx, c.coll, []bson.M{
+ {"$group": bson.M{"_id": "$conversation_id"}},
+ {"$project": bson.M{"_id": 0, "conversation_id": "$_id"}},
+ })
+ if err != nil {
+ return 0, err
+ }
+ if len(counts) == 0 {
+ return 0, nil
+ }
+ return counts[0], nil
+}
+
+func (c *ConversationMgo) PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error) {
+ return mgoutil.FindPageOnly[string](ctx, c.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"conversation_id": 1}))
+}
+
+func (c *ConversationMgo) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relation.ConversationModel, error) {
+ return mgoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"conversation_id": bson.M{"$in": conversationIDs}})
+}
+
+func (c *ConversationMgo) GetConversationIDsNeedDestruct(ctx context.Context) ([]*relation.ConversationModel, error) {
+ //"is_msg_destruct = 1 && msg_destruct_time != 0 && (UNIX_TIMESTAMP(NOW()) > (msg_destruct_time + UNIX_TIMESTAMP(latest_msg_destruct_time)) || latest_msg_destruct_time is NULL)"
+ return mgoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{
+ "is_msg_destruct": 1,
+ "msg_destruct_time": bson.M{"$ne": 0},
+ "$or": []bson.M{
+ {
+ "$expr": bson.M{
+ "$gt": []any{
+ time.Now(),
+ bson.M{"$add": []any{"$msg_destruct_time", "$latest_msg_destruct_time"}},
+ },
+ },
+ },
+ {
+ "latest_msg_destruct_time": nil,
+ },
+ },
+ })
+}
+
+func (c *ConversationMgo) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) {
+ return mgoutil.Find[string](
+ ctx,
+ c.coll,
+ bson.M{"conversation_id": conversationID, "recv_msg_opt": bson.M{"$ne": constant.ReceiveMessage}},
+ options.Find().SetProjection(bson.M{"_id": 0, "owner_user_id": 1}),
+ )
+}
diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go
new file mode 100644
index 000000000..aa9cb0301
--- /dev/null
+++ b/pkg/common/db/mgo/friend.go
@@ -0,0 +1,131 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+// FriendMgo implements FriendModelInterface using MongoDB as the storage backend.
+type FriendMgo struct {
+ coll *mongo.Collection
+}
+
+// NewFriendMongo creates a new instance of FriendMgo with the provided MongoDB database.
+func NewFriendMongo(db *mongo.Database) (relation.FriendModelInterface, error) {
+ coll := db.Collection("friend")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "owner_user_id", Value: 1},
+ {Key: "friend_user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &FriendMgo{coll: coll}, nil
+}
+
+// Create inserts multiple friend records.
+func (f *FriendMgo) Create(ctx context.Context, friends []*relation.FriendModel) error {
+ return mgoutil.InsertMany(ctx, f.coll, friends)
+}
+
+// Delete removes specified friends of the owner user.
+func (f *FriendMgo) Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) error {
+ filter := bson.M{
+ "owner_user_id": ownerUserID,
+ "friend_user_id": bson.M{"$in": friendUserIDs},
+ }
+ return mgoutil.DeleteOne(ctx, f.coll, filter)
+}
+
+// UpdateByMap updates specific fields of a friend document using a map.
+func (f *FriendMgo) UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) error {
+ if len(args) == 0 {
+ return nil
+ }
+ filter := bson.M{
+ "owner_user_id": ownerUserID,
+ "friend_user_id": friendUserID,
+ }
+ return mgoutil.UpdateOne(ctx, f.coll, filter, bson.M{"$set": args}, true)
+}
+
+// Update modifies multiple friend documents.
+// func (f *FriendMgo) Update(ctx context.Context, friends []*relation.FriendModel) error {
+// filter := bson.M{
+// "owner_user_id": ownerUserID,
+// "friend_user_id": friendUserID,
+// }
+// return mgotool.UpdateMany(ctx, f.coll, filter, friends)
+// }
+
+// UpdateRemark updates the remark for a specific friend.
+func (f *FriendMgo) UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) error {
+ return f.UpdateByMap(ctx, ownerUserID, friendUserID, map[string]any{"remark": remark})
+}
+
+// Take retrieves a single friend document. Returns an error if not found.
+func (f *FriendMgo) Take(ctx context.Context, ownerUserID, friendUserID string) (*relation.FriendModel, error) {
+ filter := bson.M{
+ "owner_user_id": ownerUserID,
+ "friend_user_id": friendUserID,
+ }
+ return mgoutil.FindOne[*relation.FriendModel](ctx, f.coll, filter)
+}
+
+// FindUserState finds the friendship status between two users.
+func (f *FriendMgo) FindUserState(ctx context.Context, userID1, userID2 string) ([]*relation.FriendModel, error) {
+ filter := bson.M{
+ "$or": []bson.M{
+ {"owner_user_id": userID1, "friend_user_id": userID2},
+ {"owner_user_id": userID2, "friend_user_id": userID1},
+ },
+ }
+ return mgoutil.Find[*relation.FriendModel](ctx, f.coll, filter)
+}
+
+// FindFriends retrieves a list of friends for a given owner. Missing friends do not cause an error.
+func (f *FriendMgo) FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) ([]*relation.FriendModel, error) {
+ filter := bson.M{
+ "owner_user_id": ownerUserID,
+ "friend_user_id": bson.M{"$in": friendUserIDs},
+ }
+ return mgoutil.Find[*relation.FriendModel](ctx, f.coll, filter)
+}
+
+// FindReversalFriends finds users who have added the specified user as a friend.
+func (f *FriendMgo) FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) ([]*relation.FriendModel, error) {
+ filter := bson.M{
+ "owner_user_id": bson.M{"$in": ownerUserIDs},
+ "friend_user_id": friendUserID,
+ }
+ return mgoutil.Find[*relation.FriendModel](ctx, f.coll, filter)
+}
+
+// FindOwnerFriends retrieves a paginated list of friends for a given owner.
+func (f *FriendMgo) FindOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (int64, []*relation.FriendModel, error) {
+ filter := bson.M{"owner_user_id": ownerUserID}
+ return mgoutil.FindPage[*relation.FriendModel](ctx, f.coll, filter, pagination)
+}
+
+// FindInWhoseFriends finds users who have added the specified user as a friend, with pagination.
+func (f *FriendMgo) FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (int64, []*relation.FriendModel, error) {
+ filter := bson.M{"friend_user_id": friendUserID}
+ return mgoutil.FindPage[*relation.FriendModel](ctx, f.coll, filter, pagination)
+}
+
+// FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
+func (f *FriendMgo) FindFriendUserIDs(ctx context.Context, ownerUserID string) ([]string, error) {
+ filter := bson.M{"owner_user_id": ownerUserID}
+ return mgoutil.Find[string](ctx, f.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "friend_user_id": 1}))
+}
diff --git a/pkg/common/db/mgo/friend_request.go b/pkg/common/db/mgo/friend_request.go
new file mode 100644
index 000000000..c1be87ca2
--- /dev/null
+++ b/pkg/common/db/mgo/friend_request.go
@@ -0,0 +1,99 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewFriendRequestMongo(db *mongo.Database) (relation.FriendRequestModelInterface, error) {
+ coll := db.Collection("friend_request")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "from_user_id", Value: 1},
+ {Key: "to_user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &FriendRequestMgo{coll: coll}, nil
+}
+
+type FriendRequestMgo struct {
+ coll *mongo.Collection
+}
+
+func (f *FriendRequestMgo) FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*relation.FriendRequestModel, err error) {
+ return mgoutil.FindPage[*relation.FriendRequestModel](ctx, f.coll, bson.M{"to_user_id": toUserID}, pagination)
+}
+
+func (f *FriendRequestMgo) FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*relation.FriendRequestModel, err error) {
+ return mgoutil.FindPage[*relation.FriendRequestModel](ctx, f.coll, bson.M{"from_user_id": fromUserID}, pagination)
+}
+
+func (f *FriendRequestMgo) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
+ filter := bson.M{"$or": []bson.M{
+ {"from_user_id": fromUserID, "to_user_id": toUserID},
+ {"from_user_id": toUserID, "to_user_id": fromUserID},
+ }}
+ return mgoutil.Find[*relation.FriendRequestModel](ctx, f.coll, filter)
+}
+
+func (f *FriendRequestMgo) Create(ctx context.Context, friendRequests []*relation.FriendRequestModel) error {
+ return mgoutil.InsertMany(ctx, f.coll, friendRequests)
+}
+
+func (f *FriendRequestMgo) Delete(ctx context.Context, fromUserID, toUserID string) (err error) {
+ return mgoutil.DeleteOne(ctx, f.coll, bson.M{"from_user_id": fromUserID, "to_user_id": toUserID})
+}
+
+func (f *FriendRequestMgo) UpdateByMap(ctx context.Context, formUserID, toUserID string, args map[string]any) (err error) {
+ if len(args) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, f.coll, bson.M{"from_user_id": formUserID, "to_user_id": toUserID}, bson.M{"$set": args}, true)
+}
+
+func (f *FriendRequestMgo) Update(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
+ updater := bson.M{}
+ if friendRequest.HandleResult != 0 {
+ updater["handle_result"] = friendRequest.HandleResult
+ }
+ if friendRequest.ReqMsg != "" {
+ updater["req_msg"] = friendRequest.ReqMsg
+ }
+ if friendRequest.HandlerUserID != "" {
+ updater["handler_user_id"] = friendRequest.HandlerUserID
+ }
+ if friendRequest.HandleMsg != "" {
+ updater["handle_msg"] = friendRequest.HandleMsg
+ }
+ if !friendRequest.HandleTime.IsZero() {
+ updater["handle_time"] = friendRequest.HandleTime
+ }
+ if friendRequest.Ex != "" {
+ updater["ex"] = friendRequest.Ex
+ }
+ if len(updater) == 0 {
+ return nil
+ }
+ filter := bson.M{"from_user_id": friendRequest.FromUserID, "to_user_id": friendRequest.ToUserID}
+ return mgoutil.UpdateOne(ctx, f.coll, filter, bson.M{"$set": updater}, true)
+}
+
+func (f *FriendRequestMgo) Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *relation.FriendRequestModel, err error) {
+ return mgoutil.FindOne[*relation.FriendRequestModel](ctx, f.coll, bson.M{"from_user_id": fromUserID, "to_user_id": toUserID})
+}
+
+func (f *FriendRequestMgo) Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *relation.FriendRequestModel, err error) {
+ return f.Find(ctx, fromUserID, toUserID)
+}
diff --git a/pkg/common/db/mgo/group.go b/pkg/common/db/mgo/group.go
new file mode 100644
index 000000000..3553b6b56
--- /dev/null
+++ b/pkg/common/db/mgo/group.go
@@ -0,0 +1,105 @@
+package mgo
+
+import (
+ "context"
+ "time"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewGroupMongo(db *mongo.Database) (relation.GroupModelInterface, error) {
+ coll := db.Collection("group")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "group_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &GroupMgo{coll: coll}, nil
+}
+
+type GroupMgo struct {
+ coll *mongo.Collection
+}
+
+func (g *GroupMgo) Create(ctx context.Context, groups []*relation.GroupModel) (err error) {
+ return mgoutil.InsertMany(ctx, g.coll, groups)
+}
+
+func (g *GroupMgo) UpdateState(ctx context.Context, groupID string, state int32) (err error) {
+ return g.UpdateMap(ctx, groupID, map[string]any{"state": state})
+}
+
+func (g *GroupMgo) UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error) {
+ if len(args) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID}, bson.M{"$set": args}, true)
+}
+
+func (g *GroupMgo) Find(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
+ return mgoutil.Find[*relation.GroupModel](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}})
+}
+
+func (g *GroupMgo) Take(ctx context.Context, groupID string) (group *relation.GroupModel, err error) {
+ return mgoutil.FindOne[*relation.GroupModel](ctx, g.coll, bson.M{"group_id": groupID})
+}
+
+func (g *GroupMgo) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*relation.GroupModel, err error) {
+ return mgoutil.FindPage[*relation.GroupModel](ctx, g.coll, bson.M{"group_name": bson.M{"$regex": keyword}}, pagination)
+}
+
+func (g *GroupMgo) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
+ if before == nil {
+ return mgoutil.Count(ctx, g.coll, bson.M{})
+ }
+ return mgoutil.Count(ctx, g.coll, bson.M{"create_time": bson.M{"$lt": before}})
+}
+
+func (g *GroupMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
+ pipeline := bson.A{
+ bson.M{
+ "$match": bson.M{
+ "create_time": bson.M{
+ "$gte": start,
+ "$lt": end,
+ },
+ },
+ },
+ bson.M{
+ "$group": bson.M{
+ "_id": bson.M{
+ "$dateToString": bson.M{
+ "format": "%Y-%m-%d",
+ "date": "$create_time",
+ },
+ },
+ "count": bson.M{
+ "$sum": 1,
+ },
+ },
+ },
+ }
+ type Item struct {
+ Date string `bson:"_id"`
+ Count int64 `bson:"count"`
+ }
+ items, err := mgoutil.Aggregate[Item](ctx, g.coll, pipeline)
+ if err != nil {
+ return nil, err
+ }
+ res := make(map[string]int64, len(items))
+ for _, item := range items {
+ res[item.Date] = item.Count
+ }
+ return res, nil
+}
diff --git a/pkg/common/db/mgo/group_member.go b/pkg/common/db/mgo/group_member.go
new file mode 100644
index 000000000..ed09a028b
--- /dev/null
+++ b/pkg/common/db/mgo/group_member.go
@@ -0,0 +1,101 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/protocol/constant"
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewGroupMember(db *mongo.Database) (relation.GroupMemberModelInterface, error) {
+ coll := db.Collection("group_member")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "group_id", Value: 1},
+ {Key: "user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &GroupMemberMgo{coll: coll}, nil
+}
+
+type GroupMemberMgo struct {
+ coll *mongo.Collection
+}
+
+func (g *GroupMemberMgo) Create(ctx context.Context, groupMembers []*relation.GroupMemberModel) (err error) {
+ return mgoutil.InsertMany(ctx, g.coll, groupMembers)
+}
+
+func (g *GroupMemberMgo) Delete(ctx context.Context, groupID string, userIDs []string) (err error) {
+ return mgoutil.DeleteMany(ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
+}
+
+func (g *GroupMemberMgo) UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error {
+ return g.Update(ctx, groupID, userID, bson.M{"role_level": roleLevel})
+}
+
+func (g *GroupMemberMgo) Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error) {
+ return mgoutil.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID}, bson.M{"$set": data}, true)
+}
+
+func (g *GroupMemberMgo) Find(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) (groupMembers []*relation.GroupMemberModel, err error) {
+ //TODO implement me
+ panic("implement me")
+}
+
+func (g *GroupMemberMgo) FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error) {
+ return mgoutil.Find[string](ctx, g.coll, bson.M{"group_id": groupID}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
+}
+
+func (g *GroupMemberMgo) Take(ctx context.Context, groupID string, userID string) (groupMember *relation.GroupMemberModel, err error) {
+ return mgoutil.FindOne[*relation.GroupMemberModel](ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID})
+}
+
+func (g *GroupMemberMgo) TakeOwner(ctx context.Context, groupID string) (groupMember *relation.GroupMemberModel, err error) {
+ return mgoutil.FindOne[*relation.GroupMemberModel](ctx, g.coll, bson.M{"group_id": groupID, "role_level": constant.GroupOwner})
+}
+
+func (g *GroupMemberMgo) FindRoleLevelUserIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) {
+ return mgoutil.Find[string](ctx, g.coll, bson.M{"group_id": groupID, "role_level": roleLevel}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
+}
+
+func (g *GroupMemberMgo) SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*relation.GroupMemberModel, err error) {
+ //TODO implement me
+ panic("implement me")
+}
+
+func (g *GroupMemberMgo) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
+ return mgoutil.Find[string](ctx, g.coll, bson.M{"user_id": userID}, options.Find().SetProjection(bson.M{"_id": 0, "group_id": 1}))
+}
+
+func (g *GroupMemberMgo) TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error) {
+ return mgoutil.Count(ctx, g.coll, bson.M{"group_id": groupID})
+}
+
+func (g *GroupMemberMgo) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
+ filter := bson.M{
+ "user_id": userID,
+ "role_level": bson.M{
+ "$in": []int{constant.GroupOwner, constant.GroupAdmin},
+ },
+ }
+ return mgoutil.Find[string](ctx, g.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "group_id": 1}))
+}
+
+func (g *GroupMemberMgo) IsUpdateRoleLevel(data map[string]any) bool {
+ if len(data) == 0 {
+ return false
+ }
+ _, ok := data["role_level"]
+ return ok
+}
diff --git a/pkg/common/db/mgo/group_request.go b/pkg/common/db/mgo/group_request.go
new file mode 100644
index 000000000..e88a39bf5
--- /dev/null
+++ b/pkg/common/db/mgo/group_request.go
@@ -0,0 +1,60 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewGroupRequestMgo(db *mongo.Database) (relation.GroupRequestModelInterface, error) {
+ coll := db.Collection("group_request")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "group_id", Value: 1},
+ {Key: "user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &GroupRequestMgo{coll: coll}, nil
+}
+
+type GroupRequestMgo struct {
+ coll *mongo.Collection
+}
+
+func (g *GroupRequestMgo) Create(ctx context.Context, groupRequests []*relation.GroupRequestModel) (err error) {
+ return mgoutil.InsertMany(ctx, g.coll, groupRequests)
+}
+
+func (g *GroupRequestMgo) Delete(ctx context.Context, groupID string, userID string) (err error) {
+ return mgoutil.DeleteOne(ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID})
+}
+
+func (g *GroupRequestMgo) UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error) {
+ return mgoutil.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID}, bson.M{"$set": bson.M{"handle_msg": handledMsg, "handle_result": handleResult}}, true)
+}
+
+func (g *GroupRequestMgo) Take(ctx context.Context, groupID string, userID string) (groupRequest *relation.GroupRequestModel, err error) {
+ return mgoutil.FindOne[*relation.GroupRequestModel](ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID})
+}
+
+func (g *GroupRequestMgo) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relation.GroupRequestModel, error) {
+ return mgoutil.Find[*relation.GroupRequestModel](ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
+}
+
+func (g *GroupRequestMgo) Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*relation.GroupRequestModel, err error) {
+ return mgoutil.FindPage[*relation.GroupRequestModel](ctx, g.coll, bson.M{"user_id": userID}, pagination)
+}
+
+func (g *GroupRequestMgo) PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*relation.GroupRequestModel, err error) {
+ return mgoutil.FindPage[*relation.GroupRequestModel](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}}, pagination)
+}
diff --git a/pkg/common/db/mgo/log.go b/pkg/common/db/mgo/log.go
new file mode 100644
index 000000000..aa280fcf2
--- /dev/null
+++ b/pkg/common/db/mgo/log.go
@@ -0,0 +1,70 @@
+package mgo
+
+import (
+ "context"
+ "time"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewLogMongo(db *mongo.Database) (relation.LogInterface, error) {
+ coll := db.Collection("log")
+ _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
+ {
+ Keys: bson.D{
+ {Key: "log_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ },
+ {
+ Keys: bson.D{
+ {Key: "user_id", Value: 1},
+ },
+ },
+ {
+ Keys: bson.D{
+ {Key: "create_time", Value: -1},
+ },
+ },
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &LogMgo{coll: coll}, nil
+}
+
+type LogMgo struct {
+ coll *mongo.Collection
+}
+
+func (l *LogMgo) Create(ctx context.Context, log []*relation.LogModel) error {
+ return mgoutil.InsertMany(ctx, l.coll, log)
+}
+
+func (l *LogMgo) Search(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error) {
+ filter := bson.M{"create_time": bson.M{"$gte": start, "$lte": end}}
+ if keyword != "" {
+ filter["user_id"] = bson.M{"$regex": keyword}
+ }
+ return mgoutil.FindPage[*relation.LogModel](ctx, l.coll, filter, pagination, options.Find().SetSort(bson.M{"create_time": -1}))
+}
+
+func (l *LogMgo) Delete(ctx context.Context, logID []string, userID string) error {
+ if userID == "" {
+ return mgoutil.DeleteMany(ctx, l.coll, bson.M{"log_id": bson.M{"$in": logID}})
+ }
+ return mgoutil.DeleteMany(ctx, l.coll, bson.M{"log_id": bson.M{"$in": logID}, "user_id": userID})
+}
+
+func (l *LogMgo) Get(ctx context.Context, logIDs []string, userID string) ([]*relation.LogModel, error) {
+ if userID == "" {
+ return mgoutil.Find[*relation.LogModel](ctx, l.coll, bson.M{"log_id": bson.M{"$in": logIDs}})
+ }
+ return mgoutil.Find[*relation.LogModel](ctx, l.coll, bson.M{"log_id": bson.M{"$in": logIDs}, "user_id": userID})
+}
diff --git a/pkg/common/db/mgo/object.go b/pkg/common/db/mgo/object.go
new file mode 100644
index 000000000..5976b2d28
--- /dev/null
+++ b/pkg/common/db/mgo/object.go
@@ -0,0 +1,55 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewS3Mongo(db *mongo.Database) (relation.ObjectInfoModelInterface, error) {
+ coll := db.Collection("s3")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "name", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &S3Mongo{coll: coll}, nil
+}
+
+type S3Mongo struct {
+ coll *mongo.Collection
+}
+
+func (o *S3Mongo) SetObject(ctx context.Context, obj *relation.ObjectModel) error {
+ filter := bson.M{"name": obj.Name, "engine": obj.Engine}
+ update := bson.M{
+ "name": obj.Name,
+ "engine": obj.Engine,
+ "key": obj.Key,
+ "size": obj.Size,
+ "content_type": obj.ContentType,
+ "group": obj.Group,
+ "create_time": obj.CreateTime,
+ }
+ return mgoutil.UpdateOne(ctx, o.coll, filter, bson.M{"$set": update}, false, options.Update().SetUpsert(true))
+}
+
+func (o *S3Mongo) Take(ctx context.Context, engine string, name string) (*relation.ObjectModel, error) {
+ if engine == "" {
+ return mgoutil.FindOne[*relation.ObjectModel](ctx, o.coll, bson.M{"name": name})
+ }
+ return mgoutil.FindOne[*relation.ObjectModel](ctx, o.coll, bson.M{"name": name, "engine": engine})
+}
+
+func (o *S3Mongo) Delete(ctx context.Context, engine string, name string) error {
+ return mgoutil.DeleteOne(ctx, o.coll, bson.M{"name": name, "engine": engine})
+}
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
new file mode 100644
index 000000000..4a53cb3c4
--- /dev/null
+++ b/pkg/common/db/mgo/user.go
@@ -0,0 +1,113 @@
+package mgo
+
+import (
+ "context"
+ "time"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewUserMongo(db *mongo.Database) (relation.UserModelInterface, error) {
+ coll := db.Collection("user")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &UserMgo{coll: coll}, nil
+}
+
+type UserMgo struct {
+ coll *mongo.Collection
+}
+
+func (u *UserMgo) Create(ctx context.Context, users []*relation.UserModel) error {
+ return mgoutil.InsertMany(ctx, u.coll, users)
+}
+
+func (u *UserMgo) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error) {
+ if len(args) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, u.coll, bson.M{"user_id": userID}, bson.M{"$set": args}, true)
+}
+
+func (u *UserMgo) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
+ return mgoutil.Find[*relation.UserModel](ctx, u.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
+}
+
+func (u *UserMgo) Take(ctx context.Context, userID string) (user *relation.UserModel, err error) {
+ return mgoutil.FindOne[*relation.UserModel](ctx, u.coll, bson.M{"user_id": userID})
+}
+
+func (u *UserMgo) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{}, pagination)
+}
+
+func (u *UserMgo) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error) {
+ return mgoutil.FindPage[string](ctx, u.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"user_id": 1}))
+}
+
+func (u *UserMgo) Exist(ctx context.Context, userID string) (exist bool, err error) {
+ return mgoutil.Exist(ctx, u.coll, bson.M{"user_id": userID})
+}
+
+func (u *UserMgo) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) {
+ return mgoutil.FindOne[int](ctx, u.coll, bson.M{"user_id": userID}, options.FindOne().SetProjection(bson.M{"global_recv_msg_opt": 1}))
+}
+
+func (u *UserMgo) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
+ if before == nil {
+ return mgoutil.Count(ctx, u.coll, bson.M{})
+ }
+ return mgoutil.Count(ctx, u.coll, bson.M{"create_time": bson.M{"$lt": before}})
+}
+
+func (u *UserMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
+ pipeline := bson.A{
+ bson.M{
+ "$match": bson.M{
+ "create_time": bson.M{
+ "$gte": start,
+ "$lt": end,
+ },
+ },
+ },
+ bson.M{
+ "$group": bson.M{
+ "_id": bson.M{
+ "$dateToString": bson.M{
+ "format": "%Y-%m-%d",
+ "date": "$create_time",
+ },
+ },
+ "count": bson.M{
+ "$sum": 1,
+ },
+ },
+ },
+ }
+ type Item struct {
+ Date string `bson:"_id"`
+ Count int64 `bson:"count"`
+ }
+ items, err := mgoutil.Aggregate[Item](ctx, u.coll, pipeline)
+ if err != nil {
+ return nil, err
+ }
+ res := make(map[string]int64, len(items))
+ for _, item := range items {
+ res[item.Date] = item.Count
+ }
+ return res, nil
+}
diff --git a/pkg/common/db/relation/black_model.go b/pkg/common/db/relation/black_model.go
deleted file mode 100644
index 34123c7a3..000000000
--- a/pkg/common/db/relation/black_model.go
+++ /dev/null
@@ -1,111 +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 relation
-
-import (
- "context"
-
- "github.com/OpenIMSDK/tools/errs"
-
- "github.com/OpenIMSDK/tools/ormutil"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type BlackGorm struct {
- *MetaDB
-}
-
-func NewBlackGorm(db *gorm.DB) relation.BlackModelInterface {
- return &BlackGorm{NewMetaDB(db, &relation.BlackModel{})}
-}
-
-func (b *BlackGorm) Create(ctx context.Context, blacks []*relation.BlackModel) (err error) {
- return utils.Wrap(b.db(ctx).Create(&blacks).Error, "")
-}
-
-func (b *BlackGorm) Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) {
- return utils.Wrap(b.db(ctx).Delete(blacks).Error, "")
-}
-
-func (b *BlackGorm) UpdateByMap(
- ctx context.Context,
- ownerUserID, blockUserID string,
- args map[string]interface{},
-) (err error) {
- return utils.Wrap(
- b.db(ctx).Where("block_user_id = ? and block_user_id = ?", ownerUserID, blockUserID).Updates(args).Error,
- "",
- )
-}
-
-func (b *BlackGorm) Update(ctx context.Context, blacks []*relation.BlackModel) (err error) {
- return utils.Wrap(b.db(ctx).Updates(&blacks).Error, "")
-}
-
-func (b *BlackGorm) Find(
- ctx context.Context,
- blacks []*relation.BlackModel,
-) (blackList []*relation.BlackModel, err error) {
- var where [][]interface{}
- for _, black := range blacks {
- where = append(where, []interface{}{black.OwnerUserID, black.BlockUserID})
- }
- return blackList, utils.Wrap(
- b.db(ctx).Where("(owner_user_id, block_user_id) in ?", where).Find(&blackList).Error,
- "",
- )
-}
-
-func (b *BlackGorm) Take(ctx context.Context, ownerUserID, blockUserID string) (black *relation.BlackModel, err error) {
- black = &relation.BlackModel{}
- return black, utils.Wrap(
- b.db(ctx).Where("owner_user_id = ? and block_user_id = ?", ownerUserID, blockUserID).Take(black).Error,
- "",
- )
-}
-
-func (b *BlackGorm) FindOwnerBlacks(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
-) (blacks []*relation.BlackModel, total int64, err error) {
- err = b.db(ctx).Count(&total).Error
- if err != nil {
- return nil, 0, utils.Wrap(err, "")
- }
- totalUint32, blacks, err := ormutil.GormPage[relation.BlackModel](
- b.db(ctx).Where("owner_user_id = ?", ownerUserID),
- pageNumber,
- showNumber,
- )
- total = int64(totalUint32)
- return
-}
-
-func (b *BlackGorm) FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error) {
- return blackUserIDs, utils.Wrap(
- b.db(ctx).Where("owner_user_id = ?", ownerUserID).Pluck("block_user_id", &blackUserIDs).Error,
- "",
- )
-}
-
-func (b *BlackGorm) FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) {
- return blacks, errs.Wrap(b.db(ctx).Where("owner_user_id = ? and block_user_id in ?", ownerUserID, userIDs).Find(&blacks).Error)
-}
diff --git a/pkg/common/db/relation/chat_log_model.go b/pkg/common/db/relation/chat_log_model.go
deleted file mode 100644
index f183a543f..000000000
--- a/pkg/common/db/relation/chat_log_model.go
+++ /dev/null
@@ -1,63 +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 relation
-
-import (
- "github.com/golang/protobuf/jsonpb"
- "github.com/jinzhu/copier"
- "google.golang.org/protobuf/proto"
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/protocol/constant"
- pbmsg "github.com/OpenIMSDK/protocol/msg"
- sdkws "github.com/OpenIMSDK/protocol/sdkws"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type ChatLogGorm struct {
- *MetaDB
-}
-
-func NewChatLogGorm(db *gorm.DB) relation.ChatLogModelInterface {
- return &ChatLogGorm{NewMetaDB(db, &relation.ChatLogModel{})}
-}
-
-func (c *ChatLogGorm) Create(msg *pbmsg.MsgDataToMQ) error {
- chatLog := new(relation.ChatLogModel)
- copier.Copy(chatLog, msg.MsgData)
- switch msg.MsgData.SessionType {
- case constant.GroupChatType, constant.SuperGroupChatType:
- chatLog.RecvID = msg.MsgData.GroupID
- case constant.SingleChatType:
- chatLog.RecvID = msg.MsgData.RecvID
- }
- if msg.MsgData.ContentType >= constant.NotificationBegin && msg.MsgData.ContentType <= constant.NotificationEnd {
- var tips sdkws.TipsComm
- _ = proto.Unmarshal(msg.MsgData.Content, &tips)
- marshaler := jsonpb.Marshaler{
- OrigName: true,
- EnumsAsInts: false,
- EmitDefaults: false,
- }
- chatLog.Content, _ = marshaler.MarshalToString(&tips)
- } else {
- chatLog.Content = string(msg.MsgData.Content)
- }
- chatLog.CreateTime = utils.UnixMillSecondToTime(msg.MsgData.CreateTime)
- chatLog.SendTime = utils.UnixMillSecondToTime(msg.MsgData.SendTime)
- return c.DB.Create(chatLog).Error
-}
diff --git a/pkg/common/db/relation/conversation_model.go b/pkg/common/db/relation/conversation_model.go
deleted file mode 100644
index f39047bf6..000000000
--- a/pkg/common/db/relation/conversation_model.go
+++ /dev/null
@@ -1,250 +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 relation
-
-import (
- "context"
-
- "github.com/OpenIMSDK/tools/errs"
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/protocol/constant"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type ConversationGorm struct {
- *MetaDB
-}
-
-func NewConversationGorm(db *gorm.DB) relation.ConversationModelInterface {
- return &ConversationGorm{NewMetaDB(db, &relation.ConversationModel{})}
-}
-
-func (c *ConversationGorm) NewTx(tx any) relation.ConversationModelInterface {
- return &ConversationGorm{NewMetaDB(tx.(*gorm.DB), &relation.ConversationModel{})}
-}
-
-func (c *ConversationGorm) Create(ctx context.Context, conversations []*relation.ConversationModel) (err error) {
- return utils.Wrap(c.db(ctx).Create(&conversations).Error, "")
-}
-
-func (c *ConversationGorm) Delete(ctx context.Context, groupIDs []string) (err error) {
- return utils.Wrap(c.db(ctx).Where("group_id in (?)", groupIDs).Delete(&relation.ConversationModel{}).Error, "")
-}
-
-func (c *ConversationGorm) UpdateByMap(
- ctx context.Context,
- userIDList []string,
- conversationID string,
- args map[string]interface{},
-) (rows int64, err error) {
- result := c.db(ctx).Where("owner_user_id IN (?) and conversation_id=?", userIDList, conversationID).Updates(args)
- return result.RowsAffected, utils.Wrap(result.Error, "")
-}
-
-func (c *ConversationGorm) Update(ctx context.Context, conversation *relation.ConversationModel) (err error) {
- return utils.Wrap(
- c.db(ctx).
- Where("owner_user_id = ? and conversation_id = ?", conversation.OwnerUserID, conversation.ConversationID).
- Updates(conversation).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) Find(
- ctx context.Context,
- ownerUserID string,
- conversationIDs []string,
-) (conversations []*relation.ConversationModel, err error) {
- err = utils.Wrap(
- c.db(ctx).
- Where("owner_user_id=? and conversation_id IN (?)", ownerUserID, conversationIDs).
- Find(&conversations).
- Error,
- "",
- )
- return conversations, err
-}
-
-func (c *ConversationGorm) Take(
- ctx context.Context,
- userID, conversationID string,
-) (conversation *relation.ConversationModel, err error) {
- cc := &relation.ConversationModel{}
- return cc, utils.Wrap(
- c.db(ctx).Where("conversation_id = ? And owner_user_id = ?", conversationID, userID).Take(cc).Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindUserID(
- ctx context.Context,
- userIDs []string,
- conversationIDs []string,
-) (existUserID []string, err error) {
- return existUserID, utils.Wrap(
- c.db(ctx).
- Where(" owner_user_id IN (?) and conversation_id in (?)", userIDs, conversationIDs).
- Pluck("owner_user_id", &existUserID).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindConversationID(
- ctx context.Context,
- userID string,
- conversationIDList []string,
-) (existConversationID []string, err error) {
- return existConversationID, utils.Wrap(
- c.db(ctx).
- Where(" conversation_id IN (?) and owner_user_id=?", conversationIDList, userID).
- Pluck("conversation_id", &existConversationID).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindUserIDAllConversationID(
- ctx context.Context,
- userID string,
-) (conversationIDList []string, err error) {
- return conversationIDList, utils.Wrap(
- c.db(ctx).Where("owner_user_id=?", userID).Pluck("conversation_id", &conversationIDList).Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindUserIDAllConversations(
- ctx context.Context,
- userID string,
-) (conversations []*relation.ConversationModel, err error) {
- return conversations, utils.Wrap(c.db(ctx).Where("owner_user_id=?", userID).Find(&conversations).Error, "")
-}
-
-func (c *ConversationGorm) FindRecvMsgNotNotifyUserIDs(
- ctx context.Context,
- groupID string,
-) (userIDs []string, err error) {
- return userIDs, utils.Wrap(
- c.db(ctx).
- Where("group_id = ? and recv_msg_opt = ?", groupID, constant.ReceiveNotNotifyMessage).
- Pluck("owner_user_id", &userIDs).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindSuperGroupRecvMsgNotNotifyUserIDs(
- ctx context.Context,
- groupID string,
-) (userIDs []string, err error) {
- return userIDs, utils.Wrap(
- c.db(ctx).
- Where("group_id = ? and recv_msg_opt = ? and conversation_type = ?", groupID, constant.ReceiveNotNotifyMessage, constant.SuperGroupChatType).
- Pluck("owner_user_id", &userIDs).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetUserRecvMsgOpt(
- ctx context.Context,
- ownerUserID, conversationID string,
-) (opt int, err error) {
- var conversation relation.ConversationModel
- return int(
- conversation.RecvMsgOpt,
- ), utils.Wrap(
- c.db(ctx).
- Where("conversation_id = ? And owner_user_id = ?", conversationID, ownerUserID).
- Select("recv_msg_opt").
- Find(&conversation).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetAllConversationIDs(ctx context.Context) (conversationIDs []string, err error) {
- return conversationIDs, utils.Wrap(
- c.db(ctx).Distinct("conversation_id").Pluck("conversation_id", &conversationIDs).Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetAllConversationIDsNumber(ctx context.Context) (int64, error) {
- var num int64
- err := c.db(ctx).Select("COUNT(DISTINCT conversation_id)").Model(&relation.ConversationModel{}).Count(&num).Error
- return num, errs.Wrap(err)
-}
-
-func (c *ConversationGorm) PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error) {
- err = c.db(ctx).Distinct("conversation_id").Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("conversation_id", &conversationIDs).Error
- err = errs.Wrap(err)
- return
-}
-
-func (c *ConversationGorm) GetUserAllHasReadSeqs(
- ctx context.Context,
- ownerUserID string,
-) (hasReadSeqs map[string]int64, err error) {
- return nil, nil
-}
-
-func (c *ConversationGorm) GetConversationsByConversationID(
- ctx context.Context,
- conversationIDs []string,
-) (conversations []*relation.ConversationModel, err error) {
- return conversations, utils.Wrap(
- c.db(ctx).Where("conversation_id IN (?)", conversationIDs).Find(&conversations).Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetConversationIDsNeedDestruct(
- ctx context.Context,
-) (conversations []*relation.ConversationModel, err error) {
- return conversations, utils.Wrap(
- c.db(ctx).
- Where("is_msg_destruct = 1 && msg_destruct_time != 0 && (UNIX_TIMESTAMP(NOW()) > (msg_destruct_time + UNIX_TIMESTAMP(latest_msg_destruct_time)) || latest_msg_destruct_time is NULL)").
- Find(&conversations).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetConversationRecvMsgOpt(ctx context.Context, userID string, conversationID string) (int32, error) {
- var recvMsgOpt int32
- return recvMsgOpt, errs.Wrap(
- c.db(ctx).
- Model(&relation.ConversationModel{}).
- Where("conversation_id = ? and owner_user_id in ?", conversationID, userID).
- Pluck("recv_msg_opt", &recvMsgOpt).
- Error,
- )
-}
-
-func (c *ConversationGorm) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) {
- var userIDs []string
- return userIDs, errs.Wrap(
- c.db(ctx).
- Model(&relation.ConversationModel{}).
- Where("conversation_id = ? and recv_msg_opt <> ?", conversationID, constant.ReceiveMessage).
- Pluck("owner_user_id", &userIDs).Error,
- )
-}
diff --git a/pkg/common/db/relation/doc.go b/pkg/common/db/relation/doc.go
deleted file mode 100644
index 41135ac97..000000000
--- a/pkg/common/db/relation/doc.go
+++ /dev/null
@@ -1,15 +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 relation // import "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
diff --git a/pkg/common/db/relation/friend_model.go b/pkg/common/db/relation/friend_model.go
deleted file mode 100644
index 869254455..000000000
--- a/pkg/common/db/relation/friend_model.go
+++ /dev/null
@@ -1,193 +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 relation
-
-import (
- "context"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type FriendGorm struct {
- *MetaDB
-}
-
-func NewFriendGorm(db *gorm.DB) relation.FriendModelInterface {
- return &FriendGorm{NewMetaDB(db, &relation.FriendModel{})}
-}
-
-func (f *FriendGorm) NewTx(tx any) relation.FriendModelInterface {
- return &FriendGorm{NewMetaDB(tx.(*gorm.DB), &relation.FriendModel{})}
-}
-
-// 插入多条记录.
-func (f *FriendGorm) Create(ctx context.Context, friends []*relation.FriendModel) (err error) {
- return utils.Wrap(f.db(ctx).Create(&friends).Error, "")
-}
-
-// 删除ownerUserID指定的好友.
-func (f *FriendGorm) Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error) {
- err = utils.Wrap(
- f.db(ctx).
- Where("owner_user_id = ? AND friend_user_id in ( ?)", ownerUserID, friendUserIDs).
- Delete(&relation.FriendModel{}).
- Error,
- "",
- )
- return err
-}
-
-// 更新ownerUserID单个好友信息 更新零值.
-func (f *FriendGorm) UpdateByMap(
- ctx context.Context,
- ownerUserID string,
- friendUserID string,
- args map[string]interface{},
-) (err error) {
- return utils.Wrap(
- f.db(ctx).Where("owner_user_id = ? AND friend_user_id = ? ", ownerUserID, friendUserID).Updates(args).Error,
- "",
- )
-}
-
-// 更新好友信息的非零值.
-func (f *FriendGorm) Update(ctx context.Context, friends []*relation.FriendModel) (err error) {
- return utils.Wrap(f.db(ctx).Updates(&friends).Error, "")
-}
-
-// 更新好友备注(也支持零值 ).
-func (f *FriendGorm) UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error) {
- if remark != "" {
- return utils.Wrap(
- f.db(ctx).
- Where("owner_user_id = ? and friend_user_id = ?", ownerUserID, friendUserID).
- Update("remark", remark).
- Error,
- "",
- )
- }
- m := make(map[string]interface{}, 1)
- m["remark"] = ""
- return utils.Wrap(f.db(ctx).Where("owner_user_id = ?", ownerUserID).Updates(m).Error, "")
-}
-
-// 获取单个好友信息,如没找到 返回错误.
-func (f *FriendGorm) Take(
- ctx context.Context,
- ownerUserID, friendUserID string,
-) (friend *relation.FriendModel, err error) {
- friend = &relation.FriendModel{}
- return friend, utils.Wrap(
- f.db(ctx).Where("owner_user_id = ? and friend_user_id", ownerUserID, friendUserID).Take(friend).Error,
- "",
- )
-}
-
-// 查找好友关系,如果是双向关系,则都返回.
-func (f *FriendGorm) FindUserState(
- ctx context.Context,
- userID1, userID2 string,
-) (friends []*relation.FriendModel, err error) {
- return friends, utils.Wrap(
- f.db(ctx).
- Where("(owner_user_id = ? and friend_user_id = ?) or (owner_user_id = ? and friend_user_id = ?)", userID1, userID2, userID2, userID1).
- Find(&friends).
- Error,
- "",
- )
-}
-
-// 获取 owner指定的好友列表 如果有friendUserIDs不存在,也不返回错误.
-func (f *FriendGorm) FindFriends(
- ctx context.Context,
- ownerUserID string,
- friendUserIDs []string,
-) (friends []*relation.FriendModel, err error) {
- return friends, utils.Wrap(
- f.db(ctx).Where("owner_user_id = ? AND friend_user_id in (?)", ownerUserID, friendUserIDs).Find(&friends).Error,
- "",
- )
-}
-
-// 获取哪些人添加了friendUserID 如果有ownerUserIDs不存在,也不返回错误.
-func (f *FriendGorm) FindReversalFriends(
- ctx context.Context,
- friendUserID string,
- ownerUserIDs []string,
-) (friends []*relation.FriendModel, err error) {
- return friends, utils.Wrap(
- f.db(ctx).Where("friend_user_id = ? AND owner_user_id in (?)", friendUserID, ownerUserIDs).Find(&friends).Error,
- "",
- )
-}
-
-// 获取ownerUserID好友列表 支持翻页.
-func (f *FriendGorm) FindOwnerFriends(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendModel, total int64, err error) {
- err = f.DB.Model(&relation.FriendModel{}).Where("owner_user_id = ? ", ownerUserID).Count(&total).Error
- if err != nil {
- return nil, 0, utils.Wrap(err, "")
- }
- err = utils.Wrap(
- f.db(ctx).
- Where("owner_user_id = ? ", ownerUserID).
- Limit(int(showNumber)).
- Offset(int((pageNumber-1)*showNumber)).
- Find(&friends).
- Error,
- "",
- )
- return
-}
-
-// 获取哪些人添加了friendUserID 支持翻页.
-func (f *FriendGorm) FindInWhoseFriends(
- ctx context.Context,
- friendUserID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendModel, total int64, err error) {
- err = f.DB.Model(&relation.FriendModel{}).Where("friend_user_id = ? ", friendUserID).Count(&total).Error
- if err != nil {
- return nil, 0, utils.Wrap(err, "")
- }
- err = utils.Wrap(
- f.db(ctx).
- Where("friend_user_id = ? ", friendUserID).
- Limit(int(showNumber)).
- Offset(int((pageNumber-1)*showNumber)).
- Find(&friends).
- Error,
- "",
- )
- return
-}
-
-func (f *FriendGorm) FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) {
- return friendUserIDs, utils.Wrap(
- f.db(ctx).
- Model(&relation.FriendModel{}).
- Where("owner_user_id = ? ", ownerUserID).
- Pluck("friend_user_id", &friendUserIDs).
- Error,
- "",
- )
-}
diff --git a/pkg/common/db/relation/friend_request_model.go b/pkg/common/db/relation/friend_request_model.go
deleted file mode 100644
index 5678f7b7b..000000000
--- a/pkg/common/db/relation/friend_request_model.go
+++ /dev/null
@@ -1,164 +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 relation
-
-import (
- "context"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type FriendRequestGorm struct {
- *MetaDB
-}
-
-func NewFriendRequestGorm(db *gorm.DB) relation.FriendRequestModelInterface {
- return &FriendRequestGorm{NewMetaDB(db, &relation.FriendRequestModel{})}
-}
-
-func (f *FriendRequestGorm) NewTx(tx any) relation.FriendRequestModelInterface {
- return &FriendRequestGorm{NewMetaDB(tx.(*gorm.DB), &relation.FriendRequestModel{})}
-}
-
-// 插入多条记录.
-func (f *FriendRequestGorm) Create(ctx context.Context, friendRequests []*relation.FriendRequestModel) (err error) {
- return utils.Wrap(f.db(ctx).Create(&friendRequests).Error, "")
-}
-
-// 删除记录.
-func (f *FriendRequestGorm) Delete(ctx context.Context, fromUserID, toUserID string) (err error) {
- return utils.Wrap(
- f.db(ctx).
- Where("from_user_id = ? AND to_user_id = ?", fromUserID, toUserID).
- Delete(&relation.FriendRequestModel{}).
- Error,
- "",
- )
-}
-
-// 更新零值.
-func (f *FriendRequestGorm) UpdateByMap(
- ctx context.Context,
- fromUserID string,
- toUserID string,
- args map[string]interface{},
-) (err error) {
- return utils.Wrap(
- f.db(ctx).
- Model(&relation.FriendRequestModel{}).
- Where("from_user_id = ? AND to_user_id =?", fromUserID, toUserID).
- Updates(args).
- Error,
- "",
- )
-}
-
-// 更新记录 (非零值).
-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(fr2).
- Error,
- "",
- )
-}
-
-// 获取来指定用户的好友申请 未找到 不返回错误.
-func (f *FriendRequestGorm) Find(
- ctx context.Context,
- fromUserID, toUserID string,
-) (friendRequest *relation.FriendRequestModel, err error) {
- friendRequest = &relation.FriendRequestModel{}
- err = utils.Wrap(
- f.db(ctx).Where("from_user_id = ? and to_user_id = ?", fromUserID, toUserID).Find(friendRequest).Error,
- "",
- )
- return friendRequest, err
-}
-
-func (f *FriendRequestGorm) Take(
- ctx context.Context,
- fromUserID, toUserID string,
-) (friendRequest *relation.FriendRequestModel, err error) {
- friendRequest = &relation.FriendRequestModel{}
- err = utils.Wrap(
- f.db(ctx).Where("from_user_id = ? and to_user_id = ?", fromUserID, toUserID).Take(friendRequest).Error,
- "",
- )
- return friendRequest, err
-}
-
-// 获取toUserID收到的好友申请列表.
-func (f *FriendRequestGorm) FindToUserID(
- ctx context.Context,
- toUserID string,
- pageNumber, showNumber int32,
-) (friendRequests []*relation.FriendRequestModel, total int64, err error) {
- err = f.db(ctx).Model(&relation.FriendRequestModel{}).Where("to_user_id = ? ", toUserID).Count(&total).Error
- if err != nil {
- return nil, 0, utils.Wrap(err, "")
- }
- err = utils.Wrap(
- f.db(ctx).
- Where("to_user_id = ? ", toUserID).
- Limit(int(showNumber)).
- Offset(int(pageNumber-1)*int(showNumber)).
- Find(&friendRequests).
- Error,
- "",
- )
- return
-}
-
-// 获取fromUserID发出去的好友申请列表.
-func (f *FriendRequestGorm) FindFromUserID(
- ctx context.Context,
- fromUserID string,
- pageNumber, showNumber int32,
-) (friendRequests []*relation.FriendRequestModel, total int64, err error) {
- err = f.db(ctx).Model(&relation.FriendRequestModel{}).Where("from_user_id = ? ", fromUserID).Count(&total).Error
- if err != nil {
- return nil, 0, utils.Wrap(err, "")
- }
- err = utils.Wrap(
- f.db(ctx).
- Where("from_user_id = ? ", fromUserID).
- Limit(int(showNumber)).
- Offset(int(pageNumber-1)*int(showNumber)).
- Find(&friendRequests).
- Error,
- "",
- )
- return
-}
-
-func (f *FriendRequestGorm) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
- err = utils.Wrap(
- f.db(ctx).
- Where("(from_user_id = ? AND to_user_id = ?) OR (from_user_id = ? AND to_user_id = ?)", fromUserID, toUserID, toUserID, fromUserID).
- Find(&friends).
- Error,
- "",
- )
- return
-}
diff --git a/pkg/common/db/relation/group_member_model.go b/pkg/common/db/relation/group_member_model.go
deleted file mode 100644
index 312e32054..000000000
--- a/pkg/common/db/relation/group_member_model.go
+++ /dev/null
@@ -1,197 +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 relation
-
-import (
- "context"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/protocol/constant"
- "github.com/OpenIMSDK/tools/ormutil"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-var _ relation.GroupMemberModelInterface = (*GroupMemberGorm)(nil)
-
-type GroupMemberGorm struct {
- *MetaDB
-}
-
-func NewGroupMemberDB(db *gorm.DB) relation.GroupMemberModelInterface {
- return &GroupMemberGorm{NewMetaDB(db, &relation.GroupMemberModel{})}
-}
-
-func (g *GroupMemberGorm) NewTx(tx any) relation.GroupMemberModelInterface {
- return &GroupMemberGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupMemberModel{})}
-}
-
-func (g *GroupMemberGorm) Create(ctx context.Context, groupMemberList []*relation.GroupMemberModel) (err error) {
- return utils.Wrap(g.db(ctx).Create(&groupMemberList).Error, "")
-}
-
-func (g *GroupMemberGorm) Delete(ctx context.Context, groupID string, userIDs []string) (err error) {
- return utils.Wrap(
- g.db(ctx).Where("group_id = ? and user_id in (?)", groupID, userIDs).Delete(&relation.GroupMemberModel{}).Error,
- "",
- )
-}
-
-func (g *GroupMemberGorm) DeleteGroup(ctx context.Context, groupIDs []string) (err error) {
- return utils.Wrap(g.db(ctx).Where("group_id in (?)", groupIDs).Delete(&relation.GroupMemberModel{}).Error, "")
-}
-
-func (g *GroupMemberGorm) Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error) {
- return utils.Wrap(g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Updates(data).Error, "")
-}
-
-func (g *GroupMemberGorm) UpdateRoleLevel(
- ctx context.Context,
- groupID string,
- userID string,
- roleLevel int32,
-) (rowsAffected int64, err error) {
- db := g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Updates(map[string]any{
- "role_level": roleLevel,
- })
- return db.RowsAffected, utils.Wrap(db.Error, "")
-}
-
-func (g *GroupMemberGorm) Find(
- ctx context.Context,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
-) (groupMembers []*relation.GroupMemberModel, err error) {
- db := g.db(ctx)
- if len(groupIDs) > 0 {
- db = db.Where("group_id in (?)", groupIDs)
- }
- if len(userIDs) > 0 {
- db = db.Where("user_id in (?)", userIDs)
- }
- if len(roleLevels) > 0 {
- db = db.Where("role_level in (?)", roleLevels)
- }
- return groupMembers, utils.Wrap(db.Find(&groupMembers).Error, "")
-}
-
-func (g *GroupMemberGorm) Take(
- ctx context.Context,
- groupID string,
- userID string,
-) (groupMember *relation.GroupMemberModel, err error) {
- groupMember = &relation.GroupMemberModel{}
- return groupMember, utils.Wrap(
- g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Take(groupMember).Error,
- "",
- )
-}
-
-func (g *GroupMemberGorm) TakeOwner(
- ctx context.Context,
- groupID string,
-) (groupMember *relation.GroupMemberModel, err error) {
- groupMember = &relation.GroupMemberModel{}
- return groupMember, utils.Wrap(
- g.db(ctx).Where("group_id = ? and role_level = ?", groupID, constant.GroupOwner).Take(groupMember).Error,
- "",
- )
-}
-
-func (g *GroupMemberGorm) SearchMember(
- ctx context.Context,
- keyword string,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
- pageNumber, showNumber int32,
-) (total uint32, groupList []*relation.GroupMemberModel, err error) {
- db := g.db(ctx)
- ormutil.GormIn(&db, "group_id", groupIDs)
- ormutil.GormIn(&db, "user_id", userIDs)
- ormutil.GormIn(&db, "role_level", roleLevels)
- return ormutil.GormSearch[relation.GroupMemberModel](db, []string{"nickname"}, keyword, pageNumber, showNumber)
-}
-
-func (g *GroupMemberGorm) MapGroupMemberNum(
- ctx context.Context,
- groupIDs []string,
-) (count map[string]uint32, err error) {
- return ormutil.MapCount(g.db(ctx).Where("group_id in (?)", groupIDs), "group_id")
-}
-
-func (g *GroupMemberGorm) FindJoinUserID(
- ctx context.Context,
- groupIDs []string,
-) (groupUsers map[string][]string, err error) {
- var groupMembers []*relation.GroupMemberModel
- if err := g.db(ctx).Select("group_id, user_id").Where("group_id in (?)", groupIDs).Find(&groupMembers).Error; err != nil {
- return nil, utils.Wrap(err, "")
- }
- groupUsers = make(map[string][]string)
- for _, item := range groupMembers {
- v, ok := groupUsers[item.GroupID]
- if !ok {
- groupUsers[item.GroupID] = []string{item.UserID}
- } else {
- groupUsers[item.GroupID] = append(v, item.UserID)
- }
- }
- return groupUsers, nil
-}
-
-func (g *GroupMemberGorm) FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error) {
- return userIDs, utils.Wrap(g.db(ctx).Where("group_id = ?", groupID).Pluck("user_id", &userIDs).Error, "")
-}
-
-func (g *GroupMemberGorm) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
- return groupIDs, utils.Wrap(g.db(ctx).Where("user_id = ?", userID).Pluck("group_id", &groupIDs).Error, "")
-}
-
-func (g *GroupMemberGorm) TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error) {
- return count, utils.Wrap(g.db(ctx).Where("group_id = ?", groupID).Count(&count).Error, "")
-}
-
-func (g *GroupMemberGorm) FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error) {
- var groupMembers []*relation.GroupMemberModel
- err := g.db(ctx).Select("group_id, user_id").Where("user_id IN (?)", userIDs).Find(&groupMembers).Error
- if err != nil {
- return nil, err
- }
- result := make(map[string][]string)
- for _, groupMember := range groupMembers {
- v, ok := result[groupMember.UserID]
- if !ok {
- result[groupMember.UserID] = []string{groupMember.GroupID}
- } else {
- result[groupMember.UserID] = append(v, groupMember.GroupID)
- }
- }
- return result, nil
-}
-
-func (g *GroupMemberGorm) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
- return groupIDs, utils.Wrap(
- g.db(ctx).
- Model(&relation.GroupMemberModel{}).
- Where("user_id = ? and (role_level = ? or role_level = ?)", userID, constant.GroupOwner, constant.GroupAdmin).
- Pluck("group_id", &groupIDs).
- Error,
- "",
- )
-}
diff --git a/pkg/common/db/relation/group_model.go b/pkg/common/db/relation/group_model.go
deleted file mode 100644
index 7a8eee9f0..000000000
--- a/pkg/common/db/relation/group_model.go
+++ /dev/null
@@ -1,106 +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 relation
-
-import (
- "context"
- "time"
-
- "github.com/OpenIMSDK/protocol/constant"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/ormutil"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-var _ relation.GroupModelInterface = (*GroupGorm)(nil)
-
-type GroupGorm struct {
- *MetaDB
-}
-
-func NewGroupDB(db *gorm.DB) relation.GroupModelInterface {
- return &GroupGorm{NewMetaDB(db, &relation.GroupModel{})}
-}
-
-func (g *GroupGorm) NewTx(tx any) relation.GroupModelInterface {
- return &GroupGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupModel{})}
-}
-
-func (g *GroupGorm) Create(ctx context.Context, groups []*relation.GroupModel) (err error) {
- return utils.Wrap(g.DB.Create(&groups).Error, "")
-}
-
-func (g *GroupGorm) UpdateMap(ctx context.Context, groupID string, args map[string]interface{}) (err error) {
- return utils.Wrap(g.DB.Where("group_id = ?", groupID).Model(&relation.GroupModel{}).Updates(args).Error, "")
-}
-
-func (g *GroupGorm) UpdateStatus(ctx context.Context, groupID string, status int32) (err error) {
- return utils.Wrap(g.DB.Where("group_id = ?", groupID).Model(&relation.GroupModel{}).Updates(map[string]any{"status": status}).Error, "")
-}
-
-func (g *GroupGorm) Find(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
- return groups, utils.Wrap(g.DB.Where("group_id in (?)", groupIDs).Find(&groups).Error, "")
-}
-
-func (g *GroupGorm) Take(ctx context.Context, groupID string) (group *relation.GroupModel, err error) {
- group = &relation.GroupModel{}
- return group, utils.Wrap(g.DB.Where("group_id = ?", groupID).Take(group).Error, "")
-}
-
-func (g *GroupGorm) Search(ctx context.Context, keyword string, pageNumber, showNumber int32) (total uint32, groups []*relation.GroupModel, err error) {
- db := g.DB
- db = db.WithContext(ctx).Where("status!=?", constant.GroupStatusDismissed)
- return ormutil.GormSearch[relation.GroupModel](db, []string{"name"}, keyword, pageNumber, showNumber)
-}
-
-func (g *GroupGorm) GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error) {
- return groupIDs, utils.Wrap(g.DB.Model(&relation.GroupModel{}).Where("group_type = ? ", groupType).Pluck("group_id", &groupIDs).Error, "")
-}
-
-func (g *GroupGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
- db := g.db(ctx).Model(&relation.GroupModel{})
- if before != nil {
- db = db.Where("create_time < ?", before)
- }
- if err := db.Count(&count).Error; err != nil {
- return 0, err
- }
- return count, nil
-}
-
-func (g *GroupGorm) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
- var res []struct {
- Date time.Time `gorm:"column:date"`
- Count int64 `gorm:"column:count"`
- }
- err := g.db(ctx).Model(&relation.GroupModel{}).Select("DATE(create_time) AS date, count(1) AS count").Where("create_time >= ? and create_time < ?", start, end).Group("date").Find(&res).Error
- if err != nil {
- return nil, errs.Wrap(err)
- }
- v := make(map[string]int64)
- for _, r := range res {
- v[r.Date.Format("2006-01-02")] = r.Count
- }
- return v, nil
-}
-
-func (g *GroupGorm) FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
- return groups, utils.Wrap(g.DB.Where("group_id in (?) and status != ?", groupIDs, constant.GroupStatusDismissed).Find(&groups).Error, "")
-}
diff --git a/pkg/common/db/relation/group_request_model.go b/pkg/common/db/relation/group_request_model.go
deleted file mode 100644
index af3f277e8..000000000
--- a/pkg/common/db/relation/group_request_model.go
+++ /dev/null
@@ -1,118 +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 relation
-
-import (
- "context"
-
- "github.com/OpenIMSDK/tools/ormutil"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type GroupRequestGorm struct {
- *MetaDB
-}
-
-func NewGroupRequest(db *gorm.DB) relation.GroupRequestModelInterface {
- return &GroupRequestGorm{
- NewMetaDB(db, &relation.GroupRequestModel{}),
- }
-}
-
-func (g *GroupRequestGorm) NewTx(tx any) relation.GroupRequestModelInterface {
- return &GroupRequestGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupRequestModel{})}
-}
-
-func (g *GroupRequestGorm) Create(ctx context.Context, groupRequests []*relation.GroupRequestModel) (err error) {
- return utils.Wrap(g.DB.WithContext(ctx).Create(&groupRequests).Error, utils.GetSelfFuncName())
-}
-
-func (g *GroupRequestGorm) Delete(ctx context.Context, groupID string, userID string) (err error) {
- return utils.Wrap(
- g.DB.WithContext(ctx).
- Where("group_id = ? and user_id = ? ", groupID, userID).
- Delete(&relation.GroupRequestModel{}).
- Error,
- utils.GetSelfFuncName(),
- )
-}
-
-func (g *GroupRequestGorm) UpdateHandler(
- ctx context.Context,
- groupID string,
- userID string,
- handledMsg string,
- handleResult int32,
-) (err error) {
- return utils.Wrap(
- g.DB.WithContext(ctx).
- Model(&relation.GroupRequestModel{}).
- Where("group_id = ? and user_id = ? ", groupID, userID).
- Updates(map[string]any{
- "handle_msg": handledMsg,
- "handle_result": handleResult,
- }).
- Error,
- utils.GetSelfFuncName(),
- )
-}
-
-func (g *GroupRequestGorm) Take(
- ctx context.Context,
- groupID string,
- userID string,
-) (groupRequest *relation.GroupRequestModel, err error) {
- groupRequest = &relation.GroupRequestModel{}
- return groupRequest, utils.Wrap(
- g.DB.WithContext(ctx).Where("group_id = ? and user_id = ? ", groupID, userID).Take(groupRequest).Error,
- utils.GetSelfFuncName(),
- )
-}
-
-func (g *GroupRequestGorm) Page(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (total uint32, groups []*relation.GroupRequestModel, err error) {
- return ormutil.GormSearch[relation.GroupRequestModel](
- g.DB.WithContext(ctx).Where("user_id = ?", userID),
- nil,
- "",
- pageNumber,
- showNumber,
- )
-}
-
-func (g *GroupRequestGorm) PageGroup(
- ctx context.Context,
- groupIDs []string,
- pageNumber, showNumber int32,
-) (total uint32, groups []*relation.GroupRequestModel, err error) {
- return ormutil.GormPage[relation.GroupRequestModel](
- g.DB.WithContext(ctx).Where("group_id in ?", groupIDs),
- pageNumber,
- showNumber,
- )
-}
-
-func (g *GroupRequestGorm) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (total int64, groupRequests []*relation.GroupRequestModel, err error) {
- err = g.DB.WithContext(ctx).Where("group_id = ? and user_id in ?", groupID, userIDs).Find(&groupRequests).Error
- return int64(len(groupRequests)), groupRequests, utils.Wrap(err, utils.GetSelfFuncName())
-}
diff --git a/pkg/common/db/relation/log_model.go b/pkg/common/db/relation/log_model.go
deleted file mode 100644
index 53365ca5b..000000000
--- a/pkg/common/db/relation/log_model.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package relation
-
-import (
- "context"
- "time"
-
- "github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/ormutil"
- "gorm.io/gorm"
-
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type LogGorm struct {
- db *gorm.DB
-}
-
-func (l *LogGorm) Create(ctx context.Context, log []*relationtb.Log) error {
- return errs.Wrap(l.db.WithContext(ctx).Create(log).Error)
-}
-
-func (l *LogGorm) Search(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relationtb.Log, error) {
- db := l.db.WithContext(ctx).Where("create_time >= ?", start)
- if end.UnixMilli() != 0 {
- db = l.db.WithContext(ctx).Where("create_time <= ?", end)
- }
- db = db.Order("create_time desc")
- return ormutil.GormSearch[relationtb.Log](db, []string{"user_id"}, keyword, pageNumber, showNumber)
-}
-
-func (l *LogGorm) Delete(ctx context.Context, logIDs []string, userID string) error {
- if userID == "" {
- return errs.Wrap(l.db.WithContext(ctx).Where("log_id in ?", logIDs).Delete(&relationtb.Log{}).Error)
- }
- return errs.Wrap(l.db.WithContext(ctx).Where("log_id in ? and user_id=?", logIDs, userID).Delete(&relationtb.Log{}).Error)
-}
-
-func (l *LogGorm) Get(ctx context.Context, logIDs []string, userID string) ([]*relationtb.Log, error) {
- var logs []*relationtb.Log
- if userID == "" {
- return logs, errs.Wrap(l.db.WithContext(ctx).Where("log_id in ?", logIDs).Find(&logs).Error)
- }
- return logs, errs.Wrap(l.db.WithContext(ctx).Where("log_id in ? and user_id=?", logIDs, userID).Find(&logs).Error)
-}
-
-func NewLogGorm(db *gorm.DB) relationtb.LogInterface {
- db.AutoMigrate(&relationtb.Log{})
- return &LogGorm{db: db}
-}
diff --git a/pkg/common/db/relation/mysql_init.go b/pkg/common/db/relation/mysql_init.go
deleted file mode 100644
index 41399d5ca..000000000
--- a/pkg/common/db/relation/mysql_init.go
+++ /dev/null
@@ -1,157 +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 relation
-
-import (
- "fmt"
- "time"
-
- "github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/log"
- "github.com/OpenIMSDK/tools/mw/specialerror"
- mysqldriver "github.com/go-sql-driver/mysql"
- "gorm.io/driver/mysql"
- "gorm.io/gorm"
- "gorm.io/gorm/logger"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/config"
-)
-
-const (
- maxRetry = 100 // number of retries
-)
-
-type option struct {
- Username string
- Password string
- Address []string
- Database string
- LogLevel int
- SlowThreshold int
- MaxLifeTime int
- MaxOpenConn int
- MaxIdleConn int
- Connect func(dsn string, maxRetry int) (*gorm.DB, error)
-}
-
-// newMysqlGormDB Initialize the database connection.
-func newMysqlGormDB(o *option) (*gorm.DB, error) {
- err := maybeCreateTable(o)
- if err != nil {
- return nil, err
- }
- dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
- o.Username, o.Password, o.Address[0], o.Database)
- sqlLogger := log.NewSqlLogger(
- logger.LogLevel(o.LogLevel),
- true,
- time.Duration(o.SlowThreshold)*time.Millisecond,
- )
- db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
- Logger: sqlLogger,
- })
- if err != nil {
- return nil, err
- }
- sqlDB, err := db.DB()
- if err != nil {
- return nil, err
- }
- sqlDB.SetConnMaxLifetime(time.Second * time.Duration(o.MaxLifeTime))
- sqlDB.SetMaxOpenConns(o.MaxOpenConn)
- sqlDB.SetMaxIdleConns(o.MaxIdleConn)
- return db, nil
-}
-
-// maybeCreateTable creates a database if it does not exists.
-func maybeCreateTable(o *option) error {
- dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
- o.Username, o.Password, o.Address[0], "mysql")
-
- var db *gorm.DB
- var err error
- if f := o.Connect; f != nil {
- db, err = f(dsn, maxRetry)
- } else {
- db, err = connectToDatabase(dsn, maxRetry)
- }
- if err != nil {
- panic(err.Error() + " Open failed " + dsn)
- }
-
- sqlDB, err := db.DB()
- if err != nil {
- return err
- }
- defer sqlDB.Close()
- sql := fmt.Sprintf(
- "CREATE DATABASE IF NOT EXISTS `%s` default charset utf8mb4 COLLATE utf8mb4_unicode_ci",
- o.Database,
- )
- err = db.Exec(sql).Error
- if err != nil {
- return fmt.Errorf("init db %w", err)
- }
- return nil
-}
-
-// connectToDatabase Connection retry for mysql.
-func connectToDatabase(dsn string, maxRetry int) (*gorm.DB, error) {
- var db *gorm.DB
- var err error
- for i := 0; i <= maxRetry; i++ {
- db, err = gorm.Open(mysql.Open(dsn), nil)
- if err == nil {
- return db, nil
- }
- if mysqlErr, ok := err.(*mysqldriver.MySQLError); ok && mysqlErr.Number == 1045 {
- return nil, err
- }
- time.Sleep(time.Duration(1) * time.Second)
- }
- return nil, err
-}
-
-// NewGormDB gorm mysql.
-func NewGormDB() (*gorm.DB, error) {
- specialerror.AddReplace(gorm.ErrRecordNotFound, errs.ErrRecordNotFound)
- specialerror.AddErrHandler(replaceDuplicateKey)
-
- return newMysqlGormDB(&option{
- Username: config.Config.Mysql.Username,
- Password: config.Config.Mysql.Password,
- Address: config.Config.Mysql.Address,
- Database: config.Config.Mysql.Database,
- LogLevel: config.Config.Mysql.LogLevel,
- SlowThreshold: config.Config.Mysql.SlowThreshold,
- MaxLifeTime: config.Config.Mysql.MaxLifeTime,
- MaxOpenConn: config.Config.Mysql.MaxOpenConn,
- MaxIdleConn: config.Config.Mysql.MaxIdleConn,
- })
-}
-
-func replaceDuplicateKey(err error) errs.CodeError {
- if IsMysqlDuplicateKey(err) {
- return errs.ErrDuplicateKey
- }
- return nil
-}
-
-func IsMysqlDuplicateKey(err error) bool {
- if mysqlErr, ok := err.(*mysqldriver.MySQLError); ok {
- return mysqlErr.Number == 1062
- }
- return false
-}
diff --git a/pkg/common/db/relation/mysql_init_test.go b/pkg/common/db/relation/mysql_init_test.go
deleted file mode 100644
index c321dfd9f..000000000
--- a/pkg/common/db/relation/mysql_init_test.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package relation
-
-import (
- "context"
- "database/sql"
- "database/sql/driver"
- "errors"
- "fmt"
- "reflect"
- "testing"
-
- "gorm.io/driver/mysql"
- "gorm.io/gorm"
- "gorm.io/gorm/logger"
-)
-
-func TestMaybeCreateTable(t *testing.T) {
- t.Run("normal", func(t *testing.T) {
- err := maybeCreateTable(&option{
- Username: "root",
- Password: "openIM123",
- Address: []string{"172.28.0.1:13306"},
- Database: "openIM_v3",
- LogLevel: 4,
- SlowThreshold: 500,
- MaxOpenConn: 1000,
- MaxIdleConn: 100,
- MaxLifeTime: 60,
- Connect: connect(expectExec{
- query: "CREATE DATABASE IF NOT EXISTS `openIM_v3` default charset utf8mb4 COLLATE utf8mb4_unicode_ci",
- args: nil,
- }),
- })
- if err != nil {
- t.Fatal(err)
- }
- })
-
- t.Run("im-db", func(t *testing.T) {
- err := maybeCreateTable(&option{
- Username: "root",
- Password: "openIM123",
- Address: []string{"172.28.0.1:13306"},
- Database: "im-db",
- LogLevel: 4,
- SlowThreshold: 500,
- MaxOpenConn: 1000,
- MaxIdleConn: 100,
- MaxLifeTime: 60,
- Connect: connect(expectExec{
- query: "CREATE DATABASE IF NOT EXISTS `im-db` default charset utf8mb4 COLLATE utf8mb4_unicode_ci",
- args: nil,
- }),
- })
- if err != nil {
- t.Fatal(err)
- }
- })
-
- t.Run("err", func(t *testing.T) {
- e := errors.New("e")
- err := maybeCreateTable(&option{
- Username: "root",
- Password: "openIM123",
- Address: []string{"172.28.0.1:13306"},
- Database: "openIM_v3",
- LogLevel: 4,
- SlowThreshold: 500,
- MaxOpenConn: 1000,
- MaxIdleConn: 100,
- MaxLifeTime: 60,
- Connect: connect(expectExec{
- err: e,
- }),
- })
- if !errors.Is(err, e) {
- t.Fatalf("err not is e: %v", err)
- }
- })
-}
-
-func connect(e expectExec) func(string, int) (*gorm.DB, error) {
- return func(string, int) (*gorm.DB, error) {
- return gorm.Open(mysql.New(mysql.Config{
- SkipInitializeWithVersion: true,
- Conn: sql.OpenDB(e),
- }), &gorm.Config{
- Logger: logger.Discard,
- })
- }
-}
-
-type expectExec struct {
- err error
- query string
- args []driver.NamedValue
-}
-
-func (c expectExec) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
- if c.err != nil {
- return nil, c.err
- }
- if query != c.query {
- return nil, fmt.Errorf("query mismatch. expect: %s, got: %s", c.query, query)
- }
- if reflect.DeepEqual(args, c.args) {
- return nil, fmt.Errorf("args mismatch. expect: %v, got: %v", c.args, args)
- }
- return noEffectResult{}, nil
-}
-
-func (e expectExec) Connect(context.Context) (driver.Conn, error) { return e, nil }
-func (expectExec) Driver() driver.Driver { panic("not implemented") }
-func (expectExec) Prepare(query string) (driver.Stmt, error) { panic("not implemented") }
-func (expectExec) Close() (e error) { return }
-func (expectExec) Begin() (driver.Tx, error) { panic("not implemented") }
-
-type noEffectResult struct{}
-
-func (noEffectResult) LastInsertId() (i int64, e error) { return }
-func (noEffectResult) RowsAffected() (i int64, e error) { return }
diff --git a/pkg/common/db/relation/object_model.go b/pkg/common/db/relation/object_model.go
deleted file mode 100644
index c5624a8d4..000000000
--- a/pkg/common/db/relation/object_model.go
+++ /dev/null
@@ -1,53 +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 relation
-
-import (
- "context"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/errs"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type ObjectInfoGorm struct {
- *MetaDB
-}
-
-func NewObjectInfo(db *gorm.DB) relation.ObjectInfoModelInterface {
- return &ObjectInfoGorm{
- NewMetaDB(db, &relation.ObjectModel{}),
- }
-}
-
-func (o *ObjectInfoGorm) NewTx(tx any) relation.ObjectInfoModelInterface {
- return &ObjectInfoGorm{
- NewMetaDB(tx.(*gorm.DB), &relation.ObjectModel{}),
- }
-}
-
-func (o *ObjectInfoGorm) SetObject(ctx context.Context, obj *relation.ObjectModel) (err error) {
- if err := o.DB.WithContext(ctx).Where("name = ?", obj.Name).FirstOrCreate(obj).Error; err != nil {
- return errs.Wrap(err)
- }
- return nil
-}
-
-func (o *ObjectInfoGorm) Take(ctx context.Context, name string) (info *relation.ObjectModel, err error) {
- info = &relation.ObjectModel{}
- return info, errs.Wrap(o.DB.WithContext(ctx).Where("name = ?", name).Take(info).Error)
-}
diff --git a/pkg/common/db/relation/user_model.go b/pkg/common/db/relation/user_model.go
deleted file mode 100644
index b04c29816..000000000
--- a/pkg/common/db/relation/user_model.go
+++ /dev/null
@@ -1,136 +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 relation
-
-import (
- "context"
- "time"
-
- "github.com/OpenIMSDK/tools/errs"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type UserGorm struct {
- *MetaDB
-}
-
-func NewUserGorm(db *gorm.DB) relation.UserModelInterface {
- return &UserGorm{NewMetaDB(db, &relation.UserModel{})}
-}
-
-// 插入多条.
-func (u *UserGorm) Create(ctx context.Context, users []*relation.UserModel) (err error) {
- return utils.Wrap(u.db(ctx).Create(&users).Error, "")
-}
-
-// 更新用户信息 零值.
-func (u *UserGorm) UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error) {
- return utils.Wrap(u.db(ctx).Model(&relation.UserModel{}).Where("user_id = ?", userID).Updates(args).Error, "")
-}
-
-// 更新多个用户信息 非零值.
-func (u *UserGorm) Update(ctx context.Context, user *relation.UserModel) (err error) {
- return utils.Wrap(u.db(ctx).Model(user).Updates(user).Error, "")
-}
-
-// 获取指定用户信息 不存在,也不返回错误.
-func (u *UserGorm) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
- err = utils.Wrap(u.db(ctx).Where("user_id in (?)", userIDs).Find(&users).Error, "")
- return users, err
-}
-
-// 获取某个用户信息 不存在,则返回错误.
-func (u *UserGorm) Take(ctx context.Context, userID string) (user *relation.UserModel, err error) {
- user = &relation.UserModel{}
- err = utils.Wrap(u.db(ctx).Where("user_id = ?", userID).Take(&user).Error, "")
- return user, err
-}
-
-// 获取用户信息 不存在,不返回错误.
-func (u *UserGorm) Page(
- ctx context.Context,
- pageNumber, showNumber int32,
-) (users []*relation.UserModel, count int64, err error) {
- err = utils.Wrap(u.db(ctx).Count(&count).Error, "")
- if err != nil {
- return
- }
- err = utils.Wrap(
- u.db(ctx).
- Limit(int(showNumber)).
- Offset(int((pageNumber-1)*showNumber)).
- Find(&users).
- Order("create_time DESC").
- Error,
- "",
- )
- return
-}
-
-// 获取所有用户ID.
-func (u *UserGorm) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err 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) {
- err = u.db(ctx).Model(&relation.UserModel{}).Where("user_id = ?", userID).Pluck("global_recv_msg_opt", &opt).Error
- return opt, err
-}
-
-func (u *UserGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
- db := u.db(ctx).Model(&relation.UserModel{})
- if before != nil {
- db = db.Where("create_time < ?", before)
- }
- if err := db.Count(&count).Error; err != nil {
- return 0, err
- }
- return count, nil
-}
-
-func (u *UserGorm) CountRangeEverydayTotal(
- ctx context.Context,
- start time.Time,
- end time.Time,
-) (map[string]int64, error) {
- var res []struct {
- Date time.Time `gorm:"column:date"`
- Count int64 `gorm:"column:count"`
- }
- err := u.db(ctx).
- Model(&relation.UserModel{}).
- Select("DATE(create_time) AS date, count(1) AS count").
- Where("create_time >= ? and create_time < ?", start, end).
- Group("date").
- Find(&res).
- Error
- if err != nil {
- return nil, errs.Wrap(err)
- }
- v := make(map[string]int64)
- for _, r := range res {
- v[r.Date.Format("2006-01-02")] = r.Count
- }
- return v, nil
-}
diff --git a/pkg/common/db/s3/cont/controller.go b/pkg/common/db/s3/cont/controller.go
index 7040c7306..1bf1a4b12 100644
--- a/pkg/common/db/s3/cont/controller.go
+++ b/pkg/common/db/s3/cont/controller.go
@@ -46,6 +46,10 @@ type Controller struct {
impl s3.Interface
}
+func (c *Controller) Engine() string {
+ return c.impl.Engine()
+}
+
func (c *Controller) HashPath(md5 string) string {
return path.Join(hashPath, md5)
}
diff --git a/pkg/common/db/s3/cos/internal.go b/pkg/common/db/s3/cos/internal.go
index 0e58a851c..02afde684 100644
--- a/pkg/common/db/s3/cos/internal.go
+++ b/pkg/common/db/s3/cos/internal.go
@@ -10,4 +10,4 @@ import (
)
//go:linkname newRequest github.com/tencentyun/cos-go-sdk-v5.(*Client).newRequest
-func newRequest(c *cos.Client, ctx context.Context, baseURL *url.URL, uri, method string, body interface{}, optQuery interface{}, optHeader interface{}) (req *http.Request, err error)
+func newRequest(c *cos.Client, ctx context.Context, baseURL *url.URL, uri, method string, body any, optQuery any, optHeader any) (req *http.Request, err error)
diff --git a/pkg/common/db/s3/kodo/internal.go b/pkg/common/db/s3/kodo/internal.go
deleted file mode 100644
index 3a4943e62..000000000
--- a/pkg/common/db/s3/kodo/internal.go
+++ /dev/null
@@ -1 +0,0 @@
-package kodo
diff --git a/pkg/common/db/s3/kodo/kodo.go b/pkg/common/db/s3/kodo/kodo.go
deleted file mode 100644
index d73220b3b..000000000
--- a/pkg/common/db/s3/kodo/kodo.go
+++ /dev/null
@@ -1,323 +0,0 @@
-package kodo
-
-import (
- "context"
- "errors"
- "fmt"
- "net/http"
- "net/url"
- "strconv"
- "strings"
- "time"
-
- "github.com/aws/aws-sdk-go-v2/aws"
- awss3config "github.com/aws/aws-sdk-go-v2/config"
- "github.com/aws/aws-sdk-go-v2/credentials"
- awss3 "github.com/aws/aws-sdk-go-v2/service/s3"
- awss3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
- "github.com/openimsdk/open-im-server/v3/pkg/common/config"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3"
- "github.com/qiniu/go-sdk/v7/auth"
- "github.com/qiniu/go-sdk/v7/storage"
-)
-
-const (
- minPartSize = 1024 * 1024 * 1 // 1MB
- maxPartSize = 1024 * 1024 * 1024 * 5 // 5GB
- maxNumSize = 10000
-)
-
-type Kodo struct {
- AccessKey string
- SecretKey string
- Region string
- Token string
- Endpoint string
- BucketURL string
- Auth *auth.Credentials
- Client *awss3.Client
- PresignClient *awss3.PresignClient
-}
-
-func NewKodo() (s3.Interface, error) {
- conf := config.Config.Object.Kodo
- //init client
- cfg, err := awss3config.LoadDefaultConfig(context.TODO(),
- awss3config.WithRegion(conf.Bucket),
- awss3config.WithEndpointResolverWithOptions(
- aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
- return aws.Endpoint{URL: conf.Endpoint}, nil
- })),
- awss3config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
- conf.AccessKeyID,
- conf.AccessKeySecret,
- conf.SessionToken),
- ),
- )
- if err != nil {
- panic(err)
- }
- client := awss3.NewFromConfig(cfg)
- presignClient := awss3.NewPresignClient(client)
-
- return &Kodo{
- AccessKey: conf.AccessKeyID,
- SecretKey: conf.AccessKeySecret,
- Region: conf.Bucket,
- BucketURL: conf.BucketURL,
- Auth: auth.New(conf.AccessKeyID, conf.AccessKeySecret),
- Client: client,
- PresignClient: presignClient,
- }, nil
-}
-
-func (k Kodo) Engine() string {
- return "kodo"
-}
-
-func (k Kodo) PartLimit() *s3.PartLimit {
- return &s3.PartLimit{
- MinPartSize: minPartSize,
- MaxPartSize: maxPartSize,
- MaxNumSize: maxNumSize,
- }
-}
-
-func (k Kodo) InitiateMultipartUpload(ctx context.Context, name string) (*s3.InitiateMultipartUploadResult, error) {
- result, err := k.Client.CreateMultipartUpload(ctx, &awss3.CreateMultipartUploadInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- if err != nil {
- return nil, err
- }
- return &s3.InitiateMultipartUploadResult{
- UploadID: aws.ToString(result.UploadId),
- Bucket: aws.ToString(result.Bucket),
- Key: aws.ToString(result.Key),
- }, nil
-}
-
-func (k Kodo) CompleteMultipartUpload(ctx context.Context, uploadID string, name string, parts []s3.Part) (*s3.CompleteMultipartUploadResult, error) {
- kodoParts := make([]awss3types.CompletedPart, len(parts))
- for i, part := range parts {
- kodoParts[i] = awss3types.CompletedPart{
- PartNumber: aws.Int32(int32(part.PartNumber)),
- ETag: aws.String(part.ETag),
- }
- }
- result, err := k.Client.CompleteMultipartUpload(ctx, &awss3.CompleteMultipartUploadInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- UploadId: aws.String(uploadID),
- MultipartUpload: &awss3types.CompletedMultipartUpload{Parts: kodoParts},
- })
- if err != nil {
- return nil, err
- }
- return &s3.CompleteMultipartUploadResult{
- Location: aws.ToString(result.Location),
- Bucket: aws.ToString(result.Bucket),
- Key: aws.ToString(result.Key),
- ETag: strings.ToLower(strings.ReplaceAll(aws.ToString(result.ETag), `"`, ``)),
- }, nil
-}
-
-func (k Kodo) PartSize(ctx context.Context, size int64) (int64, error) {
- if size <= 0 {
- return 0, errors.New("size must be greater than 0")
- }
- if size > maxPartSize*maxNumSize {
- return 0, fmt.Errorf("size must be less than %db", maxPartSize*maxNumSize)
- }
- if size <= minPartSize*maxNumSize {
- return minPartSize, nil
- }
- partSize := size / maxNumSize
- if size%maxNumSize != 0 {
- partSize++
- }
- return partSize, nil
-}
-
-func (k Kodo) AuthSign(ctx context.Context, uploadID string, name string, expire time.Duration, partNumbers []int) (*s3.AuthSignResult, error) {
- result := s3.AuthSignResult{
- URL: k.BucketURL + "/" + name,
- Query: url.Values{"uploadId": {uploadID}},
- Header: make(http.Header),
- Parts: make([]s3.SignPart, len(partNumbers)),
- }
- for i, partNumber := range partNumbers {
- part, _ := k.PresignClient.PresignUploadPart(ctx, &awss3.UploadPartInput{
- Bucket: aws.String(k.Region),
- UploadId: aws.String(uploadID),
- Key: aws.String(name),
- PartNumber: aws.Int32(int32(partNumber)),
- })
- result.Parts[i] = s3.SignPart{
- PartNumber: partNumber,
- URL: part.URL,
- Header: part.SignedHeader,
- }
- }
- return &result, nil
-
-}
-
-func (k Kodo) PresignedPutObject(ctx context.Context, name string, expire time.Duration) (string, error) {
- object, err := k.PresignClient.PresignPutObject(ctx, &awss3.PutObjectInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- }, func(po *awss3.PresignOptions) {
- po.Expires = expire
- })
- return object.URL, err
-
-}
-
-func (k Kodo) DeleteObject(ctx context.Context, name string) error {
- _, err := k.Client.DeleteObject(ctx, &awss3.DeleteObjectInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- return err
-}
-
-func (k Kodo) CopyObject(ctx context.Context, src string, dst string) (*s3.CopyObjectInfo, error) {
- result, err := k.Client.CopyObject(ctx, &awss3.CopyObjectInput{
- Bucket: aws.String(k.Region),
- CopySource: aws.String(k.Region + "/" + src),
- Key: aws.String(dst),
- })
- if err != nil {
- return nil, err
- }
- return &s3.CopyObjectInfo{
- Key: dst,
- ETag: strings.ToLower(strings.ReplaceAll(aws.ToString(result.CopyObjectResult.ETag), `"`, ``)),
- }, nil
-}
-
-func (k Kodo) StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error) {
- info, err := k.Client.HeadObject(ctx, &awss3.HeadObjectInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- if err != nil {
- return nil, err
- }
- res := &s3.ObjectInfo{Key: name}
- res.Size = aws.ToInt64(info.ContentLength)
- res.ETag = strings.ToLower(strings.ReplaceAll(aws.ToString(info.ETag), `"`, ``))
- return res, nil
-}
-
-func (k Kodo) IsNotFound(err error) bool {
- return true
-}
-
-func (k Kodo) AbortMultipartUpload(ctx context.Context, uploadID string, name string) error {
- _, err := k.Client.AbortMultipartUpload(ctx, &awss3.AbortMultipartUploadInput{
- UploadId: aws.String(uploadID),
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- return err
-}
-
-func (k Kodo) ListUploadedParts(ctx context.Context, uploadID string, name string, partNumberMarker int, maxParts int) (*s3.ListUploadedPartsResult, error) {
- result, err := k.Client.ListParts(ctx, &awss3.ListPartsInput{
- Key: aws.String(name),
- UploadId: aws.String(uploadID),
- Bucket: aws.String(k.Region),
- MaxParts: aws.Int32(int32(maxParts)),
- PartNumberMarker: aws.String(strconv.Itoa(partNumberMarker)),
- })
- if err != nil {
- return nil, err
- }
- res := &s3.ListUploadedPartsResult{
- Key: aws.ToString(result.Key),
- UploadID: aws.ToString(result.UploadId),
- MaxParts: int(aws.ToInt32(result.MaxParts)),
- UploadedParts: make([]s3.UploadedPart, len(result.Parts)),
- }
- // int to string
- NextPartNumberMarker, err := strconv.Atoi(aws.ToString(result.NextPartNumberMarker))
- if err != nil {
- return nil, err
- }
- res.NextPartNumberMarker = NextPartNumberMarker
- for i, part := range result.Parts {
- res.UploadedParts[i] = s3.UploadedPart{
- PartNumber: int(aws.ToInt32(part.PartNumber)),
- LastModified: aws.ToTime(part.LastModified),
- ETag: aws.ToString(part.ETag),
- Size: aws.ToInt64(part.Size),
- }
- }
- return res, nil
-}
-
-func (k Kodo) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (string, error) {
- //get object head
- info, err := k.Client.HeadObject(ctx, &awss3.HeadObjectInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- if err != nil {
- return "", errors.New("AccessURL object not found")
- }
- if opt != nil {
- if opt.ContentType != aws.ToString(info.ContentType) {
- //修改文件类型
- err := k.SetObjectContentType(ctx, name, opt.ContentType)
- if err != nil {
- return "", errors.New("AccessURL setContentType error")
- }
- }
- }
- imageMogr := ""
- //image dispose
- if opt != nil {
- if opt.Image != nil {
- //https://developer.qiniu.com/dora/8255/the-zoom
- process := ""
- if opt.Image.Width > 0 {
- process += strconv.Itoa(opt.Image.Width) + "x"
- }
- if opt.Image.Height > 0 {
- if opt.Image.Width > 0 {
- process += strconv.Itoa(opt.Image.Height)
- } else {
- process += "x" + strconv.Itoa(opt.Image.Height)
- }
- }
- imageMogr = "imageMogr2/thumbnail/" + process
- }
- }
- //expire
- deadline := time.Now().Add(time.Second * expire).Unix()
- domain := k.BucketURL
- query := url.Values{}
- if opt != nil && opt.Filename != "" {
- query.Add("attname", opt.Filename)
- }
- privateURL := storage.MakePrivateURLv2WithQuery(k.Auth, domain, name, query, deadline)
- if imageMogr != "" {
- privateURL += "&" + imageMogr
- }
- return privateURL, nil
-}
-
-func (k *Kodo) SetObjectContentType(ctx context.Context, name string, contentType string) error {
- //set object content-type
- _, err := k.Client.CopyObject(ctx, &awss3.CopyObjectInput{
- Bucket: aws.String(k.Region),
- CopySource: aws.String(k.Region + "/" + name),
- Key: aws.String(name),
- ContentType: aws.String(contentType),
- MetadataDirective: awss3types.MetadataDirectiveReplace,
- })
- return err
-}
diff --git a/pkg/common/db/s3/oss/internal.go b/pkg/common/db/s3/oss/internal.go
index 4ca1acc47..155708ffd 100644
--- a/pkg/common/db/s3/oss/internal.go
+++ b/pkg/common/db/s3/oss/internal.go
@@ -26,7 +26,7 @@ import (
func signHeader(c oss.Conn, req *http.Request, canonicalizedResource string)
//go:linkname getURLParams github.com/aliyun/aliyun-oss-go-sdk/oss.Conn.getURLParams
-func getURLParams(c oss.Conn, params map[string]interface{}) string
+func getURLParams(c oss.Conn, params map[string]any) string
//go:linkname getURL github.com/aliyun/aliyun-oss-go-sdk/oss.urlMaker.getURL
func getURL(um urlMaker, bucket, object, params string) *url.URL
diff --git a/pkg/common/db/s3/oss/oss.go b/pkg/common/db/s3/oss/oss.go
old mode 100755
new mode 100644
diff --git a/pkg/common/db/table/relation/black.go b/pkg/common/db/table/relation/black.go
index 59dd12122..50499054c 100644
--- a/pkg/common/db/table/relation/black.go
+++ b/pkg/common/db/table/relation/black.go
@@ -17,33 +17,27 @@ package relation
import (
"context"
"time"
-)
-const (
- BlackModelTableName = "blacks"
+ "github.com/OpenIMSDK/tools/pagination"
)
type BlackModel struct {
- OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
- BlockUserID string `gorm:"column:block_user_id;primary_key;size:64"`
- CreateTime time.Time `gorm:"column:create_time"`
- AddSource int32 `gorm:"column:add_source"`
- OperatorUserID string `gorm:"column:operator_user_id;size:64"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (BlackModel) TableName() string {
- return BlackModelTableName
+ OwnerUserID string `bson:"owner_user_id"`
+ BlockUserID string `bson:"block_user_id"`
+ CreateTime time.Time `bson:"create_time"`
+ AddSource int32 `bson:"add_source"`
+ OperatorUserID string `bson:"operator_user_id"`
+ Ex string `bson:"ex"`
}
type BlackModelInterface interface {
Create(ctx context.Context, blacks []*BlackModel) (err error)
Delete(ctx context.Context, blacks []*BlackModel) (err error)
- UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]interface{}) (err error)
- Update(ctx context.Context, blacks []*BlackModel) (err error)
+ //UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]any) (err error)
+ //Update(ctx context.Context, blacks []*BlackModel) (err error)
Find(ctx context.Context, blacks []*BlackModel) (blackList []*BlackModel, err error)
Take(ctx context.Context, ownerUserID, blockUserID string) (black *BlackModel, err error)
- FindOwnerBlacks(ctx context.Context, ownerUserID string, pageNumber, showNumber int32) (blacks []*BlackModel, total int64, err error)
+ FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*BlackModel, err error)
FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*BlackModel, err error)
FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error)
}
diff --git a/pkg/common/db/table/relation/conversation.go b/pkg/common/db/table/relation/conversation.go
index e9680873f..e0a5268ca 100644
--- a/pkg/common/db/table/relation/conversation.go
+++ b/pkg/common/db/table/relation/conversation.go
@@ -17,41 +17,35 @@ package relation
import (
"context"
"time"
-)
-const (
- conversationModelTableName = "conversations"
+ "github.com/OpenIMSDK/tools/pagination"
)
type ConversationModel struct {
- OwnerUserID string `gorm:"column:owner_user_id;primary_key;type:char(128)" json:"OwnerUserID"`
- ConversationID string `gorm:"column:conversation_id;primary_key;type:char(128)" json:"conversationID"`
- ConversationType int32 `gorm:"column:conversation_type" json:"conversationType"`
- UserID string `gorm:"column:user_id;type:char(64)" json:"userID"`
- GroupID string `gorm:"column:group_id;type:char(128)" json:"groupID"`
- RecvMsgOpt int32 `gorm:"column:recv_msg_opt" json:"recvMsgOpt"`
- IsPinned bool `gorm:"column:is_pinned" json:"isPinned"`
- IsPrivateChat bool `gorm:"column:is_private_chat" json:"isPrivateChat"`
- BurnDuration int32 `gorm:"column:burn_duration;default:30" json:"burnDuration"`
- GroupAtType int32 `gorm:"column:group_at_type" json:"groupAtType"`
- AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
- Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
- MaxSeq int64 `gorm:"column:max_seq" json:"maxSeq"`
- MinSeq int64 `gorm:"column:min_seq" json:"minSeq"`
- CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
- IsMsgDestruct bool `gorm:"column:is_msg_destruct;default:false"`
- MsgDestructTime int64 `gorm:"column:msg_destruct_time;default:604800"`
- LatestMsgDestructTime time.Time `gorm:"column:latest_msg_destruct_time;autoCreateTime"`
-}
-
-func (ConversationModel) TableName() string {
- return conversationModelTableName
+ OwnerUserID string `bson:"owner_user_id"`
+ ConversationID string `bson:"conversation_id"`
+ ConversationType int32 `bson:"conversation_type"`
+ UserID string `bson:"user_id"`
+ GroupID string `bson:"group_id"`
+ RecvMsgOpt int32 `bson:"recv_msg_opt"`
+ IsPinned bool `bson:"is_pinned"`
+ IsPrivateChat bool `bson:"is_private_chat"`
+ BurnDuration int32 `bson:"burn_duration"`
+ GroupAtType int32 `bson:"group_at_type"`
+ AttachedInfo string `bson:"attached_info"`
+ Ex string `bson:"ex"`
+ MaxSeq int64 `bson:"max_seq"`
+ MinSeq int64 `bson:"min_seq"`
+ CreateTime time.Time `bson:"create_time"`
+ IsMsgDestruct bool `bson:"is_msg_destruct"`
+ MsgDestructTime int64 `bson:"msg_destruct_time"`
+ LatestMsgDestructTime time.Time `bson:"latest_msg_destruct_time"`
}
type ConversationModelInterface interface {
Create(ctx context.Context, conversations []*ConversationModel) (err error)
Delete(ctx context.Context, groupIDs []string) (err error)
- UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) (rows int64, err error)
+ UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]any) (rows int64, err error)
Update(ctx context.Context, conversation *ConversationModel) (err error)
Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*ConversationModel, err error)
FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error)
@@ -61,13 +55,10 @@ type ConversationModelInterface interface {
FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*ConversationModel, err error)
FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
- FindSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
GetAllConversationIDs(ctx context.Context) ([]string, error)
GetAllConversationIDsNumber(ctx context.Context) (int64, error)
- PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error)
- GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (hashReadSeqs map[string]int64, err error)
+ PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*ConversationModel, error)
GetConversationIDsNeedDestruct(ctx context.Context) ([]*ConversationModel, error)
GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
- NewTx(tx any) ConversationModelInterface
}
diff --git a/pkg/common/db/table/relation/friend.go b/pkg/common/db/table/relation/friend.go
index 58d8d1d34..75dbea850 100644
--- a/pkg/common/db/table/relation/friend.go
+++ b/pkg/common/db/table/relation/friend.go
@@ -17,62 +17,43 @@ package relation
import (
"context"
"time"
-)
-const (
- FriendModelTableName = "friends"
+ "github.com/OpenIMSDK/tools/pagination"
)
+// FriendModel represents the data structure for a friend relationship in MongoDB.
type FriendModel struct {
- OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
- FriendUserID string `gorm:"column:friend_user_id;primary_key;size:64"`
- Remark string `gorm:"column:remark;size:255"`
- CreateTime time.Time `gorm:"column:create_time;autoCreateTime"`
- AddSource int32 `gorm:"column:add_source"`
- OperatorUserID string `gorm:"column:operator_user_id;size:64"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (FriendModel) TableName() string {
- return FriendModelTableName
+ OwnerUserID string `bson:"owner_user_id"`
+ FriendUserID string `bson:"friend_user_id"`
+ Remark string `bson:"remark"`
+ CreateTime time.Time `bson:"create_time"`
+ AddSource int32 `bson:"add_source"`
+ OperatorUserID string `bson:"operator_user_id"`
+ Ex string `bson:"ex"`
}
+// FriendModelInterface defines the operations for managing friends in MongoDB.
type FriendModelInterface interface {
- // 插入多条记录
+ // Create inserts multiple friend records.
Create(ctx context.Context, friends []*FriendModel) (err error)
- // 删除ownerUserID指定的好友
+ // Delete removes specified friends of the owner user.
Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
- // 更新ownerUserID单个好友信息 更新零值
- UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) (err error)
- // 更新好友信息的非零值
- Update(ctx context.Context, friends []*FriendModel) (err error)
- // 更新好友备注(也支持零值 )
+ // UpdateByMap updates specific fields of a friend document using a map.
+ UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]any) (err error)
+ // UpdateRemark modify remarks.
UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
- // 获取单个好友信息,如没找到 返回错误
+ // Take retrieves a single friend document. Returns an error if not found.
Take(ctx context.Context, ownerUserID, friendUserID string) (friend *FriendModel, err error)
- // 查找好友关系,如果是双向关系,则都返回
+ // FindUserState finds the friendship status between two users.
FindUserState(ctx context.Context, userID1, userID2 string) (friends []*FriendModel, err error)
- // 获取 owner指定的好友列表 如果有friendUserIDs不存在,也不返回错误
+ // FindFriends retrieves a list of friends for a given owner. Missing friends do not cause an error.
FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*FriendModel, err error)
- // 获取哪些人添加了friendUserID 如果有ownerUserIDs不存在,也不返回错误
- FindReversalFriends(
- ctx context.Context,
- friendUserID string,
- ownerUserIDs []string,
- ) (friends []*FriendModel, err error)
- // 获取ownerUserID好友列表 支持翻页
- FindOwnerFriends(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
- ) (friends []*FriendModel, total int64, err error)
- // 获取哪些人添加了friendUserID 支持翻页
- FindInWhoseFriends(
- ctx context.Context,
- friendUserID string,
- pageNumber, showNumber int32,
- ) (friends []*FriendModel, total int64, err error)
- // 获取好友UserID列表
+ // FindReversalFriends finds users who have added the specified user as a friend.
+ FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) (friends []*FriendModel, err error)
+ // FindOwnerFriends retrieves a paginated list of friends for a given owner.
+ FindOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
+ // FindInWhoseFriends finds users who have added the specified user as a friend, with pagination.
+ FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
+ // FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
- NewTx(tx any) FriendModelInterface
}
diff --git a/pkg/common/db/table/relation/friend_request.go b/pkg/common/db/table/relation/friend_request.go
index 51ea0ef6e..8dceb0778 100644
--- a/pkg/common/db/table/relation/friend_request.go
+++ b/pkg/common/db/table/relation/friend_request.go
@@ -17,50 +17,37 @@ package relation
import (
"context"
"time"
-)
-const FriendRequestModelTableName = "friend_requests"
+ "github.com/OpenIMSDK/tools/pagination"
+)
type FriendRequestModel struct {
- FromUserID string `gorm:"column:from_user_id;primary_key;size:64"`
- ToUserID string `gorm:"column:to_user_id;primary_key;size:64"`
- HandleResult int32 `gorm:"column:handle_result"`
- ReqMsg string `gorm:"column:req_msg;size:255"`
- CreateTime time.Time `gorm:"column:create_time; autoCreateTime"`
- HandlerUserID string `gorm:"column:handler_user_id;size:64"`
- HandleMsg string `gorm:"column:handle_msg;size:255"`
- HandleTime time.Time `gorm:"column:handle_time"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (FriendRequestModel) TableName() string {
- return FriendRequestModelTableName
+ FromUserID string `bson:"from_user_id"`
+ ToUserID string `bson:"to_user_id"`
+ HandleResult int32 `bson:"handle_result"`
+ ReqMsg string `bson:"req_msg"`
+ CreateTime time.Time `bson:"create_time"`
+ HandlerUserID string `bson:"handler_user_id"`
+ HandleMsg string `bson:"handle_msg"`
+ HandleTime time.Time `bson:"handle_time"`
+ Ex string `bson:"ex"`
}
type FriendRequestModelInterface interface {
- // 插入多条记录
+ // Insert multiple records
Create(ctx context.Context, friendRequests []*FriendRequestModel) (err error)
- // 删除记录
+ // Delete record
Delete(ctx context.Context, fromUserID, toUserID string) (err error)
- // 更新零值
- UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]interface{}) (err error)
- // 更新多条记录 (非零值)
+ // Update with zero values
+ UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]any) (err error)
+ // Update multiple records (non-zero values)
Update(ctx context.Context, friendRequest *FriendRequestModel) (err error)
- // 获取来指定用户的好友申请 未找到 不返回错误
+ // Get friend requests sent to a specific user, no error returned if not found
Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
- // 获取toUserID收到的好友申请列表
- FindToUserID(
- ctx context.Context,
- toUserID string,
- pageNumber, showNumber int32,
- ) (friendRequests []*FriendRequestModel, total int64, err error)
- // 获取fromUserID发出去的好友申请列表
- FindFromUserID(
- ctx context.Context,
- fromUserID string,
- pageNumber, showNumber int32,
- ) (friendRequests []*FriendRequestModel, total int64, err error)
+ // Get list of friend requests received by toUserID
+ FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*FriendRequestModel, err error)
+ // Get list of friend requests sent by fromUserID
+ FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*FriendRequestModel, err error)
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*FriendRequestModel, err error)
- NewTx(tx any) FriendRequestModelInterface
}
diff --git a/pkg/common/db/table/relation/group.go b/pkg/common/db/table/relation/group.go
index 6759e0d35..bb1ddd878 100644
--- a/pkg/common/db/table/relation/group.go
+++ b/pkg/common/db/table/relation/group.go
@@ -17,48 +17,35 @@ package relation
import (
"context"
"time"
-)
-const (
- GroupModelTableName = "groups"
+ "github.com/OpenIMSDK/tools/pagination"
)
type GroupModel struct {
- GroupID string `gorm:"column:group_id;primary_key;size:64" json:"groupID" binding:"required"`
- GroupName string `gorm:"column:name;size:255" json:"groupName"`
- Notification string `gorm:"column:notification;size:255" json:"notification"`
- Introduction string `gorm:"column:introduction;size:255" json:"introduction"`
- FaceURL string `gorm:"column:face_url;size:255" json:"faceURL"`
- CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
- Ex string `gorm:"column:ex" json:"ex;size:1024"`
- Status int32 `gorm:"column:status"`
- CreatorUserID string `gorm:"column:creator_user_id;size:64"`
- GroupType int32 `gorm:"column:group_type"`
- NeedVerification int32 `gorm:"column:need_verification"`
- LookMemberInfo int32 `gorm:"column:look_member_info" json:"lookMemberInfo"`
- ApplyMemberFriend int32 `gorm:"column:apply_member_friend" json:"applyMemberFriend"`
- NotificationUpdateTime time.Time `gorm:"column:notification_update_time"`
- NotificationUserID string `gorm:"column:notification_user_id;size:64"`
-}
-
-func (GroupModel) TableName() string {
- return GroupModelTableName
+ GroupID string `bson:"group_id"`
+ GroupName string `bson:"group_name"`
+ Notification string `bson:"notification"`
+ Introduction string `bson:"introduction"`
+ FaceURL string `bson:"face_url"`
+ CreateTime time.Time `bson:"create_time"`
+ Ex string `bson:"ex"`
+ Status int32 `bson:"status"`
+ CreatorUserID string `bson:"creator_user_id"`
+ GroupType int32 `bson:"group_type"`
+ NeedVerification int32 `bson:"need_verification"`
+ LookMemberInfo int32 `bson:"look_member_info"`
+ ApplyMemberFriend int32 `bson:"apply_member_friend"`
+ NotificationUpdateTime time.Time `bson:"notification_update_time"`
+ NotificationUserID string `bson:"notification_user_id"`
}
type GroupModelInterface interface {
- NewTx(tx any) GroupModelInterface
Create(ctx context.Context, groups []*GroupModel) (err error)
- UpdateMap(ctx context.Context, groupID string, args map[string]interface{}) (err error)
- UpdateStatus(ctx context.Context, groupID string, status int32) (err error)
+ UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error)
+ UpdateState(ctx context.Context, groupID string, state int32) (err error)
Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
- FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
Take(ctx context.Context, groupID string) (group *GroupModel, err error)
- Search(
- ctx context.Context,
- keyword string,
- pageNumber, showNumber int32,
- ) (total uint32, groups []*GroupModel, err error)
- GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error)
+ Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*GroupModel, err error)
// 获取群总数
CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
// 获取范围内群增量
diff --git a/pkg/common/db/table/relation/group_member.go b/pkg/common/db/table/relation/group_member.go
index bfde72834..88ab87739 100644
--- a/pkg/common/db/table/relation/group_member.go
+++ b/pkg/common/db/table/relation/group_member.go
@@ -17,58 +17,41 @@ package relation
import (
"context"
"time"
-)
-const (
- GroupMemberModelTableName = "group_members"
+ "github.com/OpenIMSDK/tools/pagination"
)
type GroupMemberModel struct {
- GroupID string `gorm:"column:group_id;primary_key;size:64"`
- UserID string `gorm:"column:user_id;primary_key;size:64"`
- Nickname string `gorm:"column:nickname;size:255"`
- FaceURL string `gorm:"column:user_group_face_url;size:255"`
- RoleLevel int32 `gorm:"column:role_level"`
- JoinTime time.Time `gorm:"column:join_time"`
- JoinSource int32 `gorm:"column:join_source"`
- InviterUserID string `gorm:"column:inviter_user_id;size:64"`
- OperatorUserID string `gorm:"column:operator_user_id;size:64"`
- MuteEndTime time.Time `gorm:"column:mute_end_time"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (GroupMemberModel) TableName() string {
- return GroupMemberModelTableName
+ GroupID string `bson:"group_id"`
+ UserID string `bson:"user_id"`
+ Nickname string `bson:"nickname"`
+ FaceURL string `bson:"face_url"`
+ RoleLevel int32 `bson:"role_level"`
+ JoinTime time.Time `bson:"join_time"`
+ JoinSource int32 `bson:"join_source"`
+ InviterUserID string `bson:"inviter_user_id"`
+ OperatorUserID string `bson:"operator_user_id"`
+ MuteEndTime time.Time `bson:"mute_end_time"`
+ Ex string `bson:"ex"`
}
type GroupMemberModelInterface interface {
- NewTx(tx any) GroupMemberModelInterface
+ //NewTx(tx any) GroupMemberModelInterface
Create(ctx context.Context, groupMembers []*GroupMemberModel) (err error)
Delete(ctx context.Context, groupID string, userIDs []string) (err error)
- DeleteGroup(ctx context.Context, groupIDs []string) (err error)
+ //DeleteGroup(ctx context.Context, groupIDs []string) (err error)
Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error)
- UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) (rowsAffected int64, err error)
- Find(
- ctx context.Context,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
- ) (groupMembers []*GroupMemberModel, err error)
+ UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error
FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error)
Take(ctx context.Context, groupID string, userID string) (groupMember *GroupMemberModel, err error)
TakeOwner(ctx context.Context, groupID string) (groupMember *GroupMemberModel, err error)
- SearchMember(
- ctx context.Context,
- keyword string,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
- pageNumber, showNumber int32,
- ) (total uint32, groupList []*GroupMemberModel, err error)
- MapGroupMemberNum(ctx context.Context, groupIDs []string) (count map[string]uint32, err error)
- FindJoinUserID(ctx context.Context, groupIDs []string) (groupUsers map[string][]string, err error)
+ SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*GroupMemberModel, err error)
+ FindRoleLevelUserIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
+ //MapGroupMemberNum(ctx context.Context, groupIDs []string) (count map[string]uint32, err error)
+ //FindJoinUserID(ctx context.Context, groupIDs []string) (groupUsers map[string][]string, err error)
FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error)
- FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error)
+ //FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error)
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
+ IsUpdateRoleLevel(data map[string]any) bool
}
diff --git a/pkg/common/db/table/relation/group_request.go b/pkg/common/db/table/relation/group_request.go
index 063b83938..39999d799 100644
--- a/pkg/common/db/table/relation/group_request.go
+++ b/pkg/common/db/table/relation/group_request.go
@@ -17,45 +17,30 @@ package relation
import (
"context"
"time"
-)
-const (
- GroupRequestModelTableName = "group_requests"
+ "github.com/OpenIMSDK/tools/pagination"
)
type GroupRequestModel struct {
- UserID string `gorm:"column:user_id;primary_key;size:64"`
- GroupID string `gorm:"column:group_id;primary_key;size:64"`
- HandleResult int32 `gorm:"column:handle_result"`
- ReqMsg string `gorm:"column:req_msg;size:1024"`
- HandledMsg string `gorm:"column:handle_msg;size:1024"`
- ReqTime time.Time `gorm:"column:req_time"`
- HandleUserID string `gorm:"column:handle_user_id;size:64"`
- HandledTime time.Time `gorm:"column:handle_time"`
- JoinSource int32 `gorm:"column:join_source"`
- InviterUserID string `gorm:"column:inviter_user_id;size:64"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (GroupRequestModel) TableName() string {
- return GroupRequestModelTableName
+ UserID string `bson:"user_id"`
+ GroupID string `bson:"group_id"`
+ HandleResult int32 `bson:"handle_result"`
+ ReqMsg string `bson:"req_msg"`
+ HandledMsg string `bson:"handled_msg"`
+ ReqTime time.Time `bson:"req_time"`
+ HandleUserID string `bson:"handle_user_id"`
+ HandledTime time.Time `bson:"handled_time"`
+ JoinSource int32 `bson:"join_source"`
+ InviterUserID string `bson:"inviter_user_id"`
+ Ex string `bson:"ex"`
}
type GroupRequestModelInterface interface {
- NewTx(tx any) GroupRequestModelInterface
Create(ctx context.Context, groupRequests []*GroupRequestModel) (err error)
Delete(ctx context.Context, groupID string, userID string) (err error)
UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
Take(ctx context.Context, groupID string, userID string) (groupRequest *GroupRequestModel, err error)
- FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*GroupRequestModel, error)
- Page(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
- ) (total uint32, groups []*GroupRequestModel, err error)
- PageGroup(
- ctx context.Context,
- groupIDs []string,
- pageNumber, showNumber int32,
- ) (total uint32, groups []*GroupRequestModel, err error)
+ FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*GroupRequestModel, error)
+ Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*GroupRequestModel, err error)
+ PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*GroupRequestModel, err error)
}
diff --git a/pkg/common/db/table/relation/log.go b/pkg/common/db/table/relation/log.go
index 72d0fa64e..f690ff8aa 100644
--- a/pkg/common/db/table/relation/log.go
+++ b/pkg/common/db/table/relation/log.go
@@ -3,23 +3,25 @@ package relation
import (
"context"
"time"
+
+ "github.com/OpenIMSDK/tools/pagination"
)
-type Log struct {
- LogID string `gorm:"column:log_id;primary_key;type:char(64)"`
- Platform string `gorm:"column:platform;type:varchar(32)"`
- UserID string `gorm:"column:user_id;type:char(64)"`
- CreateTime time.Time `gorm:"index:,sort:desc"`
- Url string `gorm:"column:url;type varchar(255)"`
- FileName string `gorm:"column:filename;type varchar(255)"`
- SystemType string `gorm:"column:system_type;type varchar(255)"`
- Version string `gorm:"column:version;type varchar(255)"`
- Ex string `gorm:"column:ex;type varchar(255)"`
+type LogModel struct {
+ LogID string `bson:"log_id"`
+ Platform string `bson:"platform"`
+ UserID string `bson:"user_id"`
+ CreateTime time.Time `bson:"create_time"`
+ Url string `bson:"url"`
+ FileName string `bson:"file_name"`
+ SystemType string `bson:"system_type"`
+ Version string `bson:"version"`
+ Ex string `bson:"ex"`
}
type LogInterface interface {
- Create(ctx context.Context, log []*Log) error
- Search(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*Log, error)
+ Create(ctx context.Context, log []*LogModel) error
+ Search(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*LogModel, error)
Delete(ctx context.Context, logID []string, userID string) error
- Get(ctx context.Context, logIDs []string, userID string) ([]*Log, error)
+ Get(ctx context.Context, logIDs []string, userID string) ([]*LogModel, error)
}
diff --git a/pkg/common/db/table/relation/object.go b/pkg/common/db/table/relation/object.go
index 0ed4130a6..678fddcfd 100644
--- a/pkg/common/db/table/relation/object.go
+++ b/pkg/common/db/table/relation/object.go
@@ -19,27 +19,20 @@ import (
"time"
)
-const (
- ObjectInfoModelTableName = "object"
-)
-
type ObjectModel struct {
- Name string `gorm:"column:name;primary_key"`
- UserID string `gorm:"column:user_id"`
- Hash string `gorm:"column:hash"`
- Key string `gorm:"column:key"`
- Size int64 `gorm:"column:size"`
- ContentType string `gorm:"column:content_type"`
- Cause string `gorm:"column:cause"`
- CreateTime time.Time `gorm:"column:create_time"`
-}
-
-func (ObjectModel) TableName() string {
- return ObjectInfoModelTableName
+ Name string `bson:"name"`
+ UserID string `bson:"user_id"`
+ Hash string `bson:"hash"`
+ Engine string `bson:"engine"`
+ Key string `bson:"key"`
+ Size int64 `bson:"size"`
+ ContentType string `bson:"content_type"`
+ Group string `bson:"group"`
+ CreateTime time.Time `bson:"create_time"`
}
type ObjectInfoModelInterface interface {
- NewTx(tx any) ObjectInfoModelInterface
SetObject(ctx context.Context, obj *ObjectModel) error
- Take(ctx context.Context, name string) (*ObjectModel, error)
+ Take(ctx context.Context, engine string, name string) (*ObjectModel, error)
+ Delete(ctx context.Context, engine string, name string) error
}
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index 10a715bda..1f26d751f 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -17,20 +17,18 @@ package relation
import (
"context"
"time"
-)
-const (
- UserModelTableName = "users"
+ "github.com/OpenIMSDK/tools/pagination"
)
type UserModel struct {
- UserID string `gorm:"column:user_id;primary_key;size:64"`
- Nickname string `gorm:"column:name;size:255"`
- FaceURL string `gorm:"column:face_url;size:255"`
- Ex string `gorm:"column:ex;size:1024"`
- CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
- AppMangerLevel int32 `gorm:"column:app_manger_level;default:1"`
- GlobalRecvMsgOpt int32 `gorm:"column:global_recv_msg_opt"`
+ UserID string `bson:"user_id"`
+ Nickname string `bson:"nickname"`
+ FaceURL string `bson:"face_url"`
+ Ex string `bson:"ex"`
+ AppMangerLevel int32 `bson:"app_manger_level"`
+ GlobalRecvMsgOpt int32 `bson:"global_recv_msg_opt"`
+ CreateTime time.Time `bson:"create_time"`
}
func (u *UserModel) GetNickname() string {
@@ -41,29 +39,22 @@ func (u *UserModel) GetFaceURL() string {
return u.FaceURL
}
-func (u *UserModel) GetUserID() string {
+func (u UserModel) GetUserID() string {
return u.UserID
}
-func (u *UserModel) GetEx() string {
+func (u UserModel) GetEx() string {
return u.Ex
}
-func (UserModel) TableName() string {
- return UserModelTableName
-}
-
type UserModelInterface interface {
Create(ctx context.Context, users []*UserModel) (err error)
- UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error)
- Update(ctx context.Context, user *UserModel) (err error)
- // 获取指定用户信息 不存在,也不返回错误
+ UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
Find(ctx context.Context, userIDs []string) (users []*UserModel, err error)
- // 获取某个用户信息 不存在,则返回错误
Take(ctx context.Context, userID string) (user *UserModel, err error)
- // 获取用户信息 不存在,不返回错误
- Page(ctx context.Context, pageNumber, showNumber int32) (users []*UserModel, count int64, err error)
- GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error)
+ Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
+ Exist(ctx context.Context, userID string) (exist bool, err error)
+ GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error)
GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
// 获取用户总数
CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
diff --git a/pkg/common/db/table/relation/utils.go b/pkg/common/db/table/relation/utils.go
index c944eae8b..380f2410e 100644
--- a/pkg/common/db/table/relation/utils.go
+++ b/pkg/common/db/table/relation/utils.go
@@ -15,9 +15,8 @@
package relation
import (
- "gorm.io/gorm"
-
"github.com/OpenIMSDK/tools/utils"
+ "go.mongodb.org/mongo-driver/mongo"
)
type BatchUpdateGroupMember struct {
@@ -32,5 +31,5 @@ type GroupSimpleUserID struct {
}
func IsNotFound(err error) bool {
- return utils.Unwrap(err) == gorm.ErrRecordNotFound
+ return utils.Unwrap(err) == mongo.ErrNoDocuments
}
diff --git a/pkg/common/db/table/unrelation/super_group.go b/pkg/common/db/table/unrelation/super_group.go
index 80c3ef9c7..1fd80c67a 100644
--- a/pkg/common/db/table/unrelation/super_group.go
+++ b/pkg/common/db/table/unrelation/super_group.go
@@ -14,40 +14,40 @@
package unrelation
-import (
- "context"
-)
-
-const (
- CSuperGroup = "super_group"
- CUserToSuperGroup = "user_to_super_group"
-)
-
-type SuperGroupModel struct {
- GroupID string `bson:"group_id" json:"groupID"`
- MemberIDs []string `bson:"member_id_list" json:"memberIDList"`
-}
-
-func (SuperGroupModel) TableName() string {
- return CSuperGroup
-}
-
-type UserToSuperGroupModel struct {
- UserID string `bson:"user_id" json:"userID"`
- GroupIDs []string `bson:"group_id_list" json:"groupIDList"`
-}
-
-func (UserToSuperGroupModel) TableName() string {
- return CUserToSuperGroup
-}
-
-type SuperGroupModelInterface interface {
- CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error
- TakeSuperGroup(ctx context.Context, groupID string) (group *SuperGroupModel, err error)
- FindSuperGroup(ctx context.Context, groupIDs []string) (groups []*SuperGroupModel, err error)
- AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error
- RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error
- GetSuperGroupByUserID(ctx context.Context, userID string) (*UserToSuperGroupModel, error)
- DeleteSuperGroup(ctx context.Context, groupID string) error
- RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error
-}
+//import (
+// "context"
+//)
+//
+//const (
+// CSuperGroup = "super_group"
+// CUserToSuperGroup = "user_to_super_group"
+//)
+//
+//type SuperGroupModel struct {
+// GroupID string `bson:"group_id" json:"groupID"`
+// MemberIDs []string `bson:"member_id_list" json:"memberIDList"`
+//}
+//
+//func (SuperGroupModel) TableName() string {
+// return CSuperGroup
+//}
+//
+//type UserToSuperGroupModel struct {
+// UserID string `bson:"user_id" json:"userID"`
+// GroupIDs []string `bson:"group_id_list" json:"groupIDList"`
+//}
+//
+//func (UserToSuperGroupModel) TableName() string {
+// return CUserToSuperGroup
+//}
+//
+//type SuperGroupModelInterface interface {
+// CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error
+// TakeSuperGroup(ctx context.Context, groupID string) (group *SuperGroupModel, err error)
+// FindSuperGroup(ctx context.Context, groupIDs []string) (groups []*SuperGroupModel, err error)
+// AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error
+// RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error
+// GetSuperGroupByUserID(ctx context.Context, userID string) (*UserToSuperGroupModel, error)
+// DeleteSuperGroup(ctx context.Context, groupID string) error
+// RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error
+//}
diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go
old mode 100755
new mode 100644
index 09e3e904e..38a335567
--- a/pkg/common/db/unrelation/mongo.go
+++ b/pkg/common/db/unrelation/mongo.go
@@ -99,16 +99,6 @@ func (m *Mongo) CreateMsgIndex() error {
return m.createMongoIndex(unrelation.Msg, true, "doc_id")
}
-func (m *Mongo) CreateSuperGroupIndex() error {
- if err := m.createMongoIndex(unrelation.CSuperGroup, true, "group_id"); err != nil {
- return err
- }
- if err := m.createMongoIndex(unrelation.CUserToSuperGroup, true, "user_id"); err != nil {
- return err
- }
- return nil
-}
-
func (m *Mongo) createMongoIndex(collection string, isUnique bool, keys ...string) error {
db := m.db.Database(config.Config.Mongo.Database).Collection(collection)
opts := options.CreateIndexes().SetMaxTime(10 * time.Second)
diff --git a/pkg/common/db/unrelation/msg.go b/pkg/common/db/unrelation/msg.go
old mode 100755
new mode 100644
diff --git a/pkg/common/db/unrelation/msg_convert.go b/pkg/common/db/unrelation/msg_convert.go
index 810b4f419..373bc843e 100644
--- a/pkg/common/db/unrelation/msg_convert.go
+++ b/pkg/common/db/unrelation/msg_convert.go
@@ -48,7 +48,7 @@ func (m *MsgMongoDriver) ConvertMsgsDocLen(ctx context.Context, conversationIDs
log.ZError(ctx, "convertAll delete many failed", err, "conversationID", conversationID)
continue
}
- var newMsgDocs []interface{}
+ var newMsgDocs []any
for _, msgDoc := range msgDocs {
if int64(len(msgDoc.Msg)) == m.model.GetSingleGocMsgNum() {
continue
diff --git a/pkg/common/db/unrelation/super_group.go b/pkg/common/db/unrelation/super_group.go
index c762140a2..6c2bb6aaf 100644
--- a/pkg/common/db/unrelation/super_group.go
+++ b/pkg/common/db/unrelation/super_group.go
@@ -14,149 +14,150 @@
package unrelation
-import (
- "context"
-
- "go.mongodb.org/mongo-driver/bson"
- "go.mongodb.org/mongo-driver/mongo"
- "go.mongodb.org/mongo-driver/mongo/options"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
-)
-
-func NewSuperGroupMongoDriver(database *mongo.Database) unrelation.SuperGroupModelInterface {
- return &SuperGroupMongoDriver{
- superGroupCollection: database.Collection(unrelation.CSuperGroup),
- userToSuperGroupCollection: database.Collection(unrelation.CUserToSuperGroup),
- }
-}
-
-type SuperGroupMongoDriver struct {
- superGroupCollection *mongo.Collection
- userToSuperGroupCollection *mongo.Collection
-}
-
-func (s *SuperGroupMongoDriver) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error {
- _, err := s.superGroupCollection.InsertOne(ctx, &unrelation.SuperGroupModel{
- GroupID: groupID,
- MemberIDs: initMemberIDs,
- })
- if err != nil {
- return err
- }
- for _, userID := range initMemberIDs {
- _, err = s.userToSuperGroupCollection.UpdateOne(
- ctx,
- bson.M{"user_id": userID},
- bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
- &options.UpdateOptions{
- Upsert: utils.ToPtr(true),
- },
- )
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-func (s *SuperGroupMongoDriver) TakeSuperGroup(
- ctx context.Context,
- groupID string,
-) (group *unrelation.SuperGroupModel, err error) {
- if err := s.superGroupCollection.FindOne(ctx, bson.M{"group_id": groupID}).Decode(&group); err != nil {
- return nil, utils.Wrap(err, "")
- }
- return group, nil
-}
-
-func (s *SuperGroupMongoDriver) FindSuperGroup(
- ctx context.Context,
- groupIDs []string,
-) (groups []*unrelation.SuperGroupModel, err error) {
- cursor, err := s.superGroupCollection.Find(ctx, bson.M{"group_id": bson.M{
- "$in": groupIDs,
- }})
- if err != nil {
- return nil, err
- }
- defer cursor.Close(ctx)
- if err := cursor.All(ctx, &groups); err != nil {
- return nil, utils.Wrap(err, "")
- }
- return groups, nil
-}
-
-func (s *SuperGroupMongoDriver) AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
- _, err := s.superGroupCollection.UpdateOne(
- ctx,
- bson.M{"group_id": groupID},
- bson.M{"$addToSet": bson.M{"member_id_list": bson.M{"$each": userIDs}}},
- )
- if err != nil {
- return err
- }
- upsert := true
- opts := &options.UpdateOptions{
- Upsert: &upsert,
- }
- for _, userID := range userIDs {
- _, err = s.userToSuperGroupCollection.UpdateOne(
- ctx,
- bson.M{"user_id": userID},
- bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
- opts,
- )
- if err != nil {
- return utils.Wrap(err, "transaction failed")
- }
- }
- return nil
-}
-
-func (s *SuperGroupMongoDriver) RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
- _, err := s.superGroupCollection.UpdateOne(
- ctx,
- bson.M{"group_id": groupID},
- bson.M{"$pull": bson.M{"member_id_list": bson.M{"$in": userIDs}}},
- )
- if err != nil {
- return err
- }
- err = s.RemoveGroupFromUser(ctx, groupID, userIDs)
- if err != nil {
- return err
- }
- return nil
-}
-
-func (s *SuperGroupMongoDriver) GetSuperGroupByUserID(
- ctx context.Context,
- userID string,
-) (*unrelation.UserToSuperGroupModel, error) {
- var user unrelation.UserToSuperGroupModel
- err := s.userToSuperGroupCollection.FindOne(ctx, bson.M{"user_id": userID}).Decode(&user)
- return &user, utils.Wrap(err, "")
-}
-
-func (s *SuperGroupMongoDriver) DeleteSuperGroup(ctx context.Context, groupID string) error {
- group, err := s.TakeSuperGroup(ctx, groupID)
- if err != nil {
- return err
- }
- if _, err := s.superGroupCollection.DeleteOne(ctx, bson.M{"group_id": groupID}); err != nil {
- return utils.Wrap(err, "")
- }
- return s.RemoveGroupFromUser(ctx, groupID, group.MemberIDs)
-}
-
-func (s *SuperGroupMongoDriver) RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error {
- _, err := s.userToSuperGroupCollection.UpdateOne(
- ctx,
- bson.M{"user_id": bson.M{"$in": userIDs}},
- bson.M{"$pull": bson.M{"group_id_list": groupID}},
- )
- return utils.Wrap(err, "")
-}
+//
+//import (
+// "context"
+//
+// "go.mongodb.org/mongo-driver/bson"
+// "go.mongodb.org/mongo-driver/mongo"
+// "go.mongodb.org/mongo-driver/mongo/options"
+//
+// "github.com/OpenIMSDK/tools/utils"
+//
+// "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
+//)
+//
+//func NewSuperGroupMongoDriver(database *mongo.Database) unrelation.SuperGroupModelInterface {
+// return &SuperGroupMongoDriver{
+// superGroupCollection: database.Collection(unrelation.CSuperGroup),
+// userToSuperGroupCollection: database.Collection(unrelation.CUserToSuperGroup),
+// }
+//}
+//
+//type SuperGroupMongoDriver struct {
+// superGroupCollection *mongo.Collection
+// userToSuperGroupCollection *mongo.Collection
+//}
+//
+//func (s *SuperGroupMongoDriver) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error {
+// _, err := s.superGroupCollection.InsertOne(ctx, &unrelation.SuperGroupModel{
+// GroupID: groupID,
+// MemberIDs: initMemberIDs,
+// })
+// if err != nil {
+// return err
+// }
+// for _, userID := range initMemberIDs {
+// _, err = s.userToSuperGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"user_id": userID},
+// bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
+// &options.UpdateOptions{
+// Upsert: utils.ToPtr(true),
+// },
+// )
+// if err != nil {
+// return err
+// }
+// }
+// return nil
+//}
+//
+//func (s *SuperGroupMongoDriver) TakeSuperGroup(
+// ctx context.Context,
+// groupID string,
+//) (group *unrelation.SuperGroupModel, err error) {
+// if err := s.superGroupCollection.FindOne(ctx, bson.M{"group_id": groupID}).Decode(&group); err != nil {
+// return nil, utils.Wrap(err, "")
+// }
+// return group, nil
+//}
+//
+//func (s *SuperGroupMongoDriver) FindSuperGroup(
+// ctx context.Context,
+// groupIDs []string,
+//) (groups []*unrelation.SuperGroupModel, err error) {
+// cursor, err := s.superGroupCollection.Find(ctx, bson.M{"group_id": bson.M{
+// "$in": groupIDs,
+// }})
+// if err != nil {
+// return nil, err
+// }
+// defer cursor.Close(ctx)
+// if err := cursor.All(ctx, &groups); err != nil {
+// return nil, utils.Wrap(err, "")
+// }
+// return groups, nil
+//}
+//
+//func (s *SuperGroupMongoDriver) AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
+// _, err := s.superGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"group_id": groupID},
+// bson.M{"$addToSet": bson.M{"member_id_list": bson.M{"$each": userIDs}}},
+// )
+// if err != nil {
+// return err
+// }
+// upsert := true
+// opts := &options.UpdateOptions{
+// Upsert: &upsert,
+// }
+// for _, userID := range userIDs {
+// _, err = s.userToSuperGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"user_id": userID},
+// bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
+// opts,
+// )
+// if err != nil {
+// return utils.Wrap(err, "transaction failed")
+// }
+// }
+// return nil
+//}
+//
+//func (s *SuperGroupMongoDriver) RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
+// _, err := s.superGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"group_id": groupID},
+// bson.M{"$pull": bson.M{"member_id_list": bson.M{"$in": userIDs}}},
+// )
+// if err != nil {
+// return err
+// }
+// err = s.RemoveGroupFromUser(ctx, groupID, userIDs)
+// if err != nil {
+// return err
+// }
+// return nil
+//}
+//
+//func (s *SuperGroupMongoDriver) GetSuperGroupByUserID(
+// ctx context.Context,
+// userID string,
+//) (*unrelation.UserToSuperGroupModel, error) {
+// var user unrelation.UserToSuperGroupModel
+// err := s.userToSuperGroupCollection.FindOne(ctx, bson.M{"user_id": userID}).Decode(&user)
+// return &user, utils.Wrap(err, "")
+//}
+//
+//func (s *SuperGroupMongoDriver) DeleteSuperGroup(ctx context.Context, groupID string) error {
+// group, err := s.TakeSuperGroup(ctx, groupID)
+// if err != nil {
+// return err
+// }
+// if _, err := s.superGroupCollection.DeleteOne(ctx, bson.M{"group_id": groupID}); err != nil {
+// return utils.Wrap(err, "")
+// }
+// return s.RemoveGroupFromUser(ctx, groupID, group.MemberIDs)
+//}
+//
+//func (s *SuperGroupMongoDriver) RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error {
+// _, err := s.userToSuperGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"user_id": bson.M{"$in": userIDs}},
+// bson.M{"$pull": bson.M{"group_id_list": groupID}},
+// )
+// return utils.Wrap(err, "")
+//}
diff --git a/pkg/common/db/unrelation/user.go b/pkg/common/db/unrelation/user.go
old mode 100755
new mode 100644
diff --git a/pkg/common/http/http_client.go b/pkg/common/http/http_client.go
index f0fde3099..e1bc83d38 100644
--- a/pkg/common/http/http_client.go
+++ b/pkg/common/http/http_client.go
@@ -57,7 +57,7 @@ func Get(url string) (response []byte, err error) {
return body, nil
}
-func Post(ctx context.Context, url string, header map[string]string, data interface{}, timeout int) (content []byte, err error) {
+func Post(ctx context.Context, url string, header map[string]string, data any, timeout int) (content []byte, err error) {
if timeout > 0 {
var cancel func()
ctx, cancel = context.WithTimeout(ctx, time.Second*time.Duration(timeout))
@@ -96,7 +96,7 @@ func Post(ctx context.Context, url string, header map[string]string, data interf
return result, nil
}
-func PostReturn(ctx context.Context, url string, header map[string]string, input, output interface{}, timeOutSecond int) error {
+func PostReturn(ctx context.Context, url string, header map[string]string, input, output any, timeOutSecond int) error {
b, err := Post(ctx, url, header, input, timeOutSecond)
if err != nil {
return err
diff --git a/pkg/common/http/http_client_test.go b/pkg/common/http/http_client_test.go
index 1735a3da7..5d2588673 100644
--- a/pkg/common/http/http_client_test.go
+++ b/pkg/common/http/http_client_test.go
@@ -54,7 +54,7 @@ func TestPost(t *testing.T) {
ctx context.Context
url string
header map[string]string
- data interface{}
+ data any
timeout int
}
tests := []struct {
@@ -84,8 +84,8 @@ func TestPostReturn(t *testing.T) {
ctx context.Context
url string
header map[string]string
- input interface{}
- output interface{}
+ input any
+ output any
timeOutSecond int
}
tests := []struct {
@@ -109,7 +109,7 @@ func Test_callBackPostReturn(t *testing.T) {
ctx context.Context
url string
command string
- input interface{}
+ input any
output callbackstruct.CallbackResp
callbackConfig config.CallBackConfig
}
diff --git a/pkg/rpcclient/grouphash/grouphash.go b/pkg/rpcclient/grouphash/grouphash.go
new file mode 100644
index 000000000..b5570dccd
--- /dev/null
+++ b/pkg/rpcclient/grouphash/grouphash.go
@@ -0,0 +1,88 @@
+package grouphash
+
+import (
+ "context"
+ "crypto/md5"
+ "encoding/binary"
+ "encoding/json"
+
+ "github.com/OpenIMSDK/protocol/group"
+ "github.com/OpenIMSDK/protocol/sdkws"
+ "github.com/OpenIMSDK/tools/utils"
+)
+
+func NewGroupHashFromGroupClient(x group.GroupClient) *GroupHash {
+ return &GroupHash{
+ getGroupAllUserIDs: func(ctx context.Context, groupID string) ([]string, error) {
+ resp, err := x.GetGroupMemberUserIDs(ctx, &group.GetGroupMemberUserIDsReq{GroupID: groupID})
+ if err != nil {
+ return nil, err
+ }
+ return resp.UserIDs, nil
+ },
+ getGroupMemberInfo: func(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
+ resp, err := x.GetGroupMembersInfo(ctx, &group.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs})
+ if err != nil {
+ return nil, err
+ }
+ return resp.Members, nil
+ },
+ }
+}
+
+func NewGroupHashFromGroupServer(x group.GroupServer) *GroupHash {
+ return &GroupHash{
+ getGroupAllUserIDs: func(ctx context.Context, groupID string) ([]string, error) {
+ resp, err := x.GetGroupMemberUserIDs(ctx, &group.GetGroupMemberUserIDsReq{GroupID: groupID})
+ if err != nil {
+ return nil, err
+ }
+ return resp.UserIDs, nil
+ },
+ getGroupMemberInfo: func(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
+ resp, err := x.GetGroupMembersInfo(ctx, &group.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs})
+ if err != nil {
+ return nil, err
+ }
+ return resp.Members, nil
+ },
+ }
+}
+
+type GroupHash struct {
+ getGroupAllUserIDs func(ctx context.Context, groupID string) ([]string, error)
+ getGroupMemberInfo func(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error)
+}
+
+func (gh *GroupHash) GetGroupHash(ctx context.Context, groupID string) (uint64, error) {
+ userIDs, err := gh.getGroupAllUserIDs(ctx, groupID)
+ if err != nil {
+ return 0, err
+ }
+ var members []*sdkws.GroupMemberFullInfo
+ if len(userIDs) > 0 {
+ members, err = gh.getGroupMemberInfo(ctx, groupID, userIDs)
+ if err != nil {
+ return 0, err
+ }
+ utils.Sort(userIDs, true)
+ }
+ memberMap := utils.SliceToMap(members, func(e *sdkws.GroupMemberFullInfo) string {
+ return e.UserID
+ })
+ res := make([]*sdkws.GroupMemberFullInfo, 0, len(members))
+ for _, userID := range userIDs {
+ member, ok := memberMap[userID]
+ if !ok {
+ continue
+ }
+ member.AppMangerLevel = 0
+ res = append(res, member)
+ }
+ data, err := json.Marshal(res)
+ if err != nil {
+ return 0, err
+ }
+ sum := md5.Sum(data)
+ return binary.BigEndian.Uint64(sum[:]), nil
+}
diff --git a/pkg/rpcclient/notification/group.go b/pkg/rpcclient/notification/group.go
index 8e71f61c3..cbae7c49b 100755
--- a/pkg/rpcclient/notification/group.go
+++ b/pkg/rpcclient/notification/group.go
@@ -52,6 +52,41 @@ type GroupNotificationSender struct {
db controller.GroupDatabase
}
+func (g *GroupNotificationSender) PopulateGroupMember(ctx context.Context, members ...*relation.GroupMemberModel) error {
+ if len(members) == 0 {
+ return nil
+ }
+ emptyUserIDs := make(map[string]struct{})
+ for _, member := range members {
+ if member.Nickname == "" || member.FaceURL == "" {
+ emptyUserIDs[member.UserID] = struct{}{}
+ }
+ }
+ if len(emptyUserIDs) > 0 {
+ users, err := g.getUsersInfo(ctx, utils.Keys(emptyUserIDs))
+ if err != nil {
+ return err
+ }
+ userMap := make(map[string]CommonUser)
+ for i, user := range users {
+ userMap[user.GetUserID()] = users[i]
+ }
+ for i, member := range members {
+ user, ok := userMap[member.UserID]
+ if !ok {
+ continue
+ }
+ if member.Nickname == "" {
+ members[i].Nickname = user.GetNickname()
+ }
+ if member.FaceURL == "" {
+ members[i].FaceURL = user.GetFaceURL()
+ }
+ }
+ }
+ return nil
+}
+
func (g *GroupNotificationSender) getUser(ctx context.Context, userID string) (*sdkws.PublicUserInfo, error) {
users, err := g.getUsersInfo(ctx, []string{userID})
if err != nil {
@@ -77,17 +112,21 @@ func (g *GroupNotificationSender) getGroupInfo(ctx context.Context, groupID stri
if err != nil {
return nil, err
}
- owner, err := g.db.TakeGroupOwner(ctx, groupID)
+ ownerUserIDs, err := g.db.GetGroupRoleLevelMemberIDs(ctx, groupID, constant.GroupOwner)
if err != nil {
return nil, err
}
+ var ownerUserID string
+ if len(ownerUserIDs) > 0 {
+ ownerUserID = ownerUserIDs[0]
+ }
return &sdkws.GroupInfo{
GroupID: gm.GroupID,
GroupName: gm.GroupName,
Notification: gm.Notification,
Introduction: gm.Introduction,
FaceURL: gm.FaceURL,
- OwnerUserID: owner.UserID,
+ OwnerUserID: ownerUserID,
CreateTime: gm.CreateTime.UnixMilli(),
MemberCount: num,
Ex: gm.Ex,
@@ -103,39 +142,18 @@ func (g *GroupNotificationSender) getGroupInfo(ctx context.Context, groupID stri
}
func (g *GroupNotificationSender) getGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
- members, err := g.db.FindGroupMember(ctx, []string{groupID}, userIDs, nil)
+ members, err := g.db.FindGroupMembers(ctx, groupID, userIDs)
if err != nil {
return nil, err
}
- log.ZDebug(ctx, "getGroupMembers", "members", members)
- users, err := g.getUsersInfoMap(ctx, userIDs)
- if err != nil {
+ if err := g.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
- log.ZDebug(ctx, "getUsersInfoMap", "users", users)
+ log.ZDebug(ctx, "getGroupMembers", "members", members)
res := make([]*sdkws.GroupMemberFullInfo, 0, len(members))
for _, member := range members {
- user, ok := users[member.UserID]
- if !ok {
- return nil, errs.ErrUserIDNotFound.Wrap(fmt.Sprintf("group %s member %s not in user", member.GroupID, member.UserID))
- }
- if member.Nickname == "" {
- member.Nickname = user.Nickname
- }
- res = append(res, g.groupMemberDB2PB(member, user.AppMangerLevel))
- delete(users, member.UserID)
- }
- //for userID, info := range users {
- // if info.AppMangerLevel == constant.AppAdmin {
- // res = append(res, &sdkws.GroupMemberFullInfo{
- // GroupID: groupID,
- // UserID: userID,
- // Nickname: info.Nickname,
- // FaceURL: info.FaceURL,
- // AppMangerLevel: info.AppMangerLevel,
- // })
- // }
- //}
+ res = append(res, g.groupMemberDB2PB(member, 0))
+ }
return res, nil
}
@@ -163,10 +181,13 @@ func (g *GroupNotificationSender) getGroupMember(ctx context.Context, groupID st
}
func (g *GroupNotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, groupID string) ([]string, error) {
- members, err := g.db.FindGroupMember(ctx, []string{groupID}, nil, []int32{constant.GroupOwner, constant.GroupAdmin})
+ members, err := g.db.FindGroupMemberRoleLevels(ctx, groupID, []int32{constant.GroupOwner, constant.GroupAdmin})
if err != nil {
return nil, err
}
+ if err := g.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
fn := func(e *relation.GroupMemberModel) string { return e.UserID }
return utils.Slice(members, fn), nil
}
diff --git a/scripts/install/openim-tools.sh b/scripts/install/openim-tools.sh
index fd95dc00d..f97b9d836 100755
--- a/scripts/install/openim-tools.sh
+++ b/scripts/install/openim-tools.sh
@@ -61,6 +61,7 @@ openim::tools::pre_start_name() {
local targets=(
ncpu
component
+ up35
)
echo "${targets[@]}"
}
diff --git a/test/e2e/api/token/token.go b/test/e2e/api/token/token.go
index 679c0bbda..4c578e8f7 100644
--- a/test/e2e/api/token/token.go
+++ b/test/e2e/api/token/token.go
@@ -125,7 +125,7 @@ func RegisterUser(token, userID, nickname, faceURL string) error {
return err
}
- var respData map[string]interface{}
+ var respData map[string]any
if err := json.Unmarshal(respBody, &respData); err != nil {
return err
}
diff --git a/test/e2e/api/user/user.go b/test/e2e/api/user/user.go
index 66419b735..9facf76ac 100644
--- a/test/e2e/api/user/user.go
+++ b/test/e2e/api/user/user.go
@@ -71,7 +71,7 @@ func GetUsers(token string, pageNumber, showNumber int) error {
}
// sendPostRequestWithToken sends a POST request with a token in the header
-func sendPostRequestWithToken(url, token string, body interface{}) error {
+func sendPostRequestWithToken(url, token string, body any) error {
reqBytes, err := json.Marshal(body)
if err != nil {
return err
@@ -98,7 +98,7 @@ func sendPostRequestWithToken(url, token string, body interface{}) error {
return err
}
- var respData map[string]interface{}
+ var respData map[string]any
if err := json.Unmarshal(respBody, &respData); err != nil {
return err
}
diff --git a/test/jwt/main.go b/test/jwt/main.go
index a669df9d6..0ef845237 100644
--- a/test/jwt/main.go
+++ b/test/jwt/main.go
@@ -25,7 +25,7 @@ func main() {
// Verify the token
claims := &jwt.MapClaims{}
- parsedT, err := jwt.ParseWithClaims(rawJWT, claims, func(token *jwt.Token) (interface{}, error) {
+ parsedT, err := jwt.ParseWithClaims(rawJWT, claims, func(token *jwt.Token) (any, error) {
// Validate the alg is HMAC signature
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
diff --git a/test/typecheck/typecheck.go b/test/typecheck/typecheck.go
index 0fc33597b..83e3c63ed 100644
--- a/test/typecheck/typecheck.go
+++ b/test/typecheck/typecheck.go
@@ -239,7 +239,7 @@ func dedup(errors []packages.Error) []string {
var outMu sync.Mutex
-func serialFprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
+func serialFprintf(w io.Writer, format string, a ...any) (n int, err error) {
outMu.Lock()
defer outMu.Unlock()
return fmt.Fprintf(w, format, a...)
diff --git a/tools/component/component.go b/tools/component/component.go
index 4e44bb7ba..140313c30 100644
--- a/tools/component/component.go
+++ b/tools/component/component.go
@@ -84,7 +84,7 @@ func main() {
}
checks := []checkFunc{
- {name: "Mysql", function: checkMysql},
+ //{name: "Mysql", function: checkMysql},
{name: "Mongo", function: checkMongo},
{name: "Minio", function: checkMinio},
{name: "Redis", function: checkRedis},
@@ -133,6 +133,9 @@ func exactIP(urll string) string {
}
func checkMysql() error {
+ if config.Config.Mysql == nil {
+ return nil
+ }
var sqlDB *sql.DB
defer func() {
if sqlDB != nil {
diff --git a/tools/component/component_test.go b/tools/component/component_test.go
index afa51ef2c..08ea0fda8 100644
--- a/tools/component/component_test.go
+++ b/tools/component/component_test.go
@@ -15,8 +15,12 @@
package main
import (
+ "context"
+ "strconv"
"testing"
+ "time"
+ "github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
@@ -40,3 +44,43 @@ func mockInitCfg() error {
config.Config.Mysql.Address = []string{"127.0.0.1:13306"}
return nil
}
+
+func TestRedis(t *testing.T) {
+ config.Config.Redis.Address = []string{
+ "172.16.8.142:7000",
+ //"172.16.8.142:7000", "172.16.8.142:7001", "172.16.8.142:7002", "172.16.8.142:7003", "172.16.8.142:7004", "172.16.8.142:7005",
+ }
+
+ 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 {
+ t.Fatal(err)
+ }
+
+ for i := 0; i < 1000000; i++ {
+ val, err := redisClient.Set(context.Background(), "b_"+strconv.Itoa(i), "test", time.Second*10).Result()
+ t.Log("index", i, "resp", val, "err", err)
+ if err != nil {
+ return
+ }
+ }
+
+}
diff --git a/tools/data-conversion/README.md b/tools/data-conversion/README.md
index 8d1bf8629..22126e4d8 100644
--- a/tools/data-conversion/README.md
+++ b/tools/data-conversion/README.md
@@ -13,8 +13,8 @@
### 2. 迁移 OpenIM MySQL 数据
-+ 位置: `open-im-server/v3/tools/data-conversion/openim/mysql.go`
-+ 配置 `mysql.go` 文件中的数据库信息。
++ 位置: `open-im-server/tools/data-conversion/openim/cmd/conversion-mysql.go`
++ 配置 `conversion-mysql.go` 文件中的数据库信息。
+ 手动创建 V3 版本的数据库,并确保字符集为 `utf8mb4`。
```bash
@@ -47,7 +47,7 @@ make build BINS="conversion-mysql"
### 3. 转换聊天消息(可选)
+ 只支持转换存储在 Kafka 中的消息。
-+ 位置: `open-im-server/v3/tools/data-conversion/openim/msg.go`
++ 位置: `open-im-server/tools/data-conversion/openim/conversion-msg/conversion-msg.go`
+ 配置 `msg.go` 文件中的消息和服务器信息。
```bash
@@ -69,7 +69,7 @@ make build BINS="conversion-msg"
### 4. 转换业务服务器数据
+ 只支持转换存储在 Kafka 中的消息。
-+ 位置: `open-im-server/v3/tools/data-conversion/chat/chat.go`
++ 位置: `open-im-server/tools/data-conversion/chat/cmd/conversion-chat/chat.go`
+ 需要手动创建 V3 版本的数据库,并确保字符集为 `utf8mb4`。
+ 配置 `main.go` 文件中的数据库信息。
diff --git a/tools/data-conversion/openim/mysql/conversion/conversion.go b/tools/data-conversion/openim/mysql/conversion/conversion.go
index 298eefb50..54cf90edf 100644
--- a/tools/data-conversion/openim/mysql/conversion/conversion.go
+++ b/tools/data-conversion/openim/mysql/conversion/conversion.go
@@ -3,8 +3,8 @@ package conversion
import (
"github.com/OpenIMSDK/protocol/constant"
- v3 "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
v2 "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v2"
+ v3 "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
"github.com/openimsdk/open-im-server/v3/tools/data-conversion/utils"
)
diff --git a/tools/data-conversion/openim/mysql/v3/black.go b/tools/data-conversion/openim/mysql/v3/black.go
new file mode 100644
index 000000000..59dd12122
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/black.go
@@ -0,0 +1,49 @@
+// 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 relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ BlackModelTableName = "blacks"
+)
+
+type BlackModel struct {
+ OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
+ BlockUserID string `gorm:"column:block_user_id;primary_key;size:64"`
+ CreateTime time.Time `gorm:"column:create_time"`
+ AddSource int32 `gorm:"column:add_source"`
+ OperatorUserID string `gorm:"column:operator_user_id;size:64"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (BlackModel) TableName() string {
+ return BlackModelTableName
+}
+
+type BlackModelInterface interface {
+ Create(ctx context.Context, blacks []*BlackModel) (err error)
+ Delete(ctx context.Context, blacks []*BlackModel) (err error)
+ UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]interface{}) (err error)
+ Update(ctx context.Context, blacks []*BlackModel) (err error)
+ Find(ctx context.Context, blacks []*BlackModel) (blackList []*BlackModel, err error)
+ Take(ctx context.Context, ownerUserID, blockUserID string) (black *BlackModel, err error)
+ FindOwnerBlacks(ctx context.Context, ownerUserID string, pageNumber, showNumber int32) (blacks []*BlackModel, total int64, err error)
+ FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*BlackModel, err error)
+ FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error)
+}
diff --git a/pkg/common/db/table/relation/chatlog.go b/tools/data-conversion/openim/mysql/v3/chatlog.go
similarity index 100%
rename from pkg/common/db/table/relation/chatlog.go
rename to tools/data-conversion/openim/mysql/v3/chatlog.go
diff --git a/tools/data-conversion/openim/mysql/v3/conversation.go b/tools/data-conversion/openim/mysql/v3/conversation.go
new file mode 100644
index 000000000..e9680873f
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/conversation.go
@@ -0,0 +1,73 @@
+// 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 relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ conversationModelTableName = "conversations"
+)
+
+type ConversationModel struct {
+ OwnerUserID string `gorm:"column:owner_user_id;primary_key;type:char(128)" json:"OwnerUserID"`
+ ConversationID string `gorm:"column:conversation_id;primary_key;type:char(128)" json:"conversationID"`
+ ConversationType int32 `gorm:"column:conversation_type" json:"conversationType"`
+ UserID string `gorm:"column:user_id;type:char(64)" json:"userID"`
+ GroupID string `gorm:"column:group_id;type:char(128)" json:"groupID"`
+ RecvMsgOpt int32 `gorm:"column:recv_msg_opt" json:"recvMsgOpt"`
+ IsPinned bool `gorm:"column:is_pinned" json:"isPinned"`
+ IsPrivateChat bool `gorm:"column:is_private_chat" json:"isPrivateChat"`
+ BurnDuration int32 `gorm:"column:burn_duration;default:30" json:"burnDuration"`
+ GroupAtType int32 `gorm:"column:group_at_type" json:"groupAtType"`
+ AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
+ Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
+ MaxSeq int64 `gorm:"column:max_seq" json:"maxSeq"`
+ MinSeq int64 `gorm:"column:min_seq" json:"minSeq"`
+ CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
+ IsMsgDestruct bool `gorm:"column:is_msg_destruct;default:false"`
+ MsgDestructTime int64 `gorm:"column:msg_destruct_time;default:604800"`
+ LatestMsgDestructTime time.Time `gorm:"column:latest_msg_destruct_time;autoCreateTime"`
+}
+
+func (ConversationModel) TableName() string {
+ return conversationModelTableName
+}
+
+type ConversationModelInterface interface {
+ Create(ctx context.Context, conversations []*ConversationModel) (err error)
+ Delete(ctx context.Context, groupIDs []string) (err error)
+ UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) (rows int64, err error)
+ Update(ctx context.Context, conversation *ConversationModel) (err error)
+ Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*ConversationModel, err error)
+ FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error)
+ FindUserIDAllConversationID(ctx context.Context, userID string) ([]string, error)
+ Take(ctx context.Context, userID, conversationID string) (conversation *ConversationModel, err error)
+ FindConversationID(ctx context.Context, userID string, conversationIDs []string) (existConversationID []string, err error)
+ FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*ConversationModel, err error)
+ FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
+ GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
+ FindSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
+ GetAllConversationIDs(ctx context.Context) ([]string, error)
+ GetAllConversationIDsNumber(ctx context.Context) (int64, error)
+ PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error)
+ GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (hashReadSeqs map[string]int64, err error)
+ GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*ConversationModel, error)
+ GetConversationIDsNeedDestruct(ctx context.Context) ([]*ConversationModel, error)
+ GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
+ NewTx(tx any) ConversationModelInterface
+}
diff --git a/pkg/common/db/table/relation/doc.go b/tools/data-conversion/openim/mysql/v3/doc.go
similarity index 100%
rename from pkg/common/db/table/relation/doc.go
rename to tools/data-conversion/openim/mysql/v3/doc.go
diff --git a/tools/data-conversion/openim/mysql/v3/friend.go b/tools/data-conversion/openim/mysql/v3/friend.go
new file mode 100644
index 000000000..58d8d1d34
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/friend.go
@@ -0,0 +1,78 @@
+// 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 relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ FriendModelTableName = "friends"
+)
+
+type FriendModel struct {
+ OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
+ FriendUserID string `gorm:"column:friend_user_id;primary_key;size:64"`
+ Remark string `gorm:"column:remark;size:255"`
+ CreateTime time.Time `gorm:"column:create_time;autoCreateTime"`
+ AddSource int32 `gorm:"column:add_source"`
+ OperatorUserID string `gorm:"column:operator_user_id;size:64"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (FriendModel) TableName() string {
+ return FriendModelTableName
+}
+
+type FriendModelInterface interface {
+ // 插入多条记录
+ Create(ctx context.Context, friends []*FriendModel) (err error)
+ // 删除ownerUserID指定的好友
+ Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
+ // 更新ownerUserID单个好友信息 更新零值
+ UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) (err error)
+ // 更新好友信息的非零值
+ Update(ctx context.Context, friends []*FriendModel) (err error)
+ // 更新好友备注(也支持零值 )
+ UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
+ // 获取单个好友信息,如没找到 返回错误
+ Take(ctx context.Context, ownerUserID, friendUserID string) (friend *FriendModel, err error)
+ // 查找好友关系,如果是双向关系,则都返回
+ FindUserState(ctx context.Context, userID1, userID2 string) (friends []*FriendModel, err error)
+ // 获取 owner指定的好友列表 如果有friendUserIDs不存在,也不返回错误
+ FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*FriendModel, err error)
+ // 获取哪些人添加了friendUserID 如果有ownerUserIDs不存在,也不返回错误
+ FindReversalFriends(
+ ctx context.Context,
+ friendUserID string,
+ ownerUserIDs []string,
+ ) (friends []*FriendModel, err error)
+ // 获取ownerUserID好友列表 支持翻页
+ FindOwnerFriends(
+ ctx context.Context,
+ ownerUserID string,
+ pageNumber, showNumber int32,
+ ) (friends []*FriendModel, total int64, err error)
+ // 获取哪些人添加了friendUserID 支持翻页
+ FindInWhoseFriends(
+ ctx context.Context,
+ friendUserID string,
+ pageNumber, showNumber int32,
+ ) (friends []*FriendModel, total int64, err error)
+ // 获取好友UserID列表
+ FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
+ NewTx(tx any) FriendModelInterface
+}
diff --git a/tools/data-conversion/openim/mysql/v3/friend_request.go b/tools/data-conversion/openim/mysql/v3/friend_request.go
new file mode 100644
index 000000000..51ea0ef6e
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/friend_request.go
@@ -0,0 +1,66 @@
+// 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 relation
+
+import (
+ "context"
+ "time"
+)
+
+const FriendRequestModelTableName = "friend_requests"
+
+type FriendRequestModel struct {
+ FromUserID string `gorm:"column:from_user_id;primary_key;size:64"`
+ ToUserID string `gorm:"column:to_user_id;primary_key;size:64"`
+ HandleResult int32 `gorm:"column:handle_result"`
+ ReqMsg string `gorm:"column:req_msg;size:255"`
+ CreateTime time.Time `gorm:"column:create_time; autoCreateTime"`
+ HandlerUserID string `gorm:"column:handler_user_id;size:64"`
+ HandleMsg string `gorm:"column:handle_msg;size:255"`
+ HandleTime time.Time `gorm:"column:handle_time"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (FriendRequestModel) TableName() string {
+ return FriendRequestModelTableName
+}
+
+type FriendRequestModelInterface interface {
+ // 插入多条记录
+ Create(ctx context.Context, friendRequests []*FriendRequestModel) (err error)
+ // 删除记录
+ Delete(ctx context.Context, fromUserID, toUserID string) (err error)
+ // 更新零值
+ UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]interface{}) (err error)
+ // 更新多条记录 (非零值)
+ Update(ctx context.Context, friendRequest *FriendRequestModel) (err error)
+ // 获取来指定用户的好友申请 未找到 不返回错误
+ Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
+ Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
+ // 获取toUserID收到的好友申请列表
+ FindToUserID(
+ ctx context.Context,
+ toUserID string,
+ pageNumber, showNumber int32,
+ ) (friendRequests []*FriendRequestModel, total int64, err error)
+ // 获取fromUserID发出去的好友申请列表
+ FindFromUserID(
+ ctx context.Context,
+ fromUserID string,
+ pageNumber, showNumber int32,
+ ) (friendRequests []*FriendRequestModel, total int64, err error)
+ FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*FriendRequestModel, err error)
+ NewTx(tx any) FriendRequestModelInterface
+}
diff --git a/tools/data-conversion/openim/mysql/v3/group.go b/tools/data-conversion/openim/mysql/v3/group.go
new file mode 100644
index 000000000..6759e0d35
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/group.go
@@ -0,0 +1,66 @@
+// 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 relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ GroupModelTableName = "groups"
+)
+
+type GroupModel struct {
+ GroupID string `gorm:"column:group_id;primary_key;size:64" json:"groupID" binding:"required"`
+ GroupName string `gorm:"column:name;size:255" json:"groupName"`
+ Notification string `gorm:"column:notification;size:255" json:"notification"`
+ Introduction string `gorm:"column:introduction;size:255" json:"introduction"`
+ FaceURL string `gorm:"column:face_url;size:255" json:"faceURL"`
+ CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
+ Ex string `gorm:"column:ex" json:"ex;size:1024"`
+ Status int32 `gorm:"column:status"`
+ CreatorUserID string `gorm:"column:creator_user_id;size:64"`
+ GroupType int32 `gorm:"column:group_type"`
+ NeedVerification int32 `gorm:"column:need_verification"`
+ LookMemberInfo int32 `gorm:"column:look_member_info" json:"lookMemberInfo"`
+ ApplyMemberFriend int32 `gorm:"column:apply_member_friend" json:"applyMemberFriend"`
+ NotificationUpdateTime time.Time `gorm:"column:notification_update_time"`
+ NotificationUserID string `gorm:"column:notification_user_id;size:64"`
+}
+
+func (GroupModel) TableName() string {
+ return GroupModelTableName
+}
+
+type GroupModelInterface interface {
+ NewTx(tx any) GroupModelInterface
+ Create(ctx context.Context, groups []*GroupModel) (err error)
+ UpdateMap(ctx context.Context, groupID string, args map[string]interface{}) (err error)
+ UpdateStatus(ctx context.Context, groupID string, status int32) (err error)
+ Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
+ FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
+ Take(ctx context.Context, groupID string) (group *GroupModel, err error)
+ Search(
+ ctx context.Context,
+ keyword string,
+ pageNumber, showNumber int32,
+ ) (total uint32, groups []*GroupModel, err error)
+ GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error)
+ // 获取群总数
+ CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
+ // 获取范围内群增量
+ CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/group_member.go b/tools/data-conversion/openim/mysql/v3/group_member.go
new file mode 100644
index 000000000..bfde72834
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/group_member.go
@@ -0,0 +1,74 @@
+// 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 relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ GroupMemberModelTableName = "group_members"
+)
+
+type GroupMemberModel struct {
+ GroupID string `gorm:"column:group_id;primary_key;size:64"`
+ UserID string `gorm:"column:user_id;primary_key;size:64"`
+ Nickname string `gorm:"column:nickname;size:255"`
+ FaceURL string `gorm:"column:user_group_face_url;size:255"`
+ RoleLevel int32 `gorm:"column:role_level"`
+ JoinTime time.Time `gorm:"column:join_time"`
+ JoinSource int32 `gorm:"column:join_source"`
+ InviterUserID string `gorm:"column:inviter_user_id;size:64"`
+ OperatorUserID string `gorm:"column:operator_user_id;size:64"`
+ MuteEndTime time.Time `gorm:"column:mute_end_time"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (GroupMemberModel) TableName() string {
+ return GroupMemberModelTableName
+}
+
+type GroupMemberModelInterface interface {
+ NewTx(tx any) GroupMemberModelInterface
+ Create(ctx context.Context, groupMembers []*GroupMemberModel) (err error)
+ Delete(ctx context.Context, groupID string, userIDs []string) (err error)
+ DeleteGroup(ctx context.Context, groupIDs []string) (err error)
+ Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error)
+ UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) (rowsAffected int64, err error)
+ Find(
+ ctx context.Context,
+ groupIDs []string,
+ userIDs []string,
+ roleLevels []int32,
+ ) (groupMembers []*GroupMemberModel, err error)
+ FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error)
+ Take(ctx context.Context, groupID string, userID string) (groupMember *GroupMemberModel, err error)
+ TakeOwner(ctx context.Context, groupID string) (groupMember *GroupMemberModel, err error)
+ SearchMember(
+ ctx context.Context,
+ keyword string,
+ groupIDs []string,
+ userIDs []string,
+ roleLevels []int32,
+ pageNumber, showNumber int32,
+ ) (total uint32, groupList []*GroupMemberModel, err error)
+ MapGroupMemberNum(ctx context.Context, groupIDs []string) (count map[string]uint32, err error)
+ FindJoinUserID(ctx context.Context, groupIDs []string) (groupUsers map[string][]string, err error)
+ FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
+ TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error)
+ FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error)
+ FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/group_request.go b/tools/data-conversion/openim/mysql/v3/group_request.go
new file mode 100644
index 000000000..063b83938
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/group_request.go
@@ -0,0 +1,61 @@
+// 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 relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ GroupRequestModelTableName = "group_requests"
+)
+
+type GroupRequestModel struct {
+ UserID string `gorm:"column:user_id;primary_key;size:64"`
+ GroupID string `gorm:"column:group_id;primary_key;size:64"`
+ HandleResult int32 `gorm:"column:handle_result"`
+ ReqMsg string `gorm:"column:req_msg;size:1024"`
+ HandledMsg string `gorm:"column:handle_msg;size:1024"`
+ ReqTime time.Time `gorm:"column:req_time"`
+ HandleUserID string `gorm:"column:handle_user_id;size:64"`
+ HandledTime time.Time `gorm:"column:handle_time"`
+ JoinSource int32 `gorm:"column:join_source"`
+ InviterUserID string `gorm:"column:inviter_user_id;size:64"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (GroupRequestModel) TableName() string {
+ return GroupRequestModelTableName
+}
+
+type GroupRequestModelInterface interface {
+ NewTx(tx any) GroupRequestModelInterface
+ Create(ctx context.Context, groupRequests []*GroupRequestModel) (err error)
+ Delete(ctx context.Context, groupID string, userID string) (err error)
+ UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
+ Take(ctx context.Context, groupID string, userID string) (groupRequest *GroupRequestModel, err error)
+ FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*GroupRequestModel, error)
+ Page(
+ ctx context.Context,
+ userID string,
+ pageNumber, showNumber int32,
+ ) (total uint32, groups []*GroupRequestModel, err error)
+ PageGroup(
+ ctx context.Context,
+ groupIDs []string,
+ pageNumber, showNumber int32,
+ ) (total uint32, groups []*GroupRequestModel, err error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/log.go b/tools/data-conversion/openim/mysql/v3/log.go
new file mode 100644
index 000000000..5904a790e
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/log.go
@@ -0,0 +1,29 @@
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+type Log struct {
+ LogID string `gorm:"column:log_id;primary_key;type:char(64)"`
+ Platform string `gorm:"column:platform;type:varchar(32)"`
+ UserID string `gorm:"column:user_id;type:char(64)"`
+ CreateTime time.Time `gorm:"index:,sort:desc"`
+ Url string `gorm:"column:url;type varchar(255)"`
+ FileName string `gorm:"column:filename;type varchar(255)"`
+ SystemType string `gorm:"column:system_type;type varchar(255)"`
+ Version string `gorm:"column:version;type varchar(255)"`
+ Ex string `gorm:"column:ex;type varchar(255)"`
+}
+
+func (Log) TableName() string {
+ return "logs"
+}
+
+type LogInterface interface {
+ Create(ctx context.Context, log []*Log) error
+ Search(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*Log, error)
+ Delete(ctx context.Context, logID []string, userID string) error
+ Get(ctx context.Context, logIDs []string, userID string) ([]*Log, error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/object.go b/tools/data-conversion/openim/mysql/v3/object.go
new file mode 100644
index 000000000..0ed4130a6
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/object.go
@@ -0,0 +1,45 @@
+// 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 relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ ObjectInfoModelTableName = "object"
+)
+
+type ObjectModel struct {
+ Name string `gorm:"column:name;primary_key"`
+ UserID string `gorm:"column:user_id"`
+ Hash string `gorm:"column:hash"`
+ Key string `gorm:"column:key"`
+ Size int64 `gorm:"column:size"`
+ ContentType string `gorm:"column:content_type"`
+ Cause string `gorm:"column:cause"`
+ CreateTime time.Time `gorm:"column:create_time"`
+}
+
+func (ObjectModel) TableName() string {
+ return ObjectInfoModelTableName
+}
+
+type ObjectInfoModelInterface interface {
+ NewTx(tx any) ObjectInfoModelInterface
+ SetObject(ctx context.Context, obj *ObjectModel) error
+ Take(ctx context.Context, name string) (*ObjectModel, error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/user.go b/tools/data-conversion/openim/mysql/v3/user.go
new file mode 100644
index 000000000..10a715bda
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/user.go
@@ -0,0 +1,72 @@
+// 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 relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ UserModelTableName = "users"
+)
+
+type UserModel struct {
+ UserID string `gorm:"column:user_id;primary_key;size:64"`
+ Nickname string `gorm:"column:name;size:255"`
+ FaceURL string `gorm:"column:face_url;size:255"`
+ Ex string `gorm:"column:ex;size:1024"`
+ CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
+ AppMangerLevel int32 `gorm:"column:app_manger_level;default:1"`
+ GlobalRecvMsgOpt int32 `gorm:"column:global_recv_msg_opt"`
+}
+
+func (u *UserModel) GetNickname() string {
+ return u.Nickname
+}
+
+func (u *UserModel) GetFaceURL() string {
+ return u.FaceURL
+}
+
+func (u *UserModel) GetUserID() string {
+ return u.UserID
+}
+
+func (u *UserModel) GetEx() string {
+ return u.Ex
+}
+
+func (UserModel) TableName() string {
+ return UserModelTableName
+}
+
+type UserModelInterface interface {
+ Create(ctx context.Context, users []*UserModel) (err error)
+ UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error)
+ Update(ctx context.Context, user *UserModel) (err error)
+ // 获取指定用户信息 不存在,也不返回错误
+ Find(ctx context.Context, userIDs []string) (users []*UserModel, err error)
+ // 获取某个用户信息 不存在,则返回错误
+ Take(ctx context.Context, userID string) (user *UserModel, err error)
+ // 获取用户信息 不存在,不返回错误
+ Page(ctx context.Context, pageNumber, showNumber int32) (users []*UserModel, count int64, err error)
+ GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error)
+ GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
+ // 获取用户总数
+ CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
+ // 获取范围内用户增量
+ CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
+}
diff --git a/pkg/common/db/relation/meta_db.go b/tools/data-conversion/openim/mysql/v3/utils.go
similarity index 70%
rename from pkg/common/db/relation/meta_db.go
rename to tools/data-conversion/openim/mysql/v3/utils.go
index 6ab980120..c944eae8b 100644
--- a/pkg/common/db/relation/meta_db.go
+++ b/tools/data-conversion/openim/mysql/v3/utils.go
@@ -15,24 +15,22 @@
package relation
import (
- "context"
-
"gorm.io/gorm"
+
+ "github.com/OpenIMSDK/tools/utils"
)
-type MetaDB struct {
- DB *gorm.DB
- table any
+type BatchUpdateGroupMember struct {
+ GroupID string
+ UserID string
+ Map map[string]any
}
-func NewMetaDB(db *gorm.DB, table any) *MetaDB {
- return &MetaDB{
- DB: db,
- table: table,
- }
+type GroupSimpleUserID struct {
+ Hash uint64
+ MemberNum uint32
}
-func (g *MetaDB) db(ctx context.Context) *gorm.DB {
- db := g.DB.WithContext(ctx).Model(g.table)
- return db
+func IsNotFound(err error) bool {
+ return utils.Unwrap(err) == gorm.ErrRecordNotFound
}
diff --git a/tools/data-conversion/openim/proto/msg/msg.pb.go b/tools/data-conversion/openim/proto/msg/msg.pb.go
index 2954a3a76..a0a6cdf02 100644
--- a/tools/data-conversion/openim/proto/msg/msg.pb.go
+++ b/tools/data-conversion/openim/proto/msg/msg.pb.go
@@ -2703,7 +2703,7 @@ func RegisterMsgServer(s *grpc.Server, srv MsgServer) {
s.RegisterService(&_Msg_serviceDesc, srv)
}
-func _Msg_GetMaxAndMinSeq_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetMaxAndMinSeq_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(sdk_ws.GetMaxAndMinSeqReq)
if err := dec(in); err != nil {
return nil, err
@@ -2715,13 +2715,13 @@ func _Msg_GetMaxAndMinSeq_Handler(srv interface{}, ctx context.Context, dec func
Server: srv,
FullMethod: "/msg.msg/GetMaxAndMinSeq",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetMaxAndMinSeq(ctx, req.(*sdk_ws.GetMaxAndMinSeqReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_PullMessageBySeqList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_PullMessageBySeqList_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(sdk_ws.PullMessageBySeqListReq)
if err := dec(in); err != nil {
return nil, err
@@ -2733,13 +2733,13 @@ func _Msg_PullMessageBySeqList_Handler(srv interface{}, ctx context.Context, dec
Server: srv,
FullMethod: "/msg.msg/PullMessageBySeqList",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).PullMessageBySeqList(ctx, req.(*sdk_ws.PullMessageBySeqListReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_SendMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_SendMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(SendMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2751,13 +2751,13 @@ func _Msg_SendMsg_Handler(srv interface{}, ctx context.Context, dec func(interfa
Server: srv,
FullMethod: "/msg.msg/SendMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).SendMsg(ctx, req.(*SendMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_DelMsgList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_DelMsgList_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(sdk_ws.DelMsgListReq)
if err := dec(in); err != nil {
return nil, err
@@ -2769,13 +2769,13 @@ func _Msg_DelMsgList_Handler(srv interface{}, ctx context.Context, dec func(inte
Server: srv,
FullMethod: "/msg.msg/DelMsgList",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).DelMsgList(ctx, req.(*sdk_ws.DelMsgListReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_DelSuperGroupMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_DelSuperGroupMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(DelSuperGroupMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2787,13 +2787,13 @@ func _Msg_DelSuperGroupMsg_Handler(srv interface{}, ctx context.Context, dec fun
Server: srv,
FullMethod: "/msg.msg/DelSuperGroupMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).DelSuperGroupMsg(ctx, req.(*DelSuperGroupMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_ClearMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_ClearMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(ClearMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2805,13 +2805,13 @@ func _Msg_ClearMsg_Handler(srv interface{}, ctx context.Context, dec func(interf
Server: srv,
FullMethod: "/msg.msg/ClearMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).ClearMsg(ctx, req.(*ClearMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_SetMsgMinSeq_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_SetMsgMinSeq_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(SetMsgMinSeqReq)
if err := dec(in); err != nil {
return nil, err
@@ -2823,13 +2823,13 @@ func _Msg_SetMsgMinSeq_Handler(srv interface{}, ctx context.Context, dec func(in
Server: srv,
FullMethod: "/msg.msg/SetMsgMinSeq",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).SetMsgMinSeq(ctx, req.(*SetMsgMinSeqReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_SetSendMsgStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_SetSendMsgStatus_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(SetSendMsgStatusReq)
if err := dec(in); err != nil {
return nil, err
@@ -2841,13 +2841,13 @@ func _Msg_SetSendMsgStatus_Handler(srv interface{}, ctx context.Context, dec fun
Server: srv,
FullMethod: "/msg.msg/SetSendMsgStatus",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).SetSendMsgStatus(ctx, req.(*SetSendMsgStatusReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_GetSendMsgStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetSendMsgStatus_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetSendMsgStatusReq)
if err := dec(in); err != nil {
return nil, err
@@ -2859,13 +2859,13 @@ func _Msg_GetSendMsgStatus_Handler(srv interface{}, ctx context.Context, dec fun
Server: srv,
FullMethod: "/msg.msg/GetSendMsgStatus",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetSendMsgStatus(ctx, req.(*GetSendMsgStatusReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_GetSuperGroupMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetSuperGroupMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetSuperGroupMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2877,13 +2877,13 @@ func _Msg_GetSuperGroupMsg_Handler(srv interface{}, ctx context.Context, dec fun
Server: srv,
FullMethod: "/msg.msg/GetSuperGroupMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetSuperGroupMsg(ctx, req.(*GetSuperGroupMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_GetWriteDiffMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetWriteDiffMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetWriteDiffMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2895,13 +2895,13 @@ func _Msg_GetWriteDiffMsg_Handler(srv interface{}, ctx context.Context, dec func
Server: srv,
FullMethod: "/msg.msg/GetWriteDiffMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetWriteDiffMsg(ctx, req.(*GetWriteDiffMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_SetMessageReactionExtensions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_SetMessageReactionExtensions_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(SetMessageReactionExtensionsReq)
if err := dec(in); err != nil {
return nil, err
@@ -2913,13 +2913,13 @@ func _Msg_SetMessageReactionExtensions_Handler(srv interface{}, ctx context.Cont
Server: srv,
FullMethod: "/msg.msg/SetMessageReactionExtensions",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).SetMessageReactionExtensions(ctx, req.(*SetMessageReactionExtensionsReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_GetMessageListReactionExtensions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetMessageListReactionExtensions_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetMessageListReactionExtensionsReq)
if err := dec(in); err != nil {
return nil, err
@@ -2931,13 +2931,13 @@ func _Msg_GetMessageListReactionExtensions_Handler(srv interface{}, ctx context.
Server: srv,
FullMethod: "/msg.msg/GetMessageListReactionExtensions",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetMessageListReactionExtensions(ctx, req.(*GetMessageListReactionExtensionsReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_AddMessageReactionExtensions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_AddMessageReactionExtensions_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(AddMessageReactionExtensionsReq)
if err := dec(in); err != nil {
return nil, err
@@ -2949,13 +2949,13 @@ func _Msg_AddMessageReactionExtensions_Handler(srv interface{}, ctx context.Cont
Server: srv,
FullMethod: "/msg.msg/AddMessageReactionExtensions",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).AddMessageReactionExtensions(ctx, req.(*AddMessageReactionExtensionsReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_DeleteMessageReactionExtensions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_DeleteMessageReactionExtensions_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(DeleteMessageListReactionExtensionsReq)
if err := dec(in); err != nil {
return nil, err
@@ -2967,7 +2967,7 @@ func _Msg_DeleteMessageReactionExtensions_Handler(srv interface{}, ctx context.C
Server: srv,
FullMethod: "/msg.msg/DeleteMessageReactionExtensions",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).DeleteMessageReactionExtensions(ctx, req.(*DeleteMessageListReactionExtensionsReq))
}
return interceptor(ctx, in, info, handler)
diff --git a/tools/data-conversion/openim/proto/sdk_ws/ws.pb.go b/tools/data-conversion/openim/proto/sdk_ws/ws.pb.go
index 097280860..94b6f9be6 100644
--- a/tools/data-conversion/openim/proto/sdk_ws/ws.pb.go
+++ b/tools/data-conversion/openim/proto/sdk_ws/ws.pb.go
@@ -4156,8 +4156,8 @@ func (m *SignalReq) GetGetTokenByRoomID() *SignalGetTokenByRoomIDReq {
}
// XXX_OneofFuncs is for the internal use of the proto package.
-func (*SignalReq) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
- return _SignalReq_OneofMarshaler, _SignalReq_OneofUnmarshaler, _SignalReq_OneofSizer, []interface{}{
+func (*SignalReq) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []any) {
+ return _SignalReq_OneofMarshaler, _SignalReq_OneofUnmarshaler, _SignalReq_OneofSizer, []any{
(*SignalReq_Invite)(nil),
(*SignalReq_InviteInGroup)(nil),
(*SignalReq_Cancel)(nil),
@@ -4523,8 +4523,8 @@ func (m *SignalResp) GetGetTokenByRoomID() *SignalGetTokenByRoomIDReply {
}
// XXX_OneofFuncs is for the internal use of the proto package.
-func (*SignalResp) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
- return _SignalResp_OneofMarshaler, _SignalResp_OneofUnmarshaler, _SignalResp_OneofSizer, []interface{}{
+func (*SignalResp) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []any) {
+ return _SignalResp_OneofMarshaler, _SignalResp_OneofUnmarshaler, _SignalResp_OneofSizer, []any{
(*SignalResp_Invite)(nil),
(*SignalResp_InviteInGroup)(nil),
(*SignalResp_Cancel)(nil),
diff --git a/tools/up35/README.md b/tools/up35/README.md
new file mode 100644
index 000000000..c5bdcd3b6
--- /dev/null
+++ b/tools/up35/README.md
@@ -0,0 +1,67 @@
+# README for OpenIM Server Data Conversion Tool
+
+## Overview
+
+This tool is part of the OpenIM Server suite, specifically designed for data conversion between MySQL and MongoDB databases. It handles the migration of various data types, including user information, friendships, group memberships, and more from a MySQL database to MongoDB, ensuring data consistency and integrity during the transition.
+
+## Features
+
++ **Configurable Database Connections:** Supports connections to both MySQL and MongoDB, configurable through a YAML file.
++ **Data Conversion Tasks:** Converts a range of data models, including user profiles, friend requests, group memberships, and logs.
++ **Version Control:** Maintains data versioning, ensuring only necessary migrations are performed.
++ **Error Handling:** Robust error handling for database connectivity and query execution.
+
+## Requirements
+
++ Go programming environment
++ MySQL and MongoDB servers
++ OpenIM Server dependencies installed
+
+## Installation
+
+1. Ensure Go is installed and set up on your system.
+2. Clone the OpenIM Server repository.
+3. Navigate to the directory containing this tool.
+4. Install required dependencies.
+
+## Configuration
+
++ Configuration is managed through a YAML file specified at runtime.
++ Set up the MySQL and MongoDB connection parameters in the config file.
+
+## Usage
+
+To run the tool, use the following command from the terminal:
+
+```go
+make build BINS="up35"
+```
+
+Where `path/to/config.yaml` is the path to your configuration file.
+
+## Functionality
+
+The main functions of the script include:
+
++ `InitConfig(path string)`: Reads and parses the YAML configuration file.
++ `GetMysql()`: Establishes a connection to the MySQL database.
++ `GetMongo()`: Establishes a connection to the MongoDB database.
++ `Main(path string)`: Orchestrates the data migration process.
++ `SetMongoDataVersion(db *mongo.Database, curver string)`: Updates the data version in MongoDB after migration.
++ `NewTask(...)`: Generic function to handle the migration of different data types.
++ `insertMany(coll *mongo.Collection, objs []any)`: Inserts multiple records into a MongoDB collection.
++ `getColl(obj any)`: Retrieves the MongoDB collection associated with a given object.
++ `convert struct`: Contains methods for converting MySQL models to MongoDB models.
+
+## Notes
+
++ Ensure that the MySQL and MongoDB instances are accessible and that the credentials provided in the config file are correct.
++ It is advisable to backup databases before running the migration to prevent data loss.
+
+## Contributing
+
+Contributions to improve the tool or address issues are welcome. Please follow the project's contribution guidelines.
+
+## License
+
+Refer to the project's license document for usage and distribution rights.
\ No newline at end of file
diff --git a/tools/up35/go.mod b/tools/up35/go.mod
new file mode 100644
index 000000000..5ae3907bf
--- /dev/null
+++ b/tools/up35/go.mod
@@ -0,0 +1,51 @@
+module github.com/openimsdk/open-im-server/v3/tools/up35
+
+go 1.19
+
+require (
+ github.com/go-sql-driver/mysql v1.7.1
+ github.com/openimsdk/open-im-server/v3 v3.5.0
+ github.com/openimsdk/open-im-server/v3/tools/data-conversion v0.0.0-00010101000000-000000000000
+ go.mongodb.org/mongo-driver v1.12.1
+ gopkg.in/yaml.v3 v3.0.1
+ gorm.io/driver/mysql v1.5.1
+ gorm.io/gorm v1.25.4
+)
+
+require (
+ github.com/OpenIMSDK/protocol v0.0.31 // indirect
+ github.com/OpenIMSDK/tools v0.0.18 // indirect
+ github.com/bwmarrin/snowflake v0.3.0 // indirect
+ github.com/golang/protobuf v1.5.3 // indirect
+ github.com/golang/snappy v0.0.4 // indirect
+ github.com/jinzhu/copier v0.4.0 // indirect
+ github.com/jinzhu/inflection v1.0.0 // indirect
+ github.com/jinzhu/now v1.1.5 // indirect
+ github.com/klauspost/compress v1.16.7 // indirect
+ github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
+ github.com/lestrrat-go/strftime v1.0.6 // indirect
+ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
+ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/xdg-go/pbkdf2 v1.0.0 // indirect
+ github.com/xdg-go/scram v1.1.2 // indirect
+ github.com/xdg-go/stringprep v1.0.4 // indirect
+ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
+ go.uber.org/atomic v1.7.0 // indirect
+ go.uber.org/multierr v1.6.0 // indirect
+ go.uber.org/zap v1.24.0 // indirect
+ golang.org/x/crypto v0.14.0 // indirect
+ golang.org/x/image v0.13.0 // indirect
+ golang.org/x/net v0.17.0 // indirect
+ golang.org/x/sync v0.4.0 // indirect
+ golang.org/x/sys v0.14.0 // indirect
+ golang.org/x/text v0.13.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
+ google.golang.org/grpc v1.59.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
+)
+
+replace (
+ github.com/openimsdk/open-im-server/v3 => ./../../../open-im-server
+ github.com/openimsdk/open-im-server/v3/tools/data-conversion => ./../data-conversion
+)
diff --git a/tools/up35/go.sum b/tools/up35/go.sum
new file mode 100644
index 000000000..1a81e5b33
--- /dev/null
+++ b/tools/up35/go.sum
@@ -0,0 +1,125 @@
+github.com/OpenIMSDK/protocol v0.0.31 h1:ax43x9aqA6EKNXNukS5MT5BSTqkUmwO4uTvbJLtzCgE=
+github.com/OpenIMSDK/protocol v0.0.31/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/tools v0.0.18 h1:h3CvKB90DNd2aIJcOQ99cqgeW6C0na0PzR1TNsfxwL0=
+github.com/OpenIMSDK/tools v0.0.18/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
+github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
+github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
+github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
+github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
+github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
+github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
+github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
+github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
+github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ=
+github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
+github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
+github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
+github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE=
+go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
+go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg=
+golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+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.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0=
+google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
+google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+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.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
+gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
diff --git a/tools/up35/up35.go b/tools/up35/up35.go
new file mode 100644
index 000000000..5d4740fca
--- /dev/null
+++ b/tools/up35/up35.go
@@ -0,0 +1,367 @@
+package main
+
+import (
+ "context"
+ "errors"
+ "flag"
+ "fmt"
+ "github.com/go-sql-driver/mysql"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/config"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+ mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
+ mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "gopkg.in/yaml.v3"
+ gormMysql "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+ "gorm.io/gorm/logger"
+ "log"
+ "os"
+ "reflect"
+ "strconv"
+)
+
+const (
+ versionTable = "dataver"
+ versionKey = "data_version"
+ versionValue = 35
+)
+
+func main() {
+ var path string
+ flag.StringVar(&path, "c", "", "path config file")
+ flag.Parse()
+ if err := Main(path); err != nil {
+ log.Fatal(err)
+ return
+ }
+ os.Exit(0)
+}
+
+func InitConfig(path string) error {
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return err
+ }
+ return yaml.Unmarshal(data, &config.Config)
+}
+
+func GetMysql() (*gorm.DB, error) {
+ conf := config.Config.Mysql
+ mysqlDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.Username, conf.Password, conf.Address[0], conf.Database)
+ return gorm.Open(gormMysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard})
+}
+
+func GetMongo() (*mongo.Database, error) {
+ mgo, err := unrelation.NewMongo()
+ if err != nil {
+ return nil, err
+ }
+ return mgo.GetDatabase(), nil
+}
+
+func Main(path string) error {
+ if err := InitConfig(path); err != nil {
+ return err
+ }
+ if config.Config.Mysql == nil {
+ return nil
+ }
+ mongoDB, err := GetMongo()
+ if err != nil {
+ return err
+ }
+ var version struct {
+ Key string `bson:"key"`
+ Value string `bson:"value"`
+ }
+ switch mongoDB.Collection(versionTable).FindOne(context.Background(), bson.M{"key": versionKey}).Decode(&version) {
+ case nil:
+ if ver, _ := strconv.Atoi(version.Value); ver >= versionValue {
+ return nil
+ }
+ case mongo.ErrNoDocuments:
+ default:
+ return err
+ }
+ mysqlDB, err := GetMysql()
+ if err != nil {
+ if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1049 {
+ if err := SetMongoDataVersion(mongoDB, version.Value); err != nil {
+ return err
+ }
+ return nil // database not exist
+ }
+ return err
+ }
+
+ var c convert
+ var tasks []func() error
+ tasks = append(tasks,
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewUserMongo, c.User) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendMongo, c.Friend) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendRequestMongo, c.FriendRequest) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewBlackMongo, c.Black) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMongo, c.Group) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMember, c.GroupMember) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupRequestMgo, c.GroupRequest) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewConversationMongo, c.Conversation) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewS3Mongo, c.Object(config.Config.Object.Enable)) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewLogMongo, c.Log) },
+ )
+
+ for _, task := range tasks {
+ if err := task(); err != nil {
+ return err
+ }
+ }
+
+ if err := SetMongoDataVersion(mongoDB, version.Value); err != nil {
+ return err
+ }
+ return nil
+}
+
+func SetMongoDataVersion(db *mongo.Database, curver string) error {
+ filter := bson.M{"key": versionKey, "value": curver}
+ update := bson.M{"$set": bson.M{"key": versionKey, "value": strconv.Itoa(versionValue)}}
+ _, err := db.Collection(versionTable).UpdateOne(context.Background(), filter, update, options.Update().SetUpsert(true))
+ return err
+}
+
+// NewTask A mysql table B mongodb model C mongodb table
+func NewTask[A interface{ TableName() string }, B any, C any](gormDB *gorm.DB, mongoDB *mongo.Database, mongoDBInit func(db *mongo.Database) (B, error), convert func(v A) C) error {
+ obj, err := mongoDBInit(mongoDB)
+ if err != nil {
+ return err
+ }
+ var zero A
+ tableName := zero.TableName()
+ coll, err := getColl(obj)
+ if err != nil {
+ return fmt.Errorf("get mongo collection %s failed, err: %w", tableName, err)
+ }
+ var count int
+ defer func() {
+ log.Printf("completed convert %s total %d\n", tableName, count)
+ }()
+ const batch = 100
+ for page := 0; ; page++ {
+ res := make([]A, 0, batch)
+ if err := gormDB.Limit(batch).Offset(page * batch).Find(&res).Error; err != nil {
+ if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1146 {
+ return nil // table not exist
+ }
+ return fmt.Errorf("find mysql table %s failed, err: %w", tableName, err)
+ }
+ if len(res) == 0 {
+ return nil
+ }
+ temp := make([]any, len(res))
+ for i := range res {
+ temp[i] = convert(res[i])
+ }
+ if err := insertMany(coll, temp); err != nil {
+ return fmt.Errorf("insert mongo table %s failed, err: %w", tableName, err)
+ }
+ count += len(res)
+ if len(res) < batch {
+ return nil
+ }
+ log.Printf("current convert %s completed %d\n", tableName, count)
+ }
+}
+
+func insertMany(coll *mongo.Collection, objs []any) error {
+ if _, err := coll.InsertMany(context.Background(), objs); err != nil {
+ if !mongo.IsDuplicateKeyError(err) {
+ return err
+ }
+ }
+ for i := range objs {
+ _, err := coll.InsertOne(context.Background(), objs[i])
+ switch {
+ case err == nil:
+ case mongo.IsDuplicateKeyError(err):
+ default:
+ return err
+ }
+ }
+ return nil
+}
+
+func getColl(obj any) (_ *mongo.Collection, err error) {
+ defer func() {
+ if e := recover(); e != nil {
+ err = fmt.Errorf("not found %+v", e)
+ }
+ }()
+ stu := reflect.ValueOf(obj).Elem()
+ typ := reflect.TypeOf(&mongo.Collection{}).String()
+ for i := 0; i < stu.NumField(); i++ {
+ field := stu.Field(i)
+ if field.Type().String() == typ {
+ return (*mongo.Collection)(field.UnsafePointer()), nil
+ }
+ }
+ return nil, errors.New("not found")
+}
+
+type convert struct{}
+
+func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel {
+ return mongoModel.UserModel{
+ UserID: v.UserID,
+ Nickname: v.Nickname,
+ FaceURL: v.FaceURL,
+ Ex: v.Ex,
+ AppMangerLevel: v.AppMangerLevel,
+ GlobalRecvMsgOpt: v.GlobalRecvMsgOpt,
+ CreateTime: v.CreateTime,
+ }
+}
+
+func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel {
+ return mongoModel.FriendModel{
+ OwnerUserID: v.OwnerUserID,
+ FriendUserID: v.FriendUserID,
+ Remark: v.Remark,
+ CreateTime: v.CreateTime,
+ AddSource: v.AddSource,
+ OperatorUserID: v.OperatorUserID,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendRequestModel {
+ return mongoModel.FriendRequestModel{
+ FromUserID: v.FromUserID,
+ ToUserID: v.ToUserID,
+ HandleResult: v.HandleResult,
+ ReqMsg: v.ReqMsg,
+ CreateTime: v.CreateTime,
+ HandlerUserID: v.HandlerUserID,
+ HandleMsg: v.HandleMsg,
+ HandleTime: v.HandleTime,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel {
+ return mongoModel.BlackModel{
+ OwnerUserID: v.OwnerUserID,
+ BlockUserID: v.BlockUserID,
+ CreateTime: v.CreateTime,
+ AddSource: v.AddSource,
+ OperatorUserID: v.OperatorUserID,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel {
+ return mongoModel.GroupModel{
+ GroupID: v.GroupID,
+ GroupName: v.GroupName,
+ Notification: v.Notification,
+ Introduction: v.Introduction,
+ FaceURL: v.FaceURL,
+ CreateTime: v.CreateTime,
+ Ex: v.Ex,
+ Status: v.Status,
+ CreatorUserID: v.CreatorUserID,
+ GroupType: v.GroupType,
+ NeedVerification: v.NeedVerification,
+ LookMemberInfo: v.LookMemberInfo,
+ ApplyMemberFriend: v.ApplyMemberFriend,
+ NotificationUpdateTime: v.NotificationUpdateTime,
+ NotificationUserID: v.NotificationUserID,
+ }
+}
+
+func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMemberModel {
+ return mongoModel.GroupMemberModel{
+ GroupID: v.GroupID,
+ UserID: v.UserID,
+ Nickname: v.Nickname,
+ FaceURL: v.FaceURL,
+ RoleLevel: v.RoleLevel,
+ JoinTime: v.JoinTime,
+ JoinSource: v.JoinSource,
+ InviterUserID: v.InviterUserID,
+ OperatorUserID: v.OperatorUserID,
+ MuteEndTime: v.MuteEndTime,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequestModel {
+ return mongoModel.GroupRequestModel{
+ UserID: v.UserID,
+ GroupID: v.GroupID,
+ HandleResult: v.HandleResult,
+ ReqMsg: v.ReqMsg,
+ HandledMsg: v.HandledMsg,
+ ReqTime: v.ReqTime,
+ HandleUserID: v.HandleUserID,
+ HandledTime: v.HandledTime,
+ JoinSource: v.JoinSource,
+ InviterUserID: v.InviterUserID,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.ConversationModel {
+ return mongoModel.ConversationModel{
+ OwnerUserID: v.OwnerUserID,
+ ConversationID: v.ConversationID,
+ ConversationType: v.ConversationType,
+ UserID: v.UserID,
+ GroupID: v.GroupID,
+ RecvMsgOpt: v.RecvMsgOpt,
+ IsPinned: v.IsPinned,
+ IsPrivateChat: v.IsPrivateChat,
+ BurnDuration: v.BurnDuration,
+ GroupAtType: v.GroupAtType,
+ AttachedInfo: v.AttachedInfo,
+ Ex: v.Ex,
+ MaxSeq: v.MaxSeq,
+ MinSeq: v.MinSeq,
+ CreateTime: v.CreateTime,
+ IsMsgDestruct: v.IsMsgDestruct,
+ MsgDestructTime: v.MsgDestructTime,
+ LatestMsgDestructTime: v.LatestMsgDestructTime,
+ }
+}
+
+func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
+ return func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
+ return mongoModel.ObjectModel{
+ Name: v.Name,
+ UserID: v.UserID,
+ Hash: v.Hash,
+ Engine: engine,
+ Key: v.Key,
+ Size: v.Size,
+ ContentType: v.ContentType,
+ Group: v.Cause,
+ CreateTime: v.CreateTime,
+ }
+ }
+}
+
+func (convert) Log(v mysqlModel.Log) mongoModel.LogModel {
+ return mongoModel.LogModel{
+ LogID: v.LogID,
+ Platform: v.Platform,
+ UserID: v.UserID,
+ CreateTime: v.CreateTime,
+ Url: v.Url,
+ FileName: v.FileName,
+ SystemType: v.SystemType,
+ Version: v.Version,
+ Ex: v.Ex,
+ }
+}
From 119e8dbb2f5275d19829622b9b4d26f535700b83 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Tue, 5 Dec 2023 21:28:00 +0800
Subject: [PATCH 007/110] feat: Provides a new reading scheme for profile
privacy through environment variables (#1520)
* fix: fix openim make install
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix openim make init
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: remove docker compose mysql
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---
.gitignore | 3 ++-
docker-compose.yml | 16 ----------------
scripts/init-config.sh | 14 ++++++++++++--
scripts/install-im-server.sh | 4 ++--
4 files changed, 16 insertions(+), 21 deletions(-)
diff --git a/.gitignore b/.gitignore
index 6b65697d9..675ce10c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -391,4 +391,5 @@ Sessionx.vim
dist/
.env
config/config.yaml
-config/alertmanager.yml
\ No newline at end of file
+config/alertmanager.yml
+config/prometheus.yml
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index ebf6a3dc4..233c8d492 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -11,22 +11,6 @@ networks:
gateway: '${DOCKER_BRIDGE_GATEWAY}'
services:
- mysql:
- image: mysql:5.7
- ports:
- - "${MYSQL_PORT}:3306"
- container_name: mysql
- volumes:
- - "${DATA_DIR}/components/mysql/data:/var/lib/mysql"
- - "/etc/localtime:/etc/localtime"
- environment:
- MYSQL_ROOT_PASSWORD: "${MYSQL_PASSWORD}"
- restart: always
- networks:
- server:
- # open-im-server_server
- ipv4_address: ${MYSQL_NETWORK_ADDRESS}
-
mongodb:
image: mongo:6.0.2
ports:
diff --git a/scripts/init-config.sh b/scripts/init-config.sh
index 3fcd2fdfd..f20fc7e73 100755
--- a/scripts/init-config.sh
+++ b/scripts/init-config.sh
@@ -39,13 +39,18 @@ openim::log::info "Read more configuration information: https://github.com/openi
for template in "${!TEMPLATES[@]}"; do
if [[ ! -f "${template}" ]]; then
- openim::log::error_exit "template file ${template} does not exist..."
+ openim::log::error_exit "Template file ${template} does not exist..."
+ exit 1
fi
+done
+for template in "${!TEMPLATES[@]}"; do
IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}"
for output_file in "${OUTPUT_FILES[@]}"; do
if [[ -f "${output_file}" ]]; then
- read -p "File ${output_file} already exists. Overwrite? (Y/N): "
+ echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
+ read -r -n 1 REPLY
+ echo # Adds a line to wrap after user input
if [[ $REPLY =~ ^[Yy]$ ]]; then
openim::log::info "Overwriting ${output_file}. Previous configuration will be lost."
else
@@ -55,6 +60,10 @@ for template in "${!TEMPLATES[@]}"; do
fi
openim::log::info "⌚ Working with template file: ${template} to ${output_file}..."
+ if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
+ openim::log::error "genconfig.sh script not found"
+ exit 1
+ fi
"${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
openim::log::error "Error processing template file ${template}"
exit 1
@@ -63,4 +72,5 @@ for template in "${!TEMPLATES[@]}"; do
done
done
+
openim::log::success "✨ All configuration files have been successfully generated!"
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index 26ab35b0d..0ad3c4a3e 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -42,11 +42,11 @@ fi
pushd "${OPENIM_ROOT}"
${DOCKER_COMPOSE_COMMAND} stop
-curl https://gitee.com/openimsdk/openim-docker/raw/main/example/full-openim-server-and-chat.yml -o docker-compose.yml && make init && docker compose up -d
+curl https://gitee.com/openimsdk/openim-docker/raw/main/example/full-openim-server-and-chat.yml -o docker-compose.yml
"${OPENIM_ROOT}"/scripts/init-config.sh
${DOCKER_COMPOSE_COMMAND} up --remove-orphans -d
sleep 60
${DOCKER_COMPOSE_COMMAND} logs openim-server
${DOCKER_COMPOSE_COMMAND} ps
-popd
+popd
\ No newline at end of file
From 4cd2713fd667abf7a3c72115c68aecc3aca60779 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Wed, 6 Dec 2023 10:45:53 +0800
Subject: [PATCH 008/110] fix: remove docker compose mysql (#1523)
* fix: remove docker compose mysql
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: remove docker compose mysql
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: set openim scripts
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: add openim scripts
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---
deployments/README.md | 2 --
deployments/templates/chat.yaml | 13 -------------
deployments/templates/env_template.yaml | 17 -----------------
deployments/templates/openim.yaml | 20 --------------------
docs/contrib/environment.md | 13 -------------
scripts/install-im-server.sh | 4 ++--
scripts/install/common.sh | 3 ---
scripts/install/dependency.sh | 11 -----------
scripts/install/environment.sh | 15 ---------------
9 files changed, 2 insertions(+), 96 deletions(-)
diff --git a/deployments/README.md b/deployments/README.md
index b24babb31..03f6d112b 100644
--- a/deployments/README.md
+++ b/deployments/README.md
@@ -154,8 +154,6 @@ GO111MODULE=on go get github.com/roboll/helmfile@latest
```
```bash
-export MYSQL_ADDRESS=im-mysql
-export MYSQL_PORT=3306
export MONGO_ADDRESS=im-mongo
export MONGO_PORT=27017
export REDIS_ADDRESS=im-redis-master
diff --git a/deployments/templates/chat.yaml b/deployments/templates/chat.yaml
index 3c3862bce..561d45d6e 100644
--- a/deployments/templates/chat.yaml
+++ b/deployments/templates/chat.yaml
@@ -53,19 +53,6 @@ rpcRegisterName:
openImAdminName: ${OPENIM_ADMIN_NAME}
openImChatName: ${OPENIM_CHAT_NAME}
-###################### MySQL ######################
-mysql:
- # address: [ 127.0.0.1:13306 ] #目前仅支持单机
- # username: root #用户名
- # password: openIM123 #密码
- # database: openIM_v2 #不建议修改
- # maxOpenConn: 1000 #最大连接数
- # maxIdleConn: 100 #最大空闲连接数
- # maxLifeTime: 60 #连接可以重复使用的最长时间(秒)
- # logLevel: 4 #日志级别 1=slient 2=error 3=warn 4=info
- # slowThreshold: 500 #慢语句阈值 (毫秒)
- database: openim_enterprise
-
###################### Log ######################
log:
storageLocation: ../logs/ #存放目录
diff --git a/deployments/templates/env_template.yaml b/deployments/templates/env_template.yaml
index 0ace53286..4db838c8e 100644
--- a/deployments/templates/env_template.yaml
+++ b/deployments/templates/env_template.yaml
@@ -55,9 +55,6 @@ DOCKER_BRIDGE_SUBNET=${DOCKER_BRIDGE_SUBNET}
# Default: DOCKER_BRIDGE_GATEWAY=172.28.0.1
DOCKER_BRIDGE_GATEWAY=${DOCKER_BRIDGE_GATEWAY}
-# Address or hostname for the MySQL network.
-# Default: MYSQL_NETWORK_ADDRESS=172.28.0.2
-MYSQL_NETWORK_ADDRESS=${MYSQL_NETWORK_ADDRESS}
MONGO_NETWORK_ADDRESS=${MONGO_NETWORK_ADDRESS}
REDIS_NETWORK_ADDRESS=${REDIS_NETWORK_ADDRESS}
KAFKA_NETWORK_ADDRESS=${KAFKA_NETWORK_ADDRESS}
@@ -86,20 +83,6 @@ ZOOKEEPER_ADDRESS=${ZOOKEEPER_NETWORK_ADDRESS}
# Default: ZOOKEEPER_PORT=12181
ZOOKEEPER_PORT=${ZOOKEEPER_PORT}
-# ----- MySQL Configuration -----
-
-# Address or hostname for the MySQL service.
-# Default: MYSQL_ADDRESS=172.28.0.1
-MYSQL_ADDRESS=${MYSQL_NETWORK_ADDRESS}
-
-# Port on which MySQL database service is running.
-# Default: MYSQL_PORT=13306
-MYSQL_PORT=${MYSQL_PORT}
-
-# Password to authenticate with the MySQL database service.
-# Default: MYSQL_PASSWORD=openIM123
-MYSQL_PASSWORD=${MYSQL_PASSWORD}
-
# ----- MongoDB Configuration -----
# Address or hostname for the MongoDB service.
# Default: MONGO_ADDRESS=172.28.0.1
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index fc90bfc2f..d822fec13 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -35,26 +35,6 @@ zookeeper:
username: ${ZOOKEEPER_USERNAME}
password: ${ZOOKEEPER_PASSWORD}
-###################### Mysql ######################
-# MySQL configuration
-# Currently, only single machine setup is supported
-#
-# Maximum number of open connections
-# Maximum number of idle connections
-# Maximum lifetime in seconds a connection can be reused
-# Log level: 1=slient, 2=error, 3=warn, 4=info
-# Slow query threshold in milliseconds
-mysql:
- address: [ ${MYSQL_ADDRESS}:${MYSQL_PORT} ]
- username: ${MYSQL_USERNAME}
- password: ${MYSQL_PASSWORD}
- database: ${MYSQL_DATABASE}
- maxOpenConn: ${MYSQL_MAX_OPEN_CONN}
- maxIdleConn: ${MYSQL_MAX_IDLE_CONN}
- maxLifeTime: ${MYSQL_MAX_LIFETIME}
- logLevel: ${MYSQL_LOG_LEVEL}
- slowThreshold: ${MYSQL_SLOW_THRESHOLD}
-
###################### Mongo ######################
# MongoDB configuration
# If uri is not empty, it will be used directly
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index 0279c750e..3dd090dcc 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -296,19 +296,6 @@ Feel free to explore the MinIO documentation for more advanced configurations an
| `ZOOKEEPER_USERNAME` | `""` | Username for Zookeeper. |
| `ZOOKEEPER_PASSWORD` | `""` | Password for Zookeeper. |
-### 2.6. MySQL Configuration
-
-**Description**: Configuration for MySQL, including port, address, and credentials.
-
-| Parameter | Example Value | Description |
-| ---------------- | ------------------------ | ------------------- |
-| `MYSQL_PORT` | `"13306"` | Port for MySQL. |
-| `MYSQL_ADDRESS` | Docker Bridge Gateway IP | Address for MySQL. |
-| `MYSQL_USERNAME` | User-defined | Username for MySQL. |
-| `MYSQL_PASSWORD` | User-defined | Password for MySQL. |
-
-Note: The configurations for other services (e.g., MONGO, REDIS, KAFKA, etc.) follow a similar pattern to MySQL and can be documented in a similar manner.
-
### 2.7. MongoDB Configuration
This section involves setting up MongoDB, including its port, address, and credentials.
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index 0ad3c4a3e..47db34433 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -40,11 +40,11 @@ else
DOCKER_COMPOSE_COMMAND="docker-compose"
fi
+"${OPENIM_ROOT}"/scripts/init-config.sh
pushd "${OPENIM_ROOT}"
${DOCKER_COMPOSE_COMMAND} stop
curl https://gitee.com/openimsdk/openim-docker/raw/main/example/full-openim-server-and-chat.yml -o docker-compose.yml
-"${OPENIM_ROOT}"/scripts/init-config.sh
-${DOCKER_COMPOSE_COMMAND} up --remove-orphans -d
+${DOCKER_COMPOSE_COMMAND} up -d
sleep 60
${DOCKER_COMPOSE_COMMAND} logs openim-server
${DOCKER_COMPOSE_COMMAND} ps
diff --git a/scripts/install/common.sh b/scripts/install/common.sh
index dd8bf614e..f6ee5d3ad 100755
--- a/scripts/install/common.sh
+++ b/scripts/install/common.sh
@@ -101,7 +101,6 @@ readonly OPENIM_SERVER_PORT_LISTARIES=("${OPENIM_SERVER_PORT_TARGETS[@]##*/}")
openim::common::dependency_name() {
local targets=(
- mysql
redis
zookeeper
kafka
@@ -117,13 +116,11 @@ readonly OPENIM_DEPENDENCY_TARGETS
# This function returns a list of ports for various services
# - zookeeper
# - kafka
-# - mysql
# - mongodb
# - redis
# - minio
openim::common::dependency_port() {
local targets=(
- ${MYSQL_PORT} # MySQL port
${REDIS_PORT} # Redis port
${ZOOKEEPER_PORT} # Zookeeper port
${KAFKA_PORT} # Kafka port
diff --git a/scripts/install/dependency.sh b/scripts/install/dependency.sh
index 7d6685186..bfa0909e2 100755
--- a/scripts/install/dependency.sh
+++ b/scripts/install/dependency.sh
@@ -22,17 +22,6 @@ set -o pipefail
OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P)
[[ -z ${COMMON_SOURCED} ]] && source "${OPENIM_ROOT}"/scripts/install/common.sh
-# Start MySQL service
-docker run -d \
- --name mysql \
- -p 13306:3306 \
- -p 23306:33060 \
- -v "${DATA_DIR}/components/mysql/data:/var/lib/mysql" \
- -v "/etc/localtime:/etc/localtime" \
- -e MYSQL_ROOT_PASSWORD=${PASSWORD} \
- --restart always \
- mysql:5.7
-
# Start MongoDB service
docker run -d \
--name mongo \
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index b7c8a5dcb..643f621b6 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -95,8 +95,6 @@ generate_ip() {
LAST_OCTET=$((LAST_OCTET + 1))
DOCKER_BRIDGE_GATEWAY=$(generate_ip)
LAST_OCTET=$((LAST_OCTET + 1))
-MYSQL_NETWORK_ADDRESS=$(generate_ip)
-LAST_OCTET=$((LAST_OCTET + 1))
MONGO_NETWORK_ADDRESS=$(generate_ip)
LAST_OCTET=$((LAST_OCTET + 1))
REDIS_NETWORK_ADDRESS=$(generate_ip)
@@ -168,19 +166,6 @@ def "ZOOKEEPER_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # Zookeeper的地址
def "ZOOKEEPER_USERNAME" "" # Zookeeper的用户名
def "ZOOKEEPER_PASSWORD" "" # Zookeeper的密码
-###################### MySQL 配置信息 ######################
-def "MYSQL_PORT" "13306" # MySQL的端口
-def "MYSQL_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # MySQL的地址
-def "MYSQL_USERNAME" "${OPENIM_USER}" # MySQL的用户名
-# MySQL的密码
-readonly MYSQL_PASSWORD=${MYSQL_PASSWORD:-"${PASSWORD}"}
-def "MYSQL_DATABASE" "${DATABASE_NAME}" # MySQL的数据库名
-def "MYSQL_MAX_OPEN_CONN" "1000" # 最大打开的连接数
-def "MYSQL_MAX_IDLE_CONN" "100" # 最大空闲连接数
-def "MYSQL_MAX_LIFETIME" "60" # 连接可以重用的最大生命周期(秒)
-def "MYSQL_LOG_LEVEL" "4" # 日志级别
-def "MYSQL_SLOW_THRESHOLD" "500" # 慢查询阈值(毫秒)
-
###################### MongoDB 配置信息 ######################
def "MONGO_URI" # MongoDB的URI
def "MONGO_PORT" "37017" # MongoDB的端口
From 60f4f67fb77272ddacbe72f6acf7624f8eb2df7e Mon Sep 17 00:00:00 2001
From: Gordon <46924906+FGadvancer@users.noreply.github.com>
Date: Wed, 6 Dec 2023 21:04:48 +0800
Subject: [PATCH 009/110] fix: online notifications do not push to herself.
(#1528)
---
go.mod | 19 --------
go.sum | 84 +++-----------------------------
internal/push/push_rpc_server.go | 10 +++-
3 files changed, 16 insertions(+), 97 deletions(-)
diff --git a/go.mod b/go.mod
index bc84bf586..6cf2089de 100644
--- a/go.mod
+++ b/go.mod
@@ -53,24 +53,6 @@ require (
cloud.google.com/go/iam v1.1.2 // indirect
cloud.google.com/go/longrunning v0.5.1 // indirect
cloud.google.com/go/storage v1.30.1 // indirect
- github.com/aws/aws-sdk-go-v2 v1.23.1 // indirect
- github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 // indirect
- github.com/aws/aws-sdk-go-v2/config v1.25.4 // indirect
- github.com/aws/aws-sdk-go-v2/credentials v1.16.3 // indirect
- github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 // indirect
- github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 // indirect
- github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 // indirect
- github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect
- github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 // indirect
- github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 // indirect
- github.com/aws/smithy-go v1.17.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -130,7 +112,6 @@ require (
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
- github.com/qiniu/go-sdk/v7 v7.18.2 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/sergi/go-diff v1.0.0 // indirect
diff --git a/go.sum b/go.sum
index 063f7691e..2f9198c9f 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,8 @@ github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
github.com/OpenIMSDK/protocol v0.0.31 h1:ax43x9aqA6EKNXNukS5MT5BSTqkUmwO4uTvbJLtzCgE=
github.com/OpenIMSDK/protocol v0.0.31/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.17 h1:1E1HUOL2W09YUHBb4wBwrXoTSZm5ONVwLxlEX1GhlKw=
-github.com/OpenIMSDK/tools v0.0.17/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/OpenIMSDK/tools v0.0.18 h1:h3CvKB90DNd2aIJcOQ99cqgeW6C0na0PzR1TNsfxwL0=
+github.com/OpenIMSDK/tools v0.0.18/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
@@ -31,42 +31,6 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
-github.com/aws/aws-sdk-go-v2 v1.23.1 h1:qXaFsOOMA+HsZtX8WoCa+gJnbyW7qyFFBlPqvTSzbaI=
-github.com/aws/aws-sdk-go-v2 v1.23.1/go.mod h1:i1XDttT4rnf6vxc9AuskLc6s7XBee8rlLilKlc03uAA=
-github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 h1:ZY3108YtBNq96jNZTICHxN1gSBSbnvIdYwwqnvCV4Mc=
-github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1/go.mod h1:t8PYl/6LzdAqsU4/9tz28V/kU+asFePvpOMkdul0gEQ=
-github.com/aws/aws-sdk-go-v2/config v1.25.4 h1:r+X1x8QI6FEPdJDWCNBDZHyAcyFwSjHN8q8uuus+Axs=
-github.com/aws/aws-sdk-go-v2/config v1.25.4/go.mod h1:8GTjImECskr7D88P/Nn9uM4M4rLY9i77hLJZgkZEWV8=
-github.com/aws/aws-sdk-go-v2/credentials v1.16.3 h1:8PeI2krzzjDJ5etmgaMiD1JswsrLrWvKKu/uBUtNy1g=
-github.com/aws/aws-sdk-go-v2/credentials v1.16.3/go.mod h1:Kdh/okh+//vQ/AjEt81CjvkTo64+/zIE4OewP7RpfXk=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 h1:KehRNiVzIfAcj6gw98zotVbb/K67taJE0fkfgM6vzqU=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5/go.mod h1:VhnExhw6uXy9QzetvpXDolo1/hjhx4u9qukBGkuUwjs=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 h1:LAm3Ycm9HJfbSCd5I+wqC2S9Ej7FPrgr5CQoOljJZcE=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4/go.mod h1:xEhvbJcyUf/31yfGSQBe01fukXwXJ0gxDp7rLfymWE0=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 h1:4GV0kKZzUxiWxSVpn/9gwR0g21NF1Jsyduzo9rHgC/Q=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4/go.mod h1:dYvTNAggxDZy6y1AF7YDwXsPuHFy/VNEpEI/2dWK9IU=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 h1:uR9lXYjdPX0xY+NhvaJ4dD8rpSRz5VY81ccIIoNG+lw=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
-github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 h1:40Q4X5ebZruRtknEZH/bg91sT5pR853F7/1X9QRbI54=
-github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4/go.mod h1:u77N7eEECzUv7F0xl2gcfK/vzc8wcjWobpy+DcrLJ5E=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 h1:rpkF4n0CyFcrJUG/rNNohoTmhtWlFTRI4BsZOh9PvLs=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1/go.mod h1:l9ymW25HOqymeU2m1gbUQ3rUIsTwKs8gYHXkqDQUhiI=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 h1:6DRKQc+9cChgzL5gplRGusI5dBGeiEod4m/pmGbcX48=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4/go.mod h1:s8ORvrW4g4v7IvYKIAoBg17w3GQ+XuwXDXYrQ5SkzU0=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 h1:rdovz3rEu0vZKbzoMYPTehp0E8veoE9AyfzqCr5Eeao=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4/go.mod h1:aYCGNjyUCUelhofxlZyj63srdxWUSsBSGg5l6MCuXuE=
-github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 h1:o3DcfCxGDIT20pTbVKVhp3vWXOj/VvgazNJvumWeYW0=
-github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4/go.mod h1:Uy0KVOxuTK2ne+/PKQ+VvEeWmjMMksE17k/2RK/r5oM=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1 h1:1w11lfXOa8HoHoSlNtt4mqv/N3HmDOa+OnUH3Y9DHm8=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1/go.mod h1:dqJ5JBL0clzgHriH35Amx3LRFY6wNIPUX7QO/BerSBo=
-github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 h1:CdsSOGlFF3Pn+koXOIpTtvX7st0IuGsZ8kJqcWMlX54=
-github.com/aws/aws-sdk-go-v2/service/sso v1.17.3/go.mod h1:oA6VjNsLll2eVuUoF2D+CMyORgNzPEW/3PyUdq6WQjI=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 h1:cbRqFTVnJV+KRpwFl76GJdIZJKKCdTPnjUZ7uWh3pIU=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1/go.mod h1:hHL974p5auvXlZPIjJTblXJpbkfK4klBczlsEaMCGVY=
-github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 h1:yEvZ4neOQ/KpUqyR+X0ycUTW/kVRNR4nDZ38wStHGAA=
-github.com/aws/aws-sdk-go-v2/service/sts v1.25.4/go.mod h1:feTnm2Tk/pJxdX+eooEsxvlvTWBvDm6CasRZ+JOs2IY=
-github.com/aws/smithy-go v1.17.0 h1:wWJD7LX6PBV6etBUwO0zElG0nWN9rUhp0WdYeHSHAaI=
-github.com/aws/smithy-go v1.17.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
@@ -92,7 +56,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -128,24 +91,15 @@ github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
-github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
-github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
-github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
-github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
-github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
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.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24=
github.com/go-playground/validator/v10 v10.15.5/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=
-github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
-github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
@@ -236,10 +190,11 @@ github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
-github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
-github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
+github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
+github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
@@ -257,15 +212,11 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
@@ -322,7 +273,6 @@ github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZ
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -338,18 +288,12 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
-github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk=
-github.com/qiniu/go-sdk/v7 v7.18.2 h1:vk9eo5OO7aqgAOPF0Ytik/gt7CMKuNgzC/IPkhda6rk=
-github.com/qiniu/go-sdk/v7 v7.18.2/go.mod h1:nqoYCNo53ZlGA521RvRethvxUDvXKt4gtYXOwye868w=
-github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg=
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
@@ -372,7 +316,6 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@@ -423,10 +366,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
@@ -457,7 +398,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
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.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
@@ -490,19 +430,16 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0/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.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -511,7 +448,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
@@ -572,8 +508,6 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
@@ -593,14 +527,10 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
-gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
-gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
-gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
-gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE=
+gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/internal/push/push_rpc_server.go b/internal/push/push_rpc_server.go
index 0f8f36a49..9e66f8f73 100644
--- a/internal/push/push_rpc_server.go
+++ b/internal/push/push_rpc_server.go
@@ -16,6 +16,7 @@ package push
import (
"context"
+ "github.com/OpenIMSDK/tools/utils"
"sync"
"google.golang.org/grpc"
@@ -78,7 +79,14 @@ func (r *pushServer) PushMsg(ctx context.Context, pbData *pbpush.PushMsgReq) (re
case constant.SuperGroupChatType:
err = r.pusher.Push2SuperGroup(ctx, pbData.MsgData.GroupID, pbData.MsgData)
default:
- err = r.pusher.Push2User(ctx, []string{pbData.MsgData.RecvID, pbData.MsgData.SendID}, pbData.MsgData)
+ var pushUserIDList []string
+ isSenderSync := utils.GetSwitchFromOptions(pbData.MsgData.Options, constant.IsSenderSync)
+ if !isSenderSync {
+ pushUserIDList = append(pushUserIDList, pbData.MsgData.RecvID)
+ } else {
+ pushUserIDList = append(pushUserIDList, pbData.MsgData.RecvID, pbData.MsgData.SendID)
+ }
+ err = r.pusher.Push2User(ctx, pushUserIDList, pbData.MsgData)
}
if err != nil {
if err != errNoOfflinePusher {
From bb6462647a21b57aee4c1bad4a52d33063e95b25 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Mon, 11 Dec 2023 12:18:55 +0800
Subject: [PATCH 010/110] fix: fix docker compose scripts (#1546)
* fix: fix docker compose scripts
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix scripts and rea
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---
.../{env_template.yaml => env-template.yaml} | 0
docs/contrib/bash-log.md | 2 +-
install_guide.sh | 176 ------------------
internal/rpc/msg/as_read.go | 96 ++++++----
scripts/init-config.sh | 60 ++++--
scripts/install/openim-api.sh | 2 +-
scripts/install/openim-rpc.sh | 2 +-
scripts/lib/logging.sh | 2 +-
8 files changed, 108 insertions(+), 232 deletions(-)
rename deployments/templates/{env_template.yaml => env-template.yaml} (100%)
delete mode 100755 install_guide.sh
diff --git a/deployments/templates/env_template.yaml b/deployments/templates/env-template.yaml
similarity index 100%
rename from deployments/templates/env_template.yaml
rename to deployments/templates/env-template.yaml
diff --git a/docs/contrib/bash-log.md b/docs/contrib/bash-log.md
index 86acb1d33..7725d5589 100644
--- a/docs/contrib/bash-log.md
+++ b/docs/contrib/bash-log.md
@@ -11,7 +11,7 @@ OpenIM, an intricate project, requires a robust logging mechanism to diagnose is
1. **Initialization**: The system begins by determining the verbosity level through the `OPENIM_VERBOSE` variable. If it's not set, a default value of 5 is assigned. This verbosity level dictates the depth of the log details.
2. **Log File Setup**: Logs are stored in the directory specified by `OPENIM_OUTPUT`. If this variable isn't explicitly set, it defaults to the `_output` directory relative to the script location. Each log file is named based on the date to facilitate easy identification.
3. **Logging Function**: The `echo_log()` function plays a pivotal role by writing messages to both the console (stdout) and the log file.
-4. **Logging to a file**: The `echo_log()` function writes to the log file by appending the message to the file. It also adds a timestamp to the message. path: `_output/logs/*`, Enable logging by default. Set to false to disable. If you wish to turn off output to log files set `ENABLE_LOGGING=flase`.
+4. **Logging to a file**: The `echo_log()` function writes to the log file by appending the message to the file. It also adds a timestamp to the message. path: `_output/logs/*`, Enable logging by default. Set to false to disable. If you wish to turn off output to log files set `export ENABLE_LOGGING=flase`.
### Key Functions & Their Usages
diff --git a/install_guide.sh b/install_guide.sh
deleted file mode 100755
index c4323d6a8..000000000
--- a/install_guide.sh
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/usr/bin/env bash
-
-echo "Welcome to the Open-IM-Server installation scripts."
-echo "Please select an deploy option:"
-echo "1. docker-compose install"
-echo "2. exit"
-
-clear_openimlog() {
- rm -rf ./logs/*
-}
-
-is_path() {
- if [ -e "$1" ]; then
- return 1
- else
- return 0
- fi
-}
-
-is_empty() {
- if [ -z "$1" ]; then
- return 1
- else
- return 0
- fi
-}
-
-is_directory_exists() {
- if [ -d "$1" ]; then
- return 1
- else
- return 0
- fi
-}
-
-edit_config() {
- echo "Is edit config.yaml?"
- echo "1. vi edit config"
- echo "2. do not edit config"
- read choice
- case $choice in
- 1)
- vi config/config.yaml
- ;;
- 2)
- echo "do not edit config"
- ;;
- esac
-}
-
-edit_enterprise_config() {
- echo "Is edit enterprise config.yaml?"
- echo "1. vi edit enterprise config"
- echo "2. do not edit enterprise config"
- read choice
- case $choice in
- 1)
- vi ./.docker-compose_cfg/config.yaml
- ;;
- 2)
- echo "Do not edit enterprise config"
- ;;
- esac
-}
-
-install_docker_compose() {
- echo "Please input the installation path, default is $(pwd)/Open-IM-Server, press enter to use default"
- read install_path
- is_empty $install_path
- if [ $? -eq 1 ]; then
- install_path="."
- fi
- echo "Installing Open-IM-Server to ${install_path}/Open-IM-Server..."
- is_path $install_path
- mkdir -p $install_path
- cd $install_path
- is_directory_exists "${install_path}/Open-IM-Server"
- if [ $? -eq 1 ]; then
- echo "WARNING: Directory $install_path/Open-IM-Server exist, please ensure your path"
- echo "1. delete the directory and install"
- echo "2. exit"
- read choice
- case $choice in
- 1)
- rm -rf "${install_path}/Open-IM-Server"
- ;;
- 2)
- exit 1
- ;;
- esac
- fi
- rm -rf ./Open-IM-Server
- set -e
- git clone https://github.com/openimsdk/open-im-server.git --recursive;
- set +e
- cd ./Open-IM-Server
- git checkout errcode
- echo "======== git clone success ========"
- source .env
- if [ $DATA_DIR = "./" ]; then
- DATA_DIR=$(pwd)/components
- fi
- echo "Please input the components data directory, deault is ${DATA_DIR}, press enter to use default"
- read NEW_DATA_DIR
- is_empty $NEW_DATA_DIR
- if [ $? -eq 0 ]; then
- DATA_DIR=$NEW_DATA_DIR
- fi
- echo "Please input the user, deault is root, press enter to use default"
- read NEW_USER
- is_empty $NEW_USER
- if [ $? -eq 0 ]; then
- OPENIM_USER=$NEW_USER
- fi
-
- echo "Please input the password, default is openIM123, press enter to use default"
- read NEW_PASSWORD
- is_empty $NEW_PASSWORD
- if [ $? -eq 0 ]; then
- PASSWORD=$NEW_PASSWORD
- fi
-
- echo "Please input the minio_endpoint, default will detect auto, press enter to use default"
- read NEW_MINIO_ENDPOINT
- is_empty $NEW_MINIO_ENDPOINT
- if [ $? -eq 1 ]; then
- internet_ip=`curl ifconfig.me -s`
- MINIO_ENDPOINT="http://${internet_ip}:10005"
- else
- MINIO_ENDPOINT=$NEW_MINIO_ENDPOINT
- fi
- set -e
- export MINIO_ENDPOINT
- export OPENIM_USER
- export PASSWORD
- export DATA_DIR
-
- cat < .env
-OPENIM_USER=${OPENIM_USER}
-PASSWORD=${PASSWORD}
-MINIO_ENDPOINT=${MINIO_ENDPOINT}
-DATA_DIR=${DATA_DIR}
-EOF
-
- edit_config
- edit_enterprise_config
-
- cd scripts;
- chmod +x *.sh;
- ./init-pwd.sh;
- ./env_check.sh;
- cd ..;
- docker-compose up -d;
- cd scripts;
- ./docker-check-service.sh;
-}
-
-read choice
-
-case $choice in
- 1)
- install_docker_compose
- ;;
- 2)
-
- ;;
- 3)
- ;;
- 4)
- echo "Exiting installation scripts..."
- exit 0
- ;;
- *)
- echo "Invalid option, please try again."
- ;;
-esac
diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go
index 49113aa0b..061498abb 100644
--- a/internal/rpc/msg/as_read.go
+++ b/internal/rpc/msg/as_read.go
@@ -16,14 +16,12 @@ package msg
import (
"context"
- cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
-
utils2 "github.com/OpenIMSDK/tools/utils"
"github.com/redis/go-redis/v9"
+ cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/OpenIMSDK/protocol/constant"
- "github.com/OpenIMSDK/protocol/conversation"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
@@ -92,7 +90,10 @@ func (m *msgServer) SetConversationHasReadSeq(
return &msg.SetConversationHasReadSeqResp{}, nil
}
-func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadReq) (resp *msg.MarkMsgsAsReadResp, err error) {
+func (m *msgServer) MarkMsgsAsRead(
+ ctx context.Context,
+ req *msg.MarkMsgsAsReadReq,
+) (resp *msg.MarkMsgsAsReadResp, err error) {
if len(req.Seqs) < 1 {
return nil, errs.ErrArgs.Wrap("seqs must not be empty")
}
@@ -111,6 +112,7 @@ func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadR
if err = m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, req.Seqs); err != nil {
return
}
+
currentHasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID)
if err != nil && errs.Unwrap(err) != redis.Nil {
return
@@ -128,7 +130,10 @@ func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadR
return &msg.MarkMsgsAsReadResp{}, nil
}
-func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkConversationAsReadReq) (resp *msg.MarkConversationAsReadResp, err error) {
+func (m *msgServer) MarkConversationAsRead(
+ ctx context.Context,
+ req *msg.MarkConversationAsReadReq,
+) (resp *msg.MarkConversationAsReadResp, err error) {
conversation, err := m.Conversation.GetConversation(ctx, req.UserID, req.ConversationID)
if err != nil {
return nil, err
@@ -137,34 +142,54 @@ func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkCon
if err != nil && errs.Unwrap(err) != redis.Nil {
return nil, err
}
- seqs := generateSeqs(hasReadSeq, req)
+ var seqs []int64
- if len(seqs) > 0 || req.HasReadSeq > hasReadSeq {
- err = m.updateReadStatus(ctx, req, conversation, seqs, hasReadSeq)
- if err != nil {
+ log.ZDebug(ctx, "MarkConversationAsRead", "hasReadSeq", hasReadSeq,
+ "req.HasReadSeq", req.HasReadSeq)
+ if conversation.ConversationType == constant.SingleChatType {
+ for i := hasReadSeq + 1; i <= req.HasReadSeq; i++ {
+ seqs = append(seqs, i)
+ }
+ //avoid client missed call MarkConversationMessageAsRead by order
+ for _, val := range req.Seqs {
+ if !utils2.Contain(val, seqs...) {
+ seqs = append(seqs, val)
+ }
+ }
+ if len(seqs) > 0 {
+ log.ZDebug(ctx, "MarkConversationAsRead", "seqs", seqs, "conversationID", req.ConversationID)
+ if err = m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, seqs); err != nil {
+ return nil, err
+ }
+ }
+ if req.HasReadSeq > hasReadSeq {
+ err = m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq)
+ if err != nil {
+ return nil, err
+ }
+ hasReadSeq = req.HasReadSeq
+ }
+ if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID,
+ m.conversationAndGetRecvID(conversation, req.UserID), seqs, hasReadSeq); err != nil {
return nil, err
}
- }
- return &msg.MarkConversationAsReadResp{}, nil
-}
-
-func generateSeqs(hasReadSeq int64, req *msg.MarkConversationAsReadReq) []int64 {
- var seqs []int64
- for _, val := range req.Seqs {
- if val > hasReadSeq && !utils2.Contain(val, seqs...) {
- seqs = append(seqs, val)
+
+ } else if conversation.ConversationType == constant.SuperGroupChatType ||
+ conversation.ConversationType == constant.NotificationChatType {
+ if req.HasReadSeq > hasReadSeq {
+ err = m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq)
+ if err != nil {
+ return nil, err
+ }
+ hasReadSeq = req.HasReadSeq
}
- }
- return seqs
-}
-
-func (m *msgServer) updateReadStatus(ctx context.Context, req *msg.MarkConversationAsReadReq, conversation *conversation.Conversation, seqs []int64, hasReadSeq int64) error {
- if conversation.ConversationType == constant.SingleChatType && len(seqs) > 0 {
- log.ZDebug(ctx, "MarkConversationAsRead", "seqs", seqs, "conversationID", req.ConversationID)
- if err := m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, seqs); err != nil {
- return err
+ if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID,
+ req.UserID, seqs, hasReadSeq); err != nil {
+ return nil, err
}
+
}
+
reqCall := &cbapi.CallbackGroupMsgReadReq{
SendID: conversation.OwnerUserID,
ReceiveID: req.UserID,
@@ -172,21 +197,10 @@ func (m *msgServer) updateReadStatus(ctx context.Context, req *msg.MarkConversat
ContentType: int64(conversation.ConversationType),
}
if err := CallbackGroupMsgRead(ctx, reqCall); err != nil {
- return err
- }
-
- if req.HasReadSeq > hasReadSeq {
- if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil {
- return err
- }
- }
-
- recvID := m.conversationAndGetRecvID(conversation, req.UserID)
- if conversation.ConversationType == constant.SuperGroupChatType || conversation.ConversationType == constant.NotificationChatType {
- recvID = req.UserID
+ return nil, err
}
- return m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID, recvID, seqs, req.HasReadSeq)
+ return &msg.MarkConversationAsReadResp{}, nil
}
func (m *msgServer) sendMarkAsReadNotification(
@@ -208,4 +222,4 @@ func (m *msgServer) sendMarkAsReadNotification(
log.ZWarn(ctx, "send has read Receipt err", err)
}
return nil
-}
+}
\ No newline at end of file
diff --git a/scripts/init-config.sh b/scripts/init-config.sh
index f20fc7e73..380239d50 100755
--- a/scripts/init-config.sh
+++ b/scripts/init-config.sh
@@ -24,12 +24,10 @@ OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${OPENIM_ROOT}/scripts/lib/init.sh"
-# (en: Define a profile array that contains the name path of the profile to be generated.)
readonly ENV_FILE=${ENV_FILE:-"${OPENIM_ROOT}/scripts/install/environment.sh"}
-# (en: Defines an associative array where the keys are the template files and the values are the corresponding output files.)
declare -A TEMPLATES=(
- ["${OPENIM_ROOT}/deployments/templates/env_template.yaml"]="${OPENIM_ROOT}/.env"
+ ["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/.env"
["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/config.yaml"
["${OPENIM_ROOT}/deployments/templates/prometheus.yml"]="${OPENIM_ROOT}/config/prometheus.yml"
["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/alertmanager.yml"
@@ -37,6 +35,42 @@ declare -A TEMPLATES=(
openim::log::info "Read more configuration information: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md"
+# New variables for argument handling
+FORCE_OVERWRITE=false
+SKIP_EXISTING=false
+
+# Function to display help
+show_help() {
+ echo "Usage: $(basename "$0") [options]"
+ echo "Options:"
+ echo " -h, --help Show this help message"
+ echo " --force Overwrite existing files without prompt"
+ echo " --skip Skip generation if file exists"
+}
+
+# Parse command-line options
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ -h|--help)
+ show_help
+ exit 0
+ ;;
+ --force)
+ FORCE_OVERWRITE=true
+ shift
+ ;;
+ --skip)
+ SKIP_EXISTING=true
+ shift
+ ;;
+ *)
+ echo "Unknown option: $1"
+ show_help
+ exit 1
+ ;;
+ esac
+done
+
for template in "${!TEMPLATES[@]}"; do
if [[ ! -f "${template}" ]]; then
openim::log::error_exit "Template file ${template} does not exist..."
@@ -48,14 +82,19 @@ for template in "${!TEMPLATES[@]}"; do
IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}"
for output_file in "${OUTPUT_FILES[@]}"; do
if [[ -f "${output_file}" ]]; then
- echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
- read -r -n 1 REPLY
- echo # Adds a line to wrap after user input
- if [[ $REPLY =~ ^[Yy]$ ]]; then
- openim::log::info "Overwriting ${output_file}. Previous configuration will be lost."
- else
- openim::log::info "Skipping generation of ${output_file}."
+ if [[ "${FORCE_OVERWRITE}" == true ]]; then
+ openim::log::info "Force overwriting ${output_file}."
+ elif [[ "${SKIP_EXISTING}" == true ]]; then
+ openim::log::info "Skipping generation of ${output_file} as it already exists."
continue
+ else
+ echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
+ read -r -n 1 REPLY
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ openim::log::info "Skipping generation of ${output_file}."
+ continue
+ fi
fi
fi
@@ -72,5 +111,4 @@ for template in "${!TEMPLATES[@]}"; do
done
done
-
openim::log::success "✨ All configuration files have been successfully generated!"
diff --git a/scripts/install/openim-api.sh b/scripts/install/openim-api.sh
index a40e23611..9f66d0ba0 100755
--- a/scripts/install/openim-api.sh
+++ b/scripts/install/openim-api.sh
@@ -66,7 +66,7 @@ function openim::api::start() {
for ((j = 0; j < ${#OPENIM_API_SERVICE_PORTS[@]}; j++)); do
openim::log::info "Starting ${OPENIM_API_SERVICE_LISTARIES[$i]} service, port: ${OPENIM_API_SERVICE_PORTS[j]}, binary root: ${OPENIM_OUTPUT_HOSTBIN}/${OPENIM_API_SERVICE_LISTARIES[$i]}"
openim::api::start_service "${OPENIM_API_SERVICE_LISTARIES[$i]}" "${OPENIM_API_PORT_LISTARIES[j]}"
- sleep 1
+ sleep 2
done
done
diff --git a/scripts/install/openim-rpc.sh b/scripts/install/openim-rpc.sh
index bd00ff9f2..b66004191 100755
--- a/scripts/install/openim-rpc.sh
+++ b/scripts/install/openim-rpc.sh
@@ -138,7 +138,7 @@ function openim::rpc::start() {
done
done
- sleep 0.5
+ sleep 1
openim::util::check_ports ${OPENIM_RPC_PORT_TARGETS[@]}
# openim::util::check_ports ${OPENIM_RPC_PROM_PORT_TARGETS[@]}
diff --git a/scripts/lib/logging.sh b/scripts/lib/logging.sh
index 90f9d0c7f..9d28aa284 100755
--- a/scripts/lib/logging.sh
+++ b/scripts/lib/logging.sh
@@ -17,7 +17,7 @@
OPENIM_VERBOSE="${OPENIM_VERBOSE:-5}"
# Enable logging by default. Set to false to disable.
-ENABLE_LOGGING=true
+ENABLE_LOGGING="${ENABLE_LOGGING:-true}"
# If OPENIM_OUTPUT is not set, set it to the default value
if [[ ! -v OPENIM_OUTPUT ]]; then
From 6b55cfd0b8fea3645e0426d1f80b86d5220cbb13 Mon Sep 17 00:00:00 2001
From: chao <48119764+withchao@users.noreply.github.com>
Date: Tue, 12 Dec 2023 10:03:40 +0800
Subject: [PATCH 011/110] feat: optimize tools up35 (#1552)
* upgrade package and rtc convert
* upgrade package and rtc convert
* upgrade package and rtc convert
---
go.mod | 4 +-
go.sum | 4 +-
internal/rpc/friend/friend.go | 1 -
tools/up35/pkg/convert.go | 227 +++++++++++
.../pkg/internal/rtc/mongo/mgo/meeting.go | 86 +++++
.../rtc/mongo/mgo/meeting_invitation.go | 76 ++++
.../internal/rtc/mongo/mgo/meeting_record.go | 32 ++
.../up35/pkg/internal/rtc/mongo/mgo/signal.go | 89 +++++
.../rtc/mongo/mgo/signal_invitation.go | 78 ++++
.../pkg/internal/rtc/mongo/table/meeting.go | 51 +++
.../pkg/internal/rtc/mongo/table/signal.go | 73 ++++
tools/up35/pkg/internal/rtc/mysql/meeting.go | 40 ++
tools/up35/pkg/internal/rtc/mysql/signal.go | 43 +++
tools/up35/pkg/pkg.go | 206 ++++++++++
tools/up35/up35.go | 352 +-----------------
15 files changed, 1007 insertions(+), 355 deletions(-)
create mode 100644 tools/up35/pkg/convert.go
create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go
create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go
create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go
create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/signal.go
create mode 100644 tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go
create mode 100644 tools/up35/pkg/internal/rtc/mongo/table/meeting.go
create mode 100644 tools/up35/pkg/internal/rtc/mongo/table/signal.go
create mode 100644 tools/up35/pkg/internal/rtc/mysql/meeting.go
create mode 100644 tools/up35/pkg/internal/rtc/mysql/signal.go
create mode 100644 tools/up35/pkg/pkg.go
diff --git a/go.mod b/go.mod
index 6cf2089de..11d374d08 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,8 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
+ github.com/OpenIMSDK/protocol v0.0.31
+ github.com/OpenIMSDK/tools v0.0.20
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
@@ -33,8 +35,6 @@ require github.com/google/uuid v1.3.1
require (
github.com/IBM/sarama v1.41.3
- github.com/OpenIMSDK/protocol v0.0.31
- github.com/OpenIMSDK/tools v0.0.18
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/go-redis/redis v6.15.9+incompatible
github.com/redis/go-redis/v9 v9.2.1
diff --git a/go.sum b/go.sum
index 2f9198c9f..30e4b3cb4 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,8 @@ github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
github.com/OpenIMSDK/protocol v0.0.31 h1:ax43x9aqA6EKNXNukS5MT5BSTqkUmwO4uTvbJLtzCgE=
github.com/OpenIMSDK/protocol v0.0.31/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.18 h1:h3CvKB90DNd2aIJcOQ99cqgeW6C0na0PzR1TNsfxwL0=
-github.com/OpenIMSDK/tools v0.0.18/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/OpenIMSDK/tools v0.0.20 h1:zBTjQZRJ5lR1FIzP9mtWyAvh5dKsmJXQugi4p8X/97k=
+github.com/OpenIMSDK/tools v0.0.20/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index 7f22c9d0d..224efe3ed 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -16,7 +16,6 @@ package friend
import (
"context"
-
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/protocol/sdkws"
diff --git a/tools/up35/pkg/convert.go b/tools/up35/pkg/convert.go
new file mode 100644
index 000000000..91fdb474e
--- /dev/null
+++ b/tools/up35/pkg/convert.go
@@ -0,0 +1,227 @@
+package pkg
+
+import (
+ mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+ mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
+ mongoModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
+ mysqlModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mysql"
+ "time"
+)
+
+type convert struct{}
+
+func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel {
+ return mongoModel.UserModel{
+ UserID: v.UserID,
+ Nickname: v.Nickname,
+ FaceURL: v.FaceURL,
+ Ex: v.Ex,
+ AppMangerLevel: v.AppMangerLevel,
+ GlobalRecvMsgOpt: v.GlobalRecvMsgOpt,
+ CreateTime: v.CreateTime,
+ }
+}
+
+func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel {
+ return mongoModel.FriendModel{
+ OwnerUserID: v.OwnerUserID,
+ FriendUserID: v.FriendUserID,
+ Remark: v.Remark,
+ CreateTime: v.CreateTime,
+ AddSource: v.AddSource,
+ OperatorUserID: v.OperatorUserID,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendRequestModel {
+ return mongoModel.FriendRequestModel{
+ FromUserID: v.FromUserID,
+ ToUserID: v.ToUserID,
+ HandleResult: v.HandleResult,
+ ReqMsg: v.ReqMsg,
+ CreateTime: v.CreateTime,
+ HandlerUserID: v.HandlerUserID,
+ HandleMsg: v.HandleMsg,
+ HandleTime: v.HandleTime,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel {
+ return mongoModel.BlackModel{
+ OwnerUserID: v.OwnerUserID,
+ BlockUserID: v.BlockUserID,
+ CreateTime: v.CreateTime,
+ AddSource: v.AddSource,
+ OperatorUserID: v.OperatorUserID,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel {
+ return mongoModel.GroupModel{
+ GroupID: v.GroupID,
+ GroupName: v.GroupName,
+ Notification: v.Notification,
+ Introduction: v.Introduction,
+ FaceURL: v.FaceURL,
+ CreateTime: v.CreateTime,
+ Ex: v.Ex,
+ Status: v.Status,
+ CreatorUserID: v.CreatorUserID,
+ GroupType: v.GroupType,
+ NeedVerification: v.NeedVerification,
+ LookMemberInfo: v.LookMemberInfo,
+ ApplyMemberFriend: v.ApplyMemberFriend,
+ NotificationUpdateTime: v.NotificationUpdateTime,
+ NotificationUserID: v.NotificationUserID,
+ }
+}
+
+func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMemberModel {
+ return mongoModel.GroupMemberModel{
+ GroupID: v.GroupID,
+ UserID: v.UserID,
+ Nickname: v.Nickname,
+ FaceURL: v.FaceURL,
+ RoleLevel: v.RoleLevel,
+ JoinTime: v.JoinTime,
+ JoinSource: v.JoinSource,
+ InviterUserID: v.InviterUserID,
+ OperatorUserID: v.OperatorUserID,
+ MuteEndTime: v.MuteEndTime,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequestModel {
+ return mongoModel.GroupRequestModel{
+ UserID: v.UserID,
+ GroupID: v.GroupID,
+ HandleResult: v.HandleResult,
+ ReqMsg: v.ReqMsg,
+ HandledMsg: v.HandledMsg,
+ ReqTime: v.ReqTime,
+ HandleUserID: v.HandleUserID,
+ HandledTime: v.HandledTime,
+ JoinSource: v.JoinSource,
+ InviterUserID: v.InviterUserID,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.ConversationModel {
+ return mongoModel.ConversationModel{
+ OwnerUserID: v.OwnerUserID,
+ ConversationID: v.ConversationID,
+ ConversationType: v.ConversationType,
+ UserID: v.UserID,
+ GroupID: v.GroupID,
+ RecvMsgOpt: v.RecvMsgOpt,
+ IsPinned: v.IsPinned,
+ IsPrivateChat: v.IsPrivateChat,
+ BurnDuration: v.BurnDuration,
+ GroupAtType: v.GroupAtType,
+ AttachedInfo: v.AttachedInfo,
+ Ex: v.Ex,
+ MaxSeq: v.MaxSeq,
+ MinSeq: v.MinSeq,
+ CreateTime: v.CreateTime,
+ IsMsgDestruct: v.IsMsgDestruct,
+ MsgDestructTime: v.MsgDestructTime,
+ LatestMsgDestructTime: v.LatestMsgDestructTime,
+ }
+}
+
+func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
+ return func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
+ return mongoModel.ObjectModel{
+ Name: v.Name,
+ UserID: v.UserID,
+ Hash: v.Hash,
+ Engine: engine,
+ Key: v.Key,
+ Size: v.Size,
+ ContentType: v.ContentType,
+ Group: v.Cause,
+ CreateTime: v.CreateTime,
+ }
+ }
+}
+
+func (convert) Log(v mysqlModel.Log) mongoModel.LogModel {
+ return mongoModel.LogModel{
+ LogID: v.LogID,
+ Platform: v.Platform,
+ UserID: v.UserID,
+ CreateTime: v.CreateTime,
+ Url: v.Url,
+ FileName: v.FileName,
+ SystemType: v.SystemType,
+ Version: v.Version,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) SignalModel(v mysqlModelRtc.SignalModel) mongoModelRtc.SignalModel {
+ return mongoModelRtc.SignalModel{
+ SID: v.SID,
+ InviterUserID: v.InviterUserID,
+ CustomData: v.CustomData,
+ GroupID: v.GroupID,
+ RoomID: v.RoomID,
+ Timeout: v.Timeout,
+ MediaType: v.MediaType,
+ PlatformID: v.PlatformID,
+ SessionType: v.SessionType,
+ InitiateTime: v.InitiateTime,
+ EndTime: v.EndTime,
+ FileURL: v.FileURL,
+ Title: v.Title,
+ Desc: v.Desc,
+ Ex: v.Ex,
+ IOSPushSound: v.IOSPushSound,
+ IOSBadgeCount: v.IOSBadgeCount,
+ SignalInfo: v.SignalInfo,
+ }
+}
+
+func (convert) SignalInvitationModel(v mysqlModelRtc.SignalInvitationModel) mongoModelRtc.SignalInvitationModel {
+ return mongoModelRtc.SignalInvitationModel{
+ SID: v.SID,
+ UserID: v.UserID,
+ Status: v.Status,
+ InitiateTime: v.InitiateTime,
+ HandleTime: v.HandleTime,
+ }
+}
+
+func (convert) Meeting(v mysqlModelRtc.MeetingInfo) mongoModelRtc.MeetingInfo {
+ return mongoModelRtc.MeetingInfo{
+ RoomID: v.RoomID,
+ MeetingName: v.MeetingName,
+ HostUserID: v.HostUserID,
+ Status: v.Status,
+ StartTime: time.Unix(v.StartTime, 0),
+ EndTime: time.Unix(v.EndTime, 0),
+ CreateTime: v.CreateTime,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) MeetingInvitationInfo(v mysqlModelRtc.MeetingInvitationInfo) mongoModelRtc.MeetingInvitationInfo {
+ return mongoModelRtc.MeetingInvitationInfo{
+ RoomID: v.RoomID,
+ UserID: v.UserID,
+ CreateTime: v.CreateTime,
+ }
+}
+
+func (convert) MeetingVideoRecord(v mysqlModelRtc.MeetingVideoRecord) mongoModelRtc.MeetingVideoRecord {
+ return mongoModelRtc.MeetingVideoRecord{
+ RoomID: v.RoomID,
+ FileURL: v.FileURL,
+ CreateTime: v.CreateTime,
+ }
+}
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go
new file mode 100644
index 000000000..e3bab7af9
--- /dev/null
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go
@@ -0,0 +1,86 @@
+package mgo
+
+import (
+ "context"
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "time"
+)
+
+func NewMeeting(db *mongo.Database) (table.MeetingInterface, error) {
+ coll := db.Collection("meeting")
+ _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
+ {
+ Keys: bson.D{
+ {Key: "room_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ },
+ {
+ Keys: bson.D{
+ {Key: "host_user_id", Value: 1},
+ },
+ },
+ {
+ Keys: bson.D{
+ {Key: "create_time", Value: -1},
+ },
+ },
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &meeting{coll: coll}, nil
+}
+
+type meeting struct {
+ coll *mongo.Collection
+}
+
+func (x *meeting) Find(ctx context.Context, roomIDs []string) ([]*table.MeetingInfo, error) {
+ return mgoutil.Find[*table.MeetingInfo](ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}})
+}
+
+func (x *meeting) CreateMeetingInfo(ctx context.Context, meetingInfo *table.MeetingInfo) error {
+ return mgoutil.InsertMany(ctx, x.coll, []*table.MeetingInfo{meetingInfo})
+}
+
+func (x *meeting) UpdateMeetingInfo(ctx context.Context, roomID string, update map[string]any) error {
+ if len(update) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, x.coll, bson.M{"room_id": roomID}, bson.M{"$set": update}, false)
+}
+
+func (x *meeting) GetUnCompleteMeetingIDList(ctx context.Context, roomIDs []string) ([]string, error) {
+ if len(roomIDs) == 0 {
+ return nil, nil
+ }
+ return mgoutil.Find[string](ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}, "status": 0}, options.Find().SetProjection(bson.M{"_id": 0, "room_id": 1}))
+}
+
+func (x *meeting) Delete(ctx context.Context, roomIDs []string) error {
+ return mgoutil.DeleteMany(ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}})
+}
+
+func (x *meeting) GetMeetingRecords(ctx context.Context, hostUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*table.MeetingInfo, error) {
+ var and []bson.M
+ if hostUserID != "" {
+ and = append(and, bson.M{"host_user_id": hostUserID})
+ }
+ if !startTime.IsZero() {
+ and = append(and, bson.M{"create_time": bson.M{"$gte": startTime}})
+ }
+ if !endTime.IsZero() {
+ and = append(and, bson.M{"create_time": bson.M{"$lte": endTime}})
+ }
+ filter := bson.M{}
+ if len(and) > 0 {
+ filter["$and"] = and
+ }
+ return mgoutil.FindPage[*table.MeetingInfo](ctx, x.coll, filter, pagination, options.Find().SetSort(bson.M{"create_time": -1}))
+}
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go
new file mode 100644
index 000000000..5286ffa95
--- /dev/null
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go
@@ -0,0 +1,76 @@
+package mgo
+
+import (
+ "context"
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "github.com/OpenIMSDK/tools/utils"
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "time"
+)
+
+func NewMeetingInvitation(db *mongo.Database) (table.MeetingInvitationInterface, error) {
+ coll := db.Collection("meeting_invitation")
+ _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
+ {
+ Keys: bson.D{
+ {Key: "room_id", Value: 1},
+ {Key: "user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ },
+ {
+ Keys: bson.D{
+ {Key: "create_time", Value: -1},
+ },
+ },
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &meetingInvitation{coll: coll}, nil
+}
+
+type meetingInvitation struct {
+ coll *mongo.Collection
+}
+
+func (x *meetingInvitation) FindUserIDs(ctx context.Context, roomID string) ([]string, error) {
+ return mgoutil.Find[string](ctx, x.coll, bson.M{"room_id": roomID}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
+}
+
+func (x *meetingInvitation) CreateMeetingInvitationInfo(ctx context.Context, roomID string, inviteeUserIDs []string) error {
+ now := time.Now()
+ return mgoutil.InsertMany(ctx, x.coll, utils.Slice(inviteeUserIDs, func(userID string) *table.MeetingInvitationInfo {
+ return &table.MeetingInvitationInfo{
+ RoomID: roomID,
+ UserID: userID,
+ CreateTime: now,
+ }
+ }))
+}
+
+func (x *meetingInvitation) GetUserInvitedMeetingIDs(ctx context.Context, userID string) (meetingIDs []string, err error) {
+ fiveDaysAgo := time.Now().AddDate(0, 0, -5)
+ return mgoutil.Find[string](ctx, x.coll, bson.M{"user_id": userID, "create_time": bson.M{"$gte": fiveDaysAgo}}, options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1}))
+}
+
+func (x *meetingInvitation) Delete(ctx context.Context, roomIDs []string) error {
+ return mgoutil.DeleteMany(ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}})
+}
+
+func (x *meetingInvitation) GetMeetingRecords(ctx context.Context, joinedUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) {
+ var and []bson.M
+ and = append(and, bson.M{"user_id": joinedUserID})
+ if !startTime.IsZero() {
+ and = append(and, bson.M{"create_time": bson.M{"$gte": startTime}})
+ }
+ if !endTime.IsZero() {
+ and = append(and, bson.M{"create_time": bson.M{"$lte": endTime}})
+ }
+ opt := options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1})
+ return mgoutil.FindPage[string](ctx, x.coll, bson.M{"$and": and}, pagination, opt)
+}
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go
new file mode 100644
index 000000000..90fc9cdca
--- /dev/null
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go
@@ -0,0 +1,32 @@
+package mgo
+
+import (
+ "context"
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+)
+
+func NewMeetingRecord(db *mongo.Database) (table.MeetingRecordInterface, error) {
+ coll := db.Collection("meeting_record")
+ _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
+ {
+ Keys: bson.D{
+ {Key: "room_id", Value: 1},
+ },
+ },
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &meetingRecord{coll: coll}, nil
+}
+
+type meetingRecord struct {
+ coll *mongo.Collection
+}
+
+func (x *meetingRecord) CreateMeetingVideoRecord(ctx context.Context, meetingVideoRecord *table.MeetingVideoRecord) error {
+ return mgoutil.InsertMany(ctx, x.coll, []*table.MeetingVideoRecord{meetingVideoRecord})
+}
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go
new file mode 100644
index 000000000..0c1879007
--- /dev/null
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go
@@ -0,0 +1,89 @@
+package mgo
+
+import (
+ "context"
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "time"
+)
+
+func NewSignal(db *mongo.Database) (table.SignalInterface, error) {
+ coll := db.Collection("signal")
+ _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
+ {
+ Keys: bson.D{
+ {Key: "sid", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ },
+ {
+ Keys: bson.D{
+ {Key: "inviter_user_id", Value: 1},
+ },
+ },
+ {
+ Keys: bson.D{
+ {Key: "initiate_time", Value: -1},
+ },
+ },
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &signal{coll: coll}, nil
+}
+
+type signal struct {
+ coll *mongo.Collection
+}
+
+func (x *signal) Find(ctx context.Context, sids []string) ([]*table.SignalModel, error) {
+ return mgoutil.Find[*table.SignalModel](ctx, x.coll, bson.M{"sid": bson.M{"$in": sids}})
+}
+
+func (x *signal) CreateSignal(ctx context.Context, signalModel *table.SignalModel) error {
+ return mgoutil.InsertMany(ctx, x.coll, []*table.SignalModel{signalModel})
+}
+
+func (x *signal) Update(ctx context.Context, sid string, update map[string]any) error {
+ if len(update) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, x.coll, bson.M{"sid": sid}, bson.M{"$set": update}, false)
+}
+
+func (x *signal) UpdateSignalFileURL(ctx context.Context, sID, fileURL string) error {
+ return x.Update(ctx, sID, map[string]any{"file_url": fileURL})
+}
+
+func (x *signal) UpdateSignalEndTime(ctx context.Context, sID string, endTime time.Time) error {
+ return x.Update(ctx, sID, map[string]any{"end_time": endTime})
+}
+
+func (x *signal) Delete(ctx context.Context, sids []string) error {
+ if len(sids) == 0 {
+ return nil
+ }
+ return mgoutil.DeleteMany(ctx, x.coll, bson.M{"sid": bson.M{"$in": sids}})
+}
+
+func (x *signal) PageSignal(ctx context.Context, sesstionType int32, sendID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*table.SignalModel, error) {
+ var and []bson.M
+ if !startTime.IsZero() {
+ and = append(and, bson.M{"initiate_time": bson.M{"$gte": startTime}})
+ }
+ if !endTime.IsZero() {
+ and = append(and, bson.M{"initiate_time": bson.M{"$lte": endTime}})
+ }
+ if sesstionType != 0 {
+ and = append(and, bson.M{"sesstion_type": sesstionType})
+ }
+ if sendID != "" {
+ and = append(and, bson.M{"inviter_user_id": sendID})
+ }
+ return mgoutil.FindPage[*table.SignalModel](ctx, x.coll, bson.M{"$and": and}, pagination, options.Find().SetSort(bson.M{"initiate_time": -1}))
+}
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go
new file mode 100644
index 000000000..274f2f11f
--- /dev/null
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go
@@ -0,0 +1,78 @@
+package mgo
+
+import (
+ "context"
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "github.com/OpenIMSDK/tools/utils"
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "time"
+)
+
+func NewSignalInvitation(db *mongo.Database) (table.SignalInvitationInterface, error) {
+ coll := db.Collection("signal_invitation")
+ _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
+ {
+ Keys: bson.D{
+ {Key: "sid", Value: 1},
+ {Key: "user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ },
+ {
+ Keys: bson.D{
+ {Key: "initiate_time", Value: -1},
+ },
+ },
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &signalInvitation{coll: coll}, nil
+}
+
+type signalInvitation struct {
+ coll *mongo.Collection
+}
+
+func (x *signalInvitation) Find(ctx context.Context, sid string) ([]*table.SignalInvitationModel, error) {
+ return mgoutil.Find[*table.SignalInvitationModel](ctx, x.coll, bson.M{"sid": sid})
+}
+
+func (x *signalInvitation) CreateSignalInvitation(ctx context.Context, sid string, inviteeUserIDs []string) error {
+ now := time.Now()
+ return mgoutil.InsertMany(ctx, x.coll, utils.Slice(inviteeUserIDs, func(userID string) *table.SignalInvitationModel {
+ return &table.SignalInvitationModel{
+ UserID: userID,
+ SID: sid,
+ InitiateTime: now,
+ HandleTime: time.Unix(0, 0),
+ }
+ }))
+}
+
+func (x *signalInvitation) HandleSignalInvitation(ctx context.Context, sID, InviteeUserID string, status int32) error {
+ return mgoutil.UpdateOne(ctx, x.coll, bson.M{"sid": sID, "user_id": InviteeUserID}, bson.M{"$set": bson.M{"status": status, "handle_time": time.Now()}}, true)
+}
+
+func (x *signalInvitation) PageSID(ctx context.Context, recvID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) {
+ var and []bson.M
+ and = append(and, bson.M{"user_id": recvID})
+ if !startTime.IsZero() {
+ and = append(and, bson.M{"initiate_time": bson.M{"$gte": startTime}})
+ }
+ if !endTime.IsZero() {
+ and = append(and, bson.M{"initiate_time": bson.M{"$lte": endTime}})
+ }
+ return mgoutil.FindPage[string](ctx, x.coll, bson.M{"$and": and}, pagination, options.Find().SetProjection(bson.M{"_id": 0, "sid": 1}).SetSort(bson.M{"initiate_time": -1}))
+}
+
+func (x *signalInvitation) Delete(ctx context.Context, sids []string) error {
+ if len(sids) == 0 {
+ return nil
+ }
+ return mgoutil.DeleteMany(ctx, x.coll, bson.M{"sid": bson.M{"$in": sids}})
+}
diff --git a/tools/up35/pkg/internal/rtc/mongo/table/meeting.go b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go
new file mode 100644
index 000000000..3b341cfb1
--- /dev/null
+++ b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go
@@ -0,0 +1,51 @@
+package table
+
+import (
+ "context"
+ "github.com/OpenIMSDK/tools/pagination"
+ "time"
+)
+
+type MeetingInfo struct {
+ RoomID string `bson:"room_id"`
+ MeetingName string `bson:"meeting_name"`
+ HostUserID string `bson:"host_user_id"`
+ Status int64 `bson:"status"`
+ StartTime time.Time `bson:"start_time"`
+ EndTime time.Time `bson:"end_time"`
+ CreateTime time.Time `bson:"create_time"`
+ Ex string `bson:"ex"`
+}
+
+type MeetingInterface interface {
+ Find(ctx context.Context, roomIDs []string) ([]*MeetingInfo, error)
+ CreateMeetingInfo(ctx context.Context, meetingInfo *MeetingInfo) error
+ UpdateMeetingInfo(ctx context.Context, roomID string, update map[string]any) error
+ GetUnCompleteMeetingIDList(ctx context.Context, roomIDs []string) ([]string, error)
+ Delete(ctx context.Context, roomIDs []string) error
+ GetMeetingRecords(ctx context.Context, hostUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*MeetingInfo, error)
+}
+
+type MeetingInvitationInfo struct {
+ RoomID string `bson:"room_id"`
+ UserID string `bson:"user_id"`
+ CreateTime time.Time `bson:"create_time"`
+}
+
+type MeetingInvitationInterface interface {
+ FindUserIDs(ctx context.Context, roomID string) ([]string, error)
+ CreateMeetingInvitationInfo(ctx context.Context, roomID string, inviteeUserIDs []string) error
+ GetUserInvitedMeetingIDs(ctx context.Context, userID string) (meetingIDs []string, err error)
+ Delete(ctx context.Context, roomIDs []string) error
+ GetMeetingRecords(ctx context.Context, joinedUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error)
+}
+
+type MeetingVideoRecord struct {
+ RoomID string `bson:"room_id"`
+ FileURL string `bson:"file_url"`
+ CreateTime time.Time `bson:"create_time"`
+}
+
+type MeetingRecordInterface interface {
+ CreateMeetingVideoRecord(ctx context.Context, meetingVideoRecord *MeetingVideoRecord) error
+}
diff --git a/tools/up35/pkg/internal/rtc/mongo/table/signal.go b/tools/up35/pkg/internal/rtc/mongo/table/signal.go
new file mode 100644
index 000000000..0cec050ff
--- /dev/null
+++ b/tools/up35/pkg/internal/rtc/mongo/table/signal.go
@@ -0,0 +1,73 @@
+package table
+
+import (
+ "context"
+ "github.com/OpenIMSDK/tools/errs"
+ "github.com/OpenIMSDK/tools/pagination"
+ "github.com/redis/go-redis/v9"
+ "go.mongodb.org/mongo-driver/mongo"
+ "time"
+)
+
+type SignalModel struct {
+ SID string `bson:"sid"`
+ InviterUserID string `bson:"inviter_user_id"`
+ CustomData string `bson:"custom_data"`
+ GroupID string `bson:"group_id"`
+ RoomID string `bson:"room_id"`
+ Timeout int32 `bson:"timeout"`
+ MediaType string `bson:"media_type"`
+ PlatformID int32 `bson:"platform_id"`
+ SessionType int32 `bson:"session_type"`
+ InitiateTime time.Time `bson:"initiate_time"`
+ EndTime time.Time `bson:"end_time"`
+ FileURL string `bson:"file_url"`
+
+ Title string `bson:"title"`
+ Desc string `bson:"desc"`
+ Ex string `bson:"ex"`
+ IOSPushSound string `bson:"ios_push_sound"`
+ IOSBadgeCount bool `bson:"ios_badge_count"`
+ SignalInfo string `bson:"signal_info"`
+}
+
+type SignalInterface interface {
+ Find(ctx context.Context, sids []string) ([]*SignalModel, error)
+ CreateSignal(ctx context.Context, signalModel *SignalModel) error
+ Update(ctx context.Context, sid string, update map[string]any) error
+ UpdateSignalFileURL(ctx context.Context, sID, fileURL string) error
+ UpdateSignalEndTime(ctx context.Context, sID string, endTime time.Time) error
+ Delete(ctx context.Context, sids []string) error
+ PageSignal(ctx context.Context, sesstionType int32, sendID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*SignalModel, error)
+}
+
+type SignalInvitationModel struct {
+ SID string `bson:"sid"`
+ UserID string `bson:"user_id"`
+ Status int32 `bson:"status"`
+ InitiateTime time.Time `bson:"initiate_time"`
+ HandleTime time.Time `bson:"handle_time"`
+}
+
+type SignalInvitationInterface interface {
+ Find(ctx context.Context, sid string) ([]*SignalInvitationModel, error)
+ CreateSignalInvitation(ctx context.Context, sid string, inviteeUserIDs []string) error
+ HandleSignalInvitation(ctx context.Context, sID, InviteeUserID string, status int32) error
+ PageSID(ctx context.Context, recvID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error)
+ Delete(ctx context.Context, sids []string) error
+}
+
+func IsNotFound(err error) bool {
+ if err == nil {
+ return false
+ }
+ err = errs.Unwrap(err)
+ return err == mongo.ErrNoDocuments || err == redis.Nil
+}
+
+func IsDuplicate(err error) bool {
+ if err == nil {
+ return false
+ }
+ return mongo.IsDuplicateKeyError(errs.Unwrap(err))
+}
diff --git a/tools/up35/pkg/internal/rtc/mysql/meeting.go b/tools/up35/pkg/internal/rtc/mysql/meeting.go
new file mode 100644
index 000000000..2c5bbed32
--- /dev/null
+++ b/tools/up35/pkg/internal/rtc/mysql/meeting.go
@@ -0,0 +1,40 @@
+package relation
+
+import (
+ "time"
+)
+
+type MeetingInfo struct {
+ RoomID string `gorm:"column:room_id;primary_key;size:128;index:room_id;index:status,priority:1"`
+ MeetingName string `gorm:"column:meeting_name;size:64"`
+ HostUserID string `gorm:"column:host_user_id;size:64;index:host_user_id"`
+ Status int64 `gorm:"column:status;index:status,priority:2"`
+ StartTime int64 `gorm:"column:start_time"`
+ EndTime int64 `gorm:"column:end_time"`
+ CreateTime time.Time `gorm:"column:create_time"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (MeetingInfo) TableName() string {
+ return "meeting"
+}
+
+type MeetingInvitationInfo struct {
+ RoomID string `gorm:"column:room_id;primary_key;size:128"`
+ UserID string `gorm:"column:user_id;primary_key;size:64;index:user_id"`
+ CreateTime time.Time `gorm:"column:create_time"`
+}
+
+func (MeetingInvitationInfo) TableName() string {
+ return "meeting_invitation"
+}
+
+type MeetingVideoRecord struct {
+ RoomID string `gorm:"column:room_id;size:128"`
+ FileURL string `gorm:"column:file_url"`
+ CreateTime time.Time `gorm:"column:create_time"`
+}
+
+func (MeetingVideoRecord) TableName() string {
+ return "meeting_video_record"
+}
diff --git a/tools/up35/pkg/internal/rtc/mysql/signal.go b/tools/up35/pkg/internal/rtc/mysql/signal.go
new file mode 100644
index 000000000..3a4d607d4
--- /dev/null
+++ b/tools/up35/pkg/internal/rtc/mysql/signal.go
@@ -0,0 +1,43 @@
+package relation
+
+import (
+ "time"
+)
+
+type SignalModel struct {
+ SID string `gorm:"column:sid;type:char(128);primary_key"`
+ InviterUserID string `gorm:"column:inviter_user_id;type:char(64);index:inviter_user_id_index"`
+ CustomData string `gorm:"column:custom_data;type:text"`
+ GroupID string `gorm:"column:group_id;type:char(64)"`
+ RoomID string `gorm:"column:room_id;primary_key;type:char(128)"`
+ Timeout int32 `gorm:"column:timeout"`
+ MediaType string `gorm:"column:media_type;type:char(64)"`
+ PlatformID int32 `gorm:"column:platform_id"`
+ SessionType int32 `gorm:"column:sesstion_type"`
+ InitiateTime time.Time `gorm:"column:initiate_time"`
+ EndTime time.Time `gorm:"column:end_time"`
+ FileURL string `gorm:"column:file_url" json:"-"`
+
+ Title string `gorm:"column:title;size:128"`
+ Desc string `gorm:"column:desc;size:1024"`
+ Ex string `gorm:"column:ex;size:1024"`
+ IOSPushSound string `gorm:"column:ios_push_sound"`
+ IOSBadgeCount bool `gorm:"column:ios_badge_count"`
+ SignalInfo string `gorm:"column:signal_info;size:1024"`
+}
+
+func (SignalModel) TableName() string {
+ return "signal"
+}
+
+type SignalInvitationModel struct {
+ UserID string `gorm:"column:user_id;primary_key"`
+ SID string `gorm:"column:sid;type:char(128);primary_key"`
+ Status int32 `gorm:"column:status"`
+ InitiateTime time.Time `gorm:"column:initiate_time;primary_key"`
+ HandleTime time.Time `gorm:"column:handle_time"`
+}
+
+func (SignalInvitationModel) TableName() string {
+ return "signal_invitation"
+}
diff --git a/tools/up35/pkg/pkg.go b/tools/up35/pkg/pkg.go
new file mode 100644
index 000000000..d834b8492
--- /dev/null
+++ b/tools/up35/pkg/pkg.go
@@ -0,0 +1,206 @@
+package pkg
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "gopkg.in/yaml.v3"
+ "log"
+ "os"
+ "reflect"
+ "strconv"
+
+ "github.com/go-sql-driver/mysql"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ gormMysql "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+ "gorm.io/gorm/logger"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/config"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
+ rtcMgo "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/mgo"
+)
+
+const (
+ versionTable = "dataver"
+ versionKey = "data_version"
+ versionValue = 35
+)
+
+func InitConfig(path string) error {
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return err
+ }
+ return yaml.Unmarshal(data, &config.Config)
+}
+
+func GetMysql() (*gorm.DB, error) {
+ conf := config.Config.Mysql
+ mysqlDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.Username, conf.Password, conf.Address[0], conf.Database)
+ return gorm.Open(gormMysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard})
+}
+
+func GetMongo() (*mongo.Database, error) {
+ mgo, err := unrelation.NewMongo()
+ if err != nil {
+ return nil, err
+ }
+ return mgo.GetDatabase(), nil
+}
+
+func Main(path string) error {
+ if err := InitConfig(path); err != nil {
+ return err
+ }
+ if config.Config.Mysql == nil {
+ return nil
+ }
+ mongoDB, err := GetMongo()
+ if err != nil {
+ return err
+ }
+ var version struct {
+ Key string `bson:"key"`
+ Value string `bson:"value"`
+ }
+ switch mongoDB.Collection(versionTable).FindOne(context.Background(), bson.M{"key": versionKey}).Decode(&version) {
+ case nil:
+ if ver, _ := strconv.Atoi(version.Value); ver >= versionValue {
+ return nil
+ }
+ case mongo.ErrNoDocuments:
+ default:
+ return err
+ }
+ mysqlDB, err := GetMysql()
+ if err != nil {
+ if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1049 {
+ if err := SetMongoDataVersion(mongoDB, version.Value); err != nil {
+ return err
+ }
+ return nil // database not exist
+ }
+ return err
+ }
+
+ var c convert
+ var tasks []func() error
+ tasks = append(tasks,
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewUserMongo, c.User) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendMongo, c.Friend) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendRequestMongo, c.FriendRequest) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewBlackMongo, c.Black) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMongo, c.Group) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMember, c.GroupMember) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupRequestMgo, c.GroupRequest) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewConversationMongo, c.Conversation) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewS3Mongo, c.Object(config.Config.Object.Enable)) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewLogMongo, c.Log) },
+
+ func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewSignal, c.SignalModel) },
+ func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewSignalInvitation, c.SignalInvitationModel) },
+ func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeeting, c.Meeting) },
+ func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeetingInvitation, c.MeetingInvitationInfo) },
+ func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeetingRecord, c.MeetingVideoRecord) },
+ )
+
+ for _, task := range tasks {
+ if err := task(); err != nil {
+ return err
+ }
+ }
+
+ if err := SetMongoDataVersion(mongoDB, version.Value); err != nil {
+ return err
+ }
+ return nil
+}
+
+func SetMongoDataVersion(db *mongo.Database, curver string) error {
+ filter := bson.M{"key": versionKey, "value": curver}
+ update := bson.M{"$set": bson.M{"key": versionKey, "value": strconv.Itoa(versionValue)}}
+ _, err := db.Collection(versionTable).UpdateOne(context.Background(), filter, update, options.Update().SetUpsert(true))
+ return err
+}
+
+// NewTask A mysql table B mongodb model C mongodb table
+func NewTask[A interface{ TableName() string }, B any, C any](gormDB *gorm.DB, mongoDB *mongo.Database, mongoDBInit func(db *mongo.Database) (B, error), convert func(v A) C) error {
+ obj, err := mongoDBInit(mongoDB)
+ if err != nil {
+ return err
+ }
+ var zero A
+ tableName := zero.TableName()
+ coll, err := getColl(obj)
+ if err != nil {
+ return fmt.Errorf("get mongo collection %s failed, err: %w", tableName, err)
+ }
+ var count int
+ defer func() {
+ log.Printf("completed convert %s total %d\n", tableName, count)
+ }()
+ const batch = 100
+ for page := 0; ; page++ {
+ res := make([]A, 0, batch)
+ if err := gormDB.Limit(batch).Offset(page * batch).Find(&res).Error; err != nil {
+ if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1146 {
+ return nil // table not exist
+ }
+ return fmt.Errorf("find mysql table %s failed, err: %w", tableName, err)
+ }
+ if len(res) == 0 {
+ return nil
+ }
+ temp := make([]any, len(res))
+ for i := range res {
+ temp[i] = convert(res[i])
+ }
+ if err := insertMany(coll, temp); err != nil {
+ return fmt.Errorf("insert mongo table %s failed, err: %w", tableName, err)
+ }
+ count += len(res)
+ if len(res) < batch {
+ return nil
+ }
+ log.Printf("current convert %s completed %d\n", tableName, count)
+ }
+}
+
+func insertMany(coll *mongo.Collection, objs []any) error {
+ if _, err := coll.InsertMany(context.Background(), objs); err != nil {
+ if !mongo.IsDuplicateKeyError(err) {
+ return err
+ }
+ }
+ for i := range objs {
+ _, err := coll.InsertOne(context.Background(), objs[i])
+ switch {
+ case err == nil:
+ case mongo.IsDuplicateKeyError(err):
+ default:
+ return err
+ }
+ }
+ return nil
+}
+
+func getColl(obj any) (_ *mongo.Collection, err error) {
+ defer func() {
+ if e := recover(); e != nil {
+ err = fmt.Errorf("not found %+v", e)
+ }
+ }()
+ stu := reflect.ValueOf(obj).Elem()
+ typ := reflect.TypeOf(&mongo.Collection{}).String()
+ for i := 0; i < stu.NumField(); i++ {
+ field := stu.Field(i)
+ if field.Type().String() == typ {
+ return (*mongo.Collection)(field.UnsafePointer()), nil
+ }
+ }
+ return nil, errors.New("not found")
+}
diff --git a/tools/up35/up35.go b/tools/up35/up35.go
index 5d4740fca..0ce56ee13 100644
--- a/tools/up35/up35.go
+++ b/tools/up35/up35.go
@@ -1,367 +1,19 @@
package main
import (
- "context"
- "errors"
"flag"
- "fmt"
- "github.com/go-sql-driver/mysql"
- "github.com/openimsdk/open-im-server/v3/pkg/common/config"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
- mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
- mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
- "go.mongodb.org/mongo-driver/bson"
- "go.mongodb.org/mongo-driver/mongo"
- "go.mongodb.org/mongo-driver/mongo/options"
- "gopkg.in/yaml.v3"
- gormMysql "gorm.io/driver/mysql"
- "gorm.io/gorm"
- "gorm.io/gorm/logger"
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg"
"log"
"os"
- "reflect"
- "strconv"
-)
-
-const (
- versionTable = "dataver"
- versionKey = "data_version"
- versionValue = 35
)
func main() {
var path string
flag.StringVar(&path, "c", "", "path config file")
flag.Parse()
- if err := Main(path); err != nil {
+ if err := pkg.Main(path); err != nil {
log.Fatal(err)
return
}
os.Exit(0)
}
-
-func InitConfig(path string) error {
- data, err := os.ReadFile(path)
- if err != nil {
- return err
- }
- return yaml.Unmarshal(data, &config.Config)
-}
-
-func GetMysql() (*gorm.DB, error) {
- conf := config.Config.Mysql
- mysqlDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.Username, conf.Password, conf.Address[0], conf.Database)
- return gorm.Open(gormMysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard})
-}
-
-func GetMongo() (*mongo.Database, error) {
- mgo, err := unrelation.NewMongo()
- if err != nil {
- return nil, err
- }
- return mgo.GetDatabase(), nil
-}
-
-func Main(path string) error {
- if err := InitConfig(path); err != nil {
- return err
- }
- if config.Config.Mysql == nil {
- return nil
- }
- mongoDB, err := GetMongo()
- if err != nil {
- return err
- }
- var version struct {
- Key string `bson:"key"`
- Value string `bson:"value"`
- }
- switch mongoDB.Collection(versionTable).FindOne(context.Background(), bson.M{"key": versionKey}).Decode(&version) {
- case nil:
- if ver, _ := strconv.Atoi(version.Value); ver >= versionValue {
- return nil
- }
- case mongo.ErrNoDocuments:
- default:
- return err
- }
- mysqlDB, err := GetMysql()
- if err != nil {
- if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1049 {
- if err := SetMongoDataVersion(mongoDB, version.Value); err != nil {
- return err
- }
- return nil // database not exist
- }
- return err
- }
-
- var c convert
- var tasks []func() error
- tasks = append(tasks,
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewUserMongo, c.User) },
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendMongo, c.Friend) },
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendRequestMongo, c.FriendRequest) },
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewBlackMongo, c.Black) },
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMongo, c.Group) },
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMember, c.GroupMember) },
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupRequestMgo, c.GroupRequest) },
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewConversationMongo, c.Conversation) },
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewS3Mongo, c.Object(config.Config.Object.Enable)) },
- func() error { return NewTask(mysqlDB, mongoDB, mgo.NewLogMongo, c.Log) },
- )
-
- for _, task := range tasks {
- if err := task(); err != nil {
- return err
- }
- }
-
- if err := SetMongoDataVersion(mongoDB, version.Value); err != nil {
- return err
- }
- return nil
-}
-
-func SetMongoDataVersion(db *mongo.Database, curver string) error {
- filter := bson.M{"key": versionKey, "value": curver}
- update := bson.M{"$set": bson.M{"key": versionKey, "value": strconv.Itoa(versionValue)}}
- _, err := db.Collection(versionTable).UpdateOne(context.Background(), filter, update, options.Update().SetUpsert(true))
- return err
-}
-
-// NewTask A mysql table B mongodb model C mongodb table
-func NewTask[A interface{ TableName() string }, B any, C any](gormDB *gorm.DB, mongoDB *mongo.Database, mongoDBInit func(db *mongo.Database) (B, error), convert func(v A) C) error {
- obj, err := mongoDBInit(mongoDB)
- if err != nil {
- return err
- }
- var zero A
- tableName := zero.TableName()
- coll, err := getColl(obj)
- if err != nil {
- return fmt.Errorf("get mongo collection %s failed, err: %w", tableName, err)
- }
- var count int
- defer func() {
- log.Printf("completed convert %s total %d\n", tableName, count)
- }()
- const batch = 100
- for page := 0; ; page++ {
- res := make([]A, 0, batch)
- if err := gormDB.Limit(batch).Offset(page * batch).Find(&res).Error; err != nil {
- if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1146 {
- return nil // table not exist
- }
- return fmt.Errorf("find mysql table %s failed, err: %w", tableName, err)
- }
- if len(res) == 0 {
- return nil
- }
- temp := make([]any, len(res))
- for i := range res {
- temp[i] = convert(res[i])
- }
- if err := insertMany(coll, temp); err != nil {
- return fmt.Errorf("insert mongo table %s failed, err: %w", tableName, err)
- }
- count += len(res)
- if len(res) < batch {
- return nil
- }
- log.Printf("current convert %s completed %d\n", tableName, count)
- }
-}
-
-func insertMany(coll *mongo.Collection, objs []any) error {
- if _, err := coll.InsertMany(context.Background(), objs); err != nil {
- if !mongo.IsDuplicateKeyError(err) {
- return err
- }
- }
- for i := range objs {
- _, err := coll.InsertOne(context.Background(), objs[i])
- switch {
- case err == nil:
- case mongo.IsDuplicateKeyError(err):
- default:
- return err
- }
- }
- return nil
-}
-
-func getColl(obj any) (_ *mongo.Collection, err error) {
- defer func() {
- if e := recover(); e != nil {
- err = fmt.Errorf("not found %+v", e)
- }
- }()
- stu := reflect.ValueOf(obj).Elem()
- typ := reflect.TypeOf(&mongo.Collection{}).String()
- for i := 0; i < stu.NumField(); i++ {
- field := stu.Field(i)
- if field.Type().String() == typ {
- return (*mongo.Collection)(field.UnsafePointer()), nil
- }
- }
- return nil, errors.New("not found")
-}
-
-type convert struct{}
-
-func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel {
- return mongoModel.UserModel{
- UserID: v.UserID,
- Nickname: v.Nickname,
- FaceURL: v.FaceURL,
- Ex: v.Ex,
- AppMangerLevel: v.AppMangerLevel,
- GlobalRecvMsgOpt: v.GlobalRecvMsgOpt,
- CreateTime: v.CreateTime,
- }
-}
-
-func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel {
- return mongoModel.FriendModel{
- OwnerUserID: v.OwnerUserID,
- FriendUserID: v.FriendUserID,
- Remark: v.Remark,
- CreateTime: v.CreateTime,
- AddSource: v.AddSource,
- OperatorUserID: v.OperatorUserID,
- Ex: v.Ex,
- }
-}
-
-func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendRequestModel {
- return mongoModel.FriendRequestModel{
- FromUserID: v.FromUserID,
- ToUserID: v.ToUserID,
- HandleResult: v.HandleResult,
- ReqMsg: v.ReqMsg,
- CreateTime: v.CreateTime,
- HandlerUserID: v.HandlerUserID,
- HandleMsg: v.HandleMsg,
- HandleTime: v.HandleTime,
- Ex: v.Ex,
- }
-}
-
-func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel {
- return mongoModel.BlackModel{
- OwnerUserID: v.OwnerUserID,
- BlockUserID: v.BlockUserID,
- CreateTime: v.CreateTime,
- AddSource: v.AddSource,
- OperatorUserID: v.OperatorUserID,
- Ex: v.Ex,
- }
-}
-
-func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel {
- return mongoModel.GroupModel{
- GroupID: v.GroupID,
- GroupName: v.GroupName,
- Notification: v.Notification,
- Introduction: v.Introduction,
- FaceURL: v.FaceURL,
- CreateTime: v.CreateTime,
- Ex: v.Ex,
- Status: v.Status,
- CreatorUserID: v.CreatorUserID,
- GroupType: v.GroupType,
- NeedVerification: v.NeedVerification,
- LookMemberInfo: v.LookMemberInfo,
- ApplyMemberFriend: v.ApplyMemberFriend,
- NotificationUpdateTime: v.NotificationUpdateTime,
- NotificationUserID: v.NotificationUserID,
- }
-}
-
-func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMemberModel {
- return mongoModel.GroupMemberModel{
- GroupID: v.GroupID,
- UserID: v.UserID,
- Nickname: v.Nickname,
- FaceURL: v.FaceURL,
- RoleLevel: v.RoleLevel,
- JoinTime: v.JoinTime,
- JoinSource: v.JoinSource,
- InviterUserID: v.InviterUserID,
- OperatorUserID: v.OperatorUserID,
- MuteEndTime: v.MuteEndTime,
- Ex: v.Ex,
- }
-}
-
-func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequestModel {
- return mongoModel.GroupRequestModel{
- UserID: v.UserID,
- GroupID: v.GroupID,
- HandleResult: v.HandleResult,
- ReqMsg: v.ReqMsg,
- HandledMsg: v.HandledMsg,
- ReqTime: v.ReqTime,
- HandleUserID: v.HandleUserID,
- HandledTime: v.HandledTime,
- JoinSource: v.JoinSource,
- InviterUserID: v.InviterUserID,
- Ex: v.Ex,
- }
-}
-
-func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.ConversationModel {
- return mongoModel.ConversationModel{
- OwnerUserID: v.OwnerUserID,
- ConversationID: v.ConversationID,
- ConversationType: v.ConversationType,
- UserID: v.UserID,
- GroupID: v.GroupID,
- RecvMsgOpt: v.RecvMsgOpt,
- IsPinned: v.IsPinned,
- IsPrivateChat: v.IsPrivateChat,
- BurnDuration: v.BurnDuration,
- GroupAtType: v.GroupAtType,
- AttachedInfo: v.AttachedInfo,
- Ex: v.Ex,
- MaxSeq: v.MaxSeq,
- MinSeq: v.MinSeq,
- CreateTime: v.CreateTime,
- IsMsgDestruct: v.IsMsgDestruct,
- MsgDestructTime: v.MsgDestructTime,
- LatestMsgDestructTime: v.LatestMsgDestructTime,
- }
-}
-
-func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
- return func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
- return mongoModel.ObjectModel{
- Name: v.Name,
- UserID: v.UserID,
- Hash: v.Hash,
- Engine: engine,
- Key: v.Key,
- Size: v.Size,
- ContentType: v.ContentType,
- Group: v.Cause,
- CreateTime: v.CreateTime,
- }
- }
-}
-
-func (convert) Log(v mysqlModel.Log) mongoModel.LogModel {
- return mongoModel.LogModel{
- LogID: v.LogID,
- Platform: v.Platform,
- UserID: v.UserID,
- CreateTime: v.CreateTime,
- Url: v.Url,
- FileName: v.FileName,
- SystemType: v.SystemType,
- Version: v.Version,
- Ex: v.Ex,
- }
-}
From bb4463349e5ae3759cb96c3ac80b16597f1eae3a Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Tue, 12 Dec 2023 16:44:02 +0800
Subject: [PATCH 012/110] feat: add openim docker compose and env (#1550)
* feat: add openim docker compose
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add openim env
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add openim env
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add openim fix env
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---
config/templates/README.md | 36 ++
config/templates/alertmanager.yml.template | 33 ++
config/templates/config.yaml.template | 506 +++++++++++++++++++++
config/templates/env.template | 249 ++++++++++
config/templates/prometheus.yml.template | 85 ++++
deployments/templates/env-template.yaml | 23 +-
docker-compose.yml | 118 +++--
docs/contrib/util-makefile.md | 2 +-
scripts/init-config.sh | 167 +++++--
9 files changed, 1093 insertions(+), 126 deletions(-)
create mode 100644 config/templates/README.md
create mode 100644 config/templates/alertmanager.yml.template
create mode 100644 config/templates/config.yaml.template
create mode 100644 config/templates/env.template
create mode 100644 config/templates/prometheus.yml.template
diff --git a/config/templates/README.md b/config/templates/README.md
new file mode 100644
index 000000000..6a979c6bb
--- /dev/null
+++ b/config/templates/README.md
@@ -0,0 +1,36 @@
+# Examples Directory
+
+Welcome to the `examples` directory of our project! This directory contains a collection of example files that demonstrate various configurations and setups for our software. These examples are designed to provide you with templates that can be used as a starting point for your own configurations.
+
+## Overview
+
+In this directory, you'll find examples for a variety of use cases. Each file is a template with default values and configurations that illustrate best practices and typical scenarios. Whether you're just getting started or looking to implement a complex setup, these examples should help you get on the right track.
+
+## Structure
+
+Here's a quick overview of what you'll find in this directory:
+
++ `env-example.yaml`: Demonstrates how to set up environment variables.
++ `openim-example.yaml`: A sample configuration file for the OpenIM application.
++ `prometheus-example.yml`: An example Prometheus configuration for monitoring.
++ `alertmanager-example.yml`: A template for setting up Alertmanager configurations.
+
+## How to Use These Examples
+
+To use these examples, simply copy the relevant file to your working directory and rename it as needed (e.g., removing the `-example` suffix). Then, modify the file according to your requirements.
+
+### Tips for Using Example Files:
+
+1. **Read the Comments**: Each file contains comments that explain various sections and settings. Make sure to read these comments for a better understanding of how to customize the file.
+2. **Check for Required Changes**: Some examples might require mandatory changes (like setting specific environment variables) before they can be used effectively.
+3. **Version Compatibility**: Ensure that the example files are compatible with the version of the software you are using.
+
+## Contributing
+
+If you have a configuration that you believe would be beneficial to others, please feel free to contribute by opening a pull request with your proposed changes. We appreciate contributions that expand our examples with new scenarios and use cases.
+
+## Support
+
+If you encounter any issues or have questions regarding the example files, please open an issue on our repository. Our community is here to help you navigate through any challenges you might face.
+
+Thank you for exploring our examples, and we hope they will be helpful in setting up and configuring your environment!
diff --git a/config/templates/alertmanager.yml.template b/config/templates/alertmanager.yml.template
new file mode 100644
index 000000000..da5f99b19
--- /dev/null
+++ b/config/templates/alertmanager.yml.template
@@ -0,0 +1,33 @@
+###################### AlertManager Configuration ######################
+# AlertManager configuration using environment variables
+#
+# Resolve timeout
+# SMTP configuration for sending alerts
+# Templates for email notifications
+# Routing configurations for alerts
+# Receiver configurations
+global:
+ resolve_timeout: 5m
+ smtp_from: alert@openim.io
+ smtp_smarthost: smtp.163.com:465
+ smtp_auth_username: alert@openim.io
+ smtp_auth_password: YOURAUTHPASSWORD
+ smtp_require_tls: false
+ smtp_hello: xxx监控告警
+
+templates:
+ - /etc/alertmanager/email.tmpl
+
+route:
+ group_by: ['alertname']
+ group_wait: 5s
+ group_interval: 5s
+ repeat_interval: 5m
+ receiver: email
+receivers:
+ - name: email
+ email_configs:
+ - to: 'alert@example.com'
+ html: '{{ template "email.to.html" . }}'
+ headers: { Subject: "[OPENIM-SERVER]Alarm" }
+ send_resolved: true
diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template
new file mode 100644
index 000000000..a35d06c8c
--- /dev/null
+++ b/config/templates/config.yaml.template
@@ -0,0 +1,506 @@
+# 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.
+
+# -----------------------------------------------------------------
+# TODO: This config file is the template file
+# --| source: deployments/templates/openim.yaml
+# --| env: scripts/install/environment
+# --| target: config/config.yaml
+# -----------------------------------------------------------------
+
+envs:
+ discovery: zookeeper
+
+###################### Zookeeper ######################
+# Zookeeper configuration
+# It's not recommended to modify the schema
+#
+# Zookeeper address
+# Zookeeper username
+# Zookeeper password
+zookeeper:
+ schema: openim
+ address: [ 172.28.0.1:12181 ]
+ username: ''
+ password: ''
+
+###################### Mongo ######################
+# MongoDB configuration
+# If uri is not empty, it will be used directly
+#
+# MongoDB address for standalone setup, Mongos address for sharded cluster setup
+# Default MongoDB database name
+# Maximum connection pool size
+mongo:
+ uri: ''
+ address: [ 172.28.0.1:37017 ]
+ database: openIM_v3
+ username: root
+ password: openIM123
+ maxPoolSize: 100
+
+###################### Redis configuration information ######################
+# Redis configuration
+#
+# Username is required only for Redis version 6.0+
+redis:
+ address: [ 172.28.0.1:16379 ]
+ username: ''
+ password: openIM123
+
+###################### Kafka configuration information ######################
+# Kafka configuration
+#
+# Kafka username
+# Kafka password
+# It's not recommended to modify this topic name
+# Consumer group ID, it's not recommended to modify
+kafka:
+ username: ''
+ password: ''
+ addr: [ 172.28.0.1:19094 ]
+ latestMsgToRedis:
+ topic: "latestMsgToRedis"
+ offlineMsgToMongo:
+ topic: "offlineMsgToMongoMysql"
+ msgToPush:
+ topic: "msgToPush"
+ consumerGroupID:
+ msgToRedis: redis
+ msgToMongo: mongo
+ msgToMySql: mysql
+ msgToPush: push
+
+###################### RPC configuration information ######################
+# RPC configuration
+#
+# IP address to register with zookeeper when starting RPC, the IP and corresponding rpcPort should be accessible by api/gateway
+# Default listen IP is 0.0.0.0
+rpc:
+ registerIP: ''
+ listenIP: 0.0.0.0
+
+###################### API configuration information ######################
+# API configuration
+#
+# API service port
+# Default listen IP is 0.0.0.0
+api:
+ openImApiPort: [ 10002 ]
+ listenIP: 0.0.0.0
+
+###################### Object configuration information ######################
+# Object storage configuration
+#
+# Use minio for object storage
+# API URL should be accessible by the app
+# It's not recommended to modify the bucket name
+# Endpoint should be accessible by the app
+# 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://172.28.0.1:10002"
+ minio:
+ bucket: "openim"
+ endpoint: "http://172.28.0.1:10005"
+ accessKeyID: "root"
+ secretAccessKey: "openIM123"
+ sessionToken: ''
+ signEndpoint: "http://172.28.0.1:10005"
+ publicRead: false
+ cos:
+ bucketURL: https://temp-1252357374.cos.ap-chengdu.myqcloud.com
+ secretID: ''
+ secretKey: ''
+ sessionToken: ''
+ publicRead: false
+ oss:
+ endpoint: "https://oss-cn-chengdu.aliyuncs.com"
+ bucket: "demo-9999999"
+ bucketURL: "https://demo-9999999.oss-cn-chengdu.aliyuncs.com"
+ accessKeyID: ''
+ accessKeySecret: ''
+ sessionToken: ''
+ publicRead: false
+ kodo:
+ endpoint: "http://s3.cn-east-1.qiniucs.com"
+ bucket: "demo-9999999"
+ bucketURL: "http://your.domain.com"
+ accessKeyID: ''
+ accessKeySecret: ''
+ sessionToken: ''
+ publicRead: false
+
+###################### RPC Port Configuration ######################
+# RPC service ports
+# 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:
+ openImUserPort: [ 10110 ]
+ openImFriendPort: [ 10120 ]
+ openImMessagePort: [ 10130 ]
+ openImGroupPort: [ 10150 ]
+ openImAuthPort: [ 10160 ]
+ openImPushPort: [ 10170 ]
+ openImConversationPort: [ 10180 ]
+ openImThirdPort: [ 10190 ]
+
+###################### RPC Register Name Configuration ######################
+# RPC service names for registration, it's not recommended to modify these
+rpcRegisterName:
+ openImUserName: User
+ openImFriendName: Friend
+ openImMsgName: Msg
+ openImPushName: Push
+ openImMessageGatewayName: MessageGateway
+ openImGroupName: Group
+ openImAuthName: Auth
+ openImConversationName: Conversation
+ openImThirdName: Third
+
+###################### Log Configuration ######################
+# Log configuration
+#
+# Storage directory
+# Log rotation time
+# Maximum number of logs to retain
+# Log level, 6 means all levels
+# Whether to output to stdout
+# 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
+ withStack: false
+
+###################### Variables definition ######################
+# Long connection server configuration
+#
+# Websocket port for msg_gateway
+# Maximum number of websocket connections
+# Maximum length of websocket request package
+# Websocket connection handshake timeout
+longConnSvr:
+ openImWsPort: [ 10001 ]
+ websocketMaxConnNum: 100000
+ openImMessageGatewayPort: [ 10140 ]
+ websocketMaxMsgLen: 4096
+ websocketTimeout: 10
+
+# Push notification service configuration
+#
+# Use GeTui for push notifications
+# GeTui offline push configuration
+# FCM offline push configuration
+# Account file, place it in the config directory
+# JPush configuration, modify these after applying in JPush backend
+push:
+ enable: getui
+ geTui:
+ pushUrl: "https://restapi.getui.com/v2/$appId"
+ masterSecret: ''
+ appKey: ''
+ intent: ''
+ channelID: ''
+ channelName: ''
+ fcm:
+ serviceAccount: "x.json"
+ jpns:
+ appKey: ''
+ masterSecret: ''
+ pushUrl: ''
+ pushIntent: ''
+
+# App manager configuration
+#
+# Built-in app manager user IDs
+# Built-in app manager nicknames
+manager:
+ userID: [ "openIM123456", "openIM654321", "openIMAdmin" ]
+ nickname: [ "system1", "system2", "system3" ]
+
+# Multi-platform login policy
+# For each platform(Android, iOS, Windows, Mac, web), only one can be online at a time
+multiLoginPolicy: 1
+
+# Whether to store messages in MySQL, messages in MySQL are only used for management background
+chatPersistenceMysql: true
+
+# Message cache timeout in seconds, it's not recommended to modify
+msgCacheTimeout: 86400
+
+# Whether to enable read receipts for group chat
+groupMessageHasReadReceiptEnable: true
+
+# Whether to enable read receipts for single chat
+singleMessageHasReadReceiptEnable: true
+
+# MongoDB offline message retention period in days
+retainChatRecords: 365
+
+# Schedule to clear expired messages(older than retainChatRecords days) in MongoDB every Wednesday at 2am
+# This deletion is just for cleaning up disk usage according to previous configuration retainChatRecords, no notification will be sent
+chatRecordsClearTime: "0 2 * * 3"
+
+# Schedule to auto delete messages every day at 2am
+# This deletion is for messages that have been retained for more than msg_destruct_time (seconds) in the conversation field
+msgDestructTime: "0 2 * * *"
+
+# Secret key
+secret: openIM123
+
+# Token policy
+#
+# Token expiration period in days
+tokenPolicy:
+ expire: 90
+
+# Message verification policy
+#
+# Whether to verify friendship when sending messages
+messageVerify:
+ friendVerify: false
+
+# iOS push notification configuration
+#
+# iOS push notification sound
+# Whether to count badge
+# Whether it's production environment
+iosPush:
+ pushSound: "xxx"
+ badgeCount: true
+ production: false
+
+###################### Third-party service configuration ######################
+# Callback configuration
+#
+# Callback URL
+# Whether to enable this callback event
+# Timeout in seconds
+# Whether to continue execution if callback fails
+callback:
+ url: ""
+ beforeSendSingleMsg:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterSendSingleMsg:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ beforeSendGroupMsg:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterSendGroupMsg:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ msgModify:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ userOnline:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ userOffline:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ userKickOff:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ offlinePush:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ onlinePush:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ superGroupOnlinePush:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ beforeAddFriend:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ beforeUpdateUserInfo:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ beforeCreateGroup:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterCreateGroup:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ beforeMemberJoinGroup:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ beforeSetGroupMemberInfo:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterSetGroupMemberInfo:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ setMessageReactionExtensions:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ quitGroup:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ killGroupMember:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ dismissGroup:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ joinGroup:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ groupMsgRead:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ singleMsgRead:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ updateUserInfo:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ beforeUserRegister:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterUserRegister:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ transferGroupOwner:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ beforeSetFriendRemark:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterSetFriendRemark:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterGroupMsgRead:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterGroupMsgRevoke:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterJoinGroup:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ beforeInviteUserToGroup:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ joinGroupAfter:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ setGroupInfoAfter:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ setGroupInfoBefore:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ revokeMsgAfter:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ addBlackBefore:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ addFriendAfter:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ addFriendAgreeBefore:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ deleteFriendAfter:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ importFriendsBefore:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ importFriendsAfter:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ removeBlackAfter:
+ enable: false
+ timeout: 5
+ failedContinue: true
+###################### Prometheus ######################
+# Prometheus configuration for various services
+# The number of Prometheus ports per service needs to correspond to rpcPort
+# The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh
+prometheus:
+ enable: false
+ prometheusUrl: 172.28.0.1:13000
+ apiPrometheusPort: [20100]
+ userPrometheusPort: [ 20110 ]
+ friendPrometheusPort: [ 20120 ]
+ messagePrometheusPort: [ 20130 ]
+ messageGatewayPrometheusPort: [ 20140 ]
+ groupPrometheusPort: [ 20150 ]
+ authPrometheusPort: [ 20160 ]
+ pushPrometheusPort: [ 20170 ]
+ conversationPrometheusPort: [ 20230 ]
+ rtcPrometheusPort: [ 21300 ]
+ thirdPrometheusPort: [ 21301 ]
+ messageTransferPrometheusPort: [ 21400, 21401, 21402, 21403 ] # List of ports
diff --git a/config/templates/env.template b/config/templates/env.template
new file mode 100644
index 000000000..e47a9c073
--- /dev/null
+++ b/config/templates/env.template
@@ -0,0 +1,249 @@
+# ======================================
+# ========= Basic Configuration ========
+# ======================================
+
+# The user for authentication or system operations.
+# Default: OPENIM_USER=root
+USER=root
+
+# Password associated with the specified user for authentication.
+# Default: PASSWORD=openIM123
+PASSWORD=openIM123
+
+# Endpoint for the MinIO object storage service.
+# Default: MINIO_ENDPOINT=http://172.28.0.1:10005
+MINIO_ENDPOINT=http://172.28.0.1:10005
+
+# Base URL for the application programming interface (API).
+# Default: API_URL=http://172.28.0.1:10002
+API_URL=http://172.28.0.1:10002
+
+# Directory path for storing data files or related information.
+# Default: DATA_DIR=./
+DATA_DIR=./
+
+# Choose the appropriate image address, the default is GITHUB image,
+# you can choose docker hub, for Chinese users can choose Ali Cloud
+# export IMAGE_REGISTRY="ghcr.io/openimsdk"
+# export IMAGE_REGISTRY="openim"
+# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
+IMAGE_REGISTRY=ghcr.io/openimsdk
+
+# ======================================
+# ========= Network Configuration ======
+# ======================================
+
+# Subnet for the Docker network.
+# Default: DOCKER_BRIDGE_SUBNET=172.28.0.0/16
+DOCKER_BRIDGE_SUBNET=172.28.0.0/16
+
+# Gateway for the Docker network.
+# Default: DOCKER_BRIDGE_GATEWAY=172.28.0.1
+DOCKER_BRIDGE_GATEWAY=172.28.0.1
+
+MONGO_NETWORK_ADDRESS=172.28.0.2
+REDIS_NETWORK_ADDRESS=172.28.0.3
+KAFKA_NETWORK_ADDRESS=172.28.0.4
+ZOOKEEPER_NETWORK_ADDRESS=172.28.0.5
+MINIO_NETWORK_ADDRESS=172.28.0.6
+OPENIM_WEB_NETWORK_ADDRESS=172.28.0.7
+OPENIM_SERVER_NETWORK_ADDRESS=172.28.0.8
+OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.9
+PROMETHEUS_NETWORK_ADDRESS=172.28.0.10
+GRAFANA_NETWORK_ADDRESS=172.28.0.11
+NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.12
+OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=172.28.0.13
+ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.14
+
+# ===============================================
+# = Component Extension Configuration =
+# ===============================================
+
+# ============ Component Extension Configuration ==========
+# ----- ZooKeeper Configuration -----
+# Address or hostname for the ZooKeeper service.
+# Default: ZOOKEEPER_ADDRESS=172.28.0.1
+ZOOKEEPER_ADDRESS=172.28.0.5
+
+# Port for ZooKeeper service.
+# Default: ZOOKEEPER_PORT=12181
+ZOOKEEPER_PORT=12181
+
+# ----- MongoDB Configuration -----
+# Address or hostname for the MongoDB service.
+# Default: MONGO_ADDRESS=172.28.0.1
+MONGO_ADDRESS=172.28.0.2
+
+# Port on which MongoDB service is running.
+# Default: MONGO_PORT=37017
+# MONGO_PORT=37017
+
+# Username to authenticate with the MongoDB service.
+# Default: MONGO_USERNAME=root
+# MONGO_USERNAME=root
+
+# Password to authenticate with the MongoDB service.
+# Default: MONGO_PASSWORD=openIM123
+MONGO_PASSWORD=openIM123
+
+# Name of the database in MongoDB to be used.
+# Default: MONGO_DATABASE=openIM_v3
+MONGO_DATABASE=openIM_v3
+
+# ----- Redis Configuration -----
+# Address or hostname for the Redis service.
+# Default: REDIS_ADDRESS=172.28.0.1
+REDIS_ADDRESS=172.28.0.3
+
+# Port on which Redis in-memory data structure store is running.
+# Default: REDIS_PORT=16379
+REDIS_PORT=16379
+
+# Password to authenticate with the Redis service.
+# Default: REDIS_PASSWORD=openIM123
+REDIS_PASSWORD=openIM123
+
+# ----- Kafka Configuration -----
+# Address or hostname for the Kafka service.
+# Default: KAFKA_ADDRESS=172.28.0.1
+KAFKA_ADDRESS=172.28.0.4
+
+# Kakfa username to authenticate with the Kafka service.
+# KAFKA_USERNAME=''
+
+# Port on which Kafka distributed streaming platform is running.
+# Default: KAFKA_PORT=19092
+KAFKA_PORT=19094
+
+# Topic in Kafka for storing the latest messages in Redis.
+# Default: KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis
+KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis
+
+# Topic in Kafka for pushing messages (e.g. notifications or updates).
+# Default: KAFKA_MSG_PUSH_TOPIC=msgToPush
+KAFKA_MSG_PUSH_TOPIC=msgToPush
+
+# Topic in Kafka for storing offline messages in MongoDB.
+# Default: KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql
+KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql
+
+# ----- MinIO Configuration ----
+# Address or hostname for the MinIO object storage service.
+# Default: MINIO_ADDRESS=172.28.0.1
+MINIO_ADDRESS=172.28.0.6
+
+# Port on which MinIO object storage service is running.
+# Default: MINIO_PORT=10005
+MINIO_PORT=10005
+
+# Access key to authenticate with the MinIO service.
+# Default: MINIO_ACCESS_KEY=root
+# MINIO_ACCESS_KEY=root
+
+# Secret key corresponding to the access key for MinIO authentication.
+# Default: MINIO_SECRET_KEY=openIM123
+MINIO_SECRET_KEY=openIM123
+
+# ----- Prometheus Configuration -----
+# Address or hostname for the Prometheus service.
+# Default: PROMETHEUS_ADDRESS=172.28.0.1
+PROMETHEUS_ADDRESS=172.28.0.10
+
+# Port on which Prometheus service is running.
+# Default: PROMETHEUS_PORT=19090
+PROMETHEUS_PORT=19090
+
+# ----- Grafana Configuration -----
+# Address or hostname for the Grafana service.
+# Default: GRAFANA_ADDRESS=172.28.0.1
+GRAFANA_ADDRESS=172.28.0.11
+
+# Port on which Grafana service is running.
+# Default: GRAFANA_PORT=13000
+GRAFANA_PORT=13000
+
+# ======================================
+# ============ OpenIM Web ===============
+# ======================================
+
+# Path to the OpenIM web distribution.
+# Default: OPENIM_WEB_DIST_PATH=/app/dist
+OPENIM_WEB_DIST_PATH=/app/dist
+
+# Port on which OpenIM web service is running.
+# Default: OPENIM_WEB_PORT=11001
+OPENIM_WEB_PORT=11001
+
+# Address or hostname for the OpenIM web service.
+# Default: OPENIM_WEB_ADDRESS=172.28.0.1
+OPENIM_WEB_ADDRESS=172.28.0.7
+
+# ======================================
+# ========= OpenIM Server ==============
+# ======================================
+
+# Address or hostname for the OpenIM server.
+# Default: OPENIM_SERVER_ADDRESS=172.28.0.1
+OPENIM_SERVER_ADDRESS=172.28.0.8
+
+# Port for the OpenIM WebSockets.
+# Default: OPENIM_WS_PORT=10001
+OPENIM_WS_PORT=10001
+
+# Port for the OpenIM API.
+# Default: API_OPENIM_PORT=10002
+API_OPENIM_PORT=10002
+
+
+# ======================================
+# ========== OpenIM Chat ===============
+# ======================================
+
+# Branch name for OpenIM chat.
+# Default: CHAT_BRANCH=main
+CHAT_BRANCH=main
+
+# Address or hostname for the OpenIM chat service.
+# Default: OPENIM_CHAT_ADDRESS=172.28.0.1
+OPENIM_CHAT_ADDRESS=172.28.0.9
+
+# Port for the OpenIM chat API.
+# Default: OPENIM_CHAT_API_PORT=10008
+OPENIM_CHAT_API_PORT=10008
+
+# Directory path for storing data files or related information for OpenIM chat.
+# Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main
+OPENIM_CHAT_DATA_DIR=./openim-chat/main
+
+
+# ======================================
+# ========== OpenIM Admin ==============
+# ======================================
+
+# Branch name for OpenIM server.
+# Default: SERVER_BRANCH=main
+SERVER_BRANCH=main
+
+# Port for the OpenIM admin API.
+# Default: OPENIM_ADMIN_API_PORT=10009
+OPENIM_ADMIN_API_PORT=10009
+
+# Port for the node exporter.
+# Default: NODE_EXPORTER_PORT=19100
+NODE_EXPORTER_PORT=19100
+
+# Port for the prometheus.
+# Default: PROMETHEUS_PORT=19090
+PROMETHEUS_PORT=19090
+
+# Port for the grafana.
+# Default: GRAFANA_PORT=13000
+GRAFANA_PORT=13000
+
+# Port for the admin front.
+# Default: OPENIM_ADMIN_FRONT_PORT=11002
+OPENIM_ADMIN_FRONT_PORT=11002
+
+# Port for the alertmanager.
+# Default: ALERT_MANAGER_PORT=19093
+ALERT_MANAGER_PORT=19093
diff --git a/config/templates/prometheus.yml.template b/config/templates/prometheus.yml.template
new file mode 100644
index 000000000..7950c5d33
--- /dev/null
+++ b/config/templates/prometheus.yml.template
@@ -0,0 +1,85 @@
+# my global config
+global:
+ scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
+ evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
+ # scrape_timeout is set to the global default (10s).
+
+# Alertmanager configuration
+alerting:
+ alertmanagers:
+ - static_configs:
+ - targets: ['172.28.0.1:19093']
+
+# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
+rule_files:
+ - "instance-down-rules.yml"
+# - "first_rules.yml"
+# - "second_rules.yml"
+
+# A scrape configuration containing exactly one endpoint to scrape:
+# Here it's Prometheus itself.
+scrape_configs:
+ # The job name is added as a label "job='job_name'"" to any timeseries scraped from this config.
+ # Monitored information captured by prometheus
+ - job_name: 'node-exporter'
+ static_configs:
+ - targets: [ '172.28.0.1:19100' ]
+ labels:
+ namespace: 'default'
+
+ # prometheus fetches application services
+ - job_name: 'openimserver-openim-api'
+ static_configs:
+ - targets: [ '172.28.0.1:20100' ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-msggateway'
+ static_configs:
+ - targets: [ '172.28.0.1:20140' ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-msgtransfer'
+ static_configs:
+ - targets: [ 172.28.0.1:21400, 172.28.0.1:21401, 172.28.0.1:21402, 172.28.0.1:21403 ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-push'
+ static_configs:
+ - targets: [ '172.28.0.1:20170' ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-rpc-auth'
+ static_configs:
+ - targets: [ '172.28.0.1:20160' ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-rpc-conversation'
+ static_configs:
+ - targets: [ '172.28.0.1:20230' ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-rpc-friend'
+ static_configs:
+ - targets: [ '172.28.0.1:20120' ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-rpc-group'
+ static_configs:
+ - targets: [ '172.28.0.1:20150' ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-rpc-msg'
+ static_configs:
+ - targets: [ '172.28.0.1:20130' ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-rpc-third'
+ static_configs:
+ - targets: [ '172.28.0.1:21301' ]
+ labels:
+ namespace: 'default'
+ - job_name: 'openimserver-openim-rpc-user'
+ static_configs:
+ - targets: [ '172.28.0.1:20110' ]
+ labels:
+ namespace: 'default'
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index 4db838c8e..b62543aba 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -1,17 +1,3 @@
-# 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.
-
# ======================================
# ========= Basic Configuration ========
# ======================================
@@ -90,11 +76,11 @@ MONGO_ADDRESS=${MONGO_NETWORK_ADDRESS}
# Port on which MongoDB service is running.
# Default: MONGO_PORT=37017
-MONGO_PORT=${MONGO_PORT}
+# MONGO_PORT=${MONGO_PORT}
# Username to authenticate with the MongoDB service.
# Default: MONGO_USERNAME=root
-MONGO_USERNAME=${MONGO_USERNAME}
+# MONGO_USERNAME=${MONGO_USERNAME}
# Password to authenticate with the MongoDB service.
# Default: MONGO_PASSWORD=openIM123
@@ -122,6 +108,9 @@ REDIS_PASSWORD=${REDIS_PASSWORD}
# Default: KAFKA_ADDRESS=172.28.0.1
KAFKA_ADDRESS=${KAFKA_NETWORK_ADDRESS}
+# Kakfa username to authenticate with the Kafka service.
+# KAFKA_USERNAME=${KAFKA_USERNAME}
+
# Port on which Kafka distributed streaming platform is running.
# Default: KAFKA_PORT=19092
KAFKA_PORT=${KAFKA_PORT}
@@ -149,7 +138,7 @@ MINIO_PORT=${MINIO_PORT}
# Access key to authenticate with the MinIO service.
# Default: MINIO_ACCESS_KEY=root
-MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
+# MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
# Secret key corresponding to the access key for MinIO authentication.
# Default: MINIO_SECRET_KEY=openIM123
diff --git a/docker-compose.yml b/docker-compose.yml
index 233c8d492..22f57d329 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -7,55 +7,57 @@ networks:
ipam:
driver: default
config:
- - subnet: '${DOCKER_BRIDGE_SUBNET}'
- gateway: '${DOCKER_BRIDGE_GATEWAY}'
+ - subnet: '${DOCKER_BRIDGE_SUBNET:-172.28.0.0/16}'
+ gateway: '${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}'
services:
mongodb:
- image: mongo:6.0.2
+ image: mongo:${MONGODB_IMAGE_VERSION-6.0.2}
ports:
- - "${MONGO_PORT}:27017"
+ - "${MONGO_PORT:-37017}:27017"
container_name: mongo
command: --wiredTigerCacheSizeGB 1 --auth
volumes:
- - "${DATA_DIR}/components/mongodb/data/db:/data/db"
- - "${DATA_DIR}/components/mongodb/data/logs:/data/logs"
- - "${DATA_DIR}/components/mongodb/data/conf:/etc/mongo"
- - ./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro"
+ - "${DATA_DIR:-./}/components/mongodb/data/db:/data/db"
+ - "${DATA_DIR:-./}/components/mongodb/data/logs:/data/logs"
+ - "${DATA_DIR:-./}/components/mongodb/data/conf:/etc/mongo"
+ - ./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro
environment:
- TZ=Asia/Shanghai
- wiredTigerCacheSizeGB=1
- - MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME}
- - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD}
- - MONGO_INITDB_DATABASE=${MONGO_DATABASE}
+ - MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME:-root}
+ - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD:-openIM123}
+ - MONGO_INITDB_DATABASE=${MONGO_DATABASE:-openIM_v3}
restart: always
networks:
server:
- ipv4_address: ${MONGO_NETWORK_ADDRESS}
+ ipv4_address: ${MONGO_NETWORK_ADDRESS:-172.28.0.2}
redis:
- image: redis:7.0.0
+ # image: redis:7.0.0
+ image: redis:${REDIS_IMAGE_VERSION:-7.0.0}
container_name: redis
ports:
- - "${REDIS_PORT}:6379"
+ - "${REDIS_PORT:-16379}:6379"
volumes:
- - "${DATA_DIR}/components/redis/data:/data"
- - "${DATA_DIR}/components/redis/config/redis.conf:/usr/local/redis/config/redis.conf"
+ - "${DATA_DIR:-./}/components/redis/data:/data"
+ - "${DATA_DIR:-./}/components/redis/config/redis.conf:/usr/local/redis/config/redis.conf"
environment:
TZ: Asia/Shanghai
restart: always
sysctls:
net.core.somaxconn: 1024
- command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes
+ command: redis-server --requirepass ${REDIS_PASSWORD:-openIM123} --appendonly yes
networks:
server:
- ipv4_address: ${REDIS_NETWORK_ADDRESS}
+ ipv4_address: ${REDIS_NETWORK_ADDRESS:-172.28.0.3}
zookeeper:
- image: bitnami/zookeeper:3.8
+ # image: bitnami/zookeeper:3.8
+ image: bitnami/zookeeper:${ZOOKEEPER_IMAGE_VERSION:-3.8}
container_name: zookeeper
ports:
- - "${ZOOKEEPER_PORT}:2181"
+ - "${ZOOKEEPER_PORT:-12181}:2181"
volumes:
- "/etc/localtime:/etc/localtime"
environment:
@@ -64,81 +66,77 @@ services:
restart: always
networks:
server:
- ipv4_address: ${ZOOKEEPER_NETWORK_ADDRESS}
+ ipv4_address: ${ZOOKEEPER_NETWORK_ADDRESS:-172.28.0.5}
kafka:
- image: 'bitnami/kafka:3.5.1'
+ # image: 'bitnami/kafka:3.5.1'
+ image: 'bitnami/kafka:${KAFKA_IMAGE_VERSION:-3.5.1}'
container_name: kafka
- user: root
restart: always
+ user: ${KAFKA_USER:-root}
ports:
- - "${KAFKA_PORT}:9094"
+ - "${KAFKA_PORT:-19094}:9094"
volumes:
- ./scripts/create-topic.sh:/opt/bitnami/kafka/create-topic.sh
- - ${DATA_DIR}/components/kafka:/bitnami/kafka
+ - "${DATA_DIR:-./}/components/kafka:/bitnami/kafka"
command: >
- bash -c "
- /opt/bitnami/scripts/kafka/run.sh & sleep 5; /opt/bitnami/kafka/create-topic.sh; wait
- "
+ bash -c "/opt/bitnami/scripts/kafka/run.sh & sleep 5; /opt/bitnami/kafka/create-topic.sh; wait"
environment:
- TZ=Asia/Shanghai
- KAFKA_CFG_NODE_ID=0
- KAFKA_CFG_PROCESS_ROLES=controller,broker
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@:9093
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
- - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://${DOCKER_BRIDGE_GATEWAY}:${KAFKA_PORT}
+ - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}:${KAFKA_PORT:-19094}
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
networks:
server:
- ipv4_address: ${KAFKA_NETWORK_ADDRESS}
+ ipv4_address: ${KAFKA_NETWORK_ADDRESS:-172.28.0.4}
minio:
- image: minio/minio
+ # image: minio/minio
+ image: minio/minio:${MINIO_IMAGE_VERSION:-latest}
ports:
- - "${MINIO_PORT}:9000"
+ - "${MINIO_PORT:-10005}:9000"
- "9090:9090"
container_name: minio
volumes:
- - "${DATA_DIR}/components/mnt/data:/data"
- - "${DATA_DIR}/components/mnt/config:/root/.minio"
+ - "${DATA_DIR:-./}/components/mnt/data:/data"
+ - "${DATA_DIR:-./}/components/mnt/config:/root/.minio"
environment:
- MINIO_ROOT_USER: "${MINIO_ACCESS_KEY}"
- MINIO_ROOT_PASSWORD: "${MINIO_SECRET_KEY}"
+ MINIO_ROOT_USER: "${MINIO_ACCESS_KEY:-root}"
+ MINIO_ROOT_PASSWORD: "${MINIO_SECRET_KEY:-openIM123}"
restart: always
command: minio server /data --console-address ':9090'
networks:
server:
- ipv4_address: ${MINIO_NETWORK_ADDRESS}
+ ipv4_address: ${MINIO_NETWORK_ADDRESS:-172.28.0.6}
openim-web:
- # image: ghcr.io/openimsdk/openim-web:latest
- # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web:latest
- # image: openim/openim-web:latest
- image: ${IMAGE_REGISTRY}/openim-web:latest
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:latest
+ image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:${OPENIM_WEB_IMAGE_VERSION:-latest}
container_name: openim-web
environment:
- - OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH}
- - OPENIM_WEB_PORT=${OPENIM_WEB_PORT}
+ - OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH:-/app/dist}
+ - OPENIM_WEB_PORT=${OPENIM_WEB_PORT:-11001}
restart: always
ports:
- - "${OPENIM_WEB_PORT}:11001"
+ - "${OPENIM_WEB_PORT:-11001}:11001"
networks:
server:
- ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS}
+ ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7}
+ # Uncomment and configure the following services as needed
# openim-admin:
- # image: ${IMAGE_REGISTRY}/openim-admin-front:v3.4.0
- # # image: ghcr.io/openimsdk/openim-admin-front:v3.4.0
- # # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:v3.4.0
- # # image: openim/openim-admin-front:v3.4.0
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0
# container_name: openim-admin
# restart: always
# ports:
- # - "${OPENIM_ADMIN_FRONT_PORT}:80"
+ # - "${OPENIM_ADMIN_FRONT_PORT:-11002}:80"
# networks:
# server:
- # ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS}
+ # ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS:-172.28.0.13}
# prometheus:
# image: prom/prometheus
@@ -149,10 +147,10 @@ services:
# - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
# - ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml
# ports:
- # - "${PROMETHEUS_PORT}:9090"
+ # - "${PROMETHEUS_PORT:-19090}:9090"
# networks:
# server:
- # ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS}
+ # ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS:-172.28.0.10}
# alertmanager:
# image: prom/alertmanager
@@ -163,10 +161,10 @@ services:
# - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
# - ./config/email.tmpl:/etc/alertmanager/email.tmpl
# ports:
- # - "${ALERT_MANAGER_PORT}:9093"
+ # - "${ALERT_MANAGER_PORT:-19093}:9093"
# networks:
# server:
- # ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS}
+ # ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS:-172.28.0.14}
# grafana:
# image: grafana/grafana
@@ -175,12 +173,12 @@ services:
# user: root
# restart: always
# ports:
- # - "${GRAFANA_PORT}:3000"
+ # - "${GRAFANA_PORT:-13000}:3000"
# volumes:
- # - ${DATA_DIR}/components/grafana:/var/lib/grafana
+ # - ${DATA_DIR:-./}/components/grafana:/var/lib/grafana
# networks:
# server:
- # ipv4_address: ${GRAFANA_NETWORK_ADDRESS}
+ # ipv4_address: ${GRAFANA_NETWORK_ADDRESS:-172.28.0.11}
# node-exporter:
# image: quay.io/prometheus/node-exporter
@@ -188,7 +186,7 @@ services:
# hostname: node-exporter
# restart: always
# ports:
- # - "${NODE_EXPORTER_PORT}:9100"
+ # - "${NODE_EXPORTER_PORT:-19100}:9100"
# networks:
# server:
- # ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS}
+ # ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS:-172.28.0.12}
diff --git a/docs/contrib/util-makefile.md b/docs/contrib/util-makefile.md
index e0331f50e..8bde02874 100644
--- a/docs/contrib/util-makefile.md
+++ b/docs/contrib/util-makefile.md
@@ -30,7 +30,7 @@ Executing `make tools` ensures verification and installation of the default tool
- go-junit-report
- go-gitlint
-The installation path is situated at `/root/workspaces/openim/Open-IM-Server/_output/tools/`.
+The installation path is situated at `./_output/tools/`.
## Toolset Categories
diff --git a/scripts/init-config.sh b/scripts/init-config.sh
index 380239d50..631bd68d7 100755
--- a/scripts/init-config.sh
+++ b/scripts/init-config.sh
@@ -2,7 +2,7 @@
# 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 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
@@ -13,19 +13,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# This script automatically initializes the various configuration files
-# Read: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md
+# This script automatically initializes various configuration files and can generate example files.
set -o errexit
set -o nounset
set -o pipefail
+# Root directory of the OpenIM project
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
+# Source initialization script
source "${OPENIM_ROOT}/scripts/lib/init.sh"
+# Default environment file
readonly ENV_FILE=${ENV_FILE:-"${OPENIM_ROOT}/scripts/install/environment.sh"}
+# Templates for configuration files
declare -A TEMPLATES=(
["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/.env"
["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/config.yaml"
@@ -33,22 +36,107 @@ declare -A TEMPLATES=(
["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/alertmanager.yml"
)
-openim::log::info "Read more configuration information: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md"
+# Templates for example files
+declare -A EXAMPLES=(
+ ["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/config/templates/env.template"
+ ["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/templates/config.yaml.template"
+ ["${OPENIM_ROOT}/deployments/templates/prometheus.yml"]="${OPENIM_ROOT}/config/templates/prometheus.yml.template"
+ ["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/templates/alertmanager.yml.template"
+)
-# New variables for argument handling
+# Command-line options
FORCE_OVERWRITE=false
SKIP_EXISTING=false
+GENERATE_EXAMPLES=false
+CLEAN_ENV_EXAMPLES=false
-# Function to display help
+# Function to display help information
show_help() {
echo "Usage: $(basename "$0") [options]"
echo "Options:"
- echo " -h, --help Show this help message"
- echo " --force Overwrite existing files without prompt"
- echo " --skip Skip generation if file exists"
+ echo " -h, --help Show this help message"
+ echo " --force Overwrite existing files without prompt"
+ echo " --skip Skip generation if file exists"
+ echo " --examples Generate example files"
+ echo " --clean-env-examples Generate example files in a clean environment"
+}
+
+# Function to generate configuration files
+generate_config_files() {
+ # Loop through each template in TEMPLATES
+ for template in "${!TEMPLATES[@]}"; do
+ # Read the corresponding output files for the template
+ IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}"
+ for output_file in "${OUTPUT_FILES[@]}"; do
+ # Check if the output file already exists
+ if [[ -f "${output_file}" ]]; then
+ # Handle existing file based on command-line options
+ if [[ "${FORCE_OVERWRITE}" == true ]]; then
+ openim::log::info "Force overwriting ${output_file}."
+ elif [[ "${SKIP_EXISTING}" == true ]]; then
+ openim::log::info "Skipping generation of ${output_file} as it already exists."
+ continue
+ else
+ # Ask user for confirmation to overwrite
+ echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
+ read -r -n 1 REPLY
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ openim::log::info "Skipping generation of ${output_file}."
+ continue
+ fi
+ fi
+ fi
+
+ # Process the template file to generate the output file
+ openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..."
+ if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
+ openim::log::error "genconfig.sh script not found"
+ exit 1
+ fi
+ "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
+ openim::log::error "Error processing template file ${template}"
+ exit 1
+ }
+ sleep 0.5
+ done
+ done
+}
+
+# Function to generate example files
+generate_example_files() {
+ for template in "${!EXAMPLES[@]}"; do
+ local example_file="${EXAMPLES[$template]}"
+ if [[ ! -f "${example_file}" ]]; then
+ openim::log::info "Generating example file: ${example_file} from ${template}..."
+ cp "${template}" "${example_file}"
+ fi
+ done
+}
+
+declare -A env_vars=(
+ ["OPENIM_IP"]="172.28.0.1"
+ ["DATA_DIR"]="./"
+ ["LOG_STORAGE_LOCATION"]="../logs/"
+)
+
+generate_clean_environment_examples() {
+ env_cmd="env -i"
+ for var in "${!env_vars[@]}"; do
+ env_cmd+=" $var='${env_vars[$var]}'"
+ done
+
+ for template in "${!EXAMPLES[@]}"; do
+ local example_file="${EXAMPLES[$template]}"
+ openim::log::info "Generating example file: ${example_file} from ${template}..."
+
+ eval "$env_cmd ${OPENIM_ROOT}/scripts/genconfig.sh '${ENV_FILE}' '${template}' > '${example_file}'" || {
+ openim::log::error "Error processing template file ${template}"
+ exit 1
+ }
+ done
}
-# Parse command-line options
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
@@ -63,6 +151,14 @@ while [[ $# -gt 0 ]]; do
SKIP_EXISTING=true
shift
;;
+ --examples)
+ GENERATE_EXAMPLES=true
+ shift
+ ;;
+ --clean-env-examples)
+ CLEAN_ENV_EXAMPLES=true
+ shift
+ ;;
*)
echo "Unknown option: $1"
show_help
@@ -71,44 +167,19 @@ while [[ $# -gt 0 ]]; do
esac
done
-for template in "${!TEMPLATES[@]}"; do
- if [[ ! -f "${template}" ]]; then
- openim::log::error_exit "Template file ${template} does not exist..."
- exit 1
- fi
-done
+# Generate configuration files if requested
+if [[ "${FORCE_OVERWRITE}" == true || "${SKIP_EXISTING}" == false ]]; then
+ generate_config_files
+fi
-for template in "${!TEMPLATES[@]}"; do
- IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}"
- for output_file in "${OUTPUT_FILES[@]}"; do
- if [[ -f "${output_file}" ]]; then
- if [[ "${FORCE_OVERWRITE}" == true ]]; then
- openim::log::info "Force overwriting ${output_file}."
- elif [[ "${SKIP_EXISTING}" == true ]]; then
- openim::log::info "Skipping generation of ${output_file} as it already exists."
- continue
- else
- echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
- read -r -n 1 REPLY
- echo
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
- openim::log::info "Skipping generation of ${output_file}."
- continue
- fi
- fi
- fi
+# Generate example files if --examples option is provided
+if [[ "${GENERATE_EXAMPLES}" == true ]]; then
+ generate_example_files
+fi
- openim::log::info "⌚ Working with template file: ${template} to ${output_file}..."
- if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
- openim::log::error "genconfig.sh script not found"
- exit 1
- fi
- "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
- openim::log::error "Error processing template file ${template}"
- exit 1
- }
- sleep 0.5
- done
-done
+# Generate example files in a clean environment if --clean-env-examples option is provided
+if [[ "${CLEAN_ENV_EXAMPLES}" == true ]]; then
+ generate_clean_environment_examples
+fi
-openim::log::success "✨ All configuration files have been successfully generated!"
+openim::log::success "Configuration and example files generation complete!"
\ No newline at end of file
From 01c3d4725ba22d21284a4111e2ae6989ecfa989f Mon Sep 17 00:00:00 2001
From: chao <48119764+withchao@users.noreply.github.com>
Date: Tue, 12 Dec 2023 18:37:23 +0800
Subject: [PATCH 013/110] feat: optimize tools up35 (#1556)
* upgrade package and rtc convert
* upgrade package and rtc convert
* upgrade package and rtc convert
* upgrade package and rtc convert
* friend user
---
internal/rpc/friend/friend.go | 4 +++
internal/rpc/user/user.go | 16 +++++++++
tools/data-conversion/go.mod | 28 +++++++--------
tools/data-conversion/go.sum | 65 +++++++++++++++++------------------
tools/up35/go.mod | 48 --------------------------
5 files changed, 65 insertions(+), 96 deletions(-)
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index 224efe3ed..21422fae3 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -52,6 +52,10 @@ type friendServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
+func (s *friendServer) PinFriends(ctx context.Context, req *pbfriend.PinFriendsReq) (*pbfriend.PinFriendsResp, error) {
+ return nil, errs.ErrInternalServer.Wrap("not implemented")
+}
+
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
// Initialize MongoDB
mongo, err := unrelation.NewMongo()
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 77da408aa..a2fa14c7a 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -56,6 +56,22 @@ type userServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
+func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) {
+ return nil, errs.ErrInternalServer.Wrap("not implemented")
+}
+
+func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) {
+ return nil, errs.ErrInternalServer.Wrap("not implemented")
+}
+
+func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) {
+ return nil, errs.ErrInternalServer.Wrap("not implemented")
+}
+
+func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) {
+ return nil, errs.ErrInternalServer.Wrap("not implemented")
+}
+
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis()
if err != nil {
diff --git a/tools/data-conversion/go.mod b/tools/data-conversion/go.mod
index b0d7aea13..37d1776c2 100644
--- a/tools/data-conversion/go.mod
+++ b/tools/data-conversion/go.mod
@@ -3,16 +3,16 @@ module github.com/openimsdk/open-im-server/v3/tools/data-conversion
go 1.19
require (
- github.com/IBM/sarama v1.41.2
- github.com/OpenIMSDK/protocol v0.0.23
- github.com/OpenIMSDK/tools v0.0.14
+ github.com/IBM/sarama v1.42.1
+ github.com/OpenIMSDK/protocol v0.0.33
+ github.com/OpenIMSDK/tools v0.0.20
github.com/golang/protobuf v1.5.3
- github.com/openimsdk/open-im-server/v3 v3.3.2
- golang.org/x/net v0.17.0
- google.golang.org/grpc v1.57.0
+ github.com/openimsdk/open-im-server/v3 v3.4.0
+ golang.org/x/net v0.19.0
+ google.golang.org/grpc v1.60.0
google.golang.org/protobuf v1.31.0
- gorm.io/driver/mysql v1.5.1
- gorm.io/gorm v1.25.4
+ gorm.io/driver/mysql v1.5.2
+ gorm.io/gorm v1.25.5
)
require (
@@ -28,7 +28,7 @@ require (
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
- github.com/go-playground/validator/v10 v10.15.3 // indirect
+ github.com/go-playground/validator/v10 v10.15.5 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
@@ -63,10 +63,10 @@ require (
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/arch v0.3.0 // indirect
- golang.org/x/crypto v0.14.0 // indirect
- golang.org/x/image v0.12.0 // indirect
- golang.org/x/sys v0.13.0 // indirect
- golang.org/x/text v0.13.0 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect
+ golang.org/x/crypto v0.16.0 // indirect
+ golang.org/x/image v0.13.0 // indirect
+ golang.org/x/sys v0.15.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/tools/data-conversion/go.sum b/tools/data-conversion/go.sum
index 9223f6e36..66f85785b 100644
--- a/tools/data-conversion/go.sum
+++ b/tools/data-conversion/go.sum
@@ -1,9 +1,9 @@
-github.com/IBM/sarama v1.41.2 h1:ZDBZfGPHAD4uuAtSv4U22fRZBgst0eEwGFzLj0fb85c=
-github.com/IBM/sarama v1.41.2/go.mod h1:xdpu7sd6OE1uxNdjYTSKUfY8FaKkJES9/+EyjSgiGQk=
-github.com/OpenIMSDK/protocol v0.0.23 h1:L545aRQez6Ro+AaJB1Z6Mz7ojnDtp41WqASxYveCkcE=
-github.com/OpenIMSDK/protocol v0.0.23/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.14 h1:WLof/+WxyPyRST+QkoTKubYCiV73uCLiL8pgnpH/yKQ=
-github.com/OpenIMSDK/tools v0.0.14/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/IBM/sarama v1.42.1 h1:wugyWa15TDEHh2kvq2gAy1IHLjEjuYOYgXz/ruC/OSQ=
+github.com/IBM/sarama v1.42.1/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
+github.com/OpenIMSDK/protocol v0.0.33 h1:T07KWD0jt7IRlrYRujCa+eXmfgcSi8sRgLL8t2ZlHQA=
+github.com/OpenIMSDK/protocol v0.0.33/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/tools v0.0.20 h1:zBTjQZRJ5lR1FIzP9mtWyAvh5dKsmJXQugi4p8X/97k=
+github.com/OpenIMSDK/tools v0.0.20/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
@@ -34,8 +34,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.15.3 h1:S+sSpunYjNPDuXkWbK+x+bA7iXiW296KG4dL3X7xUZo=
-github.com/go-playground/validator/v10 v10.15.3/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24=
+github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
@@ -47,7 +47,7 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
@@ -103,8 +103,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
-github.com/openimsdk/open-im-server/v3 v3.3.2 h1:uK6glaidrnWlYXFSwzOEq7fXS6jT1OyesUJENZJeptI=
-github.com/openimsdk/open-im-server/v3 v3.3.2/go.mod h1:rqKiCkjav5P7tQmyqaixnMJcayWlM4XtXmwG+cZNw78=
+github.com/openimsdk/open-im-server/v3 v3.4.0 h1:e7nslaWEHYc5xD1A3zHtnhbIWgfgtJSnPGHIqwjARaE=
+github.com/openimsdk/open-im-server/v3 v3.4.0/go.mod h1:HKqjLZSMjD7ec59VV694Yfqnj9SIVotzDSPWgAei2Tg=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
@@ -146,24 +146,22 @@ golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
-golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ=
-golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk=
+golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
+golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg=
+golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -171,8 +169,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/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.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/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=
@@ -180,18 +178,17 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-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.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
-google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0=
+google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k=
+google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
@@ -202,9 +199,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
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.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
-gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
+gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
+gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
+gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/tools/up35/go.mod b/tools/up35/go.mod
index 5ae3907bf..23163a4dc 100644
--- a/tools/up35/go.mod
+++ b/tools/up35/go.mod
@@ -1,51 +1,3 @@
module github.com/openimsdk/open-im-server/v3/tools/up35
go 1.19
-
-require (
- github.com/go-sql-driver/mysql v1.7.1
- github.com/openimsdk/open-im-server/v3 v3.5.0
- github.com/openimsdk/open-im-server/v3/tools/data-conversion v0.0.0-00010101000000-000000000000
- go.mongodb.org/mongo-driver v1.12.1
- gopkg.in/yaml.v3 v3.0.1
- gorm.io/driver/mysql v1.5.1
- gorm.io/gorm v1.25.4
-)
-
-require (
- github.com/OpenIMSDK/protocol v0.0.31 // indirect
- github.com/OpenIMSDK/tools v0.0.18 // indirect
- github.com/bwmarrin/snowflake v0.3.0 // indirect
- github.com/golang/protobuf v1.5.3 // indirect
- github.com/golang/snappy v0.0.4 // indirect
- github.com/jinzhu/copier v0.4.0 // indirect
- github.com/jinzhu/inflection v1.0.0 // indirect
- github.com/jinzhu/now v1.1.5 // indirect
- github.com/klauspost/compress v1.16.7 // indirect
- github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
- github.com/lestrrat-go/strftime v1.0.6 // indirect
- github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
- github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
- github.com/pkg/errors v0.9.1 // indirect
- github.com/xdg-go/pbkdf2 v1.0.0 // indirect
- github.com/xdg-go/scram v1.1.2 // indirect
- github.com/xdg-go/stringprep v1.0.4 // indirect
- github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
- go.uber.org/atomic v1.7.0 // indirect
- go.uber.org/multierr v1.6.0 // indirect
- go.uber.org/zap v1.24.0 // indirect
- golang.org/x/crypto v0.14.0 // indirect
- golang.org/x/image v0.13.0 // indirect
- golang.org/x/net v0.17.0 // indirect
- golang.org/x/sync v0.4.0 // indirect
- golang.org/x/sys v0.14.0 // indirect
- golang.org/x/text v0.13.0 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
- google.golang.org/grpc v1.59.0 // indirect
- google.golang.org/protobuf v1.31.0 // indirect
-)
-
-replace (
- github.com/openimsdk/open-im-server/v3 => ./../../../open-im-server
- github.com/openimsdk/open-im-server/v3/tools/data-conversion => ./../data-conversion
-)
From 2cef0f62b38bcf12d5a42bbac7425b3aca5d7233 Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Fri, 15 Dec 2023 17:14:43 +0800
Subject: [PATCH 014/110] fix group notification (#1557)
---
internal/rpc/group/group.go | 1 -
1 file changed, 1 deletion(-)
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index 5992ed031..b05b14b59 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -278,7 +278,6 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
break
}
}
- s.Notification.GroupCreatedNotification(ctx, tips)
if req.GroupInfo.GroupType == constant.SuperGroup {
go func() {
for _, userID := range userIDs {
From c2dfc37b0bfc5bbf35273afd23896a8dc46e84f6 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Sat, 16 Dec 2023 23:01:15 +0800
Subject: [PATCH 015/110] feat: support mac deployment and optimization make
check (#1570)
* feat: add openim server code
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add openim scripts check and mac support ss comment
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: add mac os
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
.github/workflows/openimci.yml | 53 ++++++-
config/templates/config.yaml.template | 6 +-
config/templates/env.template | 13 +-
deployments/templates/env-template.yaml | 8 +-
docker-compose.yml | 5 -
docs/contrib/environment.md | 10 +-
scripts/check-all.sh | 6 +-
scripts/docker-start-all.sh | 2 +
scripts/init-config.sh | 176 +++++++++++++-----------
scripts/install/environment.sh | 6 +-
scripts/lib/logging.sh | 2 +-
scripts/lib/util.sh | 23 +++-
12 files changed, 194 insertions(+), 116 deletions(-)
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index 5f010db8a..d65c0dc89 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -130,14 +130,14 @@ jobs:
sudo make install
execute-scripts:
- name: Execute OpenIM script on ${{ matrix.os }}
+ name: Execute OpenIM Script On ${{ matrix.os }}
runs-on: ${{ matrix.os }}
environment:
name: openim
strategy:
matrix:
go_version: ["1.20"]
- os: ["ubuntu-latest"]
+ os: ["ubuntu-latest", "macos-latest"]
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -154,18 +154,52 @@ jobs:
version: '3.x' # If available, use the latest major version that's compatible
repo-token: ${{ secrets.GITHUB_TOKEN }}
- - name: Docker Operations
+ # - name: Install latest Bash (macOS only)
+ # if: runner.os == 'macOS'
+ # run: |
+ # /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+ # brew update
+
+ # brew install bash
+ # brew install gnu-sed
+
+ # echo "/usr/local/bin" >> $GITHUB_PATH
+ # echo "$(brew --prefix)/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH
+ # continue-on-error: true
+
+ - name: Set up Docker for Ubuntu
+ if: runner.os == 'Linux'
run: |
sudo make init
sudo docker compose up -d
sudo sleep 20
- - name: Module Operations
+ # - name: Set up Docker for macOS
+ # if: runner.os == 'macOS'
+ # run: |
+ # brew install --cask docker
+ # open /Applications/Docker.app
+
+ # sleep 10
+ # docker-compose --version || brew install docker-compose
+
+ # docker-compose up -d
+ # sleep 20
+
+ - name: Module Operations for Ubuntu
+ if: runner.os == 'Linux'
run: |
sudo make tidy
sudo make tools.verify.go-gitlint
- - name: Build, Start, Check Services and Print Logs
+ # - name: Module Operations for macOS
+ # if: runner.os == 'macOS'
+ # run: |
+ # make tidy
+ # make tools.verify.go-gitlint
+
+ - name: Build, Start, Check Services and Print Logs for Ubuntu
+ if: runner.os == 'Linux'
run: |
sudo make init && \
sudo make build && \
@@ -173,6 +207,15 @@ jobs:
sudo make check || \
(echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
+ # - name: Build, Start, Check Services and Print Logs for macOS
+ # if: runner.os == 'macOS'
+ # run: |
+ # make init && \
+ # make build && \
+ # make start && \
+ # make check || \
+ # (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
+
openim-test-build-image:
name: Build OpenIM Docker Image
runs-on: ubuntu-latest
diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template
index a35d06c8c..7eb082b24 100644
--- a/config/templates/config.yaml.template
+++ b/config/templates/config.yaml.template
@@ -115,14 +115,14 @@ api:
# minio.signEndpoint is minio public network address
object:
enable: "minio"
- apiURL: "http://172.28.0.1:10002"
+ apiURL: "http://14.155.64.202:10002"
minio:
bucket: "openim"
endpoint: "http://172.28.0.1:10005"
accessKeyID: "root"
secretAccessKey: "openIM123"
sessionToken: ''
- signEndpoint: "http://172.28.0.1:10005"
+ signEndpoint: "http://14.155.64.202:10005"
publicRead: false
cos:
bucketURL: https://temp-1252357374.cos.ap-chengdu.myqcloud.com
@@ -186,7 +186,7 @@ rpcRegisterName:
# Whether to output in json format
# Whether to include stack trace in logs
log:
- storageLocation: ../logs/
+ storageLocation: /data/workspaces/open-im-server/logs/
rotationTime: 24
remainRotationCount: 2
remainLogLevel: 6
diff --git a/config/templates/env.template b/config/templates/env.template
index e47a9c073..54218c330 100644
--- a/config/templates/env.template
+++ b/config/templates/env.template
@@ -16,11 +16,11 @@ MINIO_ENDPOINT=http://172.28.0.1:10005
# Base URL for the application programming interface (API).
# Default: API_URL=http://172.28.0.1:10002
-API_URL=http://172.28.0.1:10002
+API_URL=http://14.155.64.202:10002
# Directory path for storing data files or related information.
# Default: DATA_DIR=./
-DATA_DIR=./
+DATA_DIR=/data/workspaces/open-im-server
# Choose the appropriate image address, the default is GITHUB image,
# you can choose docker hub, for Chinese users can choose Ali Cloud
@@ -200,8 +200,9 @@ API_OPENIM_PORT=10002
# ======================================
# Branch name for OpenIM chat.
-# Default: CHAT_BRANCH=main
-CHAT_BRANCH=main
+# Default: CHAT_IMAGE_VERSION=main
+# https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md
+CHAT_IMAGE_VERSION=main
# Address or hostname for the OpenIM chat service.
# Default: OPENIM_CHAT_ADDRESS=172.28.0.1
@@ -221,8 +222,8 @@ OPENIM_CHAT_DATA_DIR=./openim-chat/main
# ======================================
# Branch name for OpenIM server.
-# Default: SERVER_BRANCH=main
-SERVER_BRANCH=main
+# Default: SERVER_IMAGE_VERSION=main
+SERVER_IMAGE_VERSION=main
# Port for the OpenIM admin API.
# Default: OPENIM_ADMIN_API_PORT=10009
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index b62543aba..b4118b9ce 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -200,8 +200,8 @@ API_OPENIM_PORT=${API_OPENIM_PORT}
# ======================================
# Branch name for OpenIM chat.
-# Default: CHAT_BRANCH=main
-CHAT_BRANCH=${CHAT_BRANCH}
+# Default: CHAT_IMAGE_VERSION=main
+CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION}
# Address or hostname for the OpenIM chat service.
# Default: OPENIM_CHAT_ADDRESS=172.28.0.1
@@ -221,8 +221,8 @@ OPENIM_CHAT_DATA_DIR=${OPENIM_CHAT_DATA_DIR}
# ======================================
# Branch name for OpenIM server.
-# Default: SERVER_BRANCH=main
-SERVER_BRANCH=${SERVER_BRANCH}
+# Default: SERVER_IMAGE_VERSION=main
+SERVER_IMAGE_VERSION=${SERVER_IMAGE_VERSION}
# Port for the OpenIM admin API.
# Default: OPENIM_ADMIN_API_PORT=10009
diff --git a/docker-compose.yml b/docker-compose.yml
index 22f57d329..de3deaaea 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -34,7 +34,6 @@ services:
ipv4_address: ${MONGO_NETWORK_ADDRESS:-172.28.0.2}
redis:
- # image: redis:7.0.0
image: redis:${REDIS_IMAGE_VERSION:-7.0.0}
container_name: redis
ports:
@@ -53,7 +52,6 @@ services:
ipv4_address: ${REDIS_NETWORK_ADDRESS:-172.28.0.3}
zookeeper:
- # image: bitnami/zookeeper:3.8
image: bitnami/zookeeper:${ZOOKEEPER_IMAGE_VERSION:-3.8}
container_name: zookeeper
ports:
@@ -69,7 +67,6 @@ services:
ipv4_address: ${ZOOKEEPER_NETWORK_ADDRESS:-172.28.0.5}
kafka:
- # image: 'bitnami/kafka:3.5.1'
image: 'bitnami/kafka:${KAFKA_IMAGE_VERSION:-3.5.1}'
container_name: kafka
restart: always
@@ -95,7 +92,6 @@ services:
ipv4_address: ${KAFKA_NETWORK_ADDRESS:-172.28.0.4}
minio:
- # image: minio/minio
image: minio/minio:${MINIO_IMAGE_VERSION:-latest}
ports:
- "${MINIO_PORT:-10005}:9000"
@@ -114,7 +110,6 @@ services:
ipv4_address: ${MINIO_NETWORK_ADDRESS:-172.28.0.6}
openim-web:
- # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:latest
image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:${OPENIM_WEB_IMAGE_VERSION:-latest}
container_name: openim-web
environment:
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index 3dd090dcc..310c2df6a 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -104,18 +104,18 @@ Docker deployment offers a slightly more intricate template. Within the [openim-
Configuration file modifications can be made by specifying corresponding environment variables, for instance:
```bash
-export CHAT_BRANCH="main"
-export SERVER_BRANCH="main"
+export CHAT_IMAGE_VERSION="main"
+export SERVER_IMAGE_VERSION="main"
```
These variables are stored within the [`environment.sh`](https://github.com/OpenIMSDK/openim-docker/blob/main/scripts/install/environment.sh) configuration:
```bash
-readonly CHAT_BRANCH=${CHAT_BRANCH:-'main'}
-readonly SERVER_BRANCH=${SERVER_BRANCH:-'main'}
+readonly CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION:-'main'}
+readonly SERVER_IMAGE_VERSION=${SERVER_IMAGE_VERSION:-'main'}
```
-Setting a variable, e.g., `export CHAT_BRANCH="release-v1.3"`, will prioritize `CHAT_BRANCH="release-v1.3"` as the variable value. Ultimately, the chosen image version is determined, and rendering is achieved through `make init` (or `./scripts/init-config.sh`).
+Setting a variable, e.g., `export CHAT_IMAGE_VERSION="release-v1.3"`, will prioritize `CHAT_IMAGE_VERSION="release-v1.3"` as the variable value. Ultimately, the chosen image version is determined, and rendering is achieved through `make init` (or `./scripts/init-config.sh`).
> Note: Direct modifications to the `config.yaml` file are also permissible without utilizing `make init`.
diff --git a/scripts/check-all.sh b/scripts/check-all.sh
index 23e2119d4..5acae3498 100755
--- a/scripts/check-all.sh
+++ b/scripts/check-all.sh
@@ -33,9 +33,8 @@ openim::log::info "\n# Begin to check all openim service"
# OpenIM status
# Elegant printing function
print_services_and_ports() {
- # 获取数组
- declare -g service_names=("${!1}")
- declare -g service_ports=("${!2}")
+ local -n service_names=$1
+ local -n service_ports=$2
echo "+-------------------------+----------+"
echo "| Service Name | Port |"
@@ -48,7 +47,6 @@ print_services_and_ports() {
echo "+-------------------------+----------+"
}
-
# Print out services and their ports
print_services_and_ports OPENIM_SERVER_NAME_TARGETS OPENIM_SERVER_PORT_TARGETS
diff --git a/scripts/docker-start-all.sh b/scripts/docker-start-all.sh
index 6ad277815..3c83b02bb 100755
--- a/scripts/docker-start-all.sh
+++ b/scripts/docker-start-all.sh
@@ -28,6 +28,8 @@ openim::log::info "\n# Use Docker to start all openim service"
trap 'openim::util::onCtrlC' INT
+"${OPENIM_ROOT}"/scripts/init-config.sh --skip
+
"${OPENIM_ROOT}"/scripts/start-all.sh
sleep 5
diff --git a/scripts/init-config.sh b/scripts/init-config.sh
index 631bd68d7..0b9c0e615 100755
--- a/scripts/init-config.sh
+++ b/scripts/init-config.sh
@@ -1,17 +1,4 @@
#!/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.
# This script automatically initializes various configuration files and can generate example files.
@@ -48,7 +35,8 @@ declare -A EXAMPLES=(
FORCE_OVERWRITE=false
SKIP_EXISTING=false
GENERATE_EXAMPLES=false
-CLEAN_ENV_EXAMPLES=false
+CLEAN_CONFIG=false
+CLEAN_EXAMPLES=false
# Function to display help information
show_help() {
@@ -58,48 +46,45 @@ show_help() {
echo " --force Overwrite existing files without prompt"
echo " --skip Skip generation if file exists"
echo " --examples Generate example files"
- echo " --clean-env-examples Generate example files in a clean environment"
+ echo " --clean-config Clean all configuration files"
+ echo " --clean-examples Clean all example files"
}
# Function to generate configuration files
generate_config_files() {
- # Loop through each template in TEMPLATES
for template in "${!TEMPLATES[@]}"; do
- # Read the corresponding output files for the template
- IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}"
- for output_file in "${OUTPUT_FILES[@]}"; do
- # Check if the output file already exists
- if [[ -f "${output_file}" ]]; then
- # Handle existing file based on command-line options
- if [[ "${FORCE_OVERWRITE}" == true ]]; then
- openim::log::info "Force overwriting ${output_file}."
- elif [[ "${SKIP_EXISTING}" == true ]]; then
- openim::log::info "Skipping generation of ${output_file} as it already exists."
+ local output_file="${TEMPLATES[$template]}"
+ if [[ -f "${output_file}" ]]; then
+ if [[ "${FORCE_OVERWRITE}" == true ]]; then
+ openim::log::info "Force overwriting ${output_file}."
+ elif [[ "${SKIP_EXISTING}" == true ]]; then
+ openim::log::info "Skipping generation of ${output_file} as it already exists."
+ continue
+ else
+ echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
+ read -r -n 1 REPLY
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ openim::log::info "Skipping generation of ${output_file}."
continue
- else
- # Ask user for confirmation to overwrite
- echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
- read -r -n 1 REPLY
- echo
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
- openim::log::info "Skipping generation of ${output_file}."
- continue
- fi
fi
fi
-
- # Process the template file to generate the output file
- openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..."
- if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
- openim::log::error "genconfig.sh script not found"
- exit 1
+ else
+ if [[ "${SKIP_EXISTING}" == true ]]; then
+ openim::log::info "Generating ${output_file} as it does not exist."
fi
- "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
- openim::log::error "Error processing template file ${template}"
- exit 1
- }
- sleep 0.5
- done
+ fi
+
+ openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..."
+ if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
+ openim::log::error "genconfig.sh script not found"
+ exit 1
+ fi
+ "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
+ openim::log::error "Error processing template file ${template}"
+ exit 1
+ }
+ sleep 0.5
done
}
@@ -107,33 +92,56 @@ generate_config_files() {
generate_example_files() {
for template in "${!EXAMPLES[@]}"; do
local example_file="${EXAMPLES[$template]}"
- if [[ ! -f "${example_file}" ]]; then
- openim::log::info "Generating example file: ${example_file} from ${template}..."
- cp "${template}" "${example_file}"
+ if [[ -f "${example_file}" ]]; then
+ if [[ "${FORCE_OVERWRITE}" == true ]]; then
+ openim::log::info "Force overwriting example file: ${example_file}."
+ elif [[ "${SKIP_EXISTING}" == true ]]; then
+ openim::log::info "Skipping generation of example file: ${example_file} as it already exists."
+ continue
+ else
+ echo -n "Example file ${example_file} already exists. Overwrite? (Y/N): "
+ read -r -n 1 REPLY
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ openim::log::info "Skipping generation of example file: ${example_file}."
+ continue
+ fi
+ fi
+ elif [[ "${SKIP_EXISTING}" == true ]]; then
+ openim::log::info "Generating example file: ${example_file} as it does not exist."
fi
+
+ openim::log::info "⌚ Working with template file: ${template} to generate example file: ${example_file}..."
+ if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
+ openim::log::error "genconfig.sh script not found"
+ exit 1
+ fi
+ "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${example_file}" || {
+ openim::log::error "Error processing template file ${template}"
+ exit 1
+ }
+ sleep 0.5
done
}
-declare -A env_vars=(
- ["OPENIM_IP"]="172.28.0.1"
- ["DATA_DIR"]="./"
- ["LOG_STORAGE_LOCATION"]="../logs/"
-)
-generate_clean_environment_examples() {
- env_cmd="env -i"
- for var in "${!env_vars[@]}"; do
- env_cmd+=" $var='${env_vars[$var]}'"
+# Function to clean configuration files
+clean_config_files() {
+ for output_file in "${TEMPLATES[@]}"; do
+ if [[ -f "${output_file}" ]]; then
+ rm -f "${output_file}"
+ openim::log::info "Removed configuration file: ${output_file}"
+ fi
done
+}
- for template in "${!EXAMPLES[@]}"; do
- local example_file="${EXAMPLES[$template]}"
- openim::log::info "Generating example file: ${example_file} from ${template}..."
-
- eval "$env_cmd ${OPENIM_ROOT}/scripts/genconfig.sh '${ENV_FILE}' '${template}' > '${example_file}'" || {
- openim::log::error "Error processing template file ${template}"
- exit 1
- }
+# Function to clean example files
+clean_example_files() {
+ for example_file in "${EXAMPLES[@]}"; do
+ if [[ -f "${example_file}" ]]; then
+ rm -f "${example_file}"
+ openim::log::info "Removed example file: ${example_file}"
+ fi
done
}
@@ -155,8 +163,12 @@ while [[ $# -gt 0 ]]; do
GENERATE_EXAMPLES=true
shift
;;
- --clean-env-examples)
- CLEAN_ENV_EXAMPLES=true
+ --clean-config)
+ CLEAN_CONFIG=true
+ shift
+ ;;
+ --clean-examples)
+ CLEAN_EXAMPLES=true
shift
;;
*)
@@ -167,19 +179,29 @@ while [[ $# -gt 0 ]]; do
esac
done
+# Clean configuration files if --clean-config option is provided
+if [[ "${CLEAN_CONFIG}" == true ]]; then
+ clean_config_files
+fi
+
+# Clean example files if --clean-examples option is provided
+if [[ "${CLEAN_EXAMPLES}" == true ]]; then
+ clean_example_files
+fi
+
# Generate configuration files if requested
-if [[ "${FORCE_OVERWRITE}" == true || "${SKIP_EXISTING}" == false ]]; then
+if [[ "${FORCE_OVERWRITE}" == true || "${SKIP_EXISTING}" == false ]] && [[ "${CLEAN_CONFIG}" == false ]]; then
generate_config_files
fi
-# Generate example files if --examples option is provided
-if [[ "${GENERATE_EXAMPLES}" == true ]]; then
- generate_example_files
+# Generate configuration files if requested
+if [[ "${SKIP_EXISTING}" == true ]]; then
+ generate_config_files
fi
-# Generate example files in a clean environment if --clean-env-examples option is provided
-if [[ "${CLEAN_ENV_EXAMPLES}" == true ]]; then
- generate_clean_environment_examples
+# Generate example files if --examples option is provided
+if [[ "${GENERATE_EXAMPLES}" == true ]] && [[ "${CLEAN_EXAMPLES}" == false ]]; then
+ generate_example_files
fi
-openim::log::success "Configuration and example files generation complete!"
\ No newline at end of file
+openim::log::success "Configuration and example files operation complete!"
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index 643f621b6..3dd062af6 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -66,8 +66,8 @@ def "ENV_FILE" ""${OPENIM_ROOT}"/scripts/install/environment.sh"
###################### Docker compose ###################
# OPENIM AND CHAT
-def "CHAT_BRANCH" "main"
-def "SERVER_BRANCH" "main"
+def "CHAT_IMAGE_VERSION" "main"
+def "SERVER_IMAGE_VERSION" "main"
# Choose the appropriate image address, the default is GITHUB image,
# you can choose docker hub, for Chinese users can choose Ali Cloud
@@ -139,7 +139,7 @@ readonly API_OPENIM_PORT=${API_OPENIM_PORT:-'10002'}
def "API_LISTEN_IP" "0.0.0.0" # API的监听IP
###################### openim-chat 配置信息 ######################
-def "OPENIM_CHAT_DATA_DIR" "./openim-chat/${CHAT_BRANCH}"
+def "OPENIM_CHAT_DATA_DIR" "./openim-chat/${CHAT_IMAGE_VERSION}"
def "OPENIM_CHAT_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # OpenIM服务地址
def "OPENIM_CHAT_API_PORT" "10008" # OpenIM API端口
def "CHAT_API_LISTEN_IP" "" # OpenIM API的监听IP
diff --git a/scripts/lib/logging.sh b/scripts/lib/logging.sh
index 9d28aa284..8e7d5b09a 100755
--- a/scripts/lib/logging.sh
+++ b/scripts/lib/logging.sh
@@ -20,7 +20,7 @@ OPENIM_VERBOSE="${OPENIM_VERBOSE:-5}"
ENABLE_LOGGING="${ENABLE_LOGGING:-true}"
# If OPENIM_OUTPUT is not set, set it to the default value
-if [[ ! -v OPENIM_OUTPUT ]]; then
+if [ -z "${OPENIM_OUTPUT+x}" ]; then
OPENIM_OUTPUT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../_output" && pwd -P)"
fi
diff --git a/scripts/lib/util.sh b/scripts/lib/util.sh
index ad3baa6bf..b8d76edeb 100755
--- a/scripts/lib/util.sh
+++ b/scripts/lib/util.sh
@@ -302,8 +302,12 @@ openim::util::check_ports() {
# Iterate over each given port.
for port in "$@"; do
# Use the `ss` command to find process information related to the given port.
- local info=$(ss -ltnp | grep ":$port" || true)
-
+ if command -v ss > /dev/null 2>&1; then
+ info=$(ss -ltnp | grep ":$port" || true)
+ else
+ info=$(netstat -ltnp | grep ":$port" || true)
+ fi
+
# If there's no process information, it means the process associated with the port is not running.
if [[ -z $info ]]; then
not_started+=($port)
@@ -364,6 +368,18 @@ openim::util::check_ports() {
# openim::util::check_process_names nginx mysql redis
# The function returns a status of 1 if any of the processes is not running.
openim::util::check_process_names() {
+ # Function to get the port of a process
+ get_port() {
+ local pid=$1
+ if command -v ss > /dev/null 2>&1; then
+ # used ss comment
+ ss -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | cut -d ':' -f2
+ else
+ # used netstat comment replace ss
+ netstat -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | sed 's/.*://'
+ fi
+ }
+
# Arrays to collect details of processes
local not_started=()
local started=()
@@ -382,7 +398,7 @@ openim::util::check_process_names() {
for pid in "${pids[@]}"; do
local command=$(ps -p $pid -o cmd=)
local start_time=$(ps -p $pid -o lstart=)
- local port=$(ss -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | cut -d ':' -f2)
+ local port=$(get_port $pid)
# Check if port information was found for the PID
if [[ -z $port ]]; then
@@ -419,6 +435,7 @@ openim::util::check_process_names() {
return 0
fi
}
+
# openim::util::check_process_names docker-pr
# The `openim::util::stop_services_on_ports` function stops services running on specified ports.
From c5c5b2fd8ea3a6cc5c73b7b5860d32285c0c29e5 Mon Sep 17 00:00:00 2001
From: xuexihuang <1339326187@qq.com>
Date: Sun, 17 Dec 2023 17:40:04 +0800
Subject: [PATCH 016/110] support multipe msggateway services in k8s
deployments (#1565)
* feature:support multi msggateway
* feature:support multi msggateway
---------
Co-authored-by: lin.huang
---
.../discoveryregister/discoveryregister.go | 72 ++++++++++++++++++-
1 file changed, 69 insertions(+), 3 deletions(-)
diff --git a/pkg/common/discoveryregister/discoveryregister.go b/pkg/common/discoveryregister/discoveryregister.go
index c204184ff..62c1f4a31 100644
--- a/pkg/common/discoveryregister/discoveryregister.go
+++ b/pkg/common/discoveryregister/discoveryregister.go
@@ -4,6 +4,9 @@ import (
"context"
"errors"
"fmt"
+ "os"
+ "strconv"
+ "strings"
"time"
"github.com/OpenIMSDK/tools/discoveryregistry"
@@ -43,7 +46,12 @@ func NewK8sDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) {
}
func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.DialOption) error {
- cli.rpcRegisterAddr = serviceName
+ if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
+ cli.rpcRegisterAddr = serviceName
+ } else {
+ cli.rpcRegisterAddr = cli.getSelfHost(context.Background())
+ }
+
return nil
}
func (cli *K8sDR) UnRegister() error {
@@ -63,10 +71,68 @@ func (cli *K8sDR) GetConfFromRegistry(key string) ([]byte, error) {
return nil, nil
}
+func (cli *K8sDR) getSelfHost(ctx context.Context) string {
+ port := 88
+ instance := "openimserver"
+ selfPodName := os.Getenv("MY_POD_NAME")
+ ns := os.Getenv("MY_POD_NAMESPACE")
+ statefuleIndex := 0
+ gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":")
+ if len(gatewayEnds) != 2 {
+ log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error"))
+ } else {
+ port, _ = strconv.Atoi(gatewayEnds[1])
+ }
+ podInfo := strings.Split(selfPodName, "-")
+ instance = podInfo[0]
+ count := len(podInfo)
+ statefuleIndex, _ = strconv.Atoi(podInfo[count-1])
+ host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, statefuleIndex, instance, ns, port)
+ return host
+}
+
+// like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88
+func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string {
+ port := 88
+ instance := "openimserver"
+ selfPodName := os.Getenv("MY_POD_NAME")
+ replicas := os.Getenv("MY_MSGGATEWAY_REPLICACOUNT")
+ ns := os.Getenv("MY_POD_NAMESPACE")
+ gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":")
+ if len(gatewayEnds) != 2 {
+ log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error"))
+ } else {
+ port, _ = strconv.Atoi(gatewayEnds[1])
+ }
+ nReplicas, _ := strconv.Atoi(replicas)
+ podInfo := strings.Split(selfPodName, "-")
+ instance = podInfo[0]
+ var ret []string
+ for i := 0; i < nReplicas; i++ {
+ host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, i, instance, ns, port)
+ ret = append(ret, host)
+ }
+ log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret)
+ return ret
+}
func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
- conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
- return []*grpc.ClientConn{conn}, err
+ if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
+ conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
+ return []*grpc.ClientConn{conn}, err
+ } else {
+ var ret []*grpc.ClientConn
+ gatewayHosts := cli.getMsgGatewayHost(ctx)
+ for _, host := range gatewayHosts {
+ conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...)
+ if err != nil {
+ return nil, err
+ } else {
+ ret = append(ret, conn)
+ }
+ }
+ return ret, nil
+ }
}
func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
From f1c9686ada6d195449a5762e14c8312c48263ea3 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Mon, 18 Dec 2023 10:24:12 +0800
Subject: [PATCH 017/110] feat: Add OpenIM server, environment support for
Docker Compose, and Kubernetes deployment. (#1559)
* feat: add openim server code
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo and redis env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add zk and redis mongo env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add kafka and redis mongo env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim docker
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim docker
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim docker
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim copyright
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: docker compose
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: remove openim chat config file
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim config set
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim config set
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix Security vulnerability
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix Security vulnerability
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: docker compose
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* Update kubernetes.go
* Update discoveryregister.go
* fix: copyright-add
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
.github/workflows/build-docker-image.yml | 3 +
.github/workflows/build-openim-web-image.yml | 139 ------
.gitignore | 15 +-
config/Readme.md | 243 ++++++++++
config/templates/README.md | 36 --
config/templates/alertmanager.yml.template | 14 +
config/templates/config.yaml.template | 17 +-
.../email.tmpl.template} | 0
config/templates/env.template | 18 +-
.../instance-down-rules.yml.template | 36 ++
config/templates/notification.yaml.template | 354 +++++++++++++++
.../{ => templates}/open-im-ng-example.conf | 0
.../{ => templates}/prometheus-dashboard.yaml | 14 +
config/templates/prometheus.yml.template | 14 +
deployments/{README.md => Readme.md} | 0
deployments/charts/helmfile.yaml | 14 +
deployments/charts/openim-api/Chart.yaml | 14 +
.../charts/openim-api/templates/app-cm.yaml | 14 +
.../openim-api/templates/deployment.yaml | 14 +
.../charts/openim-api/templates/hpa.yaml | 14 +
.../charts/openim-api/templates/ingress.yaml | 14 +
.../charts/openim-api/templates/service.yaml | 14 +
.../openim-api/templates/serviceaccount.yaml | 14 +
deployments/charts/openim-api/values.yaml | 14 +
.../charts/openim-msggateway/Chart.yaml | 14 +
.../openim-msggateway/templates/hpa.yaml | 14 +
.../openim-msggateway/templates/ingress.yaml | 14 +
.../openim-msggateway/templates/service.yaml | 14 +
.../templates/serviceaccount.yaml | 14 +
.../charts/openim-msggateway/values.yaml | 14 +
.../charts/openim-msgtransfer/Chart.yaml | 14 +
.../templates/deployment.yaml | 14 +
.../openim-msgtransfer/templates/hpa.yaml | 14 +
.../openim-msgtransfer/templates/ingress.yaml | 14 +
.../openim-msgtransfer/templates/service.yaml | 14 +
.../templates/serviceaccount.yaml | 14 +
.../charts/openim-msgtransfer/values.yaml | 14 +
deployments/charts/openim-push/Chart.yaml | 14 +
.../openim-push/templates/deployment.yaml | 14 +
.../charts/openim-push/templates/hpa.yaml | 14 +
.../charts/openim-push/templates/ingress.yaml | 14 +
.../charts/openim-push/templates/service.yaml | 14 +
.../openim-push/templates/serviceaccount.yaml | 14 +
deployments/charts/openim-push/values.yaml | 14 +
deployments/charts/openim-rpc-auth/Chart.yaml | 14 +
.../openim-rpc-auth/templates/deployment.yaml | 14 +
.../charts/openim-rpc-auth/templates/hpa.yaml | 14 +
.../openim-rpc-auth/templates/ingress.yaml | 14 +
.../openim-rpc-auth/templates/service.yaml | 14 +
.../templates/serviceaccount.yaml | 14 +
.../charts/openim-rpc-auth/values.yaml | 14 +
.../charts/openim-rpc-conversation/Chart.yaml | 14 +
.../templates/deployment.yaml | 14 +
.../templates/hpa.yaml | 14 +
.../templates/ingress.yaml | 14 +
.../templates/service.yaml | 14 +
.../templates/serviceaccount.yaml | 14 +
.../openim-rpc-conversation/values.yaml | 14 +
.../charts/openim-rpc-friend/Chart.yaml | 14 +
.../templates/deployment.yaml | 14 +
.../openim-rpc-friend/templates/hpa.yaml | 14 +
.../openim-rpc-friend/templates/ingress.yaml | 14 +
.../openim-rpc-friend/templates/service.yaml | 14 +
.../templates/serviceaccount.yaml | 14 +
.../charts/openim-rpc-friend/values.yaml | 14 +
.../charts/openim-rpc-group/Chart.yaml | 14 +
.../templates/deployment.yaml | 14 +
.../openim-rpc-group/templates/hpa.yaml | 14 +
.../openim-rpc-group/templates/ingress.yaml | 14 +
.../openim-rpc-group/templates/service.yaml | 14 +
.../templates/serviceaccount.yaml | 14 +
.../charts/openim-rpc-group/values.yaml | 14 +
deployments/charts/openim-rpc-msg/Chart.yaml | 14 +
.../openim-rpc-msg/templates/deployment.yaml | 14 +
.../charts/openim-rpc-msg/templates/hpa.yaml | 14 +
.../openim-rpc-msg/templates/ingress.yaml | 14 +
.../openim-rpc-msg/templates/service.yaml | 14 +
.../templates/serviceaccount.yaml | 14 +
deployments/charts/openim-rpc-msg/values.yaml | 14 +
.../charts/openim-rpc-third/Chart.yaml | 14 +
.../templates/deployment.yaml | 14 +
.../openim-rpc-third/templates/hpa.yaml | 14 +
.../openim-rpc-third/templates/ingress.yaml | 14 +
.../openim-rpc-third/templates/service.yaml | 14 +
.../templates/serviceaccount.yaml | 14 +
.../charts/openim-rpc-third/values.yaml | 14 +
deployments/charts/openim-rpc-user/Chart.yaml | 14 +
.../openim-rpc-user/templates/deployment.yaml | 14 +
.../charts/openim-rpc-user/templates/hpa.yaml | 14 +
.../openim-rpc-user/templates/ingress.yaml | 14 +
.../openim-rpc-user/templates/service.yaml | 14 +
.../templates/serviceaccount.yaml | 14 +
.../charts/openim-rpc-user/values.yaml | 14 +
deployments/openim-charts.yaml | 14 +
deployments/templates/alertmanager.yml | 14 +
deployments/templates/charts-value.yaml | 14 +
deployments/templates/chat.yaml | 118 -----
deployments/templates/email.tmpl | 16 +
deployments/templates/env-template.yaml | 18 +-
deployments/templates/helm-image.yaml | 14 +
.../templates}/instance-down-rules.yml | 14 +
.../templates}/notification.yaml | 33 +-
deployments/templates/openim.yaml | 17 +-
deployments/templates/prometheus.yml | 14 +
internal/api/msg.go | 1 +
internal/msggateway/compressor_test.go | 14 +
internal/push/offlinepush/dummy/push.go | 14 +
internal/push/push_rpc_server.go | 3 +-
internal/rpc/friend/callback.go | 2 +
internal/rpc/friend/friend.go | 1 +
internal/rpc/group/callback.go | 3 +-
internal/rpc/group/group.go | 3 +-
internal/rpc/msg/as_read.go | 8 +-
internal/rpc/msg/callback.go | 2 +
internal/rpc/third/log.go | 14 +
internal/rpc/user/callback.go | 1 +
internal/tools/cron_task_test.go | 14 +
pkg/apistruct/msg.go | 36 +-
pkg/callbackstruct/constant.go | 14 +
pkg/callbackstruct/revoke.go | 14 +
pkg/common/cmd/constant.go | 14 +
pkg/common/config/config.go | 1 +
pkg/common/config/parse.go | 4 +-
pkg/common/convert/user.go | 3 +-
pkg/common/db/cache/group.go | 2 +-
pkg/common/db/cache/init_redis.go | 24 +-
pkg/common/db/cache/msg_test.go | 14 +
pkg/common/db/cache/s3.go | 14 +
pkg/common/db/mgo/black.go | 14 +
pkg/common/db/mgo/conversation.go | 14 +
pkg/common/db/mgo/friend.go | 14 +
pkg/common/db/mgo/friend_request.go | 14 +
pkg/common/db/mgo/group.go | 14 +
pkg/common/db/mgo/group_member.go | 14 +
pkg/common/db/mgo/group_request.go | 14 +
pkg/common/db/mgo/log.go | 14 +
pkg/common/db/mgo/object.go | 14 +
pkg/common/db/mgo/user.go | 14 +
pkg/common/db/s3/cos/internal.go | 14 +
pkg/common/db/s3/minio/internal.go | 14 +
pkg/common/db/s3/minio/thumbnail.go | 14 +
pkg/common/db/table/relation/log.go | 14 +
pkg/common/db/unrelation/mongo.go | 137 +++---
.../discoveryregister/discoveryregister.go | 169 ++-----
.../discoveryregister_test.go | 428 ++----------------
.../kubernetes/kubernetes.go | 174 +++++++
.../discoveryregister/zookeeper/zookeeper.go | 61 +++
pkg/common/ginprometheus/ginprometheus.go | 14 +
pkg/common/kafka/producer.go | 138 +++---
pkg/common/kafka/util.go | 11 +
pkg/common/prommetrics/gin_api.go | 16 +-
pkg/common/prommetrics/grpc_auth.go | 14 +
pkg/common/prommetrics/grpc_msg.go | 14 +
pkg/common/prommetrics/grpc_msggateway.go | 14 +
pkg/common/prommetrics/grpc_push.go | 14 +
pkg/common/prommetrics/prommetrics.go | 14 +
pkg/common/prommetrics/prommetrics_test.go | 14 +
pkg/common/prommetrics/transfer.go | 14 +
pkg/common/startrpc/start_test.go | 14 +
pkg/common/version/base.go | 16 +-
pkg/common/version/types.go | 14 +
pkg/common/version/version.go | 18 +-
pkg/rpcclient/grouphash/grouphash.go | 14 +
scripts/check-all.sh | 4 +-
scripts/githooks/pre-push.sh | 2 +-
scripts/init-config.sh | 159 ++++---
test/e2e/api/token/token.go | 28 +-
test/e2e/api/user/curd.go | 24 +-
test/e2e/api/user/user.go | 30 +-
test/e2e/e2e.go | 14 +
test/e2e/e2e_test.go | 14 +
test/e2e/framework/config/config.go | 14 +
test/e2e/framework/config/config_test.go | 14 +
.../framework/ginkgowrapper/ginkgowrapper.go | 14 +
.../ginkgowrapper/ginkgowrapper_test.go | 14 +
test/e2e/framework/helpers/chat/chat.go | 22 +-
tools/component/component.go | 320 +++++++------
.../chat/cmd/conversion-chat/chat.go | 14 +
.../chat/conversion/conversion.go | 14 +
tools/data-conversion/chat/v2/admin.go | 14 +
tools/data-conversion/chat/v2/chat.go | 14 +
.../cmd/conversion-msg/conversion-msg.go | 14 +
tools/data-conversion/openim/mysql/cmd.go | 14 +
.../openim/mysql/conversion/conversion.go | 14 +
.../openim/mysql/v2/model_struct.go | 14 +
tools/data-conversion/openim/mysql/v3/log.go | 14 +
.../openim/proto/msg/msg.proto | 14 +
.../openim/proto/sdk_ws/ws.proto | 14 +
tools/data-conversion/utils/find_insert.go | 14 +
tools/data-conversion/utils/time.go | 14 +
tools/infra/infra.go | 14 +
tools/up35/pkg/convert.go | 17 +-
.../pkg/internal/rtc/mongo/mgo/meeting.go | 20 +-
.../rtc/mongo/mgo/meeting_invitation.go | 27 +-
.../internal/rtc/mongo/mgo/meeting_record.go | 18 +-
.../up35/pkg/internal/rtc/mongo/mgo/signal.go | 20 +-
.../rtc/mongo/mgo/signal_invitation.go | 20 +-
.../pkg/internal/rtc/mongo/table/meeting.go | 17 +-
.../pkg/internal/rtc/mongo/table/signal.go | 17 +-
tools/up35/pkg/internal/rtc/mysql/meeting.go | 14 +
tools/up35/pkg/internal/rtc/mysql/signal.go | 16 +-
tools/up35/pkg/pkg.go | 17 +-
tools/up35/up35.go | 17 +-
tools/url2im/main.go | 14 +
tools/url2im/pkg/api.go | 14 +
tools/url2im/pkg/buffer.go | 14 +
tools/url2im/pkg/config.go | 14 +
tools/url2im/pkg/http.go | 14 +
tools/url2im/pkg/manage.go | 14 +
tools/url2im/pkg/md5.go | 14 +
tools/url2im/pkg/progress.go | 14 +
211 files changed, 3985 insertions(+), 1235 deletions(-)
delete mode 100644 .github/workflows/build-openim-web-image.yml
create mode 100644 config/Readme.md
delete mode 100644 config/templates/README.md
rename config/{email.tmpl => templates/email.tmpl.template} (100%)
create mode 100644 config/templates/instance-down-rules.yml.template
create mode 100644 config/templates/notification.yaml.template
rename config/{ => templates}/open-im-ng-example.conf (100%)
rename config/{ => templates}/prometheus-dashboard.yaml (98%)
rename deployments/{README.md => Readme.md} (100%)
delete mode 100644 deployments/templates/chat.yaml
create mode 100644 deployments/templates/email.tmpl
rename {config => deployments/templates}/instance-down-rules.yml (61%)
rename {config => deployments/templates}/notification.yaml (88%)
create mode 100644 pkg/common/discoveryregister/kubernetes/kubernetes.go
create mode 100644 pkg/common/discoveryregister/zookeeper/zookeeper.go
diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml
index a8cb98a51..619744987 100644
--- a/.github/workflows/build-docker-image.yml
+++ b/.github/workflows/build-docker-image.yml
@@ -48,6 +48,7 @@ jobs:
images: openim/openim-server
# generate Docker tags based on the following events/attributes
tags: |
+ type=ref,event=tag
type=schedule
type=ref,event=branch
type=ref,event=pr
@@ -90,6 +91,7 @@ jobs:
images: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server
# generate Docker tags based on the following events/attributes
tags: |
+ type=ref,event=tag
type=schedule
type=ref,event=branch
type=ref,event=pr
@@ -133,6 +135,7 @@ jobs:
images: ghcr.io/openimsdk/openim-server
# generate Docker tags based on the following events/attributes
tags: |
+ type=ref,event=tag
type=schedule
type=ref,event=branch
type=ref,event=pr
diff --git a/.github/workflows/build-openim-web-image.yml b/.github/workflows/build-openim-web-image.yml
deleted file mode 100644
index 999c2e1e3..000000000
--- a/.github/workflows/build-openim-web-image.yml
+++ /dev/null
@@ -1,139 +0,0 @@
-# Copyright © 2023 OpenIM open source community. 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.
-
-name: Build OpenIM Web Docker image
-
-on:
-# schedule:
-# - cron: '30 3 * * *'
- push:
- branches:
- # - main
- - release-*
- tags:
- - v*
- workflow_dispatch:
-
-env:
- # Common versions
- GO_VERSION: "1.20"
-
-jobs:
- build-openim-web-dockerhub:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
-# docker.io/openim/openim-web:latest
- - name: Extract metadata (tags, labels) for Docker
- id: meta
- uses: docker/metadata-action@v5.0.0
- with:
- images: openim/openim-web
- # generate Docker tags based on the following events/attributes
- tags: |
- type=schedule
- type=ref,event=branch
- type=ref,event=pr
- type=semver,pattern={{version}}
- type=semver,pattern={{major}}.{{minor}}
- type=semver,pattern={{major}}
- type=sha
-
- - name: Log in to Docker Hub
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKER_USERNAME }}
- password: ${{ secrets.DOCKER_PASSWORD }}
-
- - name: Build and push Docker image
- uses: docker/build-push-action@v5
- with:
- context: .
- file: ./build/images/openim-tools/openim-web/Dockerfile
- platforms: linux/amd64,linux/arm64
- push: ${{ github.event_name != 'pull_request' }}
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
-
- build-openim-web-aliyun:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-# registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web:latest
- - name: Extract metadata (tags, labels) for Docker
- id: meta2
- uses: docker/metadata-action@v5.0.0
- with:
- images: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web
-
- - name: Log in to AliYun Docker Hub
- uses: docker/login-action@v3
- with:
- registry: registry.cn-hangzhou.aliyuncs.com
- username: ${{ secrets.ALIREGISTRY_USERNAME }}
- password: ${{ secrets.ALIREGISTRY_TOKEN }}
-
- - name: Build and push Docker image
- uses: docker/build-push-action@v5
- with:
- context: .
- file: ./build/images/openim-tools/openim-web/Dockerfile
- platforms: linux/amd64,linux/arm64
- push: ${{ github.event_name != 'pull_request' }}
- tags: ${{ steps.meta2.outputs.tags }}
- labels: ${{ steps.meta2.outputs.labels }}
-
- build-openim-web-ghcr:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-# ghcr.io/openimsdk/openim-web:latest
- - name: Extract metadata (tags, labels) for Docker
- id: meta2
- uses: docker/metadata-action@v5.0.0
- with:
- images: ghcr.io/openimsdk/openim-web
-
- - name: Log in to GitHub Container Registry
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.repository_owner }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Build and push Docker image
- uses: docker/build-push-action@v5
- with:
- context: .
- file: ./build/images/openim-tools/openim-web/Dockerfile
- platforms: linux/amd64,linux/arm64
- push: ${{ github.event_name != 'pull_request' }}
- tags: ${{ steps.meta2.outputs.tags }}
- labels: ${{ steps.meta2.outputs.labels }}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 675ce10c7..fb8d428d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,10 +32,13 @@ _output/
deployments/charts/generated-configs/
### OpenIM Config ###
-config/config.yaml
-./config/config.yaml
.env
-./.env
+config/config.yaml
+config/alertmanager.yml
+config/prometheus.yml
+config/email.tmpl
+config/notification.yaml
+config/instance-down-rules.yml
### OpenIM deploy ###
deployments/openim-server/charts
@@ -388,8 +391,4 @@ Sessionx.vim
# End of https://www.toptal.com/developers/gitignore/api/go,git,vim,tags,test,emacs,backup,jetbrains
.idea
-dist/
-.env
-config/config.yaml
-config/alertmanager.yml
-config/prometheus.yml
\ No newline at end of file
+dist/
\ No newline at end of file
diff --git a/config/Readme.md b/config/Readme.md
new file mode 100644
index 000000000..72f4577a5
--- /dev/null
+++ b/config/Readme.md
@@ -0,0 +1,243 @@
+# OpenIM Configuration Guide
+
+
+* 1. [Directory Structure and File Descriptions](#DirectoryStructureandFileDescriptions)
+ * 1.1. [Directory Structure](#DirectoryStructure)
+ * 1.2. [Directory Structure Explanation](#DirectoryStructureExplanation)
+* 2. [File Descriptions](#FileDescriptions)
+ * 2.1. [Files in the Root Directory](#FilesintheRootDirectory)
+ * 2.2. [Files in the `templates/` Directory](#FilesinthetemplatesDirectory)
+* 3. [Configuration File Generation](#ConfigurationFileGeneration)
+ * 3.1. [How to Use `init-config.sh` Script](#HowtoUseinit-config.shScript)
+ * 3.2. [Examples of Operations](#ExamplesofOperations)
+ * 3.3. [Points to Note](#PointstoNote)
+* 4. [Example Directory](#ExampleDirectory)
+ * 4.1. [Overview](#Overview)
+ * 4.2. [Structure](#Structure)
+ * 4.3. [How to Use These Examples](#HowtoUseTheseExamples)
+ * 4.4. [Tips for Using Example Files:](#TipsforUsingExampleFiles:)
+* 5. [Configuration Item Descriptions](#ConfigurationItemDescriptions)
+* 6. [Version Management and Upgrading](#VersionManagementandUpgrading)
+ * 6.1. [Pulling the Latest Code](#PullingtheLatestCode)
+ * 6.2. [Generating the Latest Example Configuration Files](#GeneratingtheLatestExampleConfigurationFiles)
+ * 6.3. [Comparing Configuration File Differences](#ComparingConfigurationFileDifferences)
+ * 6.4. [Updating Configuration Files](#UpdatingConfigurationFiles)
+ * 6.5. [Updating Binary Files and Restarting Services](#UpdatingBinaryFilesandRestartingServices)
+ * 6.6. [Best Practices for Version Management](#BestPracticesforVersionManagement)
+* 7. [How to Contribute](#HowtoContribute)
+ * 7.1. [OpenIM Configuration Item Descriptions](#OpenIMConfigurationItemDescriptions)
+ * 7.2. [Modifying Template Files](#ModifyingTemplateFiles)
+ * 7.3. [Updating Configuration Center Scripts](#UpdatingConfigurationCenterScripts)
+ * 7.4. [Configuration File Generation Process](#ConfigurationFileGenerationProcess)
+ * 7.5. [Contribution Guidelines](#ContributionGuidelines)
+ * 7.6. [Submission and Review](#SubmissionandReview)
+
+
+
+
+
+## 1. Directory Structure and File Descriptions
+
+This document details the structure of the `config` directory, aiding users in understanding and managing configuration files.
+
+### 1.1. Directory Structure
+
+```bash
+$ tree config
+├── alertmanager.yml
+├── config.yaml
+├── email.tmpl
+├── instance-down-rules.yml
+├── notification.yaml
+├── prometheus.yml
+├── Readme.md
+└── templates
+ ├── alertmanager.yml.template
+ ├── config.yaml.template
+ ├── email.tmpl.template
+ ├── env.template
+ ├── instance-down-rules.yml.template
+ ├── notification.yaml.template
+ ├── open-im-ng-example.conf
+ ├── prometheus-dashboard.yaml
+ └── prometheus.yml.template
+```
+
+### 1.2. Directory Structure Explanation
+
+- **Root Directory (`config/`)**: Contains actual configuration files and the `templates` subdirectory.
+- **`templates/` Subdirectory**: Stores configuration templates for generating or updating configuration files in the root directory.
+
+## 2. File Descriptions
+
+### 2.1. Files in the Root Directory
+
+- **`alertmanager.yml`**: Configuration file for AlertManager, managing and setting up the alert system.
+- **`config.yaml`**: The main application configuration file, covering service settings.
+- **`email.tmpl`**: Template file for email notifications, defining email format and content.
+- **`instance-down-rules.yml`**: Instance downtime rules configuration file for the monitoring system.
+- **`notification.yaml`**: Configuration file for notification settings, defining different types of notifications.
+- **`prometheus.yml`**: Configuration file for the Prometheus monitoring system, setting monitoring metrics and rules.
+
+### 2.2. Files in the `templates/` Directory
+
+- **`alertmanager.yml.template`**: Template for AlertManager configuration.
+- **`config.yaml.template`**: Main configuration template for the application.
+- **`email.tmpl.template`**: Template for email notifications.
+- **`env.template`**: Template for environmental variable configurations, setting environment-related configurations.
+- **`instance-down-rules.yml.template`**: Template for instance downtime rules.
+- **`notification.yaml.template`**: Template for notification settings.
+- **`open-im-ng-example.conf`**: Example configuration file for the application.
+- **`prometheus-dashboard.yaml`**: Prometheus dashboard configuration file, specific to the OpenIM application.
+- **`prometheus.yml.template`**: Template for Prometheus configuration.
+
+## 3. Configuration File Generation
+
+Configuration files can be automatically generated using the `make init` command or the `./scripts/init-config.sh` script. These scripts conveniently extract templates from the `templates` directory and generate or update actual configuration files in the root directory.
+
+### 3.1. How to Use `init-config.sh` Script
+
+```bash
+$ ./scripts/init-config.sh --help
+Usage: init-config.sh [options]
+Options:
+ -h, --help Show this help message
+ --force Overwrite existing files without prompt
+ --skip Skip generation if file exists
+ --examples Generate example files
+ --clean-config Clean all configuration files
+ --clean-examples Clean all example files
+```
+
+### 3.2. Examples of Operations
+
+- Generate all template configuration files:
+
+ ```bash
+ $ ./scripts/init-config.sh --examples
+ ```
+
+- Force overwrite existing configuration files:
+
+ ```bash
+ $ ./scripts/init-config.sh --force
+ ```
+
+### 3.3. Points to Note
+
+- **Template files should not be directly modified**: Files in the `template` directory are templates included in source code management. Direct modification may lead to version conflicts or management issues.
+- **Operations for Windows Users**: Windows users can use the `cp` command to copy files from the `template` directory to the `config/` directory and then modify the configuration items as needed.
+
+## 4. Example Directory
+
+Welcome to our project's `examples` directory! This directory contains a range of example files, showcasing various configurations and settings of our software. These examples are intended to provide you with templates that can serve as a starting point for your own configurations.
+
+### 4.1. Overview
+
+In this directory, you'll find examples suitable for a variety of use cases. Each file is a template with default values and configurations, demonstrating best practices and typical scenarios. Whether you're just getting started or looking to implement complex settings, these examples should help you get on the right track.
+
+### 4.2. Structure
+
+Here's a quick overview of the contents in this directory:
+
+- `env-example.yaml`: Demonstrates how to set up environmental variables.
+- `openim-example.yaml`: Example configuration file for the OpenIM application.
+- `prometheus-example.yml`: Example configuration for monitoring with Prometheus.
+- `alertmanager-example.yml`: Template for setting up Alertmanager configuration.
+
+### 4.3. How to Use These Examples
+
+To use these examples, simply copy the relevant files to your working directory and rename them as needed (for example, removing the `-example` suffix). Then, modify the files according to your needs.
+
+### 4.4. Tips for Using Example Files:
+
+1. **Read Comments**: Each file contains comments explaining the various sections and settings. Make sure to read these comments for a better understanding of how to customize the file.
+2. **Check Required Changes**: Some examples might require mandatory changes before they can be used effectively (such as setting specific environmental variables).
+3. **Version Compatibility**: Ensure that the example files are compatible with the version of the software you are using.
+
+## 5. Configuration Item Descriptions
+
+## 6. Version Management and Upgrading
+
+When managing and upgrading the `config` directory's versions, it is crucial to ensure that the configuration files in both the local `config/` and `config/templates/` directories are kept in sync. This process can ensure that your configuration files are consistent with the latest standard templates, while also maintaining custom settings.
+
+### 6.1. Pulling the Latest Code
+
+First, ensure that your local repository is in sync with the remote repository. This can be achieved by pulling the latest code:
+
+```bash
+$ git pull
+```
+
+### 6.2. Generating the Latest Example Configuration Files
+
+Next, generate the latest example configuration files. This can be done by running the `init-config.sh` script, using the `--examples` option to generate example files, and the `--skip` option to avoid overwriting existing configuration files:
+
+```bash
+$ ./scripts/init-config.sh --examples --skip
+```
+
+### 6.3. Comparing Configuration File Differences
+
+Once the latest example configuration files are generated, you need to compare the configuration files in the `config/` and `config/templates/` directories to find any potential differences. This step ensures that you can identify and integrate any important updates or changes. Tools like `diff` can be helpful in completing this step:
+
+```bash
+$ diff -ur config/ config/templates/
+```
+
+### 6.4. Updating Configuration Files
+
+Based on the comparison results, manually update the configuration files in the `config/` directory to reflect the latest configurations in `config/templates/`. During this process, ensure to retain any custom configuration settings.
+
+### 6.5. Updating Binary Files and Restarting Services
+
+After updating the configuration files, the next step is to update any related binary files. This typically involves downloading and installing the latest version of the application or service. Depending on the specific application or service, this might involve running specific update scripts or directly downloading the latest version from official sources.
+
+Once the binary files are updated, the services need to be restarted to apply the new configurations. Make sure to conduct necessary checks before restarting to ensure the correctness of the configurations.
+
+### 6.6. Best Practices for Version Management
+
+- **Record Changes**: When committing changes to a version control system, ensure to log detailed change logs.
+- **Stay Synced**: Regularly sync with the remote repository to ensure that your local configurations are in line with the latest developments.
+- **Backup**: Backup your current configurations before making any significant changes, so that you can revert to a previous state if necessary.
+
+By following these steps and best practices, you can ensure effective management and smooth upgrading of your `config` directory.
+
+## 7. How to Contribute
+
+If you have an understanding of the logic behind OpenIM's configuration generation, then you will clearly know where to make modifications to contribute code.
+
+### 7.1. OpenIM Configuration Item Descriptions
+
+First, it is recommended to read the [OpenIM Configuration Items Document](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md). This will help you understand the roles of various configuration items and how they affect the operation of OpenIM.
+
+### 7.2. Modifying Template Files
+
+To contribute to OpenIM, focus on the `./deployments/templates` directory. This contains various configuration template files, which are the basis for generating the final configuration files.
+
+When making modifications, ensure that your changes align with OpenIM's configuration requirements and logic. This may involve adding new template files or modifying existing files to reflect new configuration options or structural changes.
+
+### 7.3. Updating Configuration Center Scripts
+
+In addition to modifying template files, pay attention to the `./scripts/install/environment.sh` script. In this script, you may need to add or modify environment variables.
+
+This script is responsible for defining environment variables that influence configuration generation. Therefore, any new configuration items or modifications to existing items need to be reflected here.
+
+### 7.4. Configuration File Generation Process
+
+The essence of the `make init` command is to use the environment variables defined in `/scripts/install/environment.sh` to render the template files in the `./deployments/templates` directory, thereby generating the final configuration files.
+
+When contributing code, ensure that your changes work smoothly in this process and do not cause errors during configuration file generation.
+
+### 7.5. Contribution Guidelines
+
+- **Code Review**: Ensure your changes have passed code review. This typically means that the code should be clear, easy to understand, and adhere to the project's coding style and best practices.
+- **Testing**: Before submitting changes, conduct thorough tests to ensure new or modified configurations work as expected and do not negatively impact existing functionalities.
+- **Documentation**: If you have added a new configuration option or made significant changes to an existing one, update the relevant documentation to assist other users and developers in understanding and utilizing these changes.
+
+### 7.6. Submission and Review
+
+After completing your changes, submit your code to the OpenIM repository in the form of a Pull Request (PR). The PR will be reviewed by the project maintainers and you may be asked to make further modifications or provide additional information.
\ No newline at end of file
diff --git a/config/templates/README.md b/config/templates/README.md
deleted file mode 100644
index 6a979c6bb..000000000
--- a/config/templates/README.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# Examples Directory
-
-Welcome to the `examples` directory of our project! This directory contains a collection of example files that demonstrate various configurations and setups for our software. These examples are designed to provide you with templates that can be used as a starting point for your own configurations.
-
-## Overview
-
-In this directory, you'll find examples for a variety of use cases. Each file is a template with default values and configurations that illustrate best practices and typical scenarios. Whether you're just getting started or looking to implement a complex setup, these examples should help you get on the right track.
-
-## Structure
-
-Here's a quick overview of what you'll find in this directory:
-
-+ `env-example.yaml`: Demonstrates how to set up environment variables.
-+ `openim-example.yaml`: A sample configuration file for the OpenIM application.
-+ `prometheus-example.yml`: An example Prometheus configuration for monitoring.
-+ `alertmanager-example.yml`: A template for setting up Alertmanager configurations.
-
-## How to Use These Examples
-
-To use these examples, simply copy the relevant file to your working directory and rename it as needed (e.g., removing the `-example` suffix). Then, modify the file according to your requirements.
-
-### Tips for Using Example Files:
-
-1. **Read the Comments**: Each file contains comments that explain various sections and settings. Make sure to read these comments for a better understanding of how to customize the file.
-2. **Check for Required Changes**: Some examples might require mandatory changes (like setting specific environment variables) before they can be used effectively.
-3. **Version Compatibility**: Ensure that the example files are compatible with the version of the software you are using.
-
-## Contributing
-
-If you have a configuration that you believe would be beneficial to others, please feel free to contribute by opening a pull request with your proposed changes. We appreciate contributions that expand our examples with new scenarios and use cases.
-
-## Support
-
-If you encounter any issues or have questions regarding the example files, please open an issue on our repository. Our community is here to help you navigate through any challenges you might face.
-
-Thank you for exploring our examples, and we hope they will be helpful in setting up and configuring your environment!
diff --git a/config/templates/alertmanager.yml.template b/config/templates/alertmanager.yml.template
index da5f99b19..a0daadfbd 100644
--- a/config/templates/alertmanager.yml.template
+++ b/config/templates/alertmanager.yml.template
@@ -1,3 +1,17 @@
+# 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.
+
###################### AlertManager Configuration ######################
# AlertManager configuration using environment variables
#
diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template
index 7eb082b24..fd51a2e31 100644
--- a/config/templates/config.yaml.template
+++ b/config/templates/config.yaml.template
@@ -37,13 +37,20 @@ zookeeper:
###################### Mongo ######################
# MongoDB configuration
-# If uri is not empty, it will be used directly
-#
-# MongoDB address for standalone setup, Mongos address for sharded cluster setup
-# Default MongoDB database name
-# Maximum connection pool size
+
+# If uri is not empty, it will be used directly for the MongoDB connection.
+# This is a complete MongoDB URI string.
+# Example: mongodb://user:password@host1:port1,host2:port2/dbname?options
mongo:
uri: ''
+
+# List of MongoDB server addresses.
+# Used for constructing the MongoDB URI if 'uri' above is empty.
+# For a standalone setup, specify the address of the single server.
+# For a sharded cluster, specify the addresses of the Mongos servers.
+# Example: [ '172.28.0.1:37017', '172.28.0.2:37017' ]
+# Default MongoDB database name
+# Maximum connection pool size
address: [ 172.28.0.1:37017 ]
database: openIM_v3
username: root
diff --git a/config/email.tmpl b/config/templates/email.tmpl.template
similarity index 100%
rename from config/email.tmpl
rename to config/templates/email.tmpl.template
diff --git a/config/templates/env.template b/config/templates/env.template
index 54218c330..ffcec89e5 100644
--- a/config/templates/env.template
+++ b/config/templates/env.template
@@ -1,3 +1,17 @@
+# 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.
+
# ======================================
# ========= Basic Configuration ========
# ======================================
@@ -10,10 +24,6 @@ USER=root
# Default: PASSWORD=openIM123
PASSWORD=openIM123
-# Endpoint for the MinIO object storage service.
-# Default: MINIO_ENDPOINT=http://172.28.0.1:10005
-MINIO_ENDPOINT=http://172.28.0.1:10005
-
# Base URL for the application programming interface (API).
# Default: API_URL=http://172.28.0.1:10002
API_URL=http://14.155.64.202:10002
diff --git a/config/templates/instance-down-rules.yml.template b/config/templates/instance-down-rules.yml.template
new file mode 100644
index 000000000..7a6e9fda9
--- /dev/null
+++ b/config/templates/instance-down-rules.yml.template
@@ -0,0 +1,36 @@
+# 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.
+
+groups:
+ - name: instance_down
+ rules:
+ - alert: InstanceDown
+ expr: up == 0
+ for: 1m
+ labels:
+ severity: critical
+ annotations:
+ summary: "Instance {{ $labels.instance }} down"
+ description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minutes."
+
+ - name: database_insert_failure_alerts
+ rules:
+ - alert: DatabaseInsertFailed
+ expr: (increase(msg_insert_redis_failed_total[5m]) > 0) or (increase(msg_insert_mongo_failed_total[5m]) > 0)
+ for: 1m
+ labels:
+ severity: critical
+ annotations:
+ summary: "Increase in MsgInsertRedisFailedCounter or MsgInsertMongoFailedCounter detected"
+ description: "Either MsgInsertRedisFailedCounter or MsgInsertMongoFailedCounter has increased in the last 5 minutes, indicating failures in message insert operations to Redis or MongoDB,maybe the redis or mongodb is crash."
diff --git a/config/templates/notification.yaml.template b/config/templates/notification.yaml.template
new file mode 100644
index 000000000..665c21261
--- /dev/null
+++ b/config/templates/notification.yaml.template
@@ -0,0 +1,354 @@
+# 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.
+
+# Determines if a message should be sent. If set to false, it triggers a silent sync without a message. If true, it requires triggering a conversation.
+# For rpc notification, send twice: once as a message and once as a notification.
+# The options field 'isNotification' indicates if it's a notification.
+groupCreated:
+ isSendMsg: true
+
+# Reliability level of the message sending.
+# Set to 1 to send only when online, 2 for guaranteed delivery.
+ reliabilityLevel: 1
+
+# This setting is effective only when 'isSendMsg' is true.
+# It controls whether to count unread messages.
+ unreadCount: false
+
+# Configuration for offline push notifications.
+ offlinePush:
+ # Enables or disables offline push notifications.
+ enable: false
+
+ # Title for the notification when a group is created.
+ title: "create group title"
+
+ # Description for the notification.
+ desc: "create group desc"
+
+ # Additional information for the notification.
+ ext: "create group ext"
+
+# Content type is not added here.
+# Content should use a JSON structure conforming to the protobuf format.
+
+groupInfoSet:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupInfoSet title"
+ desc: "groupInfoSet desc"
+ ext: "groupInfoSet ext"
+
+
+joinGroupApplication:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "joinGroupApplication title"
+ desc: "joinGroupApplication desc"
+ ext: "joinGroupApplication ext"
+
+memberQuit:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "memberQuit title"
+ desc: "memberQuit desc"
+ ext: "memberQuit ext"
+
+groupApplicationAccepted:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupApplicationAccepted title"
+ desc: "groupApplicationAccepted desc"
+ ext: "groupApplicationAccepted ext"
+
+groupApplicationRejected:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: " title"
+ desc: " desc"
+ ext: " ext"
+
+
+groupOwnerTransferred:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupOwnerTransferred title"
+ desc: "groupOwnerTransferred desc"
+ ext: "groupOwnerTransferred ext"
+
+memberKicked:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "memberKicked title"
+ desc: "memberKicked desc"
+ ext: "memberKicked ext"
+
+memberInvited:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "memberInvited title"
+ desc: "memberInvited desc"
+ ext: "memberInvited ext"
+
+memberEnter:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "memberEnter title"
+ desc: "memberEnter desc"
+ ext: "memberEnter ext"
+
+groupDismissed:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupDismissed title"
+ desc: "groupDismissed desc"
+ ext: "groupDismissed ext"
+
+groupMuted:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupMuted title"
+ desc: "groupMuted desc"
+ ext: "groupMuted ext"
+
+groupCancelMuted:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupCancelMuted title"
+ desc: "groupCancelMuted desc"
+ ext: "groupCancelMuted ext"
+ defaultTips:
+ tips: "group Cancel Muted"
+
+
+groupMemberMuted:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupMemberMuted title"
+ desc: "groupMemberMuted desc"
+ ext: "groupMemberMuted ext"
+
+groupMemberCancelMuted:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupMemberCancelMuted title"
+ desc: "groupMemberCancelMuted desc"
+ ext: "groupMemberCancelMuted ext"
+
+groupMemberInfoSet:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupMemberInfoSet title"
+ desc: "groupMemberInfoSet desc"
+ ext: "groupMemberInfoSet ext"
+
+groupInfoSetAnnouncement:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupInfoSetAnnouncement title"
+ desc: "groupInfoSetAnnouncement desc"
+ ext: "groupInfoSetAnnouncement ext"
+
+
+groupInfoSetName:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "groupInfoSetName title"
+ desc: "groupInfoSetName desc"
+ ext: "groupInfoSetName ext"
+
+
+#############################friend#################################
+friendApplicationAdded:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "Somebody applies to add you as a friend"
+ desc: "Somebody applies to add you as a friend"
+ ext: "Somebody applies to add you as a friend"
+
+friendApplicationApproved:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "Someone applies to add your friend application"
+ desc: "Someone applies to add your friend application"
+ ext: "Someone applies to add your friend application"
+
+friendApplicationRejected:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "Someone rejected your friend application"
+ desc: "Someone rejected your friend application"
+ ext: "Someone rejected your friend application"
+
+friendAdded:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "We have become friends"
+ desc: "We have become friends"
+ ext: "We have become friends"
+
+friendDeleted:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "deleted a friend"
+ desc: "deleted a friend"
+ ext: "deleted a friend"
+
+friendRemarkSet:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "Your friend's profile has been changed"
+ desc: "Your friend's profile has been changed"
+ ext: "Your friend's profile has been changed"
+
+blackAdded:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "blocked a user"
+ desc: "blocked a user"
+ ext: "blocked a user"
+
+blackDeleted:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "Remove a blocked user"
+ desc: "Remove a blocked user"
+ ext: "Remove a blocked user"
+
+friendInfoUpdated:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "friend info updated"
+ desc: "friend info updated"
+ ext: "friend info updated"
+
+#####################user#########################
+userInfoUpdated:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "Remove a blocked user"
+ desc: "Remove a blocked user"
+ ext: "Remove a blocked user"
+
+userStatusChanged:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: false
+ title: "user status changed"
+ desc: "user status changed"
+ ext: "user status changed"
+
+#####################conversation#########################
+conversationChanged:
+ isSendMsg: false
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "conversation changed"
+ desc: "conversation changed"
+ ext: "conversation changed"
+
+conversationSetPrivate:
+ isSendMsg: true
+ reliabilityLevel: 1
+ unreadCount: false
+ offlinePush:
+ enable: true
+ title: "burn after reading"
+ desc: "burn after reading"
+ ext: "burn after reading"
diff --git a/config/open-im-ng-example.conf b/config/templates/open-im-ng-example.conf
similarity index 100%
rename from config/open-im-ng-example.conf
rename to config/templates/open-im-ng-example.conf
diff --git a/config/prometheus-dashboard.yaml b/config/templates/prometheus-dashboard.yaml
similarity index 98%
rename from config/prometheus-dashboard.yaml
rename to config/templates/prometheus-dashboard.yaml
index 0e7823797..e1b569df3 100644
--- a/config/prometheus-dashboard.yaml
+++ b/config/templates/prometheus-dashboard.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{
"annotations": {
"list": [
diff --git a/config/templates/prometheus.yml.template b/config/templates/prometheus.yml.template
index 7950c5d33..709fe9754 100644
--- a/config/templates/prometheus.yml.template
+++ b/config/templates/prometheus.yml.template
@@ -1,3 +1,17 @@
+# 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.
+
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
diff --git a/deployments/README.md b/deployments/Readme.md
similarity index 100%
rename from deployments/README.md
rename to deployments/Readme.md
diff --git a/deployments/charts/helmfile.yaml b/deployments/charts/helmfile.yaml
index a6a009257..eb064be9a 100644
--- a/deployments/charts/helmfile.yaml
+++ b/deployments/charts/helmfile.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- define "defaultValues" -}}
- ./generated-configs/helm-image.yaml
- ./generated-configs/config.yaml
diff --git a/deployments/charts/openim-api/Chart.yaml b/deployments/charts/openim-api/Chart.yaml
index 74779b64a..e79d2a2c2 100644
--- a/deployments/charts/openim-api/Chart.yaml
+++ b/deployments/charts/openim-api/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-api
description: A OpenIM Api Helm chart for Kubernetes
diff --git a/deployments/charts/openim-api/templates/app-cm.yaml b/deployments/charts/openim-api/templates/app-cm.yaml
index 7a6f23314..9d4e96e8b 100644
--- a/deployments/charts/openim-api/templates/app-cm.yaml
+++ b/deployments/charts/openim-api/templates/app-cm.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: ConfigMap
metadata:
diff --git a/deployments/charts/openim-api/templates/deployment.yaml b/deployments/charts/openim-api/templates/deployment.yaml
index 27bfa1f13..3b4bf57a2 100644
--- a/deployments/charts/openim-api/templates/deployment.yaml
+++ b/deployments/charts/openim-api/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-api/templates/hpa.yaml b/deployments/charts/openim-api/templates/hpa.yaml
index 0e5848181..dc0742a25 100644
--- a/deployments/charts/openim-api/templates/hpa.yaml
+++ b/deployments/charts/openim-api/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-api/templates/ingress.yaml b/deployments/charts/openim-api/templates/ingress.yaml
index 62c66c135..55bc69710 100644
--- a/deployments/charts/openim-api/templates/ingress.yaml
+++ b/deployments/charts/openim-api/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-api.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-api/templates/service.yaml b/deployments/charts/openim-api/templates/service.yaml
index eb37fa56c..3704bf35c 100644
--- a/deployments/charts/openim-api/templates/service.yaml
+++ b/deployments/charts/openim-api/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-api/templates/serviceaccount.yaml b/deployments/charts/openim-api/templates/serviceaccount.yaml
index e3e7b2849..556a71e34 100644
--- a/deployments/charts/openim-api/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-api/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-api/values.yaml b/deployments/charts/openim-api/values.yaml
index e41fb6e76..4208335de 100644
--- a/deployments/charts/openim-api/values.yaml
+++ b/deployments/charts/openim-api/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-api.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-msggateway/Chart.yaml b/deployments/charts/openim-msggateway/Chart.yaml
index c8c380bf9..fb6d0d153 100644
--- a/deployments/charts/openim-msggateway/Chart.yaml
+++ b/deployments/charts/openim-msggateway/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-msggateway
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-msggateway/templates/hpa.yaml b/deployments/charts/openim-msggateway/templates/hpa.yaml
index e1fbe50a6..99121afba 100644
--- a/deployments/charts/openim-msggateway/templates/hpa.yaml
+++ b/deployments/charts/openim-msggateway/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-msggateway/templates/ingress.yaml b/deployments/charts/openim-msggateway/templates/ingress.yaml
index 5c1c24078..0e22e1936 100644
--- a/deployments/charts/openim-msggateway/templates/ingress.yaml
+++ b/deployments/charts/openim-msggateway/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-msggateway.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-msggateway/templates/service.yaml b/deployments/charts/openim-msggateway/templates/service.yaml
index 2ed58a869..e33fce6db 100644
--- a/deployments/charts/openim-msggateway/templates/service.yaml
+++ b/deployments/charts/openim-msggateway/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-msggateway/templates/serviceaccount.yaml b/deployments/charts/openim-msggateway/templates/serviceaccount.yaml
index 6b47c12c5..718880d71 100644
--- a/deployments/charts/openim-msggateway/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-msggateway/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-msggateway/values.yaml b/deployments/charts/openim-msggateway/values.yaml
index d82c674fc..059601807 100644
--- a/deployments/charts/openim-msggateway/values.yaml
+++ b/deployments/charts/openim-msggateway/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-msggateway.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-msgtransfer/Chart.yaml b/deployments/charts/openim-msgtransfer/Chart.yaml
index bba7a047f..37d897728 100644
--- a/deployments/charts/openim-msgtransfer/Chart.yaml
+++ b/deployments/charts/openim-msgtransfer/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-msgtransfer
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-msgtransfer/templates/deployment.yaml b/deployments/charts/openim-msgtransfer/templates/deployment.yaml
index adb8ae737..2c9e24bdd 100644
--- a/deployments/charts/openim-msgtransfer/templates/deployment.yaml
+++ b/deployments/charts/openim-msgtransfer/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-msgtransfer/templates/hpa.yaml b/deployments/charts/openim-msgtransfer/templates/hpa.yaml
index 75c7d4fef..89921bf30 100644
--- a/deployments/charts/openim-msgtransfer/templates/hpa.yaml
+++ b/deployments/charts/openim-msgtransfer/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-msgtransfer/templates/ingress.yaml b/deployments/charts/openim-msgtransfer/templates/ingress.yaml
index c9968a438..ab28a9e71 100644
--- a/deployments/charts/openim-msgtransfer/templates/ingress.yaml
+++ b/deployments/charts/openim-msgtransfer/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-msgtransfer.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-msgtransfer/templates/service.yaml b/deployments/charts/openim-msgtransfer/templates/service.yaml
index 839e520e5..e657f8c18 100644
--- a/deployments/charts/openim-msgtransfer/templates/service.yaml
+++ b/deployments/charts/openim-msgtransfer/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-msgtransfer/templates/serviceaccount.yaml b/deployments/charts/openim-msgtransfer/templates/serviceaccount.yaml
index 2e3ca4ee7..78816bd80 100644
--- a/deployments/charts/openim-msgtransfer/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-msgtransfer/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-msgtransfer/values.yaml b/deployments/charts/openim-msgtransfer/values.yaml
index d4a792d17..6e26d72c8 100644
--- a/deployments/charts/openim-msgtransfer/values.yaml
+++ b/deployments/charts/openim-msgtransfer/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-msgtransfer.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-push/Chart.yaml b/deployments/charts/openim-push/Chart.yaml
index 93e134879..966769b00 100644
--- a/deployments/charts/openim-push/Chart.yaml
+++ b/deployments/charts/openim-push/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-push
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-push/templates/deployment.yaml b/deployments/charts/openim-push/templates/deployment.yaml
index 684e76e02..34de33e10 100644
--- a/deployments/charts/openim-push/templates/deployment.yaml
+++ b/deployments/charts/openim-push/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-push/templates/hpa.yaml b/deployments/charts/openim-push/templates/hpa.yaml
index 89c89c041..40c77b048 100644
--- a/deployments/charts/openim-push/templates/hpa.yaml
+++ b/deployments/charts/openim-push/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-push/templates/ingress.yaml b/deployments/charts/openim-push/templates/ingress.yaml
index b00fda3d3..6638f256d 100644
--- a/deployments/charts/openim-push/templates/ingress.yaml
+++ b/deployments/charts/openim-push/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-push.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-push/templates/service.yaml b/deployments/charts/openim-push/templates/service.yaml
index 4d8bb0457..b38c35375 100644
--- a/deployments/charts/openim-push/templates/service.yaml
+++ b/deployments/charts/openim-push/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-push/templates/serviceaccount.yaml b/deployments/charts/openim-push/templates/serviceaccount.yaml
index e22115724..66dfedfdf 100644
--- a/deployments/charts/openim-push/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-push/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-push/values.yaml b/deployments/charts/openim-push/values.yaml
index dd6f0faf6..3348fe79d 100644
--- a/deployments/charts/openim-push/values.yaml
+++ b/deployments/charts/openim-push/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-push.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-rpc-auth/Chart.yaml b/deployments/charts/openim-rpc-auth/Chart.yaml
index 97848dbf2..8e8fb03b4 100644
--- a/deployments/charts/openim-rpc-auth/Chart.yaml
+++ b/deployments/charts/openim-rpc-auth/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-rpc-auth
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-rpc-auth/templates/deployment.yaml b/deployments/charts/openim-rpc-auth/templates/deployment.yaml
index 4dbc49731..202162775 100644
--- a/deployments/charts/openim-rpc-auth/templates/deployment.yaml
+++ b/deployments/charts/openim-rpc-auth/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-rpc-auth/templates/hpa.yaml b/deployments/charts/openim-rpc-auth/templates/hpa.yaml
index 20108afbf..e99536cf1 100644
--- a/deployments/charts/openim-rpc-auth/templates/hpa.yaml
+++ b/deployments/charts/openim-rpc-auth/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-rpc-auth/templates/ingress.yaml b/deployments/charts/openim-rpc-auth/templates/ingress.yaml
index f14458c52..ece395de7 100644
--- a/deployments/charts/openim-rpc-auth/templates/ingress.yaml
+++ b/deployments/charts/openim-rpc-auth/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-rpc-auth.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-rpc-auth/templates/service.yaml b/deployments/charts/openim-rpc-auth/templates/service.yaml
index ef7b00b86..3674da014 100644
--- a/deployments/charts/openim-rpc-auth/templates/service.yaml
+++ b/deployments/charts/openim-rpc-auth/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-rpc-auth/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-auth/templates/serviceaccount.yaml
index f13dcca81..555d4f6ff 100644
--- a/deployments/charts/openim-rpc-auth/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-rpc-auth/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-rpc-auth/values.yaml b/deployments/charts/openim-rpc-auth/values.yaml
index a6db6716c..93fa68b87 100644
--- a/deployments/charts/openim-rpc-auth/values.yaml
+++ b/deployments/charts/openim-rpc-auth/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-rpc-auth.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-rpc-conversation/Chart.yaml b/deployments/charts/openim-rpc-conversation/Chart.yaml
index 090d63127..0ca8f5513 100644
--- a/deployments/charts/openim-rpc-conversation/Chart.yaml
+++ b/deployments/charts/openim-rpc-conversation/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-rpc-conversation
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-rpc-conversation/templates/deployment.yaml b/deployments/charts/openim-rpc-conversation/templates/deployment.yaml
index 13dd5c531..01721aa30 100644
--- a/deployments/charts/openim-rpc-conversation/templates/deployment.yaml
+++ b/deployments/charts/openim-rpc-conversation/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-rpc-conversation/templates/hpa.yaml b/deployments/charts/openim-rpc-conversation/templates/hpa.yaml
index a2378bfa0..524245562 100644
--- a/deployments/charts/openim-rpc-conversation/templates/hpa.yaml
+++ b/deployments/charts/openim-rpc-conversation/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-rpc-conversation/templates/ingress.yaml b/deployments/charts/openim-rpc-conversation/templates/ingress.yaml
index 224591f67..078c472b8 100644
--- a/deployments/charts/openim-rpc-conversation/templates/ingress.yaml
+++ b/deployments/charts/openim-rpc-conversation/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-rpc-conversation.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-rpc-conversation/templates/service.yaml b/deployments/charts/openim-rpc-conversation/templates/service.yaml
index be8355154..f90673584 100644
--- a/deployments/charts/openim-rpc-conversation/templates/service.yaml
+++ b/deployments/charts/openim-rpc-conversation/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-rpc-conversation/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-conversation/templates/serviceaccount.yaml
index 4e2d0e29f..14b1b2129 100644
--- a/deployments/charts/openim-rpc-conversation/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-rpc-conversation/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-rpc-conversation/values.yaml b/deployments/charts/openim-rpc-conversation/values.yaml
index 1b3e1e3de..bb88ab613 100644
--- a/deployments/charts/openim-rpc-conversation/values.yaml
+++ b/deployments/charts/openim-rpc-conversation/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-rpc-conversation.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-rpc-friend/Chart.yaml b/deployments/charts/openim-rpc-friend/Chart.yaml
index d7e4a9fef..62e92db9b 100644
--- a/deployments/charts/openim-rpc-friend/Chart.yaml
+++ b/deployments/charts/openim-rpc-friend/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-rpc-friend
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-rpc-friend/templates/deployment.yaml b/deployments/charts/openim-rpc-friend/templates/deployment.yaml
index 227ef1144..a57188828 100644
--- a/deployments/charts/openim-rpc-friend/templates/deployment.yaml
+++ b/deployments/charts/openim-rpc-friend/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-rpc-friend/templates/hpa.yaml b/deployments/charts/openim-rpc-friend/templates/hpa.yaml
index 7c4f14b7c..ae88e2621 100644
--- a/deployments/charts/openim-rpc-friend/templates/hpa.yaml
+++ b/deployments/charts/openim-rpc-friend/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-rpc-friend/templates/ingress.yaml b/deployments/charts/openim-rpc-friend/templates/ingress.yaml
index b5d411743..0845aa783 100644
--- a/deployments/charts/openim-rpc-friend/templates/ingress.yaml
+++ b/deployments/charts/openim-rpc-friend/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-rpc-friend.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-rpc-friend/templates/service.yaml b/deployments/charts/openim-rpc-friend/templates/service.yaml
index 792592d87..e445d561f 100644
--- a/deployments/charts/openim-rpc-friend/templates/service.yaml
+++ b/deployments/charts/openim-rpc-friend/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-rpc-friend/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-friend/templates/serviceaccount.yaml
index c81343f6b..5146d6781 100644
--- a/deployments/charts/openim-rpc-friend/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-rpc-friend/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-rpc-friend/values.yaml b/deployments/charts/openim-rpc-friend/values.yaml
index 041665a81..34dcda9da 100644
--- a/deployments/charts/openim-rpc-friend/values.yaml
+++ b/deployments/charts/openim-rpc-friend/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-rpc-friend.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-rpc-group/Chart.yaml b/deployments/charts/openim-rpc-group/Chart.yaml
index 8e037caea..c3f7e3bfa 100644
--- a/deployments/charts/openim-rpc-group/Chart.yaml
+++ b/deployments/charts/openim-rpc-group/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-rpc-group
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-rpc-group/templates/deployment.yaml b/deployments/charts/openim-rpc-group/templates/deployment.yaml
index 74ebe6c92..406d0b342 100644
--- a/deployments/charts/openim-rpc-group/templates/deployment.yaml
+++ b/deployments/charts/openim-rpc-group/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-rpc-group/templates/hpa.yaml b/deployments/charts/openim-rpc-group/templates/hpa.yaml
index 0ba0e8283..91f313abe 100644
--- a/deployments/charts/openim-rpc-group/templates/hpa.yaml
+++ b/deployments/charts/openim-rpc-group/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-rpc-group/templates/ingress.yaml b/deployments/charts/openim-rpc-group/templates/ingress.yaml
index 6a744f914..e3cad781a 100644
--- a/deployments/charts/openim-rpc-group/templates/ingress.yaml
+++ b/deployments/charts/openim-rpc-group/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-rpc-group.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-rpc-group/templates/service.yaml b/deployments/charts/openim-rpc-group/templates/service.yaml
index aa16f71b9..fc6f76060 100644
--- a/deployments/charts/openim-rpc-group/templates/service.yaml
+++ b/deployments/charts/openim-rpc-group/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-rpc-group/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-group/templates/serviceaccount.yaml
index b42dfb13b..304bbda56 100644
--- a/deployments/charts/openim-rpc-group/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-rpc-group/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-rpc-group/values.yaml b/deployments/charts/openim-rpc-group/values.yaml
index ec36e256f..f04c64147 100644
--- a/deployments/charts/openim-rpc-group/values.yaml
+++ b/deployments/charts/openim-rpc-group/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-rpc-group.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-rpc-msg/Chart.yaml b/deployments/charts/openim-rpc-msg/Chart.yaml
index 659767484..c32fe64c1 100644
--- a/deployments/charts/openim-rpc-msg/Chart.yaml
+++ b/deployments/charts/openim-rpc-msg/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-rpc-msg
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-rpc-msg/templates/deployment.yaml b/deployments/charts/openim-rpc-msg/templates/deployment.yaml
index e0565710a..d764294ea 100644
--- a/deployments/charts/openim-rpc-msg/templates/deployment.yaml
+++ b/deployments/charts/openim-rpc-msg/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-rpc-msg/templates/hpa.yaml b/deployments/charts/openim-rpc-msg/templates/hpa.yaml
index c01e07294..0e6dde369 100644
--- a/deployments/charts/openim-rpc-msg/templates/hpa.yaml
+++ b/deployments/charts/openim-rpc-msg/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-rpc-msg/templates/ingress.yaml b/deployments/charts/openim-rpc-msg/templates/ingress.yaml
index 2f5ad9d15..2ba587338 100644
--- a/deployments/charts/openim-rpc-msg/templates/ingress.yaml
+++ b/deployments/charts/openim-rpc-msg/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-rpc-msg.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-rpc-msg/templates/service.yaml b/deployments/charts/openim-rpc-msg/templates/service.yaml
index 9afd55a8c..953b89d5d 100644
--- a/deployments/charts/openim-rpc-msg/templates/service.yaml
+++ b/deployments/charts/openim-rpc-msg/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-rpc-msg/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-msg/templates/serviceaccount.yaml
index da69e5ce8..70fd82069 100644
--- a/deployments/charts/openim-rpc-msg/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-rpc-msg/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-rpc-msg/values.yaml b/deployments/charts/openim-rpc-msg/values.yaml
index 22cfd61f1..cf2f4e84d 100644
--- a/deployments/charts/openim-rpc-msg/values.yaml
+++ b/deployments/charts/openim-rpc-msg/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-rpc-msg.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-rpc-third/Chart.yaml b/deployments/charts/openim-rpc-third/Chart.yaml
index d7763d70a..ff624aa34 100644
--- a/deployments/charts/openim-rpc-third/Chart.yaml
+++ b/deployments/charts/openim-rpc-third/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-rpc-third
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-rpc-third/templates/deployment.yaml b/deployments/charts/openim-rpc-third/templates/deployment.yaml
index c14cce817..e4f47de57 100644
--- a/deployments/charts/openim-rpc-third/templates/deployment.yaml
+++ b/deployments/charts/openim-rpc-third/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-rpc-third/templates/hpa.yaml b/deployments/charts/openim-rpc-third/templates/hpa.yaml
index 2197e21a5..f20ecb973 100644
--- a/deployments/charts/openim-rpc-third/templates/hpa.yaml
+++ b/deployments/charts/openim-rpc-third/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-rpc-third/templates/ingress.yaml b/deployments/charts/openim-rpc-third/templates/ingress.yaml
index 3ba50cf33..1c64ac545 100644
--- a/deployments/charts/openim-rpc-third/templates/ingress.yaml
+++ b/deployments/charts/openim-rpc-third/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-rpc-third.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-rpc-third/templates/service.yaml b/deployments/charts/openim-rpc-third/templates/service.yaml
index 866b5cda2..f467992a2 100644
--- a/deployments/charts/openim-rpc-third/templates/service.yaml
+++ b/deployments/charts/openim-rpc-third/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-rpc-third/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-third/templates/serviceaccount.yaml
index 8a45872ce..27f2bf067 100644
--- a/deployments/charts/openim-rpc-third/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-rpc-third/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-rpc-third/values.yaml b/deployments/charts/openim-rpc-third/values.yaml
index 8a92566a9..71d9a3ede 100644
--- a/deployments/charts/openim-rpc-third/values.yaml
+++ b/deployments/charts/openim-rpc-third/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-rpc-third.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/charts/openim-rpc-user/Chart.yaml b/deployments/charts/openim-rpc-user/Chart.yaml
index 7a2118e46..feb5a3195 100644
--- a/deployments/charts/openim-rpc-user/Chart.yaml
+++ b/deployments/charts/openim-rpc-user/Chart.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v2
name: openim-rpc-user
description: A Helm chart for Kubernetes
diff --git a/deployments/charts/openim-rpc-user/templates/deployment.yaml b/deployments/charts/openim-rpc-user/templates/deployment.yaml
index f6f679c2d..62106e5a2 100644
--- a/deployments/charts/openim-rpc-user/templates/deployment.yaml
+++ b/deployments/charts/openim-rpc-user/templates/deployment.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: apps/v1
kind: Deployment
metadata:
diff --git a/deployments/charts/openim-rpc-user/templates/hpa.yaml b/deployments/charts/openim-rpc-user/templates/hpa.yaml
index 7c00c9d64..012b15ae3 100644
--- a/deployments/charts/openim-rpc-user/templates/hpa.yaml
+++ b/deployments/charts/openim-rpc-user/templates/hpa.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
diff --git a/deployments/charts/openim-rpc-user/templates/ingress.yaml b/deployments/charts/openim-rpc-user/templates/ingress.yaml
index 7ed5a0328..38aa6fdff 100644
--- a/deployments/charts/openim-rpc-user/templates/ingress.yaml
+++ b/deployments/charts/openim-rpc-user/templates/ingress.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "openim-rpc-user.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
diff --git a/deployments/charts/openim-rpc-user/templates/service.yaml b/deployments/charts/openim-rpc-user/templates/service.yaml
index 728c5de92..f89be1c44 100644
--- a/deployments/charts/openim-rpc-user/templates/service.yaml
+++ b/deployments/charts/openim-rpc-user/templates/service.yaml
@@ -1,3 +1,17 @@
+# 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.
+
apiVersion: v1
kind: Service
metadata:
diff --git a/deployments/charts/openim-rpc-user/templates/serviceaccount.yaml b/deployments/charts/openim-rpc-user/templates/serviceaccount.yaml
index d3395f00d..ebe3e3d68 100644
--- a/deployments/charts/openim-rpc-user/templates/serviceaccount.yaml
+++ b/deployments/charts/openim-rpc-user/templates/serviceaccount.yaml
@@ -1,3 +1,17 @@
+# 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.
+
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
diff --git a/deployments/charts/openim-rpc-user/values.yaml b/deployments/charts/openim-rpc-user/values.yaml
index d137f0ad7..4f1ad7ede 100644
--- a/deployments/charts/openim-rpc-user/values.yaml
+++ b/deployments/charts/openim-rpc-user/values.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# Default values for openim-rpc-user.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
diff --git a/deployments/openim-charts.yaml b/deployments/openim-charts.yaml
index 59815dbd5..2b468dad0 100644
--- a/deployments/openim-charts.yaml
+++ b/deployments/openim-charts.yaml
@@ -1,3 +1,17 @@
+# 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.
+
---
# Source: openim-api/templates/app-cm.yaml
apiVersion: v1
diff --git a/deployments/templates/alertmanager.yml b/deployments/templates/alertmanager.yml
index ea99a9286..4e390b2bb 100644
--- a/deployments/templates/alertmanager.yml
+++ b/deployments/templates/alertmanager.yml
@@ -1,3 +1,17 @@
+# 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.
+
###################### AlertManager Configuration ######################
# AlertManager configuration using environment variables
#
diff --git a/deployments/templates/charts-value.yaml b/deployments/templates/charts-value.yaml
index 274d9b8d1..26bbe2926 100644
--- a/deployments/templates/charts-value.yaml
+++ b/deployments/templates/charts-value.yaml
@@ -1,3 +1,17 @@
+# 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.
+
#This configuration file is used to override the use of the value.yaml variable.
#Currently, only the configuration with ingressName as nginx is provided.
#If it is another gateway such as istio or treafik, please modify the corresponding gateway requirements
diff --git a/deployments/templates/chat.yaml b/deployments/templates/chat.yaml
deleted file mode 100644
index 561d45d6e..000000000
--- a/deployments/templates/chat.yaml
+++ /dev/null
@@ -1,118 +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.
-
-# Configuration for OpenIMServer
-
-# -----------------------------------------------------------------
-# TODO: This config file is the template file
-# --| source: deployments/templates/chat.yaml
-# --| env: scripts/install/environment
-# --| target: config/config.yaml
-# -----------------------------------------------------------------
-
-###################### Zookeeper ######################
-# Zookeeper configuration
-# It's not recommended to modify the schema
-zookeeper:
- schema: ${ZOOKEEPER_SCHEMA}
- zkAddr:
- - ${ZOOKEEPER_ADDRESS}:${ZOOKEEPER_PORT}
- username: ${ZOOKEEPER_USERNAME}
- password: ${ZOOKEEPER_PASSWORD}
-
-###################### Chat API ######################
-chatApi:
- openImChatApiPort: [ ${OPENIM_CHAT_API_PORT} ]
- listenIP: ${CHAT_API_LISTEN_IP}
-
-###################### Admin API ######################
-adminApi:
- openImAdminApiPort: [ ${OPENIM_ADMIN_API_PORT} ]
- listenIP: ${ADMIN_API_LISTEN_IP}
-
-###################### RPC ######################
-rpc:
- registerIP: #作为rpc启动时,注册到zookeeper的IP,api/gateway能访问到此ip和对应的rpcPort中的端口
- listenIP: #默认为0.0.0.0
-
-rpcPort:
- openImAdminPort: [ ${OPENIM_ADMIN_PORT} ]
- openImChatPort: [ ${OPENIM_CHAT_PORT} ]
-rpcRegisterName:
- openImAdminName: ${OPENIM_ADMIN_NAME}
- openImChatName: ${OPENIM_CHAT_NAME}
-
-###################### Log ######################
-log:
- storageLocation: ../logs/ #存放目录
-# rotationTime: 24 #日志旋转时间
-# remainRotationCount: 2 #日志数量
-# remainLogLevel: 6 #日志级别 6表示全都打印,
-# isStdout: false
-# isJson: false
-# withStack: false
-
-###################### Secret & Token Policy ######################
-# secret: openIM123
-#tokenPolicy:
-# expire: 86400
-
-###################### Verify Code ######################
-verifyCode:
- validTime: 300 # 验证码有效时间
- validCount: 5 # 验证码有效次数
- uintTime: 86400 # 单位时间间隔
- maxCount: 10 # 单位时间内最大获取次数
- superCode: "666666" # 超级验证码(只有use为空时使用)
- len: 6 # 验证码长度
- use: "" # 使用的验证码服务(use: "ali")
- ali:
- endpoint: "dysmsapi.aliyuncs.com"
- accessKeyId: ""
- accessKeySecret: ""
- signName: ""
- verificationCodeTemplateCode: ""
- mail: # 根据对应的发件邮箱更改 sendMail、senderAuthorizationCode、smtpAddr、smtpPort 即可
- title: ""
- senderMail: "" # 发送者
- senderAuthorizationCode: "" # 授权码
- smtpAddr: "smtp.qq.com" # smtp 服务器地址
- smtpPort: 25 # smtp 服务器邮件发送端口
- testDepartMentID: 001
- imAPIURL: http://127.0.0.1:10002
-
-###################### Proxy Header ######################
-# 获取ip的header,没有配置直接获取远程地址
-#proxyHeader: "X-Forwarded-For"
-
-###################### Admin List ######################
-adminList:
- - adminID: admin1
- nickname: chat1
- imAdmin: openIM123456
- - adminID: admin2
- nickname: chat2
- imAdmin: openIM654321
- - adminID: admin3
- nickname: chat3
- imAdmin: openIMAdmin
-
-###################### OpenIM URL ######################
-openIMUrl: ${OPENIM_SERVER_ADDRESS}:${API_OPENIM_PORT}
-
-###################### Redis ######################
-redis:
- # address: [ 127.0.0.1:16379 ]
- # username:
- # password: openIM123
diff --git a/deployments/templates/email.tmpl b/deployments/templates/email.tmpl
new file mode 100644
index 000000000..0385601d0
--- /dev/null
+++ b/deployments/templates/email.tmpl
@@ -0,0 +1,16 @@
+{{ define "email.to.html" }}
+{{ range .Alerts }}
+
+
+
OpenIM Alert
+
Alert Program: Prometheus Alert
+
Severity Level: {{ .Labels.severity }}
+
Alert Type: {{ .Labels.alertname }}
+
Affected Host: {{ .Labels.instance }}
+
Affected Service: {{ .Labels.job }}
+
Alert Subject: {{ .Annotations.summary }}
+
Trigger Time: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
+
+
+{{ end }}
+{{ end }}
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index b4118b9ce..ab9c87c02 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -1,3 +1,17 @@
+# 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.
+
# ======================================
# ========= Basic Configuration ========
# ======================================
@@ -10,10 +24,6 @@ USER=${OPENIM_USER}
# Default: PASSWORD=openIM123
PASSWORD=${PASSWORD}
-# Endpoint for the MinIO object storage service.
-# Default: MINIO_ENDPOINT=http://172.28.0.1:10005
-MINIO_ENDPOINT=${MINIO_ENDPOINT}
-
# Base URL for the application programming interface (API).
# Default: API_URL=http://172.28.0.1:10002
API_URL=${API_URL}
diff --git a/deployments/templates/helm-image.yaml b/deployments/templates/helm-image.yaml
index 317bc34ac..ef64abf91 100644
--- a/deployments/templates/helm-image.yaml
+++ b/deployments/templates/helm-image.yaml
@@ -1,3 +1,17 @@
+# 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.
+
#This configuration file is used to override the use of the value.yaml variable.
#Currently, only the configuration with ingressName as nginx is provided.
#If it is another gateway such as istio or treafik, please modify the corresponding gateway requirements
diff --git a/config/instance-down-rules.yml b/deployments/templates/instance-down-rules.yml
similarity index 61%
rename from config/instance-down-rules.yml
rename to deployments/templates/instance-down-rules.yml
index 5541d2c54..7a6e9fda9 100644
--- a/config/instance-down-rules.yml
+++ b/deployments/templates/instance-down-rules.yml
@@ -1,3 +1,17 @@
+# 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.
+
groups:
- name: instance_down
rules:
diff --git a/config/notification.yaml b/deployments/templates/notification.yaml
similarity index 88%
rename from config/notification.yaml
rename to deployments/templates/notification.yaml
index 5e5223a00..665c21261 100644
--- a/config/notification.yaml
+++ b/deployments/templates/notification.yaml
@@ -12,18 +12,36 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# Determines if a message should be sent. If set to false, it triggers a silent sync without a message. If true, it requires triggering a conversation.
+# For rpc notification, send twice: once as a message and once as a notification.
+# The options field 'isNotification' indicates if it's a notification.
groupCreated:
- isSendMsg: true #是否发送消息,false不发消息为无声的触发同步。true发消息需要触发会话,rpc notification直接发两次,一次消息一次通知, options字段isNotification是否为通知
- reliabilityLevel: 1 # 1为online才发送 2为必达
- unreadCount: false # 只在isSendMsg为true的情况下有作用
+ isSendMsg: true
+
+# Reliability level of the message sending.
+# Set to 1 to send only when online, 2 for guaranteed delivery.
+ reliabilityLevel: 1
+
+# This setting is effective only when 'isSendMsg' is true.
+# It controls whether to count unread messages.
+ unreadCount: false
+
+# Configuration for offline push notifications.
offlinePush:
- enable: false # 开启该开关
- title: "create group title" # xx create the group
+ # Enables or disables offline push notifications.
+ enable: false
+
+ # Title for the notification when a group is created.
+ title: "create group title"
+
+ # Description for the notification.
desc: "create group desc"
- ext: "create group ext"
-# 不加消息contentType,content统一json 结构体使用pb的
+ # Additional information for the notification.
+ ext: "create group ext"
+# Content type is not added here.
+# Content should use a JSON structure conforming to the protobuf format.
groupInfoSet:
isSendMsg: false
@@ -334,4 +352,3 @@ conversationSetPrivate:
title: "burn after reading"
desc: "burn after reading"
ext: "burn after reading"
-
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index d822fec13..ed5dc4fe1 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -37,13 +37,20 @@ zookeeper:
###################### Mongo ######################
# MongoDB configuration
-# If uri is not empty, it will be used directly
-#
-# MongoDB address for standalone setup, Mongos address for sharded cluster setup
-# Default MongoDB database name
-# Maximum connection pool size
+
+# If uri is not empty, it will be used directly for the MongoDB connection.
+# This is a complete MongoDB URI string.
+# Example: mongodb://user:password@host1:port1,host2:port2/dbname?options
mongo:
uri: ${MONGO_URI}
+
+# List of MongoDB server addresses.
+# Used for constructing the MongoDB URI if 'uri' above is empty.
+# For a standalone setup, specify the address of the single server.
+# For a sharded cluster, specify the addresses of the Mongos servers.
+# Example: [ '172.28.0.1:37017', '172.28.0.2:37017' ]
+# Default MongoDB database name
+# Maximum connection pool size
address: [ ${MONGO_ADDRESS}:${MONGO_PORT} ]
database: ${MONGO_DATABASE}
username: ${MONGO_USERNAME}
diff --git a/deployments/templates/prometheus.yml b/deployments/templates/prometheus.yml
index fb07a8129..5c3e0af66 100644
--- a/deployments/templates/prometheus.yml
+++ b/deployments/templates/prometheus.yml
@@ -1,3 +1,17 @@
+# 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.
+
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
diff --git a/internal/api/msg.go b/internal/api/msg.go
index 22182d985..664ee505a 100644
--- a/internal/api/msg.go
+++ b/internal/api/msg.go
@@ -27,6 +27,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/mitchellh/mapstructure"
+
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
diff --git a/internal/msggateway/compressor_test.go b/internal/msggateway/compressor_test.go
index d41c57bf3..b1544f063 100644
--- a/internal/msggateway/compressor_test.go
+++ b/internal/msggateway/compressor_test.go
@@ -1,3 +1,17 @@
+// 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 msggateway
import (
diff --git a/internal/push/offlinepush/dummy/push.go b/internal/push/offlinepush/dummy/push.go
index 2b15bc05d..f147886d9 100644
--- a/internal/push/offlinepush/dummy/push.go
+++ b/internal/push/offlinepush/dummy/push.go
@@ -1,3 +1,17 @@
+// 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 dummy
import (
diff --git a/internal/push/push_rpc_server.go b/internal/push/push_rpc_server.go
index 9e66f8f73..188ddc0e1 100644
--- a/internal/push/push_rpc_server.go
+++ b/internal/push/push_rpc_server.go
@@ -16,9 +16,10 @@ package push
import (
"context"
- "github.com/OpenIMSDK/tools/utils"
"sync"
+ "github.com/OpenIMSDK/tools/utils"
+
"google.golang.org/grpc"
"github.com/OpenIMSDK/protocol/constant"
diff --git a/internal/rpc/friend/callback.go b/internal/rpc/friend/callback.go
index d541071f5..e5054d9a9 100644
--- a/internal/rpc/friend/callback.go
+++ b/internal/rpc/friend/callback.go
@@ -16,8 +16,10 @@ package friend
import (
"context"
+
pbfriend "github.com/OpenIMSDK/protocol/friend"
"github.com/OpenIMSDK/tools/utils"
+
cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/http"
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index 21422fae3..20c47ad8f 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -16,6 +16,7 @@ package friend
import (
"context"
+
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/protocol/sdkws"
diff --git a/internal/rpc/group/callback.go b/internal/rpc/group/callback.go
index 1599cc7b4..4a89a16fb 100644
--- a/internal/rpc/group/callback.go
+++ b/internal/rpc/group/callback.go
@@ -16,9 +16,10 @@ package group
import (
"context"
- "github.com/OpenIMSDK/tools/log"
"time"
+ "github.com/OpenIMSDK/tools/log"
+
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/group"
"github.com/OpenIMSDK/protocol/wrapperspb"
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index b05b14b59..2c3c6fc43 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -17,13 +17,14 @@ package group
import (
"context"
"fmt"
- "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"math/big"
"math/rand"
"strconv"
"strings"
"time"
+ "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
+
pbconversation "github.com/OpenIMSDK/protocol/conversation"
"github.com/OpenIMSDK/protocol/wrapperspb"
"github.com/OpenIMSDK/tools/tx"
diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go
index 061498abb..5324ccba8 100644
--- a/internal/rpc/msg/as_read.go
+++ b/internal/rpc/msg/as_read.go
@@ -16,16 +16,18 @@ package msg
import (
"context"
+
utils2 "github.com/OpenIMSDK/tools/utils"
"github.com/redis/go-redis/v9"
- cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
+
+ cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
)
func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *msg.GetConversationsHasReadAndMaxSeqReq) (resp *msg.GetConversationsHasReadAndMaxSeqResp, err error) {
@@ -173,7 +175,7 @@ func (m *msgServer) MarkConversationAsRead(
m.conversationAndGetRecvID(conversation, req.UserID), seqs, hasReadSeq); err != nil {
return nil, err
}
-
+
} else if conversation.ConversationType == constant.SuperGroupChatType ||
conversation.ConversationType == constant.NotificationChatType {
if req.HasReadSeq > hasReadSeq {
@@ -222,4 +224,4 @@ func (m *msgServer) sendMarkAsReadNotification(
log.ZWarn(ctx, "send has read Receipt err", err)
}
return nil
-}
\ No newline at end of file
+}
diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go
index 4ce5a5443..0bd71d9f7 100644
--- a/internal/rpc/msg/callback.go
+++ b/internal/rpc/msg/callback.go
@@ -16,6 +16,7 @@ package msg
import (
"context"
+
"github.com/OpenIMSDK/protocol/sdkws"
"google.golang.org/protobuf/proto"
@@ -24,6 +25,7 @@ import (
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
+
cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
diff --git a/internal/rpc/third/log.go b/internal/rpc/third/log.go
index 57d4f536e..11c7467b8 100644
--- a/internal/rpc/third/log.go
+++ b/internal/rpc/third/log.go
@@ -1,3 +1,17 @@
+// 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 third
import (
diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go
index e87b4674e..7d865af5f 100644
--- a/internal/rpc/user/callback.go
+++ b/internal/rpc/user/callback.go
@@ -16,6 +16,7 @@ package user
import (
"context"
+
pbuser "github.com/OpenIMSDK/protocol/user"
"github.com/OpenIMSDK/tools/utils"
diff --git a/internal/tools/cron_task_test.go b/internal/tools/cron_task_test.go
index 1f4f1f5c1..28bc2c945 100644
--- a/internal/tools/cron_task_test.go
+++ b/internal/tools/cron_task_test.go
@@ -1,3 +1,17 @@
+// 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 tools
import (
diff --git a/pkg/apistruct/msg.go b/pkg/apistruct/msg.go
index 61b4d832b..4b7bd1e6f 100644
--- a/pkg/apistruct/msg.go
+++ b/pkg/apistruct/msg.go
@@ -16,11 +16,11 @@ package apistruct
type PictureBaseInfo struct {
UUID string `mapstructure:"uuid"`
- Type string `mapstructure:"type" validate:"required"`
+ Type string `mapstructure:"type" validate:"required"`
Size int64 `mapstructure:"size"`
- Width int32 `mapstructure:"width" validate:"required"`
+ Width int32 `mapstructure:"width" validate:"required"`
Height int32 `mapstructure:"height" validate:"required"`
- Url string `mapstructure:"url" validate:"required"`
+ Url string `mapstructure:"url" validate:"required"`
}
type PictureElem struct {
@@ -34,28 +34,28 @@ type SoundElem struct {
SoundPath string `mapstructure:"soundPath"`
SourceURL string `mapstructure:"sourceUrl" validate:"required"`
DataSize int64 `mapstructure:"dataSize"`
- Duration int64 `mapstructure:"duration" validate:"required,min=1"`
+ Duration int64 `mapstructure:"duration" validate:"required,min=1"`
}
type VideoElem struct {
- VideoPath string `mapstructure:"videoPath" `
+ VideoPath string `mapstructure:"videoPath"`
VideoUUID string `mapstructure:"videoUUID"`
- VideoURL string `mapstructure:"videoUrl" validate:"required"`
- VideoType string `mapstructure:"videoType" validate:"required"`
- VideoSize int64 `mapstructure:"videoSize" validate:"required"`
- Duration int64 `mapstructure:"duration" validate:"required"`
+ VideoURL string `mapstructure:"videoUrl" validate:"required"`
+ VideoType string `mapstructure:"videoType" validate:"required"`
+ VideoSize int64 `mapstructure:"videoSize" validate:"required"`
+ Duration int64 `mapstructure:"duration" validate:"required"`
SnapshotPath string `mapstructure:"snapshotPath"`
SnapshotUUID string `mapstructure:"snapshotUUID"`
SnapshotSize int64 `mapstructure:"snapshotSize"`
- SnapshotURL string `mapstructure:"snapshotUrl" validate:"required"`
- SnapshotWidth int32 `mapstructure:"snapshotWidth" validate:"required"`
+ SnapshotURL string `mapstructure:"snapshotUrl" validate:"required"`
+ SnapshotWidth int32 `mapstructure:"snapshotWidth" validate:"required"`
SnapshotHeight int32 `mapstructure:"snapshotHeight" validate:"required"`
}
type FileElem struct {
- FilePath string `mapstructure:"filePath" `
+ FilePath string `mapstructure:"filePath"`
UUID string `mapstructure:"uuid"`
SourceURL string `mapstructure:"sourceUrl" validate:"required"`
- FileName string `mapstructure:"fileName" validate:"required"`
- FileSize int64 `mapstructure:"fileSize" validate:"required"`
+ FileName string `mapstructure:"fileName" validate:"required"`
+ FileSize int64 `mapstructure:"fileSize" validate:"required"`
}
type AtElem struct {
Text string `mapstructure:"text"`
@@ -63,9 +63,9 @@ type AtElem struct {
IsAtSelf bool `mapstructure:"isAtSelf"`
}
type LocationElem struct {
- Description string `mapstructure:"description" `
- Longitude float64 `mapstructure:"longitude" validate:"required"`
- Latitude float64 `mapstructure:"latitude" validate:"required"`
+ Description string `mapstructure:"description"`
+ Longitude float64 `mapstructure:"longitude" validate:"required"`
+ Latitude float64 `mapstructure:"latitude" validate:"required"`
}
type CustomElem struct {
Data string `mapstructure:"data" validate:"required"`
@@ -87,7 +87,7 @@ type OANotificationElem struct {
NotificationType int32 `mapstructure:"notificationType" json:"notificationType" validate:"required"`
Text string `mapstructure:"text" json:"text" validate:"required"`
Url string `mapstructure:"url" json:"url"`
- MixType int32 `mapstructure:"mixType" json:"mixType" validate:"required"`
+ MixType int32 `mapstructure:"mixType" json:"mixType" validate:"required"`
PictureElem *PictureElem `mapstructure:"pictureElem" json:"pictureElem"`
SoundElem *SoundElem `mapstructure:"soundElem" json:"soundElem"`
VideoElem *VideoElem `mapstructure:"videoElem" json:"videoElem"`
diff --git a/pkg/callbackstruct/constant.go b/pkg/callbackstruct/constant.go
index 2af337ac6..0a03a1ef1 100644
--- a/pkg/callbackstruct/constant.go
+++ b/pkg/callbackstruct/constant.go
@@ -1,3 +1,17 @@
+// 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 callbackstruct
const CallbackBeforeInviteJoinGroupCommand = "callbackBeforeInviteJoinGroupCommand"
diff --git a/pkg/callbackstruct/revoke.go b/pkg/callbackstruct/revoke.go
index 364c0162b..1f5e0b0c1 100644
--- a/pkg/callbackstruct/revoke.go
+++ b/pkg/callbackstruct/revoke.go
@@ -1,3 +1,17 @@
+// 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 callbackstruct
type CallbackAfterRevokeMsgReq struct {
diff --git a/pkg/common/cmd/constant.go b/pkg/common/cmd/constant.go
index 835593bbe..c332ce3a6 100644
--- a/pkg/common/cmd/constant.go
+++ b/pkg/common/cmd/constant.go
@@ -1,3 +1,17 @@
+// 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 cmd
const (
diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go
index 5fb8fe7e2..6da89fc8f 100644
--- a/pkg/common/config/config.go
+++ b/pkg/common/config/config.go
@@ -16,6 +16,7 @@ package config
import (
"bytes"
+
"github.com/OpenIMSDK/tools/discoveryregistry"
"gopkg.in/yaml.v3"
)
diff --git a/pkg/common/config/parse.go b/pkg/common/config/parse.go
index 22e458e00..1410a5a4a 100644
--- a/pkg/common/config/parse.go
+++ b/pkg/common/config/parse.go
@@ -35,7 +35,7 @@ const (
DefaultFolderPath = "../config/"
)
-// return absolude path join ../config/, this is k8s container config path
+// return absolude path join ../config/, this is k8s container config path.
func GetDefaultConfigPath() string {
b, err := filepath.Abs(os.Args[0])
if err != nil {
@@ -45,7 +45,7 @@ func GetDefaultConfigPath() string {
return filepath.Join(filepath.Dir(b), "../config/")
}
-// getProjectRoot returns the absolute path of the project root directory
+// getProjectRoot returns the absolute path of the project root directory.
func GetProjectRoot() string {
b, _ := filepath.Abs(os.Args[0])
diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go
index 0c71aac22..8d960546a 100644
--- a/pkg/common/convert/user.go
+++ b/pkg/common/convert/user.go
@@ -15,9 +15,10 @@
package convert
import (
- "github.com/OpenIMSDK/protocol/sdkws"
"time"
+ "github.com/OpenIMSDK/protocol/sdkws"
+
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
diff --git a/pkg/common/db/cache/group.go b/pkg/common/db/cache/group.go
index 603d8e534..57fcf1a9b 100644
--- a/pkg/common/db/cache/group.go
+++ b/pkg/common/db/cache/group.go
@@ -39,7 +39,7 @@ const (
groupMemberIDsKey = "GROUP_MEMBER_IDS:"
groupMembersHashKey = "GROUP_MEMBERS_HASH2:"
groupMemberInfoKey = "GROUP_MEMBER_INFO:"
- //groupOwnerInfoKey = "GROUP_OWNER_INFO:"
+ //groupOwnerInfoKey = "GROUP_OWNER_INFO:".
joinedGroupsKey = "JOIN_GROUPS_KEY:"
groupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:"
groupRoleLevelMemberIDsKey = "GROUP_ROLE_LEVEL_MEMBER_IDS:"
diff --git a/pkg/common/db/cache/init_redis.go b/pkg/common/db/cache/init_redis.go
index 77b38d9b7..63d2f5707 100644
--- a/pkg/common/db/cache/init_redis.go
+++ b/pkg/common/db/cache/init_redis.go
@@ -18,6 +18,8 @@ import (
"context"
"errors"
"fmt"
+ "os"
+ "strings"
"time"
"github.com/redis/go-redis/v9"
@@ -43,6 +45,9 @@ func NewRedis() (redis.UniversalClient, error) {
return redisClient, nil
}
+ // Read configuration from environment variables
+ overrideConfigFromEnv()
+
if len(config.Config.Redis.Address) == 0 {
return nil, errors.New("redis address is empty")
}
@@ -60,9 +65,9 @@ func NewRedis() (redis.UniversalClient, error) {
rdb = redis.NewClient(&redis.Options{
Addr: config.Config.Redis.Address[0],
Username: config.Config.Redis.Username,
- Password: config.Config.Redis.Password, // no password set
- DB: 0, // use default DB
- PoolSize: 100, // connection pool size
+ Password: config.Config.Redis.Password,
+ DB: 0, // use default DB
+ PoolSize: 100, // connection pool size
MaxRetries: maxRetry,
})
}
@@ -78,3 +83,16 @@ func NewRedis() (redis.UniversalClient, error) {
redisClient = rdb
return rdb, err
}
+
+// overrideConfigFromEnv overrides configuration fields with environment variables if present.
+func overrideConfigFromEnv() {
+ if envAddr := os.Getenv("REDIS_ADDRESS"); envAddr != "" {
+ config.Config.Redis.Address = strings.Split(envAddr, ",") // Assuming addresses are comma-separated
+ }
+ if envUser := os.Getenv("REDIS_USERNAME"); envUser != "" {
+ config.Config.Redis.Username = envUser
+ }
+ if envPass := os.Getenv("REDIS_PASSWORD"); envPass != "" {
+ config.Config.Redis.Password = envPass
+ }
+}
diff --git a/pkg/common/db/cache/msg_test.go b/pkg/common/db/cache/msg_test.go
index 3fddf5965..65413199a 100644
--- a/pkg/common/db/cache/msg_test.go
+++ b/pkg/common/db/cache/msg_test.go
@@ -1,3 +1,17 @@
+// 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 cache
import (
diff --git a/pkg/common/db/cache/s3.go b/pkg/common/db/cache/s3.go
index ba40ceacc..1e68cedf8 100644
--- a/pkg/common/db/cache/s3.go
+++ b/pkg/common/db/cache/s3.go
@@ -1,3 +1,17 @@
+// 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 cache
import (
diff --git a/pkg/common/db/mgo/black.go b/pkg/common/db/mgo/black.go
index 6235639aa..1047e5c30 100644
--- a/pkg/common/db/mgo/black.go
+++ b/pkg/common/db/mgo/black.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/mgo/conversation.go b/pkg/common/db/mgo/conversation.go
index 72d04ebb3..bf5d1a145 100644
--- a/pkg/common/db/mgo/conversation.go
+++ b/pkg/common/db/mgo/conversation.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go
index aa9cb0301..8f3528d91 100644
--- a/pkg/common/db/mgo/friend.go
+++ b/pkg/common/db/mgo/friend.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/mgo/friend_request.go b/pkg/common/db/mgo/friend_request.go
index c1be87ca2..bfc101917 100644
--- a/pkg/common/db/mgo/friend_request.go
+++ b/pkg/common/db/mgo/friend_request.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/mgo/group.go b/pkg/common/db/mgo/group.go
index 3553b6b56..65dbbca59 100644
--- a/pkg/common/db/mgo/group.go
+++ b/pkg/common/db/mgo/group.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/mgo/group_member.go b/pkg/common/db/mgo/group_member.go
index ed09a028b..8c3041901 100644
--- a/pkg/common/db/mgo/group_member.go
+++ b/pkg/common/db/mgo/group_member.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/mgo/group_request.go b/pkg/common/db/mgo/group_request.go
index e88a39bf5..cb04d2308 100644
--- a/pkg/common/db/mgo/group_request.go
+++ b/pkg/common/db/mgo/group_request.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/mgo/log.go b/pkg/common/db/mgo/log.go
index aa280fcf2..09f002ee3 100644
--- a/pkg/common/db/mgo/log.go
+++ b/pkg/common/db/mgo/log.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/mgo/object.go b/pkg/common/db/mgo/object.go
index 5976b2d28..88bfde213 100644
--- a/pkg/common/db/mgo/object.go
+++ b/pkg/common/db/mgo/object.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 4a53cb3c4..37e354cbb 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -1,3 +1,17 @@
+// 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 mgo
import (
diff --git a/pkg/common/db/s3/cos/internal.go b/pkg/common/db/s3/cos/internal.go
index 02afde684..064546953 100644
--- a/pkg/common/db/s3/cos/internal.go
+++ b/pkg/common/db/s3/cos/internal.go
@@ -1,3 +1,17 @@
+// 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 cos
import (
diff --git a/pkg/common/db/s3/minio/internal.go b/pkg/common/db/s3/minio/internal.go
index 41129ce31..7e9dcd9e4 100644
--- a/pkg/common/db/s3/minio/internal.go
+++ b/pkg/common/db/s3/minio/internal.go
@@ -1,3 +1,17 @@
+// 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 minio
import (
diff --git a/pkg/common/db/s3/minio/thumbnail.go b/pkg/common/db/s3/minio/thumbnail.go
index 01b14541b..49c376c9f 100644
--- a/pkg/common/db/s3/minio/thumbnail.go
+++ b/pkg/common/db/s3/minio/thumbnail.go
@@ -1,3 +1,17 @@
+// 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 minio
import (
diff --git a/pkg/common/db/table/relation/log.go b/pkg/common/db/table/relation/log.go
index f690ff8aa..ba63c0c2b 100644
--- a/pkg/common/db/table/relation/log.go
+++ b/pkg/common/db/table/relation/log.go
@@ -1,3 +1,17 @@
+// 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 relation
import (
diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go
index 38a335567..2c1dc6f38 100644
--- a/pkg/common/db/unrelation/mongo.go
+++ b/pkg/common/db/unrelation/mongo.go
@@ -17,11 +17,11 @@ package unrelation
import (
"context"
"fmt"
+ "os"
"strings"
"time"
"go.mongodb.org/mongo-driver/bson"
-
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
@@ -34,7 +34,8 @@ import (
)
const (
- maxRetry = 10 // number of retries
+ maxRetry = 10 // number of retries
+ mongoConnTimeout = 10 * time.Second
)
type Mongo struct {
@@ -44,90 +45,122 @@ type Mongo struct {
// NewMongo Initialize MongoDB connection.
func NewMongo() (*Mongo, error) {
specialerror.AddReplace(mongo.ErrNoDocuments, errs.ErrRecordNotFound)
- uri := "mongodb://sample.host:27017/?maxPoolSize=20&w=majority"
- if config.Config.Mongo.Uri != "" {
- uri = config.Config.Mongo.Uri
- } else {
- mongodbHosts := ""
- for i, v := range config.Config.Mongo.Address {
- if i == len(config.Config.Mongo.Address)-1 {
- mongodbHosts += v
- } else {
- mongodbHosts += v + ","
- }
- }
- if config.Config.Mongo.Password != "" && config.Config.Mongo.Username != "" {
- uri = fmt.Sprintf("mongodb://%s:%s@%s/%s?maxPoolSize=%d&authSource=admin",
- config.Config.Mongo.Username, config.Config.Mongo.Password, mongodbHosts,
- config.Config.Mongo.Database, config.Config.Mongo.MaxPoolSize)
- } else {
- uri = fmt.Sprintf("mongodb://%s/%s/?maxPoolSize=%d&authSource=admin",
- mongodbHosts, config.Config.Mongo.Database,
- config.Config.Mongo.MaxPoolSize)
- }
- }
- fmt.Println("mongo:", uri)
+ uri := buildMongoURI()
+
var mongoClient *mongo.Client
- var err error = nil
+ var err error
+
+ // Retry connecting to MongoDB
for i := 0; i <= maxRetry; i++ {
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
+ ctx, cancel := context.WithTimeout(context.Background(), mongoConnTimeout)
defer cancel()
mongoClient, err = mongo.Connect(ctx, options.Client().ApplyURI(uri))
if err == nil {
return &Mongo{db: mongoClient}, nil
}
- if cmdErr, ok := err.(mongo.CommandError); ok {
- if cmdErr.Code == 13 || cmdErr.Code == 18 {
- return nil, err
- } else {
- fmt.Printf("Failed to connect to MongoDB: %s\n", err)
- }
+ if shouldRetry(err) {
+ fmt.Printf("Failed to connect to MongoDB, retrying: %s\n", err)
+ time.Sleep(time.Second) // exponential backoff could be implemented here
+ continue
}
+ return nil, err
}
return nil, err
}
+func buildMongoURI() string {
+ uri := os.Getenv("MONGO_URI")
+ if uri != "" {
+ return uri
+ }
+
+ username := os.Getenv("MONGO_USERNAME")
+ password := os.Getenv("MONGO_PASSWORD")
+ address := os.Getenv("MONGO_ADDRESS")
+ port := os.Getenv("MONGO_PORT")
+ database := os.Getenv("MONGO_DATABASE")
+ maxPoolSize := os.Getenv("MONGO_MAX_POOL_SIZE")
+
+ if username == "" {
+ username = config.Config.Mongo.Username
+ }
+ if password == "" {
+ password = config.Config.Mongo.Password
+ }
+ if address == "" {
+ address = strings.Join(config.Config.Mongo.Address, ",")
+ } else if port != "" {
+ address = fmt.Sprintf("%s:%s", address, port)
+ }
+ if database == "" {
+ database = config.Config.Mongo.Database
+ }
+ if maxPoolSize == "" {
+ maxPoolSize = fmt.Sprint(config.Config.Mongo.MaxPoolSize)
+ }
+
+ uriFormat := "mongodb://%s/%s?maxPoolSize=%s&authSource=admin"
+ if username != "" && password != "" {
+ uriFormat = "mongodb://%s:%s@%s/%s?maxPoolSize=%s&authSource=admin"
+ return fmt.Sprintf(uriFormat, username, password, address, database, maxPoolSize)
+ }
+ return fmt.Sprintf(uriFormat, address, database, maxPoolSize)
+}
+
+func shouldRetry(err error) bool {
+ if cmdErr, ok := err.(mongo.CommandError); ok {
+ return cmdErr.Code != 13 && cmdErr.Code != 18
+ }
+ return true
+}
+
+// GetClient returns the MongoDB client.
func (m *Mongo) GetClient() *mongo.Client {
return m.db
}
+// GetDatabase returns the specific database from MongoDB.
func (m *Mongo) GetDatabase() *mongo.Database {
return m.db.Database(config.Config.Mongo.Database)
}
+// CreateMsgIndex creates an index for messages in MongoDB.
func (m *Mongo) CreateMsgIndex() error {
return m.createMongoIndex(unrelation.Msg, true, "doc_id")
}
+// createMongoIndex creates an index in a MongoDB collection.
func (m *Mongo) createMongoIndex(collection string, isUnique bool, keys ...string) error {
- db := m.db.Database(config.Config.Mongo.Database).Collection(collection)
+ db := m.GetDatabase().Collection(collection)
opts := options.CreateIndexes().SetMaxTime(10 * time.Second)
indexView := db.Indexes()
- keysDoc := bson.D{}
- // create composite indexes
- for _, key := range keys {
- if strings.HasPrefix(key, "-") {
- keysDoc = append(keysDoc, bson.E{Key: strings.TrimLeft(key, "-"), Value: -1})
- // keysDoc = keysDoc.Append(strings.TrimLeft(key, "-"), bsonx.Int32(-1))
- } else {
- keysDoc = append(keysDoc, bson.E{Key: key, Value: 1})
- // keysDoc = keysDoc.Append(key, bsonx.Int32(1))
- }
- }
- // create index
+
+ keysDoc := buildIndexKeys(keys)
+
index := mongo.IndexModel{
Keys: keysDoc,
}
if isUnique {
index.Options = options.Index().SetUnique(true)
}
- result, err := indexView.CreateOne(
- context.Background(),
- index,
- opts,
- )
+
+ _, err := indexView.CreateOne(context.Background(), index, opts)
if err != nil {
- return utils.Wrap(err, result)
+ return utils.Wrap(err, "CreateIndex")
}
return nil
}
+
+// buildIndexKeys builds the BSON document for index keys.
+func buildIndexKeys(keys []string) bson.D {
+ keysDoc := bson.D{}
+ for _, key := range keys {
+ direction := 1 // default direction is ascending
+ if strings.HasPrefix(key, "-") {
+ direction = -1 // descending order for prefixed with "-"
+ key = strings.TrimLeft(key, "-")
+ }
+ keysDoc = append(keysDoc, bson.E{Key: key, Value: direction})
+ }
+ return keysDoc
+}
diff --git a/pkg/common/discoveryregister/discoveryregister.go b/pkg/common/discoveryregister/discoveryregister.go
index 62c1f4a31..c14323027 100644
--- a/pkg/common/discoveryregister/discoveryregister.go
+++ b/pkg/common/discoveryregister/discoveryregister.go
@@ -1,159 +1,42 @@
+// 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 discoveryregister
import (
- "context"
"errors"
- "fmt"
"os"
- "strconv"
- "strings"
- "time"
- "github.com/OpenIMSDK/tools/discoveryregistry"
- openkeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper"
- "github.com/OpenIMSDK/tools/log"
- "google.golang.org/grpc"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/kubernetes"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/zookeeper"
- "github.com/openimsdk/open-im-server/v3/pkg/common/config"
+ "github.com/OpenIMSDK/tools/discoveryregistry"
)
+// NewDiscoveryRegister creates a new service discovery and registry client based on the provided environment type.
func NewDiscoveryRegister(envType string) (discoveryregistry.SvcDiscoveryRegistry, error) {
- var client discoveryregistry.SvcDiscoveryRegistry
- var err error
+
+ if os.Getenv("ENVS_DISCOVERY") != "" {
+ envType = os.Getenv("ENVS_DISCOVERY")
+ }
+
switch envType {
case "zookeeper":
- client, err = openkeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema,
- openkeeper.WithFreq(time.Hour), openkeeper.WithUserNameAndPassword(
- config.Config.Zookeeper.Username,
- config.Config.Zookeeper.Password,
- ), openkeeper.WithRoundRobin(), openkeeper.WithTimeout(10), openkeeper.WithLogger(log.NewZkLogger()))
+ return zookeeper.NewZookeeperDiscoveryRegister()
case "k8s":
- client, err = NewK8sDiscoveryRegister()
+ return kubernetes.NewK8sDiscoveryRegister()
default:
- client = nil
- err = errors.New("envType not correct")
+ return nil, errors.New("envType not correct")
}
- return client, err
-}
-
-type K8sDR struct {
- options []grpc.DialOption
- rpcRegisterAddr string
-}
-
-func NewK8sDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) {
- return &K8sDR{}, nil
-}
-
-func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.DialOption) error {
- if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
- cli.rpcRegisterAddr = serviceName
- } else {
- cli.rpcRegisterAddr = cli.getSelfHost(context.Background())
- }
-
- return nil
-}
-func (cli *K8sDR) UnRegister() error {
-
- return nil
-}
-func (cli *K8sDR) CreateRpcRootNodes(serviceNames []string) error {
-
- return nil
-}
-func (cli *K8sDR) RegisterConf2Registry(key string, conf []byte) error {
-
- return nil
-}
-
-func (cli *K8sDR) GetConfFromRegistry(key string) ([]byte, error) {
-
- return nil, nil
-}
-func (cli *K8sDR) getSelfHost(ctx context.Context) string {
- port := 88
- instance := "openimserver"
- selfPodName := os.Getenv("MY_POD_NAME")
- ns := os.Getenv("MY_POD_NAMESPACE")
- statefuleIndex := 0
- gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":")
- if len(gatewayEnds) != 2 {
- log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error"))
- } else {
- port, _ = strconv.Atoi(gatewayEnds[1])
- }
- podInfo := strings.Split(selfPodName, "-")
- instance = podInfo[0]
- count := len(podInfo)
- statefuleIndex, _ = strconv.Atoi(podInfo[count-1])
- host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, statefuleIndex, instance, ns, port)
- return host
-}
-
-// like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88
-func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string {
- port := 88
- instance := "openimserver"
- selfPodName := os.Getenv("MY_POD_NAME")
- replicas := os.Getenv("MY_MSGGATEWAY_REPLICACOUNT")
- ns := os.Getenv("MY_POD_NAMESPACE")
- gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":")
- if len(gatewayEnds) != 2 {
- log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error"))
- } else {
- port, _ = strconv.Atoi(gatewayEnds[1])
- }
- nReplicas, _ := strconv.Atoi(replicas)
- podInfo := strings.Split(selfPodName, "-")
- instance = podInfo[0]
- var ret []string
- for i := 0; i < nReplicas; i++ {
- host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, i, instance, ns, port)
- ret = append(ret, host)
- }
- log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret)
- return ret
-}
-func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
-
- if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
- conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
- return []*grpc.ClientConn{conn}, err
- } else {
- var ret []*grpc.ClientConn
- gatewayHosts := cli.getMsgGatewayHost(ctx)
- for _, host := range gatewayHosts {
- conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...)
- if err != nil {
- return nil, err
- } else {
- ret = append(ret, conn)
- }
- }
- return ret, nil
- }
-}
-func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
-
- return grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
-}
-func (cli *K8sDR) GetSelfConnTarget() string {
-
- return cli.rpcRegisterAddr
-}
-func (cli *K8sDR) AddOption(opts ...grpc.DialOption) {
- cli.options = append(cli.options, opts...)
-}
-func (cli *K8sDR) CloseConn(conn *grpc.ClientConn) {
- conn.Close()
-}
-
-// do not use this method for call rpc
-func (cli *K8sDR) GetClientLocalConns() map[string][]*grpc.ClientConn {
- fmt.Println("should not call this function!!!!!!!!!!!!!!!!!!!!!!!!!")
- return nil
-}
-func (cli *K8sDR) Close() {
- return
}
diff --git a/pkg/common/discoveryregister/discoveryregister_test.go b/pkg/common/discoveryregister/discoveryregister_test.go
index 8426598f9..d4a634b91 100644
--- a/pkg/common/discoveryregister/discoveryregister_test.go
+++ b/pkg/common/discoveryregister/discoveryregister_test.go
@@ -1,407 +1,59 @@
+// 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 discoveryregister
import (
- "context"
- "reflect"
+ "os"
"testing"
"github.com/OpenIMSDK/tools/discoveryregistry"
- "google.golang.org/grpc"
+ "github.com/stretchr/testify/assert"
)
-func TestNewDiscoveryRegister(t *testing.T) {
- type args struct {
- envType string
- }
- tests := []struct {
- name string
- args args
- want discoveryregistry.SvcDiscoveryRegistry
- wantErr bool
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := NewDiscoveryRegister(tt.args.envType)
- if (err != nil) != tt.wantErr {
- t.Errorf("NewDiscoveryRegister() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("NewDiscoveryRegister() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestNewK8sDiscoveryRegister(t *testing.T) {
- tests := []struct {
- name string
- want discoveryregistry.SvcDiscoveryRegistry
- wantErr bool
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := NewK8sDiscoveryRegister()
- if (err != nil) != tt.wantErr {
- t.Errorf("NewK8sDiscoveryRegister() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("NewK8sDiscoveryRegister() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestK8sDR_Register(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- type args struct {
- serviceName string
- host string
- port int
- opts []grpc.DialOption
- }
- tests := []struct {
- name string
- fields fields
- args args
- wantErr bool
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- if err := cli.Register(tt.args.serviceName, tt.args.host, tt.args.port, tt.args.opts...); (err != nil) != tt.wantErr {
- t.Errorf("K8sDR.Register() error = %v, wantErr %v", err, tt.wantErr)
- }
- })
- }
-}
-
-func TestK8sDR_UnRegister(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- tests := []struct {
- name string
- fields fields
- wantErr bool
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- if err := cli.UnRegister(); (err != nil) != tt.wantErr {
- t.Errorf("K8sDR.UnRegister() error = %v, wantErr %v", err, tt.wantErr)
- }
- })
- }
-}
-
-func TestK8sDR_CreateRpcRootNodes(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- type args struct {
- serviceNames []string
- }
- tests := []struct {
- name string
- fields fields
- args args
- wantErr bool
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- if err := cli.CreateRpcRootNodes(tt.args.serviceNames); (err != nil) != tt.wantErr {
- t.Errorf("K8sDR.CreateRpcRootNodes() error = %v, wantErr %v", err, tt.wantErr)
- }
- })
- }
-}
-
-func TestK8sDR_RegisterConf2Registry(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- type args struct {
- key string
- conf []byte
- }
- tests := []struct {
- name string
- fields fields
- args args
- wantErr bool
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- if err := cli.RegisterConf2Registry(tt.args.key, tt.args.conf); (err != nil) != tt.wantErr {
- t.Errorf("K8sDR.RegisterConf2Registry() error = %v, wantErr %v", err, tt.wantErr)
- }
- })
- }
-}
-
-func TestK8sDR_GetConfFromRegistry(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- type args struct {
- key string
- }
- tests := []struct {
- name string
- fields fields
- args args
- want []byte
- wantErr bool
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- got, err := cli.GetConfFromRegistry(tt.args.key)
- if (err != nil) != tt.wantErr {
- t.Errorf("K8sDR.GetConfFromRegistry() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("K8sDR.GetConfFromRegistry() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestK8sDR_GetConns(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- type args struct {
- ctx context.Context
- serviceName string
- opts []grpc.DialOption
- }
- tests := []struct {
- name string
- fields fields
- args args
- want []*grpc.ClientConn
- wantErr bool
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- got, err := cli.GetConns(tt.args.ctx, tt.args.serviceName, tt.args.opts...)
- if (err != nil) != tt.wantErr {
- t.Errorf("K8sDR.GetConns() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("K8sDR.GetConns() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestK8sDR_GetConn(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- type args struct {
- ctx context.Context
- serviceName string
- opts []grpc.DialOption
- }
- tests := []struct {
- name string
- fields fields
- args args
- want *grpc.ClientConn
- wantErr bool
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- got, err := cli.GetConn(tt.args.ctx, tt.args.serviceName, tt.args.opts...)
- if (err != nil) != tt.wantErr {
- t.Errorf("K8sDR.GetConn() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("K8sDR.GetConn() = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestK8sDR_GetSelfConnTarget(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- tests := []struct {
- name string
- fields fields
- want string
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- if got := cli.GetSelfConnTarget(); got != tt.want {
- t.Errorf("K8sDR.GetSelfConnTarget() = %v, want %v", got, tt.want)
- }
- })
- }
+func setupTestEnvironment() {
+ os.Setenv("ZOOKEEPER_SCHEMA", "openim")
+ os.Setenv("ZOOKEEPER_ADDRESS", "172.28.0.1:12181")
+ os.Setenv("ZOOKEEPER_USERNAME", "")
+ os.Setenv("ZOOKEEPER_PASSWORD", "")
}
-func TestK8sDR_AddOption(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- type args struct {
- opts []grpc.DialOption
- }
- tests := []struct {
- name string
- fields fields
- args args
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- cli.AddOption(tt.args.opts...)
- })
- }
-}
+func TestNewDiscoveryRegister(t *testing.T) {
+ setupTestEnvironment()
-func TestK8sDR_CloseConn(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- type args struct {
- conn *grpc.ClientConn
- }
tests := []struct {
- name string
- fields fields
- args args
+ envType string
+ expectedError bool
+ expectedResult bool
}{
- // TODO: Add test cases.
+ {"zookeeper", false, true},
+ {"k8s", false, true}, // 假设 k8s 配置也已正确设置
+ {"invalid", true, false},
}
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- cli.CloseConn(tt.args.conn)
- })
- }
-}
-func TestK8sDR_GetClientLocalConns(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- tests := []struct {
- name string
- fields fields
- want map[string][]*grpc.ClientConn
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
- }
- if got := cli.GetClientLocalConns(); !reflect.DeepEqual(got, tt.want) {
- t.Errorf("K8sDR.GetClientLocalConns() = %v, want %v", got, tt.want)
- }
- })
- }
-}
+ for _, test := range tests {
+ client, err := NewDiscoveryRegister(test.envType)
-func TestK8sDR_Close(t *testing.T) {
- type fields struct {
- options []grpc.DialOption
- rpcRegisterAddr string
- }
- tests := []struct {
- name string
- fields fields
- }{
- // TODO: Add test cases.
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- cli := &K8sDR{
- options: tt.fields.options,
- rpcRegisterAddr: tt.fields.rpcRegisterAddr,
+ if test.expectedError {
+ assert.Error(t, err)
+ } else {
+ assert.NoError(t, err)
+ if test.expectedResult {
+ assert.Implements(t, (*discoveryregistry.SvcDiscoveryRegistry)(nil), client)
+ } else {
+ assert.Nil(t, client)
}
- cli.Close()
- })
+ }
}
}
diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go
new file mode 100644
index 000000000..cd5fb0a36
--- /dev/null
+++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go
@@ -0,0 +1,174 @@
+// 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 kubernetes
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+
+ "google.golang.org/grpc"
+
+ "github.com/OpenIMSDK/tools/discoveryregistry"
+ "github.com/OpenIMSDK/tools/log"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/config"
+)
+
+// K8sDR represents the Kubernetes service discovery and registration client.
+type K8sDR struct {
+ options []grpc.DialOption
+ rpcRegisterAddr string
+}
+
+// NewK8sDiscoveryRegister creates a new instance of K8sDR for Kubernetes service discovery and registration.
+func NewK8sDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) {
+
+ return &K8sDR{}, nil
+}
+
+// Register registers a service with Kubernetes.
+func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.DialOption) error {
+ if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
+ cli.rpcRegisterAddr = serviceName
+ } else {
+ cli.rpcRegisterAddr = cli.getSelfHost(context.Background())
+ }
+
+ return nil
+}
+
+// UnRegister removes a service registration from Kubernetes.
+func (cli *K8sDR) UnRegister() error {
+
+ return nil
+}
+
+// CreateRpcRootNodes creates root nodes for RPC in Kubernetes.
+func (cli *K8sDR) CreateRpcRootNodes(serviceNames []string) error {
+
+ return nil
+}
+
+// RegisterConf2Registry registers a configuration to the registry.
+func (cli *K8sDR) RegisterConf2Registry(key string, conf []byte) error {
+
+ return nil
+}
+
+// GetConfFromRegistry retrieves a configuration from the registry.
+func (cli *K8sDR) GetConfFromRegistry(key string) ([]byte, error) {
+ return nil, nil
+}
+
+func (cli *K8sDR) getSelfHost(ctx context.Context) string {
+ port := 88
+ instance := "openimserver"
+ selfPodName := os.Getenv("MY_POD_NAME")
+ ns := os.Getenv("MY_POD_NAMESPACE")
+ statefuleIndex := 0
+ gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":")
+ if len(gatewayEnds) != 2 {
+ log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error"))
+ } else {
+ port, _ = strconv.Atoi(gatewayEnds[1])
+ }
+ podInfo := strings.Split(selfPodName, "-")
+ instance = podInfo[0]
+ count := len(podInfo)
+ statefuleIndex, _ = strconv.Atoi(podInfo[count-1])
+ host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, statefuleIndex, instance, ns, port)
+ return host
+}
+
+// GetConns returns a list of gRPC client connections for a given service.
+func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
+ if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
+ conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
+ return []*grpc.ClientConn{conn}, err
+ }
+ var ret []*grpc.ClientConn
+ gatewayHosts := cli.getMsgGatewayHost(ctx)
+ for _, host := range gatewayHosts {
+ conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...)
+ if err != nil {
+ return nil, err
+ }
+ ret = append(ret, conn)
+ }
+ return ret, nil
+}
+
+// like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88
+func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string {
+ port := 88
+ instance := "openimserver"
+ selfPodName := os.Getenv("MY_POD_NAME")
+ replicas := os.Getenv("MY_MSGGATEWAY_REPLICACOUNT")
+ ns := os.Getenv("MY_POD_NAMESPACE")
+ gatewayEnds := strings.Split(config.Config.RpcRegisterName.OpenImMessageGatewayName, ":")
+ if len(gatewayEnds) != 2 {
+ log.ZError(ctx, "msggateway RpcRegisterName is error:config.Config.RpcRegisterName.OpenImMessageGatewayName", errors.New("config error"))
+ } else {
+ port, _ = strconv.Atoi(gatewayEnds[1])
+ }
+ nReplicas, _ := strconv.Atoi(replicas)
+ podInfo := strings.Split(selfPodName, "-")
+ instance = podInfo[0]
+ var ret []string
+ for i := 0; i < nReplicas; i++ {
+ host := fmt.Sprintf("%s-openim-msggateway-%d.%s-openim-msggateway-headless.%s.svc.cluster.local:%d", instance, i, instance, ns, port)
+ ret = append(ret, host)
+ }
+ log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret)
+
+ return ret
+}
+
+// GetConn returns a single gRPC client connection for a given service.
+func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
+ return grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
+}
+
+// GetSelfConnTarget returns the connection target of the client itself.
+func (cli *K8sDR) GetSelfConnTarget() string {
+ return cli.rpcRegisterAddr
+}
+
+// AddOption adds gRPC dial options to the client.
+func (cli *K8sDR) AddOption(opts ...grpc.DialOption) {
+ cli.options = append(cli.options, opts...)
+}
+
+// CloseConn closes a given gRPC client connection.
+func (cli *K8sDR) CloseConn(conn *grpc.ClientConn) {
+ conn.Close()
+}
+
+// do not use this method for call rpc.
+func (cli *K8sDR) GetClientLocalConns() map[string][]*grpc.ClientConn {
+ fmt.Println("should not call this function!!!!!!!!!!!!!!!!!!!!!!!!!")
+
+ return nil
+}
+
+// Close closes the K8sDR client.
+func (cli *K8sDR) Close() {
+
+ // Close any open resources here (if applicable)
+ return
+}
diff --git a/pkg/common/discoveryregister/zookeeper/zookeeper.go b/pkg/common/discoveryregister/zookeeper/zookeeper.go
new file mode 100644
index 000000000..a4edffc43
--- /dev/null
+++ b/pkg/common/discoveryregister/zookeeper/zookeeper.go
@@ -0,0 +1,61 @@
+// 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 zookeeper
+
+import (
+ "os"
+ "strings"
+ "time"
+
+ "github.com/OpenIMSDK/tools/discoveryregistry"
+ openkeeper "github.com/OpenIMSDK/tools/discoveryregistry/zookeeper"
+ "github.com/OpenIMSDK/tools/log"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/config"
+)
+
+// NewZookeeperDiscoveryRegister creates a new instance of ZookeeperDR for Zookeeper service discovery and registration.
+func NewZookeeperDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) {
+ schema := getEnv("ZOOKEEPER_SCHEMA", config.Config.Zookeeper.Schema)
+ zkAddr := getZkAddrFromEnv(config.Config.Zookeeper.ZkAddr)
+ username := getEnv("ZOOKEEPER_USERNAME", config.Config.Zookeeper.Username)
+ password := getEnv("ZOOKEEPER_PASSWORD", config.Config.Zookeeper.Password)
+
+ return openkeeper.NewClient(
+ zkAddr,
+ schema,
+ openkeeper.WithFreq(time.Hour),
+ openkeeper.WithUserNameAndPassword(username, password),
+ openkeeper.WithRoundRobin(),
+ openkeeper.WithTimeout(10),
+ openkeeper.WithLogger(log.NewZkLogger()),
+ )
+}
+
+// getEnv returns the value of an environment variable if it exists, otherwise it returns the fallback value.
+func getEnv(key, fallback string) string {
+ if value, exists := os.LookupEnv(key); exists {
+ return value
+ }
+ return fallback
+}
+
+// getZkAddrFromEnv returns the value of an environment variable if it exists, otherwise it returns the fallback value.
+func getZkAddrFromEnv(fallback []string) []string {
+ if value, exists := os.LookupEnv("ZOOKEEPER_ADDRESS"); exists {
+ return strings.Split(value, ",")
+ }
+ return fallback
+}
diff --git a/pkg/common/ginprometheus/ginprometheus.go b/pkg/common/ginprometheus/ginprometheus.go
index a325595d6..f116fc23a 100644
--- a/pkg/common/ginprometheus/ginprometheus.go
+++ b/pkg/common/ginprometheus/ginprometheus.go
@@ -1,3 +1,17 @@
+// 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 ginprometheus
import (
diff --git a/pkg/common/kafka/producer.go b/pkg/common/kafka/producer.go
index 1dad33f9c..9a06809b7 100644
--- a/pkg/common/kafka/producer.go
+++ b/pkg/common/kafka/producer.go
@@ -21,19 +21,18 @@ import (
"strings"
"time"
+ "github.com/IBM/sarama"
"github.com/OpenIMSDK/protocol/constant"
- log "github.com/OpenIMSDK/tools/log"
+ "github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
+ "google.golang.org/protobuf/proto"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
-
- "github.com/IBM/sarama"
- "google.golang.org/protobuf/proto"
)
const (
- maxRetry = 10 // number of retries
+ maxRetry = 10 // Maximum number of retries for producer creation
)
var errEmptyMsg = errors.New("binary msg is empty")
@@ -45,62 +44,85 @@ type Producer struct {
producer sarama.SyncProducer
}
-// NewKafkaProducer Initialize kafka producer.
+// NewKafkaProducer initializes a new Kafka producer.
func NewKafkaProducer(addr []string, topic string) *Producer {
- p := Producer{}
- p.config = sarama.NewConfig() // Instantiate a sarama Config
- p.config.Producer.Return.Successes = true // Whether to enable the successes channel to be notified after the message is sent successfully
+ p := Producer{
+ addr: addr,
+ topic: topic,
+ config: sarama.NewConfig(),
+ }
+
+ // Set producer return flags
+ p.config.Producer.Return.Successes = true
p.config.Producer.Return.Errors = true
- p.config.Producer.Partitioner = sarama.NewHashPartitioner // Set the hash-key automatic hash partition. When sending a message, you must specify the key value of the message. If there is no key, the partition will be selected randomly
- var producerAck = sarama.WaitForAll // default: WaitForAll
- switch strings.ToLower(config.Config.Kafka.ProducerAck) {
- case "no_response":
- producerAck = sarama.NoResponse
- case "wait_for_local":
- producerAck = sarama.WaitForLocal
- case "wait_for_all":
- producerAck = sarama.WaitForAll
- }
- p.config.Producer.RequiredAcks = producerAck
+ // Set partitioner strategy
+ p.config.Producer.Partitioner = sarama.NewHashPartitioner
- var compress = sarama.CompressionNone // default: no compress
- _ = compress.UnmarshalText(bytes.ToLower([]byte(config.Config.Kafka.CompressType)))
- p.config.Producer.Compression = compress
+ // Configure producer acknowledgement level
+ configureProducerAck(&p, config.Config.Kafka.ProducerAck)
+
+ // Configure message compression
+ configureCompression(&p, config.Config.Kafka.CompressType)
+
+ // Get Kafka configuration from environment variables or fallback to config file
+ kafkaUsername := getEnvOrConfig("KAFKA_USERNAME", config.Config.Kafka.Username)
+ kafkaPassword := getEnvOrConfig("KAFKA_PASSWORD", config.Config.Kafka.Password)
+ kafkaAddr := getEnvOrConfig("KAFKA_ADDRESS", addr[0]) // Assuming addr[0] contains address from config
- if config.Config.Kafka.Username != "" && config.Config.Kafka.Password != "" {
+ // Configure SASL authentication if credentials are provided
+ if kafkaUsername != "" && kafkaPassword != "" {
p.config.Net.SASL.Enable = true
- p.config.Net.SASL.User = config.Config.Kafka.Username
- p.config.Net.SASL.Password = config.Config.Kafka.Password
+ p.config.Net.SASL.User = kafkaUsername
+ p.config.Net.SASL.Password = kafkaPassword
}
- p.addr = addr
- p.topic = topic
+
+ // Set the Kafka address
+ p.addr = []string{kafkaAddr}
+
+ // Set up TLS configuration (if required)
SetupTLSConfig(p.config)
- var producer sarama.SyncProducer
+
+ // Create the producer with retries
var err error
for i := 0; i <= maxRetry; i++ {
- producer, err = sarama.NewSyncProducer(p.addr, p.config) // Initialize the client
+ p.producer, err = sarama.NewSyncProducer(p.addr, p.config)
if err == nil {
- p.producer = producer
return &p
}
- //TODO If the password is wrong, exit directly
- //if packetErr, ok := err.(*sarama.PacketEncodingError); ok {
- //if _, ok := packetErr.Err.(sarama.AuthenticationError); ok {
- // fmt.Println("Kafka password is wrong.")
- //}
- //} else {
- // fmt.Printf("Failed to create Kafka producer: %v\n", err)
- //}
- time.Sleep(time.Duration(1) * time.Second)
+ time.Sleep(1 * time.Second) // Wait before retrying
}
+
+ // Panic if unable to create producer after retries
if err != nil {
- panic(err.Error())
+ panic("Failed to create Kafka producer: " + err.Error())
}
- p.producer = producer
+
return &p
}
+// configureProducerAck configures the producer's acknowledgement level.
+func configureProducerAck(p *Producer, ackConfig string) {
+ switch strings.ToLower(ackConfig) {
+ case "no_response":
+ p.config.Producer.RequiredAcks = sarama.NoResponse
+ case "wait_for_local":
+ p.config.Producer.RequiredAcks = sarama.WaitForLocal
+ case "wait_for_all":
+ p.config.Producer.RequiredAcks = sarama.WaitForAll
+ default:
+ p.config.Producer.RequiredAcks = sarama.WaitForAll
+ }
+}
+
+// configureCompression configures the message compression type for the producer.
+func configureCompression(p *Producer, compressType string) {
+ var compress sarama.CompressionCodec = sarama.CompressionNone
+ compress.UnmarshalText(bytes.ToLower([]byte(compressType)))
+ p.config.Producer.Compression = compress
+}
+
+// GetMQHeaderWithContext extracts message queue headers from the context.
func GetMQHeaderWithContext(ctx context.Context) ([]sarama.RecordHeader, error) {
operationID, opUserID, platform, connID, err := mcontext.GetCtxInfos(ctx)
if err != nil {
@@ -111,22 +133,23 @@ func GetMQHeaderWithContext(ctx context.Context) ([]sarama.RecordHeader, error)
{Key: []byte(constant.OpUserID), Value: []byte(opUserID)},
{Key: []byte(constant.OpUserPlatform), Value: []byte(platform)},
{Key: []byte(constant.ConnID), Value: []byte(connID)},
- }, err
+ }, nil
}
+// GetContextWithMQHeader creates a context from message queue headers.
func GetContextWithMQHeader(header []*sarama.RecordHeader) context.Context {
var values []string
for _, recordHeader := range header {
values = append(values, string(recordHeader.Value))
}
- return mcontext.WithMustInfoCtx(values) // TODO
+ return mcontext.WithMustInfoCtx(values) // Attach extracted values to context
}
+// SendMessage sends a message to the Kafka topic configured in the Producer.
func (p *Producer) SendMessage(ctx context.Context, key string, msg proto.Message) (int32, int64, error) {
log.ZDebug(ctx, "SendMessage", "msg", msg, "topic", p.topic, "key", key)
- kMsg := &sarama.ProducerMessage{}
- kMsg.Topic = p.topic
- kMsg.Key = sarama.StringEncoder(key)
+
+ // Marshal the protobuf message
bMsg, err := proto.Marshal(msg)
if err != nil {
return 0, 0, utils.Wrap(err, "kafka proto Marshal err")
@@ -134,20 +157,33 @@ func (p *Producer) SendMessage(ctx context.Context, key string, msg proto.Messag
if len(bMsg) == 0 {
return 0, 0, utils.Wrap(errEmptyMsg, "")
}
- kMsg.Value = sarama.ByteEncoder(bMsg)
+
+ // Prepare Kafka message
+ kMsg := &sarama.ProducerMessage{
+ Topic: p.topic,
+ Key: sarama.StringEncoder(key),
+ Value: sarama.ByteEncoder(bMsg),
+ }
+
+ // Validate message key and value
if kMsg.Key.Length() == 0 || kMsg.Value.Length() == 0 {
return 0, 0, utils.Wrap(errEmptyMsg, "")
}
- kMsg.Metadata = ctx
+
+ // Attach context metadata as headers
header, err := GetMQHeaderWithContext(ctx)
if err != nil {
return 0, 0, utils.Wrap(err, "")
}
kMsg.Headers = header
+
+ // Send the message
partition, offset, err := p.producer.SendMessage(kMsg)
- log.ZDebug(ctx, "ByteEncoder SendMessage end", "key ", kMsg.Key, "key length", kMsg.Value.Length())
if err != nil {
log.ZWarn(ctx, "p.producer.SendMessage error", err)
+ return 0, 0, utils.Wrap(err, "")
}
- return partition, offset, utils.Wrap(err, "")
+
+ log.ZDebug(ctx, "ByteEncoder SendMessage end", "key", kMsg.Key, "key length", kMsg.Value.Length())
+ return partition, offset, nil
}
diff --git a/pkg/common/kafka/util.go b/pkg/common/kafka/util.go
index 722205865..da0c5349b 100644
--- a/pkg/common/kafka/util.go
+++ b/pkg/common/kafka/util.go
@@ -15,6 +15,8 @@
package kafka
import (
+ "os"
+
"github.com/IBM/sarama"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
@@ -33,3 +35,12 @@ func SetupTLSConfig(cfg *sarama.Config) {
)
}
}
+
+// getEnvOrConfig returns the value of the environment variable if it exists,
+// otherwise, it returns the value from the configuration file.
+func getEnvOrConfig(envName string, configValue string) string {
+ if value, exists := os.LookupEnv(envName); exists {
+ return value
+ }
+ return configValue
+}
diff --git a/pkg/common/prommetrics/gin_api.go b/pkg/common/prommetrics/gin_api.go
index 7cd82dad2..c5ef612a2 100644
--- a/pkg/common/prommetrics/gin_api.go
+++ b/pkg/common/prommetrics/gin_api.go
@@ -1,10 +1,24 @@
+// 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 prommetrics
import ginProm "github.com/openimsdk/open-im-server/v3/pkg/common/ginprometheus"
/*
labels := prometheus.Labels{"label_one": "any", "label_two": "value"}
-ApiCustomCnt.MetricCollector.(*prometheus.CounterVec).With(labels).Inc()
+ApiCustomCnt.MetricCollector.(*prometheus.CounterVec).With(labels).Inc().
*/
var (
ApiCustomCnt = &ginProm.Metric{
diff --git a/pkg/common/prommetrics/grpc_auth.go b/pkg/common/prommetrics/grpc_auth.go
index e44c146be..30dd5f1b1 100644
--- a/pkg/common/prommetrics/grpc_auth.go
+++ b/pkg/common/prommetrics/grpc_auth.go
@@ -1,3 +1,17 @@
+// 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 prommetrics
import (
diff --git a/pkg/common/prommetrics/grpc_msg.go b/pkg/common/prommetrics/grpc_msg.go
index 88d4ef3ce..758879b90 100644
--- a/pkg/common/prommetrics/grpc_msg.go
+++ b/pkg/common/prommetrics/grpc_msg.go
@@ -1,3 +1,17 @@
+// 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 prommetrics
import (
diff --git a/pkg/common/prommetrics/grpc_msggateway.go b/pkg/common/prommetrics/grpc_msggateway.go
index bb62426e1..98d5a3267 100644
--- a/pkg/common/prommetrics/grpc_msggateway.go
+++ b/pkg/common/prommetrics/grpc_msggateway.go
@@ -1,3 +1,17 @@
+// 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 prommetrics
import (
diff --git a/pkg/common/prommetrics/grpc_push.go b/pkg/common/prommetrics/grpc_push.go
index aa5085c2c..0b6c3e76f 100644
--- a/pkg/common/prommetrics/grpc_push.go
+++ b/pkg/common/prommetrics/grpc_push.go
@@ -1,3 +1,17 @@
+// 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 prommetrics
import (
diff --git a/pkg/common/prommetrics/prommetrics.go b/pkg/common/prommetrics/prommetrics.go
index 26b02b16f..41719dd2d 100644
--- a/pkg/common/prommetrics/prommetrics.go
+++ b/pkg/common/prommetrics/prommetrics.go
@@ -1,3 +1,17 @@
+// 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 prommetrics
import (
diff --git a/pkg/common/prommetrics/prommetrics_test.go b/pkg/common/prommetrics/prommetrics_test.go
index babc5e410..1e48c63ba 100644
--- a/pkg/common/prommetrics/prommetrics_test.go
+++ b/pkg/common/prommetrics/prommetrics_test.go
@@ -1,3 +1,17 @@
+// 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 prommetrics
import (
diff --git a/pkg/common/prommetrics/transfer.go b/pkg/common/prommetrics/transfer.go
index 6b03870b5..197b6f7fc 100644
--- a/pkg/common/prommetrics/transfer.go
+++ b/pkg/common/prommetrics/transfer.go
@@ -1,3 +1,17 @@
+// 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 prommetrics
import (
diff --git a/pkg/common/startrpc/start_test.go b/pkg/common/startrpc/start_test.go
index 171cdb1c2..481986e15 100644
--- a/pkg/common/startrpc/start_test.go
+++ b/pkg/common/startrpc/start_test.go
@@ -1,3 +1,17 @@
+// 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 startrpc
import (
diff --git a/pkg/common/version/base.go b/pkg/common/version/base.go
index ac214269f..9a656e03a 100644
--- a/pkg/common/version/base.go
+++ b/pkg/common/version/base.go
@@ -1,3 +1,17 @@
+// 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 version
// Base version information.
@@ -15,7 +29,7 @@ package version
// When releasing a new Kubernetes version, this file is updated by
// build/mark_new_version.sh to reflect the new version, and then a
// git annotated tag (using format vX.Y where X == Major version and Y
-// == Minor version) is created to point to the commit that updates
+// == Minor version) is created to point to the commit that updates.
var (
// TODO: Deprecate gitMajor and gitMinor, use only gitVersion
// instead. First step in deprecation, keep the fields but make
diff --git a/pkg/common/version/types.go b/pkg/common/version/types.go
index ee4664149..da9c1ed90 100644
--- a/pkg/common/version/types.go
+++ b/pkg/common/version/types.go
@@ -1,3 +1,17 @@
+// 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 version
// Info contains versioning information.
diff --git a/pkg/common/version/version.go b/pkg/common/version/version.go
index b8ccfaf81..3b271b3f6 100644
--- a/pkg/common/version/version.go
+++ b/pkg/common/version/version.go
@@ -1,3 +1,17 @@
+// 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 version
import (
@@ -25,7 +39,7 @@ func Get() Info {
}
}
-// GetClientVersion returns the git version of the OpenIM client repository
+// GetClientVersion returns the git version of the OpenIM client repository.
func GetClientVersion() (*OpenIMClientVersion, error) {
clientVersion, err := getClientVersion()
if err != nil {
@@ -52,7 +66,7 @@ func getClientVersion() (string, error) {
return ref.Hash().String(), nil
}
-// GetSingleVersion returns single version of sealer
+// GetSingleVersion returns single version of sealer.
func GetSingleVersion() string {
return gitVersion
}
diff --git a/pkg/rpcclient/grouphash/grouphash.go b/pkg/rpcclient/grouphash/grouphash.go
index b5570dccd..dee47ad44 100644
--- a/pkg/rpcclient/grouphash/grouphash.go
+++ b/pkg/rpcclient/grouphash/grouphash.go
@@ -1,3 +1,17 @@
+// 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 grouphash
import (
diff --git a/scripts/check-all.sh b/scripts/check-all.sh
index 5acae3498..30a4e422b 100755
--- a/scripts/check-all.sh
+++ b/scripts/check-all.sh
@@ -33,8 +33,8 @@ openim::log::info "\n# Begin to check all openim service"
# OpenIM status
# Elegant printing function
print_services_and_ports() {
- local -n service_names=$1
- local -n service_ports=$2
+ declare -g service_names=("${!1}")
+ declare -g service_ports=("${!2}")
echo "+-------------------------+----------+"
echo "| Service Name | Port |"
diff --git a/scripts/githooks/pre-push.sh b/scripts/githooks/pre-push.sh
index 2985313b7..e341cf4f2 100644
--- a/scripts/githooks/pre-push.sh
+++ b/scripts/githooks/pre-push.sh
@@ -102,7 +102,7 @@ print_color "Deleted Files: ${deleted_files}" "${BACKGROUND_GREEN}"
if [[ ! $local_branch =~ $valid_branch_regex ]]
then
printError "There is something wrong with your branch name. Branch names in this project must adhere to this contract: $valid_branch_regex.
-Your commit will be rejected. You should rename your branch to a valid name(feat/name OR bug/name) and try again."
+Your commit will be rejected. You should rename your branch to a valid name(feat/name OR fix/name) and try again."
printError "For more on this, read on: https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694"
exit 1
fi
diff --git a/scripts/init-config.sh b/scripts/init-config.sh
index 0b9c0e615..c75fc5502 100755
--- a/scripts/init-config.sh
+++ b/scripts/init-config.sh
@@ -1,4 +1,17 @@
#!/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.
# This script automatically initializes various configuration files and can generate example files.
@@ -31,6 +44,20 @@ declare -A EXAMPLES=(
["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/templates/alertmanager.yml.template"
)
+# Templates for config Copy file
+declare -A COPY_TEMPLATES=(
+ ["${OPENIM_ROOT}/deployments/templates/email.tmpl"]="${OPENIM_ROOT}/config/email.tmpl"
+ ["${OPENIM_ROOT}/deployments/templates/instance-down-rules.yml"]="${OPENIM_ROOT}/config/instance-down-rules.yml"
+ ["${OPENIM_ROOT}/deployments/templates/notification.yaml"]="${OPENIM_ROOT}/config/notification.yaml"
+)
+
+# Templates for config Copy file
+declare -A COPY_EXAMPLES=(
+ ["${OPENIM_ROOT}/deployments/templates/email.tmpl"]="${OPENIM_ROOT}/config/templates/email.tmpl.template"
+ ["${OPENIM_ROOT}/deployments/templates/instance-down-rules.yml"]="${OPENIM_ROOT}/config/templates/instance-down-rules.yml.template"
+ ["${OPENIM_ROOT}/deployments/templates/notification.yaml"]="${OPENIM_ROOT}/config/templates/notification.yaml.template"
+)
+
# Command-line options
FORCE_OVERWRITE=false
SKIP_EXISTING=false
@@ -50,84 +77,101 @@ show_help() {
echo " --clean-examples Clean all example files"
}
-# Function to generate configuration files
+# Function to generate and copy configuration files
generate_config_files() {
+ # Handle TEMPLATES array
for template in "${!TEMPLATES[@]}"; do
local output_file="${TEMPLATES[$template]}"
- if [[ -f "${output_file}" ]]; then
- if [[ "${FORCE_OVERWRITE}" == true ]]; then
- openim::log::info "Force overwriting ${output_file}."
- elif [[ "${SKIP_EXISTING}" == true ]]; then
- openim::log::info "Skipping generation of ${output_file} as it already exists."
- continue
- else
- echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
- read -r -n 1 REPLY
- echo
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
- openim::log::info "Skipping generation of ${output_file}."
- continue
- fi
- fi
- else
- if [[ "${SKIP_EXISTING}" == true ]]; then
- openim::log::info "Generating ${output_file} as it does not exist."
- fi
- fi
+ process_file "$template" "$output_file" true
+ done
- openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..."
- if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
- openim::log::error "genconfig.sh script not found"
- exit 1
- fi
- "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
- openim::log::error "Error processing template file ${template}"
- exit 1
- }
- sleep 0.5
+ # Handle COPY_TEMPLATES array
+ for template in "${!COPY_TEMPLATES[@]}"; do
+ local output_file="${COPY_TEMPLATES[$template]}"
+ process_file "$template" "$output_file" false
done
}
# Function to generate example files
generate_example_files() {
+ env_cmd="env -i"
+ for var in "${!env_vars[@]}"; do
+ env_cmd+=" $var='${env_vars[$var]}'"
+ done
+
+ # Processing EXAMPLES array
for template in "${!EXAMPLES[@]}"; do
local example_file="${EXAMPLES[$template]}"
- if [[ -f "${example_file}" ]]; then
- if [[ "${FORCE_OVERWRITE}" == true ]]; then
- openim::log::info "Force overwriting example file: ${example_file}."
- elif [[ "${SKIP_EXISTING}" == true ]]; then
- openim::log::info "Skipping generation of example file: ${example_file} as it already exists."
- continue
- else
- echo -n "Example file ${example_file} already exists. Overwrite? (Y/N): "
- read -r -n 1 REPLY
- echo
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
- openim::log::info "Skipping generation of example file: ${example_file}."
- continue
- fi
- fi
+ process_file "$template" "$example_file" true
+ done
+
+ # Processing COPY_EXAMPLES array
+ for template in "${!COPY_EXAMPLES[@]}"; do
+ local example_file="${COPY_EXAMPLES[$template]}"
+ process_file "$template" "$example_file" false
+ done
+
+}
+
+# Function to process a single file, either by generating or copying
+process_file() {
+ local template=$1
+ local output_file=$2
+ local use_genconfig=$3
+
+ if [[ -f "${output_file}" ]]; then
+ if [[ "${FORCE_OVERWRITE}" == true ]]; then
+ openim::log::info "Force overwriting ${output_file}."
elif [[ "${SKIP_EXISTING}" == true ]]; then
- openim::log::info "Generating example file: ${example_file} as it does not exist."
+ openim::log::info "Skipping generation of ${output_file} as it already exists."
+ return
+ else
+ echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
+ read -r -n 1 REPLY
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ openim::log::info "Skipping generation of ${output_file}."
+ return
+ fi
+ fi
+ else
+ if [[ "${SKIP_EXISTING}" == true ]]; then
+ openim::log::info "Generating ${output_file} as it does not exist."
fi
+ fi
- openim::log::info "⌚ Working with template file: ${template} to generate example file: ${example_file}..."
+ if [[ "$use_genconfig" == true ]]; then
+ openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..."
if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
openim::log::error "genconfig.sh script not found"
exit 1
fi
- "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${example_file}" || {
- openim::log::error "Error processing template file ${template}"
+ if [[ -n "${env_cmd}" ]]; then
+ eval "$env_cmd ${OPENIM_ROOT}/scripts/genconfig.sh '${ENV_FILE}' '${template}' > '${output_file}'" || {
+ openim::log::error "Error processing template file ${template}"
+ exit 1
+ }
+ else
+ "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
+ openim::log::error "Error processing template file ${template}"
+ exit 1
+ }
+ fi
+ else
+ openim::log::info "📋 Copying ${template} to ${output_file}..."
+ cp "${template}" "${output_file}" || {
+ openim::log::error "Error copying template file ${template}"
exit 1
}
- sleep 0.5
- done
-}
+ fi
+ sleep 0.5
+}
-# Function to clean configuration files
clean_config_files() {
- for output_file in "${TEMPLATES[@]}"; do
+ local all_templates=("${TEMPLATES[@]}" "${COPY_TEMPLATES[@]}")
+
+ for output_file in "${all_templates[@]}"; do
if [[ -f "${output_file}" ]]; then
rm -f "${output_file}"
openim::log::info "Removed configuration file: ${output_file}"
@@ -137,7 +181,10 @@ clean_config_files() {
# Function to clean example files
clean_example_files() {
- for example_file in "${EXAMPLES[@]}"; do
+ # 合并 EXAMPLES 和 COPY_EXAMPLES 数组
+ local all_examples=("${EXAMPLES[@]}" "${COPY_EXAMPLES[@]}")
+
+ for example_file in "${all_examples[@]}"; do
if [[ -f "${example_file}" ]]; then
rm -f "${example_file}"
openim::log::info "Removed example file: ${example_file}"
diff --git a/test/e2e/api/token/token.go b/test/e2e/api/token/token.go
index 4c578e8f7..88af72058 100644
--- a/test/e2e/api/token/token.go
+++ b/test/e2e/api/token/token.go
@@ -1,3 +1,17 @@
+// 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 token
import (
@@ -9,7 +23,7 @@ import (
"net/http"
)
-// API endpoints and other constants
+// API endpoints and other constants.
const (
APIHost = "http://127.0.0.1:10002"
UserTokenURL = APIHost + "/auth/user_token"
@@ -18,27 +32,27 @@ const (
OperationID = "1646445464564"
)
-// UserTokenRequest represents a request to get a user token
+// UserTokenRequest represents a request to get a user token.
type UserTokenRequest struct {
Secret string `json:"secret"`
PlatformID int `json:"platformID"`
UserID string `json:"userID"`
}
-// UserTokenResponse represents a response containing a user token
+// UserTokenResponse represents a response containing a user token.
type UserTokenResponse struct {
Token string `json:"token"`
ErrCode int `json:"errCode"`
}
-// User represents user data for registration
+// User represents user data for registration.
type User struct {
UserID string `json:"userID"`
Nickname string `json:"nickname"`
FaceURL string `json:"faceURL"`
}
-// UserRegisterRequest represents a request to register a user
+// UserRegisterRequest represents a request to register a user.
type UserRegisterRequest struct {
Secret string `json:"secret"`
Users []User `json:"users"`
@@ -58,7 +72,7 @@ func main() {
}
}
-// GetUserToken requests a user token from the API
+// GetUserToken requests a user token from the API.
func GetUserToken(userID string) (string, error) {
reqBody := UserTokenRequest{
Secret: SecretKey,
@@ -88,7 +102,7 @@ func GetUserToken(userID string) (string, error) {
return tokenResp.Token, nil
}
-// RegisterUser registers a new user using the API
+// RegisterUser registers a new user using the API.
func RegisterUser(token, userID, nickname, faceURL string) error {
user := User{
UserID: userID,
diff --git a/test/e2e/api/user/curd.go b/test/e2e/api/user/curd.go
index c0380b235..1b56492b3 100644
--- a/test/e2e/api/user/curd.go
+++ b/test/e2e/api/user/curd.go
@@ -1,3 +1,17 @@
+// 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 user
import (
@@ -7,18 +21,18 @@ import (
"github.com/openimsdk/open-im-server/v3/test/e2e/framework/config"
)
-// UserInfoRequest represents a request to get or update user information
+// UserInfoRequest represents a request to get or update user information.
type UserInfoRequest struct {
UserIDs []string `json:"userIDs,omitempty"`
UserInfo *gettoken.User `json:"userInfo,omitempty"`
}
-// GetUsersOnlineStatusRequest represents a request to get users' online status
+// GetUsersOnlineStatusRequest represents a request to get users' online status.
type GetUsersOnlineStatusRequest struct {
UserIDs []string `json:"userIDs"`
}
-// GetUsersInfo retrieves detailed information for a list of user IDs
+// GetUsersInfo retrieves detailed information for a list of user IDs.
func GetUsersInfo(token string, userIDs []string) error {
url := fmt.Sprintf("http://%s:%s/user/get_users_info", config.LoadConfig().APIHost, config.LoadConfig().APIPort)
@@ -29,7 +43,7 @@ func GetUsersInfo(token string, userIDs []string) error {
return sendPostRequestWithToken(url, token, requestBody)
}
-// UpdateUserInfo updates the information for a user
+// UpdateUserInfo updates the information for a user.
func UpdateUserInfo(token, userID, nickname, faceURL string) error {
url := fmt.Sprintf("http://%s:%s/user/update_user_info", config.LoadConfig().APIHost, config.LoadConfig().APIPort)
@@ -44,7 +58,7 @@ func UpdateUserInfo(token, userID, nickname, faceURL string) error {
return sendPostRequestWithToken(url, token, requestBody)
}
-// GetUsersOnlineStatus retrieves the online status for a list of user IDs
+// GetUsersOnlineStatus retrieves the online status for a list of user IDs.
func GetUsersOnlineStatus(token string, userIDs []string) error {
url := fmt.Sprintf("http://%s:%s/user/get_users_online_status", config.LoadConfig().APIHost, config.LoadConfig().APIPort)
diff --git a/test/e2e/api/user/user.go b/test/e2e/api/user/user.go
index 9facf76ac..fd8144acd 100644
--- a/test/e2e/api/user/user.go
+++ b/test/e2e/api/user/user.go
@@ -1,3 +1,17 @@
+// 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 user
import (
@@ -11,29 +25,29 @@ import (
"github.com/openimsdk/open-im-server/v3/test/e2e/framework/config"
)
-// ForceLogoutRequest represents a request to force a user logout
+// ForceLogoutRequest represents a request to force a user logout.
type ForceLogoutRequest struct {
PlatformID int `json:"platformID"`
UserID string `json:"userID"`
}
-// CheckUserAccountRequest represents a request to check a user account
+// CheckUserAccountRequest represents a request to check a user account.
type CheckUserAccountRequest struct {
CheckUserIDs []string `json:"checkUserIDs"`
}
-// GetUsersRequest represents a request to get a list of users
+// GetUsersRequest represents a request to get a list of users.
type GetUsersRequest struct {
Pagination Pagination `json:"pagination"`
}
-// Pagination specifies the page number and number of items per page
+// Pagination specifies the page number and number of items per page.
type Pagination struct {
PageNumber int `json:"pageNumber"`
ShowNumber int `json:"showNumber"`
}
-// ForceLogout forces a user to log out
+// ForceLogout forces a user to log out.
func ForceLogout(token, userID string, platformID int) error {
url := fmt.Sprintf("http://%s:%s/auth/force_logout", config.LoadConfig().APIHost, config.LoadConfig().APIPort)
@@ -45,7 +59,7 @@ func ForceLogout(token, userID string, platformID int) error {
return sendPostRequestWithToken(url, token, requestBody)
}
-// CheckUserAccount checks if the user accounts exist
+// CheckUserAccount checks if the user accounts exist.
func CheckUserAccount(token string, userIDs []string) error {
url := fmt.Sprintf("http://%s:%s/user/account_check", config.LoadConfig().APIHost, config.LoadConfig().APIPort)
@@ -56,7 +70,7 @@ func CheckUserAccount(token string, userIDs []string) error {
return sendPostRequestWithToken(url, token, requestBody)
}
-// GetUsers retrieves a list of users with pagination
+// GetUsers retrieves a list of users with pagination.
func GetUsers(token string, pageNumber, showNumber int) error {
url := fmt.Sprintf("http://%s:%s/user/account_check", config.LoadConfig().APIHost, config.LoadConfig().APIPort)
@@ -70,7 +84,7 @@ func GetUsers(token string, pageNumber, showNumber int) error {
return sendPostRequestWithToken(url, token, requestBody)
}
-// sendPostRequestWithToken sends a POST request with a token in the header
+// sendPostRequestWithToken sends a POST request with a token in the header.
func sendPostRequestWithToken(url, token string, body any) error {
reqBytes, err := json.Marshal(body)
if err != nil {
diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go
index d1d6c5509..a3d3b1bcf 100644
--- a/test/e2e/e2e.go
+++ b/test/e2e/e2e.go
@@ -1,3 +1,17 @@
+// 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 e2e
import (
diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go
index 8fe810789..a6496679c 100644
--- a/test/e2e/e2e_test.go
+++ b/test/e2e/e2e_test.go
@@ -1,3 +1,17 @@
+// 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 e2e
import (
diff --git a/test/e2e/framework/config/config.go b/test/e2e/framework/config/config.go
index ed3c6a258..14074fec1 100644
--- a/test/e2e/framework/config/config.go
+++ b/test/e2e/framework/config/config.go
@@ -1,3 +1,17 @@
+// 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 config
import (
diff --git a/test/e2e/framework/config/config_test.go b/test/e2e/framework/config/config_test.go
index c411df31e..b7259bf37 100644
--- a/test/e2e/framework/config/config_test.go
+++ b/test/e2e/framework/config/config_test.go
@@ -1,3 +1,17 @@
+// 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 config
import (
diff --git a/test/e2e/framework/ginkgowrapper/ginkgowrapper.go b/test/e2e/framework/ginkgowrapper/ginkgowrapper.go
index 16779440b..814d393bc 100644
--- a/test/e2e/framework/ginkgowrapper/ginkgowrapper.go
+++ b/test/e2e/framework/ginkgowrapper/ginkgowrapper.go
@@ -1 +1,15 @@
+// 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 ginkgowrapper
diff --git a/test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go b/test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go
index 16779440b..814d393bc 100644
--- a/test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go
+++ b/test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go
@@ -1 +1,15 @@
+// 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 ginkgowrapper
diff --git a/test/e2e/framework/helpers/chat/chat.go b/test/e2e/framework/helpers/chat/chat.go
index 4fca28f2a..a4ead528b 100644
--- a/test/e2e/framework/helpers/chat/chat.go
+++ b/test/e2e/framework/helpers/chat/chat.go
@@ -1,3 +1,17 @@
+// 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 main
import (
@@ -10,7 +24,7 @@ import (
)
var (
- // The default template version
+ // The default template version.
defaultTemplateVersion = "v1.3.0"
)
@@ -84,7 +98,7 @@ func main() {
select {}
}
-// getLatestVersion fetches the latest version number from a given URL
+// getLatestVersion fetches the latest version number from a given URL.
func getLatestVersion(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
@@ -102,7 +116,7 @@ func getLatestVersion(url string) (string, error) {
return latestVersion, nil
}
-// downloadAndExtract downloads a file from a URL and extracts it to a destination directory
+// downloadAndExtract downloads a file from a URL and extracts it to a destination directory.
func downloadAndExtract(url, destDir string) error {
resp, err := http.Get(url)
if err != nil {
@@ -141,7 +155,7 @@ func downloadAndExtract(url, destDir string) error {
return cmd.Run()
}
-// startProcess starts a process and prints any errors encountered
+// startProcess starts a process and prints any errors encountered.
func startProcess(cmdPath string) {
cmd := exec.Command(cmdPath)
cmd.Stdout = os.Stdout
diff --git a/tools/component/component.go b/tools/component/component.go
index 140313c30..7150c91af 100644
--- a/tools/component/component.go
+++ b/tools/component/component.go
@@ -16,7 +16,6 @@ package main
import (
"context"
- "database/sql"
"flag"
"fmt"
"net"
@@ -31,15 +30,11 @@ import (
"github.com/IBM/sarama"
"github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/utils"
"github.com/go-zookeeper/zk"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
- "gorm.io/driver/mysql"
- "gorm.io/gorm"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
- "github.com/openimsdk/open-im-server/v3/pkg/common/kafka"
"github.com/minio/minio-go/v7/pkg/credentials"
)
@@ -53,6 +48,12 @@ const (
configErrCode = 6001
)
+const (
+ colorRed = 31
+ colorGreen = 32
+ colorYellow = 33
+)
+
var (
cfgPath = flag.String("c", defaultCfgPath, "Path to the configuration file")
@@ -132,127 +133,131 @@ func exactIP(urll string) string {
return host
}
-func checkMysql() error {
- if config.Config.Mysql == nil {
- return nil
+// Helper function to get environment variable or default value
+func getEnv(key, fallback string) string {
+ if value, exists := os.LookupEnv(key); exists {
+ return value
}
- 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)
+ return fallback
+}
+
+// checkMongo checks the MongoDB connection
+func checkMongo() error {
+ // Use environment variables or fallback to config
+ uri := getEnv("MONGO_URI", buildMongoURI())
+
+ client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
if err != nil {
return errs.Wrap(err)
- } else {
- sqlDB, err = db.DB()
- err = sqlDB.Ping()
- if err != nil {
- return errs.Wrap(err)
- }
+ }
+ defer client.Disconnect(context.TODO())
+
+ if err = client.Ping(context.TODO(), nil); err != nil {
+ return errs.Wrap(err)
}
return nil
}
-func checkMongo() error {
- var client *mongo.Client
- uri := "mongodb://sample.host:27017/?maxPoolSize=20&w=majority"
- defer func() {
- if client != nil {
- client.Disconnect(context.TODO())
- }
- }()
- if config.Config.Mongo.Uri != "" {
- uri = config.Config.Mongo.Uri
- } else {
- mongodbHosts := ""
- for i, v := range config.Config.Mongo.Address {
- if i == len(config.Config.Mongo.Address)-1 {
- mongodbHosts += v
- } else {
- mongodbHosts += v + ","
- }
- }
- if config.Config.Mongo.Password != "" && config.Config.Mongo.Username != "" {
- uri = fmt.Sprintf("mongodb://%s:%s@%s/%s?maxPoolSize=%d&authSource=admin",
- config.Config.Mongo.Username, config.Config.Mongo.Password, mongodbHosts,
- config.Config.Mongo.Database, config.Config.Mongo.MaxPoolSize)
- } else {
- uri = fmt.Sprintf("mongodb://%s/%s/?maxPoolSize=%d&authSource=admin",
- mongodbHosts, config.Config.Mongo.Database,
- config.Config.Mongo.MaxPoolSize)
- }
+// buildMongoURI constructs the MongoDB URI using configuration settings
+func buildMongoURI() string {
+ // Fallback to config if environment variables are not set
+ username := config.Config.Mongo.Username
+ password := config.Config.Mongo.Password
+ database := config.Config.Mongo.Database
+ maxPoolSize := config.Config.Mongo.MaxPoolSize
+
+ mongodbHosts := strings.Join(config.Config.Mongo.Address, ",")
+
+ if username != "" && password != "" {
+ return fmt.Sprintf("mongodb://%s:%s@%s/%s?maxPoolSize=%d&authSource=admin",
+ username, password, mongodbHosts, database, maxPoolSize)
}
- client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
+ return fmt.Sprintf("mongodb://%s/%s?maxPoolSize=%d&authSource=admin",
+ mongodbHosts, database, maxPoolSize)
+}
+
+// checkMinio checks the MinIO connection
+func checkMinio() error {
+ // Check if MinIO is enabled
+ if config.Config.Object.Enable != "minio" {
+ return nil
+ }
+
+ // Prioritize environment variables
+ endpoint := getEnv("MINIO_ENDPOINT", config.Config.Object.Minio.Endpoint)
+ accessKeyID := getEnv("MINIO_ACCESS_KEY_ID", config.Config.Object.Minio.AccessKeyID)
+ secretAccessKey := getEnv("MINIO_SECRET_ACCESS_KEY", config.Config.Object.Minio.SecretAccessKey)
+ useSSL := getEnv("MINIO_USE_SSL", "false") // Assuming SSL is not used by default
+
+ if endpoint == "" || accessKeyID == "" || secretAccessKey == "" {
+ return ErrConfig.Wrap("MinIO configuration missing")
+ }
+
+ // Parse endpoint URL to determine if SSL is enabled
+ u, err := url.Parse(endpoint)
if err != nil {
return errs.Wrap(err)
- } else {
- err = client.Ping(context.TODO(), nil)
- if err != nil {
- return errs.Wrap(err)
- }
}
+ secure := u.Scheme == "https" || useSSL == "true"
- return nil
-}
+ // Initialize MinIO client
+ minioClient, err := minio.New(u.Host, &minio.Options{
+ Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
+ Secure: secure,
+ })
+ if err != nil {
+ return errs.Wrap(err)
+ }
-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 errs.Wrap(err)
- }
+ // Perform health check
+ cancel, err := minioClient.HealthCheck(time.Duration(minioHealthCheckDuration) * time.Second)
+ if err != nil {
+ return errs.Wrap(err)
+ }
+ defer cancel()
- cancel, err := minioClient.HealthCheck(time.Duration(minioHealthCheckDuration) * time.Second)
- defer func() {
- if cancel != nil {
- cancel()
- }
- }()
- if err != nil {
- return errs.Wrap(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.SignEndpoint) == "127.0.0.1" {
- return ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1")
- }
+ if minioClient.IsOffline() {
+ return ErrComponentStart.Wrap("Minio server is offline")
+ }
+
+ // Check for localhost in API URL and Minio SignEndpoint
+ if exactIP(config.Config.Object.ApiURL) == "127.0.0.1" || exactIP(config.Config.Object.Minio.SignEndpoint) == "127.0.0.1" {
+ return ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1")
}
return nil
}
+// checkRedis checks the Redis connection
func checkRedis() error {
+ // Prioritize environment variables
+ address := getEnv("REDIS_ADDRESS", strings.Join(config.Config.Redis.Address, ","))
+ username := getEnv("REDIS_USERNAME", config.Config.Redis.Username)
+ password := getEnv("REDIS_PASSWORD", config.Config.Redis.Password)
+
+ // Split address to handle multiple addresses for cluster setup
+ redisAddresses := strings.Split(address, ",")
+
var redisClient redis.UniversalClient
- defer func() {
- if redisClient != nil {
- redisClient.Close()
- }
- }()
- if len(config.Config.Redis.Address) > 1 {
+ if len(redisAddresses) > 1 {
+ // Use cluster client for multiple addresses
redisClient = redis.NewClusterClient(&redis.ClusterOptions{
- Addrs: config.Config.Redis.Address,
- Username: config.Config.Redis.Username,
- Password: config.Config.Redis.Password,
+ Addrs: redisAddresses,
+ Username: username,
+ Password: password,
})
} else {
+ // Use regular client for single address
redisClient = redis.NewClient(&redis.Options{
- Addr: config.Config.Redis.Address[0],
- Username: config.Config.Redis.Username,
- Password: config.Config.Redis.Password,
+ Addr: redisAddresses[0],
+ Username: username,
+ Password: password,
})
}
+ defer redisClient.Close()
+
+ // Ping Redis to check connectivity
_, err := redisClient.Ping(context.Background()).Result()
if err != nil {
return errs.Wrap(err)
@@ -261,75 +266,110 @@ func checkRedis() error {
return nil
}
+// checkZookeeper checks the Zookeeper connection
func checkZookeeper() error {
- var c *zk.Conn
- defer func() {
- if c != nil {
- c.Close()
- }
- }()
- c, _, err := zk.Connect(config.Config.Zookeeper.ZkAddr, time.Second)
+ // Prioritize environment variables
+ schema := getEnv("ZOOKEEPER_SCHEMA", "digest")
+ address := getEnv("ZOOKEEPER_ADDRESS", strings.Join(config.Config.Zookeeper.ZkAddr, ","))
+ username := getEnv("ZOOKEEPER_USERNAME", config.Config.Zookeeper.Username)
+ password := getEnv("ZOOKEEPER_PASSWORD", config.Config.Zookeeper.Password)
+
+ // Split addresses to handle multiple Zookeeper nodes
+ zookeeperAddresses := strings.Split(address, ",")
+
+ // Connect to Zookeeper
+ c, _, err := zk.Connect(zookeeperAddresses, time.Second) // Adjust the timeout as necessary
if err != nil {
return errs.Wrap(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 errs.Wrap(err)
- }
- }
- _, _, err = c.Get("/")
- if err != nil {
+ }
+ defer c.Close()
+
+ // Set authentication if username and password are provided
+ if username != "" && password != "" {
+ if err := c.AddAuth(schema, []byte(username+":"+password)); err != nil {
return errs.Wrap(err)
}
}
+ // Check if Zookeeper is reachable
+ _, _, err = c.Get("/")
+ if err != nil {
+ return errs.Wrap(err)
+ }
+
return nil
}
+// checkKafka checks the Kafka connection
func checkKafka() error {
- var kafkaClient sarama.Client
- defer func() {
- if kafkaClient != nil {
- kafkaClient.Close()
- }
- }()
+ // Prioritize environment variables
+ username := getEnv("KAFKA_USERNAME", config.Config.Kafka.Username)
+ password := getEnv("KAFKA_PASSWORD", config.Config.Kafka.Password)
+ address := getEnv("KAFKA_ADDRESS", strings.Join(config.Config.Kafka.Addr, ","))
+
+ // Split addresses to handle multiple Kafka brokers
+ kafkaAddresses := strings.Split(address, ",")
+
+ // Configure Kafka client
cfg := sarama.NewConfig()
- if config.Config.Kafka.Username != "" && config.Config.Kafka.Password != "" {
+ if username != "" && password != "" {
cfg.Net.SASL.Enable = true
- cfg.Net.SASL.User = config.Config.Kafka.Username
- cfg.Net.SASL.Password = config.Config.Kafka.Password
+ cfg.Net.SASL.User = username
+ cfg.Net.SASL.Password = password
}
- kafka.SetupTLSConfig(cfg)
- kafkaClient, err := sarama.NewClient(config.Config.Kafka.Addr, cfg)
+ // Additional Kafka setup (e.g., TLS configuration) can be added here
+ // kafka.SetupTLSConfig(cfg)
+
+ // Create Kafka client
+ kafkaClient, err := sarama.NewClient(kafkaAddresses, cfg)
if err != nil {
return errs.Wrap(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))
+ }
+ defer kafkaClient.Close()
+
+ // Verify if necessary topics exist
+ topics, err := kafkaClient.Topics()
+ if err != nil {
+ return errs.Wrap(err)
+ }
+
+ requiredTopics := []string{
+ config.Config.Kafka.MsgToMongo.Topic,
+ config.Config.Kafka.MsgToPush.Topic,
+ config.Config.Kafka.LatestMsgToRedis.Topic,
+ }
+
+ for _, requiredTopic := range requiredTopics {
+ if !isTopicPresent(requiredTopic, topics) {
+ return ErrComponentStart.Wrap(fmt.Sprintf("Kafka doesn't contain topic: %v", requiredTopic))
}
}
return nil
}
+// isTopicPresent checks if a topic is present in the list of topics
+func isTopicPresent(topic string, topics []string) bool {
+ for _, t := range topics {
+ if t == topic {
+ return true
+ }
+ }
+ return false
+}
+
+func colorPrint(colorCode int, format string, a ...interface{}) {
+ fmt.Printf("\x1b[%dm%s\x1b[0m\n", colorCode, fmt.Sprintf(format, a...))
+}
+
func errorPrint(s string) {
- fmt.Printf("\x1b[%dm%v\x1b[0m\n", 31, s)
+ colorPrint(colorRed, "%v", s)
}
func successPrint(s string) {
- fmt.Printf("\x1b[%dm%v\x1b[0m\n", 32, s)
+ colorPrint(colorGreen, "%v", s)
}
func warningPrint(s string) {
- fmt.Printf("\x1b[%dmWarning: But %v\x1b[0m\n", 33, s)
+ colorPrint(colorYellow, "Warning: But %v", s)
}
diff --git a/tools/data-conversion/chat/cmd/conversion-chat/chat.go b/tools/data-conversion/chat/cmd/conversion-chat/chat.go
index 77c62ee1f..0fc49c782 100644
--- a/tools/data-conversion/chat/cmd/conversion-chat/chat.go
+++ b/tools/data-conversion/chat/cmd/conversion-chat/chat.go
@@ -1,3 +1,17 @@
+// 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 main
import (
diff --git a/tools/data-conversion/chat/conversion/conversion.go b/tools/data-conversion/chat/conversion/conversion.go
index 6032a4569..084fff59c 100644
--- a/tools/data-conversion/chat/conversion/conversion.go
+++ b/tools/data-conversion/chat/conversion/conversion.go
@@ -1,3 +1,17 @@
+// 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 conversion
import (
diff --git a/tools/data-conversion/chat/v2/admin.go b/tools/data-conversion/chat/v2/admin.go
index 7bc1b6c1b..fec11ff5b 100644
--- a/tools/data-conversion/chat/v2/admin.go
+++ b/tools/data-conversion/chat/v2/admin.go
@@ -1,3 +1,17 @@
+// 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 v2
import (
diff --git a/tools/data-conversion/chat/v2/chat.go b/tools/data-conversion/chat/v2/chat.go
index 6690e110b..15cc4797f 100644
--- a/tools/data-conversion/chat/v2/chat.go
+++ b/tools/data-conversion/chat/v2/chat.go
@@ -1,3 +1,17 @@
+// 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 v2
import (
diff --git a/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go b/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go
index 338fbf111..f2b9623a6 100644
--- a/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go
+++ b/tools/data-conversion/openim/cmd/conversion-msg/conversion-msg.go
@@ -1,3 +1,17 @@
+// 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 main
import (
diff --git a/tools/data-conversion/openim/mysql/cmd.go b/tools/data-conversion/openim/mysql/cmd.go
index 924b0a206..f5a23facb 100644
--- a/tools/data-conversion/openim/mysql/cmd.go
+++ b/tools/data-conversion/openim/mysql/cmd.go
@@ -1,3 +1,17 @@
+// 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 mysql
import (
diff --git a/tools/data-conversion/openim/mysql/conversion/conversion.go b/tools/data-conversion/openim/mysql/conversion/conversion.go
index 54cf90edf..f371654df 100644
--- a/tools/data-conversion/openim/mysql/conversion/conversion.go
+++ b/tools/data-conversion/openim/mysql/conversion/conversion.go
@@ -1,3 +1,17 @@
+// 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 conversion
import (
diff --git a/tools/data-conversion/openim/mysql/v2/model_struct.go b/tools/data-conversion/openim/mysql/v2/model_struct.go
index 9da33f2a5..f05b84977 100644
--- a/tools/data-conversion/openim/mysql/v2/model_struct.go
+++ b/tools/data-conversion/openim/mysql/v2/model_struct.go
@@ -1,3 +1,17 @@
+// 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 db
import "time"
diff --git a/tools/data-conversion/openim/mysql/v3/log.go b/tools/data-conversion/openim/mysql/v3/log.go
index 5904a790e..22198ca7c 100644
--- a/tools/data-conversion/openim/mysql/v3/log.go
+++ b/tools/data-conversion/openim/mysql/v3/log.go
@@ -1,3 +1,17 @@
+// 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 relation
import (
diff --git a/tools/data-conversion/openim/proto/msg/msg.proto b/tools/data-conversion/openim/proto/msg/msg.proto
index d2fe5337e..3149a7337 100644
--- a/tools/data-conversion/openim/proto/msg/msg.proto
+++ b/tools/data-conversion/openim/proto/msg/msg.proto
@@ -1,3 +1,17 @@
+// 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.
+
syntax = "proto3";
import "Open-IM-Server/pkg/proto/sdk_ws/ws.proto";
import "Open-IM-Server/pkg/proto/sdk_ws/wrappers.proto";
diff --git a/tools/data-conversion/openim/proto/sdk_ws/ws.proto b/tools/data-conversion/openim/proto/sdk_ws/ws.proto
index c8ef680c9..95b956b0e 100644
--- a/tools/data-conversion/openim/proto/sdk_ws/ws.proto
+++ b/tools/data-conversion/openim/proto/sdk_ws/ws.proto
@@ -1,3 +1,17 @@
+// 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.
+
syntax = "proto3";
import "Open-IM-Server/pkg/proto/sdk_ws/wrappers.proto";
option go_package = "Open_IM/pkg/proto/sdk_ws;server_api_params";
diff --git a/tools/data-conversion/utils/find_insert.go b/tools/data-conversion/utils/find_insert.go
index 4789cd554..150820fce 100644
--- a/tools/data-conversion/utils/find_insert.go
+++ b/tools/data-conversion/utils/find_insert.go
@@ -1,3 +1,17 @@
+// 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 utils
import (
diff --git a/tools/data-conversion/utils/time.go b/tools/data-conversion/utils/time.go
index e2dac4bb8..9077a3d88 100644
--- a/tools/data-conversion/utils/time.go
+++ b/tools/data-conversion/utils/time.go
@@ -1,3 +1,17 @@
+// 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 utils
import "time"
diff --git a/tools/infra/infra.go b/tools/infra/infra.go
index f8d8c7522..c14b92fa3 100644
--- a/tools/infra/infra.go
+++ b/tools/infra/infra.go
@@ -1,3 +1,17 @@
+// 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 main
import (
diff --git a/tools/up35/pkg/convert.go b/tools/up35/pkg/convert.go
index 91fdb474e..24d3a2781 100644
--- a/tools/up35/pkg/convert.go
+++ b/tools/up35/pkg/convert.go
@@ -1,11 +1,26 @@
+// 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 pkg
import (
+ "time"
+
mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
mongoModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
mysqlModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mysql"
- "time"
)
type convert struct{}
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go
index e3bab7af9..fd0f2818b 100644
--- a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go
@@ -1,14 +1,30 @@
+// 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 mgo
import (
"context"
+ "time"
+
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
- "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
- "time"
+
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
)
func NewMeeting(db *mongo.Database) (table.MeetingInterface, error) {
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go
index 5286ffa95..9926748bf 100644
--- a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go
@@ -1,15 +1,31 @@
+// 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 mgo
import (
"context"
+ "time"
+
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"github.com/OpenIMSDK/tools/utils"
- "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
- "time"
+
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
)
func NewMeetingInvitation(db *mongo.Database) (table.MeetingInvitationInterface, error) {
@@ -55,7 +71,12 @@ func (x *meetingInvitation) CreateMeetingInvitationInfo(ctx context.Context, roo
func (x *meetingInvitation) GetUserInvitedMeetingIDs(ctx context.Context, userID string) (meetingIDs []string, err error) {
fiveDaysAgo := time.Now().AddDate(0, 0, -5)
- return mgoutil.Find[string](ctx, x.coll, bson.M{"user_id": userID, "create_time": bson.M{"$gte": fiveDaysAgo}}, options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1}))
+ return mgoutil.Find[string](
+ ctx,
+ x.coll,
+ bson.M{"user_id": userID, "create_time": bson.M{"$gte": fiveDaysAgo}},
+ options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1}),
+ )
}
func (x *meetingInvitation) Delete(ctx context.Context, roomIDs []string) error {
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go
index 90fc9cdca..4e9dc5e0f 100644
--- a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go
@@ -1,11 +1,27 @@
+// 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 mgo
import (
"context"
+
"github.com/OpenIMSDK/tools/mgoutil"
- "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
+
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
)
func NewMeetingRecord(db *mongo.Database) (table.MeetingRecordInterface, error) {
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go
index 0c1879007..47fd3fb02 100644
--- a/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go
@@ -1,14 +1,30 @@
+// 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 mgo
import (
"context"
+ "time"
+
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
- "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
- "time"
+
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
)
func NewSignal(db *mongo.Database) (table.SignalInterface, error) {
diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go
index 274f2f11f..1f76381e9 100644
--- a/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go
+++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go
@@ -1,15 +1,31 @@
+// 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 mgo
import (
"context"
+ "time"
+
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"github.com/OpenIMSDK/tools/utils"
- "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
- "time"
+
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
)
func NewSignalInvitation(db *mongo.Database) (table.SignalInvitationInterface, error) {
diff --git a/tools/up35/pkg/internal/rtc/mongo/table/meeting.go b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go
index 3b341cfb1..6ff387bbb 100644
--- a/tools/up35/pkg/internal/rtc/mongo/table/meeting.go
+++ b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go
@@ -1,9 +1,24 @@
+// 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 table
import (
"context"
- "github.com/OpenIMSDK/tools/pagination"
"time"
+
+ "github.com/OpenIMSDK/tools/pagination"
)
type MeetingInfo struct {
diff --git a/tools/up35/pkg/internal/rtc/mongo/table/signal.go b/tools/up35/pkg/internal/rtc/mongo/table/signal.go
index 0cec050ff..8d8aa96ed 100644
--- a/tools/up35/pkg/internal/rtc/mongo/table/signal.go
+++ b/tools/up35/pkg/internal/rtc/mongo/table/signal.go
@@ -1,12 +1,27 @@
+// 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 table
import (
"context"
+ "time"
+
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/pagination"
"github.com/redis/go-redis/v9"
"go.mongodb.org/mongo-driver/mongo"
- "time"
)
type SignalModel struct {
diff --git a/tools/up35/pkg/internal/rtc/mysql/meeting.go b/tools/up35/pkg/internal/rtc/mysql/meeting.go
index 2c5bbed32..71515c3b7 100644
--- a/tools/up35/pkg/internal/rtc/mysql/meeting.go
+++ b/tools/up35/pkg/internal/rtc/mysql/meeting.go
@@ -1,3 +1,17 @@
+// 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 relation
import (
diff --git a/tools/up35/pkg/internal/rtc/mysql/signal.go b/tools/up35/pkg/internal/rtc/mysql/signal.go
index 3a4d607d4..c546360a4 100644
--- a/tools/up35/pkg/internal/rtc/mysql/signal.go
+++ b/tools/up35/pkg/internal/rtc/mysql/signal.go
@@ -1,3 +1,17 @@
+// 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 relation
import (
@@ -16,7 +30,7 @@ type SignalModel struct {
SessionType int32 `gorm:"column:sesstion_type"`
InitiateTime time.Time `gorm:"column:initiate_time"`
EndTime time.Time `gorm:"column:end_time"`
- FileURL string `gorm:"column:file_url" json:"-"`
+ FileURL string `gorm:"column:file_url" json:"-"`
Title string `gorm:"column:title;size:128"`
Desc string `gorm:"column:desc;size:1024"`
diff --git a/tools/up35/pkg/pkg.go b/tools/up35/pkg/pkg.go
index d834b8492..6d16817ec 100644
--- a/tools/up35/pkg/pkg.go
+++ b/tools/up35/pkg/pkg.go
@@ -1,15 +1,30 @@
+// 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 pkg
import (
"context"
"errors"
"fmt"
- "gopkg.in/yaml.v3"
"log"
"os"
"reflect"
"strconv"
+ "gopkg.in/yaml.v3"
+
"github.com/go-sql-driver/mysql"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
diff --git a/tools/up35/up35.go b/tools/up35/up35.go
index 0ce56ee13..63b6ec2c2 100644
--- a/tools/up35/up35.go
+++ b/tools/up35/up35.go
@@ -1,10 +1,25 @@
+// 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 main
import (
"flag"
- "github.com/openimsdk/open-im-server/v3/tools/up35/pkg"
"log"
"os"
+
+ "github.com/openimsdk/open-im-server/v3/tools/up35/pkg"
)
func main() {
diff --git a/tools/url2im/main.go b/tools/url2im/main.go
index ee159b5e8..8d6151b09 100644
--- a/tools/url2im/main.go
+++ b/tools/url2im/main.go
@@ -1,3 +1,17 @@
+// 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 main
import (
diff --git a/tools/url2im/pkg/api.go b/tools/url2im/pkg/api.go
index 1fc3813bb..7575b078a 100644
--- a/tools/url2im/pkg/api.go
+++ b/tools/url2im/pkg/api.go
@@ -1,3 +1,17 @@
+// 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 pkg
import (
diff --git a/tools/url2im/pkg/buffer.go b/tools/url2im/pkg/buffer.go
index 8ccc5c52f..b4c104652 100644
--- a/tools/url2im/pkg/buffer.go
+++ b/tools/url2im/pkg/buffer.go
@@ -1,3 +1,17 @@
+// 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 pkg
import (
diff --git a/tools/url2im/pkg/config.go b/tools/url2im/pkg/config.go
index 020395262..740e748cb 100644
--- a/tools/url2im/pkg/config.go
+++ b/tools/url2im/pkg/config.go
@@ -1,3 +1,17 @@
+// 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 pkg
import "time"
diff --git a/tools/url2im/pkg/http.go b/tools/url2im/pkg/http.go
index 32e128524..50fb30c7b 100644
--- a/tools/url2im/pkg/http.go
+++ b/tools/url2im/pkg/http.go
@@ -1,3 +1,17 @@
+// 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 pkg
import "net/http"
diff --git a/tools/url2im/pkg/manage.go b/tools/url2im/pkg/manage.go
index a68078f85..70c6713fc 100644
--- a/tools/url2im/pkg/manage.go
+++ b/tools/url2im/pkg/manage.go
@@ -1,3 +1,17 @@
+// 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 pkg
import (
diff --git a/tools/url2im/pkg/md5.go b/tools/url2im/pkg/md5.go
index 0db5ba000..26b8d47a2 100644
--- a/tools/url2im/pkg/md5.go
+++ b/tools/url2im/pkg/md5.go
@@ -1,3 +1,17 @@
+// 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 pkg
import (
diff --git a/tools/url2im/pkg/progress.go b/tools/url2im/pkg/progress.go
index 2d6ef3891..5f30495c6 100644
--- a/tools/url2im/pkg/progress.go
+++ b/tools/url2im/pkg/progress.go
@@ -1,3 +1,17 @@
+// 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 pkg
import (
From c8463a0a80ddd350c4e9e7f4070776c160a906a3 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Mon, 18 Dec 2023 12:30:38 +0800
Subject: [PATCH 018/110] Update check-all.sh (#1573)
---
scripts/check-all.sh | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/scripts/check-all.sh b/scripts/check-all.sh
index 30a4e422b..a438ac26b 100755
--- a/scripts/check-all.sh
+++ b/scripts/check-all.sh
@@ -33,8 +33,8 @@ openim::log::info "\n# Begin to check all openim service"
# OpenIM status
# Elegant printing function
print_services_and_ports() {
- declare -g service_names=("${!1}")
- declare -g service_ports=("${!2}")
+ local -n service_names=$1
+ local -n service_ports=$2
echo "+-------------------------+----------+"
echo "| Service Name | Port |"
@@ -89,4 +89,4 @@ else
echo "++++ Check all openim service ports successfully !"
fi
-set -e
\ No newline at end of file
+set -e
From 87610568ae1189540a2e0b6ed5bd42c3540ba4ce Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Mon, 18 Dec 2023 18:39:58 +0800
Subject: [PATCH 019/110] add crud for general function user process, add
pinFriend (#1532)
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* fix bugs
* fix bugs
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* Update go.mod
* Update friend.go
* debug
* debug
* debug
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* I cannot solve todo in test.sh
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* Update go.mod
* fix group notification
* fix group notification
* update openimsdk tools
* update openim server remove duplicate code
* update openim server remove duplicate code
* update user command get
* update user command get
* update response of callback response error
* update black ex
* update join group ex
* update user pb2map
* update go sum
* update go sum
---------
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
go.mod | 8 ++-
internal/api/friend.go | 3 ++
internal/api/route.go | 6 +++
internal/api/user.go | 20 +++++++
internal/rpc/friend/black.go | 1 +
internal/rpc/friend/friend.go | 38 ++++++++++++--
internal/rpc/group/callback.go | 8 +--
internal/rpc/group/group.go | 2 +
internal/rpc/msg/callback.go | 1 -
internal/rpc/third/third.go | 10 ++++
internal/rpc/user/user.go | 72 +++++++++++++++++++------
pkg/callbackstruct/group.go | 1 +
pkg/common/convert/friend.go | 3 +-
pkg/common/convert/user.go | 2 +-
pkg/common/db/controller/friend.go | 7 +++
pkg/common/db/controller/user.go | 19 +++++++
pkg/common/db/mgo/friend.go | 19 ++++++-
pkg/common/db/mgo/user.go | 73 ++++++++++++++++++++++++++
pkg/common/db/table/relation/friend.go | 3 ++
pkg/common/db/table/relation/user.go | 6 +++
pkg/common/http/http_client.go | 2 +-
scripts/install/test.sh | 50 ++++++++++++++++--
22 files changed, 320 insertions(+), 34 deletions(-)
diff --git a/go.mod b/go.mod
index 11d374d08..c8dd96689 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,6 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.31
- github.com/OpenIMSDK/tools v0.0.20
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
@@ -35,6 +33,8 @@ require github.com/google/uuid v1.3.1
require (
github.com/IBM/sarama v1.41.3
+ github.com/OpenIMSDK/protocol v0.0.36
+ github.com/OpenIMSDK/tools v0.0.20
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/go-redis/redis v6.15.9+incompatible
github.com/redis/go-redis/v9 v9.2.1
@@ -154,3 +154,7 @@ require (
golang.org/x/crypto v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
+//replace (
+// github.com/OpenIMSDK/protocol v0.0.34 => github.com/AndrewZuo01/protocol v0.0.0-20231218034338-b8d838e0b182
+//)
+
diff --git a/internal/api/friend.go b/internal/api/friend.go
index 23f337a9f..58e7398dd 100644
--- a/internal/api/friend.go
+++ b/internal/api/friend.go
@@ -92,3 +92,6 @@ func (o *FriendApi) GetFriendIDs(c *gin.Context) {
func (o *FriendApi) GetSpecifiedFriendsInfo(c *gin.Context) {
a2r.Call(friend.FriendClient.GetSpecifiedFriendsInfo, o.Client, c)
}
+func (o *FriendApi) SetPinFriends(c *gin.Context) {
+ a2r.Call(friend.FriendClient.PinFriends, o.Client, c)
+}
diff --git a/internal/api/route.go b/internal/api/route.go
index 7a331d643..8bfea5cca 100644
--- a/internal/api/route.go
+++ b/internal/api/route.go
@@ -77,6 +77,11 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
userRouterGroup.POST("/subscribe_users_status", ParseToken, u.SubscriberStatus)
userRouterGroup.POST("/get_users_status", ParseToken, u.GetUserStatus)
userRouterGroup.POST("/get_subscribe_users_status", ParseToken, u.GetSubscribeUsersStatus)
+
+ userRouterGroup.POST("/process_user_command_add", ParseToken, u.ProcessUserCommandAdd)
+ userRouterGroup.POST("/process_user_command_delete", ParseToken, u.ProcessUserCommandDelete)
+ userRouterGroup.POST("/process_user_command_update", ParseToken, u.ProcessUserCommandUpdate)
+ userRouterGroup.POST("/process_user_command_get", ParseToken, u.ProcessUserCommandGet)
}
// friend routing group
friendRouterGroup := r.Group("/friend", ParseToken)
@@ -98,6 +103,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
friendRouterGroup.POST("/is_friend", f.IsFriend)
friendRouterGroup.POST("/get_friend_id", f.GetFriendIDs)
friendRouterGroup.POST("/get_specified_friends_info", f.GetSpecifiedFriendsInfo)
+ friendRouterGroup.POST("/set_pin_friend", f.SetPinFriends)
}
g := NewGroupApi(*groupRpc)
groupRouterGroup := r.Group("/group", ParseToken)
diff --git a/internal/api/user.go b/internal/api/user.go
index 86b7c0b0b..8350d1711 100644
--- a/internal/api/user.go
+++ b/internal/api/user.go
@@ -199,3 +199,23 @@ func (u *UserApi) GetUserStatus(c *gin.Context) {
func (u *UserApi) GetSubscribeUsersStatus(c *gin.Context) {
a2r.Call(user.UserClient.GetSubscribeUsersStatus, u.Client, c)
}
+
+// ProcessUserCommandAdd user general function add
+func (u *UserApi) ProcessUserCommandAdd(c *gin.Context) {
+ a2r.Call(user.UserClient.ProcessUserCommandAdd, u.Client, c)
+}
+
+// ProcessUserCommandDelete user general function delete
+func (u *UserApi) ProcessUserCommandDelete(c *gin.Context) {
+ a2r.Call(user.UserClient.ProcessUserCommandDelete, u.Client, c)
+}
+
+// ProcessUserCommandUpdate user general function update
+func (u *UserApi) ProcessUserCommandUpdate(c *gin.Context) {
+ a2r.Call(user.UserClient.ProcessUserCommandUpdate, u.Client, c)
+}
+
+// ProcessUserCommandGet user general function get
+func (u *UserApi) ProcessUserCommandGet(c *gin.Context) {
+ a2r.Call(user.UserClient.ProcessUserCommandGet, u.Client, c)
+}
diff --git a/internal/rpc/friend/black.go b/internal/rpc/friend/black.go
index 54cdbb2cc..ed5791c38 100644
--- a/internal/rpc/friend/black.go
+++ b/internal/rpc/friend/black.go
@@ -79,6 +79,7 @@ func (s *friendServer) AddBlack(ctx context.Context, req *pbfriend.AddBlackReq)
BlockUserID: req.BlackUserID,
OperatorUserID: mcontext.GetOpUserID(ctx),
CreateTime: time.Now(),
+ Ex: req.Ex,
}
if err := s.blackDatabase.Create(ctx, []*relation.BlackModel{&black}); err != nil {
return nil, err
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index 20c47ad8f..12203aa7e 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -53,10 +53,6 @@ type friendServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
-func (s *friendServer) PinFriends(ctx context.Context, req *pbfriend.PinFriendsReq) (*pbfriend.PinFriendsResp, error) {
- return nil, errs.ErrInternalServer.Wrap("not implemented")
-}
-
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
// Initialize MongoDB
mongo, err := unrelation.NewMongo()
@@ -411,6 +407,7 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien
}
var friendInfo *sdkws.FriendInfo
if friend := friendMap[userID]; friend != nil {
+
friendInfo = &sdkws.FriendInfo{
OwnerUserID: friend.OwnerUserID,
Remark: friend.Remark,
@@ -418,6 +415,7 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien
AddSource: friend.AddSource,
OperatorUserID: friend.OperatorUserID,
Ex: friend.Ex,
+ IsPinned: friend.IsPinned,
}
}
var blackInfo *sdkws.BlackInfo
@@ -438,3 +436,35 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien
}
return resp, nil
}
+func (s *friendServer) PinFriends(
+ ctx context.Context,
+ req *pbfriend.PinFriendsReq,
+) (*pbfriend.PinFriendsResp, error) {
+ if len(req.FriendUserIDs) == 0 {
+ return nil, errs.ErrArgs.Wrap("friendIDList is empty")
+ }
+ if utils.Duplicate(req.FriendUserIDs) {
+ return nil, errs.ErrArgs.Wrap("friendIDList repeated")
+ }
+ var isPinned bool
+ if req.IsPinned != nil {
+ isPinned = req.IsPinned.Value
+ } else {
+ return nil, errs.ErrArgs.Wrap("isPinned is nil")
+ }
+ //check whther in friend list
+ _, err := s.friendDatabase.FindFriendsWithError(ctx, req.OwnerUserID, req.FriendUserIDs)
+ if err != nil {
+ return nil, err
+ }
+
+ //set friendslist friend pin status to isPinned
+ for _, friendID := range req.FriendUserIDs {
+ if err := s.friendDatabase.UpdateFriendPinStatus(ctx, req.OwnerUserID, friendID, isPinned); err != nil {
+ return nil, err
+ }
+ }
+
+ resp := &pbfriend.PinFriendsResp{}
+ return resp, nil
+}
diff --git a/internal/rpc/group/callback.go b/internal/rpc/group/callback.go
index 4a89a16fb..8779cb89b 100644
--- a/internal/rpc/group/callback.go
+++ b/internal/rpc/group/callback.go
@@ -327,8 +327,6 @@ func CallbackBeforeInviteUserToGroup(ctx context.Context, req *group.InviteUserT
// Handle the scenario where certain members are refused
// You might want to update the req.Members list or handle it as per your business logic
}
- utils.StructFieldNotNilReplace(req, resp)
-
return nil
}
@@ -395,7 +393,10 @@ func CallbackBeforeSetGroupInfo(ctx context.Context, req *group.SetGroupInfoReq)
if resp.ApplyMemberFriend != nil {
req.GroupInfoForSet.ApplyMemberFriend = wrapperspb.Int32(*resp.ApplyMemberFriend)
}
- utils.StructFieldNotNilReplace(req, resp)
+ utils.NotNilReplace(&req.GroupInfoForSet.GroupID, &resp.GroupID)
+ utils.NotNilReplace(&req.GroupInfoForSet.GroupName, &resp.GroupName)
+ utils.NotNilReplace(&req.GroupInfoForSet.FaceURL, &resp.FaceURL)
+ utils.NotNilReplace(&req.GroupInfoForSet.Introduction, &resp.Introduction)
return nil
}
func CallbackAfterSetGroupInfo(ctx context.Context, req *group.SetGroupInfoReq) error {
@@ -426,6 +427,5 @@ func CallbackAfterSetGroupInfo(ctx context.Context, req *group.SetGroupInfoReq)
if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackAfterSetGroupInfo); err != nil {
return err
}
- utils.StructFieldNotNilReplace(req, resp)
return nil
}
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index 2c3c6fc43..ba129d7e9 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -802,6 +802,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
GroupType: string(group.GroupType),
ApplyID: req.InviterUserID,
ReqMessage: req.ReqMessage,
+ Ex: req.Ex,
}
if err = CallbackApplyJoinGroupBefore(ctx, reqCall); err != nil {
@@ -848,6 +849,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
JoinSource: req.JoinSource,
ReqTime: time.Now(),
HandledTime: time.Unix(0, 0),
+ Ex: req.Ex,
}
if err := s.db.CreateGroupRequest(ctx, []*relationtb.GroupRequestModel{&groupRequest}); err != nil {
return nil, err
diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go
index 0bd71d9f7..3a8587ea3 100644
--- a/internal/rpc/msg/callback.go
+++ b/internal/rpc/msg/callback.go
@@ -202,6 +202,5 @@ func CallbackAfterRevokeMsg(ctx context.Context, req *pbchat.RevokeMsgReq) error
if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, callbackReq, resp, config.Config.Callback.CallbackAfterRevokeMsg); err != nil {
return err
}
- utils.StructFieldNotNilReplace(req, resp)
return nil
}
diff --git a/internal/rpc/third/third.go b/internal/rpc/third/third.go
index 7a63d3526..35df3f925 100644
--- a/internal/rpc/third/third.go
+++ b/internal/rpc/third/third.go
@@ -101,6 +101,16 @@ type thirdServer struct {
defaultExpire time.Duration
}
+func (t *thirdServer) InitiateFormData(ctx context.Context, req *third.InitiateFormDataReq) (*third.InitiateFormDataResp, error) {
+ //TODO implement me
+ panic("implement me")
+}
+
+func (t *thirdServer) CompleteFormData(ctx context.Context, req *third.CompleteFormDataReq) (*third.CompleteFormDataResp, error) {
+ //TODO implement me
+ panic("implement me")
+}
+
func (t *thirdServer) FcmUpdateToken(ctx context.Context, req *third.FcmUpdateTokenReq) (resp *third.FcmUpdateTokenResp, err error) {
err = t.thirdDatabase.FcmUpdateToken(ctx, req.Account, int(req.PlatformID), req.FcmToken, req.ExpireTime)
if err != nil {
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index a2fa14c7a..70e3aebe6 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -56,22 +56,6 @@ type userServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
-func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) {
- return nil, errs.ErrInternalServer.Wrap("not implemented")
-}
-
-func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) {
- return nil, errs.ErrInternalServer.Wrap("not implemented")
-}
-
-func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) {
- return nil, errs.ErrInternalServer.Wrap("not implemented")
-}
-
-func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) {
- return nil, errs.ErrInternalServer.Wrap("not implemented")
-}
-
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis()
if err != nil {
@@ -350,3 +334,59 @@ func (s *userServer) GetSubscribeUsersStatus(ctx context.Context,
}
return &pbuser.GetSubscribeUsersStatusResp{StatusList: onlineStatusList}, nil
}
+
+// ProcessUserCommandAdd user general function add
+func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) {
+ // Assuming you have a method in s.UserDatabase to add a user command
+ err := s.UserDatabase.AddUserCommand(ctx, req.UserID, req.Type, req.Uuid, req.Value)
+ if err != nil {
+ return nil, err
+ }
+
+ return &pbuser.ProcessUserCommandAddResp{}, nil
+}
+
+// ProcessUserCommandDelete user general function delete
+func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) {
+ // Assuming you have a method in s.UserDatabase to delete a user command
+ err := s.UserDatabase.DeleteUserCommand(ctx, req.UserID, req.Type, req.Uuid)
+ if err != nil {
+ return nil, err
+ }
+
+ return &pbuser.ProcessUserCommandDeleteResp{}, nil
+}
+
+// ProcessUserCommandUpdate user general function update
+func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) {
+ // Assuming you have a method in s.UserDatabase to update a user command
+ err := s.UserDatabase.UpdateUserCommand(ctx, req.UserID, req.Type, req.Uuid, req.Value)
+ if err != nil {
+ return nil, err
+ }
+
+ return &pbuser.ProcessUserCommandUpdateResp{}, nil
+}
+
+func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) {
+ // Fetch user commands from the database
+ commands, err := s.UserDatabase.GetUserCommands(ctx, req.UserID, req.Type)
+ if err != nil {
+ return nil, err
+ }
+
+ // Initialize commandInfoSlice as an empty slice
+ commandInfoSlice := make([]*pbuser.CommandInfoResp, 0, len(commands))
+
+ for _, command := range commands {
+ // No need to use index since command is already a pointer
+ commandInfoSlice = append(commandInfoSlice, &pbuser.CommandInfoResp{
+ Uuid: command.Uuid,
+ Value: command.Value,
+ CreateTime: command.CreateTime,
+ })
+ }
+
+ // Return the response with the slice
+ return &pbuser.ProcessUserCommandGetResp{KVArray: commandInfoSlice}, nil
+}
diff --git a/pkg/callbackstruct/group.go b/pkg/callbackstruct/group.go
index 899b4312f..5968f1e55 100644
--- a/pkg/callbackstruct/group.go
+++ b/pkg/callbackstruct/group.go
@@ -148,6 +148,7 @@ type CallbackJoinGroupReq struct {
GroupType string `json:"groupType"`
ApplyID string `json:"applyID"`
ReqMessage string `json:"reqMessage"`
+ Ex string `json:"ex"`
}
type CallbackJoinGroupResp struct {
diff --git a/pkg/common/convert/friend.go b/pkg/common/convert/friend.go
index c81cd98d6..62ce6f95b 100644
--- a/pkg/common/convert/friend.go
+++ b/pkg/common/convert/friend.go
@@ -17,7 +17,6 @@ package convert
import (
"context"
"fmt"
-
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
@@ -62,6 +61,7 @@ func FriendsDB2Pb(
for _, friendDB := range friendsDB {
userID = append(userID, friendDB.FriendUserID)
}
+
users, err := getUsers(ctx, userID)
if err != nil {
return nil, err
@@ -74,6 +74,7 @@ func FriendsDB2Pb(
friendPb.FriendUser.FaceURL = users[friend.FriendUserID].FaceURL
friendPb.FriendUser.Ex = users[friend.FriendUserID].Ex
friendPb.CreateTime = friend.CreateTime.Unix()
+ friendPb.IsPinned = friend.IsPinned
friendsPb = append(friendsPb, friendPb)
}
return friendsPb, nil
diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go
index 8d960546a..72041a790 100644
--- a/pkg/common/convert/user.go
+++ b/pkg/common/convert/user.go
@@ -64,7 +64,7 @@ func UserPb2DBMap(user *sdkws.UserInfo) map[string]any {
"global_recv_msg_opt": user.GlobalRecvMsgOpt,
}
for key, value := range fields {
- if v, ok := value.(string); ok && v != "" {
+ if v, ok := value.(string); ok {
val[key] = v
} else if v, ok := value.(int32); ok && v != 0 {
val[key] = v
diff --git a/pkg/common/db/controller/friend.go b/pkg/common/db/controller/friend.go
index 29b2ef9b1..34ce22295 100644
--- a/pkg/common/db/controller/friend.go
+++ b/pkg/common/db/controller/friend.go
@@ -58,6 +58,7 @@ type FriendDatabase interface {
FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error)
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error)
+ UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error)
}
type friendDatabase struct {
@@ -298,3 +299,9 @@ func (f *friendDatabase) FindFriendUserIDs(ctx context.Context, ownerUserID stri
func (f *friendDatabase) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
return f.friendRequest.FindBothFriendRequests(ctx, fromUserID, toUserID)
}
+func (f *friendDatabase) UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) {
+ if err := f.friend.UpdatePinStatus(ctx, ownerUserID, friendUserID, isPinned); err != nil {
+ return err
+ }
+ return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx)
+}
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index ca703b729..433fb7ad3 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -68,6 +68,12 @@ type UserDatabase interface {
GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error)
// SetUserStatus Set the user status and store the user status in redis
SetUserStatus(ctx context.Context, userID string, status, platformID int32) error
+
+ //CRUD user command
+ AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error
+ DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error
+ UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error
+ GetUserCommands(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error)
}
type userDatabase struct {
@@ -227,3 +233,16 @@ func (u *userDatabase) GetUserStatus(ctx context.Context, userIDs []string) ([]*
func (u *userDatabase) SetUserStatus(ctx context.Context, userID string, status, platformID int32) error {
return u.cache.SetUserStatus(ctx, userID, status, platformID)
}
+func (u *userDatabase) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error {
+ return u.userDB.AddUserCommand(ctx, userID, Type, UUID, value)
+}
+func (u *userDatabase) DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error {
+ return u.userDB.DeleteUserCommand(ctx, userID, Type, UUID)
+}
+func (u *userDatabase) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error {
+ return u.userDB.UpdateUserCommand(ctx, userID, Type, UUID, value)
+}
+func (u *userDatabase) GetUserCommands(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) {
+ commands, err := u.userDB.GetUserCommand(ctx, userID, Type)
+ return commands, err
+}
diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go
index 8f3528d91..667098819 100644
--- a/pkg/common/db/mgo/friend.go
+++ b/pkg/common/db/mgo/friend.go
@@ -16,7 +16,7 @@ package mgo
import (
"context"
-
+ "github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/mongo/options"
@@ -143,3 +143,20 @@ func (f *FriendMgo) FindFriendUserIDs(ctx context.Context, ownerUserID string) (
filter := bson.M{"owner_user_id": ownerUserID}
return mgoutil.Find[string](ctx, f.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "friend_user_id": 1}))
}
+
+// UpdatePinStatus update friend's pin status
+func (f *FriendMgo) UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) {
+
+ filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID}
+ // Create an update operation to set the "is_pinned" field to isPinned for all documents.
+ update := bson.M{"$set": bson.M{"is_pinned": isPinned}}
+
+ // Perform the update operation for all documents in the collection.
+ _, err = f.coll.UpdateMany(ctx, filter, update)
+
+ if err != nil {
+ return errs.Wrap(err, "update pin error")
+ }
+
+ return nil
+}
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 37e354cbb..268d69ce3 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -16,6 +16,7 @@ package mgo
import (
"context"
+ "github.com/OpenIMSDK/protocol/user"
"time"
"github.com/OpenIMSDK/tools/mgoutil"
@@ -87,6 +88,78 @@ func (u *UserMgo) CountTotal(ctx context.Context, before *time.Time) (count int6
return mgoutil.Count(ctx, u.coll, bson.M{"create_time": bson.M{"$lt": before}})
}
+func (u *UserMgo) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error {
+ collection := u.coll.Database().Collection("userCommands")
+
+ // Create a new document instead of updating an existing one
+ doc := bson.M{
+ "userID": userID,
+ "type": Type,
+ "uuid": UUID,
+ "createTime": time.Now().Unix(), // assuming you want the creation time in Unix timestamp
+ "value": value,
+ }
+
+ _, err := collection.InsertOne(ctx, doc)
+ return err
+}
+func (u *UserMgo) DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error {
+ collection := u.coll.Database().Collection("userCommands")
+
+ filter := bson.M{"userID": userID, "type": Type, "uuid": UUID}
+
+ _, err := collection.DeleteOne(ctx, filter)
+ return err
+}
+func (u *UserMgo) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error {
+ collection := u.coll.Database().Collection("userCommands")
+
+ filter := bson.M{"userID": userID, "type": Type, "uuid": UUID}
+ update := bson.M{"$set": bson.M{"value": value}}
+
+ _, err := collection.UpdateOne(ctx, filter, update)
+ return err
+}
+func (u *UserMgo) GetUserCommand(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) {
+ collection := u.coll.Database().Collection("userCommands")
+ filter := bson.M{"userID": userID, "type": Type}
+
+ cursor, err := collection.Find(ctx, filter)
+ if err != nil {
+ return nil, err
+ }
+ defer cursor.Close(ctx)
+
+ // Initialize commands as a slice of pointers
+ commands := []*user.CommandInfoResp{}
+
+ for cursor.Next(ctx) {
+ var document struct {
+ UUID string `bson:"uuid"`
+ Value string `bson:"value"`
+ CreateTime int64 `bson:"createTime"`
+ }
+
+ if err := cursor.Decode(&document); err != nil {
+ return nil, err
+ }
+
+ commandInfo := &user.CommandInfoResp{ // Change here: use a pointer to the struct
+ Uuid: document.UUID,
+ Value: document.Value,
+ CreateTime: document.CreateTime,
+ }
+
+ commands = append(commands, commandInfo)
+ }
+
+ if err := cursor.Err(); err != nil {
+ return nil, err
+ }
+
+ return commands, nil
+}
+
func (u *UserMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
pipeline := bson.A{
bson.M{
diff --git a/pkg/common/db/table/relation/friend.go b/pkg/common/db/table/relation/friend.go
index 75dbea850..4f85998f4 100644
--- a/pkg/common/db/table/relation/friend.go
+++ b/pkg/common/db/table/relation/friend.go
@@ -30,6 +30,7 @@ type FriendModel struct {
AddSource int32 `bson:"add_source"`
OperatorUserID string `bson:"operator_user_id"`
Ex string `bson:"ex"`
+ IsPinned bool `bson:"is_pinned"`
}
// FriendModelInterface defines the operations for managing friends in MongoDB.
@@ -56,4 +57,6 @@ type FriendModelInterface interface {
FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
// FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
+ // UpdatePinStatus update friend's pin status
+ UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error)
}
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index 1f26d751f..213a6b774 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -16,6 +16,7 @@ package relation
import (
"context"
+ "github.com/OpenIMSDK/protocol/user"
"time"
"github.com/OpenIMSDK/tools/pagination"
@@ -60,4 +61,9 @@ type UserModelInterface interface {
CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
// 获取范围内用户增量
CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
+ //CRUD user command
+ AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error
+ DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error
+ UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error
+ GetUserCommand(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error)
}
diff --git a/pkg/common/http/http_client.go b/pkg/common/http/http_client.go
index e1bc83d38..baad60459 100644
--- a/pkg/common/http/http_client.go
+++ b/pkg/common/http/http_client.go
@@ -127,7 +127,7 @@ func callBackPostReturn(ctx context.Context, url, command string, input interfac
log.ZWarn(ctx, "callback failed but continue", err, "url", url)
return nil
}
- return errs.ErrData.Wrap(err.Error())
+ return errs.ErrData.WithDetail(err.Error() + "response format error")
}
return output.Parse()
diff --git a/scripts/install/test.sh b/scripts/install/test.sh
index 049dc19c8..93a39f298 100755
--- a/scripts/install/test.sh
+++ b/scripts/install/test.sh
@@ -70,14 +70,16 @@ function openim::test::auth() {
#################################### Auth Module ####################################
-# Define a function to get a token (Admin Token)
+# Define a function to get a token for a specific user
openim::test::get_token() {
+ local user_id="${1:-openIM123456}" # Default user ID if not provided
token_response=$(${CCURL} "${OperationID}" "${Header}" ${INSECURE_OPENIMAPI}/auth/user_token \
- -d'{"secret": "'"$SECRET"'","platformID": 1,"userID": "openIM123456"}')
+ -d'{"secret": "'"$SECRET"'","platformID": 1,"userID": "'$user_id'"}')
token=$(echo $token_response | grep -Po 'token[" :]+\K[^"]+')
echo "$token"
}
+
Header="-HContent-Type: application/json"
OperationID="-HoperationID: 1646445464564"
Token="-Htoken: $(openim::test::get_token)"
@@ -530,6 +532,36 @@ EOF
openim::test::check_error "$response"
}
+# Updates the pin status of multiple friends.
+openim::test::update_pin_status() {
+ local ownerUserID="${1}"
+ shift # Shift the arguments to skip the first one (ownerUserID)
+ local isPinned="${1}"
+ shift # Shift the arguments to skip the isPinned argument
+
+ # Constructing the list of friendUserIDs
+ local friendUserIDsArray=()
+ for friendUserID in "$@"; do
+ friendUserIDsArray+=("\"${friendUserID}\"")
+ done
+ local friendUserIDs=$(IFS=,; echo "${friendUserIDsArray[*]}")
+
+ local request_body=$(cat <
Date: Wed, 20 Dec 2023 10:22:55 +0800
Subject: [PATCH 020/110] fix: fix the output format (#1585)
* fix: update the component output format
* fix: fix the successful tiops
* fix: update the error format
---
tools/component/component.go | 72 +++++++++++++++++++++---------------
1 file changed, 42 insertions(+), 30 deletions(-)
diff --git a/tools/component/component.go b/tools/component/component.go
index 7150c91af..28ea7a2fe 100644
--- a/tools/component/component.go
+++ b/tools/component/component.go
@@ -72,7 +72,7 @@ func initCfg() error {
type checkFunc struct {
name string
- function func() error
+ function func() (string, error)
}
func main() {
@@ -101,13 +101,13 @@ func main() {
allSuccess := true
for _, check := range checks {
- err := check.function()
+ str, err := check.function()
if err != nil {
- errorPrint(fmt.Sprintf("Starting %s failed: %v", check.name, err))
+ errorPrint(fmt.Sprintf("Starting %s failed, %v", check.name, err))
allSuccess = false
break
} else {
- successPrint(fmt.Sprintf("%s starts successfully", check.name))
+ successPrint(fmt.Sprintf("%s connected successfully, %s", check.name, str))
}
}
@@ -142,21 +142,22 @@ func getEnv(key, fallback string) string {
}
// checkMongo checks the MongoDB connection
-func checkMongo() error {
+func checkMongo() (string, error) {
// Use environment variables or fallback to config
uri := getEnv("MONGO_URI", buildMongoURI())
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
+ str := "ths addr is:" + strings.Join(config.Config.Mongo.Address, ",")
if err != nil {
- return errs.Wrap(err)
+ return "", errs.Wrap(errStr(err, str))
}
defer client.Disconnect(context.TODO())
if err = client.Ping(context.TODO(), nil); err != nil {
- return errs.Wrap(err)
+ return "", errs.Wrap(errStr(err, str))
}
- return nil
+ return str, nil
}
// buildMongoURI constructs the MongoDB URI using configuration settings
@@ -178,10 +179,10 @@ func buildMongoURI() string {
}
// checkMinio checks the MinIO connection
-func checkMinio() error {
+func checkMinio() (string, error) {
// Check if MinIO is enabled
if config.Config.Object.Enable != "minio" {
- return nil
+ return "", nil
}
// Prioritize environment variables
@@ -191,13 +192,14 @@ func checkMinio() error {
useSSL := getEnv("MINIO_USE_SSL", "false") // Assuming SSL is not used by default
if endpoint == "" || accessKeyID == "" || secretAccessKey == "" {
- return ErrConfig.Wrap("MinIO configuration missing")
+ return "", ErrConfig.Wrap("MinIO configuration missing")
}
// Parse endpoint URL to determine if SSL is enabled
u, err := url.Parse(endpoint)
if err != nil {
- return errs.Wrap(err)
+ str := "the endpoint is:" + endpoint
+ return "", errs.Wrap(errStr(err, str))
}
secure := u.Scheme == "https" || useSSL == "true"
@@ -206,31 +208,34 @@ func checkMinio() error {
Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
Secure: secure,
})
+ str := "ths addr is:" + u.Host
if err != nil {
- return errs.Wrap(err)
+ strs := fmt.Sprintf("%v;host:%s,accessKeyID:%s,secretAccessKey:%s,Secure:%v", err, u.Host, accessKeyID, secretAccessKey, secure)
+ return "", errs.Wrap(err, strs)
}
// Perform health check
cancel, err := minioClient.HealthCheck(time.Duration(minioHealthCheckDuration) * time.Second)
if err != nil {
- return errs.Wrap(err)
+ return "", errs.Wrap(errStr(err, str))
}
defer cancel()
if minioClient.IsOffline() {
- return ErrComponentStart.Wrap("Minio server is offline")
+ str := fmt.Sprintf("Minio server is offline;%s", str)
+ return "", ErrComponentStart.Wrap(str)
}
// Check for localhost in API URL and Minio SignEndpoint
if exactIP(config.Config.Object.ApiURL) == "127.0.0.1" || exactIP(config.Config.Object.Minio.SignEndpoint) == "127.0.0.1" {
- return ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1")
+ return "", ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1")
}
- return nil
+ return str, nil
}
// checkRedis checks the Redis connection
-func checkRedis() error {
+func checkRedis() (string, error) {
// Prioritize environment variables
address := getEnv("REDIS_ADDRESS", strings.Join(config.Config.Redis.Address, ","))
username := getEnv("REDIS_USERNAME", config.Config.Redis.Username)
@@ -259,15 +264,16 @@ func checkRedis() error {
// Ping Redis to check connectivity
_, err := redisClient.Ping(context.Background()).Result()
+ str := "the addr is:" + strings.Join(redisAddresses, ",")
if err != nil {
- return errs.Wrap(err)
+ return "", errs.Wrap(errStr(err, str))
}
- return nil
+ return str, nil
}
// checkZookeeper checks the Zookeeper connection
-func checkZookeeper() error {
+func checkZookeeper() (string, error) {
// Prioritize environment variables
schema := getEnv("ZOOKEEPER_SCHEMA", "digest")
address := getEnv("ZOOKEEPER_ADDRESS", strings.Join(config.Config.Zookeeper.ZkAddr, ","))
@@ -278,30 +284,31 @@ func checkZookeeper() error {
zookeeperAddresses := strings.Split(address, ",")
// Connect to Zookeeper
+ str := "the addr is:" + address
c, _, err := zk.Connect(zookeeperAddresses, time.Second) // Adjust the timeout as necessary
if err != nil {
- return errs.Wrap(err)
+ return "", errs.Wrap(errStr(err, str))
}
defer c.Close()
// Set authentication if username and password are provided
if username != "" && password != "" {
if err := c.AddAuth(schema, []byte(username+":"+password)); err != nil {
- return errs.Wrap(err)
+ return "", errs.Wrap(errStr(err, str))
}
}
// Check if Zookeeper is reachable
_, _, err = c.Get("/")
if err != nil {
- return errs.Wrap(err)
+ return "", errs.Wrap(err, str)
}
- return nil
+ return str, nil
}
// checkKafka checks the Kafka connection
-func checkKafka() error {
+func checkKafka() (string, error) {
// Prioritize environment variables
username := getEnv("KAFKA_USERNAME", config.Config.Kafka.Username)
password := getEnv("KAFKA_PASSWORD", config.Config.Kafka.Password)
@@ -321,16 +328,17 @@ func checkKafka() error {
// kafka.SetupTLSConfig(cfg)
// Create Kafka client
+ str := "the addr is:" + address
kafkaClient, err := sarama.NewClient(kafkaAddresses, cfg)
if err != nil {
- return errs.Wrap(err)
+ return "", errs.Wrap(errStr(err, str))
}
defer kafkaClient.Close()
// Verify if necessary topics exist
topics, err := kafkaClient.Topics()
if err != nil {
- return errs.Wrap(err)
+ return "", errs.Wrap(err)
}
requiredTopics := []string{
@@ -341,11 +349,11 @@ func checkKafka() error {
for _, requiredTopic := range requiredTopics {
if !isTopicPresent(requiredTopic, topics) {
- return ErrComponentStart.Wrap(fmt.Sprintf("Kafka doesn't contain topic: %v", requiredTopic))
+ return "", ErrComponentStart.Wrap(fmt.Sprintf("Kafka doesn't contain topic: %v", requiredTopic))
}
}
- return nil
+ return str, nil
}
// isTopicPresent checks if a topic is present in the list of topics
@@ -373,3 +381,7 @@ func successPrint(s string) {
func warningPrint(s string) {
colorPrint(colorYellow, "Warning: But %v", s)
}
+
+func errStr(err error, str string) error {
+ return fmt.Errorf("%v;%s", err, str)
+}
From 34ed032af13e9743c8bf2b97695ba1d0d0692a54 Mon Sep 17 00:00:00 2001
From: xuexihuang <1339326187@qq.com>
Date: Mon, 25 Dec 2023 15:32:07 +0800
Subject: [PATCH 021/110] K8s environment supports multiple msggateway by
consistent hash (#1600)
* feature:support multi msggateway
* feature:support multi msggateway
* feature:support multi msggateway by hash method
* fix:fix log
* change to consistent hash
* change go.mod
* fix:fix go routine values error
* fix:fix push filter logic
* fix:fix push filter logic
---------
Co-authored-by: lin.huang
---
go.mod | 8 +-
go.sum | 12 +-
internal/msggateway/n_ws_server.go | 13 +-
internal/push/push_to_client.go | 139 +++++++++++++++---
.../kubernetes/kubernetes.go | 90 ++++++------
5 files changed, 178 insertions(+), 84 deletions(-)
diff --git a/go.mod b/go.mod
index c8dd96689..9a9cde30e 100644
--- a/go.mod
+++ b/go.mod
@@ -34,10 +34,11 @@ require github.com/google/uuid v1.3.1
require (
github.com/IBM/sarama v1.41.3
github.com/OpenIMSDK/protocol v0.0.36
- github.com/OpenIMSDK/tools v0.0.20
+ github.com/OpenIMSDK/tools v0.0.21
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/go-redis/redis v6.15.9+incompatible
github.com/redis/go-redis/v9 v9.2.1
+ github.com/stathat/consistent v1.0.0
github.com/tencentyun/cos-go-sdk-v5 v0.7.45
go.uber.org/automaxprocs v1.5.3
golang.org/x/sync v0.4.0
@@ -141,6 +142,7 @@ require (
gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gorm.io/gorm v1.23.8 // indirect
+ stathat.com/c/consistent v1.0.0 // indirect
)
require (
@@ -154,7 +156,3 @@ require (
golang.org/x/crypto v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
-//replace (
-// github.com/OpenIMSDK/protocol v0.0.34 => github.com/AndrewZuo01/protocol v0.0.0-20231218034338-b8d838e0b182
-//)
-
diff --git a/go.sum b/go.sum
index 30e4b3cb4..61323c57b 100644
--- a/go.sum
+++ b/go.sum
@@ -18,10 +18,10 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.31 h1:ax43x9aqA6EKNXNukS5MT5BSTqkUmwO4uTvbJLtzCgE=
-github.com/OpenIMSDK/protocol v0.0.31/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.20 h1:zBTjQZRJ5lR1FIzP9mtWyAvh5dKsmJXQugi4p8X/97k=
-github.com/OpenIMSDK/tools v0.0.20/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/OpenIMSDK/protocol v0.0.36 h1:UJnFsr1A4RrNeHMNDVS/1nvXWFoGM43dcXpZeJiIZ+0=
+github.com/OpenIMSDK/protocol v0.0.36/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
+github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
@@ -308,6 +308,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
+github.com/stathat/consistent v1.0.0 h1:ZFJ1QTRn8npNBKW065raSZ8xfOqhpb8vLOkfp4CcL/U=
+github.com/stathat/consistent v1.0.0/go.mod h1:uajTPbgSygZBJ+V+0mY7meZ8i0XAcZs7AQ6V121XSxw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -536,3 +538,5 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
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=
+stathat.com/c/consistent v1.0.0 h1:ezyc51EGcRPJUxfHGSgJjWzJdj3NiMU9pNfLNGiXV0c=
+stathat.com/c/consistent v1.0.0/go.mod h1:QkzMWzcbB+yQBL2AttO6sgsQS/JSTapcDISJalmCDS0=
diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go
index 737d5db14..70c2f8fe0 100644
--- a/internal/msggateway/n_ws_server.go
+++ b/internal/msggateway/n_ws_server.go
@@ -288,12 +288,13 @@ func (ws *WsServer) registerClient(client *Client) {
}
wg := sync.WaitGroup{}
- wg.Add(1)
- go func() {
- defer wg.Done()
- _ = ws.sendUserOnlineInfoToOtherNode(client.ctx, client)
- }()
-
+ if config.Config.Envs.Discovery == "zookeeper" {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ _ = ws.sendUserOnlineInfoToOtherNode(client.ctx, client)
+ }()
+ }
wg.Add(1)
go func() {
defer wg.Done()
diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go
index 2ee8c457f..12b78ea2d 100644
--- a/internal/push/push_to_client.go
+++ b/internal/push/push_to_client.go
@@ -18,6 +18,7 @@ import (
"context"
"encoding/json"
"errors"
+ "google.golang.org/grpc"
"sync"
"golang.org/x/sync/errgroup"
@@ -142,6 +143,47 @@ func (p *Pusher) UnmarshalNotificationElem(bytes []byte, t any) error {
return json.Unmarshal([]byte(notification.Detail), t)
}
+/*
+k8s deployment,offline push group messages function
+*/
+func (p *Pusher) k8sOfflinePush2SuperGroup(ctx context.Context, groupID string, msg *sdkws.MsgData, wsResults []*msggateway.SingleMsgToUserResults) error {
+
+ var needOfflinePushUserIDs []string
+ for _, v := range wsResults {
+ if !v.OnlinePush {
+ needOfflinePushUserIDs = append(needOfflinePushUserIDs, v.UserID)
+ }
+ }
+ if len(needOfflinePushUserIDs) > 0 {
+ var offlinePushUserIDs []string
+ err := callbackOfflinePush(ctx, needOfflinePushUserIDs, msg, &offlinePushUserIDs)
+ if err != nil {
+ return err
+ }
+
+ if len(offlinePushUserIDs) > 0 {
+ needOfflinePushUserIDs = offlinePushUserIDs
+ }
+ if msg.ContentType != constant.SignalingNotification {
+ resp, err := p.conversationRpcClient.Client.GetConversationOfflinePushUserIDs(
+ ctx,
+ &conversation.GetConversationOfflinePushUserIDsReq{ConversationID: utils.GenGroupConversationID(groupID), UserIDs: needOfflinePushUserIDs},
+ )
+ if err != nil {
+ return err
+ }
+ if len(resp.UserIDs) > 0 {
+ err = p.offlinePushMsg(ctx, groupID, msg, resp.UserIDs)
+ if err != nil {
+ log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg)
+ return err
+ }
+ }
+ }
+
+ }
+ return nil
+}
func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws.MsgData) (err error) {
log.ZDebug(ctx, "Get super group msg from msg_transfer and push msg", "msg", msg.String(), "groupID", groupID)
var pushToUserIDs []string
@@ -205,7 +247,10 @@ func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws
log.ZDebug(ctx, "get conn and online push success", "result", wsResults, "msg", msg)
isOfflinePush := utils.GetSwitchFromOptions(msg.Options, constant.IsOfflinePush)
- if isOfflinePush {
+ if isOfflinePush && config.Config.Envs.Discovery == "k8s" {
+ return p.k8sOfflinePush2SuperGroup(ctx, groupID, msg, wsResults)
+ }
+ if isOfflinePush && config.Config.Envs.Discovery == "zookeeper" {
var (
onlineSuccessUserIDs = []string{msg.SendID}
webAndPcBackgroundUserIDs []string
@@ -239,14 +284,7 @@ func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws
}
needOfflinePushUserIDs := utils.DifferenceString(onlineSuccessUserIDs, pushToUserIDs)
- if msg.ContentType != constant.SignalingNotification {
- notNotificationUserIDs, err := p.conversationLocalCache.GetRecvMsgNotNotifyUserIDs(ctx, groupID)
- if err != nil {
- return err
- }
- needOfflinePushUserIDs = utils.SliceSub(needOfflinePushUserIDs, notNotificationUserIDs)
- }
// Use offline push messaging
if len(needOfflinePushUserIDs) > 0 {
var offlinePushUserIDs []string
@@ -258,30 +296,89 @@ func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws
if len(offlinePushUserIDs) > 0 {
needOfflinePushUserIDs = offlinePushUserIDs
}
- resp, err := p.conversationRpcClient.Client.GetConversationOfflinePushUserIDs(
- ctx,
- &conversation.GetConversationOfflinePushUserIDsReq{ConversationID: utils.GenGroupConversationID(groupID), UserIDs: needOfflinePushUserIDs},
- )
- if err != nil {
- return err
- }
- if len(resp.UserIDs) > 0 {
- err = p.offlinePushMsg(ctx, groupID, msg, resp.UserIDs)
+ if msg.ContentType != constant.SignalingNotification {
+ resp, err := p.conversationRpcClient.Client.GetConversationOfflinePushUserIDs(
+ ctx,
+ &conversation.GetConversationOfflinePushUserIDsReq{ConversationID: utils.GenGroupConversationID(groupID), UserIDs: needOfflinePushUserIDs},
+ )
if err != nil {
- log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg)
return err
}
- if _, err := p.GetConnsAndOnlinePush(ctx, msg, utils.IntersectString(resp.UserIDs, webAndPcBackgroundUserIDs)); err != nil {
- log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg, "userIDs", utils.IntersectString(needOfflinePushUserIDs, webAndPcBackgroundUserIDs))
- return err
+ if len(resp.UserIDs) > 0 {
+ err = p.offlinePushMsg(ctx, groupID, msg, resp.UserIDs)
+ if err != nil {
+ log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg)
+ return err
+ }
+ if _, err := p.GetConnsAndOnlinePush(ctx, msg, utils.IntersectString(resp.UserIDs, webAndPcBackgroundUserIDs)); err != nil {
+ log.ZError(ctx, "offlinePushMsg failed", err, "groupID", groupID, "msg", msg, "userIDs", utils.IntersectString(needOfflinePushUserIDs, webAndPcBackgroundUserIDs))
+ return err
+ }
}
}
+
}
}
return nil
}
+func (p *Pusher) k8sOnlinePush(ctx context.Context, msg *sdkws.MsgData, pushToUserIDs []string) (wsResults []*msggateway.SingleMsgToUserResults, err error) {
+ var usersHost = make(map[string][]string)
+ for _, v := range pushToUserIDs {
+ tHost, err := p.discov.GetUserIdHashGatewayHost(ctx, v)
+ if err != nil {
+ log.ZError(ctx, "get msggateway hash error", err)
+ return nil, err
+ }
+ tUsers, tbl := usersHost[tHost]
+ if tbl {
+ tUsers = append(tUsers, v)
+ usersHost[tHost] = tUsers
+ } else {
+ usersHost[tHost] = []string{v}
+ }
+ }
+ log.ZDebug(ctx, "genUsers send hosts struct:", "usersHost", usersHost)
+ var usersConns = make(map[*grpc.ClientConn][]string)
+ for host, userIds := range usersHost {
+ tconn, _ := p.discov.GetConn(ctx, host)
+ usersConns[tconn] = userIds
+ }
+ var (
+ mu sync.Mutex
+ wg = errgroup.Group{}
+ maxWorkers = config.Config.Push.MaxConcurrentWorkers
+ )
+ if maxWorkers < 3 {
+ maxWorkers = 3
+ }
+ wg.SetLimit(maxWorkers)
+ for conn, userIds := range usersConns {
+ tcon := conn
+ tuserIds := userIds
+ wg.Go(func() error {
+ input := &msggateway.OnlineBatchPushOneMsgReq{MsgData: msg, PushToUserIDs: tuserIds}
+ msgClient := msggateway.NewMsgGatewayClient(tcon)
+ reply, err := msgClient.SuperGroupOnlineBatchPushOneMsg(ctx, input)
+ if err != nil {
+ return nil
+ }
+ log.ZDebug(ctx, "push result", "reply", reply)
+ if reply != nil && reply.SinglePushResult != nil {
+ mu.Lock()
+ wsResults = append(wsResults, reply.SinglePushResult...)
+ mu.Unlock()
+ }
+ return nil
+ })
+ }
+ _ = wg.Wait()
+ return wsResults, nil
+}
func (p *Pusher) GetConnsAndOnlinePush(ctx context.Context, msg *sdkws.MsgData, pushToUserIDs []string) (wsResults []*msggateway.SingleMsgToUserResults, err error) {
+ if config.Config.Envs.Discovery == "k8s" {
+ return p.k8sOnlinePush(ctx, msg, pushToUserIDs)
+ }
conns, err := p.discov.GetConns(ctx, config.Config.RpcRegisterName.OpenImMessageGatewayName)
log.ZDebug(ctx, "get gateway conn", "conn length", len(conns))
if err != nil {
diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go
index cd5fb0a36..2ff1539e6 100644
--- a/pkg/common/discoveryregister/kubernetes/kubernetes.go
+++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go
@@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
+ "github.com/stathat/consistent"
"os"
"strconv"
"strings"
@@ -31,51 +32,54 @@ import (
// K8sDR represents the Kubernetes service discovery and registration client.
type K8sDR struct {
- options []grpc.DialOption
- rpcRegisterAddr string
+ options []grpc.DialOption
+ rpcRegisterAddr string
+ gatewayHostConsistent *consistent.Consistent
}
-// NewK8sDiscoveryRegister creates a new instance of K8sDR for Kubernetes service discovery and registration.
func NewK8sDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, error) {
-
- return &K8sDR{}, nil
+ gatewayConsistent := consistent.New()
+ gatewayHosts := getMsgGatewayHost(context.Background())
+ for _, v := range gatewayHosts {
+ gatewayConsistent.Add(v)
+ }
+ return &K8sDR{gatewayHostConsistent: gatewayConsistent}, nil
}
-// Register registers a service with Kubernetes.
func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.DialOption) error {
if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
cli.rpcRegisterAddr = serviceName
} else {
- cli.rpcRegisterAddr = cli.getSelfHost(context.Background())
+ cli.rpcRegisterAddr = getSelfHost(context.Background())
}
return nil
}
-
-// UnRegister removes a service registration from Kubernetes.
func (cli *K8sDR) UnRegister() error {
return nil
}
-
-// CreateRpcRootNodes creates root nodes for RPC in Kubernetes.
func (cli *K8sDR) CreateRpcRootNodes(serviceNames []string) error {
return nil
}
-
-// RegisterConf2Registry registers a configuration to the registry.
func (cli *K8sDR) RegisterConf2Registry(key string, conf []byte) error {
return nil
}
-// GetConfFromRegistry retrieves a configuration from the registry.
func (cli *K8sDR) GetConfFromRegistry(key string) ([]byte, error) {
+
return nil, nil
}
-
-func (cli *K8sDR) getSelfHost(ctx context.Context) string {
+func (cli *K8sDR) GetUserIdHashGatewayHost(ctx context.Context, userId string) (string, error) {
+ host, err := cli.gatewayHostConsistent.Get(userId)
+ if err != nil {
+ log.ZError(ctx, "GetUserIdHashGatewayHost error", err)
+ }
+ return host, err
+}
+func getSelfHost(ctx context.Context) string {
port := 88
instance := "openimserver"
selfPodName := os.Getenv("MY_POD_NAME")
@@ -95,26 +99,8 @@ func (cli *K8sDR) getSelfHost(ctx context.Context) string {
return host
}
-// GetConns returns a list of gRPC client connections for a given service.
-func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
- if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
- conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
- return []*grpc.ClientConn{conn}, err
- }
- var ret []*grpc.ClientConn
- gatewayHosts := cli.getMsgGatewayHost(ctx)
- for _, host := range gatewayHosts {
- conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...)
- if err != nil {
- return nil, err
- }
- ret = append(ret, conn)
- }
- return ret, nil
-}
-
// like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88
-func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string {
+func getMsgGatewayHost(ctx context.Context) []string {
port := 88
instance := "openimserver"
selfPodName := os.Getenv("MY_POD_NAME")
@@ -135,40 +121,48 @@ func (cli *K8sDR) getMsgGatewayHost(ctx context.Context) []string {
ret = append(ret, host)
}
log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret)
-
return ret
}
+func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
-// GetConn returns a single gRPC client connection for a given service.
+ if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
+ conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
+ return []*grpc.ClientConn{conn}, err
+ } else {
+ var ret []*grpc.ClientConn
+ gatewayHosts := getMsgGatewayHost(ctx)
+ for _, host := range gatewayHosts {
+ conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...)
+ if err != nil {
+ return nil, err
+ } else {
+ ret = append(ret, conn)
+ }
+ }
+ return ret, nil
+ }
+}
func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
+
return grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
}
-// GetSelfConnTarget returns the connection target of the client itself.
func (cli *K8sDR) GetSelfConnTarget() string {
+
return cli.rpcRegisterAddr
}
-
-// AddOption adds gRPC dial options to the client.
func (cli *K8sDR) AddOption(opts ...grpc.DialOption) {
cli.options = append(cli.options, opts...)
}
-
-// CloseConn closes a given gRPC client connection.
func (cli *K8sDR) CloseConn(conn *grpc.ClientConn) {
conn.Close()
}
-// do not use this method for call rpc.
+// do not use this method for call rpc
func (cli *K8sDR) GetClientLocalConns() map[string][]*grpc.ClientConn {
fmt.Println("should not call this function!!!!!!!!!!!!!!!!!!!!!!!!!")
-
return nil
}
-
-// Close closes the K8sDR client.
func (cli *K8sDR) Close() {
-
- // Close any open resources here (if applicable)
return
}
From f10528010b9bad2ac32f833a8abe93f2b33a8f07 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Mon, 25 Dec 2023 16:26:59 +0800
Subject: [PATCH 022/110] Update check-all.sh (#1591)
---
scripts/check-all.sh | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/check-all.sh b/scripts/check-all.sh
index a438ac26b..efaa2ccb7 100755
--- a/scripts/check-all.sh
+++ b/scripts/check-all.sh
@@ -33,15 +33,15 @@ openim::log::info "\n# Begin to check all openim service"
# OpenIM status
# Elegant printing function
print_services_and_ports() {
- local -n service_names=$1
- local -n service_ports=$2
+ service_names=("$1[@]")
+ service_ports=("$2[@]")
echo "+-------------------------+----------+"
echo "| Service Name | Port |"
echo "+-------------------------+----------+"
- for index in "${!service_names[@]}"; do
- printf "| %-23s | %-8s |\n" "${service_names[$index]}" "${service_ports[$index]}"
+ for index in "${!service_names}"; do
+ printf "| %-23s | %-8s |\n" "${!service_names[$index]}" "${!service_ports[$index]}"
done
echo "+-------------------------+----------+"
From 11a147792d7a8bd0e9d14933c64d60bcdb4da1da Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Mon, 25 Dec 2023 16:28:42 +0800
Subject: [PATCH 023/110] Update prometheus.yml (#1586)
---
deployments/templates/prometheus.yml | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/deployments/templates/prometheus.yml b/deployments/templates/prometheus.yml
index 5c3e0af66..f1a551a62 100644
--- a/deployments/templates/prometheus.yml
+++ b/deployments/templates/prometheus.yml
@@ -44,12 +44,12 @@ scrape_configs:
# prometheus fetches application services
- job_name: 'openimserver-openim-api'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${API_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${API_PROM_PORT}' ]
labels:
namespace: 'default'
- job_name: 'openimserver-openim-msggateway'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${MSG_GATEWAY_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${MSG_GATEWAY_PROM_PORT}' ]
labels:
namespace: 'default'
- job_name: 'openimserver-openim-msgtransfer'
@@ -59,41 +59,41 @@ scrape_configs:
namespace: 'default'
- job_name: 'openimserver-openim-push'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${PUSH_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${PUSH_PROM_PORT}' ]
labels:
namespace: 'default'
- job_name: 'openimserver-openim-rpc-auth'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${AUTH_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${AUTH_PROM_PORT}' ]
labels:
namespace: 'default'
- job_name: 'openimserver-openim-rpc-conversation'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${CONVERSATION_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${CONVERSATION_PROM_PORT}' ]
labels:
namespace: 'default'
- job_name: 'openimserver-openim-rpc-friend'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${FRIEND_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${FRIEND_PROM_PORT}' ]
labels:
namespace: 'default'
- job_name: 'openimserver-openim-rpc-group'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${GROUP_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${GROUP_PROM_PORT}' ]
labels:
namespace: 'default'
- job_name: 'openimserver-openim-rpc-msg'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${MESSAGE_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${MESSAGE_PROM_PORT}' ]
labels:
namespace: 'default'
- job_name: 'openimserver-openim-rpc-third'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${THIRD_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${THIRD_PROM_PORT}' ]
labels:
namespace: 'default'
- job_name: 'openimserver-openim-rpc-user'
static_configs:
- - targets: [ '${OPENIM_SERVER_ADDRESS}:${USER_PROM_PORT}' ]
+ - targets: [ '${DOCKER_BRIDGE_GATEWAY}:${USER_PROM_PORT}' ]
labels:
namespace: 'default'
From de451d4cea1d961464318b7b2cd0ee657bd8b37d Mon Sep 17 00:00:00 2001
From: Gordon <46924906+FGadvancer@users.noreply.github.com>
Date: Mon, 25 Dec 2023 16:30:18 +0800
Subject: [PATCH 024/110] fix: online notifications do not push to herself.
(#1534)
* fix: online notifications do not push to herself.
* fix: online notifications do not push to herself.
* fix: online notifications do not push to herself.
---
internal/push/push_handler.go | 11 ++++++-----
internal/push/push_rpc_server.go | 3 +--
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/internal/push/push_handler.go b/internal/push/push_handler.go
index a1a9ff08e..c91206ecc 100644
--- a/internal/push/push_handler.go
+++ b/internal/push/push_handler.go
@@ -67,13 +67,14 @@ func (c *ConsumerHandler) handleMs2PsChat(ctx context.Context, msg []byte) {
case constant.SuperGroupChatType:
err = c.pusher.Push2SuperGroup(ctx, pbData.MsgData.GroupID, pbData.MsgData)
default:
- var pushUserIDs []string
- if pbData.MsgData.SendID != pbData.MsgData.RecvID {
- pushUserIDs = []string{pbData.MsgData.SendID, pbData.MsgData.RecvID}
+ var pushUserIDList []string
+ isSenderSync := utils.GetSwitchFromOptions(pbData.MsgData.Options, constant.IsSenderSync)
+ if !isSenderSync || pbData.MsgData.SendID == pbData.MsgData.RecvID {
+ pushUserIDList = append(pushUserIDList, pbData.MsgData.RecvID)
} else {
- pushUserIDs = []string{pbData.MsgData.SendID}
+ pushUserIDList = append(pushUserIDList, pbData.MsgData.RecvID, pbData.MsgData.SendID)
}
- err = c.pusher.Push2User(ctx, pushUserIDs, pbData.MsgData)
+ err = c.pusher.Push2User(ctx, pushUserIDList, pbData.MsgData)
}
if err != nil {
if err == errNoOfflinePusher {
diff --git a/internal/push/push_rpc_server.go b/internal/push/push_rpc_server.go
index 188ddc0e1..9e66f8f73 100644
--- a/internal/push/push_rpc_server.go
+++ b/internal/push/push_rpc_server.go
@@ -16,9 +16,8 @@ package push
import (
"context"
- "sync"
-
"github.com/OpenIMSDK/tools/utils"
+ "sync"
"google.golang.org/grpc"
From 7389639f174441ff66414e2e541e52aa138ba67f Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Tue, 26 Dec 2023 10:15:15 +0800
Subject: [PATCH 025/110] feat: add the notificationAccount (#1602)
* feat: add notification API
* fix: fix the script
* fix: fix the error
---
deployments/templates/openim.yaml | 8 ++
docs/contrib/environment.md | 74 ++++++++---------
go.mod | 2 +
go.sum | 4 +-
internal/api/friend.go | 3 -
internal/api/msg.go | 5 +-
internal/api/route.go | 6 +-
internal/api/user.go | 15 +++-
internal/rpc/friend/friend.go | 11 ++-
internal/rpc/user/user.go | 128 ++++++++++++++++++++++++++++++
pkg/apistruct/msg.go | 2 +-
pkg/authverify/token.go | 9 +++
pkg/common/config/config.go | 5 ++
pkg/common/db/controller/user.go | 6 ++
pkg/common/http/http_client.go | 2 +-
pkg/rpcclient/user.go | 7 ++
scripts/check-all.sh | 2 +-
scripts/install/environment.sh | 2 +
18 files changed, 238 insertions(+), 53 deletions(-)
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index ed5dc4fe1..cbb4a8c6e 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -247,6 +247,14 @@ manager:
userID: [ "${MANAGER_USERID_1}", "${MANAGER_USERID_2}", "${MANAGER_USERID_3}" ]
nickname: [ "${NICKNAME_1}", "${NICKNAME_2}", "${NICKNAME_3}" ]
+# chatAdmin, use for send notification
+#
+# Built-in app system notification account ID
+# Built-in app system notification account nickname
+im-admin:
+ userID: [ "${IM_ADMIN_USERID}" ]
+ nickname: [ "${IM_ADMIN_NAME}" ]
+
# Multi-platform login policy
# For each platform(Android, iOS, Windows, Mac, web), only one can be online at a time
multiLoginPolicy: ${MULTILOGIN_POLICY}
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index 310c2df6a..e52d57235 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -453,43 +453,45 @@ This section involves configuring the log settings, including storage location,
This section involves setting up additional configuration variables for Websocket, Push Notifications, and Chat.
-| Parameter | Example Value | Description |
-|-------------------------|-------------------|------------------------------------|
-| WEBSOCKET_MAX_CONN_NUM | "100000" | Maximum Websocket connections |
-| WEBSOCKET_MAX_MSG_LEN | "4096" | Maximum Websocket message length |
-| WEBSOCKET_TIMEOUT | "10" | Websocket timeout |
-| PUSH_ENABLE | "getui" | Push notification enable status |
-| GETUI_PUSH_URL | [Generated URL] | GeTui Push Notification URL |
-| GETUI_MASTER_SECRET | [User Defined] | GeTui Master Secret |
-| GETUI_APP_KEY | [User Defined] | GeTui Application Key |
-| GETUI_INTENT | [User Defined] | GeTui Push Intent |
-| GETUI_CHANNEL_ID | [User Defined] | GeTui Channel ID |
-| GETUI_CHANNEL_NAME | [User Defined] | GeTui Channel Name |
-| FCM_SERVICE_ACCOUNT | "x.json" | FCM Service Account |
-| JPNS_APP_KEY | [User Defined] | JPNS Application Key |
-| JPNS_MASTER_SECRET | [User Defined] | JPNS Master Secret |
-| JPNS_PUSH_URL | [User Defined] | JPNS Push Notification URL |
-| JPNS_PUSH_INTENT | [User Defined] | JPNS Push Intent |
-| MANAGER_USERID_1 | "openIM123456" | Administrator ID 1 |
-| MANAGER_USERID_2 | "openIM654321" | Administrator ID 2 |
-| MANAGER_USERID_3 | "openIMAdmin" | Administrator ID 3 |
-| NICKNAME_1 | "system1" | Nickname 1 |
-| NICKNAME_2 | "system2" | Nickname 2 |
-| NICKNAME_3 | "system3" | Nickname 3 |
-| MULTILOGIN_POLICY | "1" | Multi-login Policy |
-| CHAT_PERSISTENCE_MYSQL | "true" | Chat Persistence in MySQL |
-| MSG_CACHE_TIMEOUT | "86400" | Message Cache Timeout |
-| GROUP_MSG_READ_RECEIPT | "true" | Group Message Read Receipt Enable |
+| Parameter | Example Value | Description |
+|-------------------------|-------------------|----------------------------------|
+| WEBSOCKET_MAX_CONN_NUM | "100000" | Maximum Websocket connections |
+| WEBSOCKET_MAX_MSG_LEN | "4096" | Maximum Websocket message length |
+| WEBSOCKET_TIMEOUT | "10" | Websocket timeout |
+| PUSH_ENABLE | "getui" | Push notification enable status |
+| GETUI_PUSH_URL | [Generated URL] | GeTui Push Notification URL |
+| GETUI_MASTER_SECRET | [User Defined] | GeTui Master Secret |
+| GETUI_APP_KEY | [User Defined] | GeTui Application Key |
+| GETUI_INTENT | [User Defined] | GeTui Push Intent |
+| GETUI_CHANNEL_ID | [User Defined] | GeTui Channel ID |
+| GETUI_CHANNEL_NAME | [User Defined] | GeTui Channel Name |
+| FCM_SERVICE_ACCOUNT | "x.json" | FCM Service Account |
+| JPNS_APP_KEY | [User Defined] | JPNS Application Key |
+| JPNS_MASTER_SECRET | [User Defined] | JPNS Master Secret |
+| JPNS_PUSH_URL | [User Defined] | JPNS Push Notification URL |
+| JPNS_PUSH_INTENT | [User Defined] | JPNS Push Intent |
+| MANAGER_USERID_1 | "openIM123456" | Administrator ID 1 |
+| MANAGER_USERID_2 | "openIM654321" | Administrator ID 2 |
+| MANAGER_USERID_3 | "openIMAdmin" | Administrator ID 3 |
+| NICKNAME_1 | "system1" | Nickname 1 |
+| NICKNAME_2 | "system2" | Nickname 2 |
+| NICKNAME_3 | "system3" | Nickname 3 |
+| IM_ADMIN_USERID | "imAdmin" | IM Administrator ID |
+| IM_ADMIN_NAME | "imAdmin" | IM Administrator Nickname |
+| MULTILOGIN_POLICY | "1" | Multi-login Policy |
+| CHAT_PERSISTENCE_MYSQL | "true" | Chat Persistence in MySQL |
+| MSG_CACHE_TIMEOUT | "86400" | Message Cache Timeout |
+| GROUP_MSG_READ_RECEIPT | "true" | Group Message Read Receipt Enable |
| SINGLE_MSG_READ_RECEIPT | "true" | Single Message Read Receipt Enable |
-| RETAIN_CHAT_RECORDS | "365" | Retain Chat Records (in days) |
-| CHAT_RECORDS_CLEAR_TIME | [Cron Expression] | Chat Records Clear Time |
-| MSG_DESTRUCT_TIME | [Cron Expression] | Message Destruct Time |
-| SECRET | "${PASSWORD}" | Secret Key |
-| TOKEN_EXPIRE | "90" | Token Expiry Time |
-| FRIEND_VERIFY | "false" | Friend Verification Enable |
-| IOS_PUSH_SOUND | "xxx" | iOS |
-| CALLBACK_ENABLE | "false" | Enable callback |
-| CALLBACK_TIMEOUT | "5" | Maximum timeout for callback call |
+| RETAIN_CHAT_RECORDS | "365" | Retain Chat Records (in days) |
+| CHAT_RECORDS_CLEAR_TIME | [Cron Expression] | Chat Records Clear Time |
+| MSG_DESTRUCT_TIME | [Cron Expression] | Message Destruct Time |
+| SECRET | "${PASSWORD}" | Secret Key |
+| TOKEN_EXPIRE | "90" | Token Expiry Time |
+| FRIEND_VERIFY | "false" | Friend Verification Enable |
+| IOS_PUSH_SOUND | "xxx" | iOS |
+| CALLBACK_ENABLE | "false" | Enable callback |
+| CALLBACK_TIMEOUT | "5" | Maximum timeout for callback call |
| CALLBACK_FAILED_CONTINUE| "true" | fails to continue to the next step |
### 2.20. Prometheus Configuration
diff --git a/go.mod b/go.mod
index 9a9cde30e..fb5be5b90 100644
--- a/go.mod
+++ b/go.mod
@@ -156,3 +156,5 @@ require (
golang.org/x/crypto v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
+
+replace github.com/OpenIMSDK/protocol v0.0.36 => github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5
diff --git a/go.sum b/go.sum
index 61323c57b..cde33c7cd 100644
--- a/go.sum
+++ b/go.sum
@@ -18,8 +18,6 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.36 h1:UJnFsr1A4RrNeHMNDVS/1nvXWFoGM43dcXpZeJiIZ+0=
-github.com/OpenIMSDK/protocol v0.0.36/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
@@ -227,6 +225,8 @@ github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205Ah
github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w=
github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w=
+github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5 h1:nmrJmAgQsCAxKgw109kaTcBV4rMWDRvqOson0ehw708=
+github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
diff --git a/internal/api/friend.go b/internal/api/friend.go
index 58e7398dd..23f337a9f 100644
--- a/internal/api/friend.go
+++ b/internal/api/friend.go
@@ -92,6 +92,3 @@ func (o *FriendApi) GetFriendIDs(c *gin.Context) {
func (o *FriendApi) GetSpecifiedFriendsInfo(c *gin.Context) {
a2r.Call(friend.FriendClient.GetSpecifiedFriendsInfo, o.Client, c)
}
-func (o *FriendApi) SetPinFriends(c *gin.Context) {
- a2r.Call(friend.FriendClient.PinFriends, o.Client, c)
-}
diff --git a/internal/api/msg.go b/internal/api/msg.go
index 664ee505a..b6bfcebb6 100644
--- a/internal/api/msg.go
+++ b/internal/api/msg.go
@@ -169,9 +169,8 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM
case constant.OANotification:
data = apistruct.OANotificationElem{}
req.SessionType = constant.NotificationChatType
- if !authverify.IsManagerUserID(req.SendID) {
- return nil, errs.ErrNoPermission.
- Wrap("only app manager can as sender send OANotificationElem")
+ if err = m.userRpcClient.GetNotificationByID(c, req.SendID); err != nil {
+ return nil, err
}
default:
return nil, errs.ErrArgs.WithDetail("not support err contentType")
diff --git a/internal/api/route.go b/internal/api/route.go
index 8bfea5cca..05aa6ac92 100644
--- a/internal/api/route.go
+++ b/internal/api/route.go
@@ -82,6 +82,10 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
userRouterGroup.POST("/process_user_command_delete", ParseToken, u.ProcessUserCommandDelete)
userRouterGroup.POST("/process_user_command_update", ParseToken, u.ProcessUserCommandUpdate)
userRouterGroup.POST("/process_user_command_get", ParseToken, u.ProcessUserCommandGet)
+
+ userRouterGroup.POST("/add_notification_account", ParseToken, u.AddNotificationAccount)
+ userRouterGroup.POST("/update_notification_account", ParseToken, u.UpdateNotificationAccountInfo)
+ userRouterGroup.POST("/search_notification_account", ParseToken, u.SearchNotificationAccount)
}
// friend routing group
friendRouterGroup := r.Group("/friend", ParseToken)
@@ -103,7 +107,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
friendRouterGroup.POST("/is_friend", f.IsFriend)
friendRouterGroup.POST("/get_friend_id", f.GetFriendIDs)
friendRouterGroup.POST("/get_specified_friends_info", f.GetSpecifiedFriendsInfo)
- friendRouterGroup.POST("/set_pin_friend", f.SetPinFriends)
+ //friendRouterGroup.POST("/set_pin_friend", f.SetPinFriends)
}
g := NewGroupApi(*groupRpc)
groupRouterGroup := r.Group("/group", ParseToken)
diff --git a/internal/api/user.go b/internal/api/user.go
index 8350d1711..cf68fb422 100644
--- a/internal/api/user.go
+++ b/internal/api/user.go
@@ -15,8 +15,6 @@
package api
import (
- "github.com/gin-gonic/gin"
-
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/msggateway"
"github.com/OpenIMSDK/protocol/user"
@@ -24,6 +22,7 @@ import (
"github.com/OpenIMSDK/tools/apiresp"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
+ "github.com/gin-gonic/gin"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
@@ -219,3 +218,15 @@ func (u *UserApi) ProcessUserCommandUpdate(c *gin.Context) {
func (u *UserApi) ProcessUserCommandGet(c *gin.Context) {
a2r.Call(user.UserClient.ProcessUserCommandGet, u.Client, c)
}
+
+func (u *UserApi) AddNotificationAccount(c *gin.Context) {
+ a2r.Call(user.UserClient.AddNotificationAccount, u.Client, c)
+}
+
+func (u *UserApi) UpdateNotificationAccountInfo(c *gin.Context) {
+ a2r.Call(user.UserClient.UpdateNotificationAccountInfo, u.Client, c)
+}
+
+func (u *UserApi) SearchNotificationAccount(c *gin.Context) {
+ a2r.Call(user.UserClient.SearchNotificationAccount, u.Client, c)
+}
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index 12203aa7e..97e53d197 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -53,6 +53,11 @@ type friendServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
+func (s *friendServer) UpdateFriends(ctx context.Context, req *pbfriend.UpdateFriendsReq) (*pbfriend.UpdateFriendsResp, error) {
+ //TODO implement me
+ panic("implement me")
+}
+
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
// Initialize MongoDB
mongo, err := unrelation.NewMongo()
@@ -438,8 +443,8 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien
}
func (s *friendServer) PinFriends(
ctx context.Context,
- req *pbfriend.PinFriendsReq,
-) (*pbfriend.PinFriendsResp, error) {
+ req *pbfriend.UpdateFriendsReq,
+) (*pbfriend.UpdateFriendsResp, error) {
if len(req.FriendUserIDs) == 0 {
return nil, errs.ErrArgs.Wrap("friendIDList is empty")
}
@@ -465,6 +470,6 @@ func (s *friendServer) PinFriends(
}
}
- resp := &pbfriend.PinFriendsResp{}
+ resp := &pbfriend.UpdateFriendsResp{}
return resp, nil
}
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 70e3aebe6..9bc56298f 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -17,6 +17,7 @@ package user
import (
"context"
"errors"
+ "math/rand"
"strings"
"time"
@@ -72,6 +73,12 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
for k, v := range config.Config.Manager.UserID {
users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.Manager.Nickname[k], AppMangerLevel: constant.AppAdmin})
}
+ if len(config.Config.IMAdmin.UserID) != len(config.Config.IMAdmin.Nickname) {
+ return errors.New("len(config.Config.AppNotificationAdmin.AppManagerUid) != len(config.Config.AppNotificationAdmin.Nickname)")
+ }
+ for k, v := range config.Config.IMAdmin.UserID {
+ users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.IMAdmin.Nickname[k], AppMangerLevel: constant.AppNotificationAdmin})
+ }
userDB, err := mgo.NewUserMongo(mongo.GetDatabase())
if err != nil {
return err
@@ -390,3 +397,124 @@ func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.Proc
// Return the response with the slice
return &pbuser.ProcessUserCommandGetResp{KVArray: commandInfoSlice}, nil
}
+
+func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.AddNotificationAccountReq) (*pbuser.AddNotificationAccountResp, error) {
+ if err := authverify.CheckIMAdmin(ctx); err != nil {
+ return nil, err
+ }
+
+ var userID string
+ for i := 0; i < 20; i++ {
+ userId := s.genUserID()
+ _, err := s.UserDatabase.FindWithError(ctx, []string{userId})
+ if err == nil {
+ continue
+ }
+ userID = userId
+ break
+ }
+ if userID == "" {
+ return nil, errs.ErrInternalServer.Wrap("gen user id failed")
+ }
+
+ user := &tablerelation.UserModel{
+ UserID: userID,
+ Nickname: req.NickName,
+ FaceURL: req.FaceURL,
+ CreateTime: time.Now(),
+ AppMangerLevel: constant.AppNotificationAdmin,
+ }
+ if err := s.UserDatabase.Create(ctx, []*tablerelation.UserModel{user}); err != nil {
+ return nil, err
+ }
+
+ return &pbuser.AddNotificationAccountResp{}, nil
+}
+
+func (s *userServer) UpdateNotificationAccountInfo(ctx context.Context, req *pbuser.UpdateNotificationAccountInfoReq) (*pbuser.UpdateNotificationAccountInfoResp, error) {
+ if err := authverify.CheckIMAdmin(ctx); err != nil {
+ return nil, err
+ }
+
+ if _, err := s.UserDatabase.FindWithError(ctx, []string{req.UserID}); err != nil {
+ return nil, errs.ErrArgs.Wrap()
+ }
+
+ user := map[string]interface{}{}
+
+ if req.NickName != "" {
+ user["nickname"] = req.NickName
+ }
+
+ if req.FaceURL != "" {
+ user["face_url"] = req.FaceURL
+ }
+
+ if err := s.UserDatabase.UpdateByMap(ctx, req.UserID, user); err != nil {
+ return nil, err
+ }
+
+ return &pbuser.UpdateNotificationAccountInfoResp{}, nil
+}
+
+func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.SearchNotificationAccountReq) (*pbuser.SearchNotificationAccountResp, error) {
+ if err := authverify.CheckIMAdmin(ctx); err != nil {
+ return nil, err
+ }
+
+ _, users, err := s.UserDatabase.Page(ctx, req.Pagination)
+ if err != nil {
+ return nil, err
+ }
+
+ var total int64
+ accounts := make([]*pbuser.NotificationAccountInfo, 0, len(users))
+ for _, v := range users {
+ if v.AppMangerLevel != constant.AppNotificationAdmin {
+ continue
+ }
+ temp := &pbuser.NotificationAccountInfo{
+ UserID: v.UserID,
+ FaceURL: v.FaceURL,
+ NickName: v.Nickname,
+ }
+ accounts = append(accounts, temp)
+ total += 1
+ }
+ return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts}, nil
+}
+
+func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) {
+ //TODO implement me
+ panic("implement me")
+}
+
+func (s *userServer) GetNotificationAccount(ctx context.Context, req *pbuser.GetNotificationAccountReq) (*pbuser.GetNotificationAccountResp, error) {
+ if req.UserID == "" {
+ return nil, errs.ErrArgs.Wrap("userID is empty")
+ }
+ user, err := s.UserDatabase.GetUserByID(ctx, req.UserID)
+ if err != nil {
+ return nil, errs.ErrUserIDNotFound.Wrap()
+ }
+ if user.AppMangerLevel == constant.AppAdmin || user.AppMangerLevel == constant.AppNotificationAdmin {
+ return &pbuser.GetNotificationAccountResp{}, nil
+ }
+
+ return nil, errs.ErrNoPermission.Wrap("notification messages cannot be sent for this ID")
+}
+
+func (s *userServer) genUserID() string {
+ const l = 10
+ data := make([]byte, l)
+ rand.Read(data)
+ chars := []byte("0123456789")
+ for i := 0; i < len(data); i++ {
+ if i == 0 {
+ data[i] = chars[1:][data[i]%9]
+ } else {
+ data[i] = chars[data[i]%10]
+ }
+ }
+ return string(data)
+}
diff --git a/pkg/apistruct/msg.go b/pkg/apistruct/msg.go
index 4b7bd1e6f..d23db9bf5 100644
--- a/pkg/apistruct/msg.go
+++ b/pkg/apistruct/msg.go
@@ -87,7 +87,7 @@ type OANotificationElem struct {
NotificationType int32 `mapstructure:"notificationType" json:"notificationType" validate:"required"`
Text string `mapstructure:"text" json:"text" validate:"required"`
Url string `mapstructure:"url" json:"url"`
- MixType int32 `mapstructure:"mixType" json:"mixType" validate:"required"`
+ MixType int32 `mapstructure:"mixType" json:"mixType"`
PictureElem *PictureElem `mapstructure:"pictureElem" json:"pictureElem"`
SoundElem *SoundElem `mapstructure:"soundElem" json:"soundElem"`
VideoElem *VideoElem `mapstructure:"videoElem" json:"videoElem"`
diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go
index fd01e8c5a..d9aa0dbb1 100644
--- a/pkg/authverify/token.go
+++ b/pkg/authverify/token.go
@@ -54,6 +54,15 @@ func CheckAdmin(ctx context.Context) error {
}
return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx)))
}
+func CheckIMAdmin(ctx context.Context) error {
+ if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID) {
+ return nil
+ }
+ if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) {
+ return nil
+ }
+ return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not CheckIMAdmin userID", mcontext.GetOpUserID(ctx)))
+}
func ParseRedisInterfaceToken(redisToken any) (*tokenverify.Claims, error) {
return tokenverify.GetClaimFromToken(string(redisToken.([]uint8)), Secret())
diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go
index 6da89fc8f..707601234 100644
--- a/pkg/common/config/config.go
+++ b/pkg/common/config/config.go
@@ -236,6 +236,11 @@ type configStruct struct {
Nickname []string `yaml:"nickname"`
} `yaml:"manager"`
+ IMAdmin struct {
+ UserID []string `yaml:"userID"`
+ Nickname []string `yaml:"nickname"`
+ } `yaml:"im-admin"`
+
MultiLoginPolicy int `yaml:"multiLoginPolicy"`
ChatPersistenceMysql bool `yaml:"chatPersistenceMysql"`
MsgCacheTimeout int `yaml:"msgCacheTimeout"`
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index 433fb7ad3..2fafcf266 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -50,6 +50,8 @@ type UserDatabase interface {
IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
// GetAllUserID Get all user IDs
GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error)
+ // Get user by userID
+ GetUserByID(ctx context.Context, userID string) (user *relation.UserModel, err error)
// InitOnce Inside the function, first query whether it exists in the db, if it exists, do nothing; if it does not exist, insert it
InitOnce(ctx context.Context, users []*relation.UserModel) (err error)
// CountTotal Get the total number of users
@@ -183,6 +185,10 @@ func (u *userDatabase) GetAllUserID(ctx context.Context, pagination pagination.P
return u.userDB.GetAllUserID(ctx, pagination)
}
+func (u *userDatabase) GetUserByID(ctx context.Context, userID string) (user *relation.UserModel, err error) {
+ return u.userDB.Take(ctx, userID)
+}
+
// CountTotal Get the total number of users.
func (u *userDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
return u.userDB.CountTotal(ctx, before)
diff --git a/pkg/common/http/http_client.go b/pkg/common/http/http_client.go
index baad60459..a80d1c9a4 100644
--- a/pkg/common/http/http_client.go
+++ b/pkg/common/http/http_client.go
@@ -112,7 +112,6 @@ func callBackPostReturn(ctx context.Context, url, command string, input interfac
//v.Set(constant.CallbackCommand, command)
//url = url + "/" + v.Encode()
url = url + "/" + command
-
b, err := Post(ctx, url, nil, input, callbackConfig.CallbackTimeOut)
if err != nil {
if callbackConfig.CallbackFailedContinue != nil && *callbackConfig.CallbackFailedContinue {
@@ -121,6 +120,7 @@ func callBackPostReturn(ctx context.Context, url, command string, input interfac
}
return errs.ErrNetwork.Wrap(err.Error())
}
+ defer log.ZDebug(ctx, "callback", "data", string(b))
if err = json.Unmarshal(b, output); err != nil {
if callbackConfig.CallbackFailedContinue != nil && *callbackConfig.CallbackFailedContinue {
diff --git a/pkg/rpcclient/user.go b/pkg/rpcclient/user.go
index c40d95727..de633ee30 100644
--- a/pkg/rpcclient/user.go
+++ b/pkg/rpcclient/user.go
@@ -179,3 +179,10 @@ func (u *UserRpcClient) SetUserStatus(ctx context.Context, userID string, status
})
return err
}
+
+func (u *UserRpcClient) GetNotificationByID(ctx context.Context, userID string) error {
+ _, err := u.Client.GetNotificationAccount(ctx, &user.GetNotificationAccountReq{
+ UserID: userID,
+ })
+ return err
+}
diff --git a/scripts/check-all.sh b/scripts/check-all.sh
index efaa2ccb7..e1e07bd65 100755
--- a/scripts/check-all.sh
+++ b/scripts/check-all.sh
@@ -89,4 +89,4 @@ else
echo "++++ Check all openim service ports successfully !"
fi
-set -e
+set -e
\ No newline at end of file
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index 3dd062af6..feb36c3c1 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -353,6 +353,8 @@ def "MANAGER_USERID_3" "openIMAdmin" # 管理员ID 3
def "NICKNAME_1" "system1" # 昵称1
def "NICKNAME_2" "system2" # 昵称2
def "NICKNAME_3" "system3" # 昵称3
+def "IM_ADMIN_USERID" "imAdmin" # IM管理员ID
+def "IM_ADMIN_NAME" "imAdmin" # IM管理员昵称
def "MULTILOGIN_POLICY" "1" # 多登录策略
def "CHAT_PERSISTENCE_MYSQL" "true" # 聊天持久化MySQL
def "MSG_CACHE_TIMEOUT" "86400" # 消息缓存超时
From 47dd6b17f61736686dabf3798888aaa7060d75a8 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Tue, 26 Dec 2023 12:16:55 +0800
Subject: [PATCH 026/110] Update openimci.yml (#1610)
* Update openimci.yml
* Update Makefile
---
.github/workflows/openimci.yml | 8 +++++++-
Makefile | 2 +-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index d65c0dc89..d8e988f0b 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -207,6 +207,12 @@ jobs:
sudo make check || \
(echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
+ - name: Restart Services and Print Logs for Ubuntu
+ if: runner.os == 'Linux'
+ run: |
+ sudo make restart
+ sudo make check
+
# - name: Build, Start, Check Services and Print Logs for macOS
# if: runner.os == 'macOS'
# run: |
@@ -239,4 +245,4 @@ jobs:
- name: Test Docker Build
run: |
sudo make init
- sudo make image
\ No newline at end of file
+ sudo make image
diff --git a/Makefile b/Makefile
index 1941bde6c..4faf1c21d 100644
--- a/Makefile
+++ b/Makefile
@@ -95,7 +95,7 @@ stop:
## restart: Restart openim (make init configuration file is initialized) ✨
.PHONY: restart
-restart: clean stop build init start check
+restart: clean stop build start check
## multiarch: Build binaries for multiple platforms. See option PLATFORMS. ✨
.PHONY: multiarch
From cd1235fb32072af665808d3bffd6f782a6643dd3 Mon Sep 17 00:00:00 2001
From: chao <48119764+withchao@users.noreply.github.com>
Date: Tue, 26 Dec 2023 17:29:42 +0800
Subject: [PATCH 027/110] feat: s3 FormData upload (#1614)
* upgrade package and rtc convert
* upgrade package and rtc convert
* upgrade package and rtc convert
* upgrade package and rtc convert
* friend user
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
---
go.mod | 8 +-
go.sum | 8 +-
internal/api/route.go | 2 +
internal/api/third.go | 8 ++
internal/rpc/friend/friend.go | 3 +-
internal/rpc/third/s3.go | 113 ++++++++++++++++++++++
internal/rpc/third/third.go | 10 --
internal/rpc/third/tool.go | 3 +
internal/rpc/user/user.go | 9 +-
pkg/common/cmd/root.go | 2 +-
pkg/common/db/controller/s3.go | 10 ++
pkg/common/db/s3/cont/consts.go | 1 +
pkg/common/db/s3/cont/controller.go | 4 +
pkg/common/db/s3/cos/cos.go | 69 +++++++++++++
pkg/common/db/s3/minio/minio.go | 50 ++++++++++
pkg/common/db/s3/oss/oss.go | 49 ++++++++++
pkg/common/db/s3/s3.go | 11 +++
pkg/common/ginprometheus/ginprometheus.go | 2 +-
18 files changed, 334 insertions(+), 28 deletions(-)
diff --git a/go.mod b/go.mod
index fb5be5b90..a753cae51 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,8 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
+ github.com/OpenIMSDK/protocol v0.0.39
+ github.com/OpenIMSDK/tools v0.0.21
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
@@ -33,8 +35,6 @@ require github.com/google/uuid v1.3.1
require (
github.com/IBM/sarama v1.41.3
- github.com/OpenIMSDK/protocol v0.0.36
- github.com/OpenIMSDK/tools v0.0.21
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/go-redis/redis v6.15.9+incompatible
github.com/redis/go-redis/v9 v9.2.1
@@ -133,7 +133,7 @@ require (
golang.org/x/oauth2 v0.13.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.13.0 // indirect
- golang.org/x/time v0.3.0 // indirect
+ golang.org/x/time v0.5.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect
@@ -156,5 +156,3 @@ require (
golang.org/x/crypto v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
-
-replace github.com/OpenIMSDK/protocol v0.0.36 => github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5
diff --git a/go.sum b/go.sum
index cde33c7cd..a4609f6f2 100644
--- a/go.sum
+++ b/go.sum
@@ -18,6 +18,8 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
+github.com/OpenIMSDK/protocol v0.0.39 h1:DfvFcNGBcfj2vtT7W3uw4U/ipnI7NecTzQdlSYGuQz8=
+github.com/OpenIMSDK/protocol v0.0.39/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
@@ -225,8 +227,6 @@ github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205Ah
github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w=
github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w=
-github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5 h1:nmrJmAgQsCAxKgw109kaTcBV4rMWDRvqOson0ehw708=
-github.com/luhaoling/protocol v0.0.0-20231222100538-d625562d53d5/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
@@ -453,8 +453,8 @@ 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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.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/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
diff --git a/internal/api/route.go b/internal/api/route.go
index 05aa6ac92..8fb372587 100644
--- a/internal/api/route.go
+++ b/internal/api/route.go
@@ -171,6 +171,8 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
objectGroup.POST("/auth_sign", t.AuthSign)
objectGroup.POST("/complete_multipart_upload", t.CompleteMultipartUpload)
objectGroup.POST("/access_url", t.AccessURL)
+ objectGroup.POST("/initiate_form_data", t.InitiateFormData)
+ objectGroup.POST("/complete_form_data", t.CompleteFormData)
objectGroup.GET("/*name", t.ObjectRedirect)
}
// Message
diff --git a/internal/api/third.go b/internal/api/third.go
index 5191903da..37ec55098 100644
--- a/internal/api/third.go
+++ b/internal/api/third.go
@@ -71,6 +71,14 @@ func (o *ThirdApi) AccessURL(c *gin.Context) {
a2r.Call(third.ThirdClient.AccessURL, o.Client, c)
}
+func (o *ThirdApi) InitiateFormData(c *gin.Context) {
+ a2r.Call(third.ThirdClient.InitiateFormData, o.Client, c)
+}
+
+func (o *ThirdApi) CompleteFormData(c *gin.Context) {
+ a2r.Call(third.ThirdClient.CompleteFormData, o.Client, c)
+}
+
func (o *ThirdApi) ObjectRedirect(c *gin.Context) {
name := c.Param("name")
if name == "" {
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index 97e53d197..c40b566f3 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -54,8 +54,7 @@ type friendServer struct {
}
func (s *friendServer) UpdateFriends(ctx context.Context, req *pbfriend.UpdateFriendsReq) (*pbfriend.UpdateFriendsResp, error) {
- //TODO implement me
- panic("implement me")
+ return nil, errs.ErrInternalServer.Wrap("not implemented")
}
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
diff --git a/internal/rpc/third/s3.go b/internal/rpc/third/s3.go
index ca826e805..2c230f258 100644
--- a/internal/rpc/third/s3.go
+++ b/internal/rpc/third/s3.go
@@ -16,6 +16,12 @@ package third
import (
"context"
+ "encoding/base64"
+ "encoding/hex"
+ "encoding/json"
+ "github.com/google/uuid"
+ "github.com/openimsdk/open-im-server/v3/pkg/authverify"
+ "path"
"strconv"
"time"
@@ -179,6 +185,113 @@ func (t *thirdServer) AccessURL(ctx context.Context, req *third.AccessURLReq) (*
}, nil
}
+func (t *thirdServer) InitiateFormData(ctx context.Context, req *third.InitiateFormDataReq) (*third.InitiateFormDataResp, error) {
+ if req.Name == "" {
+ return nil, errs.ErrArgs.Wrap("name is empty")
+ }
+ if req.Size <= 0 {
+ return nil, errs.ErrArgs.Wrap("size must be greater than 0")
+ }
+ if err := checkUploadName(ctx, req.Name); err != nil {
+ return nil, err
+ }
+ var duration time.Duration
+ opUserID := mcontext.GetOpUserID(ctx)
+ var key string
+ if authverify.IsManagerUserID(opUserID) {
+ if req.Millisecond <= 0 {
+ duration = time.Minute * 10
+ } else {
+ duration = time.Millisecond * time.Duration(req.Millisecond)
+ }
+ if req.Absolute {
+ key = req.Name
+ }
+ } else {
+ duration = time.Minute * 10
+ }
+ uid, err := uuid.NewRandom()
+ if err != nil {
+ return nil, err
+ }
+ if key == "" {
+ date := time.Now().Format("20060102")
+ key = path.Join(cont.DirectPath, date, opUserID, hex.EncodeToString(uid[:])+path.Ext(req.Name))
+ }
+ mate := FormDataMate{
+ Name: req.Name,
+ Size: req.Size,
+ ContentType: req.ContentType,
+ Group: req.Group,
+ Key: key,
+ }
+ mateData, err := json.Marshal(&mate)
+ if err != nil {
+ return nil, err
+ }
+ resp, err := t.s3dataBase.FormData(ctx, key, req.Size, req.ContentType, duration)
+ if err != nil {
+ return nil, err
+ }
+ return &third.InitiateFormDataResp{
+ Id: base64.RawStdEncoding.EncodeToString(mateData),
+ Url: resp.URL,
+ File: resp.File,
+ Header: toPbMapArray(resp.Header),
+ FormData: resp.FormData,
+ Expires: resp.Expires.UnixMilli(),
+ SuccessCodes: utils.Slice(resp.SuccessCodes, func(code int) int32 {
+ return int32(code)
+ }),
+ }, nil
+}
+
+func (t *thirdServer) CompleteFormData(ctx context.Context, req *third.CompleteFormDataReq) (*third.CompleteFormDataResp, error) {
+ if req.Id == "" {
+ return nil, errs.ErrArgs.Wrap("id is empty")
+ }
+ data, err := base64.RawStdEncoding.DecodeString(req.Id)
+ if err != nil {
+ return nil, errs.ErrArgs.Wrap("invalid id " + err.Error())
+ }
+ var mate FormDataMate
+ if err := json.Unmarshal(data, &mate); err != nil {
+ return nil, errs.ErrArgs.Wrap("invalid id " + err.Error())
+ }
+ if err := checkUploadName(ctx, mate.Name); err != nil {
+ return nil, err
+ }
+ info, err := t.s3dataBase.StatObject(ctx, mate.Key)
+ if err != nil {
+ return nil, err
+ }
+ if info.Size > 0 && info.Size != mate.Size {
+ return nil, errs.ErrData.Wrap("file size mismatch")
+ }
+ obj := &relation.ObjectModel{
+ Name: mate.Name,
+ UserID: mcontext.GetOpUserID(ctx),
+ Hash: "etag_" + info.ETag,
+ Key: info.Key,
+ Size: info.Size,
+ ContentType: mate.ContentType,
+ Group: mate.Group,
+ CreateTime: time.Now(),
+ }
+ if err := t.s3dataBase.SetObject(ctx, obj); err != nil {
+ return nil, err
+ }
+ return &third.CompleteFormDataResp{Url: t.apiAddress(mate.Name)}, nil
+}
+
func (t *thirdServer) apiAddress(name string) string {
return t.apiURL + name
}
+
+type FormDataMate struct {
+ Name string `json:"name"`
+ Size int64 `json:"size"`
+ ContentType string `json:"contentType"`
+ Group string `json:"group"`
+ Key string `json:"key"`
+}
diff --git a/internal/rpc/third/third.go b/internal/rpc/third/third.go
index 35df3f925..7a63d3526 100644
--- a/internal/rpc/third/third.go
+++ b/internal/rpc/third/third.go
@@ -101,16 +101,6 @@ type thirdServer struct {
defaultExpire time.Duration
}
-func (t *thirdServer) InitiateFormData(ctx context.Context, req *third.InitiateFormDataReq) (*third.InitiateFormDataResp, error) {
- //TODO implement me
- panic("implement me")
-}
-
-func (t *thirdServer) CompleteFormData(ctx context.Context, req *third.CompleteFormDataReq) (*third.CompleteFormDataResp, error) {
- //TODO implement me
- panic("implement me")
-}
-
func (t *thirdServer) FcmUpdateToken(ctx context.Context, req *third.FcmUpdateTokenReq) (resp *third.FcmUpdateTokenResp, err error) {
err = t.thirdDatabase.FcmUpdateToken(ctx, req.Account, int(req.PlatformID), req.FcmToken, req.ExpireTime)
if err != nil {
diff --git a/internal/rpc/third/tool.go b/internal/rpc/third/tool.go
index a65d882dd..a6c16ff9d 100644
--- a/internal/rpc/third/tool.go
+++ b/internal/rpc/third/tool.go
@@ -29,6 +29,9 @@ import (
)
func toPbMapArray(m map[string][]string) []*third.KeyValues {
+ if len(m) == 0 {
+ return nil
+ }
res := make([]*third.KeyValues, 0, len(m))
for key := range m {
res = append(res, &third.KeyValues{
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 9bc56298f..b5ad186a5 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -57,6 +57,10 @@ type userServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
+func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) {
+ return nil, errs.ErrInternalServer.Wrap("not implemented")
+}
+
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis()
if err != nil {
@@ -484,11 +488,6 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.
return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts}, nil
}
-func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) {
- //TODO implement me
- panic("implement me")
-}
-
func (s *userServer) GetNotificationAccount(ctx context.Context, req *pbuser.GetNotificationAccountReq) (*pbuser.GetNotificationAccountResp, error) {
if req.UserID == "" {
return nil, errs.ErrArgs.Wrap("userID is empty")
diff --git a/pkg/common/cmd/root.go b/pkg/common/cmd/root.go
index 0bc308e07..66bec61a7 100644
--- a/pkg/common/cmd/root.go
+++ b/pkg/common/cmd/root.go
@@ -45,7 +45,7 @@ type CmdOpts struct {
func WithCronTaskLogName() func(*CmdOpts) {
return func(opts *CmdOpts) {
- opts.loggerPrefixName = "OpenIM.CronTask.log.all"
+ opts.loggerPrefixName = "openim.crontask.log.all"
}
}
diff --git a/pkg/common/db/controller/s3.go b/pkg/common/db/controller/s3.go
index 6916a7d30..95505de41 100644
--- a/pkg/common/db/controller/s3.go
+++ b/pkg/common/db/controller/s3.go
@@ -35,6 +35,8 @@ type S3Database interface {
CompleteMultipartUpload(ctx context.Context, uploadID string, parts []string) (*cont.UploadResult, 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
+ StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error)
+ FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error)
}
func NewS3Database(rdb redis.UniversalClient, s3 s3.Interface, obj relation.ObjectInfoModelInterface) S3Database {
@@ -100,3 +102,11 @@ func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Dur
}
return expireTime, rawURL, nil
}
+
+func (s *s3Database) StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error) {
+ return s.s3.StatObject(ctx, name)
+}
+
+func (s *s3Database) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) {
+ return s.s3.FormData(ctx, name, size, contentType, duration)
+}
diff --git a/pkg/common/db/s3/cont/consts.go b/pkg/common/db/s3/cont/consts.go
index 1a0467ce5..a01a8312c 100644
--- a/pkg/common/db/s3/cont/consts.go
+++ b/pkg/common/db/s3/cont/consts.go
@@ -17,6 +17,7 @@ package cont
const (
hashPath = "openim/data/hash/"
tempPath = "openim/temp/"
+ DirectPath = "openim/direct"
UploadTypeMultipart = 1 // 分片上传
UploadTypePresigned = 2 // 预签名上传
partSeparator = ","
diff --git a/pkg/common/db/s3/cont/controller.go b/pkg/common/db/s3/cont/controller.go
index 1bf1a4b12..82c27c1f2 100644
--- a/pkg/common/db/s3/cont/controller.go
+++ b/pkg/common/db/s3/cont/controller.go
@@ -279,3 +279,7 @@ func (c *Controller) AccessURL(ctx context.Context, name string, expire time.Dur
}
return c.impl.AccessURL(ctx, name, expire, opt)
}
+
+func (c *Controller) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) {
+ return c.impl.FormData(ctx, name, size, contentType, duration)
+}
diff --git a/pkg/common/db/s3/cos/cos.go b/pkg/common/db/s3/cos/cos.go
index 7add88487..7d2c0befe 100644
--- a/pkg/common/db/s3/cos/cos.go
+++ b/pkg/common/db/s3/cos/cos.go
@@ -16,6 +16,11 @@ package cos
import (
"context"
+ "crypto/hmac"
+ "crypto/sha1"
+ "encoding/base64"
+ "encoding/hex"
+ "encoding/json"
"errors"
"fmt"
"net/http"
@@ -44,6 +49,8 @@ const (
imageWebp = "webp"
)
+const successCode = http.StatusOK
+
const (
videoSnapshotImagePng = "png"
videoSnapshotImageJpg = "jpg"
@@ -326,3 +333,65 @@ func (c *Cos) getPresignedURL(ctx context.Context, name string, expire time.Dura
}
return c.client.Object.GetObjectURL(name), nil
}
+
+func (c *Cos) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) {
+ // https://cloud.tencent.com/document/product/436/14690
+ now := time.Now()
+ expiration := now.Add(duration)
+ keyTime := fmt.Sprintf("%d;%d", now.Unix(), expiration.Unix())
+ conditions := []any{
+ map[string]string{"q-sign-algorithm": "sha1"},
+ map[string]string{"q-ak": c.credential.SecretID},
+ map[string]string{"q-sign-time": keyTime},
+ map[string]string{"key": name},
+ }
+ if contentType != "" {
+ conditions = append(conditions, map[string]string{"Content-Type": contentType})
+ }
+ policy := map[string]any{
+ "expiration": expiration.Format("2006-01-02T15:04:05.000Z"),
+ "conditions": conditions,
+ }
+ policyJson, err := json.Marshal(policy)
+ if err != nil {
+ return nil, err
+ }
+ signKey := hmacSha1val(c.credential.SecretKey, keyTime)
+ strToSign := sha1val(string(policyJson))
+ signature := hmacSha1val(signKey, strToSign)
+
+ fd := &s3.FormData{
+ URL: c.client.BaseURL.BucketURL.String(),
+ File: "file",
+ Expires: expiration,
+ FormData: map[string]string{
+ "policy": base64.StdEncoding.EncodeToString(policyJson),
+ "q-sign-algorithm": "sha1",
+ "q-ak": c.credential.SecretID,
+ "q-key-time": keyTime,
+ "q-signature": signature,
+ "key": name,
+ "success_action_status": strconv.Itoa(successCode),
+ },
+ SuccessCodes: []int{successCode},
+ }
+ if contentType != "" {
+ fd.FormData["Content-Type"] = contentType
+ }
+ if c.credential.SessionToken != "" {
+ fd.FormData["x-cos-security-token"] = c.credential.SessionToken
+ }
+ return fd, nil
+}
+
+func hmacSha1val(key, msg string) string {
+ v := hmac.New(sha1.New, []byte(key))
+ v.Write([]byte(msg))
+ return hex.EncodeToString(v.Sum(nil))
+}
+
+func sha1val(msg string) string {
+ sha1Hash := sha1.New()
+ sha1Hash.Write([]byte(msg))
+ return hex.EncodeToString(sha1Hash.Sum(nil))
+}
diff --git a/pkg/common/db/s3/minio/minio.go b/pkg/common/db/s3/minio/minio.go
index be49e2faa..7dfe35b51 100644
--- a/pkg/common/db/s3/minio/minio.go
+++ b/pkg/common/db/s3/minio/minio.go
@@ -57,6 +57,8 @@ const (
imageThumbnailPath = "openim/thumbnail"
)
+const successCode = http.StatusOK
+
func NewMinio(cache cache.MinioCache) (s3.Interface, error) {
u, err := url.Parse(config.Config.Object.Minio.Endpoint)
if err != nil {
@@ -441,3 +443,51 @@ func (m *Minio) getObjectData(ctx context.Context, name string, limit int64) ([]
}
return io.ReadAll(io.LimitReader(object, limit))
}
+
+func (m *Minio) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) {
+ if err := m.initMinio(ctx); err != nil {
+ return nil, err
+ }
+ policy := minio.NewPostPolicy()
+ if err := policy.SetKey(name); err != nil {
+ return nil, err
+ }
+ expires := time.Now().Add(duration)
+ if err := policy.SetExpires(expires); err != nil {
+ return nil, err
+ }
+ if size > 0 {
+ if err := policy.SetContentLengthRange(0, size); err != nil {
+ return nil, err
+ }
+ }
+ if err := policy.SetSuccessStatusAction(strconv.Itoa(successCode)); err != nil {
+ return nil, err
+ }
+ if contentType != "" {
+ if err := policy.SetContentType(contentType); err != nil {
+ return nil, err
+ }
+ }
+ if err := policy.SetBucket(m.bucket); err != nil {
+ return nil, err
+ }
+ u, fd, err := m.core.PresignedPostPolicy(ctx, policy)
+ if err != nil {
+ return nil, err
+ }
+ sign, err := url.Parse(m.signEndpoint)
+ if err != nil {
+ return nil, err
+ }
+ u.Scheme = sign.Scheme
+ u.Host = sign.Host
+ return &s3.FormData{
+ URL: u.String(),
+ File: "file",
+ Header: nil,
+ FormData: fd,
+ Expires: expires,
+ SuccessCodes: []int{successCode},
+ }, nil
+}
diff --git a/pkg/common/db/s3/oss/oss.go b/pkg/common/db/s3/oss/oss.go
index 6a728127b..8fa2a538e 100644
--- a/pkg/common/db/s3/oss/oss.go
+++ b/pkg/common/db/s3/oss/oss.go
@@ -16,8 +16,13 @@ package oss
import (
"context"
+ "crypto/hmac"
+ "crypto/sha1"
+ "encoding/base64"
+ "encoding/json"
"errors"
"fmt"
+ "io"
"net/http"
"net/url"
"reflect"
@@ -45,6 +50,8 @@ const (
imageWebp = "webp"
)
+const successCode = http.StatusOK
+
const (
videoSnapshotImagePng = "png"
videoSnapshotImageJpg = "jpg"
@@ -327,3 +334,45 @@ func (o *OSS) AccessURL(ctx context.Context, name string, expire time.Duration,
params := getURLParams(*o.bucket.Client.Conn, rawParams)
return getURL(o.um, o.bucket.BucketName, name, params).String(), nil
}
+
+func (o *OSS) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) {
+ // https://help.aliyun.com/zh/oss/developer-reference/postobject?spm=a2c4g.11186623.0.0.1cb83cebkP55nn
+ expires := time.Now().Add(duration)
+ conditions := []any{
+ map[string]string{"bucket": o.bucket.BucketName},
+ map[string]string{"key": name},
+ }
+ if size > 0 {
+ conditions = append(conditions, []any{"content-length-range", 0, size})
+ }
+ policy := map[string]any{
+ "expiration": expires.Format("2006-01-02T15:04:05.000Z"),
+ "conditions": conditions,
+ }
+ policyJson, err := json.Marshal(policy)
+ if err != nil {
+ return nil, err
+ }
+ policyStr := base64.StdEncoding.EncodeToString(policyJson)
+ h := hmac.New(sha1.New, []byte(o.credentials.GetAccessKeySecret()))
+ if _, err := io.WriteString(h, policyStr); err != nil {
+ return nil, err
+ }
+ fd := &s3.FormData{
+ URL: o.bucketURL,
+ File: "file",
+ Expires: expires,
+ FormData: map[string]string{
+ "key": name,
+ "policy": policyStr,
+ "OSSAccessKeyId": o.credentials.GetAccessKeyID(),
+ "success_action_status": strconv.Itoa(successCode),
+ "signature": base64.StdEncoding.EncodeToString(h.Sum(nil)),
+ },
+ SuccessCodes: []int{successCode},
+ }
+ if contentType != "" {
+ fd.FormData["x-oss-content-type"] = contentType
+ }
+ return fd, nil
+}
diff --git a/pkg/common/db/s3/s3.go b/pkg/common/db/s3/s3.go
index afbe91955..0352004b5 100644
--- a/pkg/common/db/s3/s3.go
+++ b/pkg/common/db/s3/s3.go
@@ -74,6 +74,15 @@ type CopyObjectInfo struct {
ETag string `json:"etag"`
}
+type FormData struct {
+ URL string `json:"url"`
+ File string `json:"file"`
+ Header http.Header `json:"header"`
+ FormData map[string]string `json:"form"`
+ Expires time.Time `json:"expires"`
+ SuccessCodes []int `json:"successActionStatus"`
+}
+
type SignPart struct {
PartNumber int `json:"partNumber"`
URL string `json:"url"`
@@ -152,4 +161,6 @@ type Interface interface {
ListUploadedParts(ctx context.Context, uploadID string, name string, partNumberMarker int, maxParts int) (*ListUploadedPartsResult, error)
AccessURL(ctx context.Context, name string, expire time.Duration, opt *AccessURLOption) (string, error)
+
+ FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*FormData, error)
}
diff --git a/pkg/common/ginprometheus/ginprometheus.go b/pkg/common/ginprometheus/ginprometheus.go
index f116fc23a..1ee8f8e34 100644
--- a/pkg/common/ginprometheus/ginprometheus.go
+++ b/pkg/common/ginprometheus/ginprometheus.go
@@ -432,7 +432,7 @@ func computeApproximateRequestSize(r *http.Request) int {
}
s += len(r.Host)
- // r.Form and r.MultipartForm are assumed to be included in r.URL.
+ // r.FormData and r.MultipartForm are assumed to be included in r.URL.
if r.ContentLength != -1 {
s += int(r.ContentLength)
From 222064542927b643ed00d6edd7cd0ec9114a84e9 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Tue, 26 Dec 2023 18:03:07 +0800
Subject: [PATCH 028/110] Update README.md (#1615)
---
README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/README.md b/README.md
index a2c5fc732..781db1217 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,10 @@ It's crafted in Golang and supports cross-platform deployment, ensuring a cohere
## :rocket: Quick Start
+We support many platforms. Here are the addresses for quick experience on the web side:
+
+👉 **[OpenIM online web demo](https://web-enterprise.rentsoft.cn/)**
+
You can quickly learn OpenIM engineering solutions, all it takes is one simple command:
```bash
From cff90a3099f8784c49f616fa1884e71505c305d5 Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Thu, 28 Dec 2023 00:29:44 +0800
Subject: [PATCH 029/110] fix: fix the searchNotificationAccout by userID or
nickname (#1617)
* feat: add notification API
* fix: fix the script
* fix: fix the error
* fix: fix the searchNotificationAccount
* fix: fix the protocol version
* fix: fix the proto version
---
go.mod | 4 +-
go.sum | 4 +-
internal/rpc/user/user.go | 62 +++++++++++++++++++---------
pkg/common/db/controller/user.go | 7 ++++
pkg/common/db/mgo/user.go | 4 ++
pkg/common/db/table/relation/user.go | 1 +
6 files changed, 60 insertions(+), 22 deletions(-)
diff --git a/go.mod b/go.mod
index a753cae51..1b80650c5 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.39
+ github.com/OpenIMSDK/protocol v0.0.40
github.com/OpenIMSDK/tools v0.0.21
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
@@ -156,3 +156,5 @@ require (
golang.org/x/crypto v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
+
+replace github.com/OpenIMSDK/protocol v0.0.40 => github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3
diff --git a/go.sum b/go.sum
index a4609f6f2..09e4ce06b 100644
--- a/go.sum
+++ b/go.sum
@@ -18,8 +18,6 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.39 h1:DfvFcNGBcfj2vtT7W3uw4U/ipnI7NecTzQdlSYGuQz8=
-github.com/OpenIMSDK/protocol v0.0.39/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
@@ -227,6 +225,8 @@ github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205Ah
github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w=
github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w=
+github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3 h1:HZz2U/M3T4x9SqPxWdrD9MZy7jxx7nS+nx/aRN9m3RQ=
+github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index b5ad186a5..af9720590 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -17,6 +17,7 @@ package user
import (
"context"
"errors"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"math/rand"
"strings"
"time"
@@ -57,10 +58,6 @@ type userServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
-func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) {
- return nil, errs.ErrInternalServer.Wrap("not implemented")
-}
-
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis()
if err != nil {
@@ -466,26 +463,36 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.
return nil, err
}
+ if req.NickName != "" {
+ users, err := s.UserDatabase.FindByNickname(ctx, req.NickName)
+ if err != nil {
+ return nil, err
+ }
+ resp := s.userModelToResp(users)
+ return resp, nil
+ }
+
+ if req.UserID != "" {
+ users, err := s.UserDatabase.Find(ctx, []string{req.UserID})
+ if err != nil {
+ return nil, err
+ }
+ resp := s.userModelToResp(users)
+ return resp, nil
+ }
+
_, users, err := s.UserDatabase.Page(ctx, req.Pagination)
if err != nil {
return nil, err
}
- var total int64
- accounts := make([]*pbuser.NotificationAccountInfo, 0, len(users))
- for _, v := range users {
- if v.AppMangerLevel != constant.AppNotificationAdmin {
- continue
- }
- temp := &pbuser.NotificationAccountInfo{
- UserID: v.UserID,
- FaceURL: v.FaceURL,
- NickName: v.Nickname,
- }
- accounts = append(accounts, temp)
- total += 1
- }
- return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts}, nil
+ resp := s.userModelToResp(users)
+ return resp, nil
+}
+
+func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) {
+ //TODO implement me
+ panic("implement me")
}
func (s *userServer) GetNotificationAccount(ctx context.Context, req *pbuser.GetNotificationAccountReq) (*pbuser.GetNotificationAccountResp, error) {
@@ -517,3 +524,20 @@ func (s *userServer) genUserID() string {
}
return string(data)
}
+
+func (s *userServer) userModelToResp(users []*relation.UserModel) *pbuser.SearchNotificationAccountResp {
+ accounts := make([]*pbuser.NotificationAccountInfo, 0)
+ var total int64
+ for _, v := range users {
+ if v.AppMangerLevel == constant.AppNotificationAdmin || v.AppMangerLevel == constant.AppAdmin {
+ temp := &pbuser.NotificationAccountInfo{
+ UserID: v.UserID,
+ FaceURL: v.FaceURL,
+ NickName: v.Nickname,
+ }
+ accounts = append(accounts, temp)
+ total += 1
+ }
+ }
+ return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts}
+}
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index 2fafcf266..72bdf6b06 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -38,6 +38,8 @@ type UserDatabase interface {
FindWithError(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error)
// Find Get the information of the specified user If the userID is not found, no error will be returned
Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error)
+ // Find userInfo By Nickname
+ FindByNickname(ctx context.Context, nickname string) (users []*relation.UserModel, err error)
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db
Create(ctx context.Context, users []*relation.UserModel) (err error)
// Update update (non-zero value) external guarantee userID exists
@@ -133,6 +135,11 @@ func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*rel
return u.cache.GetUsersInfo(ctx, userIDs)
}
+// Find userInfo By Nickname
+func (u *userDatabase) FindByNickname(ctx context.Context, nickname string) (users []*relation.UserModel, err error) {
+ return u.userDB.TakeByNickname(ctx, nickname)
+}
+
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db.
func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) {
return u.tx.Transaction(ctx, func(ctx context.Context) error {
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 268d69ce3..0ca711ad8 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -65,6 +65,10 @@ func (u *UserMgo) Take(ctx context.Context, userID string) (user *relation.UserM
return mgoutil.FindOne[*relation.UserModel](ctx, u.coll, bson.M{"user_id": userID})
}
+func (u *UserMgo) TakeByNickname(ctx context.Context, nickname string) (user []*relation.UserModel, err error) {
+ return mgoutil.Find[*relation.UserModel](ctx, u.coll, bson.M{"nickname": nickname})
+}
+
func (u *UserMgo) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{}, pagination)
}
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index 213a6b774..8917ba55f 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -53,6 +53,7 @@ type UserModelInterface interface {
UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
Find(ctx context.Context, userIDs []string) (users []*UserModel, err error)
Take(ctx context.Context, userID string) (user *UserModel, err error)
+ TakeByNickname(ctx context.Context, nickname string) (user []*UserModel, err error)
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
Exist(ctx context.Context, userID string) (exist bool, err error)
GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error)
From 53a3f475f382743e93c62e0473d3ef0affbbf215 Mon Sep 17 00:00:00 2001
From: Gordon <46924906+FGadvancer@users.noreply.github.com>
Date: Thu, 28 Dec 2023 00:41:51 +0800
Subject: [PATCH 030/110] fix: add notifications for some notifications.
(#1609)
---
pkg/msgprocessor/options.go | 13 +------------
pkg/rpcclient/msg.go | 9 +++++++++
2 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/pkg/msgprocessor/options.go b/pkg/msgprocessor/options.go
index c17c7cb05..ea383a1af 100644
--- a/pkg/msgprocessor/options.go
+++ b/pkg/msgprocessor/options.go
@@ -30,10 +30,9 @@ func NewOptions(opts ...OptionsOpt) Options {
options[constant.IsOfflinePush] = false
options[constant.IsUnreadCount] = false
options[constant.IsConversationUpdate] = false
- options[constant.IsSenderSync] = false
+ options[constant.IsSenderSync] = true
options[constant.IsNotPrivate] = false
options[constant.IsSenderConversationUpdate] = false
- options[constant.IsSenderNotificationPush] = false
options[constant.IsReactionFromCache] = false
for _, opt := range opts {
opt(options)
@@ -114,12 +113,6 @@ func WithSenderConversationUpdate() OptionsOpt {
}
}
-func WithSenderNotificationPush() OptionsOpt {
- return func(options Options) {
- options[constant.IsSenderNotificationPush] = true
- }
-}
-
func WithReactionFromCache() OptionsOpt {
return func(options Options) {
options[constant.IsReactionFromCache] = true
@@ -174,10 +167,6 @@ func (o Options) IsSenderConversationUpdate() bool {
return o.Is(constant.IsSenderConversationUpdate)
}
-func (o Options) IsSenderNotificationPush() bool {
- return o.Is(constant.IsSenderNotificationPush)
-}
-
func (o Options) IsReactionFromCache() bool {
return o.Is(constant.IsReactionFromCache)
}
diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go
index 3b09b5062..50e1cd4a1 100644
--- a/pkg/rpcclient/msg.go
+++ b/pkg/rpcclient/msg.go
@@ -256,6 +256,7 @@ func (s *NotificationSender) NotificationWithSesstionType(ctx context.Context, s
optionsConfig.ReliabilityLevel = constant.UnreliableNotification
}
options := config.GetOptionsByNotification(optionsConfig)
+ s.SetOptionsByContentType(ctx, options, contentType)
msg.Options = options
offlineInfo.Title = title
offlineInfo.Desc = desc
@@ -274,3 +275,11 @@ func (s *NotificationSender) NotificationWithSesstionType(ctx context.Context, s
func (s *NotificationSender) Notification(ctx context.Context, sendID, recvID string, contentType int32, m proto.Message, opts ...NotificationOptions) error {
return s.NotificationWithSesstionType(ctx, sendID, recvID, contentType, s.sessionTypeConf[contentType], m, opts...)
}
+
+func (s *NotificationSender) SetOptionsByContentType(_ context.Context, options map[string]bool, contentType int32) {
+ switch contentType {
+ case constant.UserStatusChangeNotification:
+ options[constant.IsSenderSync] = false
+ default:
+ }
+}
From b90b8a1a558603107b65b51b1742c2ce944def0f Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Thu, 28 Dec 2023 14:17:27 +0800
Subject: [PATCH 031/110] fix: fix openim zk env set (#1623)
* fix: fix openim zk env set
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix openim zk env set
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
pkg/common/db/cache/init_redis.go | 10 +++++++++-
.../discoveryregister_test.go | 3 ++-
.../discoveryregister/zookeeper/zookeeper.go | 14 +++++++++++---
pkg/common/kafka/producer.go | 13 ++++++-------
pkg/common/kafka/util.go | 19 +++++++++++++++++++
tools/component/component_test.go | 12 ------------
6 files changed, 47 insertions(+), 24 deletions(-)
diff --git a/pkg/common/db/cache/init_redis.go b/pkg/common/db/cache/init_redis.go
index 63d2f5707..1308e9649 100644
--- a/pkg/common/db/cache/init_redis.go
+++ b/pkg/common/db/cache/init_redis.go
@@ -87,7 +87,15 @@ func NewRedis() (redis.UniversalClient, error) {
// overrideConfigFromEnv overrides configuration fields with environment variables if present.
func overrideConfigFromEnv() {
if envAddr := os.Getenv("REDIS_ADDRESS"); envAddr != "" {
- config.Config.Redis.Address = strings.Split(envAddr, ",") // Assuming addresses are comma-separated
+ if envPort := os.Getenv("REDIS_PORT"); envPort != "" {
+ addresses := strings.Split(envAddr, ",")
+ for i, addr := range addresses {
+ addresses[i] = addr + ":" + envPort
+ }
+ config.Config.Redis.Address = addresses
+ } else {
+ config.Config.Redis.Address = strings.Split(envAddr, ",")
+ }
}
if envUser := os.Getenv("REDIS_USERNAME"); envUser != "" {
config.Config.Redis.Username = envUser
diff --git a/pkg/common/discoveryregister/discoveryregister_test.go b/pkg/common/discoveryregister/discoveryregister_test.go
index d4a634b91..d83da1285 100644
--- a/pkg/common/discoveryregister/discoveryregister_test.go
+++ b/pkg/common/discoveryregister/discoveryregister_test.go
@@ -24,7 +24,8 @@ import (
func setupTestEnvironment() {
os.Setenv("ZOOKEEPER_SCHEMA", "openim")
- os.Setenv("ZOOKEEPER_ADDRESS", "172.28.0.1:12181")
+ os.Setenv("ZOOKEEPER_ADDRESS", "172.28.0.1")
+ os.Setenv("ZOOKEEPER_PORT", "12181")
os.Setenv("ZOOKEEPER_USERNAME", "")
os.Setenv("ZOOKEEPER_PASSWORD", "")
}
diff --git a/pkg/common/discoveryregister/zookeeper/zookeeper.go b/pkg/common/discoveryregister/zookeeper/zookeeper.go
index a4edffc43..db1a5c6c4 100644
--- a/pkg/common/discoveryregister/zookeeper/zookeeper.go
+++ b/pkg/common/discoveryregister/zookeeper/zookeeper.go
@@ -52,10 +52,18 @@ func getEnv(key, fallback string) string {
return fallback
}
-// getZkAddrFromEnv returns the value of an environment variable if it exists, otherwise it returns the fallback value.
+// getZkAddrFromEnv returns the Zookeeper addresses combined from the ZOOKEEPER_ADDRESS and ZOOKEEPER_PORT environment variables.
+// If the environment variables are not set, it returns the fallback value.
func getZkAddrFromEnv(fallback []string) []string {
- if value, exists := os.LookupEnv("ZOOKEEPER_ADDRESS"); exists {
- return strings.Split(value, ",")
+ address, addrExists := os.LookupEnv("ZOOKEEPER_ADDRESS")
+ port, portExists := os.LookupEnv("ZOOKEEPER_PORT")
+
+ if addrExists && portExists {
+ addresses := strings.Split(address, ",")
+ for i, addr := range addresses {
+ addresses[i] = addr + ":" + port
+ }
+ return addresses
}
return fallback
}
diff --git a/pkg/common/kafka/producer.go b/pkg/common/kafka/producer.go
index 9a06809b7..06b1e2b4c 100644
--- a/pkg/common/kafka/producer.go
+++ b/pkg/common/kafka/producer.go
@@ -31,15 +31,14 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
)
-const (
- maxRetry = 10 // Maximum number of retries for producer creation
-)
+const maxRetry = 10 // number of retries
-var errEmptyMsg = errors.New("binary msg is empty")
+var errEmptyMsg = errors.New("kafka binary msg is empty")
+// Producer represents a Kafka producer.
type Producer struct {
- topic string
addr []string
+ topic string
config *sarama.Config
producer sarama.SyncProducer
}
@@ -68,7 +67,7 @@ func NewKafkaProducer(addr []string, topic string) *Producer {
// Get Kafka configuration from environment variables or fallback to config file
kafkaUsername := getEnvOrConfig("KAFKA_USERNAME", config.Config.Kafka.Username)
kafkaPassword := getEnvOrConfig("KAFKA_PASSWORD", config.Config.Kafka.Password)
- kafkaAddr := getEnvOrConfig("KAFKA_ADDRESS", addr[0]) // Assuming addr[0] contains address from config
+ kafkaAddr := getKafkaAddrFromEnv(addr) // Updated to use the new function
// Configure SASL authentication if credentials are provided
if kafkaUsername != "" && kafkaPassword != "" {
@@ -78,7 +77,7 @@ func NewKafkaProducer(addr []string, topic string) *Producer {
}
// Set the Kafka address
- p.addr = []string{kafkaAddr}
+ p.addr = kafkaAddr
// Set up TLS configuration (if required)
SetupTLSConfig(p.config)
diff --git a/pkg/common/kafka/util.go b/pkg/common/kafka/util.go
index da0c5349b..f318ecf73 100644
--- a/pkg/common/kafka/util.go
+++ b/pkg/common/kafka/util.go
@@ -15,7 +15,9 @@
package kafka
import (
+ "fmt"
"os"
+ "strings"
"github.com/IBM/sarama"
@@ -44,3 +46,20 @@ func getEnvOrConfig(envName string, configValue string) string {
}
return configValue
}
+
+// getKafkaAddrFromEnv returns the Kafka addresses combined from the KAFKA_ADDRESS and KAFKA_PORT environment variables.
+// If the environment variables are not set, it returns the fallback value.
+func getKafkaAddrFromEnv(fallback []string) []string {
+ envAddr := os.Getenv("KAFKA_ADDRESS")
+ envPort := os.Getenv("KAFKA_PORT")
+
+ if envAddr != "" && envPort != "" {
+ addresses := strings.Split(envAddr, ",")
+ for i, addr := range addresses {
+ addresses[i] = fmt.Sprintf("%s:%s", addr, envPort)
+ }
+ return addresses
+ }
+
+ return fallback
+}
diff --git a/tools/component/component_test.go b/tools/component/component_test.go
index 08ea0fda8..4488c029e 100644
--- a/tools/component/component_test.go
+++ b/tools/component/component_test.go
@@ -21,22 +21,10 @@ import (
"time"
"github.com/redis/go-redis/v9"
- "github.com/stretchr/testify/assert"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
)
-func TestCheckMysql(t *testing.T) {
- err := mockInitCfg()
- assert.NoError(t, err, "Initialization should not produce errors")
-
- err = checkMysql()
- if err != nil {
- // You might expect an error if MySQL isn't running locally with the mock credentials.
- t.Logf("Expected error due to mock configuration: %v", err)
- }
-}
-
// Mock for initCfg for testing purpose
func mockInitCfg() error {
config.Config.Mysql.Username = "root"
From 998d4a3504fd30623e75ec6e9590050749104483 Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Thu, 28 Dec 2023 14:45:27 +0800
Subject: [PATCH 032/110] Add updates friend, set user ex (#1592)
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* fix bugs
* fix bugs
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* Update go.mod
* Update friend.go
* debug
* debug
* debug
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* I cannot solve todo in test.sh
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* Update go.mod
* fix group notification
* fix group notification
* update openimsdk tools
* update openim server remove duplicate code
* update openim server remove duplicate code
* update user command get
* update user command get
* update response of callback response error
* update black ex
* update join group ex
* update user pb2map
* update go sum
* update go sum
* update updateUserInfoEx
* update updateUserInfoEx
* update updateUserInfoEx add callback functions
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* update pin friend to update friend
* fix go mod
* fix err golangci-lint
* fix UserPb2DBMap
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* fix callback
* fix go.mod
* fix debug
* fix bugs
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
---------
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
config/templates/config.yaml.template | 8 ++++
go.sum | 2 +
internal/api/friend.go | 3 ++
internal/api/msg.go | 26 +++++++++++
internal/api/route.go | 3 +-
internal/api/user.go | 4 +-
internal/msggateway/client.go | 4 ++
internal/rpc/friend/friend.go | 36 +++++++++-------
internal/rpc/msg/callback.go | 2 +-
internal/rpc/user/callback.go | 36 +++++++++++++++-
internal/rpc/user/user.go | 39 ++++++++++++++---
pkg/callbackstruct/constant.go | 2 +
pkg/callbackstruct/user.go | 30 ++++++++++++-
pkg/common/config/config.go | 2 +
pkg/common/convert/user.go | 21 ++++++++-
pkg/common/db/controller/friend.go | 60 ++++++++++++++++++++------
pkg/common/db/mgo/friend.go | 30 +++++++++++++
pkg/common/db/table/relation/friend.go | 4 ++
pkg/rpcclient/msg.go | 2 +
pkg/rpcclient/notification/friend.go | 7 ++-
tools/component/component.go | 22 +++++++---
21 files changed, 297 insertions(+), 46 deletions(-)
diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template
index fd51a2e31..89f11f359 100644
--- a/config/templates/config.yaml.template
+++ b/config/templates/config.yaml.template
@@ -312,6 +312,14 @@ callback:
enable: false
timeout: 5
failedContinue: true
+ beforeUpdateUserInfoEx:
+ enable: false
+ timeout: 5
+ failedContinue: true
+ afterUpdateUserInfoEx:
+ enable: false
+ timeout: 5
+ failedContinue: true
afterSendSingleMsg:
enable: false
timeout: 5
diff --git a/go.sum b/go.sum
index 09e4ce06b..881000381 100644
--- a/go.sum
+++ b/go.sum
@@ -18,6 +18,8 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
+github.com/OpenIMSDK/protocol v0.0.40 h1:1/Oij6RSAaePCPrWGwp9Cyz976/8Uxr94hM5M5FXzlg=
+github.com/OpenIMSDK/protocol v0.0.40/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
diff --git a/internal/api/friend.go b/internal/api/friend.go
index 23f337a9f..7dc898a02 100644
--- a/internal/api/friend.go
+++ b/internal/api/friend.go
@@ -92,3 +92,6 @@ func (o *FriendApi) GetFriendIDs(c *gin.Context) {
func (o *FriendApi) GetSpecifiedFriendsInfo(c *gin.Context) {
a2r.Call(friend.FriendClient.GetSpecifiedFriendsInfo, o.Client, c)
}
+func (o *FriendApi) UpdateFriends(c *gin.Context) {
+ a2r.Call(friend.FriendClient.UpdateFriends, o.Client, c)
+}
diff --git a/internal/api/msg.go b/internal/api/msg.go
index b6bfcebb6..8346ad860 100644
--- a/internal/api/msg.go
+++ b/internal/api/msg.go
@@ -172,6 +172,7 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM
if err = m.userRpcClient.GetNotificationByID(c, req.SendID); err != nil {
return nil, err
}
+
default:
return nil, errs.ErrArgs.WithDetail("not support err contentType")
}
@@ -185,38 +186,63 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM
return m.newUserSendMsgReq(c, &req), nil
}
+// SendMessage handles the sending of a message. It's an HTTP handler function to be used with Gin framework.
func (m *MessageApi) SendMessage(c *gin.Context) {
+ // Initialize a request struct for sending a message.
req := apistruct.SendMsgReq{}
+
+ // Bind the JSON request body to the request struct.
if err := c.BindJSON(&req); err != nil {
+ // Respond with an error if request body binding fails.
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
return
}
+
+ // Check if the user has the app manager role.
if !authverify.IsAppManagerUid(c) {
+ // Respond with a permission error if the user is not an app manager.
apiresp.GinError(c, errs.ErrNoPermission.Wrap("only app manager can send message"))
return
}
+
+ // Prepare the message request with additional required data.
sendMsgReq, err := m.getSendMsgReq(c, req.SendMsg)
if err != nil {
+ // Log and respond with an error if preparation fails.
log.ZError(c, "decodeData failed", err)
apiresp.GinError(c, err)
return
}
+
+ // Set the receiver ID in the message data.
sendMsgReq.MsgData.RecvID = req.RecvID
+
+ // Declare a variable to store the message sending status.
var status int
+
+ // Attempt to send the message using the client.
respPb, err := m.Client.SendMsg(c, sendMsgReq)
if err != nil {
+ // Set the status to failed and respond with an error if sending fails.
status = constant.MsgSendFailed
log.ZError(c, "send message err", err)
apiresp.GinError(c, err)
return
}
+
+ // Set the status to successful if the message is sent.
status = constant.MsgSendSuccessed
+
+ // Attempt to update the message sending status in the system.
_, err = m.Client.SetSendMsgStatus(c, &msg.SetSendMsgStatusReq{
Status: int32(status),
})
if err != nil {
+ // Log the error if updating the status fails.
log.ZError(c, "SetSendMsgStatus failed", err)
}
+
+ // Respond with a success message and the response payload.
apiresp.GinSuccess(c, respPb)
}
diff --git a/internal/api/route.go b/internal/api/route.go
index 8fb372587..766912d45 100644
--- a/internal/api/route.go
+++ b/internal/api/route.go
@@ -67,6 +67,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
{
userRouterGroup.POST("/user_register", u.UserRegister)
userRouterGroup.POST("/update_user_info", ParseToken, u.UpdateUserInfo)
+ userRouterGroup.POST("/update_user_info_ex", ParseToken, u.UpdateUserInfoEx)
userRouterGroup.POST("/set_global_msg_recv_opt", ParseToken, u.SetGlobalRecvMessageOpt)
userRouterGroup.POST("/get_users_info", ParseToken, u.GetUsersPublicInfo)
userRouterGroup.POST("/get_all_users_uid", ParseToken, u.GetAllUsersID)
@@ -107,7 +108,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
friendRouterGroup.POST("/is_friend", f.IsFriend)
friendRouterGroup.POST("/get_friend_id", f.GetFriendIDs)
friendRouterGroup.POST("/get_specified_friends_info", f.GetSpecifiedFriendsInfo)
- //friendRouterGroup.POST("/set_pin_friend", f.SetPinFriends)
+ friendRouterGroup.POST("/update_friends", f.UpdateFriends)
}
g := NewGroupApi(*groupRpc)
groupRouterGroup := r.Group("/group", ParseToken)
diff --git a/internal/api/user.go b/internal/api/user.go
index cf68fb422..5f0e23631 100644
--- a/internal/api/user.go
+++ b/internal/api/user.go
@@ -41,7 +41,9 @@ func (u *UserApi) UserRegister(c *gin.Context) {
func (u *UserApi) UpdateUserInfo(c *gin.Context) {
a2r.Call(user.UserClient.UpdateUserInfo, u.Client, c)
}
-
+func (u *UserApi) UpdateUserInfoEx(c *gin.Context) {
+ a2r.Call(user.UserClient.UpdateUserInfoEx, u.Client, c)
+}
func (u *UserApi) SetGlobalRecvMessageOpt(c *gin.Context) {
a2r.Call(user.UserClient.SetGlobalRecvMessageOpt, u.Client, c)
}
diff --git a/internal/msggateway/client.go b/internal/msggateway/client.go
index 69b49d81a..43047fd73 100644
--- a/internal/msggateway/client.go
+++ b/internal/msggateway/client.go
@@ -87,6 +87,7 @@ func newClient(ctx *UserConnContext, conn LongConn, isCompress bool) *Client {
}
}
+// ResetClient updates the client's state with new connection and context information.
func (c *Client) ResetClient(
ctx *UserConnContext,
conn LongConn,
@@ -108,11 +109,13 @@ func (c *Client) ResetClient(
c.token = token
}
+// pingHandler handles ping messages and sends pong responses.
func (c *Client) pingHandler(_ string) error {
_ = c.conn.SetReadDeadline(pongWait)
return c.writePongMsg()
}
+// readMessage continuously reads messages from the connection.
func (c *Client) readMessage() {
defer func() {
if r := recover(); r != nil {
@@ -164,6 +167,7 @@ func (c *Client) readMessage() {
}
}
+// handleMessage processes a single message received by the client.
func (c *Client) handleMessage(message []byte) error {
if c.IsCompress {
var err error
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index c40b566f3..c53cb88f5 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -53,10 +53,6 @@ type friendServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
-func (s *friendServer) UpdateFriends(ctx context.Context, req *pbfriend.UpdateFriendsReq) (*pbfriend.UpdateFriendsResp, error) {
- return nil, errs.ErrInternalServer.Wrap("not implemented")
-}
-
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
// Initialize MongoDB
mongo, err := unrelation.NewMongo()
@@ -440,7 +436,7 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien
}
return resp, nil
}
-func (s *friendServer) PinFriends(
+func (s *friendServer) UpdateFriends(
ctx context.Context,
req *pbfriend.UpdateFriendsReq,
) (*pbfriend.UpdateFriendsResp, error) {
@@ -450,25 +446,35 @@ func (s *friendServer) PinFriends(
if utils.Duplicate(req.FriendUserIDs) {
return nil, errs.ErrArgs.Wrap("friendIDList repeated")
}
- var isPinned bool
- if req.IsPinned != nil {
- isPinned = req.IsPinned.Value
- } else {
- return nil, errs.ErrArgs.Wrap("isPinned is nil")
- }
- //check whther in friend list
+
_, err := s.friendDatabase.FindFriendsWithError(ctx, req.OwnerUserID, req.FriendUserIDs)
if err != nil {
return nil, err
}
- //set friendslist friend pin status to isPinned
for _, friendID := range req.FriendUserIDs {
- if err := s.friendDatabase.UpdateFriendPinStatus(ctx, req.OwnerUserID, friendID, isPinned); err != nil {
- return nil, err
+ if req.IsPinned != nil {
+ if err = s.friendDatabase.UpdateFriendPinStatus(ctx, req.OwnerUserID, friendID, req.IsPinned.Value); err != nil {
+ return nil, err
+ }
+ }
+ if req.Remark != nil {
+ if err = s.friendDatabase.UpdateFriendRemark(ctx, req.OwnerUserID, friendID, req.Remark.Value); err != nil {
+ return nil, err
+ }
+ }
+ if req.Ex != nil {
+ if err = s.friendDatabase.UpdateFriendEx(ctx, req.OwnerUserID, friendID, req.Ex.Value); err != nil {
+ return nil, err
+ }
}
}
resp := &pbfriend.UpdateFriendsResp{}
+
+ err = s.notificationSender.FriendsInfoUpdateNotification(ctx, req.OwnerUserID, req.FriendUserIDs)
+ if err != nil {
+ return nil, errs.Wrap(err, "FriendsInfoUpdateNotification Error")
+ }
return resp, nil
}
diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go
index 3a8587ea3..5d192fb87 100644
--- a/internal/rpc/msg/callback.go
+++ b/internal/rpc/msg/callback.go
@@ -100,7 +100,7 @@ func callbackAfterSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) err
}
func callbackBeforeSendGroupMsg(ctx context.Context, msg *pbchat.SendMsgReq) error {
- if !config.Config.Callback.CallbackBeforeSendSingleMsg.Enable {
+ if !config.Config.Callback.CallbackBeforeSendGroupMsg.Enable {
return nil
}
req := &cbapi.CallbackBeforeSendGroupMsgReq{
diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go
index 7d865af5f..9e02eb130 100644
--- a/internal/rpc/user/callback.go
+++ b/internal/rpc/user/callback.go
@@ -44,7 +44,6 @@ func CallbackBeforeUpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserInf
utils.NotNilReplace(&req.UserInfo.Nickname, resp.Nickname)
return nil
}
-
func CallbackAfterUpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserInfoReq) error {
if !config.Config.Callback.CallbackAfterUpdateUserInfo.Enable {
return nil
@@ -61,6 +60,41 @@ func CallbackAfterUpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserInfo
}
return nil
}
+func CallbackBeforeUpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) error {
+ if !config.Config.Callback.CallbackBeforeUpdateUserInfoEx.Enable {
+ return nil
+ }
+ cbReq := &cbapi.CallbackBeforeUpdateUserInfoExReq{
+ CallbackCommand: cbapi.CallbackBeforeUpdateUserInfoExCommand,
+ UserID: req.UserInfo.UserID,
+ FaceURL: &req.UserInfo.FaceURL,
+ Nickname: &req.UserInfo.Nickname,
+ }
+ resp := &cbapi.CallbackBeforeUpdateUserInfoExResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeUpdateUserInfoEx); err != nil {
+ return err
+ }
+ utils.NotNilReplace(&req.UserInfo.FaceURL, resp.FaceURL)
+ utils.NotNilReplace(req.UserInfo.Ex, resp.Ex)
+ utils.NotNilReplace(&req.UserInfo.Nickname, resp.Nickname)
+ return nil
+}
+func CallbackAfterUpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) error {
+ if !config.Config.Callback.CallbackAfterUpdateUserInfoEx.Enable {
+ return nil
+ }
+ cbReq := &cbapi.CallbackAfterUpdateUserInfoExReq{
+ CallbackCommand: cbapi.CallbackAfterUpdateUserInfoExCommand,
+ UserID: req.UserInfo.UserID,
+ FaceURL: req.UserInfo.FaceURL,
+ Nickname: req.UserInfo.Nickname,
+ }
+ resp := &cbapi.CallbackAfterUpdateUserInfoExResp{}
+ if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeUpdateUserInfoEx); err != nil {
+ return err
+ }
+ return nil
+}
func CallbackBeforeUserRegister(ctx context.Context, req *pbuser.UserRegisterReq) error {
if !config.Config.Callback.CallbackBeforeUserRegister.Enable {
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index af9720590..fdfd81ed2 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -149,7 +149,41 @@ func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserI
}
return resp, nil
}
+func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (resp *pbuser.UpdateUserInfoExResp, err error) {
+ resp = &pbuser.UpdateUserInfoExResp{}
+ err = authverify.CheckAccessV3(ctx, req.UserInfo.UserID)
+ if err != nil {
+ return nil, err
+ }
+ if err = CallbackBeforeUpdateUserInfoEx(ctx, req); err != nil {
+ return nil, err
+ }
+ data := convert.UserPb2DBMapEx(req.UserInfo)
+ if err = s.UpdateByMap(ctx, req.UserInfo.UserID, data); err != nil {
+ return nil, err
+ }
+ _ = s.friendNotificationSender.UserInfoUpdatedNotification(ctx, req.UserInfo.UserID)
+ friends, err := s.friendRpcClient.GetFriendIDs(ctx, req.UserInfo.UserID)
+ if err != nil {
+ return nil, err
+ }
+ if req.UserInfo.Nickname != "" || req.UserInfo.FaceURL != "" {
+ if err := s.groupRpcClient.NotificationUserInfoUpdate(ctx, req.UserInfo.UserID); err != nil {
+ log.ZError(ctx, "NotificationUserInfoUpdate", err)
+ }
+ }
+ for _, friendID := range friends {
+ s.friendNotificationSender.FriendInfoUpdatedNotification(ctx, req.UserInfo.UserID, friendID)
+ }
+ if err := CallbackAfterUpdateUserInfoEx(ctx, req); err != nil {
+ return nil, err
+ }
+ if err := s.groupRpcClient.NotificationUserInfoUpdate(ctx, req.UserInfo.UserID); err != nil {
+ log.ZError(ctx, "NotificationUserInfoUpdate", err, "userID", req.UserInfo.UserID)
+ }
+ return resp, nil
+}
func (s *userServer) SetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.SetGlobalRecvMessageOptReq) (resp *pbuser.SetGlobalRecvMessageOptResp, err error) {
resp = &pbuser.SetGlobalRecvMessageOptResp{}
if _, err := s.FindWithError(ctx, []string{req.UserID}); err != nil {
@@ -490,11 +524,6 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.
return resp, nil
}
-func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) (*pbuser.UpdateUserInfoExResp, error) {
- //TODO implement me
- panic("implement me")
-}
-
func (s *userServer) GetNotificationAccount(ctx context.Context, req *pbuser.GetNotificationAccountReq) (*pbuser.GetNotificationAccountResp, error) {
if req.UserID == "" {
return nil, errs.ErrArgs.Wrap("userID is empty")
diff --git a/pkg/callbackstruct/constant.go b/pkg/callbackstruct/constant.go
index 0a03a1ef1..cda98af16 100644
--- a/pkg/callbackstruct/constant.go
+++ b/pkg/callbackstruct/constant.go
@@ -37,6 +37,8 @@ const (
CallbackGroupMsgReadCommand = "callbackGroupMsgReadCommand"
CallbackMsgModifyCommand = "callbackMsgModifyCommand"
CallbackAfterUpdateUserInfoCommand = "callbackAfterUpdateUserInfoCommand"
+ CallbackAfterUpdateUserInfoExCommand = "callbackAfterUpdateUserInfoExCommand"
+ CallbackBeforeUpdateUserInfoExCommand = "callbackBeforeUpdateUserInfoExCommand"
CallbackBeforeUserRegisterCommand = "callbackBeforeUserRegisterCommand"
CallbackAfterUserRegisterCommand = "callbackAfterUserRegisterCommand"
CallbackTransferGroupOwnerAfter = "callbackTransferGroupOwnerAfter"
diff --git a/pkg/callbackstruct/user.go b/pkg/callbackstruct/user.go
index f35cff554..bfb69bd38 100644
--- a/pkg/callbackstruct/user.go
+++ b/pkg/callbackstruct/user.go
@@ -14,7 +14,10 @@
package callbackstruct
-import "github.com/OpenIMSDK/protocol/sdkws"
+import (
+ "github.com/OpenIMSDK/protocol/sdkws"
+ "github.com/OpenIMSDK/protocol/wrapperspb"
+)
type CallbackBeforeUpdateUserInfoReq struct {
CallbackCommand `json:"callbackCommand"`
@@ -41,6 +44,31 @@ type CallbackAfterUpdateUserInfoResp struct {
CommonCallbackResp
}
+type CallbackBeforeUpdateUserInfoExReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ UserID string `json:"userID"`
+ Nickname *string `json:"nickName"`
+ FaceURL *string `json:"faceURL"`
+ Ex *wrapperspb.StringValue `json:"ex"`
+}
+type CallbackBeforeUpdateUserInfoExResp struct {
+ CommonCallbackResp
+ Nickname *string `json:"nickName"`
+ FaceURL *string `json:"faceURL"`
+ Ex *wrapperspb.StringValue `json:"ex"`
+}
+
+type CallbackAfterUpdateUserInfoExReq struct {
+ CallbackCommand `json:"callbackCommand"`
+ UserID string `json:"userID"`
+ Nickname string `json:"nickName"`
+ FaceURL string `json:"faceURL"`
+ Ex *wrapperspb.StringValue `json:"ex"`
+}
+type CallbackAfterUpdateUserInfoExResp struct {
+ CommonCallbackResp
+}
+
type CallbackBeforeUserRegisterReq struct {
CallbackCommand `json:"callbackCommand"`
Secret string `json:"secret"`
diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go
index 707601234..ea26ca677 100644
--- a/pkg/common/config/config.go
+++ b/pkg/common/config/config.go
@@ -282,6 +282,8 @@ type configStruct struct {
CallbackBeforeSetFriendRemark CallBackConfig `yaml:"callbackBeforeSetFriendRemark"`
CallbackAfterSetFriendRemark CallBackConfig `yaml:"callbackAfterSetFriendRemark"`
CallbackBeforeUpdateUserInfo CallBackConfig `yaml:"beforeUpdateUserInfo"`
+ CallbackBeforeUpdateUserInfoEx CallBackConfig `yaml:"beforeUpdateUserInfoEx"`
+ CallbackAfterUpdateUserInfoEx CallBackConfig `yaml:"afterUpdateUserInfoEx"`
CallbackBeforeUserRegister CallBackConfig `yaml:"beforeUserRegister"`
CallbackAfterUpdateUserInfo CallBackConfig `yaml:"updateUserInfo"`
CallbackAfterUserRegister CallBackConfig `yaml:"afterUserRegister"`
diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go
index 72041a790..6d43595bc 100644
--- a/pkg/common/convert/user.go
+++ b/pkg/common/convert/user.go
@@ -64,7 +64,7 @@ func UserPb2DBMap(user *sdkws.UserInfo) map[string]any {
"global_recv_msg_opt": user.GlobalRecvMsgOpt,
}
for key, value := range fields {
- if v, ok := value.(string); ok {
+ if v, ok := value.(string); ok && v != "" {
val[key] = v
} else if v, ok := value.(int32); ok && v != 0 {
val[key] = v
@@ -72,3 +72,22 @@ func UserPb2DBMap(user *sdkws.UserInfo) map[string]any {
}
return val
}
+func UserPb2DBMapEx(user *sdkws.UserInfoWithEx) map[string]any {
+ if user == nil {
+ return nil
+ }
+ val := make(map[string]any)
+
+ // Map fields from UserInfoWithEx to val
+ val["nickname"] = user.Nickname
+ val["face_url"] = user.FaceURL
+
+ if user.Ex != nil {
+ val["ex"] = user.Ex.Value
+ }
+ if user.GlobalRecvMsgOpt != 0 {
+ val["global_recv_msg_opt"] = user.GlobalRecvMsgOpt
+ }
+
+ return val
+}
diff --git a/pkg/common/db/controller/friend.go b/pkg/common/db/controller/friend.go
index 34ce22295..924a179ba 100644
--- a/pkg/common/db/controller/friend.go
+++ b/pkg/common/db/controller/friend.go
@@ -32,33 +32,57 @@ import (
)
type FriendDatabase interface {
- // 检查user2是否在user1的好友列表中(inUser1Friends==true) 检查user1是否在user2的好友列表中(inUser2Friends==true)
+ // CheckIn checks if user2 is in user1's friend list (inUser1Friends==true) and if user1 is in user2's friend list (inUser2Friends==true)
CheckIn(ctx context.Context, user1, user2 string) (inUser1Friends bool, inUser2Friends bool, err error)
- // 增加或者更新好友申请
+
+ // AddFriendRequest adds or updates a friend request
AddFriendRequest(ctx context.Context, fromUserID, toUserID string, reqMsg string, ex string) (err error)
- // 先判断是否在好友表,如果在则不插入
+
+ // BecomeFriends first checks if the users are already in the friends table; if not, it inserts them as friends
BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error)
- // 拒绝好友申请
+
+ // RefuseFriendRequest refuses a friend request
RefuseFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error)
- // 同意好友申请
+
+ // AgreeFriendRequest accepts a friend request
AgreeFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error)
- // 删除好友
+
+ // Delete removes a friend or friends from the owner's friend list
Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
- // 更新好友备注
+
+ // UpdateRemark updates the remark for a friend
UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
- // 获取ownerUserID的好友列表
+
+ // PageOwnerFriends retrieves the friend list of ownerUserID with pagination
PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
- // friendUserID在哪些人的好友列表中
+
+ // PageInWhoseFriends finds the users who have friendUserID in their friend list with pagination
PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
- // 获取我发出去的好友申请
+
+ // PageFriendRequestFromMe retrieves the friend requests sent by the user with pagination
PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
- // 获取我收到的的好友申请
+
+ // PageFriendRequestToMe retrieves the friend requests received by the user with pagination
PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
- // 获取某人指定好友的信息
+
+ // FindFriendsWithError fetches specified friends of a user and returns an error if any do not exist
FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error)
+
+ // FindFriendUserIDs retrieves the friend IDs of a user
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
+
+ // FindBothFriendRequests finds friend requests sent and received
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error)
+
+ // UpdateFriendPinStatus updates the pinned status of a friend
UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error)
+
+ // UpdateFriendRemark updates the remark for a friend
+ UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error)
+
+ // UpdateFriendEx updates the 'ex' field for a friend
+ UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error)
+
}
type friendDatabase struct {
@@ -305,3 +329,15 @@ func (f *friendDatabase) UpdateFriendPinStatus(ctx context.Context, ownerUserID
}
return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx)
}
+func (f *friendDatabase) UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) {
+ if err := f.friend.UpdateFriendRemark(ctx, ownerUserID, friendUserID, remark); err != nil {
+ return err
+ }
+ return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx)
+}
+func (f *friendDatabase) UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) {
+ if err := f.friend.UpdateFriendEx(ctx, ownerUserID, friendUserID, ex); err != nil {
+ return err
+ }
+ return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx)
+}
diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go
index 667098819..72289181b 100644
--- a/pkg/common/db/mgo/friend.go
+++ b/pkg/common/db/mgo/friend.go
@@ -160,3 +160,33 @@ func (f *FriendMgo) UpdatePinStatus(ctx context.Context, ownerUserID string, fri
return nil
}
+func (f *FriendMgo) UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) {
+
+ filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID}
+ // Create an update operation to set the "is_pinned" field to isPinned for all documents.
+ update := bson.M{"$set": bson.M{"remark": remark}}
+
+ // Perform the update operation for all documents in the collection.
+ _, err = f.coll.UpdateMany(ctx, filter, update)
+
+ if err != nil {
+ return errs.Wrap(err, "update remark error")
+ }
+
+ return nil
+}
+func (f *FriendMgo) UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) {
+
+ filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID}
+ // Create an update operation to set the "is_pinned" field to isPinned for all documents.
+ update := bson.M{"$set": bson.M{"ex": ex}}
+
+ // Perform the update operation for all documents in the collection.
+ _, err = f.coll.UpdateMany(ctx, filter, update)
+
+ if err != nil {
+ return errs.Wrap(err, "update ex error")
+ }
+
+ return nil
+}
diff --git a/pkg/common/db/table/relation/friend.go b/pkg/common/db/table/relation/friend.go
index 4f85998f4..cc337701d 100644
--- a/pkg/common/db/table/relation/friend.go
+++ b/pkg/common/db/table/relation/friend.go
@@ -59,4 +59,8 @@ type FriendModelInterface interface {
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
// UpdatePinStatus update friend's pin status
UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error)
+ // UpdateFriendRemark update friend's remark
+ UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error)
+ // UpdateFriendEx update friend's ex
+ UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error)
}
diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go
index 50e1cd4a1..03769dc74 100644
--- a/pkg/rpcclient/msg.go
+++ b/pkg/rpcclient/msg.go
@@ -68,6 +68,7 @@ func newContentTypeConf() map[int32]config.NotificationConf {
constant.BlackAddedNotification: config.Config.Notification.BlackAdded,
constant.BlackDeletedNotification: config.Config.Notification.BlackDeleted,
constant.FriendInfoUpdatedNotification: config.Config.Notification.FriendInfoUpdated,
+ constant.FriendsInfoUpdateNotification: config.Config.Notification.FriendInfoUpdated, //use the same FriendInfoUpdated
// conversation
constant.ConversationChangeNotification: config.Config.Notification.ConversationChanged,
constant.ConversationUnreadNotification: config.Config.Notification.ConversationChanged,
@@ -115,6 +116,7 @@ func newSessionTypeConf() map[int32]int32 {
constant.BlackAddedNotification: constant.SingleChatType,
constant.BlackDeletedNotification: constant.SingleChatType,
constant.FriendInfoUpdatedNotification: constant.SingleChatType,
+ constant.FriendsInfoUpdateNotification: constant.SingleChatType,
// conversation
constant.ConversationChangeNotification: constant.SingleChatType,
constant.ConversationUnreadNotification: constant.SingleChatType,
diff --git a/pkg/rpcclient/notification/friend.go b/pkg/rpcclient/notification/friend.go
index b061a24ae..00759b1b2 100644
--- a/pkg/rpcclient/notification/friend.go
+++ b/pkg/rpcclient/notification/friend.go
@@ -196,7 +196,12 @@ func (f *FriendNotificationSender) FriendRemarkSetNotification(ctx context.Conte
tips.FromToUserID.ToUserID = toUserID
return f.Notification(ctx, fromUserID, toUserID, constant.FriendRemarkSetNotification, &tips)
}
-
+func (f *FriendNotificationSender) FriendsInfoUpdateNotification(ctx context.Context, toUserID string, friendIDs []string) error {
+ tips := sdkws.FriendsInfoUpdateTips{}
+ tips.FromToUserID.ToUserID = toUserID
+ tips.FriendIDs = friendIDs
+ return f.Notification(ctx, toUserID, toUserID, constant.FriendsInfoUpdateNotification, &tips)
+}
func (f *FriendNotificationSender) BlackAddedNotification(ctx context.Context, req *pbfriend.AddBlackReq) error {
tips := sdkws.BlackAddedTips{FromToUserID: &sdkws.FromToUserID{}}
tips.FromToUserID.FromUserID = req.OwnerUserID
diff --git a/tools/component/component.go b/tools/component/component.go
index 28ea7a2fe..616ffec2d 100644
--- a/tools/component/component.go
+++ b/tools/component/component.go
@@ -16,6 +16,7 @@ package main
import (
"context"
+ "errors"
"flag"
"fmt"
"net"
@@ -285,10 +286,23 @@ func checkZookeeper() (string, error) {
// Connect to Zookeeper
str := "the addr is:" + address
- c, _, err := zk.Connect(zookeeperAddresses, time.Second) // Adjust the timeout as necessary
+ c, eventChan, err := zk.Connect(zookeeperAddresses, time.Second) // Adjust the timeout as necessary
if err != nil {
return "", errs.Wrap(errStr(err, str))
}
+ timeout := time.After(5 * time.Second)
+ for {
+ select {
+ case event := <-eventChan:
+ if event.State == zk.StateConnected {
+ fmt.Println("Connected to Zookeeper")
+ goto Connected
+ }
+ case <-timeout:
+ return "", errs.Wrap(errors.New("timeout waiting for Zookeeper connection"), "Zookeeper Addr: "+strings.Join(config.Config.Zookeeper.ZkAddr, " "))
+ }
+ }
+Connected:
defer c.Close()
// Set authentication if username and password are provided
@@ -298,12 +312,6 @@ func checkZookeeper() (string, error) {
}
}
- // Check if Zookeeper is reachable
- _, _, err = c.Get("/")
- if err != nil {
- return "", errs.Wrap(err, str)
- }
-
return str, nil
}
From cfde7bb0ff6d7441e3ae593016d6848b9e6af020 Mon Sep 17 00:00:00 2001
From: a3d21 <93191329+a3d21@users.noreply.github.com>
Date: Fri, 29 Dec 2023 10:25:03 +0800
Subject: [PATCH 033/110] fix: mongo uri connect (#1611)
---
pkg/common/db/unrelation/mongo.go | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go
index 2c1dc6f38..8cfb97a98 100644
--- a/pkg/common/db/unrelation/mongo.go
+++ b/pkg/common/db/unrelation/mongo.go
@@ -74,6 +74,10 @@ func buildMongoURI() string {
return uri
}
+ if config.Config.Mongo.Uri != "" {
+ return config.Config.Mongo.Uri
+ }
+
username := os.Getenv("MONGO_USERNAME")
password := os.Getenv("MONGO_PASSWORD")
address := os.Getenv("MONGO_ADDRESS")
From 7ddb84f7fcdab6fc2b67593691fbf741da0c56ff Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Fri, 29 Dec 2023 18:14:15 +0800
Subject: [PATCH 034/110] fix: add the GetconversationAPI 1542 (#1604)
* feat: add GetConversationsUnreadSeqAndMaxSeq func
* feat: add GetConversationsUnreadSeqAndMaxSeq func
* feat: add GetConversationsUnreadSeqAndMaxSeq func
* fix: fix the conflect
* feat: add GetConversationList Api
* fix: fix the error
* fix: move the GetConversationList to conversation folder
* fix: fix the go.mod
* fix: add InitiateFormData and CompleteFormData
* fix: fix the error
* fix: find error
* fix: test
* feat: add notification API
* fix: find error
* fix: fix the error
* fix: fix the PinFriend error
* fix: fix the Ex error
* fix: find the error
* fix: fix the rpc error
* fix: fix the error
* fix: fix the log error
* fix: fix the error1
* fix: fix the error
* fix: fix the script
* fix: fix the error
* fix: fix the error
* fix: fix the error of tag
* fix: fix the protocol
* fix: fix the error
* fix: fix the error
* fix: fix the err not wrap
* fix: fix the error
* fix: fix GetGroupMembers by nickname
* fix: fix the error
* fix: fix the FindOneByDocIDs
* fix: fix the protocol version
* fix: fit the protocol version
---
go.mod | 4 +-
go.sum | 6 +-
internal/api/conversation.go | 4 +
internal/api/msg.go | 5 +-
internal/api/route.go | 1 +
internal/rpc/conversation/conversaion.go | 173 +++++++++++++++++++++++
internal/rpc/msg/as_read.go | 3 +-
internal/rpc/msg/seq.go | 25 +++-
pkg/apistruct/manage.go | 24 ++++
pkg/common/db/controller/msg.go | 16 +++
pkg/rpcclient/msg.go | 25 +++-
11 files changed, 273 insertions(+), 13 deletions(-)
diff --git a/go.mod b/go.mod
index 1b80650c5..2db34a8b1 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.40
+ github.com/OpenIMSDK/protocol v0.0.41
github.com/OpenIMSDK/tools v0.0.21
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
@@ -156,5 +156,3 @@ require (
golang.org/x/crypto v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
-
-replace github.com/OpenIMSDK/protocol v0.0.40 => github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3
diff --git a/go.sum b/go.sum
index 881000381..fc1d15242 100644
--- a/go.sum
+++ b/go.sum
@@ -18,8 +18,8 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.40 h1:1/Oij6RSAaePCPrWGwp9Cyz976/8Uxr94hM5M5FXzlg=
-github.com/OpenIMSDK/protocol v0.0.40/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/protocol v0.0.42 h1:vIWXqZJZZ1ddleJA25fxhjZ1GyEHATpYM3wVWh4/+PY=
+github.com/OpenIMSDK/protocol v0.0.42/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
@@ -227,8 +227,6 @@ github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205Ah
github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w=
github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w=
-github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3 h1:HZz2U/M3T4x9SqPxWdrD9MZy7jxx7nS+nx/aRN9m3RQ=
-github.com/luhaoling/protocol v0.0.0-20231227040641-2f934a0d64a3/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
diff --git a/internal/api/conversation.go b/internal/api/conversation.go
index e422de677..6463cbde6 100644
--- a/internal/api/conversation.go
+++ b/internal/api/conversation.go
@@ -33,6 +33,10 @@ func (o *ConversationApi) GetAllConversations(c *gin.Context) {
a2r.Call(conversation.ConversationClient.GetAllConversations, o.Client, c)
}
+func (o *ConversationApi) GetConversationsList(c *gin.Context) {
+ a2r.Call(conversation.ConversationClient.GetConversationList, o.Client, c)
+}
+
func (o *ConversationApi) GetConversation(c *gin.Context) {
a2r.Call(conversation.ConversationClient.GetConversation, o.Client, c)
}
diff --git a/internal/api/msg.go b/internal/api/msg.go
index 8346ad860..548450534 100644
--- a/internal/api/msg.go
+++ b/internal/api/msg.go
@@ -250,13 +250,14 @@ func (m *MessageApi) SendBusinessNotification(c *gin.Context) {
req := struct {
Key string `json:"key"`
Data string `json:"data"`
- SendUserID string `json:"sendUserID"`
- RecvUserID string `json:"recvUserID"`
+ SendUserID string `json:"sendUserID" binding:"required"`
+ RecvUserID string `json:"recvUserID" binding:"required"`
}{}
if err := c.BindJSON(&req); err != nil {
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
return
}
+
if !authverify.IsAppManagerUid(c) {
apiresp.GinError(c, errs.ErrNoPermission.Wrap("only app manager can send message"))
return
diff --git a/internal/api/route.go b/internal/api/route.go
index 766912d45..1c91f4dde 100644
--- a/internal/api/route.go
+++ b/internal/api/route.go
@@ -204,6 +204,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
conversationGroup := r.Group("/conversation", ParseToken)
{
c := NewConversationApi(*conversationRpc)
+ conversationGroup.POST("/get_conversations_list", c.GetConversationsList)
conversationGroup.POST("/get_all_conversations", c.GetAllConversations)
conversationGroup.POST("/get_conversation", c.GetConversation)
conversationGroup.POST("/get_conversations", c.GetConversations)
diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go
index 88c9ff7ff..b80e32953 100644
--- a/internal/rpc/conversation/conversaion.go
+++ b/internal/rpc/conversation/conversaion.go
@@ -17,6 +17,8 @@ package conversation
import (
"context"
"errors"
+ "github.com/OpenIMSDK/protocol/sdkws"
+ "sort"
"github.com/OpenIMSDK/tools/tx"
@@ -41,6 +43,8 @@ import (
)
type conversationServer struct {
+ msgRpcClient *rpcclient.MessageRpcClient
+ user *rpcclient.UserRpcClient
groupRpcClient *rpcclient.GroupRpcClient
conversationDatabase controller.ConversationDatabase
conversationNotificationSender *notification.ConversationNotificationSender
@@ -61,7 +65,10 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
}
groupRpcClient := rpcclient.NewGroupRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)
+ userRpcClient := rpcclient.NewUserRpcClient(client)
pbconversation.RegisterConversationServer(server, &conversationServer{
+ msgRpcClient: &msgRpcClient,
+ user: &userRpcClient,
conversationNotificationSender: notification.NewConversationNotificationSender(&msgRpcClient),
groupRpcClient: &groupRpcClient,
conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx.NewMongo(mongo.GetClient())),
@@ -82,6 +89,73 @@ func (c *conversationServer) GetConversation(ctx context.Context, req *pbconvers
return resp, nil
}
+func (m *conversationServer) GetConversationList(ctx context.Context, req *pbconversation.GetConversationListReq) (resp *pbconversation.GetConversationListResp, err error) {
+ log.ZDebug(ctx, "GetConversationList", "seqs", req, "userID", req.UserID)
+ var conversationIDs []string
+ if len(req.ConversationIDs) == 0 {
+ conversationIDs, err = m.conversationDatabase.GetConversationIDs(ctx, req.UserID)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ conversationIDs = req.ConversationIDs
+ }
+
+ conversations, err := m.conversationDatabase.FindConversations(ctx, req.UserID, conversationIDs)
+ if err != nil {
+ return nil, err
+ }
+ if len(conversations) == 0 {
+ return nil, errs.ErrRecordNotFound.Wrap()
+ }
+
+ maxSeqs, err := m.msgRpcClient.GetMaxSeqs(ctx, conversationIDs)
+ if err != nil {
+ return nil, err
+ }
+
+ chatLogs, err := m.msgRpcClient.GetMsgByConversationIDs(ctx, conversationIDs, maxSeqs)
+ if err != nil {
+ return nil, err
+ }
+
+ conversationMsg, err := m.getConversationInfo(ctx, chatLogs, req.UserID)
+ if err != nil {
+ return nil, err
+ }
+
+ hasReadSeqs, err := m.msgRpcClient.GetHasReadSeqs(ctx, req.UserID, conversationIDs)
+ if err != nil {
+ return nil, err
+ }
+
+ conversation_unreadCount := make(map[string]int64)
+ for conversationID, maxSeq := range maxSeqs {
+ conversation_unreadCount[conversationID] = maxSeq - hasReadSeqs[conversationID]
+ }
+
+ conversation_isPinkTime := make(map[int64]string)
+ conversation_notPinkTime := make(map[int64]string)
+ for _, v := range conversations {
+ conversationID := v.ConversationID
+ time := conversationMsg[conversationID].MsgInfo.LatestMsgRecvTime
+ conversationMsg[conversationID].RecvMsgOpt = v.RecvMsgOpt
+ if v.IsPinned {
+ conversationMsg[conversationID].IsPinned = v.IsPinned
+ conversation_isPinkTime[time] = conversationID
+ continue
+ }
+ conversation_notPinkTime[time] = conversationID
+ }
+ resp = &pbconversation.GetConversationListResp{
+ ConversationElems: []*pbconversation.ConversationElem{},
+ }
+
+ m.conversationSort(conversation_isPinkTime, resp, conversation_unreadCount, conversationMsg)
+ m.conversationSort(conversation_notPinkTime, resp, conversation_unreadCount, conversationMsg)
+ return resp, nil
+}
+
func (c *conversationServer) GetAllConversations(ctx context.Context, req *pbconversation.GetAllConversationsReq) (*pbconversation.GetAllConversationsResp, error) {
conversations, err := c.conversationDatabase.GetUserAllConversation(ctx, req.OwnerUserID)
if err != nil {
@@ -348,3 +422,102 @@ func (c *conversationServer) GetConversationOfflinePushUserIDs(
}
return &pbconversation.GetConversationOfflinePushUserIDsResp{UserIDs: utils.Keys(userIDSet)}, nil
}
+
+func (c *conversationServer) conversationSort(
+ conversations map[int64]string,
+ resp *pbconversation.GetConversationListResp,
+ conversation_unreadCount map[string]int64,
+ conversationMsg map[string]*pbconversation.ConversationElem,
+) {
+ keys := []int64{}
+ for key := range conversations {
+ keys = append(keys, key)
+ }
+
+ sort.Slice(keys[:], func(i, j int) bool {
+ return keys[i] > keys[j]
+ })
+ index := 0
+
+ cons := make([]*pbconversation.ConversationElem, len(conversations))
+ for _, v := range keys {
+ conversationID := conversations[v]
+ conversationElem := conversationMsg[conversationID]
+ conversationElem.UnreadCount = conversation_unreadCount[conversationID]
+ cons[index] = conversationElem
+ index++
+ }
+ resp.ConversationElems = append(resp.ConversationElems, cons...)
+}
+
+func (c *conversationServer) getConversationInfo(
+ ctx context.Context,
+ chatLogs map[string]*sdkws.MsgData,
+ userID string) (map[string]*pbconversation.ConversationElem, error) {
+ var (
+ sendIDs []string
+ groupIDs []string
+ sendMap = make(map[string]*sdkws.UserInfo)
+ groupMap = make(map[string]*sdkws.GroupInfo)
+ conversationMsg = make(map[string]*pbconversation.ConversationElem)
+ )
+ for _, chatLog := range chatLogs {
+ switch chatLog.SessionType {
+ case constant.SingleChatType:
+ if chatLog.SendID == userID {
+ sendIDs = append(sendIDs, chatLog.RecvID)
+ }
+ sendIDs = append(sendIDs, chatLog.SendID)
+ case constant.GroupChatType, constant.SuperGroupChatType:
+ groupIDs = append(groupIDs, chatLog.GroupID)
+ sendIDs = append(sendIDs, chatLog.SendID)
+ }
+ }
+ if len(sendIDs) != 0 {
+ sendInfos, err := c.user.GetUsersInfo(ctx, sendIDs)
+ if err != nil {
+ return nil, err
+ }
+ for _, sendInfo := range sendInfos {
+ sendMap[sendInfo.UserID] = sendInfo
+ }
+ }
+ if len(groupIDs) != 0 {
+ groupInfos, err := c.groupRpcClient.GetGroupInfos(ctx, groupIDs, false)
+ if err != nil {
+ return nil, err
+ }
+ for _, groupInfo := range groupInfos {
+ groupMap[groupInfo.GroupID] = groupInfo
+ }
+ }
+ for conversationID, chatLog := range chatLogs {
+ pbchatLog := &pbconversation.ConversationElem{}
+ msgInfo := &pbconversation.MsgInfo{}
+ if err := utils.CopyStructFields(msgInfo, chatLog); err != nil {
+ return nil, err
+ }
+ switch chatLog.SessionType {
+ case constant.SingleChatType:
+ if chatLog.SendID == userID {
+ msgInfo.FaceURL = sendMap[chatLog.RecvID].FaceURL
+ msgInfo.SenderName = sendMap[chatLog.RecvID].Nickname
+ break
+ }
+ msgInfo.FaceURL = sendMap[chatLog.SendID].FaceURL
+ msgInfo.SenderName = sendMap[chatLog.SendID].Nickname
+ case constant.GroupChatType, constant.SuperGroupChatType:
+ msgInfo.GroupName = groupMap[chatLog.GroupID].GroupName
+ msgInfo.GroupFaceURL = groupMap[chatLog.GroupID].FaceURL
+ msgInfo.GroupMemberCount = groupMap[chatLog.GroupID].MemberCount
+ msgInfo.GroupID = chatLog.GroupID
+ msgInfo.GroupType = groupMap[chatLog.GroupID].GroupType
+ msgInfo.SenderName = sendMap[chatLog.SendID].Nickname
+ }
+ pbchatLog.ConversationID = conversationID
+ msgInfo.LatestMsgRecvTime = chatLog.SendTime
+ pbchatLog.MsgInfo = msgInfo
+ conversationMsg[conversationID] = pbchatLog
+ }
+ return conversationMsg, nil
+}
diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go
index 5324ccba8..71e038b39 100644
--- a/internal/rpc/msg/as_read.go
+++ b/internal/rpc/msg/as_read.go
@@ -18,6 +18,7 @@ import (
"context"
utils2 "github.com/OpenIMSDK/tools/utils"
+ cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/redis/go-redis/v9"
@@ -26,8 +27,6 @@ import (
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
-
- cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
)
func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *msg.GetConversationsHasReadAndMaxSeqReq) (resp *msg.GetConversationsHasReadAndMaxSeqResp, err error) {
diff --git a/internal/rpc/msg/seq.go b/internal/rpc/msg/seq.go
index 4f6a01e8d..c12f258b7 100644
--- a/internal/rpc/msg/seq.go
+++ b/internal/rpc/msg/seq.go
@@ -16,7 +16,6 @@ package msg
import (
"context"
-
pbmsg "github.com/OpenIMSDK/protocol/msg"
)
@@ -30,3 +29,27 @@ func (m *msgServer) GetConversationMaxSeq(
}
return &pbmsg.GetConversationMaxSeqResp{MaxSeq: maxSeq}, nil
}
+
+func (m *msgServer) GetMaxSeqs(ctx context.Context, req *pbmsg.GetMaxSeqsReq) (*pbmsg.SeqsInfoResp, error) {
+ maxSeqs, err := m.MsgDatabase.GetMaxSeqs(ctx, req.ConversationIDs)
+ if err != nil {
+ return nil, err
+ }
+ return &pbmsg.SeqsInfoResp{MaxSeqs: maxSeqs}, nil
+}
+
+func (m *msgServer) GetHasReadSeqs(ctx context.Context, req *pbmsg.GetHasReadSeqsReq) (*pbmsg.SeqsInfoResp, error) {
+ hasReadSeqs, err := m.MsgDatabase.GetHasReadSeqs(ctx, req.UserID, req.ConversationIDs)
+ if err != nil {
+ return nil, err
+ }
+ return &pbmsg.SeqsInfoResp{MaxSeqs: hasReadSeqs}, nil
+}
+
+func (m *msgServer) GetMsgByConversationIDs(ctx context.Context, req *pbmsg.GetMsgByConversationIDsReq) (*pbmsg.GetMsgByConversationIDsResp, error) {
+ Msgs, err := m.MsgDatabase.FindOneByDocIDs(ctx, req.ConversationIDs, req.MaxSeqs)
+ if err != nil {
+ return nil, err
+ }
+ return &pbmsg.GetMsgByConversationIDsResp{MsgDatas: Msgs}, nil
+}
diff --git a/pkg/apistruct/manage.go b/pkg/apistruct/manage.go
index a48f5253c..f9f542835 100644
--- a/pkg/apistruct/manage.go
+++ b/pkg/apistruct/manage.go
@@ -64,6 +64,30 @@ type SendMsgReq struct {
SendMsg
}
+type GetConversationListReq struct {
+ // userID uniquely identifies the user.
+ UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty" binding:"required"`
+
+ // ConversationIDs contains a list of unique identifiers for conversations.
+ ConversationIDs []string `protobuf:"bytes,2,rep,name=conversationIDs,proto3" json:"conversationIDs,omitempty"`
+}
+
+type GetConversationListResp struct {
+ // ConversationElems is a map that associates conversation IDs with their respective details.
+ ConversationElems map[string]*ConversationElem `protobuf:"bytes,1,rep,name=conversationElems,proto3" json:"conversationElems,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+}
+
+type ConversationElem struct {
+ // MaxSeq represents the maximum sequence number within the conversation.
+ MaxSeq int64 `protobuf:"varint,1,opt,name=maxSeq,proto3" json:"maxSeq,omitempty"`
+
+ // UnreadSeq represents the number of unread messages in the conversation.
+ UnreadSeq int64 `protobuf:"varint,2,opt,name=unreadSeq,proto3" json:"unreadSeq,omitempty"`
+
+ // LastSeqTime represents the timestamp of the last sequence in the conversation.
+ LastSeqTime int64 `protobuf:"varint,3,opt,name=LastSeqTime,proto3" json:"LastSeqTime,omitempty"`
+}
+
// BatchSendMsgReq defines the structure for sending a message to multiple recipients.
type BatchSendMsgReq struct {
SendMsg
diff --git a/pkg/common/db/controller/msg.go b/pkg/common/db/controller/msg.go
index fb0a9c702..dfff5c61d 100644
--- a/pkg/common/db/controller/msg.go
+++ b/pkg/common/db/controller/msg.go
@@ -98,6 +98,7 @@ type CommonMsgDatabase interface {
SetSendMsgStatus(ctx context.Context, id string, status int32) error
GetSendMsgStatus(ctx context.Context, id string) (int32, error)
SearchMessage(ctx context.Context, req *pbmsg.SearchMessageReq) (total int32, msgData []*sdkws.MsgData, err error)
+ FindOneByDocIDs(ctx context.Context, docIDs []string, seqs map[string]int64) (map[string]*sdkws.MsgData, error)
// to mq
MsgToMQ(ctx context.Context, key string, msg2mq *sdkws.MsgData) error
@@ -1051,6 +1052,21 @@ func (db *commonMsgDatabase) SearchMessage(ctx context.Context, req *pbmsg.Searc
return total, totalMsgs, nil
}
+func (db *commonMsgDatabase) FindOneByDocIDs(ctx context.Context, conversationIDs []string, seqs map[string]int64) (map[string]*sdkws.MsgData, error) {
+ totalMsgs := make(map[string]*sdkws.MsgData)
+ for _, conversationID := range conversationIDs {
+ seq := seqs[conversationID]
+ docID := db.msg.GetDocID(conversationID, seq)
+ msgs, err := db.msgDocDatabase.FindOneByDocID(ctx, docID)
+ if err != nil {
+ return nil, err
+ }
+ index := db.msg.GetMsgIndex(seq)
+ totalMsgs[conversationID] = convert.MsgDB2Pb(msgs.Msg[index].Msg)
+ }
+ return totalMsgs, nil
+}
+
func (db *commonMsgDatabase) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string) {
db.msgDocDatabase.ConvertMsgsDocLen(ctx, conversationIDs)
}
diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go
index 03769dc74..abad0075a 100644
--- a/pkg/rpcclient/msg.go
+++ b/pkg/rpcclient/msg.go
@@ -17,7 +17,6 @@ package rpcclient
import (
"context"
"encoding/json"
-
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"
@@ -157,6 +156,30 @@ func (m *MessageRpcClient) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqRe
return resp, err
}
+func (m *MessageRpcClient) GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) {
+ log.ZDebug(ctx, "GetMaxSeqs", "conversationIDs", conversationIDs)
+ resp, err := m.Client.GetMaxSeqs(ctx, &msg.GetMaxSeqsReq{
+ ConversationIDs: conversationIDs,
+ })
+ return resp.MaxSeqs, err
+}
+
+func (m *MessageRpcClient) GetHasReadSeqs(ctx context.Context, userID string, conversationIDs []string) (map[string]int64, error) {
+ resp, err := m.Client.GetHasReadSeqs(ctx, &msg.GetHasReadSeqsReq{
+ UserID: userID,
+ ConversationIDs: conversationIDs,
+ })
+ return resp.MaxSeqs, err
+}
+
+func (m *MessageRpcClient) GetMsgByConversationIDs(ctx context.Context, docIDs []string, seqs map[string]int64) (map[string]*sdkws.MsgData, error) {
+ resp, err := m.Client.GetMsgByConversationIDs(ctx, &msg.GetMsgByConversationIDsReq{
+ ConversationIDs: docIDs,
+ MaxSeqs: seqs,
+ })
+ return resp.MsgDatas, err
+}
+
func (m *MessageRpcClient) PullMessageBySeqList(ctx context.Context, req *sdkws.PullMessageBySeqsReq) (*sdkws.PullMessageBySeqsResp, error) {
resp, err := m.Client.PullMessageBySeqs(ctx, req)
return resp, err
From c68a61d8c240143f1b4d58d5d82bb44e807fb5ad Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Fri, 29 Dec 2023 20:38:43 +0800
Subject: [PATCH 035/110] fix setUserInfoEx (#1635)
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* fix bugs
* fix bugs
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* Update go.mod
* Update friend.go
* debug
* debug
* debug
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* I cannot solve todo in test.sh
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* Update go.mod
* fix group notification
* fix group notification
* update openimsdk tools
* update openim server remove duplicate code
* update openim server remove duplicate code
* update user command get
* update user command get
* update response of callback response error
* update black ex
* update join group ex
* update user pb2map
* update go sum
* update go sum
* update updateUserInfoEx
* update updateUserInfoEx
* update updateUserInfoEx add callback functions
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* update pin friend to update friend
* fix go mod
* fix err golangci-lint
* fix UserPb2DBMap
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* fix callback
* fix go.mod
* fix debug
* fix bugs
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* fix updateUserInfoEx
* fix updateUserInfoEx
* modify go.mod
* fix updateUserInfoEx
* fix updateUserInfoEx
---------
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
go.mod | 4 ++--
internal/rpc/user/callback.go | 9 ++++-----
internal/rpc/user/user.go | 2 +-
pkg/callbackstruct/user.go | 12 ++++++------
pkg/common/convert/user.go | 13 ++++++++-----
5 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/go.mod b/go.mod
index 2db34a8b1..393e742de 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.41
+ github.com/OpenIMSDK/protocol v0.0.42
github.com/OpenIMSDK/tools v0.0.21
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
@@ -155,4 +155,4 @@ require (
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
-)
+)
\ No newline at end of file
diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go
index 9e02eb130..092a66a07 100644
--- a/internal/rpc/user/callback.go
+++ b/internal/rpc/user/callback.go
@@ -16,7 +16,6 @@ package user
import (
"context"
-
pbuser "github.com/OpenIMSDK/protocol/user"
"github.com/OpenIMSDK/tools/utils"
@@ -67,16 +66,16 @@ func CallbackBeforeUpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserI
cbReq := &cbapi.CallbackBeforeUpdateUserInfoExReq{
CallbackCommand: cbapi.CallbackBeforeUpdateUserInfoExCommand,
UserID: req.UserInfo.UserID,
- FaceURL: &req.UserInfo.FaceURL,
- Nickname: &req.UserInfo.Nickname,
+ FaceURL: req.UserInfo.FaceURL,
+ Nickname: req.UserInfo.Nickname,
}
resp := &cbapi.CallbackBeforeUpdateUserInfoExResp{}
if err := http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeUpdateUserInfoEx); err != nil {
return err
}
- utils.NotNilReplace(&req.UserInfo.FaceURL, resp.FaceURL)
+ utils.NotNilReplace(req.UserInfo.FaceURL, resp.FaceURL)
utils.NotNilReplace(req.UserInfo.Ex, resp.Ex)
- utils.NotNilReplace(&req.UserInfo.Nickname, resp.Nickname)
+ utils.NotNilReplace(req.UserInfo.Nickname, resp.Nickname)
return nil
}
func CallbackAfterUpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUserInfoExReq) error {
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index fdfd81ed2..5a79fbc91 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -168,7 +168,7 @@ func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser.UpdateUse
if err != nil {
return nil, err
}
- if req.UserInfo.Nickname != "" || req.UserInfo.FaceURL != "" {
+ if req.UserInfo.Nickname != nil || req.UserInfo.FaceURL != nil {
if err := s.groupRpcClient.NotificationUserInfoUpdate(ctx, req.UserInfo.UserID); err != nil {
log.ZError(ctx, "NotificationUserInfoUpdate", err)
}
diff --git a/pkg/callbackstruct/user.go b/pkg/callbackstruct/user.go
index bfb69bd38..98536882d 100644
--- a/pkg/callbackstruct/user.go
+++ b/pkg/callbackstruct/user.go
@@ -47,22 +47,22 @@ type CallbackAfterUpdateUserInfoResp struct {
type CallbackBeforeUpdateUserInfoExReq struct {
CallbackCommand `json:"callbackCommand"`
UserID string `json:"userID"`
- Nickname *string `json:"nickName"`
- FaceURL *string `json:"faceURL"`
+ Nickname *wrapperspb.StringValue `json:"nickName"`
+ FaceURL *wrapperspb.StringValue `json:"faceURL"`
Ex *wrapperspb.StringValue `json:"ex"`
}
type CallbackBeforeUpdateUserInfoExResp struct {
CommonCallbackResp
- Nickname *string `json:"nickName"`
- FaceURL *string `json:"faceURL"`
+ Nickname *wrapperspb.StringValue `json:"nickName"`
+ FaceURL *wrapperspb.StringValue `json:"faceURL"`
Ex *wrapperspb.StringValue `json:"ex"`
}
type CallbackAfterUpdateUserInfoExReq struct {
CallbackCommand `json:"callbackCommand"`
UserID string `json:"userID"`
- Nickname string `json:"nickName"`
- FaceURL string `json:"faceURL"`
+ Nickname *wrapperspb.StringValue `json:"nickName"`
+ FaceURL *wrapperspb.StringValue `json:"faceURL"`
Ex *wrapperspb.StringValue `json:"ex"`
}
type CallbackAfterUpdateUserInfoExResp struct {
diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go
index 6d43595bc..62f80e458 100644
--- a/pkg/common/convert/user.go
+++ b/pkg/common/convert/user.go
@@ -79,14 +79,17 @@ func UserPb2DBMapEx(user *sdkws.UserInfoWithEx) map[string]any {
val := make(map[string]any)
// Map fields from UserInfoWithEx to val
- val["nickname"] = user.Nickname
- val["face_url"] = user.FaceURL
-
+ if user.Nickname != nil {
+ val["nickname"] = user.Nickname.Value
+ }
+ if user.FaceURL != nil {
+ val["face_url"] = user.FaceURL.Value
+ }
if user.Ex != nil {
val["ex"] = user.Ex.Value
}
- if user.GlobalRecvMsgOpt != 0 {
- val["global_recv_msg_opt"] = user.GlobalRecvMsgOpt
+ if user.GlobalRecvMsgOpt != nil {
+ val["global_recv_msg_opt"] = user.GlobalRecvMsgOpt.Value
}
return val
From 1e52376d7b6e8e10e0f0a01988faff1ad5a7b011 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Fri, 29 Dec 2023 20:43:58 +0800
Subject: [PATCH 036/110] fix: fix openim scripts and ci add openim check
(#1632)
* fix: fix openim zk env set
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix openim zk env set
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim docker prom
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
.github/workflows/openimci.yml | 1 -
deployments/templates/env-template.yaml | 64 ++++++++-----------------
docker-compose.yml | 2 +-
scripts/check-all.sh | 12 +++--
scripts/install/environment.sh | 2 +-
tools/component/component.go | 4 +-
6 files changed, 32 insertions(+), 53 deletions(-)
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index d8e988f0b..d16e91ba4 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -201,7 +201,6 @@ jobs:
- name: Build, Start, Check Services and Print Logs for Ubuntu
if: runner.os == 'Linux'
run: |
- sudo make init && \
sudo make build && \
sudo make start && \
sudo make check || \
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index ab9c87c02..f98eda1c1 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -1,39 +1,20 @@
-# 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.
-
-# ======================================
-# ========= Basic Configuration ========
-# ======================================
-
-# The user for authentication or system operations.
-# Default: OPENIM_USER=root
-USER=${OPENIM_USER}
-
-# Password associated with the specified user for authentication.
-# Default: PASSWORD=openIM123
-PASSWORD=${PASSWORD}
-
-# Base URL for the application programming interface (API).
-# Default: API_URL=http://172.28.0.1:10002
-API_URL=${API_URL}
-
-# Directory path for storing data files or related information.
-# Default: DATA_DIR=./
+# -----------------------------------------------------------------------------
+# General Configuration
+# This section contains general configuration options for the entire environment.
+# These options can be set via environment variables. If both environment variables
+# and settings in this .env file exist, the environment variables take precedence.
+# -----------------------------------------------------------------------------
+
+# Local IP address for the service
+# To modify, uncomment and replace with the actual IP address
+OPENIM_IP=${OPENIM_IP}
+
+# Data storage directory
DATA_DIR=${DATA_DIR}
-# Choose the appropriate image address, the default is GITHUB image,
-# you can choose docker hub, for Chinese users can choose Ali Cloud
+# Choose the image address: GitHub (ghcr.io/openimsdk), Docker Hub (openim),
+# or Ali Cloud (registry.cn-hangzhou.aliyuncs.com/openimsdk).
+# Uncomment one of the following three options. Aliyun is recommended for users in China.
# export IMAGE_REGISTRY="ghcr.io/openimsdk"
# export IMAGE_REGISTRY="openim"
# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
@@ -47,10 +28,9 @@ IMAGE_REGISTRY=${IMAGE_REGISTRY}
# Default: DOCKER_BRIDGE_SUBNET=172.28.0.0/16
DOCKER_BRIDGE_SUBNET=${DOCKER_BRIDGE_SUBNET}
-# Gateway for the Docker network.
-# Default: DOCKER_BRIDGE_GATEWAY=172.28.0.1
+# Set and specify the IP addresses of some containers. Generally speaking,
+# you do not need to modify these configurations to facilitate debugging
DOCKER_BRIDGE_GATEWAY=${DOCKER_BRIDGE_GATEWAY}
-
MONGO_NETWORK_ADDRESS=${MONGO_NETWORK_ADDRESS}
REDIS_NETWORK_ADDRESS=${REDIS_NETWORK_ADDRESS}
KAFKA_NETWORK_ADDRESS=${KAFKA_NETWORK_ADDRESS}
@@ -65,15 +45,13 @@ NODE_EXPORTER_NETWORK_ADDRESS=${NODE_EXPORTER_NETWORK_ADDRESS}
OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS}
ALERT_MANAGER_NETWORK_ADDRESS=${ALERT_MANAGER_NETWORK_ADDRESS}
-# ===============================================
-# = Component Extension Configuration =
-# ===============================================
+# -----------------------------------------------------------------------------
+# Database Configuration
+# This section contains environment variable settings related to databases.
+# -----------------------------------------------------------------------------
-# ============ Component Extension Configuration ==========
# ----- ZooKeeper Configuration -----
# Address or hostname for the ZooKeeper service.
-# Default: ZOOKEEPER_ADDRESS=172.28.0.1
-ZOOKEEPER_ADDRESS=${ZOOKEEPER_NETWORK_ADDRESS}
# Port for ZooKeeper service.
# Default: ZOOKEEPER_PORT=12181
diff --git a/docker-compose.yml b/docker-compose.yml
index de3deaaea..bdfee3748 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -122,7 +122,7 @@ services:
server:
ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7}
- # Uncomment and configure the following services as needed
+ ## Uncomment and configure the following services as needed
# openim-admin:
# image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0
# container_name: openim-admin
diff --git a/scripts/check-all.sh b/scripts/check-all.sh
index e1e07bd65..48c38331d 100755
--- a/scripts/check-all.sh
+++ b/scripts/check-all.sh
@@ -30,23 +30,25 @@ OPENIM_VERBOSE=4
openim::log::info "\n# Begin to check all openim service"
-# OpenIM status
# Elegant printing function
print_services_and_ports() {
- service_names=("$1[@]")
- service_ports=("$2[@]")
+ local -n service_names=$1
+ local -n service_ports=$2
echo "+-------------------------+----------+"
echo "| Service Name | Port |"
echo "+-------------------------+----------+"
- for index in "${!service_names}"; do
- printf "| %-23s | %-8s |\n" "${!service_names[$index]}" "${!service_ports[$index]}"
+ for index in "${!service_names[@]}"; do
+ printf "| %-23s | %-8s |\n" "${service_names[$index]}" "${service_ports[$index]}"
done
echo "+-------------------------+----------+"
}
+# Assuming OPENIM_SERVER_NAME_TARGETS and OPENIM_SERVER_PORT_TARGETS are defined
+# Similarly for OPENIM_DEPENDENCY_TARGETS and OPENIM_DEPENDENCY_PORT_TARGETS
+
# Print out services and their ports
print_services_and_ports OPENIM_SERVER_NAME_TARGETS OPENIM_SERVER_PORT_TARGETS
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index feb36c3c1..0e3a428e8 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -378,7 +378,7 @@ def "CALLBACK_TIMEOUT" "5" # 最长超时时间
def "CALLBACK_FAILED_CONTINUE" "true" # 失败后是否继续
###################### Prometheus 配置信息 ######################
# 是否启用 Prometheus
-readonly PROMETHEUS_ENABLE=${PROMETHEUS_ENABLE:-'false'}
+readonly PROMETHEUS_ENABLE=${PROMETHEUS_ENABLE:-'true'}
def "PROMETHEUS_URL" "${GRAFANA_ADDRESS}:${GRAFANA_PORT}"
# Api 服务的 Prometheus 端口
readonly API_PROM_PORT=${API_PROM_PORT:-'20100'}
diff --git a/tools/component/component.go b/tools/component/component.go
index 616ffec2d..e09fa11e6 100644
--- a/tools/component/component.go
+++ b/tools/component/component.go
@@ -223,8 +223,8 @@ func checkMinio() (string, error) {
defer cancel()
if minioClient.IsOffline() {
- str := fmt.Sprintf("Minio server is offline;%s", str)
- return "", ErrComponentStart.Wrap(str)
+ // str := fmt.Sprintf("Minio server is offline;%s", str)
+ // return "", ErrComponentStart.Wrap(str)
}
// Check for localhost in API URL and Minio SignEndpoint
From 959c5a7ae11186862743df1a2e3456341d3754c0 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Fri, 29 Dec 2023 22:29:52 +0800
Subject: [PATCH 037/110] feat: add openim scripts fix and optimize config
about openim source code deployment for this PR? openim ci and scripts
(#1641)
* fix: fix openim zk env set
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix openim zk env set
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim docker prom
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim docker prom
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
deployments/templates/env-template.yaml | 124 +++++++++++-------------
1 file changed, 57 insertions(+), 67 deletions(-)
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index f98eda1c1..e0fd7bc9f 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -4,20 +4,20 @@
# These options can be set via environment variables. If both environment variables
# and settings in this .env file exist, the environment variables take precedence.
# -----------------------------------------------------------------------------
+# ==========================
+# General Configuration
+# ==========================
+# These settings apply to the overall environment.
-# Local IP address for the service
-# To modify, uncomment and replace with the actual IP address
-OPENIM_IP=${OPENIM_IP}
-
-# Data storage directory
+# Data storage directory for persistent data.
+# Example: DATA_DIR=/path/to/data
DATA_DIR=${DATA_DIR}
-# Choose the image address: GitHub (ghcr.io/openimsdk), Docker Hub (openim),
-# or Ali Cloud (registry.cn-hangzhou.aliyuncs.com/openimsdk).
-# Uncomment one of the following three options. Aliyun is recommended for users in China.
-# export IMAGE_REGISTRY="ghcr.io/openimsdk"
-# export IMAGE_REGISTRY="openim"
-# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
+# Docker image registry. Uncomment the preferred one.
+# Options: ghcr.io/openimsdk, openim, registry.cn-hangzhou.aliyuncs.com/openimsdk
+# IMAGE_REGISTRY="ghcr.io/openimsdk"
+# IMAGE_REGISTRY="openim"
+# IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
IMAGE_REGISTRY=${IMAGE_REGISTRY}
# ======================================
@@ -45,23 +45,45 @@ NODE_EXPORTER_NETWORK_ADDRESS=${NODE_EXPORTER_NETWORK_ADDRESS}
OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS}
ALERT_MANAGER_NETWORK_ADDRESS=${ALERT_MANAGER_NETWORK_ADDRESS}
-# -----------------------------------------------------------------------------
-# Database Configuration
-# This section contains environment variable settings related to databases.
-# -----------------------------------------------------------------------------
+# ==============================================================================
+# Configuration Update Instructions
+# ==============================================================================
+# This header outlines the methods to update common variables in config.yaml and .env files.
+# These instructions are vital for maintaining the OpenIM environment's configuration.
+#
+# METHOD 1: Regenerate All Configurations
+# ----------------------------------------
+# Use this method to regenerate all configurations.
+# Steps:
+# 1. Delete existing config files:
+# - openim-server/config/config.yaml
+# - openim-chat/config/config.yaml
+# 2. Modify the .env file as required.
+# 3. Run 'docker compose up -d'. This will regenerate:
+# - config/config.yaml
+#
+# METHOD 2: Modify Individual Configuration Files
+# -----------------------------------------------
+# Use this method to update specific configuration files.
+# Steps:
+# 1. Modify the .env file as necessary.
+# 2. Update the corresponding entries in:
+# - config/config.yaml
+# 3. Restart the services with 'docker compose up -d'.
+# 4. Special Note: If you modify OPENIM_IP, API_OPENIM_PORT, or MINIO_PORT in .env,
+# ensure to update the corresponding services and configurations accordingly.
+#
+# It is essential to follow these methods to ensure consistent and correct application behavior.
+# ==============================================================================
+# Local IP address of the service. Modify if necessary.
+# Example: OPENIM_IP=172.28.0.1,
+OPENIM_IP=${OPENIM_IP}
# ----- ZooKeeper Configuration -----
-# Address or hostname for the ZooKeeper service.
-
# Port for ZooKeeper service.
# Default: ZOOKEEPER_PORT=12181
ZOOKEEPER_PORT=${ZOOKEEPER_PORT}
-# ----- MongoDB Configuration -----
-# Address or hostname for the MongoDB service.
-# Default: MONGO_ADDRESS=172.28.0.1
-MONGO_ADDRESS=${MONGO_NETWORK_ADDRESS}
-
# Port on which MongoDB service is running.
# Default: MONGO_PORT=37017
# MONGO_PORT=${MONGO_PORT}
@@ -79,9 +101,6 @@ MONGO_PASSWORD=${MONGO_PASSWORD}
MONGO_DATABASE=${MONGO_DATABASE}
# ----- Redis Configuration -----
-# Address or hostname for the Redis service.
-# Default: REDIS_ADDRESS=172.28.0.1
-REDIS_ADDRESS=${REDIS_NETWORK_ADDRESS}
# Port on which Redis in-memory data structure store is running.
# Default: REDIS_PORT=16379
@@ -91,11 +110,6 @@ REDIS_PORT=${REDIS_PORT}
# Default: REDIS_PASSWORD=openIM123
REDIS_PASSWORD=${REDIS_PASSWORD}
-# ----- Kafka Configuration -----
-# Address or hostname for the Kafka service.
-# Default: KAFKA_ADDRESS=172.28.0.1
-KAFKA_ADDRESS=${KAFKA_NETWORK_ADDRESS}
-
# Kakfa username to authenticate with the Kafka service.
# KAFKA_USERNAME=${KAFKA_USERNAME}
@@ -107,20 +121,13 @@ KAFKA_PORT=${KAFKA_PORT}
# Default: KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis
KAFKA_LATESTMSG_REDIS_TOPIC=${KAFKA_LATESTMSG_REDIS_TOPIC}
-# Topic in Kafka for pushing messages (e.g. notifications or updates).
-# Default: KAFKA_MSG_PUSH_TOPIC=msgToPush
-KAFKA_MSG_PUSH_TOPIC=${KAFKA_MSG_PUSH_TOPIC}
-
-# Topic in Kafka for storing offline messages in MongoDB.
-# Default: KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql
-KAFKA_OFFLINEMSG_MONGO_TOPIC=${KAFKA_OFFLINEMSG_MONGO_TOPIC}
-
-# ----- MinIO Configuration ----
-# Address or hostname for the MinIO object storage service.
-# Default: MINIO_ADDRESS=172.28.0.1
-MINIO_ADDRESS=${MINIO_NETWORK_ADDRESS}
-
-# Port on which MinIO object storage service is running.
+# MINIO_PORT
+# ----------
+# MINIO_PORT sets the port for the MinIO object storage service.
+# Upon changing this port, the MinIO endpoint URLs in the `config/config.yaml` file must be updated
+# to reflect this change. The endpoints include both the 'endpoint' and 'signEndpoint'
+# under the MinIO configuration.
+#
# Default: MINIO_PORT=10005
MINIO_PORT=${MINIO_PORT}
@@ -133,19 +140,11 @@ MINIO_PORT=${MINIO_PORT}
MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
# ----- Prometheus Configuration -----
-# Address or hostname for the Prometheus service.
-# Default: PROMETHEUS_ADDRESS=172.28.0.1
-PROMETHEUS_ADDRESS=${PROMETHEUS_NETWORK_ADDRESS}
-
# Port on which Prometheus service is running.
# Default: PROMETHEUS_PORT=19090
PROMETHEUS_PORT=${PROMETHEUS_PORT}
# ----- Grafana Configuration -----
-# Address or hostname for the Grafana service.
-# Default: GRAFANA_ADDRESS=172.28.0.1
-GRAFANA_ADDRESS=${GRAFANA_NETWORK_ADDRESS}
-
# Port on which Grafana service is running.
# Default: GRAFANA_PORT=13000
GRAFANA_PORT=${GRAFANA_PORT}
@@ -162,23 +161,19 @@ OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH}
# Default: OPENIM_WEB_PORT=11001
OPENIM_WEB_PORT=${OPENIM_WEB_PORT}
-# Address or hostname for the OpenIM web service.
-# Default: OPENIM_WEB_ADDRESS=172.28.0.1
-OPENIM_WEB_ADDRESS=${OPENIM_WEB_NETWORK_ADDRESS}
-
# ======================================
# ========= OpenIM Server ==============
# ======================================
-
-# Address or hostname for the OpenIM server.
-# Default: OPENIM_SERVER_ADDRESS=172.28.0.1
-OPENIM_SERVER_ADDRESS=${OPENIM_SERVER_NETWORK_ADDRESS}
-
# Port for the OpenIM WebSockets.
# Default: OPENIM_WS_PORT=10001
OPENIM_WS_PORT=${OPENIM_WS_PORT}
-# Port for the OpenIM API.
+# API_OPENIM_PORT
+# ---------------
+# This variable defines the port on which the OpenIM API service will listen.
+# When changing this port, it's essential to update the apiURL in the config.yaml file
+# to ensure the API service is accessible at the new port.
+#
# Default: API_OPENIM_PORT=10002
API_OPENIM_PORT=${API_OPENIM_PORT}
@@ -191,10 +186,6 @@ API_OPENIM_PORT=${API_OPENIM_PORT}
# Default: CHAT_IMAGE_VERSION=main
CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION}
-# Address or hostname for the OpenIM chat service.
-# Default: OPENIM_CHAT_ADDRESS=172.28.0.1
-OPENIM_CHAT_ADDRESS=${OPENIM_CHAT_NETWORK_ADDRESS}
-
# Port for the OpenIM chat API.
# Default: OPENIM_CHAT_API_PORT=10008
OPENIM_CHAT_API_PORT=${OPENIM_CHAT_API_PORT}
@@ -203,7 +194,6 @@ OPENIM_CHAT_API_PORT=${OPENIM_CHAT_API_PORT}
# Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main
OPENIM_CHAT_DATA_DIR=${OPENIM_CHAT_DATA_DIR}
-
# ======================================
# ========== OpenIM Admin ==============
# ======================================
From a7138cb3b7d93f4c9462e8233a8fd9f52a5245bb Mon Sep 17 00:00:00 2001
From: xuexihuang <1339326187@qq.com>
Date: Sat, 30 Dec 2023 10:40:42 +0800
Subject: [PATCH 038/110] feature:grafana web inside (#1636)
* feature:grafana web inside
* fix: using protocal v0.0.42
* fix: review values(but not use)
---
config/templates/config.yaml.template | 2 +-
deployments/templates/openim.yaml | 2 +-
docker-compose.yml | 6 ++++++
internal/api/third.go | 2 +-
pkg/common/config/config.go | 2 +-
scripts/install/environment.sh | 3 +--
6 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template
index 89f11f359..9954a8863 100644
--- a/config/templates/config.yaml.template
+++ b/config/templates/config.yaml.template
@@ -506,7 +506,7 @@ callback:
# The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh
prometheus:
enable: false
- prometheusUrl: 172.28.0.1:13000
+ grafanaUrl: 172.28.0.1:13000
apiPrometheusPort: [20100]
userPrometheusPort: [ 20110 ]
friendPrometheusPort: [ 20120 ]
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index cbb4a8c6e..96d867e10 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -506,7 +506,7 @@ callback:
# The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh
prometheus:
enable: ${PROMETHEUS_ENABLE}
- prometheusUrl: ${PROMETHEUS_URL}
+ grafanaUrl: ${GRAFANA_URL}
apiPrometheusPort: [${API_PROM_PORT}]
userPrometheusPort: [ ${USER_PROM_PORT} ]
friendPrometheusPort: [ ${FRIEND_PROM_PORT} ]
diff --git a/docker-compose.yml b/docker-compose.yml
index bdfee3748..5b1e11d4e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -167,6 +167,12 @@ services:
# hostname: grafana
# user: root
# restart: always
+ # environment:
+ # - GF_SECURITY_ALLOW_EMBEDDING=true
+ # - GF_SESSION_COOKIE_SAMESITE=none
+ # - GF_SESSION_COOKIE_SECURE=true
+ # - GF_AUTH_ANONYMOUS_ENABLED=true
+ # - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
# ports:
# - "${GRAFANA_PORT:-13000}:3000"
# volumes:
diff --git a/internal/api/third.go b/internal/api/third.go
index 37ec55098..0a1ef0fbe 100644
--- a/internal/api/third.go
+++ b/internal/api/third.go
@@ -130,5 +130,5 @@ func (o *ThirdApi) SearchLogs(c *gin.Context) {
}
func GetPrometheus(c *gin.Context) {
- c.Redirect(http.StatusFound, config2.Config.Prometheus.PrometheusUrl)
+ c.Redirect(http.StatusFound, config2.Config.Prometheus.GrafanaUrl)
}
diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go
index ea26ca677..88e87e709 100644
--- a/pkg/common/config/config.go
+++ b/pkg/common/config/config.go
@@ -314,7 +314,7 @@ type configStruct struct {
Prometheus struct {
Enable bool `yaml:"enable"`
- PrometheusUrl string `yaml:"prometheusUrl"`
+ GrafanaUrl string `yaml:"grafanaUrl"`
ApiPrometheusPort []int `yaml:"apiPrometheusPort"`
UserPrometheusPort []int `yaml:"userPrometheusPort"`
FriendPrometheusPort []int `yaml:"friendPrometheusPort"`
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index 0e3a428e8..22a0996fc 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -285,7 +285,6 @@ readonly ALERTMANAGER_SEND_RESOLVED=${ALERTMANAGER_SEND_RESOLVED:-"{SEND_RESOLVE
###################### Grafana 配置信息 ######################
def "GRAFANA_PORT" "13000" # Grafana的端口
def "GRAFANA_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # Grafana的地址
-
###################### RPC Port Configuration Variables ######################
# For launching multiple programs, just fill in multiple ports separated by commas
# For example:
@@ -379,7 +378,7 @@ def "CALLBACK_FAILED_CONTINUE" "true" # 失败后是否继续
###################### Prometheus 配置信息 ######################
# 是否启用 Prometheus
readonly PROMETHEUS_ENABLE=${PROMETHEUS_ENABLE:-'true'}
-def "PROMETHEUS_URL" "${GRAFANA_ADDRESS}:${GRAFANA_PORT}"
+readonly GRAFANA_URL=${GRAFANA_URL:-"http://${OPENIM_IP}:${GRAFANA_PORT}/"}
# Api 服务的 Prometheus 端口
readonly API_PROM_PORT=${API_PROM_PORT:-'20100'}
# User 服务的 Prometheus 端口
From bed112d037333c4a78ba8cf17f490aefbe3ec239 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Sat, 30 Dec 2023 11:12:19 +0800
Subject: [PATCH 039/110] Update check-all.sh (#1643)
---
scripts/check-all.sh | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/scripts/check-all.sh b/scripts/check-all.sh
index 48c38331d..7b53e4a89 100755
--- a/scripts/check-all.sh
+++ b/scripts/check-all.sh
@@ -30,16 +30,18 @@ OPENIM_VERBOSE=4
openim::log::info "\n# Begin to check all openim service"
+# Elegant printing function
# Elegant printing function
print_services_and_ports() {
- local -n service_names=$1
- local -n service_ports=$2
+ local service_names=("$@")
+ local half_length=$((${#service_names[@]} / 2))
+ local service_ports=("${service_names[@]:half_length}")
echo "+-------------------------+----------+"
echo "| Service Name | Port |"
echo "+-------------------------+----------+"
- for index in "${!service_names[@]}"; do
+ for ((index=0; index < half_length; index++)); do
printf "| %-23s | %-8s |\n" "${service_names[$index]}" "${service_ports[$index]}"
done
@@ -50,11 +52,10 @@ print_services_and_ports() {
# Similarly for OPENIM_DEPENDENCY_TARGETS and OPENIM_DEPENDENCY_PORT_TARGETS
# Print out services and their ports
-print_services_and_ports OPENIM_SERVER_NAME_TARGETS OPENIM_SERVER_PORT_TARGETS
+print_services_and_ports "${OPENIM_SERVER_NAME_TARGETS[@]}" "${OPENIM_SERVER_PORT_TARGETS[@]}"
# Print out dependencies and their ports
-print_services_and_ports OPENIM_DEPENDENCY_TARGETS OPENIM_DEPENDENCY_PORT_TARGETS
-
+print_services_and_ports "${OPENIM_DEPENDENCY_TARGETS[@]}" "${OPENIM_DEPENDENCY_PORT_TARGETS[@]}"
# OpenIM check
echo "++ The port being checked: ${OPENIM_SERVER_PORT_LISTARIES[@]}"
@@ -91,4 +92,4 @@ else
echo "++++ Check all openim service ports successfully !"
fi
-set -e
\ No newline at end of file
+set -e
From 49f4e3f0deaa4c165d1f3d2bcc1d35368544401f Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Mon, 1 Jan 2024 21:11:57 +0800
Subject: [PATCH 040/110] fix: fix Security vulnerability (#1646)
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
docker-compose.yml | 2 +-
pkg/common/discoveryregister/kubernetes/kubernetes.go | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 5b1e11d4e..fd71896a7 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -124,7 +124,7 @@ services:
## Uncomment and configure the following services as needed
# openim-admin:
- # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin:toc-base-open-docker.35
# container_name: openim-admin
# restart: always
# ports:
diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go
index 2ff1539e6..c10518056 100644
--- a/pkg/common/discoveryregister/kubernetes/kubernetes.go
+++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go
@@ -55,14 +55,17 @@ func (cli *K8sDR) Register(serviceName, host string, port int, opts ...grpc.Dial
return nil
}
+
func (cli *K8sDR) UnRegister() error {
return nil
}
+
func (cli *K8sDR) CreateRpcRootNodes(serviceNames []string) error {
return nil
}
+
func (cli *K8sDR) RegisterConf2Registry(key string, conf []byte) error {
return nil
@@ -123,6 +126,8 @@ func getMsgGatewayHost(ctx context.Context) []string {
log.ZInfo(ctx, "getMsgGatewayHost", "instance", instance, "selfPodName", selfPodName, "replicas", replicas, "ns", ns, "ret", ret)
return ret
}
+
+// GetConns returns the gRPC client connections to the specified service.
func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
@@ -142,6 +147,7 @@ func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc
return ret, nil
}
}
+
func (cli *K8sDR) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
return grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
@@ -151,9 +157,11 @@ func (cli *K8sDR) GetSelfConnTarget() string {
return cli.rpcRegisterAddr
}
+
func (cli *K8sDR) AddOption(opts ...grpc.DialOption) {
cli.options = append(cli.options, opts...)
}
+
func (cli *K8sDR) CloseConn(conn *grpc.ClientConn) {
conn.Close()
}
From 3fffc2f2123c35bc151e9202595cb0d39293893d Mon Sep 17 00:00:00 2001
From: chao <48119764+withchao@users.noreply.github.com>
Date: Tue, 2 Jan 2024 11:51:09 +0800
Subject: [PATCH 041/110] feat: support websocket first message method response
code (#1651)
* upgrade package and rtc convert
* upgrade package and rtc convert
* upgrade package and rtc convert
* upgrade package and rtc convert
* friend user
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* s3 form data
* ws
* ws
* ws
* ws
* ws
---
internal/msggateway/constant.go | 1 +
internal/msggateway/n_ws_server.go | 131 +++++++++++++++++------------
2 files changed, 77 insertions(+), 55 deletions(-)
diff --git a/internal/msggateway/constant.go b/internal/msggateway/constant.go
index fe5f09bdc..045629b4e 100644
--- a/internal/msggateway/constant.go
+++ b/internal/msggateway/constant.go
@@ -26,6 +26,7 @@ const (
Compression = "compression"
GzipCompressionProtocol = "gzip"
BackgroundStatus = "isBackground"
+ MsgResp = "isMsgResp"
)
const (
diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go
index 70c2f8fe0..cdc3d719c 100644
--- a/internal/msggateway/n_ws_server.go
+++ b/internal/msggateway/n_ws_server.go
@@ -16,7 +16,10 @@ package msggateway
import (
"context"
+ "encoding/json"
"errors"
+ "fmt"
+ "github.com/OpenIMSDK/tools/apiresp"
"net/http"
"os"
"os/signal"
@@ -422,84 +425,102 @@ func (ws *WsServer) unregisterClient(client *Client) {
)
}
-func (ws *WsServer) wsHandler(w http.ResponseWriter, r *http.Request) {
- connContext := newContext(w, r)
+func (ws *WsServer) ParseWSArgs(r *http.Request) (args *WSArgs, err error) {
+ var v WSArgs
+ defer func() {
+ args = &v
+ }()
+ query := r.URL.Query()
+ v.MsgResp, _ = strconv.ParseBool(query.Get(MsgResp))
if ws.onlineUserConnNum.Load() >= ws.wsMaxConnNum {
- httpError(connContext, errs.ErrConnOverMaxNumLimit)
- return
+ return nil, errs.ErrConnOverMaxNumLimit.Wrap("over max conn num limit")
}
- var (
- token string
- userID string
- platformIDStr string
- exists bool
- compression bool
- )
-
- token, exists = connContext.Query(Token)
- if !exists {
- httpError(connContext, errs.ErrConnArgsErr)
- return
+ if v.Token = query.Get(Token); v.Token == "" {
+ return nil, errs.ErrConnArgsErr.Wrap("token is empty")
}
- userID, exists = connContext.Query(WsUserID)
- if !exists {
- httpError(connContext, errs.ErrConnArgsErr)
- return
+ if v.UserID = query.Get(WsUserID); v.UserID == "" {
+ return nil, errs.ErrConnArgsErr.Wrap("sendID is empty")
}
- platformIDStr, exists = connContext.Query(PlatformID)
- if !exists {
- httpError(connContext, errs.ErrConnArgsErr)
- return
+ platformIDStr := query.Get(PlatformID)
+ if platformIDStr == "" {
+ return nil, errs.ErrConnArgsErr.Wrap("platformID is empty")
}
platformID, err := strconv.Atoi(platformIDStr)
if err != nil {
- httpError(connContext, errs.ErrConnArgsErr)
- return
+ return nil, errs.ErrConnArgsErr.Wrap("platformID is not int")
+ }
+ v.PlatformID = platformID
+ if err = authverify.WsVerifyToken(v.Token, v.UserID, platformID); err != nil {
+ return nil, err
+ }
+ if query.Get(Compression) == GzipCompressionProtocol {
+ v.Compression = true
}
- if err = authverify.WsVerifyToken(token, userID, platformID); err != nil {
- httpError(connContext, err)
- return
+ if r.Header.Get(Compression) == GzipCompressionProtocol {
+ v.Compression = true
}
- m, err := ws.cache.GetTokensWithoutError(context.Background(), userID, platformID)
+ m, err := ws.cache.GetTokensWithoutError(context.Background(), v.UserID, platformID)
if err != nil {
- httpError(connContext, err)
- return
+ return nil, err
}
- if v, ok := m[token]; ok {
+ if v, ok := m[v.Token]; ok {
switch v {
case constant.NormalToken:
case constant.KickedToken:
- httpError(connContext, errs.ErrTokenKicked.Wrap())
- return
+ return nil, errs.ErrTokenKicked.Wrap()
default:
- httpError(connContext, errs.ErrTokenUnknown.Wrap())
- return
+ return nil, errs.ErrTokenUnknown.Wrap(fmt.Sprintf("token status is %d", v))
}
} else {
- httpError(connContext, errs.ErrTokenNotExist.Wrap())
- return
+ return nil, errs.ErrTokenNotExist.Wrap()
}
+ return &v, nil
+}
- wsLongConn := newGWebSocket(WebSocket, ws.handshakeTimeout, ws.writeBufferSize)
- err = wsLongConn.GenerateLongConn(w, r)
- if err != nil {
- httpError(connContext, err)
- return
- }
- compressProtoc, exists := connContext.Query(Compression)
- if exists {
- if compressProtoc == GzipCompressionProtocol {
- compression = true
+type WSArgs struct {
+ Token string
+ UserID string
+ PlatformID int
+ Compression bool
+ MsgResp bool
+}
+
+func (ws *WsServer) wsHandler(w http.ResponseWriter, r *http.Request) {
+ connContext := newContext(w, r)
+ args, pErr := ws.ParseWSArgs(r)
+ var wsLongConn *GWebSocket
+ if args.MsgResp {
+ wsLongConn = newGWebSocket(WebSocket, ws.handshakeTimeout, ws.writeBufferSize)
+ if err := wsLongConn.GenerateLongConn(w, r); err != nil {
+ httpError(connContext, err)
+ return
}
- }
- compressProtoc, exists = connContext.GetHeader(Compression)
- if exists {
- if compressProtoc == GzipCompressionProtocol {
- compression = true
+ data, err := json.Marshal(apiresp.ParseError(pErr))
+ if err != nil {
+ _ = wsLongConn.Close()
+ return
+ }
+ if err := wsLongConn.WriteMessage(MessageText, data); err != nil {
+ _ = wsLongConn.Close()
+ return
+ }
+ if pErr != nil {
+ _ = wsLongConn.Close()
+ return
+ }
+ } else {
+ if pErr != nil {
+ httpError(connContext, pErr)
+ return
+ }
+ wsLongConn = newGWebSocket(WebSocket, ws.handshakeTimeout, ws.writeBufferSize)
+ if err := wsLongConn.GenerateLongConn(w, r); err != nil {
+ httpError(connContext, err)
+ return
}
}
client := ws.clientPool.Get().(*Client)
- client.ResetClient(connContext, wsLongConn, connContext.GetBackground(), compression, ws, token)
+ client.ResetClient(connContext, wsLongConn, connContext.GetBackground(), args.Compression, ws, args.Token)
ws.registerChan <- client
go client.readMessage()
}
From d594d6f5171b4e54772803b3e4573d357f4ad34f Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Tue, 2 Jan 2024 12:42:46 +0800
Subject: [PATCH 042/110] fix: install-im-server (#1648)
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
scripts/install-im-server.sh | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index 47db34433..e52a1a21a 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -45,8 +45,19 @@ pushd "${OPENIM_ROOT}"
${DOCKER_COMPOSE_COMMAND} stop
curl https://gitee.com/openimsdk/openim-docker/raw/main/example/full-openim-server-and-chat.yml -o docker-compose.yml
${DOCKER_COMPOSE_COMMAND} up -d
-sleep 60
+
+# Wait for a short period to allow containers to initialize
+sleep 10
+
+# Check the status of the containers
+if ! ${DOCKER_COMPOSE_COMMAND} ps | grep -q 'Up'; then
+ echo "Error: One or more docker containers failed to start."
+ ${DOCKER_COMPOSE_COMMAND} logs
+ exit 1
+fi
+
+sleep 50 # Keep the original 60-second wait, adjusted for the 10-second check above
${DOCKER_COMPOSE_COMMAND} logs openim-server
${DOCKER_COMPOSE_COMMAND} ps
-popd
\ No newline at end of file
+popd
From c19bafc49dad633e83b669e3601d5b361a5c8ce0 Mon Sep 17 00:00:00 2001
From: Gordon <46924906+FGadvancer@users.noreply.github.com>
Date: Tue, 2 Jan 2024 15:37:05 +0800
Subject: [PATCH 043/110] fix: modify dismissed group's status. (#1655)
* fix: add notifications for some notifications.
* fix: modify dismissed group's status.
---
pkg/common/db/controller/group.go | 2 +-
pkg/common/db/mgo/group.go | 4 ++--
pkg/common/db/mgo/group_member.go | 10 +++++++---
pkg/common/db/table/relation/group.go | 2 +-
4 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/pkg/common/db/controller/group.go b/pkg/common/db/controller/group.go
index 4147d59c0..decd868d6 100644
--- a/pkg/common/db/controller/group.go
+++ b/pkg/common/db/controller/group.go
@@ -197,7 +197,7 @@ func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data ma
func (g *groupDatabase) DismissGroup(ctx context.Context, groupID string, deleteMember bool) error {
return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
c := g.cache.NewCache()
- if err := g.groupDB.UpdateState(ctx, groupID, constant.GroupStatusDismissed); err != nil {
+ if err := g.groupDB.UpdateStatus(ctx, groupID, constant.GroupStatusDismissed); err != nil {
return err
}
if deleteMember {
diff --git a/pkg/common/db/mgo/group.go b/pkg/common/db/mgo/group.go
index 65dbbca59..a9c6d1eb8 100644
--- a/pkg/common/db/mgo/group.go
+++ b/pkg/common/db/mgo/group.go
@@ -49,8 +49,8 @@ func (g *GroupMgo) Create(ctx context.Context, groups []*relation.GroupModel) (e
return mgoutil.InsertMany(ctx, g.coll, groups)
}
-func (g *GroupMgo) UpdateState(ctx context.Context, groupID string, state int32) (err error) {
- return g.UpdateMap(ctx, groupID, map[string]any{"state": state})
+func (g *GroupMgo) UpdateStatus(ctx context.Context, groupID string, status int32) (err error) {
+ return g.UpdateMap(ctx, groupID, map[string]any{"status": status})
}
func (g *GroupMgo) UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error) {
diff --git a/pkg/common/db/mgo/group_member.go b/pkg/common/db/mgo/group_member.go
index 8c3041901..8e3dd1efa 100644
--- a/pkg/common/db/mgo/group_member.go
+++ b/pkg/common/db/mgo/group_member.go
@@ -51,7 +51,11 @@ func (g *GroupMemberMgo) Create(ctx context.Context, groupMembers []*relation.Gr
}
func (g *GroupMemberMgo) Delete(ctx context.Context, groupID string, userIDs []string) (err error) {
- return mgoutil.DeleteMany(ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
+ filter := bson.M{"group_id": groupID}
+ if len(userIDs) > 0 {
+ filter["user_id"] = bson.M{"$in": userIDs}
+ }
+ return mgoutil.DeleteMany(ctx, g.coll, filter)
}
func (g *GroupMemberMgo) UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error {
@@ -84,8 +88,8 @@ func (g *GroupMemberMgo) FindRoleLevelUserIDs(ctx context.Context, groupID strin
}
func (g *GroupMemberMgo) SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*relation.GroupMemberModel, err error) {
- //TODO implement me
- panic("implement me")
+ filter := bson.M{"group_id": groupID, "nickname": bson.M{"$regex": keyword}}
+ return mgoutil.FindPage[*relation.GroupMemberModel](ctx, g.coll, filter, pagination)
}
func (g *GroupMemberMgo) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
diff --git a/pkg/common/db/table/relation/group.go b/pkg/common/db/table/relation/group.go
index bb1ddd878..57d6b1d62 100644
--- a/pkg/common/db/table/relation/group.go
+++ b/pkg/common/db/table/relation/group.go
@@ -42,7 +42,7 @@ type GroupModel struct {
type GroupModelInterface interface {
Create(ctx context.Context, groups []*GroupModel) (err error)
UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error)
- UpdateState(ctx context.Context, groupID string, state int32) (err error)
+ UpdateStatus(ctx context.Context, groupID string, status int32) (err error)
Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
Take(ctx context.Context, groupID string) (group *GroupModel, err error)
Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*GroupModel, err error)
From 11108e1ddf3318bda80eed8cd9df0c4bb687614c Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Tue, 2 Jan 2024 20:59:26 +0800
Subject: [PATCH 044/110] fix: release openim version not auto build (#1660)
---
build/goreleaser.yaml | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/build/goreleaser.yaml b/build/goreleaser.yaml
index ed7f7cd1b..93fe9f4c8 100644
--- a/build/goreleaser.yaml
+++ b/build/goreleaser.yaml
@@ -3,12 +3,36 @@
before:
hooks:
+ - make clean
# You may remove this if you don't use go modules.
- make tidy
- make copyright.add
# you may remove this if you don't need go generate
- go generate ./...
+git:
+ # What should be used to sort tags when gathering the current and previous
+ # tags if there are more than one tag in the same commit.
+ #
+ # Default: '-version:refname'
+ tag_sort: -version:creatordate
+
+ # What should be used to specify prerelease suffix while sorting tags when gathering
+ # the current and previous tags if there are more than one tag in the same commit.
+ #
+ # Since: v1.17
+ prerelease_suffix: "-"
+
+ # Tags to be ignored by GoReleaser.
+ # This means that GoReleaser will not pick up tags that match any of the
+ # provided values as either previous or current tags.
+ #
+ # Templates: allowed.
+ # Since: v1.21.
+ ignore_tags:
+ - nightly
+ # - "{{.Env.IGNORE_TAG}}"
+
snapshot:
name_template: "{{ incpatch .Version }}-next"
@@ -495,4 +519,4 @@ checksum:
algorithm: sha256
release:
- prerelease: auto
\ No newline at end of file
+ prerelease: auto
From f1ba5c2bffdc5b4f28a798fa3a6bdea2f59c3206 Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Wed, 3 Jan 2024 10:07:01 +0800
Subject: [PATCH 045/110] fix: fix the error (#1653)
---
internal/rpc/user/user.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 5a79fbc91..8219ec0bc 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -558,7 +558,7 @@ func (s *userServer) userModelToResp(users []*relation.UserModel) *pbuser.Search
accounts := make([]*pbuser.NotificationAccountInfo, 0)
var total int64
for _, v := range users {
- if v.AppMangerLevel == constant.AppNotificationAdmin || v.AppMangerLevel == constant.AppAdmin {
+ if v.AppMangerLevel == constant.AppNotificationAdmin {
temp := &pbuser.NotificationAccountInfo{
UserID: v.UserID,
FaceURL: v.FaceURL,
From 5d1cf8c06150f75c5f6d7c2a4cb48b722edd3a0a Mon Sep 17 00:00:00 2001
From: Gordon <46924906+FGadvancer@users.noreply.github.com>
Date: Wed, 3 Jan 2024 15:32:42 +0800
Subject: [PATCH 046/110] fix: Adjust the logic in multiTerminalLoginChecker to
prevent onlineUserNum from decreasing below zero, thereby avoiding negative
values. (#1658)
* fix: add notifications for some notifications.
* fix: modify dismissed group's status.
* fix: Adjust the logic in multiTerminalLoginChecker to prevent onlineUserNum from decreasing below zero, thereby avoiding negative values.
---
internal/msggateway/n_ws_server.go | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go
index cdc3d719c..7e8129105 100644
--- a/internal/msggateway/n_ws_server.go
+++ b/internal/msggateway/n_ws_server.go
@@ -345,11 +345,7 @@ func (ws *WsServer) multiTerminalLoginChecker(clientOK bool, oldClients []*Clien
if !clientOK {
return
}
-
- isDeleteUser := ws.clients.deleteClients(newClient.UserID, oldClients)
- if isDeleteUser {
- ws.onlineUserNum.Add(-1)
- }
+ ws.clients.deleteClients(newClient.UserID, oldClients)
for _, c := range oldClients {
err := c.KickOnlineMessage()
if err != nil {
From 587533df4dc29b2c4921259c03b3adee0107b0eb Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Wed, 3 Jan 2024 15:46:38 +0800
Subject: [PATCH 047/110] fix: update Notification update resp (#1663)
* fix: fix the error
* fix: fix the SearchNotificationAccount resp
* fix: fix the god
* Update install-im-server.sh
* Update install-im-server.sh
---------
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
go.mod | 4 ++--
go.sum | 4 ++--
internal/rpc/user/user.go | 2 +-
scripts/install-im-server.sh | 7 +++----
4 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/go.mod b/go.mod
index 393e742de..f1b3239c3 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.42
+ github.com/OpenIMSDK/protocol v0.0.43
github.com/OpenIMSDK/tools v0.0.21
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
@@ -155,4 +155,4 @@ require (
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
-)
\ No newline at end of file
+)
diff --git a/go.sum b/go.sum
index fc1d15242..e72d862e6 100644
--- a/go.sum
+++ b/go.sum
@@ -18,8 +18,8 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.42 h1:vIWXqZJZZ1ddleJA25fxhjZ1GyEHATpYM3wVWh4/+PY=
-github.com/OpenIMSDK/protocol v0.0.42/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/protocol v0.0.43 h1:8B921vEyO7r0AfQfZd7kCycYja+hJ2vuIZsKge/WRhU=
+github.com/OpenIMSDK/protocol v0.0.43/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 8219ec0bc..824b8a9bb 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -558,7 +558,7 @@ func (s *userServer) userModelToResp(users []*relation.UserModel) *pbuser.Search
accounts := make([]*pbuser.NotificationAccountInfo, 0)
var total int64
for _, v := range users {
- if v.AppMangerLevel == constant.AppNotificationAdmin {
+ if v.AppMangerLevel == constant.AppNotificationAdmin && !utils.IsContain(v.UserID, config.Config.IMAdmin.UserID) {
temp := &pbuser.NotificationAccountInfo{
UserID: v.UserID,
FaceURL: v.FaceURL,
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index e52a1a21a..a21ae134d 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -43,20 +43,19 @@ fi
"${OPENIM_ROOT}"/scripts/init-config.sh
pushd "${OPENIM_ROOT}"
${DOCKER_COMPOSE_COMMAND} stop
-curl https://gitee.com/openimsdk/openim-docker/raw/main/example/full-openim-server-and-chat.yml -o docker-compose.yml
+curl https://raw.githubusercontent.com/openimsdk/openim-docker/main/docker-compose.yaml -o docker-compose.yml
${DOCKER_COMPOSE_COMMAND} up -d
# Wait for a short period to allow containers to initialize
-sleep 10
+sleep 30
# Check the status of the containers
if ! ${DOCKER_COMPOSE_COMMAND} ps | grep -q 'Up'; then
echo "Error: One or more docker containers failed to start."
${DOCKER_COMPOSE_COMMAND} logs
- exit 1
fi
-sleep 50 # Keep the original 60-second wait, adjusted for the 10-second check above
+sleep 30 # Keep the original 60-second wait, adjusted for the 10-second check above
${DOCKER_COMPOSE_COMMAND} logs openim-server
${DOCKER_COMPOSE_COMMAND} ps
From 9e2a25681778a7889d0c434d3fe81da11847fdf4 Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Wed, 3 Jan 2024 17:24:02 +0800
Subject: [PATCH 048/110] fix: fix the imAdmin permission (#1664)
* fix: fix the error
* fix: fix the SearchNotificationAccount resp
* fix: fix the god
* Update install-im-server.sh
* Update install-im-server.sh
* fix: fix the searchNotificationAccounts
* fix: fix the imAdmin competence
* fix: fix the error
* fix: fix the checkAdminV3
---------
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
internal/rpc/user/user.go | 2 +-
pkg/authverify/token.go | 11 +++++++++--
pkg/common/db/controller/user.go | 7 +++++++
pkg/common/db/mgo/user.go | 4 ++++
pkg/common/db/table/relation/user.go | 1 +
pkg/rpcclient/user.go | 3 +++
6 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 824b8a9bb..51403d631 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -515,7 +515,7 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.
return resp, nil
}
- _, users, err := s.UserDatabase.Page(ctx, req.Pagination)
+ users, err := s.UserDatabase.FindNotification(ctx, constant.AppNotificationAdmin)
if err != nil {
return nil, err
}
diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go
index d9aa0dbb1..e810dfecf 100644
--- a/pkg/authverify/token.go
+++ b/pkg/authverify/token.go
@@ -38,6 +38,9 @@ func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
if utils.IsContain(opUserID, config.Config.Manager.UserID) {
return nil
}
+ if utils.IsContain(opUserID, config.Config.IMAdmin.UserID) {
+ return nil
+ }
if opUserID == ownerUserID {
return nil
}
@@ -45,13 +48,16 @@ func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
}
func IsAppManagerUid(ctx context.Context) bool {
- return utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID)
+ return utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) || utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID)
}
func CheckAdmin(ctx context.Context) error {
if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) {
return nil
}
+ if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID) {
+ return nil
+ }
return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx)))
}
func CheckIMAdmin(ctx context.Context) error {
@@ -69,7 +75,8 @@ func ParseRedisInterfaceToken(redisToken any) (*tokenverify.Claims, error) {
}
func IsManagerUserID(opUserID string) bool {
- return utils.IsContain(opUserID, config.Config.Manager.UserID)
+ return utils.IsContain(opUserID, config.Config.Manager.UserID) || utils.IsContain(opUserID, config.Config.IMAdmin.UserID)
+
}
func WsVerifyToken(token, userID string, platformID int) error {
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index 72bdf6b06..a109b81ef 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -40,6 +40,8 @@ type UserDatabase interface {
Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error)
// Find userInfo By Nickname
FindByNickname(ctx context.Context, nickname string) (users []*relation.UserModel, err error)
+ // Find notificationAccounts
+ FindNotification(ctx context.Context, level int64) (users []*relation.UserModel, err error)
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db
Create(ctx context.Context, users []*relation.UserModel) (err error)
// Update update (non-zero value) external guarantee userID exists
@@ -140,6 +142,11 @@ func (u *userDatabase) FindByNickname(ctx context.Context, nickname string) (use
return u.userDB.TakeByNickname(ctx, nickname)
}
+// Find notificationAccouts
+func (u *userDatabase) FindNotification(ctx context.Context, level int64) (users []*relation.UserModel, err error) {
+ return u.userDB.TakeNotification(ctx, level)
+}
+
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db.
func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) {
return u.tx.Transaction(ctx, func(ctx context.Context) error {
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 0ca711ad8..27ca264dd 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -65,6 +65,10 @@ func (u *UserMgo) Take(ctx context.Context, userID string) (user *relation.UserM
return mgoutil.FindOne[*relation.UserModel](ctx, u.coll, bson.M{"user_id": userID})
}
+func (u *UserMgo) TakeNotification(ctx context.Context, level int64) (user []*relation.UserModel, err error) {
+ return mgoutil.Find[*relation.UserModel](ctx, u.coll, bson.M{"app_manger_level": level})
+}
+
func (u *UserMgo) TakeByNickname(ctx context.Context, nickname string) (user []*relation.UserModel, err error) {
return mgoutil.Find[*relation.UserModel](ctx, u.coll, bson.M{"nickname": nickname})
}
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index 8917ba55f..fc116adc2 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -53,6 +53,7 @@ type UserModelInterface interface {
UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
Find(ctx context.Context, userIDs []string) (users []*UserModel, err error)
Take(ctx context.Context, userID string) (user *UserModel, err error)
+ TakeNotification(ctx context.Context, level int64) (user []*UserModel, err error)
TakeByNickname(ctx context.Context, nickname string) (user []*UserModel, err error)
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
Exist(ctx context.Context, userID string) (exist bool, err error)
diff --git a/pkg/rpcclient/user.go b/pkg/rpcclient/user.go
index de633ee30..451914cd3 100644
--- a/pkg/rpcclient/user.go
+++ b/pkg/rpcclient/user.go
@@ -64,6 +64,9 @@ func NewUserRpcClient(client discoveryregistry.SvcDiscoveryRegistry) UserRpcClie
// GetUsersInfo retrieves information for multiple users based on their user IDs.
func (u *UserRpcClient) GetUsersInfo(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error) {
+ if len(userIDs) == 0 {
+ return []*sdkws.UserInfo{}, nil
+ }
resp, err := u.Client.GetDesignateUsers(ctx, &user.GetDesignateUsersReq{
UserIDs: userIDs,
})
From e1c2e94ec92db799bdefbbdd6272721884d84c04 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Thu, 4 Jan 2024 14:15:14 +0800
Subject: [PATCH 049/110] Update env-template.yaml (#1670)
* Update env-template.yaml
* Update env-template.yaml
* Update env-template.yaml
---
deployments/templates/env-template.yaml | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index e0fd7bc9f..1772af644 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -177,7 +177,6 @@ OPENIM_WS_PORT=${OPENIM_WS_PORT}
# Default: API_OPENIM_PORT=10002
API_OPENIM_PORT=${API_OPENIM_PORT}
-
# ======================================
# ========== OpenIM Chat ===============
# ======================================
@@ -188,8 +187,14 @@ CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION}
# Port for the OpenIM chat API.
# Default: OPENIM_CHAT_API_PORT=10008
+# !!! TODO: Do not change the chat port https://github.com/openimsdk/chat/issues/365
OPENIM_CHAT_API_PORT=${OPENIM_CHAT_API_PORT}
+# Port for the OpenIM admin API.
+# Default: OPENIM_ADMIN_API_PORT=10009
+# !!! TODO: Do not change the chat port https://github.com/openimsdk/chat/issues/365
+OPENIM_ADMIN_API_PORT=${OPENIM_ADMIN_API_PORT}
+
# Directory path for storing data files or related information for OpenIM chat.
# Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main
OPENIM_CHAT_DATA_DIR=${OPENIM_CHAT_DATA_DIR}
@@ -201,10 +206,6 @@ OPENIM_CHAT_DATA_DIR=${OPENIM_CHAT_DATA_DIR}
# Branch name for OpenIM server.
# Default: SERVER_IMAGE_VERSION=main
SERVER_IMAGE_VERSION=${SERVER_IMAGE_VERSION}
-
-# Port for the OpenIM admin API.
-# Default: OPENIM_ADMIN_API_PORT=10009
-OPENIM_ADMIN_API_PORT=${OPENIM_ADMIN_API_PORT}
# Port for the node exporter.
# Default: NODE_EXPORTER_PORT=19100
@@ -224,4 +225,4 @@ OPENIM_ADMIN_FRONT_PORT=${OPENIM_ADMIN_FRONT_PORT}
# Port for the alertmanager.
# Default: ALERT_MANAGER_PORT=19093
-ALERT_MANAGER_PORT=${ALERT_MANAGER_PORT}
\ No newline at end of file
+ALERT_MANAGER_PORT=${ALERT_MANAGER_PORT}
From 09c3229d9d5819732c87938ce55438ec22de1c15 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Thu, 4 Jan 2024 16:01:32 +0800
Subject: [PATCH 050/110] feat(main): fix openim docker start openim server
internal port lock (#1673)
* fix: fix the bug
* fix: fix the imAdmin permission and searchNoficitaion resp
* 2023 Annual Summary Reflections and Aspirations
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Co-authored-by: luhaoling <2198702716@qq.com>
---
pkg/authverify/token.go | 1 -
scripts/docker-start-all.sh | 19 +++++++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go
index e810dfecf..4c71224ee 100644
--- a/pkg/authverify/token.go
+++ b/pkg/authverify/token.go
@@ -76,7 +76,6 @@ func ParseRedisInterfaceToken(redisToken any) (*tokenverify.Claims, error) {
func IsManagerUserID(opUserID string) bool {
return utils.IsContain(opUserID, config.Config.Manager.UserID) || utils.IsContain(opUserID, config.Config.IMAdmin.UserID)
-
}
func WsVerifyToken(token, userID string, platformID int) error {
diff --git a/scripts/docker-start-all.sh b/scripts/docker-start-all.sh
index 3c83b02bb..85954a677 100755
--- a/scripts/docker-start-all.sh
+++ b/scripts/docker-start-all.sh
@@ -21,6 +21,25 @@ set -o pipefail
#fixme This scripts is the total startup scripts
#fixme The full name of the shell scripts that needs to be started is placed in the need_to_start_server_shell array
+# Fixed ports inside the docker startup container
+export OPENIM_WS_PORT=10001
+export API_OPENIM_PORT=10002
+export API_PROM_PORT=20100
+export USER_PROM_PORT=20110
+export FRIEND_PROM_PORT=20120
+export MESSAGE_PROM_PORT=20130
+export MSG_GATEWAY_PROM_PORT=20140
+export GROUP_PROM_PORT=20150
+export AUTH_PROM_PORT=20160
+export PUSH_PROM_PORT=20170
+export CONVERSATION_PROM_PORT=20230
+export RTC_PROM_PORT=21300
+export THIRD_PROM_PORT=21301
+export MSG_TRANSFER_PROM_PORT=21400
+export MSG_TRANSFER_PROM_PORT=21401
+export MSG_TRANSFER_PROM_PORT=21402
+export MSG_TRANSFER_PROM_PORT=21403
+
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${OPENIM_ROOT}/scripts/install/common.sh"
From d3047d73b69b505203edad3c1ba109e56d2873ef Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Thu, 4 Jan 2024 16:04:15 +0800
Subject: [PATCH 051/110] fix: dissmissGroup and lack of keyword bug (#1672)
* feat: add GetConversationsUnreadSeqAndMaxSeq func
* feat: add GetConversationsUnreadSeqAndMaxSeq func
* feat: add GetConversationsUnreadSeqAndMaxSeq func
* fix: fix the conflect
* feat: add GetConversationList Api
* fix: fix the error
* fix: move the GetConversationList to conversation folder
* fix: fix the go.mod
* fix: add InitiateFormData and CompleteFormData
* fix: fix the error
* fix: find error
* fix: test
* feat: add notification API
* fix: find error
* fix: fix the error
* fix: fix the PinFriend error
* fix: fix the Ex error
* fix: find the error
* fix: fix the rpc error
* fix: fix the error
* fix: fix the log error
* fix: fix the error1
* fix: fix the error
* fix: fix the script
* fix: fix the error
* fix: fix the error
* fix: fix the error of tag
* fix: fix the protocol
* fix: fix the error
* fix: fix the error
* fix: fix the err not wrap
* fix: fix the error
* fix: fix GetGroupMembers by nickname
* fix: support search userInfo by nickname or userID
* fix: fix the search by nickname error
* fix: fix the mod
---
go.mod | 2 +-
go.sum | 4 +--
internal/rpc/group/group.go | 50 ++++++++++++++++++++++++++++++++-----
3 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/go.mod b/go.mod
index f1b3239c3..f10e123a0 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.43
+ github.com/OpenIMSDK/protocol v0.0.44
github.com/OpenIMSDK/tools v0.0.21
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
diff --git a/go.sum b/go.sum
index e72d862e6..34f5d3ae9 100644
--- a/go.sum
+++ b/go.sum
@@ -18,8 +18,8 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.43 h1:8B921vEyO7r0AfQfZd7kCycYja+hJ2vuIZsKge/WRhU=
-github.com/OpenIMSDK/protocol v0.0.43/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/protocol v0.0.44 h1:P+9gJ9EW3y+VmzrjPludzn/5r1fjubaC19mKYJ7Oiew=
+github.com/OpenIMSDK/protocol v0.0.44/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index ba129d7e9..b1ea0aa03 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -476,13 +476,42 @@ func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGro
func (s *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGroupMemberListReq) (*pbgroup.GetGroupMemberListResp, error) {
resp := &pbgroup.GetGroupMemberListResp{}
- total, members, err := s.db.PageGetGroupMember(ctx, req.GroupID, req.Pagination)
+ var (
+ total int64
+ members []*relationtb.GroupMemberModel
+ err error
+ )
+ if req.Keyword == "" {
+ total, members, err = s.db.PageGetGroupMember(ctx, req.GroupID, req.Pagination)
+ } else {
+ members, err = s.db.FindGroupMemberAll(ctx, req.GroupID)
+ }
if err != nil {
return nil, err
}
if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
+ if req.Keyword != "" {
+ groupMembers := make([]*relationtb.GroupMemberModel, 0)
+ for _, member := range members {
+ if member.UserID == req.Keyword {
+ groupMembers = append(groupMembers, member)
+ total++
+ continue
+ }
+ if member.Nickname == req.Keyword {
+ groupMembers = append(groupMembers, member)
+ total++
+ continue
+ }
+ }
+
+ GMembers := utils.Paginate(groupMembers, int(req.Pagination.GetPageNumber()), int(req.Pagination.GetShowNumber()))
+ resp.Members = utils.Batch(convert.Db2PbGroupMember, GMembers)
+ resp.Total = uint32(total)
+ return resp, nil
+ }
resp.Total = uint32(total)
resp.Members = utils.Batch(convert.Db2PbGroupMember, members)
return resp, nil
@@ -1042,20 +1071,29 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq) (*pbgroup.GetGroupsResp, error) {
resp := &pbgroup.GetGroupsResp{}
var (
- groups []*relationtb.GroupModel
- err error
+ group []*relationtb.GroupModel
+ err error
)
if req.GroupID != "" {
- groups, err = s.db.FindGroup(ctx, []string{req.GroupID})
- resp.Total = uint32(len(groups))
+ group, err = s.db.FindGroup(ctx, []string{req.GroupID})
+ resp.Total = uint32(len(group))
} else {
var total int64
- total, groups, err = s.db.SearchGroup(ctx, req.GroupName, req.Pagination)
+ total, group, err = s.db.SearchGroup(ctx, req.GroupName, req.Pagination)
resp.Total = uint32(total)
}
if err != nil {
return nil, err
}
+
+ var groups []*relationtb.GroupModel
+ for _, v := range group {
+ if v.Status == constant.GroupStatusDismissed {
+ resp.Total--
+ continue
+ }
+ groups = append(groups, v)
+ }
groupIDs := utils.Slice(groups, func(e *relationtb.GroupModel) string {
return e.GroupID
})
From 6764fa5e70b07934db588aac336637feb450e639 Mon Sep 17 00:00:00 2001
From: skiffer-git <72860476+skiffer-git@users.noreply.github.com>
Date: Thu, 4 Jan 2024 20:50:29 +0800
Subject: [PATCH 052/110] MongoDB supports non-root users (#1684)
* MongoDB supports non-root users
Signed-off-by: skiffer-git <44203734@qq.com>
* Update component.go
* Update env-template.yaml
* Update docker-compose.yml
* Update environment.sh
* Update openim.yaml
* Update mongo-init.sh
---------
Signed-off-by: skiffer-git <44203734@qq.com>
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
deployments/templates/env-template.yaml | 16 ++++++++++++----
deployments/templates/openim.yaml | 4 ++--
docker-compose.yml | 16 +++++++---------
pkg/common/db/unrelation/mongo.go | 4 ++--
scripts/install/environment.sh | 9 +++++++--
scripts/mongo-init.sh | 18 ++++++++++++------
tools/component/component.go | 11 +++++------
7 files changed, 47 insertions(+), 31 deletions(-)
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index 1772af644..bdeda054f 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -84,19 +84,27 @@ OPENIM_IP=${OPENIM_IP}
# Default: ZOOKEEPER_PORT=12181
ZOOKEEPER_PORT=${ZOOKEEPER_PORT}
-# Port on which MongoDB service is running.
+# MongoDB service port configuration.
# Default: MONGO_PORT=37017
# MONGO_PORT=${MONGO_PORT}
-# Username to authenticate with the MongoDB service.
+# Username for MongoDB admin user. Used for service authentication.
# Default: MONGO_USERNAME=root
# MONGO_USERNAME=${MONGO_USERNAME}
-# Password to authenticate with the MongoDB service.
+# Password for MongoDB admin user. Used for service authentication.
# Default: MONGO_PASSWORD=openIM123
MONGO_PASSWORD=${MONGO_PASSWORD}
-# Name of the database in MongoDB to be used.
+# Username for a regular OpenIM user in MongoDB.
+# Default: MONGO_OPENIM_USERNAME=openIM
+MONGO_OPENIM_USERNAME=${MONGO_OPENIM_USERNAME}
+
+# Password for a regular OpenIM user in MongoDB.
+# Default: MONGO_OPENIM_PASSWORD=openIM123456
+MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD}
+
+# Specifies the database name to be used within MongoDB.
# Default: MONGO_DATABASE=openIM_v3
MONGO_DATABASE=${MONGO_DATABASE}
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index 96d867e10..6880e4c4e 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -53,8 +53,8 @@ mongo:
# Maximum connection pool size
address: [ ${MONGO_ADDRESS}:${MONGO_PORT} ]
database: ${MONGO_DATABASE}
- username: ${MONGO_USERNAME}
- password: ${MONGO_PASSWORD}
+ username: ${MONGO_OPENIM_USERNAME}
+ password: ${MONGO_OPENIM_PASSWORD}
maxPoolSize: ${MONGO_MAX_POOL_SIZE}
###################### Redis configuration information ######################
diff --git a/docker-compose.yml b/docker-compose.yml
index fd71896a7..b5c80188c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -10,6 +10,8 @@ networks:
- subnet: '${DOCKER_BRIDGE_SUBNET:-172.28.0.0/16}'
gateway: '${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}'
+
+
services:
mongodb:
image: mongo:${MONGODB_IMAGE_VERSION-6.0.2}
@@ -21,13 +23,15 @@ services:
- "${DATA_DIR:-./}/components/mongodb/data/db:/data/db"
- "${DATA_DIR:-./}/components/mongodb/data/logs:/data/logs"
- "${DATA_DIR:-./}/components/mongodb/data/conf:/etc/mongo"
- - ./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro
+ - "./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro"
environment:
- TZ=Asia/Shanghai
- wiredTigerCacheSizeGB=1
- MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME:-root}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD:-openIM123}
- MONGO_INITDB_DATABASE=${MONGO_DATABASE:-openIM_v3}
+ - MONGO_OPENIM_USERNAME=${MONGO_OPENIM_USERNAME:-openIM} # Non-root username
+ - MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD:-openIM123456} # Non-root password
restart: always
networks:
server:
@@ -122,9 +126,9 @@ services:
server:
ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7}
- ## Uncomment and configure the following services as needed
+ # Uncomment and configure the following services as needed
# openim-admin:
- # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin:toc-base-open-docker.35
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0
# container_name: openim-admin
# restart: always
# ports:
@@ -167,12 +171,6 @@ services:
# hostname: grafana
# user: root
# restart: always
- # environment:
- # - GF_SECURITY_ALLOW_EMBEDDING=true
- # - GF_SESSION_COOKIE_SAMESITE=none
- # - GF_SESSION_COOKIE_SECURE=true
- # - GF_AUTH_ANONYMOUS_ENABLED=true
- # - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
# ports:
# - "${GRAFANA_PORT:-13000}:3000"
# volumes:
diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go
index 8cfb97a98..279a7901e 100644
--- a/pkg/common/db/unrelation/mongo.go
+++ b/pkg/common/db/unrelation/mongo.go
@@ -103,9 +103,9 @@ func buildMongoURI() string {
maxPoolSize = fmt.Sprint(config.Config.Mongo.MaxPoolSize)
}
- uriFormat := "mongodb://%s/%s?maxPoolSize=%s&authSource=admin"
+ uriFormat := "mongodb://%s/%s?maxPoolSize=%s"
if username != "" && password != "" {
- uriFormat = "mongodb://%s:%s@%s/%s?maxPoolSize=%s&authSource=admin"
+ uriFormat = "mongodb://%s:%s@%s/%s?maxPoolSize=%s"
return fmt.Sprintf(uriFormat, username, password, address, database, maxPoolSize)
}
return fmt.Sprintf(uriFormat, address, database, maxPoolSize)
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index 22a0996fc..a95bf6a93 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -171,9 +171,14 @@ def "MONGO_URI" # MongoDB的URI
def "MONGO_PORT" "37017" # MongoDB的端口
def "MONGO_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # MongoDB的地址
def "MONGO_DATABASE" "${DATABASE_NAME}" # MongoDB的数据库名
-def "MONGO_USERNAME" "${OPENIM_USER}" # MongoDB的用户名
-# MongoDB的密码
+def "MONGO_USERNAME" "root" # MongoDB的管理员身份用户名
+# MongoDB的管理员身份密码
readonly MONGO_PASSWORD=${MONGO_PASSWORD:-"${PASSWORD}"}
+# Mongo OpenIM 身份用户名
+def "MONGO_OPENIM_USERNAME" "openIM"
+# Mongo OpenIM 身份密码
+readonly MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD:-'openIM123456'}
+
def "MONGO_MAX_POOL_SIZE" "100" # 最大连接池大小
###################### Object 配置信息 ######################
diff --git a/scripts/mongo-init.sh b/scripts/mongo-init.sh
index 07d0e3d03..bb9519648 100755
--- a/scripts/mongo-init.sh
+++ b/scripts/mongo-init.sh
@@ -12,15 +12,21 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-mongo -- "$MONGO_INITDB_DATABASE" <
Date: Thu, 4 Jan 2024 20:51:21 +0800
Subject: [PATCH 053/110] Update docker-start-all.sh fix MSG_TRANSFER_PROM_PORT
(#1679)
* fix: fix the bug
* fix: fix the imAdmin permission and searchNoficitaion resp
* 2023 Annual Summary Reflections and Aspirations
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: dissmissGroup and lack of keyword bug (#1678)
* Update docker-start-all.sh
* Update env-template.yaml
* Update docker-start-all.sh
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Co-authored-by: luhaoling <2198702716@qq.com>
Co-authored-by: Brabem <69128477+luhaoling@users.noreply.github.com>
Co-authored-by: OpenIM Bot <124379614+kubbot@users.noreply.github.com>
---
deployments/templates/env-template.yaml | 6 ------
scripts/docker-start-all.sh | 21 +--------------------
2 files changed, 1 insertion(+), 26 deletions(-)
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index bdeda054f..09349aab0 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -195,18 +195,12 @@ CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION}
# Port for the OpenIM chat API.
# Default: OPENIM_CHAT_API_PORT=10008
-# !!! TODO: Do not change the chat port https://github.com/openimsdk/chat/issues/365
OPENIM_CHAT_API_PORT=${OPENIM_CHAT_API_PORT}
# Port for the OpenIM admin API.
# Default: OPENIM_ADMIN_API_PORT=10009
-# !!! TODO: Do not change the chat port https://github.com/openimsdk/chat/issues/365
OPENIM_ADMIN_API_PORT=${OPENIM_ADMIN_API_PORT}
-# Directory path for storing data files or related information for OpenIM chat.
-# Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main
-OPENIM_CHAT_DATA_DIR=${OPENIM_CHAT_DATA_DIR}
-
# ======================================
# ========== OpenIM Admin ==============
# ======================================
diff --git a/scripts/docker-start-all.sh b/scripts/docker-start-all.sh
index 85954a677..2616b7bd1 100755
--- a/scripts/docker-start-all.sh
+++ b/scripts/docker-start-all.sh
@@ -21,25 +21,6 @@ set -o pipefail
#fixme This scripts is the total startup scripts
#fixme The full name of the shell scripts that needs to be started is placed in the need_to_start_server_shell array
-# Fixed ports inside the docker startup container
-export OPENIM_WS_PORT=10001
-export API_OPENIM_PORT=10002
-export API_PROM_PORT=20100
-export USER_PROM_PORT=20110
-export FRIEND_PROM_PORT=20120
-export MESSAGE_PROM_PORT=20130
-export MSG_GATEWAY_PROM_PORT=20140
-export GROUP_PROM_PORT=20150
-export AUTH_PROM_PORT=20160
-export PUSH_PROM_PORT=20170
-export CONVERSATION_PROM_PORT=20230
-export RTC_PROM_PORT=21300
-export THIRD_PROM_PORT=21301
-export MSG_TRANSFER_PROM_PORT=21400
-export MSG_TRANSFER_PROM_PORT=21401
-export MSG_TRANSFER_PROM_PORT=21402
-export MSG_TRANSFER_PROM_PORT=21403
-
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${OPENIM_ROOT}/scripts/install/common.sh"
@@ -55,4 +36,4 @@ sleep 5
"${OPENIM_ROOT}"/scripts/check-all.sh
-tail -f ${LOG_FILE}
\ No newline at end of file
+tail -f ${LOG_FILE}
From 8aac6c6f819ffdcff4aa6369a16a030f754273af Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Fri, 5 Jan 2024 11:19:40 +0800
Subject: [PATCH 054/110] Fix(main): fix openim config from mongo password env
upgrade openim build CICD (#1689)
* fix openim config mongo passwd env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix openim config mongo passwd env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix openim config mongo passwd env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix openim config mongo passwd env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
.github/workflows/openimci.yml | 15 ++++----
docs/contrib/environment.md | 6 ++--
pkg/common/db/unrelation/mongo.go | 4 +--
scripts/install-im-server.sh | 57 ++++++++++++++++++-------------
scripts/install/dependency.sh | 4 +--
5 files changed, 48 insertions(+), 38 deletions(-)
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index d16e91ba4..45541f5f4 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -128,6 +128,8 @@ jobs:
- name: Run OpenIM make install start
run: |
sudo make install
+ sudo docker images
+ sudo docker ps
execute-scripts:
name: Execute OpenIM Script On ${{ matrix.os }}
@@ -212,14 +214,10 @@ jobs:
sudo make restart
sudo make check
- # - name: Build, Start, Check Services and Print Logs for macOS
- # if: runner.os == 'macOS'
- # run: |
- # make init && \
- # make build && \
- # make start && \
- # make check || \
- # (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
+ - name: Build, Start, Check Services and Print Logs for macOS
+ if: runner.os == 'macOS'
+ run: |
+ make build
openim-test-build-image:
name: Build OpenIM Docker Image
@@ -245,3 +243,4 @@ jobs:
run: |
sudo make init
sudo make image
+ sudo docker images
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index e52d57235..8db462688 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -304,8 +304,10 @@ This section involves setting up MongoDB, including its port, address, and crede
| -------------- | -------------- | ----------------------- |
| MONGO_PORT | "27017" | Port used by MongoDB. |
| MONGO_ADDRESS | [Generated IP] | IP address for MongoDB. |
-| MONGO_USERNAME | [User Defined] | Username for MongoDB. |
-| MONGO_PASSWORD | [User Defined] | Password for MongoDB. |
+| MONGO_USERNAME | [User Defined] | Admin Username for MongoDB. |
+| MONGO_PASSWORD | [User Defined] | Admin Password for MongoDB. |
+| MONGO_OPENIM_PASSWORD | [User Defined] | OpenIM Username for MongoDB. |
+| MONGO_OPENIM_PASSWORD | [User Defined] | OpenIM Password for MongoDB. |
### 2.8. Tencent Cloud COS Configuration
diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go
index 279a7901e..b8184d767 100644
--- a/pkg/common/db/unrelation/mongo.go
+++ b/pkg/common/db/unrelation/mongo.go
@@ -78,8 +78,8 @@ func buildMongoURI() string {
return config.Config.Mongo.Uri
}
- username := os.Getenv("MONGO_USERNAME")
- password := os.Getenv("MONGO_PASSWORD")
+ username := os.Getenv("MONGO_OPENIM_USERNAME")
+ password := os.Getenv("MONGO_OPENIM_PASSWORD")
address := os.Getenv("MONGO_ADDRESS")
port := os.Getenv("MONGO_PORT")
database := os.Getenv("MONGO_DATABASE")
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index a21ae134d..16ac625ee 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -1,20 +1,18 @@
#!/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
+# OpenIM Docker Deployment Script
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# This script automates the process of building the OpenIM server image
+# and deploying it using Docker Compose.
#
-# 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.
-
+# Variables:
+# - SERVER_IMAGE_VERSION: Version of the server image (default: test)
+# - IMAGE_REGISTRY: Docker image registry (default: openim)
+# - DOCKER_COMPOSE_FILE_URL: URL to the docker-compose.yml file
+#
+# Usage:
+# SERVER_IMAGE_VERSION=latest IMAGE_REGISTRY=myregistry ./this_script.sh
-# Common utilities, variables and checks for all build scripts.
set -o errexit
set -o nounset
set -o pipefail
@@ -28,35 +26,46 @@ chmod +x "${OPENIM_ROOT}"/scripts/*.sh
openim::util::ensure_docker_daemon_connectivity
+# Default values for variables
+: ${SERVER_IMAGE_VERSION:=test}
+: ${IMAGE_REGISTRY:=openim}
+: ${DOCKER_COMPOSE_FILE_URL:="https://raw.githubusercontent.com/openimsdk/openim-docker/main/docker-compose.yaml"}
+
DOCKER_COMPOSE_COMMAND=
# Check if docker-compose command is available
openim::util::check_docker_and_compose_versions
-
-if command -v docker compose &> /dev/null
-then
+if command -v docker compose &> /dev/null; then
openim::log::info "docker compose command is available"
DOCKER_COMPOSE_COMMAND="docker compose"
else
DOCKER_COMPOSE_COMMAND="docker-compose"
fi
+export SERVER_IMAGE_VERSION
+export IMAGE_REGISTRY
"${OPENIM_ROOT}"/scripts/init-config.sh
+
pushd "${OPENIM_ROOT}"
+docker build -t "${IMAGE_REGISTRY}/openim-server:${SERVER_IMAGE_VERSION}" .
${DOCKER_COMPOSE_COMMAND} stop
-curl https://raw.githubusercontent.com/openimsdk/openim-docker/main/docker-compose.yaml -o docker-compose.yml
+curl "${DOCKER_COMPOSE_FILE_URL}" -o docker-compose.yml
${DOCKER_COMPOSE_COMMAND} up -d
+# Function to check container status
+check_containers() {
+ if ! ${DOCKER_COMPOSE_COMMAND} ps | grep -q 'Up'; then
+ echo "Error: One or more docker containers failed to start."
+ ${DOCKER_COMPOSE_COMMAND} logs
+ return 1
+ fi
+ return 0
+}
+
# Wait for a short period to allow containers to initialize
sleep 30
+check_containers
-# Check the status of the containers
-if ! ${DOCKER_COMPOSE_COMMAND} ps | grep -q 'Up'; then
- echo "Error: One or more docker containers failed to start."
- ${DOCKER_COMPOSE_COMMAND} logs
-fi
-
-sleep 30 # Keep the original 60-second wait, adjusted for the 10-second check above
${DOCKER_COMPOSE_COMMAND} logs openim-server
${DOCKER_COMPOSE_COMMAND} ps
-popd
+popd
\ No newline at end of file
diff --git a/scripts/install/dependency.sh b/scripts/install/dependency.sh
index bfa0909e2..78995bcf9 100755
--- a/scripts/install/dependency.sh
+++ b/scripts/install/dependency.sh
@@ -35,8 +35,8 @@ docker run -d \
-e MONGO_INITDB_ROOT_USERNAME=${OPENIM_USER} \
-e MONGO_INITDB_ROOT_PASSWORD=${PASSWORD} \
-e MONGO_INITDB_DATABASE=openIM \
- -e MONGO_USERNAME=${OPENIM_USER} \
- -e MONGO_PASSWORD=${PASSWORD} \
+ -e MONGO_OPENIM_USERNAME=${OPENIM_USER} \
+ -e MONGO_OPENIM_PASSWORD=${PASSWORD} \
--restart always \
mongo:6.0.2 --wiredTigerCacheSizeGB 1 --auth
From c241f5bea1b660f13e67dc55351ebba2c02ea86d Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Sat, 6 Jan 2024 21:02:47 +0800
Subject: [PATCH 055/110] Update cla.yml (#1692)
---
.github/workflows/cla.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml
index 540c8a48b..ae27c8a0a 100644
--- a/.github/workflows/cla.yml
+++ b/.github/workflows/cla.yml
@@ -33,7 +33,7 @@ env:
OPEN_IM_SERVER_CLA_DOCUMENT: https://github.com/openim-sigs/cla/blob/main/README.md
OPEN_IM_SERVER_SIGNATURES_PATH: signatures/${{ github.event.repository.name }}/cla.json
- OPEN_IM_SERVER_ALLOWLIST: kubbot,bot*,bot-*,bot/*,bot-/*,bot,*[bot]
+ OPEN_IM_SERVER_ALLOWLIST: kubbot,openimbot,bot*,dependabot,sweep-ai,*bot,bot-*,bot/*,bot-/*,bot,*[bot]
jobs:
CLAAssistant:
From f27b1e43f57c2a0f49fad387fe6e486930845fce Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Sun, 7 Jan 2024 15:02:59 +0800
Subject: [PATCH 056/110] Enhancements to Script Variables and Logic in OpenIM,
Including dig Detection and Mongo Startup Checks (#1696)
* update openim and optimize openim docs and dig check
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim and optimize openim docs and dig check
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim and optimize openim docs and dig check
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix openim config mongo passwd env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update openim environment and status
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: sava openim cicd
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim mongo logic
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
.github/workflows/docker-buildx.yml | 130 ++++++++++++++++++++++++
.github/workflows/e2e-test.yml | 37 ++++++-
.github/workflows/openimci.yml | 60 +++++++++--
deployments/templates/env-template.yaml | 18 +++-
docker-compose.yml | 4 +-
docs/contrib/environment.md | 17 ++--
docs/contrib/images.md | 1 +
docs/contrib/version.md | 21 ++++
pkg/common/config/version | 2 +-
pkg/msgprocessor/conversation.go | 1 +
pkg/msgprocessor/options.go | 1 +
scripts/genconfig.sh | 12 +--
scripts/install-im-server.sh | 14 +++
scripts/install/environment.sh | 4 +-
scripts/lib/util.sh | 9 +-
scripts/make-rules/common.mk | 2 +-
scripts/mongo-init.sh | 2 -
17 files changed, 291 insertions(+), 44 deletions(-)
diff --git a/.github/workflows/docker-buildx.yml b/.github/workflows/docker-buildx.yml
index 6113cfae5..b3b0b5683 100644
--- a/.github/workflows/docker-buildx.yml
+++ b/.github/workflows/docker-buildx.yml
@@ -106,6 +106,16 @@ jobs:
ghcr.io/openimsdk/openim-api
openim/openim-api
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-api
uses: docker/build-push-action@v5
@@ -127,6 +137,16 @@ jobs:
ghcr.io/openimsdk/openim-cmdutils
openim/openim-cmdutils
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-cmdutils
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-cmdutils
uses: docker/build-push-action@v5
@@ -148,6 +168,16 @@ jobs:
ghcr.io/openimsdk/openim-crontask
openim/openim-crontask
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-crontask
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-crontask
uses: docker/build-push-action@v5
@@ -169,6 +199,16 @@ jobs:
ghcr.io/openimsdk/openim-msggateway
openim/openim-msggateway
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-msggateway
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-msggateway
uses: docker/build-push-action@v5
@@ -190,6 +230,16 @@ jobs:
ghcr.io/openimsdk/openim-msgtransfer
openim/openim-msgtransfer
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-msgtransfer
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-msgtransfer
uses: docker/build-push-action@v5
@@ -211,6 +261,16 @@ jobs:
ghcr.io/openimsdk/openim-push
openim/openim-push
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-push
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-push
uses: docker/build-push-action@v5
@@ -232,6 +292,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-auth
openim/openim-rpc-auth
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-auth
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-auth
uses: docker/build-push-action@v5
@@ -253,6 +323,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-conversation
openim/openim-rpc-conversation
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-conversation
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-conversation
uses: docker/build-push-action@v5
@@ -274,6 +354,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-friend
openim/openim-rpc-friend
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-friend
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-friend
uses: docker/build-push-action@v5
@@ -295,6 +385,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-group
openim/openim-rpc-group
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-group
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-group
uses: docker/build-push-action@v5
@@ -316,6 +416,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-msg
openim/openim-rpc-msg
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-msg
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-msg
uses: docker/build-push-action@v5
@@ -337,6 +447,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-third
openim/openim-rpc-third
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-third
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-third
uses: docker/build-push-action@v5
@@ -358,6 +478,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-user
openim/openim-rpc-user
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-user
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-user
uses: docker/build-push-action@v5
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index 2f6d7fe05..6d8112eb4 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -92,11 +92,40 @@ jobs:
- name: Exec OpenIM API test
run: |
- sudo make test-api
-
- - name: Exec OpenIM E2E test
+ touch /tmp/test.md
+ echo "# OpenIM Test" >> /tmp/test.md
+ echo "## OpenIM API Test" >> /tmp/test.md
+ echo "Command Output for OpenIM API Test " >> /tmp/test.md
+ echo "" >> /tmp/test.md
+ sudo make test-api | tee -a /tmp/test.md
+ echo "
" >> /tmp/test.md
+ echo " " >> /tmp/test.md
+
+ - name: Exec OpenIM E2E Test
run: |
- sudo make test-e2e
+ echo "" >> /tmp/test.md
+ echo "## OpenIM E2E Test" >> /tmp/test.md
+ echo "Command Output for OpenIM E2E Test " >> /tmp/test.md
+ echo "" >> /tmp/test.md
+ sudo make test-e2e | tee -a /tmp/test.md
+ echo "
" >> /tmp/test.md
+ echo " " >> /tmp/test.md
+
+ - name: Comment PR with file
+ uses: thollander/actions-comment-pull-request@v2
+ with:
+ filePath: /tmp/test.md
+ comment_tag: nrt_file
+ reactions: eyes, rocket
+ mode: recreate
+ GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
+ continue-on-error: true
+
+ - name: Check outputs
+ run: |
+ echo "id : ${{ steps.nrt_message.outputs.id }}"
+ echo "body : ${{ steps.nrt_message.outputs.body }}"
+ echo "html_url : ${{ steps.nrt_message.outputs.html_url }}"
- name: Exec OpenIM System uninstall
run: |
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index 45541f5f4..96e03f214 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -36,21 +36,19 @@ env:
GO_VERSION: "1.19"
GOLANGCI_VERSION: "v1.50.1"
-
jobs:
openim:
name: Test with go ${{ matrix.go_version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
permissions:
contents: write
+ pull-requests: write
environment:
name: openim
-
strategy:
matrix:
go_version: ["1.19","1.20","1.21"]
os: [ubuntu-latest]
-
steps:
- name: Setup
uses: actions/checkout@v4
@@ -111,6 +109,9 @@ jobs:
openim-start:
name: Test OpenIM install/start on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
+ permissions:
+ contents: write
+ pull-requests: write
environment:
name: openim
strategy:
@@ -128,12 +129,46 @@ jobs:
- name: Run OpenIM make install start
run: |
sudo make install
- sudo docker images
- sudo docker ps
+
+ # - name: Check the OpenIM environment and status
+ # run: |
+ # sudo docker images
+ # sudo docker ps
+
+ - name: Check the OpenIM environment and status
+ id: docker_info
+ run: |
+ sleep 30
+ echo "images<> $GITHUB_ENV
+ sudo docker images >> $GITHUB_ENV
+ echo "EOF" >> $GITHUB_ENV
+ echo "containers<> $GITHUB_ENV
+ sudo docker ps >> $GITHUB_ENV
+ echo "EOF" >> $GITHUB_ENV
+
+ - name: Comment PR
+ uses: thollander/actions-comment-pull-request@v2
+ with:
+ message: |
+ > [!TIP]
+ > Run make install to check the status
+
+ ### Docker Images:
+ ```
+ ${{ env.images }}
+ ```
+ ### Docker Processes:
+ ```
+ ${{ env.containers }}
+ ```
+ GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
execute-scripts:
name: Execute OpenIM Script On ${{ matrix.os }}
runs-on: ${{ matrix.os }}
+ permissions:
+ contents: write
+ pull-requests: write
environment:
name: openim
strategy:
@@ -203,10 +238,9 @@ jobs:
- name: Build, Start, Check Services and Print Logs for Ubuntu
if: runner.os == 'Linux'
run: |
- sudo make build && \
- sudo make start && \
- sudo make check || \
- (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
+ sudo make build
+ sudo make start
+ sudo make check
- name: Restart Services and Print Logs for Ubuntu
if: runner.os == 'Linux'
@@ -222,6 +256,9 @@ jobs:
openim-test-build-image:
name: Build OpenIM Docker Image
runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
environment:
name: openim
steps:
@@ -243,4 +280,9 @@ jobs:
run: |
sudo make init
sudo make image
+
+ - name: Get OpenIM Docker Images Status
+ id: docker_processes
+ run: |
sudo docker images
+ sudo docker ps
\ No newline at end of file
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index 09349aab0..e7166ff2d 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -1,3 +1,17 @@
+# Copyright © 2024 OpenIM. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
# -----------------------------------------------------------------------------
# General Configuration
# This section contains general configuration options for the entire environment.
@@ -88,10 +102,6 @@ ZOOKEEPER_PORT=${ZOOKEEPER_PORT}
# Default: MONGO_PORT=37017
# MONGO_PORT=${MONGO_PORT}
-# Username for MongoDB admin user. Used for service authentication.
-# Default: MONGO_USERNAME=root
-# MONGO_USERNAME=${MONGO_USERNAME}
-
# Password for MongoDB admin user. Used for service authentication.
# Default: MONGO_PASSWORD=openIM123
MONGO_PASSWORD=${MONGO_PASSWORD}
diff --git a/docker-compose.yml b/docker-compose.yml
index b5c80188c..defc910c4 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -10,15 +10,13 @@ networks:
- subnet: '${DOCKER_BRIDGE_SUBNET:-172.28.0.0/16}'
gateway: '${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}'
-
-
services:
mongodb:
image: mongo:${MONGODB_IMAGE_VERSION-6.0.2}
ports:
- "${MONGO_PORT:-37017}:27017"
container_name: mongo
- command: --wiredTigerCacheSizeGB 1 --auth
+ command: ["/bin/bash", "-c", "/docker-entrypoint-initdb.d/mongo-init.sh || true; docker-entrypoint.sh mongod --wiredTigerCacheSizeGB 1 --auth"]
volumes:
- "${DATA_DIR:-./}/components/mongodb/data/db:/data/db"
- "${DATA_DIR:-./}/components/mongodb/data/logs:/data/logs"
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index 8db462688..7425c8022 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -104,8 +104,8 @@ Docker deployment offers a slightly more intricate template. Within the [openim-
Configuration file modifications can be made by specifying corresponding environment variables, for instance:
```bash
-export CHAT_IMAGE_VERSION="main"
-export SERVER_IMAGE_VERSION="main"
+export CHAT_IMAGE_VERSION="main"
+export SERVER_IMAGE_VERSION="main"
```
These variables are stored within the [`environment.sh`](https://github.com/OpenIMSDK/openim-docker/blob/main/scripts/install/environment.sh) configuration:
@@ -114,6 +114,9 @@ These variables are stored within the [`environment.sh`](https://github.com/Open
readonly CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION:-'main'}
readonly SERVER_IMAGE_VERSION=${SERVER_IMAGE_VERSION:-'main'}
```
+> [!IMPORTANT]
+> Can learn to read our mirror version strategy: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md
+
Setting a variable, e.g., `export CHAT_IMAGE_VERSION="release-v1.3"`, will prioritize `CHAT_IMAGE_VERSION="release-v1.3"` as the variable value. Ultimately, the chosen image version is determined, and rendering is achieved through `make init` (or `./scripts/init-config.sh`).
@@ -127,7 +130,7 @@ For convenience, configuration through modifying environment variables is recomm
+ PASSWORD
- + **Description**: Password for mysql, mongodb, redis, and minio.
+ + **Description**: Password for mongodb, redis, and minio.
+ **Default**: `openIM123`
+ Notes:
+ Minimum password length: 8 characters.
@@ -139,20 +142,22 @@ For convenience, configuration through modifying environment variables is recomm
+ OPENIM_USER
- + **Description**: Username for mysql, mongodb, redis, and minio.
+ + **Description**: Username for redis, and minio.
+ **Default**: `root`
```bash
export OPENIM_USER="root"
```
-+ API_URL
+> mongo is `openIM`, use `export MONGO_OPENIM_USERNAME="openIM"` to modify
+
++ OPENIM_IP
+ **Description**: API address.
+ **Note**: If the server has an external IP, it will be automatically obtained. For internal networks, set this variable to the IP serving internally.
```bash
- export API_URL="http://ip:10002"
+ export OPENIM_IP="ip"
```
+ DATA_DIR
diff --git a/docs/contrib/images.md b/docs/contrib/images.md
index 44bd7b5bf..d1a83d639 100644
--- a/docs/contrib/images.md
+++ b/docs/contrib/images.md
@@ -26,6 +26,7 @@ We provide multiple versions of our images to meet different project requirement
1. `main`: This image corresponds to the latest version of the main branch in OpenIM. It is updated frequently, making it perfect for users who want to stay at the cutting edge of our features.
2. `release-v3.*`: This is the image that corresponds to the latest version of OpenIM's stable release branch. It's ideal for users who prefer a balance between new features and stability.
3. `v3.*.*`: These images are specific to each tag in OpenIM. They are preserved in their original state and are never overwritten. These are the go-to images for users who need a specific, unchanging version of OpenIM.
+4. The image versions adhere to Semantic Versioning 2.0.0 strategy. Taking the `openim-server` image as an example, available at [openim-server container package](https://github.com/openimsdk/open-im-server/pkgs/container/openim-server): upon tagging with v3.5.0, the CI automatically releases the following tags - `openim-server:3`, `openim-server:3.5`, `openim-server:3.5.0`, `openim-server:v3.5.0`, `openim-server:latest`, and `sha-e0244d9`. It's important to note that only `sha-e0244d9` is absolutely unique, whereas `openim-server:v3.5.0` and `openim-server:3.5.0` maintain a degree of uniqueness.
### Multi-Architecture Images
diff --git a/docs/contrib/version.md b/docs/contrib/version.md
index 0e03b8d8b..574badf59 100644
--- a/docs/contrib/version.md
+++ b/docs/contrib/version.md
@@ -1,6 +1,7 @@
# OpenIM Branch Management and Versioning: A Blueprint for High-Grade Software Development
[📚 **OpenIM TOC**](#openim-branch-management-and-versioning-a-blueprint-for-high-grade-software-development)
+- [OpenIM Branch Management and Versioning: A Blueprint for High-Grade Software Development](#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)
@@ -8,8 +9,21 @@
- [Release Management: A Guided Tour](#release-management-a-guided-tour)
- [Milestones, Branching, and Addressing Major Bugs](#milestones-branching-and-addressing-major-bugs)
- [Version Skew Policy](#version-skew-policy)
+ - [Supported version skew](#supported-version-skew)
+ - [OpenIM Versioning, Branching, and Tag Strategy](#openim-versioning-branching-and-tag-strategy)
+ - [Supported Version Skew](#supported-version-skew-1)
+ - [openim-api](#openim-api)
+ - [openim-rpc-\* Components](#openim-rpc--components)
+ - [Other OpenIM Services](#other-openim-services)
+ - [Supported Component Upgrade Order](#supported-component-upgrade-order)
+ - [openim-api](#openim-api-1)
+ - [openim-rpc-\* Components](#openim-rpc--components-1)
+ - [Other OpenIM Services](#other-openim-services-1)
+ - [Conclusion](#conclusion)
- [Applying Principles: A Git Workflow Example](#applying-principles-a-git-workflow-example)
+ - [Release Process](#release-process)
- [Docker Images Version Management](#docker-images-version-management)
+ - [More](#more)
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/).
@@ -213,3 +227,10 @@ Throughout this process, active communication within the team is pivotal to main
## Docker Images Version Management
For more details on managing Docker image versions, visit [OpenIM Docker Images Administration](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md).
+
+## More
+
+More on multi-branch version management design and version management design at helm charts:
+
++ https://github.com/openimsdk/open-im-server/issues/1695
++ https://github.com/openimsdk/open-im-server/issues/1662
\ No newline at end of file
diff --git a/pkg/common/config/version b/pkg/common/config/version
index e682ea429..4d0729e54 100644
--- a/pkg/common/config/version
+++ b/pkg/common/config/version
@@ -1 +1 @@
-v3.3.0
\ No newline at end of file
+v3.5.0
\ No newline at end of file
diff --git a/pkg/msgprocessor/conversation.go b/pkg/msgprocessor/conversation.go
index 56255f37c..7477bea7a 100644
--- a/pkg/msgprocessor/conversation.go
+++ b/pkg/msgprocessor/conversation.go
@@ -52,6 +52,7 @@ func GetChatConversationIDByMsg(msg *sdkws.MsgData) string {
case constant.NotificationChatType:
return "sn_" + msg.SendID + "_" + msg.RecvID
}
+
return ""
}
diff --git a/pkg/msgprocessor/options.go b/pkg/msgprocessor/options.go
index ea383a1af..c6e209b98 100644
--- a/pkg/msgprocessor/options.go
+++ b/pkg/msgprocessor/options.go
@@ -37,6 +37,7 @@ func NewOptions(opts ...OptionsOpt) Options {
for _, opt := range opts {
opt(options)
}
+
return options
}
diff --git a/scripts/genconfig.sh b/scripts/genconfig.sh
index 2371edc9d..8ded38b22 100755
--- a/scripts/genconfig.sh
+++ b/scripts/genconfig.sh
@@ -29,16 +29,8 @@ if [ $# -ne 2 ];then
exit 1
fi
-openim::util::require-dig
-result=$?
-if [ $result -ne 0 ]; then
- openim::log::info "Please install 'dig' to use this feature."
- openim::log::info "Installation instructions:"
- openim::log::info " For Ubuntu/Debian: sudo apt-get install dnsutils"
- openim::log::info " For CentOS/RedHat: sudo yum install bind-utils"
- openim::log::info " For macOS: 'dig' should be preinstalled. If missing, try: brew install bind"
- openim::log::info " For Windows: Install BIND9 tools from https://www.isc.org/download/"
- openim::log::error_exit "Error: 'dig' command is required but not installed."
+if [ -z "${OPENIM_IP}" ]; then
+ openim::util::require-dig
fi
source "${env_file}"
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index 16ac625ee..9afbb97c9 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -1,4 +1,18 @@
#!/usr/bin/env bash
+# Copyright © 2024 OpenIM. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
#
# OpenIM Docker Deployment Script
#
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index a95bf6a93..9d9fc4028 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -171,13 +171,13 @@ def "MONGO_URI" # MongoDB的URI
def "MONGO_PORT" "37017" # MongoDB的端口
def "MONGO_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # MongoDB的地址
def "MONGO_DATABASE" "${DATABASE_NAME}" # MongoDB的数据库名
-def "MONGO_USERNAME" "root" # MongoDB的管理员身份用户名
+def "MONGO_USERNAME" "root" # MongoDB的管理员身份用户名
# MongoDB的管理员身份密码
readonly MONGO_PASSWORD=${MONGO_PASSWORD:-"${PASSWORD}"}
# Mongo OpenIM 身份用户名
def "MONGO_OPENIM_USERNAME" "openIM"
# Mongo OpenIM 身份密码
-readonly MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD:-'openIM123456'}
+readonly MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD:-"${PASSWORD}"}
def "MONGO_MAX_POOL_SIZE" "100" # 最大连接池大小
diff --git a/scripts/lib/util.sh b/scripts/lib/util.sh
index b8d76edeb..4de240972 100755
--- a/scripts/lib/util.sh
+++ b/scripts/lib/util.sh
@@ -1146,8 +1146,13 @@ function openim::util::require-jq {
# Checks whether dig is installed and provides installation instructions if it is not.
function openim::util::require-dig {
if ! command -v dig &>/dev/null; then
- openim::log::error "dig command not found."
- return 1
+ openim::log::error "Please install 'dig' to use this feature."
+ openim::log::error "Installation instructions:"
+ openim::log::error " For Ubuntu/Debian: sudo apt-get install dnsutils"
+ openim::log::error " For CentOS/RedHat: sudo yum install bind-utils"
+ openim::log::error " For macOS: 'dig' should be preinstalled. If missing, try: brew install bind"
+ openim::log::error " For Windows: Install BIND9 tools from https://www.isc.org/download/"
+ openim::log::error_exit "dig command not found."
fi
return 0
}
diff --git a/scripts/make-rules/common.mk b/scripts/make-rules/common.mk
index 81b44826b..c56f9f071 100644
--- a/scripts/make-rules/common.mk
+++ b/scripts/make-rules/common.mk
@@ -129,7 +129,7 @@ FIND := find . ! -path './utils/*' ! -path './vendor/*' ! -path './third_party/*
XARGS := xargs -r --no-run-if-empty
# Linux command settings-CODE DIRS Copyright
-CODE_DIRS := $(ROOT_DIR)/pkg $(ROOT_DIR)/cmd $(ROOT_DIR)/config $(ROOT_DIR)/.docker-compose_cfg $(ROOT_DIR)/internal $(ROOT_DIR)/scripts $(ROOT_DIR)/test $(ROOT_DIR)/.github $(ROOT_DIR)/build $(ROOT_DIR)/tools $(ROOT_DIR)/deployments
+CODE_DIRS := $(ROOT_DIR)/pkg $(ROOT_DIR)/cmd $(ROOT_DIR)/config $(ROOT_DIR)/internal $(ROOT_DIR)/scripts $(ROOT_DIR)/test $(ROOT_DIR)/.github $(ROOT_DIR)/build $(ROOT_DIR)/tools $(ROOT_DIR)/deployments
FINDS := find $(CODE_DIRS)
# Makefile settings: Select different behaviors by determining whether V option is set
diff --git a/scripts/mongo-init.sh b/scripts/mongo-init.sh
index bb9519648..41d9ca0aa 100755
--- a/scripts/mongo-init.sh
+++ b/scripts/mongo-init.sh
@@ -18,7 +18,6 @@ mongosh <
Date: Mon, 8 Jan 2024 15:16:28 +0800
Subject: [PATCH 057/110] feat: send msg at text (#1705)
---
internal/api/msg.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/internal/api/msg.go b/internal/api/msg.go
index 548450534..9348596ac 100644
--- a/internal/api/msg.go
+++ b/internal/api/msg.go
@@ -164,6 +164,8 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM
data = apistruct.VideoElem{}
case constant.File:
data = apistruct.FileElem{}
+ case constant.AtText:
+ data = apistruct.AtElem{}
case constant.Custom:
data = apistruct.CustomElem{}
case constant.OANotification:
@@ -172,7 +174,6 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM
if err = m.userRpcClient.GetNotificationByID(c, req.SendID); err != nil {
return nil, err
}
-
default:
return nil, errs.ErrArgs.WithDetail("not support err contentType")
}
From d91a665891570c5be7b0b77e510a0178973b2140 Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Mon, 8 Jan 2024 21:38:48 +0800
Subject: [PATCH 058/110] fix: fix some bug (#1710)
* fix: test the getUser api
* fix: fix the go.mod
* fix: fix the go.mod
* fix: fix the go.mod
* fix: fix the addNotificationAccount req
* fix: fix the addnotificationAccount resp
* fix: fix the searchNotificationResp
* fix: fix the go mod
* fix: fix the field of PageFindUser
* Update openimci.yml
* Update openimci.yml
---------
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
.github/workflows/openimci.yml | 5 +-
go.mod | 4 +-
go.sum | 8 +--
internal/rpc/user/user.go | 83 +++++++++++++++-------------
pkg/common/db/controller/user.go | 6 ++
pkg/common/db/mgo/user.go | 4 ++
pkg/common/db/table/relation/user.go | 1 +
7 files changed, 65 insertions(+), 46 deletions(-)
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index 96e03f214..00339110c 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -161,7 +161,8 @@ jobs:
```
${{ env.containers }}
```
- GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ continue-on-error: true
execute-scripts:
name: Execute OpenIM Script On ${{ matrix.os }}
@@ -285,4 +286,4 @@ jobs:
id: docker_processes
run: |
sudo docker images
- sudo docker ps
\ No newline at end of file
+ sudo docker ps
diff --git a/go.mod b/go.mod
index f10e123a0..345cf044d 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,8 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.44
- github.com/OpenIMSDK/tools v0.0.21
+ github.com/OpenIMSDK/protocol v0.0.46
+ github.com/OpenIMSDK/tools v0.0.23
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
diff --git a/go.sum b/go.sum
index 34f5d3ae9..8a102d347 100644
--- a/go.sum
+++ b/go.sum
@@ -18,10 +18,10 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.44 h1:P+9gJ9EW3y+VmzrjPludzn/5r1fjubaC19mKYJ7Oiew=
-github.com/OpenIMSDK/protocol v0.0.44/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
-github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/OpenIMSDK/protocol v0.0.46 h1:LKfwcC3pUcJKSxiIyj82fc479BuDbDtsCrPxa7bHxmo=
+github.com/OpenIMSDK/protocol v0.0.46/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/tools v0.0.23 h1:xozfrGzhbpNPlDTap5DLVPk+JfgZ/ZyIj4Cuu3/bm9w=
+github.com/OpenIMSDK/tools v0.0.23/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 51403d631..a1e2c75bc 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -17,6 +17,7 @@ package user
import (
"context"
"errors"
+ "github.com/OpenIMSDK/tools/pagination"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"math/rand"
"strings"
@@ -58,6 +59,11 @@ type userServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
+func (s *userServer) ProcessUserCommandGetAll(ctx context.Context, req *pbuser.ProcessUserCommandGetAllReq) (*pbuser.ProcessUserCommandGetAllResp, error) {
+ //TODO implement me
+ panic("implement me")
+}
+
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis()
if err != nil {
@@ -228,7 +234,7 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
}
func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPaginationUsersReq) (resp *pbuser.GetPaginationUsersResp, err error) {
- total, users, err := s.Page(ctx, req.Pagination)
+ total, users, err := s.PageFindUser(ctx, constant.IMOrdinaryUser, req.Pagination)
if err != nil {
return nil, err
}
@@ -379,11 +385,6 @@ func (s *userServer) GetSubscribeUsersStatus(ctx context.Context,
// ProcessUserCommandAdd user general function add
func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) {
- // Assuming you have a method in s.UserDatabase to add a user command
- err := s.UserDatabase.AddUserCommand(ctx, req.UserID, req.Type, req.Uuid, req.Value)
- if err != nil {
- return nil, err
- }
return &pbuser.ProcessUserCommandAddResp{}, nil
}
@@ -401,11 +402,6 @@ func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.P
// ProcessUserCommandUpdate user general function update
func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) {
- // Assuming you have a method in s.UserDatabase to update a user command
- err := s.UserDatabase.UpdateUserCommand(ctx, req.UserID, req.Type, req.Uuid, req.Value)
- if err != nil {
- return nil, err
- }
return &pbuser.ProcessUserCommandUpdateResp{}, nil
}
@@ -430,7 +426,7 @@ func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.Proc
}
// Return the response with the slice
- return &pbuser.ProcessUserCommandGetResp{KVArray: commandInfoSlice}, nil
+ return &pbuser.ProcessUserCommandGetResp{}, nil
}
func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.AddNotificationAccountReq) (*pbuser.AddNotificationAccountResp, error) {
@@ -438,22 +434,23 @@ func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.Add
return nil, err
}
- var userID string
- for i := 0; i < 20; i++ {
- userId := s.genUserID()
- _, err := s.UserDatabase.FindWithError(ctx, []string{userId})
- if err == nil {
- continue
+ if req.UserID == "" {
+ for i := 0; i < 20; i++ {
+ userId := s.genUserID()
+ _, err := s.UserDatabase.FindWithError(ctx, []string{userId})
+ if err == nil {
+ continue
+ }
+ req.UserID = userId
+ break
+ }
+ if req.UserID == "" {
+ return nil, errs.ErrInternalServer.Wrap("gen user id failed")
}
- userID = userId
- break
- }
- if userID == "" {
- return nil, errs.ErrInternalServer.Wrap("gen user id failed")
}
user := &tablerelation.UserModel{
- UserID: userID,
+ UserID: req.UserID,
Nickname: req.NickName,
FaceURL: req.FaceURL,
CreateTime: time.Now(),
@@ -463,7 +460,11 @@ func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.Add
return nil, err
}
- return &pbuser.AddNotificationAccountResp{}, nil
+ return &pbuser.AddNotificationAccountResp{
+ UserID: req.UserID,
+ NickName: req.NickName,
+ FaceURL: req.FaceURL,
+ }, nil
}
func (s *userServer) UpdateNotificationAccountInfo(ctx context.Context, req *pbuser.UpdateNotificationAccountInfoReq) (*pbuser.UpdateNotificationAccountInfoResp, error) {
@@ -497,30 +498,33 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.
return nil, err
}
- if req.NickName != "" {
- users, err := s.UserDatabase.FindByNickname(ctx, req.NickName)
+ var users []*relation.UserModel
+ var err error
+ if req.Keyword != "" {
+ users, err = s.UserDatabase.Find(ctx, []string{req.Keyword})
if err != nil {
return nil, err
}
- resp := s.userModelToResp(users)
- return resp, nil
- }
-
- if req.UserID != "" {
- users, err := s.UserDatabase.Find(ctx, []string{req.UserID})
+ resp := s.userModelToResp(users, req.Pagination)
+ if resp.Total != 0 {
+ return resp, nil
+ }
+ users, err = s.UserDatabase.FindByNickname(ctx, req.Keyword)
if err != nil {
return nil, err
}
- resp := s.userModelToResp(users)
+ resp = s.userModelToResp(users, req.Pagination)
+ return resp, nil
+
return resp, nil
}
- users, err := s.UserDatabase.FindNotification(ctx, constant.AppNotificationAdmin)
+ users, err = s.UserDatabase.FindNotification(ctx, constant.AppNotificationAdmin)
if err != nil {
return nil, err
}
- resp := s.userModelToResp(users)
+ resp := s.userModelToResp(users, req.Pagination)
return resp, nil
}
@@ -554,7 +558,7 @@ func (s *userServer) genUserID() string {
return string(data)
}
-func (s *userServer) userModelToResp(users []*relation.UserModel) *pbuser.SearchNotificationAccountResp {
+func (s *userServer) userModelToResp(users []*relation.UserModel, pagination pagination.Pagination) *pbuser.SearchNotificationAccountResp {
accounts := make([]*pbuser.NotificationAccountInfo, 0)
var total int64
for _, v := range users {
@@ -568,5 +572,8 @@ func (s *userServer) userModelToResp(users []*relation.UserModel) *pbuser.Search
total += 1
}
}
- return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts}
+
+ notificationAccounts := utils.Paginate(accounts, int(pagination.GetPageNumber()), int(pagination.GetShowNumber()))
+
+ return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: notificationAccounts}
}
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index a109b81ef..445700e5e 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -50,6 +50,8 @@ type UserDatabase interface {
UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
// Page If not found, no error is returned
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
+ // FindUser
+ PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
// IsExist true as long as one exists
IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
// GetAllUserID Get all user IDs
@@ -182,6 +184,10 @@ func (u *userDatabase) Page(ctx context.Context, pagination pagination.Paginatio
return u.userDB.Page(ctx, pagination)
}
+func (u *userDatabase) PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return u.userDB.PageFindUser(ctx, level, pagination)
+}
+
// IsExist Does userIDs exist? As long as there is one, it will be true.
func (u *userDatabase) IsExist(ctx context.Context, userIDs []string) (exist bool, err error) {
users, err := u.userDB.Find(ctx, userIDs)
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 27ca264dd..892a42003 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -77,6 +77,10 @@ func (u *UserMgo) Page(ctx context.Context, pagination pagination.Pagination) (c
return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{}, pagination)
}
+func (u *UserMgo) PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{"app_manger_level": level}, pagination)
+}
+
func (u *UserMgo) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error) {
return mgoutil.FindPage[string](ctx, u.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"user_id": 1}))
}
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index fc116adc2..9844bdcee 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -56,6 +56,7 @@ type UserModelInterface interface {
TakeNotification(ctx context.Context, level int64) (user []*UserModel, err error)
TakeByNickname(ctx context.Context, nickname string) (user []*UserModel, err error)
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
+ PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
Exist(ctx context.Context, userID string) (exist bool, err error)
GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error)
GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
From 3ff588896f53f6ed2465074cb8e8b9a219211800 Mon Sep 17 00:00:00 2001
From: skiffer-git <72860476+skiffer-git@users.noreply.github.com>
Date: Mon, 8 Jan 2024 21:40:04 +0800
Subject: [PATCH 059/110] update: update readme (#1714)
* update: update readme
* update: update readme
* update: update readme
* update: update readme
---
README-zh_CN.md | 56 +++++++++-------
README.md | 174 ++++++++----------------------------------------
2 files changed, 59 insertions(+), 171 deletions(-)
diff --git a/README-zh_CN.md b/README-zh_CN.md
index e2df68a56..12a56d4f6 100644
--- a/README-zh_CN.md
+++ b/README-zh_CN.md
@@ -35,52 +35,62 @@
## Ⓜ️ 关于 OpenIM
-OpenIM 不仅仅是一个开源的即时消息组件,它是你的应用程序生态系统的一个不可或缺的部分。查看下面的图表,了解 AppServer、AppClient、OpenIMServer 和 OpenIMSDK 是如何交互的。
+OpenIM 是一个专门设计用于在应用程序中集成聊天、音视频通话、通知以及AI聊天机器人等通信功能的服务平台。它通过提供一系列强大的API和Webhooks,使开发者可以轻松地在他们的应用中加入这些交互特性。OpenIM 本身并不是一个独立运行的聊天应用,而是作为一个平台,为其他应用提供支持,实现丰富的通信功能。下图展示 AppServer、AppClient、OpenIMServer 和 OpenIMSDK 之间的交互关系来具体说明。
+
+
+
+

## 🚀 关于 OpenIMSDK
-**OpenIMSDK** 无缝集成到您的应用中,提供丰富、实时的消息体验,无需复杂的 UI 集成。它提供:
+**OpenIMSDK** 是为 **OpenIMServer** 设计的IM SDK,专为嵌入客户端应用而生。其主要功能及模块如下:
-+ **本地存储**:用于快速数据检索和消息同步。
-+ **监听器回调**:确保实时消息交互性。
-+ **API 封装**:简化开发流程。
-+ **连接管理**:保证可靠的消息传递。
++ 🌟 主要功能:
-它使用 Golang 构建,并支持跨平台部署,确保在所有平台上提供一致的消息体验。
+ - 📦 本地存储
+ - 🔔 监听器回调
+ - 🛡️ API封装
+ - 🌐 连接管理
+
+ ## 📚 主要模块:
+
+ 1. 🚀 初始化及登录
+ 2. 👤 用户管理
+ 3. 👫 好友管理
+ 4. 🤖 群组功能
+ 5. 💬 会话处理
+
+它使用 Golang 构建,并支持跨平台部署,确保在所有平台上提供一致的接入体验。
👉 **[探索 GO SDK](https://github.com/openimsdk/openim-sdk-core)**
## 🌐 关于 OpenIMServer
-精心用 Golang 开发的 **OpenIMServer** 通过多重方式确保了卓越的即时消息服务器能力:
-
-+ **模块组成**:它由多个模块组成,例如网关和多个 RPC 服务,提供一个多功能的消息环境。
-+ **微服务架构**:支持集群模式,确保出色的性能和可伸缩性,以有效管理各个实例间的通信。
-+ **多样的部署选项**:适应你的操作偏好,通过源代码、Kubernetes 或 Docker 提供部署选项。
++ **OpenIMServer** 具有以下特点:
+ - 🌐 微服务架构:支持集群模式,包括网关(gateway)和多个rpc服务。
+ - 🚀 部署方式多样:支持源代码、kubernetes或docker部署。
+ - 海量用户支持:十万超级大群,千万用户,及百亿消息
### 增强的业务功能:
-+ **REST API**:OpenIMServer 为业务系统提供 REST API,旨在通过后端接口为您的操作提供附加功能,如群组创建和消息推送。
-+ **回调**:为了扩展其在各种业务形式中的实用性,OpenIMServer 提供了回调能力。即,在事件发生之前或之后,它向业务服务器发送请求,比如发送消息,丰富通信过程中的交互和数据交换流。
++ **REST API**:OpenIMServer 提供了REST API供业务系统使用,旨在赋予业务更多功能,例如通过后台接口建立群组、发送推送消息等。
++ **Webhooks**:OpenIMServer提供了回调能力以扩展更多的业务形态,所谓回调,即OpenIMServer会在某一事件发生之前或者之后,向业务服务器发送请求,如发送消息之前或之后的回调。
-👉 **[了解更多](https://doc.rentsoft.cn/guides/introduction/product)**
+👉 **[了解更多](https://docs.openim.io/guides/introduction/product)**
## :rocket: 快速开始
-你只需要一个简单的命令,就可以快速学习 OpenIM 的工程解决方案:
+在线体验iOS/Android/H5/PC/Web:
-```
-bashCopy code
-$ make demo
-```
+👉 **[OpenIM online demo](https://www.openim.io/zh/commercial)**
🤲 为了方便用户体验,我们提供了多种部署解决方案,您可以根据下面的列表选择自己的部署方法:
-+ **[源代码部署指南](https://doc.rentsoft.cn/guides/gettingStarted/imSourceCodeDeployment)**
-+ **[Docker 部署指南](https://doc.rentsoft.cn/guides/gettingStarted/dockerCompose)**
-+ **[Kubernetes 部署指南](https://github.com/openimsdk/open-im-server/tree/main/deployments)**
++ **[源代码部署指南](https://docs.openim.io/guides/gettingStarted/imSourceCodeDeployment)**
++ **[Docker 部署指南](https://docs.openim.io/guides/gettingStarted/dockerCompose)**
++ **[Kubernetes 部署指南](https://docs.openim.io/guides/gettingStarted/k8s-deployment)**
## :hammer_and_wrench: 开始开发 OpenIM
diff --git a/README.md b/README.md
index 781db1217..025672a0b 100644
--- a/README.md
+++ b/README.md
@@ -25,178 +25,56 @@
-
## Ⓜ️ About OpenIM
-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, OpenIMServer, and OpenIMSDK interact.
+OpenIM is a service platform specifically designed for integrating chat, audio-video calls, notifications, and AI chatbots into applications. It provides a range of powerful APIs and Webhooks, enabling developers to easily incorporate these interactive features into their applications. OpenIM is not a standalone chat application, but rather serves as a platform to support other applications in achieving rich communication functionalities. The following diagram illustrates the interaction between AppServer, AppClient, OpenIMServer, and OpenIMSDK to explain in detail.

## 🚀 About OpenIMSDK
-**OpenIMSDK** seamlessly integrates into your application, delivering a rich, real-time messaging experience without requiring intricate UI integration. It provides:
-
-+ **Local Storage**: For quick data retrieval and message synchronization.
-+ **Listener Callbacks**: Ensuring real-time message interactivity.
-+ **API Encapsulation**: Streamlining development processes.
-+ **Connection Management**: Guaranteeing reliable message delivery.
-
-It's crafted in Golang and supports cross-platform deployment, ensuring a coherent messaging experience across all platforms.
-
-👉 **[Explore GO SDK](https://github.com/openimsdk/openim-sdk-core)**
-
-## 🌐 About OpenIMServer
-
-**OpenIMServer**, meticulously developed in Golang, ensures a stellar instant messaging server capability with a multifold approach:
-
-+ **Modular Composition**: It's comprised of several modules, such as the gateway and multiple RPC services, offering a versatile messaging environment.
-+ **Microservices Architecture**: Supporting cluster modes, it assures outstanding performance and scalability to manage communication effectively across various instances.
-+ **Diverse Deployment Options**: Adapts to your operational preferences, offering deployment via source code, Kubernetes, or Docker.
-
-### Enhanced Business Functionalities:
-
-+ **REST API**: OpenIMServer provides REST API for business systems, aiming to empower your operations with additional functionalities like group creation and message push via backend interfaces.
-+ **Callbacks**: To expand its utility across varied business forms, OpenIMServer offers callback capabilities. That is, it sends a request to the business server before or after an event occurs, such as sending a message, enriching the interaction and data exchange flow in the communication processes.
-
-👉 **[Learn More](https://docs.openim.io/guides/introduction/product)**
-
-
++ **REST API**: OpenIMServer offers REST APIs for business systems, aimed at empowering businesses with more functionalities, such as creating groups and sending push messages through backend interfaces.
++ **Webhooks**: OpenIMServer provides callback capabilities to extend more business forms. A callback means that OpenIMServer sends a request to the business server before or after a certain event, like callbacks before or after sending a message.
+👉 **[Learn more](https://docs.openim.io/guides/introduction/product)**
## :rocket: Quick Start
-We support many platforms. Here are the addresses for quick experience on the web side:
-
-👉 **[OpenIM online web demo](https://web-enterprise.rentsoft.cn/)**
-
-You can quickly learn OpenIM engineering solutions, all it takes is one simple command:
-
-```bash
-$ make demo
-```
-
-🤲 In order to facilitate the user experience, we have provided a variety of deployment solutions, you can choose your own deployment method according to the list below:
-
-
+🤲 To facilitate user experience, we offer various deployment solutions. You can choose your deployment method from the list below:
+ **[Source Code Deployment Guide](https://docs.openim.io/guides/gettingStarted/imSourceCodeDeployment)**
-+ **[Production deployment of Linux systems](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-openim-linux-system.md)**
+ **[Docker Deployment Guide](https://docs.openim.io/guides/gettingStarted/dockerCompose)**
-+ **[Kubernetes Deployment Guide](https://github.com/openimsdk/open-im-server/tree/main/deployments)**
-
-
++ **[Kubernetes Deployment Guide](https://docs.openim.io/guides/gettingStarted/k8s-deployment)**
## :hammer_and_wrench: To start developing OpenIM
From 535ae19f7aea4ac06ca1959951396704f67e9674 Mon Sep 17 00:00:00 2001
From: Gordon <46924906+FGadvancer@users.noreply.github.com>
Date: Tue, 9 Jan 2024 14:49:31 +0800
Subject: [PATCH 060/110] fix: group messages sync failed. (#1720)
* fix: add notifications for some notifications.
* fix: modify dismissed group's status.
* fix: Adjust the logic in multiTerminalLoginChecker to prevent onlineUserNum from decreasing below zero, thereby avoiding negative values.
* fix: group messages sync failed.
---
pkg/common/db/controller/conversation.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/common/db/controller/conversation.go b/pkg/common/db/controller/conversation.go
index 2a0cb63e4..c6629e9c8 100644
--- a/pkg/common/db/controller/conversation.go
+++ b/pkg/common/db/controller/conversation.go
@@ -279,7 +279,7 @@ func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context,
for _, v := range existConversationUserIDs {
cache = cache.DelConversations(v, conversationID)
}
- return c.cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
})
}
From a2a082f681a900c0c064b5aca5227b6e4c56b12d Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Wed, 10 Jan 2024 10:27:03 +0800
Subject: [PATCH 061/110] update usercommand and fix callback (#1681)
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* fix bugs
* fix bugs
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* Update go.mod
* Update friend.go
* debug
* debug
* debug
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* I cannot solve todo in test.sh
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* Update go.mod
* fix group notification
* fix group notification
* update openimsdk tools
* update openim server remove duplicate code
* update openim server remove duplicate code
* update user command get
* update user command get
* update response of callback response error
* update black ex
* update join group ex
* update user pb2map
* update go sum
* update go sum
* update updateUserInfoEx
* update updateUserInfoEx
* update updateUserInfoEx add callback functions
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* update pin friend to update friend
* fix go mod
* fix err golangci-lint
* fix UserPb2DBMap
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* fix callback
* fix go.mod
* fix debug
* fix bugs
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* fix updateUserInfoEx
* fix updateUserInfoEx
* modify go.mod
* fix updateUserInfoEx
* fix updateUserInfoEx
* fix updateUserInfoEx
* update user command notification
* update user command get all notification
* update user command get all notification
* fix type = 0
* fix type = 0
* fix type = 0
* fix type = 0
* fix type = 0
* fix type = 0
* fix typing cause callback
* add ex to usercommand
* add ex to usercommand
* update updatefriends
* fix updatefriend map
* fix updatefriend FriendsInfoUpdateNotification
* fix push online and offline user, but why typing trigger callback push?
* fix push online and offline user, but why typing trigger callback push?
* update user command record not found and user access check
* update user command get all user access check
* update go.mod
* fix callback name and place
* upadtae callback test
* fix callback typing
* fix callback typing
* fix callback typing
* fix callback typing
* fix lint on processusercommand
---------
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
---
deployments/templates/openim.yaml | 8 ++
internal/api/route.go | 1 +
internal/api/user.go | 5 ++
internal/push/callback.go | 6 +-
internal/push/push_to_client.go | 5 +-
internal/rpc/friend/friend.go | 29 +++----
internal/rpc/group/callback.go | 8 +-
internal/rpc/group/group.go | 2 +-
internal/rpc/msg/callback.go | 8 +-
internal/rpc/msg/send.go | 2 +
internal/rpc/user/user.go | 108 +++++++++++++++++++++++--
pkg/callbackstruct/constant.go | 2 +-
pkg/common/config/config.go | 2 +-
pkg/common/db/cache/friend.go | 14 ++++
pkg/common/db/controller/friend.go | 30 ++-----
pkg/common/db/controller/user.go | 17 ++--
pkg/common/db/mgo/friend.go | 54 +++----------
pkg/common/db/mgo/user.go | 80 ++++++++++++++++--
pkg/common/db/table/relation/friend.go | 8 +-
pkg/common/db/table/relation/user.go | 5 +-
pkg/rpcclient/notification/friend.go | 2 +-
pkg/rpcclient/notification/user.go | 18 +++++
22 files changed, 287 insertions(+), 127 deletions(-)
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index 6880e4c4e..4c84373a5 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -320,6 +320,14 @@ callback:
enable: ${CALLBACK_ENABLE}
timeout: ${CALLBACK_TIMEOUT}
failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ beforeUpdateUserInfoEx:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
+ afterUpdateUserInfoEx:
+ enable: ${CALLBACK_ENABLE}
+ timeout: ${CALLBACK_TIMEOUT}
+ failedContinue: ${CALLBACK_FAILED_CONTINUE}
afterSendSingleMsg:
enable: ${CALLBACK_ENABLE}
timeout: ${CALLBACK_TIMEOUT}
diff --git a/internal/api/route.go b/internal/api/route.go
index 1c91f4dde..8729bc1b9 100644
--- a/internal/api/route.go
+++ b/internal/api/route.go
@@ -83,6 +83,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
userRouterGroup.POST("/process_user_command_delete", ParseToken, u.ProcessUserCommandDelete)
userRouterGroup.POST("/process_user_command_update", ParseToken, u.ProcessUserCommandUpdate)
userRouterGroup.POST("/process_user_command_get", ParseToken, u.ProcessUserCommandGet)
+ userRouterGroup.POST("/process_user_command_get_all", ParseToken, u.ProcessUserCommandGetAll)
userRouterGroup.POST("/add_notification_account", ParseToken, u.AddNotificationAccount)
userRouterGroup.POST("/update_notification_account", ParseToken, u.UpdateNotificationAccountInfo)
diff --git a/internal/api/user.go b/internal/api/user.go
index 5f0e23631..03d22c354 100644
--- a/internal/api/user.go
+++ b/internal/api/user.go
@@ -221,6 +221,11 @@ func (u *UserApi) ProcessUserCommandGet(c *gin.Context) {
a2r.Call(user.UserClient.ProcessUserCommandGet, u.Client, c)
}
+// ProcessUserCommandGet user general function get all
+func (u *UserApi) ProcessUserCommandGetAll(c *gin.Context) {
+ a2r.Call(user.UserClient.ProcessUserCommandGetAll, u.Client, c)
+}
+
func (u *UserApi) AddNotificationAccount(c *gin.Context) {
a2r.Call(user.UserClient.AddNotificationAccount, u.Client, c)
}
diff --git a/internal/push/callback.go b/internal/push/callback.go
index 2085493c5..99a58fb07 100644
--- a/internal/push/callback.go
+++ b/internal/push/callback.go
@@ -37,7 +37,7 @@ func callbackOfflinePush(
msg *sdkws.MsgData,
offlinePushUserIDs *[]string,
) error {
- if !config.Config.Callback.CallbackOfflinePush.Enable {
+ if !config.Config.Callback.CallbackOfflinePush.Enable || msg.ContentType == constant.Typing {
return nil
}
req := &callbackstruct.CallbackBeforePushReq{
@@ -73,7 +73,7 @@ func callbackOfflinePush(
}
func callbackOnlinePush(ctx context.Context, userIDs []string, msg *sdkws.MsgData) error {
- if !config.Config.Callback.CallbackOnlinePush.Enable || utils.Contain(msg.SendID, userIDs...) {
+ if !config.Config.Callback.CallbackOnlinePush.Enable || utils.Contain(msg.SendID, userIDs...) || msg.ContentType == constant.Typing {
return nil
}
req := callbackstruct.CallbackBeforePushReq{
@@ -107,7 +107,7 @@ func callbackBeforeSuperGroupOnlinePush(
msg *sdkws.MsgData,
pushToUserIDs *[]string,
) error {
- if !config.Config.Callback.CallbackBeforeSuperGroupOnlinePush.Enable {
+ if !config.Config.Callback.CallbackBeforeSuperGroupOnlinePush.Enable || msg.ContentType == constant.Typing {
return nil
}
req := callbackstruct.CallbackBeforeSuperGroupOnlinePushReq{
diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go
index 12b78ea2d..7cee7b99d 100644
--- a/internal/push/push_to_client.go
+++ b/internal/push/push_to_client.go
@@ -101,11 +101,9 @@ func (p *Pusher) DeleteMemberAndSetConversationSeq(ctx context.Context, groupID
func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.MsgData) error {
log.ZDebug(ctx, "Get msg from msg_transfer And push msg", "userIDs", userIDs, "msg", msg.String())
- // callback
if err := callbackOnlinePush(ctx, userIDs, msg); err != nil {
return err
}
-
// push
wsResults, err := p.GetConnsAndOnlinePush(ctx, msg, userIDs)
if err != nil {
@@ -120,7 +118,7 @@ func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.Msg
}
for _, v := range wsResults {
- if msg.SendID != v.UserID && (!v.OnlinePush) {
+ if !v.OnlinePush && msg.SendID == v.UserID {
if err = callbackOfflinePush(ctx, userIDs, msg, &[]string{}); err != nil {
return err
}
@@ -130,6 +128,7 @@ func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.Msg
return err
}
}
+
}
return nil
}
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index c53cb88f5..84702f548 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -452,22 +452,19 @@ func (s *friendServer) UpdateFriends(
return nil, err
}
- for _, friendID := range req.FriendUserIDs {
- if req.IsPinned != nil {
- if err = s.friendDatabase.UpdateFriendPinStatus(ctx, req.OwnerUserID, friendID, req.IsPinned.Value); err != nil {
- return nil, err
- }
- }
- if req.Remark != nil {
- if err = s.friendDatabase.UpdateFriendRemark(ctx, req.OwnerUserID, friendID, req.Remark.Value); err != nil {
- return nil, err
- }
- }
- if req.Ex != nil {
- if err = s.friendDatabase.UpdateFriendEx(ctx, req.OwnerUserID, friendID, req.Ex.Value); err != nil {
- return nil, err
- }
- }
+ val := make(map[string]any)
+
+ if req.IsPinned != nil {
+ val["is_pinned"] = req.IsPinned.Value
+ }
+ if req.Remark != nil {
+ val["remark"] = req.Remark.Value
+ }
+ if req.Ex != nil {
+ val["ex"] = req.Ex.Value
+ }
+ if err = s.friendDatabase.UpdateFriends(ctx, req.OwnerUserID, req.FriendUserIDs, val); err != nil {
+ return nil, err
}
resp := &pbfriend.UpdateFriendsResp{}
diff --git a/internal/rpc/group/callback.go b/internal/rpc/group/callback.go
index 8779cb89b..d891f4d1e 100644
--- a/internal/rpc/group/callback.go
+++ b/internal/rpc/group/callback.go
@@ -279,20 +279,20 @@ func CallbackApplyJoinGroupBefore(ctx context.Context, req *callbackstruct.Callb
return nil
}
-func CallbackTransferGroupOwnerAfter(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) (err error) {
- if !config.Config.Callback.CallbackTransferGroupOwnerAfter.Enable {
+func CallbackAfterTransferGroupOwner(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) (err error) {
+ if !config.Config.Callback.CallbackAfterTransferGroupOwner.Enable {
return nil
}
cbReq := &callbackstruct.CallbackTransferGroupOwnerReq{
- CallbackCommand: callbackstruct.CallbackTransferGroupOwnerAfter,
+ CallbackCommand: callbackstruct.CallbackAfterTransferGroupOwner,
GroupID: req.GroupID,
OldOwnerUserID: req.OldOwnerUserID,
NewOwnerUserID: req.NewOwnerUserID,
}
resp := &callbackstruct.CallbackTransferGroupOwnerResp{}
- if err = http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeJoinGroup); err != nil {
+ if err = http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackAfterTransferGroupOwner); err != nil {
return err
}
return nil
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index b1ea0aa03..f9b73ad2b 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -1061,7 +1061,7 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
return nil, err
}
- if err := CallbackTransferGroupOwnerAfter(ctx, req); err != nil {
+ if err := CallbackAfterTransferGroupOwner(ctx, req); err != nil {
return nil, err
}
s.Notification.GroupOwnerTransferredNotification(ctx, req)
diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go
index 5d192fb87..f98318bba 100644
--- a/internal/rpc/msg/callback.go
+++ b/internal/rpc/msg/callback.go
@@ -70,7 +70,7 @@ func GetContent(msg *sdkws.MsgData) string {
}
func callbackBeforeSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) error {
- if !config.Config.Callback.CallbackBeforeSendSingleMsg.Enable {
+ if !config.Config.Callback.CallbackBeforeSendSingleMsg.Enable || msg.MsgData.ContentType == constant.Typing {
return nil
}
req := &cbapi.CallbackBeforeSendSingleMsgReq{
@@ -85,7 +85,7 @@ func callbackBeforeSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) er
}
func callbackAfterSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) error {
- if !config.Config.Callback.CallbackAfterSendSingleMsg.Enable {
+ if !config.Config.Callback.CallbackAfterSendSingleMsg.Enable || msg.MsgData.ContentType == constant.Typing {
return nil
}
req := &cbapi.CallbackAfterSendSingleMsgReq{
@@ -100,7 +100,7 @@ func callbackAfterSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) err
}
func callbackBeforeSendGroupMsg(ctx context.Context, msg *pbchat.SendMsgReq) error {
- if !config.Config.Callback.CallbackBeforeSendGroupMsg.Enable {
+ if !config.Config.Callback.CallbackBeforeSendGroupMsg.Enable || msg.MsgData.ContentType == constant.Typing {
return nil
}
req := &cbapi.CallbackBeforeSendGroupMsgReq{
@@ -115,7 +115,7 @@ func callbackBeforeSendGroupMsg(ctx context.Context, msg *pbchat.SendMsgReq) err
}
func callbackAfterSendGroupMsg(ctx context.Context, msg *pbchat.SendMsgReq) error {
- if !config.Config.Callback.CallbackAfterSendGroupMsg.Enable {
+ if !config.Config.Callback.CallbackAfterSendGroupMsg.Enable || msg.MsgData.ContentType == constant.Typing {
return nil
}
req := &cbapi.CallbackAfterSendGroupMsgReq{
diff --git a/internal/rpc/msg/send.go b/internal/rpc/msg/send.go
index dd08292bd..630b74a4a 100644
--- a/internal/rpc/msg/send.go
+++ b/internal/rpc/msg/send.go
@@ -65,6 +65,7 @@ func (m *msgServer) sendMsgSuperGroupChat(
if err = callbackBeforeSendGroupMsg(ctx, req); err != nil {
return nil, err
}
+
if err := callbackMsgModify(ctx, req); err != nil {
return nil, err
}
@@ -167,6 +168,7 @@ func (m *msgServer) sendMsgSingleChat(ctx context.Context, req *pbmsg.SendMsgReq
if err = callbackBeforeSendSingleMsg(ctx, req); err != nil {
return nil, err
}
+
if err := callbackMsgModify(ctx, req); err != nil {
return nil, err
}
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index a1e2c75bc..21b419fa3 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -59,11 +59,6 @@ type userServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
-func (s *userServer) ProcessUserCommandGetAll(ctx context.Context, req *pbuser.ProcessUserCommandGetAllReq) (*pbuser.ProcessUserCommandGetAllResp, error) {
- //TODO implement me
- panic("implement me")
-}
-
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis()
if err != nil {
@@ -385,28 +380,94 @@ func (s *userServer) GetSubscribeUsersStatus(ctx context.Context,
// ProcessUserCommandAdd user general function add
func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) {
+ err := authverify.CheckAccessV3(ctx, req.UserID)
+ if err != nil {
+ return nil, err
+ }
+ var value string
+ if req.Value != nil {
+ value = req.Value.Value
+ }
+ var ex string
+ if req.Ex != nil {
+ value = req.Ex.Value
+ }
+ // Assuming you have a method in s.UserDatabase to add a user command
+ err = s.UserDatabase.AddUserCommand(ctx, req.UserID, req.Type, req.Uuid, value, ex)
+ if err != nil {
+ return nil, err
+ }
+ tips := &sdkws.UserCommandAddTips{
+ FromUserID: req.UserID,
+ ToUserID: req.UserID,
+ }
+ err = s.userNotificationSender.UserCommandAddNotification(ctx, tips)
+ if err != nil {
+ return nil, err
+ }
return &pbuser.ProcessUserCommandAddResp{}, nil
}
// ProcessUserCommandDelete user general function delete
func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) {
- // Assuming you have a method in s.UserDatabase to delete a user command
- err := s.UserDatabase.DeleteUserCommand(ctx, req.UserID, req.Type, req.Uuid)
+ err := authverify.CheckAccessV3(ctx, req.UserID)
if err != nil {
return nil, err
}
+ err = s.UserDatabase.DeleteUserCommand(ctx, req.UserID, req.Type, req.Uuid)
+ if err != nil {
+ return nil, err
+ }
+ tips := &sdkws.UserCommandDeleteTips{
+ FromUserID: req.UserID,
+ ToUserID: req.UserID,
+ }
+ err = s.userNotificationSender.UserCommandDeleteNotification(ctx, tips)
+ if err != nil {
+ return nil, err
+ }
return &pbuser.ProcessUserCommandDeleteResp{}, nil
}
// ProcessUserCommandUpdate user general function update
func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) {
+ err := authverify.CheckAccessV3(ctx, req.UserID)
+ if err != nil {
+ return nil, err
+ }
+ val := make(map[string]any)
+ // Map fields from eax to val
+ if req.Value != nil {
+ val["value"] = req.Value.Value
+ }
+ if req.Ex != nil {
+ val["ex"] = req.Ex.Value
+ }
+
+ // Assuming you have a method in s.UserDatabase to update a user command
+ err = s.UserDatabase.UpdateUserCommand(ctx, req.UserID, req.Type, req.Uuid, val)
+ if err != nil {
+ return nil, err
+ }
+ tips := &sdkws.UserCommandUpdateTips{
+ FromUserID: req.UserID,
+ ToUserID: req.UserID,
+ }
+ err = s.userNotificationSender.UserCommandUpdateNotification(ctx, tips)
+ if err != nil {
+ return nil, err
+ }
return &pbuser.ProcessUserCommandUpdateResp{}, nil
}
func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) {
+ err := authverify.CheckAccessV3(ctx, req.UserID)
+ if err != nil {
+ return nil, err
+ }
// Fetch user commands from the database
commands, err := s.UserDatabase.GetUserCommands(ctx, req.UserID, req.Type)
if err != nil {
@@ -419,14 +480,45 @@ func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.Proc
for _, command := range commands {
// No need to use index since command is already a pointer
commandInfoSlice = append(commandInfoSlice, &pbuser.CommandInfoResp{
+ Type: command.Type,
+ Uuid: command.Uuid,
+ Value: command.Value,
+ CreateTime: command.CreateTime,
+ Ex: command.Ex,
+ })
+ }
+
+ // Return the response with the slice
+ return &pbuser.ProcessUserCommandGetResp{CommandResp: commandInfoSlice}, nil
+}
+
+func (s *userServer) ProcessUserCommandGetAll(ctx context.Context, req *pbuser.ProcessUserCommandGetAllReq) (*pbuser.ProcessUserCommandGetAllResp, error) {
+ err := authverify.CheckAccessV3(ctx, req.UserID)
+ if err != nil {
+ return nil, err
+ }
+ // Fetch user commands from the database
+ commands, err := s.UserDatabase.GetAllUserCommands(ctx, req.UserID)
+ if err != nil {
+ return nil, err
+ }
+
+ // Initialize commandInfoSlice as an empty slice
+ commandInfoSlice := make([]*pbuser.AllCommandInfoResp, 0, len(commands))
+
+ for _, command := range commands {
+ // No need to use index since command is already a pointer
+ commandInfoSlice = append(commandInfoSlice, &pbuser.AllCommandInfoResp{
+ Type: command.Type,
Uuid: command.Uuid,
Value: command.Value,
CreateTime: command.CreateTime,
+ Ex: command.Ex,
})
}
// Return the response with the slice
- return &pbuser.ProcessUserCommandGetResp{}, nil
+ return &pbuser.ProcessUserCommandGetAllResp{CommandResp: commandInfoSlice}, nil
}
func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.AddNotificationAccountReq) (*pbuser.AddNotificationAccountResp, error) {
diff --git a/pkg/callbackstruct/constant.go b/pkg/callbackstruct/constant.go
index cda98af16..f3bcf1383 100644
--- a/pkg/callbackstruct/constant.go
+++ b/pkg/callbackstruct/constant.go
@@ -41,7 +41,7 @@ const (
CallbackBeforeUpdateUserInfoExCommand = "callbackBeforeUpdateUserInfoExCommand"
CallbackBeforeUserRegisterCommand = "callbackBeforeUserRegisterCommand"
CallbackAfterUserRegisterCommand = "callbackAfterUserRegisterCommand"
- CallbackTransferGroupOwnerAfter = "callbackTransferGroupOwnerAfter"
+ CallbackAfterTransferGroupOwner = "callbackAfterTransferGroupOwner"
CallbackBeforeSetFriendRemark = "callbackBeforeSetFriendRemark"
CallbackAfterSetFriendRemark = "callbackAfterSetFriendRemark"
CallbackSingleMsgRead = "callbackSingleMsgRead"
diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go
index 88e87e709..9696e9367 100644
--- a/pkg/common/config/config.go
+++ b/pkg/common/config/config.go
@@ -296,7 +296,7 @@ type configStruct struct {
CallbackKillGroupMember CallBackConfig `yaml:"killGroupMember"`
CallbackDismissGroup CallBackConfig `yaml:"dismissGroup"`
CallbackBeforeJoinGroup CallBackConfig `yaml:"joinGroup"`
- CallbackTransferGroupOwnerAfter CallBackConfig `yaml:"transferGroupOwner"`
+ CallbackAfterTransferGroupOwner CallBackConfig `yaml:"transferGroupOwner"`
CallbackBeforeInviteUserToGroup CallBackConfig `yaml:"beforeInviteUserToGroup"`
CallbackAfterJoinGroup CallBackConfig `yaml:"joinGroupAfter"`
CallbackAfterSetGroupInfo CallBackConfig `yaml:"setGroupInfoAfter"`
diff --git a/pkg/common/db/cache/friend.go b/pkg/common/db/cache/friend.go
index 1708f7664..a2b60d48f 100644
--- a/pkg/common/db/cache/friend.go
+++ b/pkg/common/db/cache/friend.go
@@ -44,6 +44,8 @@ type FriendCache interface {
GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error)
// Delete friend when friend info changed
DelFriend(ownerUserID, friendUserID string) FriendCache
+ // Delete friends when friends' info changed
+ DelFriends(ownerUserID string, friendUserIDs []string) FriendCache
}
// FriendCacheRedis is an implementation of the FriendCache interface using Redis.
@@ -152,3 +154,15 @@ func (f *FriendCacheRedis) DelFriend(ownerUserID, friendUserID string) FriendCac
return newFriendCache
}
+
+// DelFriends deletes multiple friend infos from the cache.
+func (f *FriendCacheRedis) DelFriends(ownerUserID string, friendUserIDs []string) FriendCache {
+ newFriendCache := f.NewCache()
+
+ for _, friendUserID := range friendUserIDs {
+ key := f.getFriendKey(ownerUserID, friendUserID)
+ newFriendCache.AddKeys(key) // Assuming AddKeys marks the keys for deletion
+ }
+
+ return newFriendCache
+}
diff --git a/pkg/common/db/controller/friend.go b/pkg/common/db/controller/friend.go
index 924a179ba..3b98f5d7b 100644
--- a/pkg/common/db/controller/friend.go
+++ b/pkg/common/db/controller/friend.go
@@ -74,15 +74,8 @@ type FriendDatabase interface {
// FindBothFriendRequests finds friend requests sent and received
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error)
- // UpdateFriendPinStatus updates the pinned status of a friend
- UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error)
-
- // UpdateFriendRemark updates the remark for a friend
- UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error)
-
- // UpdateFriendEx updates the 'ex' field for a friend
- UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error)
-
+ // UpdateFriends updates fields for friends
+ UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error)
}
type friendDatabase struct {
@@ -323,21 +316,12 @@ func (f *friendDatabase) FindFriendUserIDs(ctx context.Context, ownerUserID stri
func (f *friendDatabase) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
return f.friendRequest.FindBothFriendRequests(ctx, fromUserID, toUserID)
}
-func (f *friendDatabase) UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) {
- if err := f.friend.UpdatePinStatus(ctx, ownerUserID, friendUserID, isPinned); err != nil {
- return err
+func (f *friendDatabase) UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error) {
+ if len(val) == 0 {
+ return nil
}
- return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx)
-}
-func (f *friendDatabase) UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) {
- if err := f.friend.UpdateFriendRemark(ctx, ownerUserID, friendUserID, remark); err != nil {
+ if err := f.friend.UpdateFriends(ctx, ownerUserID, friendUserIDs, val); err != nil {
return err
}
- return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx)
-}
-func (f *friendDatabase) UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) {
- if err := f.friend.UpdateFriendEx(ctx, ownerUserID, friendUserID, ex); err != nil {
- return err
- }
- return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx)
+ return f.cache.DelFriends(ownerUserID, friendUserIDs).ExecDel(ctx)
}
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index 445700e5e..cedae5c97 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -78,10 +78,11 @@ type UserDatabase interface {
SetUserStatus(ctx context.Context, userID string, status, platformID int32) error
//CRUD user command
- AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error
+ AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string, ex string) error
DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error
- UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error
+ UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, val map[string]any) error
GetUserCommands(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error)
+ GetAllUserCommands(ctx context.Context, userID string) ([]*user.AllCommandInfoResp, error)
}
type userDatabase struct {
@@ -259,16 +260,20 @@ func (u *userDatabase) GetUserStatus(ctx context.Context, userIDs []string) ([]*
func (u *userDatabase) SetUserStatus(ctx context.Context, userID string, status, platformID int32) error {
return u.cache.SetUserStatus(ctx, userID, status, platformID)
}
-func (u *userDatabase) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error {
- return u.userDB.AddUserCommand(ctx, userID, Type, UUID, value)
+func (u *userDatabase) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string, ex string) error {
+ return u.userDB.AddUserCommand(ctx, userID, Type, UUID, value, ex)
}
func (u *userDatabase) DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error {
return u.userDB.DeleteUserCommand(ctx, userID, Type, UUID)
}
-func (u *userDatabase) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error {
- return u.userDB.UpdateUserCommand(ctx, userID, Type, UUID, value)
+func (u *userDatabase) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, val map[string]any) error {
+ return u.userDB.UpdateUserCommand(ctx, userID, Type, UUID, val)
}
func (u *userDatabase) GetUserCommands(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) {
commands, err := u.userDB.GetUserCommand(ctx, userID, Type)
return commands, err
}
+func (u *userDatabase) GetAllUserCommands(ctx context.Context, userID string) ([]*user.AllCommandInfoResp, error) {
+ commands, err := u.userDB.GetAllUserCommand(ctx, userID)
+ return commands, err
+}
diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go
index 72289181b..b4172d0fb 100644
--- a/pkg/common/db/mgo/friend.go
+++ b/pkg/common/db/mgo/friend.go
@@ -16,7 +16,6 @@ package mgo
import (
"context"
- "github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/mongo/options"
@@ -144,49 +143,22 @@ func (f *FriendMgo) FindFriendUserIDs(ctx context.Context, ownerUserID string) (
return mgoutil.Find[string](ctx, f.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "friend_user_id": 1}))
}
-// UpdatePinStatus update friend's pin status
-func (f *FriendMgo) UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) {
-
- filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID}
- // Create an update operation to set the "is_pinned" field to isPinned for all documents.
- update := bson.M{"$set": bson.M{"is_pinned": isPinned}}
-
- // Perform the update operation for all documents in the collection.
- _, err = f.coll.UpdateMany(ctx, filter, update)
-
- if err != nil {
- return errs.Wrap(err, "update pin error")
+func (f *FriendMgo) UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) error {
+ // Ensure there are IDs to update
+ if len(friendUserIDs) == 0 {
+ return nil // Or return an error if you expect there to always be IDs
}
- return nil
-}
-func (f *FriendMgo) UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) {
-
- filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID}
- // Create an update operation to set the "is_pinned" field to isPinned for all documents.
- update := bson.M{"$set": bson.M{"remark": remark}}
-
- // Perform the update operation for all documents in the collection.
- _, err = f.coll.UpdateMany(ctx, filter, update)
-
- if err != nil {
- return errs.Wrap(err, "update remark error")
+ // Create a filter to match documents with the specified ownerUserID and any of the friendUserIDs
+ filter := bson.M{
+ "owner_user_id": ownerUserID,
+ "friend_user_id": bson.M{"$in": friendUserIDs},
}
- return nil
-}
-func (f *FriendMgo) UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) {
-
- filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID}
- // Create an update operation to set the "is_pinned" field to isPinned for all documents.
- update := bson.M{"$set": bson.M{"ex": ex}}
-
- // Perform the update operation for all documents in the collection.
- _, err = f.coll.UpdateMany(ctx, filter, update)
-
- if err != nil {
- return errs.Wrap(err, "update ex error")
- }
+ // Create an update document
+ update := bson.M{"$set": val}
- return nil
+ // Perform the update operation for all matching documents
+ _, err := mgoutil.UpdateMany(ctx, f.coll, filter, update)
+ return err
}
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 892a42003..b82966371 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -17,6 +17,7 @@ package mgo
import (
"context"
"github.com/OpenIMSDK/protocol/user"
+ "github.com/OpenIMSDK/tools/errs"
"time"
"github.com/OpenIMSDK/tools/mgoutil"
@@ -100,7 +101,7 @@ func (u *UserMgo) CountTotal(ctx context.Context, before *time.Time) (count int6
return mgoutil.Count(ctx, u.coll, bson.M{"create_time": bson.M{"$lt": before}})
}
-func (u *UserMgo) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error {
+func (u *UserMgo) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string, ex string) error {
collection := u.coll.Database().Collection("userCommands")
// Create a new document instead of updating an existing one
@@ -110,28 +111,48 @@ func (u *UserMgo) AddUserCommand(ctx context.Context, userID string, Type int32,
"uuid": UUID,
"createTime": time.Now().Unix(), // assuming you want the creation time in Unix timestamp
"value": value,
+ "ex": ex,
}
_, err := collection.InsertOne(ctx, doc)
return err
}
+
func (u *UserMgo) DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error {
collection := u.coll.Database().Collection("userCommands")
filter := bson.M{"userID": userID, "type": Type, "uuid": UUID}
- _, err := collection.DeleteOne(ctx, filter)
+ result, err := collection.DeleteOne(ctx, filter)
+ if result.DeletedCount == 0 {
+ // No records found to update
+ return errs.Wrap(errs.ErrRecordNotFound)
+ }
return err
}
-func (u *UserMgo) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error {
+func (u *UserMgo) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, val map[string]any) error {
+ if len(val) == 0 {
+ return nil
+ }
+
collection := u.coll.Database().Collection("userCommands")
filter := bson.M{"userID": userID, "type": Type, "uuid": UUID}
- update := bson.M{"$set": bson.M{"value": value}}
+ update := bson.M{"$set": val}
- _, err := collection.UpdateOne(ctx, filter, update)
- return err
+ result, err := collection.UpdateOne(ctx, filter, update)
+ if err != nil {
+ return err
+ }
+
+ if result.MatchedCount == 0 {
+ // No records found to update
+ return errs.Wrap(errs.ErrRecordNotFound)
+ }
+
+ return nil
}
+
func (u *UserMgo) GetUserCommand(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) {
collection := u.coll.Database().Collection("userCommands")
filter := bson.M{"userID": userID, "type": Type}
@@ -147,19 +168,23 @@ func (u *UserMgo) GetUserCommand(ctx context.Context, userID string, Type int32)
for cursor.Next(ctx) {
var document struct {
+ Type int32 `bson:"type"`
UUID string `bson:"uuid"`
Value string `bson:"value"`
CreateTime int64 `bson:"createTime"`
+ Ex string `bson:"ex"`
}
if err := cursor.Decode(&document); err != nil {
return nil, err
}
- commandInfo := &user.CommandInfoResp{ // Change here: use a pointer to the struct
+ commandInfo := &user.CommandInfoResp{
+ Type: document.Type,
Uuid: document.UUID,
Value: document.Value,
CreateTime: document.CreateTime,
+ Ex: document.Ex,
}
commands = append(commands, commandInfo)
@@ -171,7 +196,48 @@ func (u *UserMgo) GetUserCommand(ctx context.Context, userID string, Type int32)
return commands, nil
}
+func (u *UserMgo) GetAllUserCommand(ctx context.Context, userID string) ([]*user.AllCommandInfoResp, error) {
+ collection := u.coll.Database().Collection("userCommands")
+ filter := bson.M{"userID": userID}
+ cursor, err := collection.Find(ctx, filter)
+ if err != nil {
+ return nil, err
+ }
+ defer cursor.Close(ctx)
+
+ // Initialize commands as a slice of pointers
+ commands := []*user.AllCommandInfoResp{}
+
+ for cursor.Next(ctx) {
+ var document struct {
+ Type int32 `bson:"type"`
+ UUID string `bson:"uuid"`
+ Value string `bson:"value"`
+ CreateTime int64 `bson:"createTime"`
+ Ex string `bson:"ex"`
+ }
+
+ if err := cursor.Decode(&document); err != nil {
+ return nil, err
+ }
+
+ commandInfo := &user.AllCommandInfoResp{
+ Type: document.Type,
+ Uuid: document.UUID,
+ Value: document.Value,
+ CreateTime: document.CreateTime,
+ Ex: document.Ex,
+ }
+
+ commands = append(commands, commandInfo)
+ }
+
+ if err := cursor.Err(); err != nil {
+ return nil, err
+ }
+ return commands, nil
+}
func (u *UserMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
pipeline := bson.A{
bson.M{
diff --git a/pkg/common/db/table/relation/friend.go b/pkg/common/db/table/relation/friend.go
index cc337701d..73f7454df 100644
--- a/pkg/common/db/table/relation/friend.go
+++ b/pkg/common/db/table/relation/friend.go
@@ -57,10 +57,6 @@ type FriendModelInterface interface {
FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
// FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
- // UpdatePinStatus update friend's pin status
- UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error)
- // UpdateFriendRemark update friend's remark
- UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error)
- // UpdateFriendEx update friend's ex
- UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error)
+ // UpdateFriends update friends' fields
+ UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error)
}
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index 9844bdcee..a1b4269d1 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -65,8 +65,9 @@ type UserModelInterface interface {
// 获取范围内用户增量
CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
//CRUD user command
- AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error
+ AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string, ex string) error
DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error
- UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error
+ UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, val map[string]any) error
GetUserCommand(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error)
+ GetAllUserCommand(ctx context.Context, userID string) ([]*user.AllCommandInfoResp, error)
}
diff --git a/pkg/rpcclient/notification/friend.go b/pkg/rpcclient/notification/friend.go
index 00759b1b2..b98a1d38e 100644
--- a/pkg/rpcclient/notification/friend.go
+++ b/pkg/rpcclient/notification/friend.go
@@ -197,7 +197,7 @@ func (f *FriendNotificationSender) FriendRemarkSetNotification(ctx context.Conte
return f.Notification(ctx, fromUserID, toUserID, constant.FriendRemarkSetNotification, &tips)
}
func (f *FriendNotificationSender) FriendsInfoUpdateNotification(ctx context.Context, toUserID string, friendIDs []string) error {
- tips := sdkws.FriendsInfoUpdateTips{}
+ tips := sdkws.FriendsInfoUpdateTips{FromToUserID: &sdkws.FromToUserID{}}
tips.FromToUserID.ToUserID = toUserID
tips.FriendIDs = friendIDs
return f.Notification(ctx, toUserID, toUserID, constant.FriendsInfoUpdateNotification, &tips)
diff --git a/pkg/rpcclient/notification/user.go b/pkg/rpcclient/notification/user.go
index 4feebf7b9..4347faece 100644
--- a/pkg/rpcclient/notification/user.go
+++ b/pkg/rpcclient/notification/user.go
@@ -103,3 +103,21 @@ func (u *UserNotificationSender) UserStatusChangeNotification(
) error {
return u.Notification(ctx, tips.FromUserID, tips.ToUserID, constant.UserStatusChangeNotification, tips)
}
+func (u *UserNotificationSender) UserCommandUpdateNotification(
+ ctx context.Context,
+ tips *sdkws.UserCommandUpdateTips,
+) error {
+ return u.Notification(ctx, tips.FromUserID, tips.ToUserID, constant.UserCommandUpdateNotification, tips)
+}
+func (u *UserNotificationSender) UserCommandAddNotification(
+ ctx context.Context,
+ tips *sdkws.UserCommandAddTips,
+) error {
+ return u.Notification(ctx, tips.FromUserID, tips.ToUserID, constant.UserCommandAddNotification, tips)
+}
+func (u *UserNotificationSender) UserCommandDeleteNotification(
+ ctx context.Context,
+ tips *sdkws.UserCommandDeleteTips,
+) error {
+ return u.Notification(ctx, tips.FromUserID, tips.ToUserID, constant.UserCommandDeleteNotification, tips)
+}
From 1c72e46cc97732c5e67e4547c2782d243ae7c789 Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Wed, 10 Jan 2024 10:55:55 +0800
Subject: [PATCH 062/110] fix: fix the GetSortedConversationList (#1725)
* fix: improve the GetSortedConversation api
* fix: fix the go.mod
* fix: fix the valiable name
---
go.mod | 2 +-
go.sum | 4 ++--
internal/api/conversation.go | 4 ++--
internal/api/route.go | 2 +-
internal/rpc/conversation/conversaion.go | 29 +++++++++++++++---------
internal/rpc/user/user.go | 5 ++++
6 files changed, 29 insertions(+), 17 deletions(-)
diff --git a/go.mod b/go.mod
index 345cf044d..5e8e7275b 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.46
+ github.com/OpenIMSDK/protocol v0.0.47
github.com/OpenIMSDK/tools v0.0.23
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
diff --git a/go.sum b/go.sum
index 8a102d347..80a02d20a 100644
--- a/go.sum
+++ b/go.sum
@@ -18,8 +18,8 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.46 h1:LKfwcC3pUcJKSxiIyj82fc479BuDbDtsCrPxa7bHxmo=
-github.com/OpenIMSDK/protocol v0.0.46/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/protocol v0.0.47 h1:DTJMFSONzqT0i/wa4Q1CtDT/jVATVudIRHcpY1zSWYE=
+github.com/OpenIMSDK/protocol v0.0.47/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.23 h1:xozfrGzhbpNPlDTap5DLVPk+JfgZ/ZyIj4Cuu3/bm9w=
github.com/OpenIMSDK/tools v0.0.23/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
diff --git a/internal/api/conversation.go b/internal/api/conversation.go
index 6463cbde6..eb735e550 100644
--- a/internal/api/conversation.go
+++ b/internal/api/conversation.go
@@ -33,8 +33,8 @@ func (o *ConversationApi) GetAllConversations(c *gin.Context) {
a2r.Call(conversation.ConversationClient.GetAllConversations, o.Client, c)
}
-func (o *ConversationApi) GetConversationsList(c *gin.Context) {
- a2r.Call(conversation.ConversationClient.GetConversationList, o.Client, c)
+func (o *ConversationApi) GetSortedConversationList(c *gin.Context) {
+ a2r.Call(conversation.ConversationClient.GetSortedConversationList, o.Client, c)
}
func (o *ConversationApi) GetConversation(c *gin.Context) {
diff --git a/internal/api/route.go b/internal/api/route.go
index 8729bc1b9..3f16d3e50 100644
--- a/internal/api/route.go
+++ b/internal/api/route.go
@@ -205,7 +205,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
conversationGroup := r.Group("/conversation", ParseToken)
{
c := NewConversationApi(*conversationRpc)
- conversationGroup.POST("/get_conversations_list", c.GetConversationsList)
+ conversationGroup.POST("/get_sorted_conversation_list", c.GetSortedConversationList)
conversationGroup.POST("/get_all_conversations", c.GetAllConversations)
conversationGroup.POST("/get_conversation", c.GetConversation)
conversationGroup.POST("/get_conversations", c.GetConversations)
diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go
index b80e32953..d0d59547c 100644
--- a/internal/rpc/conversation/conversaion.go
+++ b/internal/rpc/conversation/conversaion.go
@@ -89,8 +89,8 @@ func (c *conversationServer) GetConversation(ctx context.Context, req *pbconvers
return resp, nil
}
-func (m *conversationServer) GetConversationList(ctx context.Context, req *pbconversation.GetConversationListReq) (resp *pbconversation.GetConversationListResp, err error) {
- log.ZDebug(ctx, "GetConversationList", "seqs", req, "userID", req.UserID)
+func (m *conversationServer) GetSortedConversationList(ctx context.Context, req *pbconversation.GetSortedConversationListReq) (resp *pbconversation.GetSortedConversationListResp, err error) {
+ log.ZDebug(ctx, "GetSortedConversationList", "seqs", req, "userID", req.UserID)
var conversationIDs []string
if len(req.ConversationIDs) == 0 {
conversationIDs, err = m.conversationDatabase.GetConversationIDs(ctx, req.UserID)
@@ -129,30 +129,37 @@ func (m *conversationServer) GetConversationList(ctx context.Context, req *pbcon
return nil, err
}
+ var unreadTotal int64
conversation_unreadCount := make(map[string]int64)
for conversationID, maxSeq := range maxSeqs {
- conversation_unreadCount[conversationID] = maxSeq - hasReadSeqs[conversationID]
+ unreadCount := maxSeq - hasReadSeqs[conversationID]
+ conversation_unreadCount[conversationID] = unreadCount
+ unreadTotal += unreadCount
}
- conversation_isPinkTime := make(map[int64]string)
- conversation_notPinkTime := make(map[int64]string)
+ conversation_isPinTime := make(map[int64]string)
+ conversation_notPinTime := make(map[int64]string)
for _, v := range conversations {
conversationID := v.ConversationID
time := conversationMsg[conversationID].MsgInfo.LatestMsgRecvTime
conversationMsg[conversationID].RecvMsgOpt = v.RecvMsgOpt
if v.IsPinned {
conversationMsg[conversationID].IsPinned = v.IsPinned
- conversation_isPinkTime[time] = conversationID
+ conversation_isPinTime[time] = conversationID
continue
}
- conversation_notPinkTime[time] = conversationID
+ conversation_notPinTime[time] = conversationID
}
- resp = &pbconversation.GetConversationListResp{
+ resp = &pbconversation.GetSortedConversationListResp{
+ ConversationTotal: int64(len(chatLogs)),
ConversationElems: []*pbconversation.ConversationElem{},
+ UnreadTotal: unreadTotal,
}
- m.conversationSort(conversation_isPinkTime, resp, conversation_unreadCount, conversationMsg)
- m.conversationSort(conversation_notPinkTime, resp, conversation_unreadCount, conversationMsg)
+ m.conversationSort(conversation_isPinTime, resp, conversation_unreadCount, conversationMsg)
+ m.conversationSort(conversation_notPinTime, resp, conversation_unreadCount, conversationMsg)
+
+ resp.ConversationElems = utils.Paginate(resp.ConversationElems, int(req.Pagination.GetPageNumber()), int(req.Pagination.GetShowNumber()))
return resp, nil
}
@@ -425,7 +432,7 @@ func (c *conversationServer) GetConversationOfflinePushUserIDs(
func (c *conversationServer) conversationSort(
conversations map[int64]string,
- resp *pbconversation.GetConversationListResp,
+ resp *pbconversation.GetSortedConversationListResp,
conversation_unreadCount map[string]int64,
conversationMsg map[string]*pbconversation.ConversationElem,
) {
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 21b419fa3..158e37d70 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -539,6 +539,11 @@ func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.Add
if req.UserID == "" {
return nil, errs.ErrInternalServer.Wrap("gen user id failed")
}
+ } else {
+ _, err := s.UserDatabase.FindWithError(ctx, []string{req.UserID})
+ if err == nil {
+ return nil, errs.ErrArgs.Wrap("userID is used")
+ }
}
user := &tablerelation.UserModel{
From 04c77bff7e3093b4839484a9404a2c3a1dd60489 Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Wed, 10 Jan 2024 18:59:12 +0800
Subject: [PATCH 063/110] fix: fix the mongo search error (#1736)
* fix: improve the GetSortedConversation api
* fix: fix the go.mod
* fix: fix the valiable name
* fix: the FindUser error
* fix: fix the mongo search
---
pkg/common/db/mgo/user.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index b82966371..b07f82928 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -83,7 +83,7 @@ func (u *UserMgo) PageFindUser(ctx context.Context, level int64, pagination pagi
}
func (u *UserMgo) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error) {
- return mgoutil.FindPage[string](ctx, u.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"user_id": 1}))
+ return mgoutil.FindPage[string](ctx, u.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
}
func (u *UserMgo) Exist(ctx context.Context, userID string) (exist bool, err error) {
@@ -91,7 +91,7 @@ func (u *UserMgo) Exist(ctx context.Context, userID string) (exist bool, err err
}
func (u *UserMgo) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) {
- return mgoutil.FindOne[int](ctx, u.coll, bson.M{"user_id": userID}, options.FindOne().SetProjection(bson.M{"global_recv_msg_opt": 1}))
+ return mgoutil.FindOne[int](ctx, u.coll, bson.M{"user_id": userID}, options.FindOne().SetProjection(bson.M{"_id": 0, "global_recv_msg_opt": 1}))
}
func (u *UserMgo) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
From bf46412c5a9d6e68eca1e87f69c6db3aa1d31d13 Mon Sep 17 00:00:00 2001
From: chao <48119764+withchao@users.noreply.github.com>
Date: Fri, 12 Jan 2024 11:49:16 +0800
Subject: [PATCH 064/110] fix: GroupApplicationRejectedNotification not
notification apply for userID (#1740)
* fix: GroupApplicationAcceptedNotification
* fix: GroupApplicationAcceptedNotification
* fix: NotificationUserInfoUpdate
---
internal/rpc/group/group.go | 5 +----
pkg/rpcclient/notification/group.go | 16 +++++++++++++---
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index f9b73ad2b..abc271651 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -109,14 +109,11 @@ type groupServer struct {
}
func (s *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgroup.NotificationUserInfoUpdateReq) (*pbgroup.NotificationUserInfoUpdateResp, error) {
- defer log.ZDebug(ctx, "return")
+ defer log.ZDebug(ctx, "NotificationUserInfoUpdate return")
members, err := s.db.FindGroupMemberUser(ctx, nil, req.UserID)
if err != nil {
return nil, err
}
- if err := s.PopulateGroupMember(ctx, members...); err != nil {
- return nil, err
- }
groupIDs := make([]string, 0, len(members))
for _, member := range members {
if member.Nickname != "" && member.FaceURL != "" {
diff --git a/pkg/rpcclient/notification/group.go b/pkg/rpcclient/notification/group.go
index cbae7c49b..8c3719b2c 100755
--- a/pkg/rpcclient/notification/group.go
+++ b/pkg/rpcclient/notification/group.go
@@ -409,11 +409,16 @@ func (g *GroupNotificationSender) GroupApplicationAcceptedNotification(ctx conte
if err != nil {
return err
}
- tips := &sdkws.GroupApplicationAcceptedTips{Group: group, HandleMsg: req.HandledMsg, ReceiverAs: 1}
+ tips := &sdkws.GroupApplicationAcceptedTips{Group: group, HandleMsg: req.HandledMsg}
if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
return err
}
- for _, userID := range append(userIDs, mcontext.GetOpUserID(ctx)) {
+ for _, userID := range append(userIDs, req.FromUserID) {
+ if userID == req.FromUserID {
+ tips.ReceiverAs = 0
+ } else {
+ tips.ReceiverAs = 1
+ }
err = g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationAcceptedNotification, tips)
if err != nil {
log.ZError(ctx, "failed", err)
@@ -441,7 +446,12 @@ func (g *GroupNotificationSender) GroupApplicationRejectedNotification(ctx conte
if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
return err
}
- for _, userID := range append(userIDs, mcontext.GetOpUserID(ctx)) {
+ for _, userID := range append(userIDs, req.FromUserID) {
+ if userID == req.FromUserID {
+ tips.ReceiverAs = 0
+ } else {
+ tips.ReceiverAs = 1
+ }
err = g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationRejectedNotification, tips)
if err != nil {
log.ZError(ctx, "failed", err)
From c795304df108f4f868b12c72d9889f95f7b73af7 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Fri, 12 Jan 2024 18:04:06 +0800
Subject: [PATCH 065/110] =?UTF-8?q?=F0=9F=9A=80=20Enhancements=20in=20Offl?=
=?UTF-8?q?ine=20Deployment=20Documentation,=20CICD=20Process=20Upgrades,?=
=?UTF-8?q?=20Deployment=20Optimization,=20and=20Additional=20Fixes=20(#17?=
=?UTF-8?q?21)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: support openim prom enbels
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: support openim prom enbels
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: support openim prom enbels
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: support openim prom enbels
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: support openim prom enbels
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: support openim prom enbels
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: support openim prom enbels
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: support openim prom enbels
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add go formity checker
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim offline deployment docs
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim offline deployment docs
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim offline deployment docs
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim support arm arch
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fox openim support arm arch
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fox openim support arm arch
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim v3.4 and v3.5 changelog
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add devcontainer.json file
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim v3.4 and v3.5 changelog
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim v3.4 and v3.5 changelog
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* Update util.sh
amend shell get pid command fd on mac.
* feat: Add To start developing OpenIM Docs
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* docs: update openim readme and dov container
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: set openim lint
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: fix go release scripts
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: fix go release scripts
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* docs(changelog): add CHANGELOG-3.5.0+6.a09200e.md
* docs(changelog): add CHANGELOG-3.5.0+2.e0bd54f.md
* docs(changelog): add CHANGELOG-3.5.0+2.e0bd54f-1-g4ce6a0fa6.md
* feat: set openim lint
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* docs(changelog): add CHANGELOG-3.5.0+2.e0bd54f-3-g52f9fc209.md
* docs(changelog): add CHANGELOG-3.5.0+2.e0bd54f-4-g87f685b17.md
* docs(changelog): add CHANGELOG-3.5.0.md
* feat: set openim lint
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix scripts functions upload
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix scripts functions upload
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* docs(changelog): add CHANGELOG-3.5.0.md
* fix: fix scripts functions upload
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix scripts functions upload
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: set openim lint
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
Co-authored-by: mrwenhui
---
.devcontainer /README.md | 140 ++
.devcontainer /devcontainer.json | 83 +
.github/workflows/e2e-test.yml | 33 +-
.github/workflows/openimci.yml | 36 +-
CHANGELOG/CHANGELOG-3.4.md | 32 +
CHANGELOG/CHANGELOG-3.5.0.md | 15 +
CHANGELOG/CHANGELOG-3.5.md | 76 +
README.md | 6 +-
assets/README.md | 2 +-
cmd/openim-api/main.go | 4 +-
docker-compose.yml | 56 +-
docs/contrib/environment.md | 4 +-
docs/contrib/gitcherry-pick.md | 2 +-
docs/contrib/github-workflow.md | 5 +-
docs/contrib/init-config.md | 4 +-
.../contrib/mac-developer-deployment-guide.md | 149 ++
docs/contrib/offline-deployment.md | 118 +-
docs/contrib/prometheus-grafana.md | 55 +-
docs/contrib/release.md | 251 +++
go.work | 11 +-
pkg/common/prommetrics/gin_api.go | 4 +-
pkg/common/prommetrics/prommetrics.go | 6 +-
scripts/.spelling_failures | 4 +-
scripts/build-all-service.sh | 2 +-
scripts/check-all.sh | 3 +-
scripts/common.sh | 17 +-
scripts/ensure-tag.sh | 4 +-
scripts/genconfig.sh | 2 +-
scripts/install/environment.sh | 34 +-
scripts/install/openim-man.sh | 6 +-
scripts/install/openim-tools.sh | 9 +-
scripts/lib/chat.sh | 6 +-
scripts/lib/golang.sh | 15 +-
scripts/lib/init.sh | 9 +-
scripts/lib/release.sh | 156 +-
scripts/lib/util.sh | 1490 ++++++++++++++++-
scripts/make-rules/common.mk | 5 +-
scripts/make-rules/tools.mk | 2 +-
scripts/release.sh | 135 +-
scripts/stop-all.sh | 11 +-
scripts/update-generated-docs.sh | 2 +-
scripts/update-yamlfmt.sh | 6 +-
scripts/verify-shellcheck.sh | 2 +-
scripts/verify-spelling.sh | 4 +-
scripts/verify-yamlfmt.sh | 4 +-
test/typecheck/typecheck.go | 8 +-
test/wrktest.sh | 2 +-
tools/changelog/changelog.go | 2 +-
tools/component/component.go | 34 +-
tools/formitychecker/README.md | 102 ++
tools/formitychecker/checker/checker.go | 97 ++
tools/formitychecker/config/config.go | 27 +
tools/formitychecker/formitychecker.go | 27 +
tools/formitychecker/go.mod | 3 +
tools/imctl/imctl.go | 8 +
tools/up35/pkg/convert.go | 70 +-
tools/up35/pkg/pkg.go | 16 +-
tools/yamlfmt/OWNERS | 10 -
58 files changed, 3090 insertions(+), 336 deletions(-)
create mode 100644 .devcontainer /README.md
create mode 100644 .devcontainer /devcontainer.json
create mode 100644 CHANGELOG/CHANGELOG-3.4.md
create mode 100644 CHANGELOG/CHANGELOG-3.5.0.md
create mode 100644 CHANGELOG/CHANGELOG-3.5.md
create mode 100644 docs/contrib/mac-developer-deployment-guide.md
create mode 100644 docs/contrib/release.md
create mode 100644 tools/formitychecker/README.md
create mode 100644 tools/formitychecker/checker/checker.go
create mode 100644 tools/formitychecker/config/config.go
create mode 100644 tools/formitychecker/formitychecker.go
create mode 100644 tools/formitychecker/go.mod
create mode 100644 tools/imctl/imctl.go
delete mode 100644 tools/yamlfmt/OWNERS
diff --git a/.devcontainer /README.md b/.devcontainer /README.md
new file mode 100644
index 000000000..7abba5ac1
--- /dev/null
+++ b/.devcontainer /README.md
@@ -0,0 +1,140 @@
+# OpenIM - OSS Development Container
+
+[](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/openimsdk/open-im-server)
+
+This repository includes configuration for a development container for working with OpenIM - OSS in a local container or using [GitHub Codespaces](https://github.com/features/codespaces).
+
+> **Tip:** The default VNC password is `openIM123`. The VNC server runs on port `5901` and a web client is available on port `11001`, openim-admin on port `11002`.
+
+## Quick start - local
+
+If you already have VS Code and Docker installed, you can click the badge above or [here](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/openimsdk/open-im-server) to get started. Clicking these links will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use.
+
+1. Install Docker Desktop or Docker for Linux on your local machine. (See [docs](https://aka.ms/vscode-remote/containers/getting-started) for additional details.)
+
+2. **Important**: Docker needs at least **4 Cores and 8 GB of RAM** to run a full build with **9 GB of RAM** being recommended. If you are on macOS, or are using the old Hyper-V engine for Windows, update these values for Docker Desktop by right-clicking on the Docker status bar item and going to **Preferences/Settings > Resources > Advanced**.
+
+ > **Note:** The [Resource Monitor](https://marketplace.visualstudio.com/items?itemName=mutantdino.resourcemonitor) extension is included in the container so you can keep an eye on CPU/Memory in the status bar.
+
+3. Install [Visual Studio Code Stable](https://code.visualstudio.com/) or [Insiders](https://code.visualstudio.com/insiders/) and the [Dev Containers](https://aka.ms/vscode-remote/download/containers) extension.
+
+ 
+
+ > **Note:** The Dev Containers extension requires the Visual Studio Code distribution of OpenIM - OSS. See the [FAQ](https://aka.ms/vscode-remote/faq/license) for details.
+
+4. Press Ctrl/Cmd + Shift + P or F1 and select **Dev Containers: Clone Repository in Container Volume...**.
+
+ > **Tip:** While you can use your local source tree instead, operations like `yarn install` can be slow on macOS or when using the Hyper-V engine on Windows. We recommend using the WSL filesystem on Windows or the "clone repository in container" approach on Windows and macOS instead since it uses "named volume" rather than the local filesystem.
+
+5. Type `https://github.com/openimsdk/open-im-server` (or a branch or PR URL) in the input box and press Enter .
+
+6. After the container is running:
+ 1. If you have the `DISPLAY` or `WAYLAND_DISPLAY` environment variables set locally (or in WSL on Windows), desktop apps in the container will be shown in local windows.
+ 2. If these are not set, open a web browser and go to [http://localhost:11001](http://localhost:11001), or use a [VNC Viewer][def] to connect to `localhost:11001` and enter `vscode` as the password. Anything you start in VS Code, or the integrated terminal, will appear here.
+
+Next: **[Try it out!](#try-it)**
+
+## Quick start - GitHub Codespaces
+
+1. From the [openimsdk/open-im-server GitHub repository](https://github.com/openimsdk/open-im-server), click on the **Code** dropdown, select **Open with Codespaces**, and then click on **New codespace**. If prompted, select the **Standard** machine size (which is also the default).
+
+ > **Note:** You will not see these options within GitHub if you are not in the Codespaces beta.
+
+2. After the codespace is up and running in your browser, press Ctrl/Cmd + Shift + P or F1 and select **Ports: Focus on Ports View**.
+
+3. You should see **VNC web client (11001)** under in the list of ports. Select the line and click on the globe icon to open it in a browser tab.
+
+ > **Tip:** If you do not see the port, Ctrl/Cmd + Shift + P or F1 , select **Forward a Port** and enter port `11001`.
+
+4. In the new tab, you should see noVNC. Click **Connect** and enter `vscode` as the password.
+
+Anything you start in VS Code, or the integrated terminal, will appear here.
+
+Next: **[Try it out!](#try-it)**
+
+### Using VS Code with GitHub Codespaces
+
+You may see improved VNC responsiveness when accessing a codespace from VS Code client since you can use a [VNC Viewer][def]. Here's how to do it.
+
+1. Install [Visual Studio Code Stable](https://code.visualstudio.com/) or [Insiders](https://code.visualstudio.com/insiders/) and the the [GitHub Codespaces extension](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces).
+
+ > **Note:** The GitHub Codespaces extension requires the Visual Studio Code distribution of OpenIM - OSS.
+
+2. After the VS Code is up and running, press Ctrl/Cmd + Shift + P or F1 , choose **Codespaces: Create New Codespace**, and use the following settings:
+
+- `openimsdk/open-im-server` for the repository.
+- Select any branch (e.g. **main**) - you can select a different one later.
+- Choose **Standard** (4-core, 8GB) as the size.
+
+3. After you have connected to the codespace, you can use a [VNC Viewer][def] to connect to `localhost:5901` and enter `vscode` as the password.
+
+ > **Tip:** You may also need change your VNC client's **Picture Quality** setting to **High** to get a full color desktop.
+
+4. Anything you start in VS Code, or the integrated terminal, will appear here.
+
+Next: **[Try it out!](#try-it)**
+
+## Try it
+
+This container uses the [Fluxbox](http://fluxbox.org/) window manager to keep things lean. **Right-click on the desktop** to see menu options. It works with GNOME and GTK applications, so other tools can be installed if needed.
+
+ > **Note:** You can also set the resolution from the command line by typing `set-resolution`.
+
+To start working with OpenIM - OSS, follow these steps:
+
+1. In your local VS Code client, open a terminal (Ctrl/Cmd + Shift + \` ) and type the following commands:
+
+ ```bash
+ yarn install
+ bash scripts/code.sh
+ ```
+
+2. After the build is complete, open a web browser or a [VNC Viewer][def] to connect to the desktop environment as described in the quick start and enter `vscode` as the password.
+
+3. You should now see OpenIM - OSS!
+
+Next, let's try debugging.
+
+1. Shut down OpenIM - OSS by clicking the box in the upper right corner of the OpenIM - OSS window through your browser or VNC viewer.
+
+2. Go to your local VS Code client, and use the **Run / Debug** view to launch the **VS Code** configuration. (Typically the default, so you can likely just press F5 ).
+
+ > **Note:** If launching times out, you can increase the value of `timeout` in the "VS Code", "Attach Main Process", "Attach Extension Host", and "Attach to Shared Process" configurations in [launch.json](../../.vscode/launch.json). However, running `./scripts/code.sh` first will set up Electron which will usually solve timeout issues.
+
+3. After a bit, OpenIM - OSS will appear with the debugger attached!
+
+Enjoy!
+
+
+### Dotfiles
+
+Dotfiles are files and folders on Unix-like systems starting with `.` that control the configuration of applications and shells on your system. You can store and manage your dotfiles in a repository on GitHub. For advice and tutorials about what to include in your dotfiles repository, see [GitHub does dotfiles](https://dotfiles.github.io/).
+
+Your dotfiles repository might include your shell aliases and preferences, any tools you want to install, or any other codespace personalization you want to make.
+
+You can configure GitHub Codespaces to use dotfiles from any repository you own by selecting that repository in your [personal GitHub Codespaces settings](https://github.com/settings/codespaces).
+
+When you create a new codespace, GitHub clones your selected dotfiles repository to the codespace environment, and looks for one of the following files to set up the environment.
+
+- *install.sh*
+- *install*
+- *bootstrap.sh*
+- *bootstrap*
+- *script/bootstrap*
+- *setup.sh*
+- *setup*
+- *script/setup*
+
+If none of these files are found, then any files or folders in your selected dotfiles repository starting with `.` are symlinked to the codespace's `~` or `$HOME` directory.
+
+Any changes to your selected dotfiles repository will apply only to each new codespace, and do not affect any existing codespace.
+
+**Note:** Currently, Codespaces does not support personalizing the User-scoped settings for VS Code with your `dotfiles` repository. You can set default Workspace and Remote [Codespaces] settings for a specific project in the project's repository. For more information, see "[Introduction to dev containers](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers#creating-a-custom-dev-container-configuration)."
+
+In addition, you can also configure Codespaces secrets on your personal profile page at [github.com/settings/codespaces](https://github.com/settings/codespaces). Development environment secrets are environment variables that are encrypted, and they are accessible to any codespace you create using repositories that have access to these secrets.
+
+### Notes
+
+The container comes with VS Code Insiders installed. To run it from an Integrated Terminal use `VSCODE_IPC_HOOK_CLI= /usr/bin/code-insiders .`.
+
+[def]: https://www.realvnc.com/en/connect/download/viewer/
\ No newline at end of file
diff --git a/.devcontainer /devcontainer.json b/.devcontainer /devcontainer.json
new file mode 100644
index 000000000..d8b13d3a4
--- /dev/null
+++ b/.devcontainer /devcontainer.json
@@ -0,0 +1,83 @@
+{
+ // Reference Doc: https://code.visualstudio.com/remote/advancedcontainers/overview
+ "name": "OpenIM Dev Environment",
+ // Update the container version when you publish dev-container
+ "dockerComposeFile": "docker-compose.yml",
+ "build": { "dockerfile": "Dockerfile" },
+ // Replace with uncommented line below to build your own local copy of the image
+ // "dockerFile": "../docker/Dockerfile-dev",
+ "containerEnv": {
+ // Uncomment to overwrite devcontainer .kube/config and .minikube certs with the localhost versions
+ // each time the devcontainer starts, if the respective .kube-localhost/config and .minikube-localhost
+ // folders respectively are bind mounted to the devcontainer.
+ // "SYNC_LOCALHOST_KUBECONFIG": "true"
+
+ // Uncomment to disable docker-in-docker and automatically proxy default /var/run/docker.sock to
+ // the localhost bind-mount /var/run/docker-host.sock.
+ // "BIND_LOCALHOST_DOCKER": "true"
+ },
+ "remoteEnv": {
+ "GO111MODULE": "on",
+ "GOPROXY": "https://goproxy.cn",
+ "GOSUMDB": "sum.golang.org",
+ "GONOPROXY": "github.com/openimsdk",
+ "GONOSUMDB": "github.com/openimsdk",
+ "GOPRIVATE": "github.com/openimsdk"
+ },
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "davidanson.vscode-markdownlint",
+ "golang.go",
+ "ms-azuretools.vscode-dapr",
+ "ms-azuretools.vscode-docker",
+ "ms-kubernetes-tools.vscode-kubernetes-tools"
+ ],
+ "settings": {
+ "go.toolsManagement.checkForUpdates": "local",
+ "go.useLanguageServer": true,
+ "go.gopath": "/go"
+ }
+ }
+ },
+ "mounts": [
+ // Mount docker-in-docker library volume
+ "type=volume,source=dind-var-lib-docker,target=/var/lib/docker",
+
+ // Bind mount docker socket under an alias to support docker-from-docker
+ "type=bind,source=/var/run/docker.sock,target=/var/run/docker-host.sock",
+
+ // Bind mount docker socket under an alias to support docker-from-docker
+ // "type=bind,source=${env:HOME}${env:USERPROFILE}/.minikube/cache,target=/home/openim/.minikube/cache",
+
+ // Uncomment to clone local .kube/config into devcontainer
+ "type=bind,source=${env:HOME}${env:USERPROFILE}/.kube,target=/home/openim/.kube-localhost"
+
+ // Uncomment to additionally clone minikube certs into devcontainer for use with .kube/config
+ // "type=bind,source=${env:HOME}${env:USERPROFILE}/.minikube,target=/home/openim/.minikube-localhost"
+ ],
+ // Always run image-defined default command
+ "overrideCommand": false,
+ // On Linux, this will prevent new files getting created as root, but you
+ // may need to update the USER_UID and USER_GID in docker/Dockerfile-dev
+ // to match your user if not 1000.
+ // "remoteUser": "openimsdk",
+ "runArgs": [
+ // Enable ptrace-based debugging for go
+ "--cap-add=SYS_PTRACE",
+ "--security-opt",
+ "seccomp=unconfined",
+
+ // Uncomment to bind to host network for local devcontainer; this is necessary if using the
+ // bind-mounted /var/run/docker-host.sock directly.
+ "--net=host",
+
+ // Enable docker-in-docker configuration. Comment out if not using for better security.
+ "--privileged",
+
+ // Run the entrypoint defined in container image.
+ "--init"
+ ],
+ "workspaceFolder": "/workspaces/openim",
+ "workspaceMount": "type=bind,source=${localWorkspaceFolder},target=/workspaces/openim"
+}
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index 6d8112eb4..21bb4986e 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -92,29 +92,30 @@ jobs:
- name: Exec OpenIM API test
run: |
- touch /tmp/test.md
- echo "# OpenIM Test" >> /tmp/test.md
- echo "## OpenIM API Test" >> /tmp/test.md
- echo "Command Output for OpenIM API Test " >> /tmp/test.md
- echo "" >> /tmp/test.md
- sudo make test-api | tee -a /tmp/test.md
- echo "
" >> /tmp/test.md
- echo " " >> /tmp/test.md
+ mkdir -p ./tmp
+ touch ./tmp/test.md
+ echo "# OpenIM Test" >> ./tmp/test.md
+ echo "## OpenIM API Test" >> ./tmp/test.md
+ echo "Command Output for OpenIM API Test " >> ./tmp/test.md
+ echo "" >> ./tmp/test.md
+ sudo make test-api | tee -a ./tmp/test.md
+ echo "
" >> ./tmp/test.md
+ echo " " >> ./tmp/test.md
- name: Exec OpenIM E2E Test
run: |
- echo "" >> /tmp/test.md
- echo "## OpenIM E2E Test" >> /tmp/test.md
- echo "Command Output for OpenIM E2E Test " >> /tmp/test.md
- echo "" >> /tmp/test.md
- sudo make test-e2e | tee -a /tmp/test.md
- echo "
" >> /tmp/test.md
- echo " " >> /tmp/test.md
+ echo "" >> ./tmp/test.md
+ echo "## OpenIM E2E Test" >> ./tmp/test.md
+ echo "Command Output for OpenIM E2E Test " >> ./tmp/test.md
+ echo "" >> ./tmp/test.md
+ sudo make test-e2e | tee -a ./tmp/test.md
+ echo "
" >> ./tmp/test.md
+ echo " " >> ./tmp/test.md
- name: Comment PR with file
uses: thollander/actions-comment-pull-request@v2
with:
- filePath: /tmp/test.md
+ filePath: ./tmp/test.md
comment_tag: nrt_file
reactions: eyes, rocket
mode: recreate
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index 00339110c..dce5649df 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -18,6 +18,7 @@ on:
push:
branches:
- main
+ - release-*
paths-ignore:
- "docs/**"
- "README.md"
@@ -26,6 +27,7 @@ on:
pull_request:
branches:
- main
+ - release-*
paths-ignore:
- "README.md"
- "README_zh-CN.md"
@@ -81,6 +83,11 @@ jobs:
- name: Build Source
run: sudo make build
+ - name: Build multiarch PLATFORMS
+ if: startsWith(github.ref, 'refs/heads/release-')
+ run: |
+ sudo make multiarch
+
- name: Cleanup Build
run: sudo make clean
@@ -107,7 +114,7 @@ jobs:
continue-on-error: true
openim-start:
- name: Test OpenIM install/start on ${{ matrix.os }}
+ name: Test OpenIM install/start on ${{ matrix.os }}-${{ matrix.arch }}
runs-on: ${{ matrix.os }}
permissions:
contents: write
@@ -136,6 +143,7 @@ jobs:
# sudo docker ps
- name: Check the OpenIM environment and status
+ if: runner.os == 'Linux' && matrix.arch == 'amd64'
id: docker_info
run: |
sleep 30
@@ -148,24 +156,29 @@ jobs:
- name: Comment PR
uses: thollander/actions-comment-pull-request@v2
+ if: runner.os == 'Linux' && matrix.arch == 'amd64'
with:
message: |
> [!TIP]
> Run make install to check the status
### Docker Images:
- ```
+ Click to expand docker images
+ ```bash
${{ env.images }}
```
+
+
### Docker Processes:
- ```
+ Click to expand docker ps
+ ```bash
${{ env.containers }}
```
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- continue-on-error: true
+
+ GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
execute-scripts:
- name: Execute OpenIM Script On ${{ matrix.os }}
+ name: Execute OpenIM Script On ${{ matrix.os }}-${{ matrix.arch }}
runs-on: ${{ matrix.os }}
permissions:
contents: write
@@ -174,8 +187,9 @@ jobs:
name: openim
strategy:
matrix:
- go_version: ["1.20"]
+ go_version: ["1.21"]
os: ["ubuntu-latest", "macos-latest"]
+ arch: [arm64, armv7, amd64]
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -193,7 +207,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# - name: Install latest Bash (macOS only)
- # if: runner.os == 'macOS'
+ # if: runner.os == 'macOS' && matrix.arch == 'arm64'
# run: |
# /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# brew update
@@ -213,7 +227,7 @@ jobs:
sudo sleep 20
# - name: Set up Docker for macOS
- # if: runner.os == 'macOS'
+ # if: runner.os == 'macOS' && matrix.arch == 'arm64'
# run: |
# brew install --cask docker
# open /Applications/Docker.app
@@ -244,13 +258,13 @@ jobs:
sudo make check
- name: Restart Services and Print Logs for Ubuntu
- if: runner.os == 'Linux'
+ if: runner.os == 'Linux' && matrix.arch == 'amd64'
run: |
sudo make restart
sudo make check
- name: Build, Start, Check Services and Print Logs for macOS
- if: runner.os == 'macOS'
+ if: runner.os == 'macOS' && matrix.arch == 'arm64'
run: |
make build
diff --git a/CHANGELOG/CHANGELOG-3.4.md b/CHANGELOG/CHANGELOG-3.4.md
new file mode 100644
index 000000000..db4dd59c5
--- /dev/null
+++ b/CHANGELOG/CHANGELOG-3.4.md
@@ -0,0 +1,32 @@
+# Version logging for OpenIM
+
+
+
+
+
+
+## [Unreleased]
+
+
+
+## [v3.4.2] - 2023-12-14
+
+
+## [v3.4.0] - 2023-11-10
+
+
+## [v3.4.0-rc.1] - 2023-11-09
+
+
+## v3.4.0-rc.0 - 2023-11-09
+### Reverts
+- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
+
+### Pull Requests
+- Merge branch 'tuoyun'
+
+
+[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.4.2...HEAD
+[v3.4.2]: https://github.com/openimsdk/open-im-server/compare/v3.4.0...v3.4.2
+[v3.4.0]: https://github.com/openimsdk/open-im-server/compare/v3.4.0-rc.1...v3.4.0
+[v3.4.0-rc.1]: https://github.com/openimsdk/open-im-server/compare/v3.4.0-rc.0...v3.4.0-rc.1
diff --git a/CHANGELOG/CHANGELOG-3.5.0.md b/CHANGELOG/CHANGELOG-3.5.0.md
new file mode 100644
index 000000000..02c28308d
--- /dev/null
+++ b/CHANGELOG/CHANGELOG-3.5.0.md
@@ -0,0 +1,15 @@
+# Version logging for OpenIM
+
+
+
+
+
+
+## [Unreleased]
+
+
+
+## [v3.5.0+3.97baaac] - 2024-01-12
+
+[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.5.0+3.97baaac...HEAD
+[v3.5.0+3.97baaac]: https://github.com/openimsdk/open-im-server/compare/v3.5.0+5.950e970...v3.5.0+3.97baaac
diff --git a/CHANGELOG/CHANGELOG-3.5.md b/CHANGELOG/CHANGELOG-3.5.md
new file mode 100644
index 000000000..ed9ba77c6
--- /dev/null
+++ b/CHANGELOG/CHANGELOG-3.5.md
@@ -0,0 +1,76 @@
+# Version logging for OpenIM
+
+
+
+
+
+
+## [Unreleased]
+
+
+
+## [v3.5.1-alpha.1] - 2024-01-09
+
+
+## [v3.5.0] - 2024-01-02
+
+
+## [v3.5.1] - 2024-01-02
+
+
+## [v3.5.1-bate.1] - 2024-01-02
+
+
+## [v3.5.1-rc.0] - 2023-12-30
+
+
+## [v3.5.0-rc.8] - 2023-12-28
+
+
+## [v3.5.0-rc.7] - 2023-12-18
+
+
+## [v3.5.0-rc.6] - 2023-12-15
+
+
+## [v3.5.0-rc.5] - 2023-12-15
+
+
+## [v3.5.0-rc.4] - 2023-12-14
+
+
+## [v3.5.0-rc.3] - 2023-12-14
+
+
+## [v3.5.0-rc.2] - 2023-12-14
+
+
+## [v3.5.0-rc.1] - 2023-12-14
+
+
+## [v3.5.0-rc.0] - 2023-12-14
+
+
+## v3.5.0-beta.1 - 2023-11-29
+### Reverts
+- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
+
+### Pull Requests
+- Merge branch 'tuoyun'
+
+
+[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-alpha.1...HEAD
+[v3.5.1-alpha.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.0...v3.5.1-alpha.1
+[v3.5.0]: https://github.com/openimsdk/open-im-server/compare/v3.5.1...v3.5.0
+[v3.5.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-bate.1...v3.5.1
+[v3.5.1-bate.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-rc.0...v3.5.1-bate.1
+[v3.5.1-rc.0]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.8...v3.5.1-rc.0
+[v3.5.0-rc.8]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.7...v3.5.0-rc.8
+[v3.5.0-rc.7]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.6...v3.5.0-rc.7
+[v3.5.0-rc.6]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.5...v3.5.0-rc.6
+[v3.5.0-rc.5]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.4...v3.5.0-rc.5
+[v3.5.0-rc.4]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.3...v3.5.0-rc.4
+[v3.5.0-rc.3]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.2...v3.5.0-rc.3
+[v3.5.0-rc.2]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.1...v3.5.0-rc.2
+[v3.5.0-rc.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.0...v3.5.0-rc.1
+[v3.5.0-rc.0]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-beta.1...v3.5.0-rc.0
diff --git a/README.md b/README.md
index 025672a0b..551ff27f8 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@ It is built using Golang and supports cross-platform deployment, ensuring a cons
+ **[Docker Deployment Guide](https://docs.openim.io/guides/gettingStarted/dockerCompose)**
+ **[Kubernetes Deployment Guide](https://docs.openim.io/guides/gettingStarted/k8s-deployment)**
-## :hammer_and_wrench: To start developing OpenIM
+## :hammer_and_wrench: To Start Developing OpenIM
[](https://vscode.dev/github/openimsdk/open-im-server)
@@ -114,6 +114,8 @@ Before you start, please make sure your changes are in demand. The best for that
- [OpenIM Script Utilities](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/util-scripts.md)
- [OpenIM Versioning](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/version.md)
- [Manage backend and monitor deployment](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/prometheus-grafana.md)
+- [Mac Developer Deployment Guide for OpenIM](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/mac-developer-deployment-guide.md)
+
## :busts_in_silhouette: Community
@@ -130,7 +132,7 @@ Our conference is in the [OpenIM Slack](https://join.slack.com/t/openimsdk/share
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
+## :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.
diff --git a/assets/README.md b/assets/README.md
index d3e735dc0..152e5850c 100644
--- a/assets/README.md
+++ b/assets/README.md
@@ -25,7 +25,7 @@ assets/
## Copyright Notice:
-The OpenIM logo, including its variations and animated versions, displayed in this repository [OpenIM](https://github.com/OpenIMSDK/openim) under the `/assets/logo` and `/assets/logo-gif` directories, are protected by copyright laws.
+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` and `/assets/logo-gif` directories, are protected by copyright laws.
The logo design is credited to @Xx(席欣).
diff --git a/cmd/openim-api/main.go b/cmd/openim-api/main.go
index cb9b09802..f0b62e31f 100644
--- a/cmd/openim-api/main.go
+++ b/cmd/openim-api/main.go
@@ -35,7 +35,7 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
- ginProm "github.com/openimsdk/open-im-server/v3/pkg/common/ginprometheus"
+ ginprom "github.com/openimsdk/open-im-server/v3/pkg/common/ginprometheus"
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
)
@@ -88,7 +88,7 @@ func run(port int, proPort int) error {
log.ZInfo(context.Background(), "api register public config to discov success")
router := api.NewGinRouter(client, rdb)
if config.Config.Prometheus.Enable {
- p := ginProm.NewPrometheus("app", prommetrics.GetGinCusMetrics("Api"))
+ p := ginprom.NewPrometheus("app", prommetrics.GetGinCusMetrics("Api"))
p.SetListenAddress(fmt.Sprintf(":%d", proPort))
p.Use(router)
}
diff --git a/docker-compose.yml b/docker-compose.yml
index defc910c4..de4b30d48 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -124,10 +124,52 @@ services:
server:
ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7}
+### TODO: Uncomment, or deploy using openim docker: https://github.com/openimsdk/openim-docker
# Uncomment and configure the following services as needed
+
+ # openim-chat:
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-chat:${CHAT_IMAGE_VERSION:-latest}
+ # container_name: openim-chat
+ # healthcheck:
+ # test: ["CMD", "/openim/openim-chat/scripts/check_all.sh"]
+ # interval: 60s
+ # timeout: 30s
+ # retries: 5
+ # env_file:
+ # - .env
+ # environment:
+ # - ZOOKEEPER_ADDRESS=${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}
+ # - ZOOKEEPER_PORT=${ZOOKEEPER_PORT:-12181}
+ # - OPENIM_SERVER_ADDRESS=http://${OPENIM_SERVER_ADDRESS:-172.28.0.1}
+ # - API_OPENIM_PORT=${API_OPENIM_PORT:-10002}
+ # - MYSQL_ADDRESS=${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}
+ # - MYSQL_PORT=${MYSQL_PORT:-13306}
+ # - REDIS_ADDRESS=${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}
+ # - REDIS_PORT=${REDIS_PORT:-16379}
+ # ports:
+ # - "${OPENIM_CHAT_API_PORT:-10008}:10008"
+ # - "${OPENIM_ADMIN_API_PORT:-10009}:10009"
+ # volumes:
+ # - "${DATA_DIR:-./}/components/openim-chat/logs:/openim/openim-chat/logs"
+ # - "${DATA_DIR:-./}/components/openim-chat/config:/openim/openim-chat/config"
+ # restart: always
+ # # user: root:root
+ # depends_on:
+ # openim-server:
+ # condition: service_healthy
+ # logging:
+ # driver: json-file
+ # options:
+ # max-size: "1g"
+ # max-file: "2"
+ # networks:
+ # server:
+ # ipv4_address: ${OPENIM_CHAT_NETWORK_ADDRESS:-172.28.0.9}
+
# openim-admin:
- # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0
- # container_name: openim-admin
+ # # https://github.com/openimsdk/open-im-server/issues/1662
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin:${ADMIN_FRONT_VERSION:-toc-base-open-docker.35}
+ # container_name: openim-admin
# restart: always
# ports:
# - "${OPENIM_ADMIN_FRONT_PORT:-11002}:80"
@@ -141,8 +183,8 @@ services:
# hostname: prometheus
# restart: always
# volumes:
- # - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
- # - ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml
+ # - "${DATA_DIR:-./}/config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml"
+ # - "${DATA_DIR:-./}/config/prometheus.yml:/etc/prometheus/prometheus.yml"
# ports:
# - "${PROMETHEUS_PORT:-19090}:9090"
# networks:
@@ -155,8 +197,8 @@ services:
# hostname: alertmanager
# restart: always
# volumes:
- # - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
- # - ./config/email.tmpl:/etc/alertmanager/email.tmpl
+ # - ${DATA_DIR:-./}/config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
+ # - ${DATA_DIR:-./}/config/email.tmpl:/etc/alertmanager/email.tmpl
# ports:
# - "${ALERT_MANAGER_PORT:-19093}:9093"
# networks:
@@ -172,7 +214,7 @@ services:
# ports:
# - "${GRAFANA_PORT:-13000}:3000"
# volumes:
- # - ${DATA_DIR:-./}/components/grafana:/var/lib/grafana
+ # - "${DATA_DIR:-./}/components/grafana:/var/lib/grafana"
# networks:
# server:
# ipv4_address: ${GRAFANA_NETWORK_ADDRESS:-172.28.0.11}
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index 7425c8022..7d672eda5 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -108,7 +108,7 @@ export CHAT_IMAGE_VERSION="main"
export SERVER_IMAGE_VERSION="main"
```
-These variables are stored within the [`environment.sh`](https://github.com/OpenIMSDK/openim-docker/blob/main/scripts/install/environment.sh) configuration:
+These variables are stored within the [`environment.sh`](https://github.com/OpenIMSDK/open-im-server/blob/main/scripts/install/environment.sh) configuration:
```bash
readonly CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION:-'main'}
@@ -448,7 +448,7 @@ This section involves configuring the log settings, including storage location,
| Parameter | Example Value | Description |
| ------------------------- | ------------------------ | --------------------------------- |
-| LOG_STORAGE_LOCATION | ""${OPENIM_ROOT}"/logs/" | Location for storing logs |
+| LOG_STORAGE_LOCATION | "${OPENIM_ROOT}/logs/" | Location for storing logs |
| LOG_ROTATION_TIME | "24" | Log rotation time (in hours) |
| LOG_REMAIN_ROTATION_COUNT | "2" | Number of log rotations to retain |
| LOG_REMAIN_LOG_LEVEL | "6" | Log level to retain |
diff --git a/docs/contrib/gitcherry-pick.md b/docs/contrib/gitcherry-pick.md
index 010685d65..2e901385f 100644
--- a/docs/contrib/gitcherry-pick.md
+++ b/docs/contrib/gitcherry-pick.md
@@ -75,7 +75,7 @@ It is critical that our full community is actively engaged on enhancements in th
- Be aware the cherry pick script assumes you have a git remote called `upstream` that points at the openim-server github org.
- Please see our [recommended Git workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contributors/github-workflow.md#workflow).
+ Please see our [recommended Git workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/github-workflow.md#workflow).
- You will need to run the cherry pick script separately for each patch release you want to cherry pick to. Cherry picks should be applied to all [active](https://github.com/openimsdk/open-im-server/releases) release branches where the fix is applicable.
diff --git a/docs/contrib/github-workflow.md b/docs/contrib/github-workflow.md
index 0afbae144..50f2e0bb2 100644
--- a/docs/contrib/github-workflow.md
+++ b/docs/contrib/github-workflow.md
@@ -8,7 +8,6 @@ description: |
commit hygiene.
---
-
## 1. Fork in the cloud
@@ -28,10 +27,10 @@ neither `$GOPATH/src/github.com/${your github profile name}/`
nor any other pattern will work.
```sh
-export working_dir="$(go env GOPATH)/src/k8s.io"
+export working_dir="$(go env GOPATH)/src/github.com/openimsdk"
```
-If you already do Go development on github, the `k8s.io` directory
+If you already do Go development on github, the `github.com/openimsdk` directory
will be a sibling to your existing `github.com` directory.
Set `user` to match your github profile name:
diff --git a/docs/contrib/init-config.md b/docs/contrib/init-config.md
index 9ef4759a4..5e3139dea 100644
--- a/docs/contrib/init-config.md
+++ b/docs/contrib/init-config.md
@@ -23,8 +23,8 @@ In the `scripts/init_config.sh` file, we defined some template files. These temp
```
# Defines an associative array where the keys are the template files and the values are the corresponding output files.
declare -A TEMPLATES=(
- [""${OPENIM_ROOT}"/scripts/template/config-tmpl/env.template"]="${OPENIM_OUTPUT_SUBPATH}/bin/.env"
- [""${OPENIM_ROOT}"/scripts/template/config-tmpl/config.yaml"]="${OPENIM_OUTPUT_SUBPATH}/bin/config.yaml"
+ ["${OPENIM_ROOT}/scripts/template/config-tmpl/env.template"]="${OPENIM_OUTPUT_SUBPATH}/bin/.env"
+ ["${OPENIM_ROOT}/scripts/template/config-tmpl/config.yaml"]="${OPENIM_OUTPUT_SUBPATH}/bin/config.yaml"
)
```
diff --git a/docs/contrib/mac-developer-deployment-guide.md b/docs/contrib/mac-developer-deployment-guide.md
new file mode 100644
index 000000000..40ef4b8be
--- /dev/null
+++ b/docs/contrib/mac-developer-deployment-guide.md
@@ -0,0 +1,149 @@
+# Mac Developer Deployment Guide for OpenIM
+
+## Introduction
+
+This guide aims to assist Mac-based developers in contributing effectively to OpenIM. It covers the setup of a development environment tailored for Mac, including the use of GitHub for development workflow and `devcontainer` for a consistent development experience.
+
+Before contributing to OpenIM through issues and pull requests, make sure you are familiar with GitHub and the [pull request workflow](https://docs.github.com/en/get-started/quickstart/github-flow).
+
+## Prerequisites
+
+### System Requirements
+
+- macOS (latest stable version recommended)
+- Internet connection
+- Administrator access
+
+### Knowledge Requirements
+
+- Basic understanding of Git and GitHub
+- Familiarity with Docker and containerization
+- Experience with Go programming language
+
+## Setting up the Development Environment
+
+### Installing Homebrew
+
+Homebrew is an essential package manager for macOS. Install it using:
+
+```sh
+/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+```
+
+### Installing and Configuring Git
+
+1. Install Git:
+
+ ```sh
+ brew install git
+ ```
+
+2. Configure Git with your user details:
+
+ ```sh
+ git config --global user.name "Your Name"
+ git config --global user.email "your.email@example.com"
+ ```
+
+### Forking and Cloning the Repository
+
+1. Fork the OpenIM repository on GitHub to your account.
+2. Clone your fork to your local machine:
+
+ ```sh
+ git clone https://github.com//open-im-server.git
+ # The Docker bridging network mode for Mac is slightly different and needs to be set:
+ export DOCKER_BRIDGE_SUBNET=127.0.0.0/16
+ # Set OpenIM IP
+ export OPENIM_IP=
+ # Init Config
+ make init
+
+ # Start Components
+ docker compose up -d
+
+ # Start OpenIM Server
+ make start
+ ```
+
+### Setting Up the Devcontainer
+
+`Devcontainers` provide a Docker-based isolated development environment.
+
+Read [README.md](https://github.com/openimsdk/open-im-server/tree/main/.devcontainer) in the `.devcontainer` directory of the project to learn more about the devcontainer.
+
+To set it up:
+
+1. Install Docker Desktop for Mac from [Docker Hub](https://docs.docker.com/desktop/install/mac-install/).
+2. Install Visual Studio Code and the Remote - Containers extension.
+3. Open the cloned OpenIM repository in VS Code.
+4. VS Code will prompt to reopen the project in a container. Accept this to set up the environment automatically.
+
+### Installing Go and Dependencies
+
+Use Homebrew to install Go:
+
+```sh
+brew install go
+```
+
+Ensure the version of Go is compatible with the version required by OpenIM (refer to the main documentation for version requirements).
+
+### Additional Tools
+
+Install other required tools like Docker, Vagrant, and necessary GNU utils as described in the main documentation.
+
+## GitHub Development Workflow
+
+### Creating a New Branch
+
+For new features or fixes, create a new branch:
+
+```sh
+git checkout -b feat/your-feature-name
+```
+
+### Making Changes and Committing
+
+1. Make your changes in the code.
+2. Stage your changes:
+
+ ```sh
+ git add .
+ ```
+
+3. Commit with a meaningful message:
+
+ ```sh
+ git commit -m "Add a brief description of your changes"
+ ```
+
+### Pushing Changes and Creating Pull Requests
+
+1. Push your branch to GitHub:
+
+ ```sh
+ git push origin feat/your-feature-name
+ ```
+
+2. Go to your fork on GitHub and create a pull request to the main OpenIM repository.
+
+### Keeping Your Fork Updated
+
+Regularly sync your fork with the main repository:
+
+```sh
+git fetch upstream
+git checkout main
+git rebase upstream/main
+```
+
+More read: [https://github.com/openimsdk/open-im-server/blob/main/CONTRIBUTING.md](https://github.com/openimsdk/open-im-server/blob/main/CONTRIBUTING.md)
+
+## Testing and Quality Assurance
+
+Run tests as described in the OpenIM documentation to ensure your changes do not break existing functionality.
+
+## Conclusion
+
+This guide provides a comprehensive overview for Mac developers to set up and contribute to OpenIM. By following these steps, you can ensure a smooth and efficient development experience. Happy coding!
\ No newline at end of file
diff --git a/docs/contrib/offline-deployment.md b/docs/contrib/offline-deployment.md
index 39fc3598e..a96f82d4a 100644
--- a/docs/contrib/offline-deployment.md
+++ b/docs/contrib/offline-deployment.md
@@ -6,25 +6,57 @@
Below are the base images and their versions you'll need:
-- wurstmeister/kafka
-- redis:7.0.0
-- mongo:6.0.2
-- mysql:5.7
-- wurstmeister/zookeeper
-- minio/minio
+- [ ] bitnami/kafka:3.5.1
+- [ ] redis:7.0.0
+- [ ] mongo:6.0.2
+- [ ] bitnami/zookeeper:3.8
+- [ ] minio/minio:latest
+
+> [!IMPORTANT]
+> It is important to note that OpenIM removed mysql components from versions v3.5.0 (release-v3.5) and above, so mysql can be deployed without this requirement or above
+
+**If you need to install more IM components or monitoring products:**
+
+OpenIM:
+
+> [!TIP]
+> If you need to install more IM components or monitoring products [images.md](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md)
+
+- [ ] ghcr.io/openimsdk/openim-web:latest
+- [ ] ghcr.io/openimsdk/openim-admin:latest
+- [ ] ghcr.io/openimsdk/openim-chat:latest
+- [ ] ghcr.io/openimsdk/openim-server:latest
+
+
+Monitoring:
+
+- [ ] prom/prometheus:v2.48.1
+- [ ] prom/alertmanager:v0.23.0
+- [ ] grafana/grafana:10.2.2
+- [ ] bitnami/node-exporter:1.7.0
+
Use the following commands to pull these base images:
-```
-docker pull wurstmeister/kafka
+```bash
+docker pull bitnami/kafka:3.5.1
docker pull redis:7.0.0
docker pull mongo:6.0.2
docker pull mysql:5.7
-docker pull wurstmeister/zookeeper
-docker pull minio/minio
+docker pull bitnami/zookeeper:3.8
+docker pull minio/minio:latest
```
-## 2. OpenIM & Chat Images
+If you need to install more IM components or monitoring products:
+
+```bash
+docker pull prom/prometheus:v2.48.1
+docker pull prom/alertmanager:v0.23.0
+docker pull grafana/grafana:10.2.2
+docker pull bitnami/node-exporter:1.7.0
+```
+
+## 2. OpenIM Images
**For detailed understanding of version management and storage of OpenIM and Chat**: [version.md](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md)
@@ -42,9 +74,26 @@ docker pull ghcr.io/openimsdk/openim-server:
- Execute the following command to pull the image:
```bash
-docker pull ghcr.io/openimsdk/openim-server:
+docker pull ghcr.io/openimsdk/openim-chat:
+```
+
+### Web Image
+
+- Execute the following command to pull the image:
+
+```bash
+docker pull ghcr.io/openimsdk/openim-web:
```
+### Admin Image
+
+- Execute the following command to pull the image:
+
+```bash
+docker pull ghcr.io/openimsdk/openim-admin:
+```
+
+
## 3. Image Storage Selection
**Repositories**:
@@ -71,46 +120,61 @@ You can select from the following versions:
1. **Pull images**: Execute the above `docker pull` commands to pull all required images locally.
2. **Save images**:
-```
+```bash
docker save -o .tar
```
-1. **Fetch code**: Clone the repository:
+If you want to save all the images, use the following command:
+```bash
+docker save -o .tar $(docker images -q)
```
-git clone https://github.com/OpenIMSDK/openim-docker.git
+
+3. **Fetch code**: Clone the repository:
+
+```bash
+git clone https://github.com/openimsdk/openim-docker.git
```
-Or download the code from [Releases](https://github.com/OpenIMSDK/openim-docker/releases/).
+Or download the code from [Releases](https://github.com/openimsdk/openim-docker/releases/).
-1. **Transfer files**: Use `scp` to transfer all images and code to the intranet server.
+> Because of the difference between win and linux newlines, please do not clone the repository with win and then synchronize scp to linux.
-```
+4. **Transfer files**: Use `scp` to transfer all images and code to the intranet server.
+
+```bash
scp .tar user@remote-ip:/path/on/remote/server
```
Or choose other transfer methods such as a hard drive.
-1. **Import images**: On the intranet server:
+5. **Import images**: On the intranet server:
-```
+```bash
docker load -i .tar
```
-1. **Deploy**: Navigate to the `openim-docker` repository directory and follow the README guide for deployment.
-2. **Deploy using Docker-compose**:
+Import directly with shortcut commands:
+```bash
+for i in `ls ./`;do docker load -i $i;done
```
-docker-compose up -d
-# Verify
-docker-compose ps
+6. **Deploy**: Navigate to the `openim-docker` repository directory and follow the [README guide](https://github.com/openimsdk/openim-docker) for deployment.
+
+7. **Deploy using docker compose**:
+
+```bash
+export OPENIM_IP="your ip" # Set Ip
+make init # Init config
+docker compose up -d # Deployment
+docker compose ps # Verify
```
> **Note**: If you're using a version of Docker prior to 20, make sure you've installed `docker-compose`.
## 6. Reference Links
-- [OpenIMSDK Issue #432](https://github.com/openimsdk/open-im-server/issues/432)
+- [openimsdk Issue #432](https://github.com/openimsdk/open-im-server/issues/432)
- [Notion Link](https://nsddd.notion.site/435ee747c0bc44048da9300a2d745ad3?pvs=25)
-- [OpenIMSDK Issue #474](https://github.com/openimsdk/open-im-server/issues/474)
\ No newline at end of file
+- [openimsdk Issue #474](https://github.com/openimsdk/open-im-server/issues/474)
\ No newline at end of file
diff --git a/docs/contrib/prometheus-grafana.md b/docs/contrib/prometheus-grafana.md
index a59847f71..5b57c5942 100644
--- a/docs/contrib/prometheus-grafana.md
+++ b/docs/contrib/prometheus-grafana.md
@@ -111,32 +111,35 @@ Importing Grafana Dashboards is a straightforward process and is applicable to O
To monitor OpenIM in Grafana, you need to focus on three categories of key metrics, each with its specific deployment and configuration steps:
-1. **OpenIM Metrics (`prometheus-dashboard.yaml`)**:
- + **Configuration File Path**: Located at `config/prometheus-dashboard.yaml`.
- + **Enabling Monitoring**: Set the environment variable `export PROMETHEUS_ENABLE=true` to enable Prometheus monitoring.
- + **More Information**: Refer to the [OpenIM Configuration Guide](https://docs.openim.io/configurations/prometheus-integration).
-2. **Node Exporter**:
- + **Container Deployment**: Deploy the `quay.io/prometheus/node-exporter` container for node monitoring.
- + **Get Dashboard**: Access the [Node Exporter Full Feature Dashboard](https://grafana.com/grafana/dashboards/1860-node-exporter-full/) and import it using YAML file download or ID import.
- + **Deployment Guide**: Refer to the [Node Exporter Deployment Documentation](https://prometheus.io/docs/guides/node-exporter/).
-3. **Middleware Metrics**: Each middleware requires specific steps and configurations to enable monitoring. Here is a list of common middleware and links to their respective setup guides:
- + MySQL:
- + **Configuration**: Ensure MySQL has performance monitoring enabled.
- + **Link**: Refer to the [MySQL Monitoring Configuration Guide](https://grafana.com/docs/grafana/latest/datasources/mysql/).
- + Redis:
- + **Configuration**: Configure Redis to allow monitoring data export.
- + **Link**: Refer to the [Redis Monitoring Guide](https://grafana.com/docs/grafana/latest/datasources/redis/).
- + MongoDB:
- + **Configuration**: Set up monitoring metrics for MongoDB.
- + **Link**: Refer to the [MongoDB Monitoring Guide](https://grafana.com/grafana/plugins/grafana-mongodb-datasource/).
- + Kafka:
- + **Configuration**: Integrate Kafka with Prometheus monitoring.
- + **Link**: Refer to the [Kafka Monitoring Guide](https://grafana.com/grafana/plugins/grafana-kafka-datasource/).
- + Zookeeper:
- + **Configuration**: Ensure Zookeeper can be monitored by Prometheus.
- + **Link**: Refer to the [Zookeeper Monitoring Configuration](https://grafana.com/docs/grafana/latest/datasources/zookeeper/).
-
-
+**OpenIM Metrics (`prometheus-dashboard.yaml`)**:
+
+- **Configuration File Path**: Find this at `config/prometheus-dashboard.yaml`.
+- **Enabling Monitoring**: Activate Prometheus monitoring by setting the environment variable: `export PROMETHEUS_ENABLE=true`.
+- **More Information**: For detailed instructions, see the [OpenIM Configuration Guide](https://docs.openim.io/configurations/prometheus-integration).
+
+**Node Exporter**:
+
+- **Container Deployment**: Use the container `quay.io/prometheus/node-exporter` for effective node monitoring.
+- **Access Dashboard**: Visit the [Node Exporter Full Feature Dashboard](https://grafana.com/grafana/dashboards/1860-node-exporter-full/) for dashboard integration either through YAML file download or ID.
+- **Deployment Guide**: For deployment steps, consult the [Node Exporter Deployment Documentation](https://prometheus.io/docs/guides/node-exporter/).
+
+**Middleware Metrics**: Different middlewares require unique steps and configurations for monitoring:
+
+- MySQL:
+ - **Configuration**: Make sure MySQL is set up for performance monitoring.
+ - **Guide**: See the [MySQL Monitoring Configuration Guide](https://grafana.com/docs/grafana/latest/datasources/mysql/).
+- Redis:
+ - **Configuration**: Adjust Redis settings to enable monitoring data export.
+ - **Guide**: Consult the [Redis Monitoring Guide](https://grafana.com/docs/grafana/latest/datasources/redis/).
+- MongoDB:
+ - **Configuration**: Configure MongoDB for monitoring metrics.
+ - **Guide**: Visit the [MongoDB Monitoring Guide](https://grafana.com/grafana/plugins/grafana-mongodb-datasource/).
+- Kafka:
+ - **Configuration**: Set up Kafka for Prometheus monitoring integration.
+ - **Guide**: Refer to the [Kafka Monitoring Guide](https://grafana.com/grafana/plugins/grafana-kafka-datasource/).
+- Zookeeper:
+ - **Configuration**: Ensure Prometheus can monitor Zookeeper.
+ - **Guide**: Check out the [Zookeeper Monitoring Configuration](https://grafana.com/docs/grafana/latest/datasources/zookeeper/).
**Importing Steps**:
diff --git a/docs/contrib/release.md b/docs/contrib/release.md
new file mode 100644
index 000000000..65756fe9a
--- /dev/null
+++ b/docs/contrib/release.md
@@ -0,0 +1,251 @@
+# OpenIM Release Automation Design Document
+
+This document outlines the automation process for releasing OpenIM. You can use the `make release` command for automated publishing. We will discuss how to use the `make release` command and Github Actions CICD separately, while also providing insight into the design principles involved.
+
+## Github Actions Automation
+
+In our CICD pipeline, we have implemented logic for automating the release process using the goreleaser tool. To achieve this, follow these steps on your local machine or server:
+
+```bash
+git clone https://github.com/openimsdk/open-im-server
+cd open-im-server
+git tag -a v3.6.0 -s -m "release: xxx"
+# For pre-release versions: git tag -a v3.6.0-rc.0 -s -m "pre-release: xxx"
+git push origin v3.6.0
+```
+
+The remaining tasks are handled by automated processes:
+
++ Automatically complete the release publication on Github
++ Automatically build the `v3.6.0` version image and push it to aliyun, dockerhub, and github
+
+Through these automated steps, we achieve rapid and efficient OpenIM version releases, simplifying the release process and enhancing productivity.
+
+
+Certainly, here is the continuation of the document in English:
+
+## Local Make Release Design
+
+There are two primary scenarios for local usage:
+
++ Advanced compilation and release, manually executed locally
++ Quick compilation verification and version release, manually executed locally
+
+**These two scenarios can also be combined, for example, by tagging locally and then releasing:**
+
+```bash
+git add .
+git commit -a -s -m "release(v3.6.0): ......"
+git tag v3.6.0
+git release
+git push origin main
+```
+
+In a local environment, you can use the `make release` command to complete the release process. The main implementation logic can be found in the `/data/workspaces/open-im-server/scripts/lib/release.sh` file. First, let's explore its usage through the help information.
+
+### Help Information
+
+To view the help information, execute the following command:
+
+```bash
+$ ./scripts/release.sh --help
+Usage: release.sh [options]
+Options:
+ -h, --help Display this help message
+ -se, --setup-env Execute environment setup
+ -vp, --verify-prereqs Execute prerequisite verification
+ -bc, --build-command Execute build command
+ -bi, --build-image Execute build image (default is not executed)
+ -pt, --package-tarballs Execute tarball packaging
+ -ut, --upload-tarballs Execute tarball upload
+ -gr, --github-release Execute GitHub release
+ -gc, --generate-changelog Execute changelog generation
+```
+
+### Default Behavior
+
+If no options are provided, all operations are executed by default:
+
+```bash
+# If no options are provided, enable all operations by default
+if [ "$#" -eq 0 ]; then
+ perform_setup_env=true
+ perform_verify_prereqs=true
+ perform_build_command=true
+ perform_package_tarballs=true
+ perform_upload_tarballs=true
+ perform_github_release=true
+ perform_generate_changelog=true
+ # TODO: Defaultly not enable build_image
+ # perform_build_image=true
+fi
+```
+
+### Environment Variable Setup
+
+Before starting, you need to set environment variables:
+
+```bash
+export TENCENT_SECRET_KEY=OZZ****************************
+export TENCENT_SECRET_ID=AKI****************************
+```
+
+### Modifying COS Account and Password
+
+If you need to change the COS account, password, and bucket information, please modify the following section in the `/data/workspaces/open-im-server/scripts/lib/release.sh` file:
+
+```bash
+readonly BUCKET="openim-1306374445"
+readonly REGION="ap-guangzhou"
+readonly COS_RELEASE_DIR="openim-release"
+```
+
+### GitHub Release Configuration
+
+If you intend to use the GitHub Release feature, you also need to set the environment variable:
+
+```bash
+export GITHUB_TOKEN="your_github_token"
+```
+
+### Modifying GitHub Release Basic Information
+
+If you need to modify the basic information of GitHub Release, please edit the following section in the `/data/workspaces/open-im-server/scripts/lib/release.sh` file:
+
+```bash
+# OpenIM GitHub account information
+readonly OPENIM_GITHUB_ORG=openimsdk
+readonly OPENIM_GITHUB_REPO=open-im-server
+```
+
+This setup allows you to configure and execute the local release process according to your specific needs.
+
+
+### GitHub Release Versioning Rules
+
+Firstly, it's important to note that GitHub Releases should primarily be for pre-release versions. However, goreleaser might provide a `prerelease: auto` option, which automatically marks versions with pre-release indicators like `-rc1`, `-beta`, etc., as pre-releases.
+
+So, if your most recent tag does not have pre-release indicators such as `-rc1` or `-beta`, even if you use `make release` for pre-release versions, goreleaser might still consider them as formal releases.
+
+To avoid this issue, I have added the `--draft` flag to github-release. This way, all releases are created as drafts.
+
+## CICD Release Documentation Design
+
+The release records still require manual composition for GitHub Release. This is different from github-release.
+
+This approach ensures that all releases are initially created as drafts, allowing you to manually review and edit the release documentation on GitHub. This manual step provides more control and allows you to curate release notes and other information before making them public.
+
+
+## Makefile Section
+
+This document aims to elaborate and explain key sections of the OpenIM Release automation design, including the Makefile section and functions within the code. Below, we will provide a detailed explanation of the logic and functions of each section.
+
+In the project's root directory, the Makefile imports a subdirectory:
+
+```makefile
+include scripts/make-rules/release.mk
+```
+
+And defines the `release` target as follows:
+
+```makefile
+## release: release the project ✨
+.PHONY: release release: release.verify release.ensure-tag
+ @scripts/release.sh
+```
+
+### Importing Subdirectory
+
+At the beginning of the Makefile, the `include scripts/make-rules/release.mk` statement imports the `release.mk` file from the subdirectory. This file contains rules and configurations related to releases to be used in subsequent operations.
+
+### The `release` Target
+
+The Makefile defines a target named `release`, which is used to execute the project's release operation. This target is marked as a phony target (`.PHONY`), meaning it doesn't represent an actual file or directory but serves as an identifier for executing a series of actions.
+
+In the `release` target, two dependency targets are executed first: `release.verify` and `release.ensure-tag`. Afterward, the `scripts/release.sh` script is called to perform the actual release operation.
+
+## Logic of `release.verify` and `release.ensure-tag`
+
+```makefile
+## release.verify: Check if a tool is installed and install it
+.PHONY: release.verify
+release.verify: tools.verify.git-chglog tools.verify.github-release tools.verify.coscmd tools.verify.coscli
+
+## release.ensure-tag: ensure tag
+.PHONY: release.ensure-tag
+release.ensure-tag: tools.verify.gsemver
+ @scripts/ensure-tag.sh
+```
+
+### `release.verify` Target
+
+The `release.verify` target is used to check and install tools. It depends on four sub-targets: `tools.verify.git-chglog`, `tools.verify.github-release`, `tools.verify.coscmd`, and `tools.verify.coscli`. These sub-targets aim to check if specific tools are installed and attempt to install them if they are not.
+
+The purpose of this target is to ensure that the necessary tools required for the release process are available so that subsequent operations can be executed smoothly.
+
+### `release.ensure-tag` Target
+
+The `release.ensure-tag` target is used to ensure that the project has a version tag. It depends on the sub-target `tools.verify.gsemver`, indicating that it should check if the `gsemver` tool is installed before executing.
+
+When the `release.ensure-tag` target is executed, it calls the `scripts/ensure-tag.sh` script to ensure that the project has a version tag. Version tags are typically used to identify specific versions of the project for management and release in version control systems.
+
+## Logic of `release.sh` Script
+
+```bash
+openim::golang::setup_env
+openim::build::verify_prereqs
+openim::release::verify_prereqs
+#openim::build::build_image
+openim::build::build_command
+openim::release::package_tarballs
+openim::release::upload_tarballs
+git push origin ${VERSION}
+#openim::release::github_release
+#openim::release::generate_changelog
+```
+
+The `release.sh` script is responsible for executing the actual release operations. Below is the logic of this script:
+
+1. `openim::golang::setup_env`: This function sets up some configurations for the Golang development environment.
+
+2. `openim::build::verify_prereqs`: This function is used to verify whether the prerequisites for building are met. This includes checking dependencies, environment variables, and more.
+
+3. `openim::release::verify_prereqs`: Similar to the previous function, this one is used to verify whether the prerequisites for the release are met. It focuses on conditions relevant to the release.
+
+4. `openim::build::build_command`: This function is responsible for building the project's command, which typically involves compiling the project or performing other build operations.
+
+5. `openim::release::package_tarballs`: This function is used to package tarball files required for the release. These tarballs are usually used for distribution packages during the release.
+
+6. `openim::release::upload_tarballs`: This function is used to upload the packaged tarball files, typically to a distribution platform or repository.
+
+7. `git push origin ${VERSION}`: This line of command pushes the version tag to the remote Git repository's `origin` branch, marking this release in the version control system.
+
+In the comments, you can see that there are some operations that are commented out, such as `openim::build::build_image`, `openim::release::github_release`, and `openim::release::generate_changelog`. These operations are related to building images, releasing to GitHub, and generating changelogs, and they can be enabled in the release process as needed.
+
+Let's take a closer look at the function responsible for packaging the tarball files:
+
+```bash
+function openim::release::package_tarballs() {
+ # Clean out any old releases
+ rm -rf "${RELEASE_STAGE}" "${RELEASE_TARS}" "${RELEASE_IMAGES}"
+ mkdir -p "${RELEASE_TARS}"
+ openim::release::package_src_tarball &
+ openim::release::package_client_tarballs &
+ openim::release::package_openim_manifests_tarball &
+ openim::release::package_server_tarballs &
+ openim::util::wait-for-jobs || { openim::log::error "previous tarball phase failed"; return 1; }
+
+ openim::release::package_final_tarball & # _final depends on some of the previous phases
+ openim::util::wait-for-jobs || { openim::log::error "previous tarball phase failed"; return 1; }
+}
+```
+
+The `openim::release::package_tarballs()` function is responsible for packaging the tarball files required for the release. Here is the specific logic of this function:
+
+1. `rm -rf "${RELEASE_STAGE}" "${RELEASE_TARS}" "${RELEASE_IMAGES}"`: First, the function removes any old release directories and files to ensure a clean starting state.
+
+2. `mkdir -p "${RELEASE_TARS}"`: Next, it creates a directory `${RELEASE_TARS}` to store the packaged tarball files. If the directory doesn't exist, it will be created.
+
+3. `openim::release::package_final_tarball &`: This is an asynchronous operation that depends on some of the previous phases. It is likely used to package the final tarball file, which includes the contents of all previous asynchronous operations.
+
+4. `openim::util::wait-for-jobs`: It waits for all asynchronous operations to complete. If any of the previous asynchronous operations fail, an error will be returned.
diff --git a/go.work b/go.work
index 63100b9f6..97d2816d6 100644
--- a/go.work
+++ b/go.work
@@ -4,14 +4,15 @@ use (
.
./test/typecheck
./tools/changelog
- //./tools/imctl
+ ./tools/component
+ ./tools/data-conversion
+ ./tools/formitychecker
+ ./tools/imctl
./tools/infra
./tools/ncpu
./tools/openim-web
+ ./tools/up35
+ ./tools/url2im
./tools/versionchecker
./tools/yamlfmt
- ./tools/component
- ./tools/url2im
- ./tools/data-conversion
- ./tools/up35
)
diff --git a/pkg/common/prommetrics/gin_api.go b/pkg/common/prommetrics/gin_api.go
index c5ef612a2..9f2e4c99d 100644
--- a/pkg/common/prommetrics/gin_api.go
+++ b/pkg/common/prommetrics/gin_api.go
@@ -14,14 +14,14 @@
package prommetrics
-import ginProm "github.com/openimsdk/open-im-server/v3/pkg/common/ginprometheus"
+import ginprom "github.com/openimsdk/open-im-server/v3/pkg/common/ginprometheus"
/*
labels := prometheus.Labels{"label_one": "any", "label_two": "value"}
ApiCustomCnt.MetricCollector.(*prometheus.CounterVec).With(labels).Inc().
*/
var (
- ApiCustomCnt = &ginProm.Metric{
+ ApiCustomCnt = &ginprom.Metric{
Name: "custom_total",
Description: "Custom counter events.",
Type: "counter_vec",
diff --git a/pkg/common/prommetrics/prommetrics.go b/pkg/common/prommetrics/prommetrics.go
index 41719dd2d..b7c5e07f4 100644
--- a/pkg/common/prommetrics/prommetrics.go
+++ b/pkg/common/prommetrics/prommetrics.go
@@ -15,7 +15,7 @@
package prommetrics
import (
- grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
+ gp "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
@@ -23,10 +23,10 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/ginprometheus"
)
-func NewGrpcPromObj(cusMetrics []prometheus.Collector) (*prometheus.Registry, *grpc_prometheus.ServerMetrics, error) {
+func NewGrpcPromObj(cusMetrics []prometheus.Collector) (*prometheus.Registry, *gp.ServerMetrics, error) {
////////////////////////////////////////////////////////
reg := prometheus.NewRegistry()
- grpcMetrics := grpc_prometheus.NewServerMetrics()
+ grpcMetrics := gp.NewServerMetrics()
grpcMetrics.EnableHandlingTimeHistogram()
cusMetrics = append(cusMetrics, grpcMetrics, collectors.NewGoCollector())
reg.MustRegister(cusMetrics...)
diff --git a/scripts/.spelling_failures b/scripts/.spelling_failures
index 5c29b5992..149d314ba 100644
--- a/scripts/.spelling_failures
+++ b/scripts/.spelling_failures
@@ -3,4 +3,6 @@ go.mod
go.sum
third_party/
translations/
-log
\ No newline at end of file
+logs
+.git
+.golangci.yml
\ No newline at end of file
diff --git a/scripts/build-all-service.sh b/scripts/build-all-service.sh
index c79018a87..4b5c0613a 100755
--- a/scripts/build-all-service.sh
+++ b/scripts/build-all-service.sh
@@ -30,7 +30,7 @@ OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${OPENIM_ROOT}/scripts/lib/init.sh"
# CPU core number
-pushd ""${OPENIM_ROOT}"/tools/ncpu" >/dev/null
+pushd "${OPENIM_ROOT}/tools/ncpu" >/dev/null
cpu_count=$(go run .)
popd >/dev/null
diff --git a/scripts/check-all.sh b/scripts/check-all.sh
index 7b53e4a89..72a34a5e5 100755
--- a/scripts/check-all.sh
+++ b/scripts/check-all.sh
@@ -30,6 +30,7 @@ OPENIM_VERBOSE=4
openim::log::info "\n# Begin to check all openim service"
+openim::log::status "Check all dependent service ports"
# Elegant printing function
# Elegant printing function
print_services_and_ports() {
@@ -60,7 +61,7 @@ print_services_and_ports "${OPENIM_DEPENDENCY_TARGETS[@]}" "${OPENIM_DEPENDENCY_
# OpenIM check
echo "++ The port being checked: ${OPENIM_SERVER_PORT_LISTARIES[@]}"
openim::log::info "\n## Check all dependent service ports"
-echo "+++ The port being checked: ${OPENIM_DEPENDENCY_PORT_LISTARIES[@]}"
+echo "++ The port being checked: ${OPENIM_DEPENDENCY_PORT_LISTARIES[@]}"
set +e
diff --git a/scripts/common.sh b/scripts/common.sh
index da0d36118..882641ae9 100755
--- a/scripts/common.sh
+++ b/scripts/common.sh
@@ -42,7 +42,7 @@ OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd -P)
# Constants
readonly OPENIM_BUILD_IMAGE_REPO=openim-build
-#readonly OPENIM_BUILD_IMAGE_CROSS_TAG="$(cat ""${OPENIM_ROOT}"/build/build-image/cross/VERSION")"
+#readonly OPENIM_BUILD_IMAGE_CROSS_TAG="$(cat "${OPENIM_ROOT}/build/build-image/cross/VERSION")"
readonly OPENIM_DOCKER_REGISTRY="${OPENIM_DOCKER_REGISTRY:-k8s.gcr.io}"
readonly OPENIM_BASE_IMAGE_REGISTRY="${OPENIM_BASE_IMAGE_REGISTRY:-us.gcr.io/k8s-artifacts-prod/build-image}"
@@ -53,7 +53,7 @@ readonly OPENIM_BASE_IMAGE_REGISTRY="${OPENIM_BASE_IMAGE_REGISTRY:-us.gcr.io/k8s
#
# Increment/change this number if you change the build image (anything under
# build/build-image) or change the set of volumes in the data container.
-#readonly OPENIM_BUILD_IMAGE_VERSION_BASE="$(cat ""${OPENIM_ROOT}"/build/build-image/VERSION")"
+#readonly OPENIM_BUILD_IMAGE_VERSION_BASE="$(cat "${OPENIM_ROOT}/build/build-image/VERSION")"
#readonly OPENIM_BUILD_IMAGE_VERSION="${OPENIM_BUILD_IMAGE_VERSION_BASE}-${OPENIM_BUILD_IMAGE_CROSS_TAG}"
# Here we map the output directories across both the local and remote _output
@@ -66,9 +66,10 @@ readonly OPENIM_BASE_IMAGE_REGISTRY="${OPENIM_BASE_IMAGE_REGISTRY:-us.gcr.io/k8s
# is really remote, this is the stuff that has to be copied
# back.
# OUT_DIR can come in from the Makefile, so honor it.
-readonly LOCAL_OUTPUT_ROOT=""${OPENIM_ROOT}"/${OUT_DIR:-_output}"
-readonly LOCAL_OUTPUT_SUBPATH="${LOCAL_OUTPUT_ROOT}/platforms"
-readonly LOCAL_OUTPUT_BINPATH="${LOCAL_OUTPUT_SUBPATH}"
+readonly LOCAL_OUTPUT_ROOT="${OPENIM_ROOT}/${OUT_DIR:-_output}"
+readonly LOCAL_OUTPUT_SUBPATH="${LOCAL_OUTPUT_ROOT}/bin"
+readonly LOCAL_OUTPUT_BINPATH="${LOCAL_OUTPUT_SUBPATH}/platforms"
+readonly LOCAL_OUTPUT_BINTOOLSPATH="${LOCAL_OUTPUT_SUBPATH}/tools"
readonly LOCAL_OUTPUT_GOPATH="${LOCAL_OUTPUT_SUBPATH}/go"
readonly LOCAL_OUTPUT_IMAGE_STAGING="${LOCAL_OUTPUT_ROOT}/images"
@@ -161,7 +162,7 @@ function openim::build::verify_prereqs() {
#LOCAL_OUTPUT_BUILD_CONTEXT="${LOCAL_OUTPUT_IMAGE_STAGING}/${OPENIM_BUILD_IMAGE}"
openim::version::get_version_vars
- #openim::version::save_version_vars ""${OPENIM_ROOT}"/.dockerized-openim-version-defs"
+ #openim::version::save_version_vars "${OPENIM_ROOT}/.dockerized-openim-version-defs"
}
# ---------------------------------------------------------------------------
@@ -416,8 +417,8 @@ function openim::build::build_image() {
cp /etc/localtime "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
- cp ""${OPENIM_ROOT}"/build/build-image/Dockerfile" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
- cp ""${OPENIM_ROOT}"/build/build-image/rsyncd.sh" "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
+ cp "${OPENIM_ROOT}/build/build-image/Dockerfile" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
+ cp "${OPENIM_ROOT}/build/build-image/rsyncd.sh" "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
dd if=/dev/urandom bs=512 count=1 2>/dev/null | LC_ALL=C tr -dc 'A-Za-z0-9' | dd bs=32 count=1 2>/dev/null > "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
chmod go= "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
diff --git a/scripts/ensure-tag.sh b/scripts/ensure-tag.sh
index c6fea7ca0..2847342f4 100755
--- a/scripts/ensure-tag.sh
+++ b/scripts/ensure-tag.sh
@@ -14,9 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
+
version="${VERSION}"
if [ "${version}" == "" ];then
- version=v`gsemver bump`
+ version=v`${OPENIM_ROOT}/_output/tools/gsemver bump`
fi
if [ -z "`git tag -l ${version}`" ];then
diff --git a/scripts/genconfig.sh b/scripts/genconfig.sh
index 8ded38b22..659e8f4be 100755
--- a/scripts/genconfig.sh
+++ b/scripts/genconfig.sh
@@ -53,4 +53,4 @@ fi
eval "cat << EOF
$(cat ${template_file})
-EOF"
+EOF"
\ No newline at end of file
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index 9d9fc4028..f84cb924a 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -22,7 +22,7 @@
OPENIM_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)"
# 生成文件存放目录
-LOCAL_OUTPUT_ROOT=""${OPENIM_ROOT}"/${OUT_DIR:-_output}"
+LOCAL_OUTPUT_ROOT="${OPENIM_ROOT}/${OUT_DIR:-_output}"
source "${OPENIM_ROOT}/scripts/lib/init.sh"
#TODO: Access to the OPENIM_IP networks outside, or you want to use the OPENIM_IP network
@@ -62,7 +62,7 @@ readonly LINUX_PASSWORD=${LINUX_PASSWORD:-"${PASSWORD}"}
def "INSTALL_DIR" "${LOCAL_OUTPUT_ROOT}/installs"
mkdir -p ${INSTALL_DIR}
-def "ENV_FILE" ""${OPENIM_ROOT}"/scripts/install/environment.sh"
+def "ENV_FILE" "${OPENIM_ROOT}/scripts/install/environment.sh"
###################### Docker compose ###################
# OPENIM AND CHAT
@@ -128,7 +128,7 @@ def "OPENIM_CONFIG_DIR" "/etc/openim/config"
def "OPENIM_LOG_DIR" "/var/log/openim"
def "CA_FILE" "${OPENIM_CONFIG_DIR}/cert/ca.pem"
-def "OPNEIM_CONFIG" ""${OPENIM_ROOT}"/config"
+def "OPNEIM_CONFIG" "${OPENIM_ROOT}/config"
def "OPENIM_SERVER_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # OpenIM服务地址
# OpenIM Websocket端口
@@ -326,7 +326,7 @@ def "OPENIM_CONVERSATION_NAME" "Conversation" # OpenIM对话服务名称
def "OPENIM_THIRD_NAME" "Third" # OpenIM第三方服务名称
###################### Log Configuration Variables ######################
-def "LOG_STORAGE_LOCATION" ""${OPENIM_ROOT}"/logs/" # 日志存储位置
+def "LOG_STORAGE_LOCATION" "${OPENIM_ROOT}/logs/" # 日志存储位置
def "LOG_ROTATION_TIME" "24" # 日志轮替时间
def "LOG_REMAIN_ROTATION_COUNT" "2" # 保留的日志轮替数量
def "LOG_REMAIN_LOG_LEVEL" "6" # 保留的日志级别
@@ -414,7 +414,7 @@ readonly MSG_TRANSFER_PROM_ADDRESS_PORT=${MSG_TRANSFER_PROM_ADDRESS_PORT:-"${DOC
###################### OpenIM openim-api ######################
def "OPENIM_API_HOST" "127.0.0.1"
def "OPENIM_API_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-api" # OpenIM openim-api 二进制文件路径
-def "OPENIM_API_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-api 配置文件路径
+def "OPENIM_API_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-api 配置文件路径
def "OPENIM_API_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-api" # OpenIM openim-api 日志存储路径
def "OPENIM_API_LOG_LEVEL" "info" # OpenIM openim-api 日志级别
def "OPENIM_API_LOG_MAX_SIZE" "100" # OpenIM openim-api 日志最大大小(MB)
@@ -426,7 +426,7 @@ def "OPENIM_API_LOG_WITH_STACK" "${LOG_WITH_STACK}" # OpenIM openim-ap
###################### OpenIM openim-cmdutils ######################
def "OPENIM_CMDUTILS_HOST" "127.0.0.1"
def "OPENIM_CMDUTILS_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-cmdutils" # OpenIM openim-cmdutils 二进制文件路径
-def "OPENIM_CMDUTILS_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-cmdutils 配置文件路径
+def "OPENIM_CMDUTILS_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-cmdutils 配置文件路径
def "OPENIM_CMDUTILS_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-cmdutils" # OpenIM openim-cmdutils 日志存储路径
def "OPENIM_CMDUTILS_LOG_LEVEL" "info" # OpenIM openim-cmdutils 日志级别
def "OPENIM_CMDUTILS_LOG_MAX_SIZE" "100" # OpenIM openim-cmdutils 日志最大大小(MB)
@@ -438,7 +438,7 @@ def "OPENIM_CMDUTILS_LOG_WITH_STACK" "${LOG_WITH_STACK}" # OpenIM
###################### OpenIM openim-crontask ######################
def "OPENIM_CRONTASK_HOST" "127.0.0.1"
def "OPENIM_CRONTASK_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-crontask" # OpenIM openim-crontask 二进制文件路径
-def "OPENIM_CRONTASK_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-crontask 配置文件路径
+def "OPENIM_CRONTASK_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-crontask 配置文件路径
def "OPENIM_CRONTASK_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-crontask" # OpenIM openim-crontask 日志存储路径
def "OPENIM_CRONTASK_LOG_LEVEL" "info" # OpenIM openim-crontask 日志级别
def "OPENIM_CRONTASK_LOG_MAX_SIZE" "100" # OpenIM openim-crontask 日志最大大小(MB)
@@ -450,7 +450,7 @@ def "OPENIM_CRONTASK_LOG_WITH_STACK" "${LOG_WITH_STACK}" # OpenIM
###################### OpenIM openim-msggateway ######################
def "OPENIM_MSGGATEWAY_HOST" "127.0.0.1"
def "OPENIM_MSGGATEWAY_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-msggateway"
-def "OPENIM_MSGGATEWAY_CONFIG" ""${OPENIM_ROOT}"/config/"
+def "OPENIM_MSGGATEWAY_CONFIG" "${OPENIM_ROOT}/config/"
def "OPENIM_MSGGATEWAY_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-msggateway"
def "OPENIM_MSGGATEWAY_LOG_LEVEL" "info"
def "OPENIM_MSGGATEWAY_LOG_MAX_SIZE" "100"
@@ -465,7 +465,7 @@ readonly OPENIM_MSGGATEWAY_NUM=${OPENIM_MSGGATEWAY_NUM:-'4'}
###################### OpenIM openim-msgtransfer ######################
def "OPENIM_MSGTRANSFER_HOST" "127.0.0.1"
def "OPENIM_MSGTRANSFER_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-msgtransfer" # OpenIM openim-msgtransfer 二进制文件路径
-def "OPENIM_MSGTRANSFER_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-msgtransfer 配置文件路径
+def "OPENIM_MSGTRANSFER_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-msgtransfer 配置文件路径
def "OPENIM_MSGTRANSFER_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-msgtransfer" # OpenIM openim-msgtransfer 日志存储路径
def "OPENIM_MSGTRANSFER_LOG_LEVEL" "info" # OpenIM openim-msgtransfer 日志级别
def "OPENIM_MSGTRANSFER_LOG_MAX_SIZE" "100" # OpenIM openim-msgtransfer 日志最大大小(MB)
@@ -477,7 +477,7 @@ def "OPENIM_MSGTRANSFER_LOG_WITH_STACK" "${LOG_WITH_STACK}" #
###################### OpenIM openim-push ######################
def "OPENIM_PUSH_HOST" "127.0.0.1"
def "OPENIM_PUSH_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-push" # OpenIM openim-push 二进制文件路径
-def "OPENIM_PUSH_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-push 配置文件路径
+def "OPENIM_PUSH_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-push 配置文件路径
def "OPENIM_PUSH_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-push" # OpenIM openim-push 日志存储路径
def "OPENIM_PUSH_LOG_LEVEL" "info" # OpenIM openim-push 日志级别
def "OPENIM_PUSH_LOG_MAX_SIZE" "100" # OpenIM openim-push 日志最大大小(MB)
@@ -489,7 +489,7 @@ def "OPENIM_PUSH_LOG_WITH_STACK" "${LOG_WITH_STACK}" # OpenIM openim-
###################### OpenIM openim-rpc-auth ######################
def "OPENIM_RPC_AUTH_HOST" "127.0.0.1"
def "OPENIM_RPC_AUTH_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-rpc-auth" # OpenIM openim-rpc-auth 二进制文件路径
-def "OPENIM_RPC_AUTH_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-rpc-auth 配置文件路径
+def "OPENIM_RPC_AUTH_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-rpc-auth 配置文件路径
def "OPENIM_RPC_AUTH_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-rpc-auth" # OpenIM openim-rpc-auth 日志存储路径
def "OPENIM_RPC_AUTH_LOG_LEVEL" "info" # OpenIM openim-rpc-auth 日志级别
def "OPENIM_RPC_AUTH_LOG_MAX_SIZE" "100" # OpenIM openim-rpc-auth 日志最大大小(MB)
@@ -501,7 +501,7 @@ def "OPENIM_RPC_AUTH_LOG_WITH_STACK" "${LOG_WITH_STACK}" # OpenIM
###################### OpenIM openim-rpc-conversation ######################
def "OPENIM_RPC_CONVERSATION_HOST" "127.0.0.1"
def "OPENIM_RPC_CONVERSATION_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-rpc-conversation" # OpenIM openim-rpc-conversation 二进制文件路径
-def "OPENIM_RPC_CONVERSATION_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-rpc-conversation 配置文件路径
+def "OPENIM_RPC_CONVERSATION_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-rpc-conversation 配置文件路径
def "OPENIM_RPC_CONVERSATION_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-rpc-conversation" # OpenIM openim-rpc-conversation 日志存储路径
def "OPENIM_RPC_CONVERSATION_LOG_LEVEL" "info" # OpenIM openim-rpc-conversation 日志级别
def "OPENIM_RPC_CONVERSATION_LOG_MAX_SIZE" "100" # OpenIM openim-rpc-conversation 日志最大大小(MB)
@@ -513,7 +513,7 @@ def "OPENIM_RPC_CONVERSATION_LOG_WITH_STACK" "${LOG_WITH_STACK}"
###################### OpenIM openim-rpc-friend ######################
def "OPENIM_RPC_FRIEND_HOST" "127.0.0.1"
def "OPENIM_RPC_FRIEND_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-rpc-friend" # OpenIM openim-rpc-friend 二进制文件路径
-def "OPENIM_RPC_FRIEND_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-rpc-friend 配置文件路径
+def "OPENIM_RPC_FRIEND_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-rpc-friend 配置文件路径
def "OPENIM_RPC_FRIEND_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-rpc-friend" # OpenIM openim-rpc-friend 日志存储路径
def "OPENIM_RPC_FRIEND_LOG_LEVEL" "info" # OpenIM openim-rpc-friend 日志级别
def "OPENIM_RPC_FRIEND_LOG_MAX_SIZE" "100" # OpenIM openim-rpc-friend 日志最大大小(MB)
@@ -525,7 +525,7 @@ def "OPENIM_RPC_FRIEND_LOG_WITH_STACK" "${LOG_WITH_STACK}" # Op
###################### OpenIM openim-rpc-group ######################
def "OPENIM_RPC_GROUP_HOST" "127.0.0.1"
def "OPENIM_RPC_GROUP_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-rpc-group" # OpenIM openim-rpc-group 二进制文件路径
-def "OPENIM_RPC_GROUP_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-rpc-group 配置文件路径
+def "OPENIM_RPC_GROUP_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-rpc-group 配置文件路径
def "OPENIM_RPC_GROUP_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-rpc-group" # OpenIM openim-rpc-group 日志存储路径
def "OPENIM_RPC_GROUP_LOG_LEVEL" "info" # OpenIM openim-rpc-group 日志级别
def "OPENIM_RPC_GROUP_LOG_MAX_SIZE" "100" # OpenIM openim-rpc-group 日志最大大小(MB)
@@ -537,7 +537,7 @@ def "OPENIM_RPC_GROUP_LOG_WITH_STACK" "${LOG_WITH_STACK}" # Open
###################### OpenIM openim-rpc-msg ######################
def "OPENIM_RPC_MSG_HOST" "127.0.0.1"
def "OPENIM_RPC_MSG_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-rpc-msg" # OpenIM openim-rpc-msg 二进制文件路径
-def "OPENIM_RPC_MSG_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-rpc-msg 配置文件路径
+def "OPENIM_RPC_MSG_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-rpc-msg 配置文件路径
def "OPENIM_RPC_MSG_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-rpc-msg" # OpenIM openim-rpc-msg 日志存储路径
def "OPENIM_RPC_MSG_LOG_LEVEL" "info" # OpenIM openim-rpc-msg 日志级别
def "OPENIM_RPC_MSG_LOG_MAX_SIZE" "100" # OpenIM openim-rpc-msg 日志最大大小(MB)
@@ -549,7 +549,7 @@ def "OPENIM_RPC_MSG_LOG_WITH_STACK" "${LOG_WITH_STACK}" # OpenIM o
###################### OpenIM openim-rpc-third ######################
def "OPENIM_RPC_THIRD_HOST" "127.0.0.1"
def "OPENIM_RPC_THIRD_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-rpc-third" # OpenIM openim-rpc-third 二进制文件路径
-def "OPENIM_RPC_THIRD_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-rpc-third 配置文件路径
+def "OPENIM_RPC_THIRD_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-rpc-third 配置文件路径
def "OPENIM_RPC_THIRD_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-rpc-third" # OpenIM openim-rpc-third 日志存储路径
def "OPENIM_RPC_THIRD_LOG_LEVEL" "info" # OpenIM openim-rpc-third 日志级别
def "OPENIM_RPC_THIRD_LOG_MAX_SIZE" "100" # OpenIM openim-rpc-third 日志最大大小(MB)
@@ -561,7 +561,7 @@ def "OPENIM_RPC_THIRD_LOG_WITH_STACK" "${LOG_WITH_STACK}" # Open
###################### OpenIM openim-rpc-user ######################
def "OPENIM_RPC_USER_HOST" "127.0.0.1"
def "OPENIM_RPC_USER_BINARY" "${OPENIM_OUTPUT_HOSTBIN}/openim-rpc-user" # OpenIM openim-rpc-user 二进制文件路径
-def "OPENIM_RPC_USER_CONFIG" ""${OPENIM_ROOT}"/config/" # OpenIM openim-rpc-user 配置文件路径
+def "OPENIM_RPC_USER_CONFIG" "${OPENIM_ROOT}/config/" # OpenIM openim-rpc-user 配置文件路径
def "OPENIM_RPC_USER_LOG_DIR" "${LOG_STORAGE_LOCATION}/openim-rpc-user" # OpenIM openim-rpc-user 日志存储路径
def "OPENIM_RPC_USER_LOG_LEVEL" "info" # OpenIM openim-rpc-user 日志级别
def "OPENIM_RPC_USER_LOG_MAX_SIZE" "100" # OpenIM openim-rpc-user 日志最大大小(MB)
diff --git a/scripts/install/openim-man.sh b/scripts/install/openim-man.sh
index 6dda4bfe1..f23c54a20 100755
--- a/scripts/install/openim-man.sh
+++ b/scripts/install/openim-man.sh
@@ -26,9 +26,9 @@
# ./openim-man.sh openim::man::status - Check installation status
#
# Dependencies:
-# - Assumes there's a common.sh in ""${OPENIM_ROOT}"/scripts/install/"
+# - Assumes there's a common.sh in "${OPENIM_ROOT}/scripts/install/"
# containing shared functions and variables.
-# - Relies on the script ""${OPENIM_ROOT}"/scripts/update-generated-docs.sh"
+# - Relies on the script "${OPENIM_ROOT}/scripts/update-generated-docs.sh"
# to generate the man pages.
#
# Notes:
@@ -58,7 +58,7 @@ function openim::man::install() {
pushd "${OPENIM_ROOT}" > /dev/null
# Generate man pages for each component
- ""${OPENIM_ROOT}"/scripts/update-generated-docs.sh"
+ "${OPENIM_ROOT}/scripts/update-generated-docs.sh"
openim::common::sudo "cp docs/man/man1/* /usr/share/man/man1/"
# Verify installation status
diff --git a/scripts/install/openim-tools.sh b/scripts/install/openim-tools.sh
index f97b9d836..385df64f5 100755
--- a/scripts/install/openim-tools.sh
+++ b/scripts/install/openim-tools.sh
@@ -103,8 +103,13 @@ function openim::tools::start_service() {
printf "Specifying prometheus port: %s\n" "${prometheus_port}"
cmd="${cmd} --prometheus_port ${prometheus_port}"
fi
- openim::log::info "Starting ${binary_name}..."
- ${cmd}
+ openim::log::status "Starting ${binary_name}..."
+ # Later, after discarding Docker, the Docker keyword is unreliable, and Kubepods is used
+ if grep -qE 'docker|kubepods' /proc/1/cgroup || [ -f /.dockerenv ]; then
+ ${cmd} >> "${LOG_FILE}" 2>&1
+ else
+ ${cmd} | tee -a "${LOG_FILE}"
+ fi
}
function openim::tools::start() {
diff --git a/scripts/lib/chat.sh b/scripts/lib/chat.sh
index eef94edbd..549422b11 100755
--- a/scripts/lib/chat.sh
+++ b/scripts/lib/chat.sh
@@ -27,7 +27,7 @@ openim::chat::validate() {
# validate if in path
command -v chat >/dev/null || {
openim::log::usage "chat must be in your PATH"
- openim::log::info "You can use 'hack/install-chat.sh' to install a copy in third_party/."
+ openim::log::info "You can use 'scripts/install-chat.sh' to install a copy in third_party/."
exit 1
}
@@ -61,7 +61,7 @@ openim::chat::validate() {
version=$(chat --version | grep Version | head -n 1 | cut -d " " -f 3)
if [[ $(openim::chat::version "${CHAT_VERSION}") -gt $(openim::chat::version "${version}") ]]; then
openim::log::usage "chat version ${CHAT_VERSION} or greater required."
- openim::log::info "You can use 'hack/install-chat.sh' to install a copy in third_party/."
+ openim::log::info "You can use 'scripts/install-chat.sh' to install a copy in third_party/."
exit 1
fi
fi
@@ -148,7 +148,7 @@ openim::chat::install() {
os=$(openim::util::host_os)
arch=$(openim::util::host_arch)
- cd ""${OPENIM_ROOT}"/third_party" || return 1
+ cd "${OPENIM_ROOT}/third_party" || return 1
if [[ $(readlink chat) == chat-v${CHAT_VERSION}-${os}-* ]]; then
openim::log::info "chat v${CHAT_VERSION} already installed. To use:"
openim::log::info "export PATH=\"$(pwd)/chat:\${PATH}\""
diff --git a/scripts/lib/golang.sh b/scripts/lib/golang.sh
index a65d2c9f5..af04771d5 100755
--- a/scripts/lib/golang.sh
+++ b/scripts/lib/golang.sh
@@ -89,7 +89,7 @@ readonly OPENIM_SERVER_TARGETS
readonly OPENIM_SERVER_BINARIES=("${OPENIM_SERVER_TARGETS[@]##*/}")
# TODO: Label
-START_SCRIPTS_PATH=""${OPENIM_ROOT}"/scripts/install/"
+START_SCRIPTS_PATH="${OPENIM_ROOT}/scripts/install/"
openim::golang::start_script_list() {
local targets=(
openim-api.sh
@@ -261,7 +261,18 @@ openim::golang::setup_platforms
# The set of client targets that we are building for all platforms
# If you update this list, please also update build/BUILD.
readonly OPENIM_CLIENT_TARGETS=(
- imctl
+ changelog
+ component
+ conversion-msg
+ conversion-mysql
+ formitychecker
+ imctl
+ infra
+ ncpu
+ openim-web
+ up35
+ versionchecker
+ yamlfmt
)
readonly OPENIM_CLIENT_BINARIES=("${OPENIM_CLIENT_TARGETS[@]##*/}")
diff --git a/scripts/lib/init.sh b/scripts/lib/init.sh
index 631e751ba..be8e9f8aa 100755
--- a/scripts/lib/init.sh
+++ b/scripts/lib/init.sh
@@ -25,7 +25,7 @@ unset CDPATH
# Until all GOPATH references are removed from all build scripts as well,
# explicitly disable module mode to avoid picking up user-set GO111MODULE preferences.
-# As individual scripts (like hack/update-vendor.sh) make use of go modules,
+# As individual scripts (like scripts/update-vendor.sh) make use of go modules,
# they can explicitly set GO111MODULE=on
export GO111MODULE=on
@@ -33,7 +33,7 @@ export GO111MODULE=on
OPENIM_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)"
OPENIM_OUTPUT_SUBPATH="${OPENIM_OUTPUT_SUBPATH:-_output}"
-OPENIM_OUTPUT=""${OPENIM_ROOT}"/${OPENIM_OUTPUT_SUBPATH}"
+OPENIM_OUTPUT="${OPENIM_ROOT}/${OPENIM_OUTPUT_SUBPATH}"
OPENIM_OUTPUT_BINPATH="${OPENIM_OUTPUT}/bin/platforms"
OPENIM_OUTPUT_BINTOOLPATH="${OPENIM_OUTPUT}/bin/tools"
@@ -50,8 +50,8 @@ OPENIM_RSYNC_COMPRESS="${KUBE_RSYNC_COMPRESS:-0}"
export no_proxy="127.0.0.1,localhost${no_proxy:+,${no_proxy}}"
# This is a symlink to binaries for "this platform", e.g. build tools.
-export THIS_PLATFORM_BIN=""${OPENIM_ROOT}"/_output/bin/platforms"
-export THIS_PLATFORM_BIN_TOOLS=""${OPENIM_ROOT}"/_output/bin/tools"
+export THIS_PLATFORM_BIN="${OPENIM_ROOT}/_output/bin/platforms"
+export THIS_PLATFORM_BIN_TOOLS="${OPENIM_ROOT}/_output/bin/tools"
. $(dirname ${BASH_SOURCE})/color.sh
. $(dirname ${BASH_SOURCE})/util.sh
@@ -62,7 +62,6 @@ openim::util::ensure-bash-version
. $(dirname ${BASH_SOURCE})/version.sh
. $(dirname ${BASH_SOURCE})/golang.sh
-. $(dirname ${BASH_SOURCE})/release.sh
. $(dirname ${BASH_SOURCE})/chat.sh
OPENIM_OUTPUT_HOSTBIN="${OPENIM_OUTPUT_BINPATH}/$(openim::util::host_platform)"
diff --git a/scripts/lib/release.sh b/scripts/lib/release.sh
index dba74c768..16f2cd97a 100755
--- a/scripts/lib/release.sh
+++ b/scripts/lib/release.sh
@@ -22,7 +22,6 @@
# example: ./coscli cp/sync -r /home/off-line/docker-off-line/ cos://openim-1306374445/openim/image/amd/off-line/off-line/ -e cos.ap-guangzhou.myqcloud.com
# https://cloud.tencent.com/document/product/436/71763
-# Tencent cos configuration
readonly BUCKET="openim-1306374445"
readonly REGION="ap-guangzhou"
readonly COS_RELEASE_DIR="openim-release"
@@ -36,8 +35,8 @@ readonly RELEASE_TARS="${LOCAL_OUTPUT_ROOT}/release-tars"
readonly RELEASE_IMAGES="${LOCAL_OUTPUT_ROOT}/release-images"
# OpenIM github account info
-readonly OPENIM_GITHUB_ORG=OpenIMSDK
-readonly OPENIM_GITHUB_REPO=Open-IM-Server
+readonly OPENIM_GITHUB_ORG=openimsdk
+readonly OPENIM_GITHUB_REPO=open-im-server
readonly CHAT_GITHUB_REPO=chat
readonly ARTIFACT=openim.tar.gz
@@ -46,6 +45,14 @@ readonly CHECKSUM=${ARTIFACT}.sha1sum
OPENIM_BUILD_CONFORMANCE=${OPENIM_BUILD_CONFORMANCE:-y}
OPENIM_BUILD_PULL_LATEST_IMAGES=${OPENIM_BUILD_PULL_LATEST_IMAGES:-y}
+if [ -z "${OPENIM_ROOT}" ]; then
+ OPENIM_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)"
+fi
+
+if [ -z "${TOOLS_DIR}" ]; then
+ TOOLS_DIR="${OPENIM_ROOT}/_output/tools"
+fi
+
# Validate a ci version
#
# Globals:
@@ -113,13 +120,14 @@ function openim::release::package_tarballs() {
openim::util::wait-for-jobs || { openim::log::error "previous tarball phase failed"; return 1; }
}
-function openim::release::updload_tarballs() {
+function openim::release::upload_tarballs() {
openim::log::info "upload ${RELEASE_TARS}/* to cos bucket ${BUCKET}."
for file in $(ls ${RELEASE_TARS}/*)
do
if [ "${COSTOOL}" == "coscli" ];then
- coscli cp "${file}" "cos://${BUCKET}/${COS_RELEASE_DIR}/${OPENIM_GIT_VERSION}/${file##*/}"
- coscli cp "${file}" "cos://${BUCKET}/${COS_RELEASE_DIR}/latest/${file##*/}"
+ echo "++++ ${TOOLS_DIR}/coscli cp ${file} cos://${BUCKET}/${COS_RELEASE_DIR}/${OPENIM_GIT_VERSION}/${file##*/}"
+ ${TOOLS_DIR}/coscli cp "${file}" "cos://${BUCKET}/${COS_RELEASE_DIR}/${OPENIM_GIT_VERSION}/${file##*/}"
+ ${TOOLS_DIR}/coscli cp "${file}" "cos://${BUCKET}/${COS_RELEASE_DIR}/latest/${file##*/}"
else
coscmd upload "${file}" "${COS_RELEASE_DIR}/${OPENIM_GIT_VERSION}/"
coscmd upload "${file}" "${COS_RELEASE_DIR}/latest/"
@@ -139,6 +147,8 @@ function openim::release::package_src_tarball() {
\( -path "${OPENIM_ROOT}"/_\* -o \
-path "${OPENIM_ROOT}"/.git\* -o \
-path "${OPENIM_ROOT}"/.github\* -o \
+ -path "${OPENIM_ROOT}"/components\* -o \
+ -path "${OPENIM_ROOT}"/logs\* -o \
-path "${OPENIM_ROOT}"/.gitignore\* -o \
-path "${OPENIM_ROOT}"/.gsemver.yml\* -o \
-path "${OPENIM_ROOT}"/.config\* -o \
@@ -158,6 +168,7 @@ function openim::release::package_src_tarball() {
function openim::release::package_server_tarballs() {
# Find all of the built client binaries
local long_platforms=("${LOCAL_OUTPUT_BINPATH}"/*/*)
+
if [[ -n ${OPENIM_BUILD_PLATFORMS-} ]]; then
read -ra long_platforms <<< "${OPENIM_BUILD_PLATFORMS}"
fi
@@ -167,68 +178,81 @@ function openim::release::package_server_tarballs() {
local platform_tag
platform=${platform_long##${LOCAL_OUTPUT_BINPATH}/} # Strip LOCAL_OUTPUT_BINPATH
platform_tag=${platform/\//-} # Replace a "/" for a "-"
+
openim::log::status "Starting tarball: server $platform_tag"
(
local release_stage="${RELEASE_STAGE}/server/${platform_tag}/openim"
+ openim::log::info "release_stage: ${release_stage}"
+
rm -rf "${release_stage}"
mkdir -p "${release_stage}/server/bin"
local server_bins=("${OPENIM_SERVER_BINARIES[@]}")
- # This fancy expression will expand to prepend a path
- # (${LOCAL_OUTPUT_BINPATH}/${platform}/) to every item in the
- # server_bins array.
- cp "${server_bins[@]/bin/#/${LOCAL_OUTPUT_BINPATH}/${platform}/}" \
+ openim::log::info " Copy client binaries: ${client_bins[@]/#/${LOCAL_OUTPUT_BINPATH}/${platform}/}"
+ openim::log::info " Copy client binaries to: ${release_stage}/server/bin"
+
+ # Copy server binaries
+ cp "${server_bins[@]/#/${LOCAL_OUTPUT_BINPATH}/${platform}/}" \
"${release_stage}/server/bin/"
- openim::release::clean_cruft
+ openim::release::clean_cruft
- local package_name="${RELEASE_TARS}/openim-server-${platform_tag}.tar.gz"
- openim::release::create_tarball "${package_name}" "${release_stage}/.."
- ) &
- done
-
- openim::log::status "Waiting on tarballs"
- openim::util::wait-for-jobs || { openim::log::error "server tarball creation failed"; exit 1; }
- }
+ local package_name="${RELEASE_TARS}/openim-server-${platform_tag}.tar.gz"
+ openim::release::create_tarball "${package_name}" "${release_stage}/.."
+ ) &
+ done
+ openim::log::status "Waiting on tarballs"
+ openim::util::wait-for-jobs || { openim::log::error "server tarball creation failed"; exit 1; }
+}
+# Package up all of the cross compiled clients. Over time this should grow into
+# a full SDK
# Package up all of the cross compiled clients. Over time this should grow into
# a full SDK
function openim::release::package_client_tarballs() {
# Find all of the built client binaries
- local long_platforms=("${LOCAL_OUTPUT_BINPATH}"/*/*)
+ local long_platforms=("${LOCAL_OUTPUT_BINTOOLSPATH}"/*/*)
if [[ -n ${OPENIM_BUILD_PLATFORMS-} ]]; then
read -ra long_platforms <<< "${OPENIM_BUILD_PLATFORMS}"
fi
+ # echo "++++ LOCAL_OUTPUT_BINTOOLSPATH: ${LOCAL_OUTPUT_BINTOOLSPATH}"
+ # LOCAL_OUTPUT_BINTOOLSPATH: /data/workspaces/open-im-server/_output/bin/tools
+ # echo "++++ long_platforms: ${long_platforms[@]}"
+ # long_platforms: /data/workspaces/open-im-server/_output/bin/tools/darwin/amd64 /data/workspaces/open-im-server/_output/bin/tools/darwin/arm64 /data/workspaces/open-im-server/_output/bin/tools/linux/amd64 /data/workspaces/open-im-server/_output/bin/tools/linux/arm64 /data/workspaces/open-im-server/_output/bin/tools/linux/mips64 /data/workspaces/open-im-server/_output/bin/tools/linux/mips64le /data/workspaces/open-im-server/_output/bin/tools/linux/ppc64le /data/workspaces/open-im-server/_output/bin/tools/linux/s390x /data/workspaces/open-im-server/_output/bin/tools/windows/amd64
for platform_long in "${long_platforms[@]}"; do
local platform
local platform_tag
- platform=${platform_long##${LOCAL_OUTPUT_BINPATH}/} # Strip LOCAL_OUTPUT_BINPATH
+ platform=${platform_long##${LOCAL_OUTPUT_BINTOOLSPATH}/} # Strip LOCAL_OUTPUT_BINTOOLSPATH
platform_tag=${platform/\//-} # Replace a "/" for a "-"
- openim::log::status "Starting tarball: client $platform_tag"
+ openim::log::status "Starting tarball: client $platform_tag" # darwin-amd64
(
local release_stage="${RELEASE_STAGE}/client/${platform_tag}/openim"
+
+ openim::log::info "release_stage: ${release_stage}"
+ # ++++ release_stage: /data/workspaces/open-im-server/_output/release-stage/client/darwin-amd64/openim
rm -rf "${release_stage}"
mkdir -p "${release_stage}/client/bin"
local client_bins=("${OPENIM_CLIENT_BINARIES[@]}")
- # This fancy expression will expand to prepend a path
- # (${LOCAL_OUTPUT_BINPATH}/${platform}/) to every item in the
- # client_bins array.
- cp "${client_bins[@]/bin/#/${LOCAL_OUTPUT_BINPATH}/${platform}/}" \
+ # client_bins: changelog component conversion-msg conversion-mysql formitychecker imctl infra ncpu openim-web up35 versionchecker yamlfmt
+ # Copy client binclient_bins:aries
+ openim::log::info " Copy client binaries: ${client_bins[@]/#/${LOCAL_OUTPUT_BINTOOLSPATH}/${platform}/}"
+ openim::log::info " Copy client binaries to: ${release_stage}/client/bin"
+
+ cp "${client_bins[@]/#/${LOCAL_OUTPUT_BINTOOLSPATH}/${platform}/}" \
"${release_stage}/client/bin/"
- openim::release::clean_cruft
+ openim::release::clean_cruft
- local package_name="${RELEASE_TARS}/openim-client-${platform_tag}.tar.gz"
- openim::release::create_tarball "${package_name}" "${release_stage}/.."
+ local package_name="${RELEASE_TARS}/openim-client-${platform_tag}.tar.gz"
+ openim::release::create_tarball "${package_name}" "${release_stage}/.."
) &
done
-
openim::log::status "Waiting on tarballs"
openim::util::wait-for-jobs || { openim::log::error "client tarball creation failed"; exit 1; }
}
@@ -354,7 +378,7 @@ function openim::release::create_docker_images_for_server() {
rm -rf "${docker_build_path}"
mkdir -p "${docker_build_path}"
ln "${binary_file_path}" "${docker_build_path}/${binary_name}"
- ln ""${OPENIM_ROOT}"/build/nsswitch.conf" "${docker_build_path}/nsswitch.conf"
+ ln "${OPENIM_ROOT}/build/nsswitch.conf" "${docker_build_path}/nsswitch.conf"
chmod 0644 "${docker_build_path}/nsswitch.conf"
cat < "${docker_file_path}"
FROM ${base_image}
@@ -399,7 +423,7 @@ EOF
function openim::release::package_openim_manifests_tarball() {
openim::log::status "Building tarball: manifests"
- local src_dir=""${OPENIM_ROOT}"/deployments"
+ local src_dir="${OPENIM_ROOT}/deployments"
local release_stage="${RELEASE_STAGE}/manifests/openim"
rm -rf "${release_stage}"
@@ -420,7 +444,7 @@ function openim::release::package_openim_manifests_tarball() {
#cp "${src_dir}/openim-rpc-msg.yaml" "${dst_dir}"
#cp "${src_dir}/openim-rpc-third.yaml" "${dst_dir}"
#cp "${src_dir}/openim-rpc-user.yaml" "${dst_dir}"
- #cp ""${OPENIM_ROOT}"/cluster/gce/gci/health-monitor.sh" "${dst_dir}/health-monitor.sh"
+ #cp "${OPENIM_ROOT}/cluster/gce/gci/health-monitor.sh" "${dst_dir}/health-monitor.sh"
openim::release::clean_cruft
@@ -442,6 +466,7 @@ function openim::release::package_final_tarball() {
# This isn't a "full" tarball anymore, but the release lib still expects
# artifacts under "full/openim/"
local release_stage="${RELEASE_STAGE}/full/openim"
+ openim::log::info "release_stage(final): ${release_stage}"
rm -rf "${release_stage}"
mkdir -p "${release_stage}"
@@ -454,7 +479,8 @@ EOF
# We want everything in /scripts.
mkdir -p "${release_stage}/release"
- cp -R ""${OPENIM_ROOT}"/scripts/release" "${release_stage}/"
+ mkdir -p "${OPENIM_ROOT}/scripts/release"
+ cp -R "${OPENIM_ROOT}/scripts/release" "${release_stage}/"
cat < "${release_stage}/release/get-openim-binaries.sh"
#!/usr/bin/env bash
# This file download openim client and server binaries from tencent cos bucket.
@@ -471,11 +497,11 @@ Server binary tarballs are no longer included in the OpenIM final tarball.
Run release/get-openim-binaries.sh to download client and server binaries.
EOF
- # Include hack/lib as a dependency for the cluster/ scripts
+ # Include scripts/lib as a dependency for the cluster/ scripts
#mkdir -p "${release_stage}/hack"
- #cp -R ""${OPENIM_ROOT}"/hack/lib" "${release_stage}/hack/"
+ #cp -R "${OPENIM_ROOT}/scripts/lib" "${release_stage}/scripts/"
- cp -R "${OPENIM_ROOT}"/{docs,configs,scripts,deployments,init,README.md,LICENSE} "${release_stage}/"
+ cp -R "${OPENIM_ROOT}"/{docs,config,scripts,deployments,README.md,LICENSE} "${release_stage}/"
echo "${OPENIM_GIT_VERSION}" > "${release_stage}/version"
@@ -507,7 +533,7 @@ function openim::release::install_github_release(){
# - git-chglog
# - coscmd or coscli
function openim::release::verify_prereqs(){
- if [ -z "$(which github-release 2>/dev/null)" ]; then
+ if [ -z "$(which ${TOOLS_DIR}/github-release 2>/dev/null)" ]; then
openim::log::info "'github-release' tool not installed, try to install it."
if ! openim::release::install_github_release; then
@@ -516,7 +542,7 @@ function openim::release::verify_prereqs(){
fi
fi
- if [ -z "$(which git-chglog 2>/dev/null)" ]; then
+ if [ -z "$(which ${TOOLS_DIR}/git-chglog 2>/dev/null)" ]; then
openim::log::info "'git-chglog' tool not installed, try to install it."
if ! go install github.com/git-chglog/git-chglog/cmd/git-chglog@latest &>/dev/null; then
@@ -525,7 +551,7 @@ function openim::release::verify_prereqs(){
fi
fi
- if [ -z "$(which gsemver 2>/dev/null)" ]; then
+ if [ -z "$(which ${TOOLS_DIR}/gsemver 2>/dev/null)" ]; then
openim::log::info "'gsemver' tool not installed, try to install it."
if ! go install github.com/arnaud-deprez/gsemver@latest &>/dev/null; then
@@ -534,8 +560,7 @@ function openim::release::verify_prereqs(){
fi
fi
-
- if [ -z "$(which ${COSTOOL} 2>/dev/null)" ]; then
+ if [ -z "$(which ${TOOLS_DIR}/${COSTOOL} 2>/dev/null)" ]; then
openim::log::info "${COSTOOL} tool not installed, try to install it."
if ! make -C "${OPENIM_ROOT}" tools.install.${COSTOOL}; then
@@ -545,6 +570,7 @@ function openim::release::verify_prereqs(){
fi
if [ -z "${TENCENT_SECRET_ID}" -o -z "${TENCENT_SECRET_KEY}" ];then
+ openim::log::info "You need set env: TENCENT_SECRET_ID(cos secretid) and TENCENT_SECRET_KEY(cos secretkey)"
openim::log::error "can not find env: TENCENT_SECRET_ID and TENCENT_SECRET_KEY"
return 1
fi
@@ -584,39 +610,57 @@ EOF
# https://github.com/github-release/github-release
function openim::release::github_release() {
# create a github release
+ if [ -z "${GITHUB_TOKEN}" ];then
+ openim::log::error "can not find env: GITHUB_TOKEN"
+ return 1
+ fi
openim::log::info "create a new github release with tag ${OPENIM_GIT_VERSION}"
- github-release release \
+ ${TOOLS_DIR}/github-release release \
--user ${OPENIM_GITHUB_ORG} \
--repo ${OPENIM_GITHUB_REPO} \
--tag ${OPENIM_GIT_VERSION} \
--description "" \
- --pre-release
+ --pre-release \
+ --draft
# update openim tarballs
openim::log::info "upload ${ARTIFACT} to release ${OPENIM_GIT_VERSION}"
- github-release upload \
+ ${TOOLS_DIR}/github-release upload \
--user ${OPENIM_GITHUB_ORG} \
--repo ${OPENIM_GITHUB_REPO} \
--tag ${OPENIM_GIT_VERSION} \
--name ${ARTIFACT} \
+ --label "openim-${OPENIM_GIT_VERSION}" \
--file ${RELEASE_TARS}/${ARTIFACT}
- openim::log::info "upload openim-src.tar.gz to release ${OPENIM_GIT_VERSION}"
- github-release upload \
- --user ${OPENIM_GITHUB_ORG} \
- --repo ${OPENIM_GITHUB_REPO} \
- --tag ${OPENIM_GIT_VERSION} \
- --name "openim-src.tar.gz" \
- --file ${RELEASE_TARS}/openim-src.tar.gz
+ for file in ${RELEASE_TARS}/*.tar.gz; do
+ if [[ -f "$file" ]]; then
+ filename=$(basename "$file")
+ openim::log::info "Update file ${filename} to release vertion ${OPENIM_GIT_VERSION}"
+ ${TOOLS_DIR}/github-release upload \
+ --user ${OPENIM_GITHUB_ORG} \
+ --repo ${OPENIM_GITHUB_REPO} \
+ --tag ${OPENIM_GIT_VERSION} \
+ --name "${filename}" \
+ --file "${file}"
+ fi
+ done
}
function openim::release::generate_changelog() {
openim::log::info "generate CHANGELOG-${OPENIM_GIT_VERSION#v}.md and commit it"
- git-chglog ${OPENIM_GIT_VERSION} > "${OPENIM_ROOT}"/CHANGELOG/CHANGELOG-${OPENIM_GIT_VERSION#v}.md
+ local major_version=$(echo ${OPENIM_GIT_VERSION} | cut -d '+' -f 1)
+
+ ${TOOLS_DIR}/git-chglog --config ${OPENIM_ROOT}/CHANGELOG/.chglog/config.yml ${OPENIM_GIT_VERSION} > ${OPENIM_ROOT}/CHANGELOG/CHANGELOG-${major_version#v}.md
set +o errexit
- git add "${OPENIM_ROOT}"/CHANGELOG/CHANGELOG-${OPENIM_GIT_VERSION#v}.md
- git commit -a -m "docs(changelog): add CHANGELOG-${OPENIM_GIT_VERSION#v}.md"
- git push -f origin main # 最后将 CHANGELOG 也 push 上去
+ git add "${OPENIM_ROOT}"/CHANGELOG/CHANGELOG-${major_version#v}.md
+ git commit -a -m "docs(changelog): add CHANGELOG-${major_version#v}.md"
+ echo ""
+ echo "##########################################################################"
+ echo "git commit -a -m \"docs(changelog): add CHANGELOG-${major_version#v}.md\""
+ openim::log::info "You need git push CHANGELOG-${major_version#v}.md to remote"
+ echo "##########################################################################"
+ echo ""
}
diff --git a/scripts/lib/util.sh b/scripts/lib/util.sh
index 4de240972..1ec722d8f 100755
--- a/scripts/lib/util.sh
+++ b/scripts/lib/util.sh
@@ -301,29 +301,1275 @@ openim::util::check_ports() {
openim::log::info "Checking ports: $*"
# Iterate over each given port.
for port in "$@"; do
- # Use the `ss` command to find process information related to the given port.
- if command -v ss > /dev/null 2>&1; then
- info=$(ss -ltnp | grep ":$port" || true)
+ # Initialize variables
+ # Check the OS and use the appropriate command
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ if command -v ss > /dev/null 2>&1; then
+ info=$(ss -ltnp | grep ":$port" || true)
+ else
+ info=$(netstat -ltnp | grep ":$port" || true)
+ fi
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # For macOS, use lsof
+ info=$(lsof -i:"$port" | grep "\*:$port" || true)
+ fi
+
+ # Check if any process is using the port
+ if [[ -z $info ]]; then
+ not_started+=($port)
+ else
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ # Extract relevant details for Linux: Process Name, PID, and FD.
+ details=$(echo $info | sed -n 's/.*users:(("\([^"]*\)",pid=\([^,]*\),fd=\([^)]*\))).*/\1 \2 \3/p')
+ command=$(echo $details | awk '{print $1}')
+ pid=$(echo $details | awk '{print $2}')
+ fd=$(echo $details | awk '{print $3}')
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # Handle extraction for macOS
+ pid=$(echo $info | awk '{print $2}' | cut -d'/' -f1)
+ command=$(ps -p $pid -o comm= | xargs basename)
+ fd=$(echo $info | awk '{print $4}' | cut -d'/' -f1)
+ fi
+
+ # Get the start time of the process using the PID
+ if [[ -z $pid ]]; then
+ start_time="N/A"
+ else
+ start_time=$(ps -p $pid -o lstart=)
+ fi
+
+ started+=("Port $port - Command: $command, PID: $pid, FD: $fd, Started: $start_time")
+ fi
+ done
+
+ # Print information about ports whose processes are not running.
+ if [[ ${#not_started[@]} -ne 0 ]]; then
+ openim::log::info "\n### Not started ports:"
+ for port in "${not_started[@]}"; do
+ openim::log::error "Port $port is not started."
+ done
+ fi
+
+ # Print information about ports whose processes are running.
+ if [[ ${#started[@]} -ne 0 ]]; then
+ openim::log::info "\n### Started ports:"
+ for info in "${started[@]}"; do
+ openim::log::info "$info"
+ done
+ fi
+
+ # If any of the processes is not running, return a status of 1.
+ if [[ ${#not_started[@]} -ne 0 ]]; then
+ echo "++++ OpenIM Log >> cat ${LOG_FILE}"
+ return 1
+ else
+ openim::log::success "All specified processes are running."
+ return 0
+ fi
+}
+
+# set +o errexit
+# Sample call for testing:
+# openim::util::check_ports 10002 1004 12345 13306
+# set -o errexit
+
+# The `openim::util::check_process_names` function analyzes the state of processes based on given names.
+# It accepts multiple process names as arguments and prints:
+# 1. The state of the process (whether it's running or not).
+# 2. The start time of the process if it's running.
+# User:
+# openim::util::check_process_names nginx mysql redis
+# The function returns a status of 1 if any of the processes is not running.
+openim::util::check_process_names() {
+ # Function to get the port of a process
+ get_port() {
+ local pid=$1
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ # Linux
+ ss -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | cut -d ':' -f2
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # macOS
+ lsof -nP -iTCP -sTCP:LISTEN -a -p $pid | awk 'NR>1 {print $9}' | sed 's/.*://'
+ else
+ echo "Unsupported OS"
+ return 1
+ fi
+ }
+
+ # Arrays to collect details of processes
+ local not_started=()
+ local started=()
+
+ openim::log::info "Checking processes: $*"
+ # Iterate over each given process name
+ for process_name in "$@"; do
+ # Use `pgrep` to find process IDs related to the given process name
+ local pids=($(pgrep -f $process_name))
+
+ # Check if any process IDs were found
+ if [[ ${#pids[@]} -eq 0 ]]; then
+ not_started+=($process_name)
+ else
+ # If there are PIDs, loop through each one
+ for pid in "${pids[@]}"; do
+ local command=$(ps -p $pid -o cmd=)
+ local start_time=$(ps -p $pid -o lstart=)
+ local port=$(get_port $pid)
+
+ # Check if port information was found for the PID
+ if [[ -z $port ]]; then
+ port="N/A"
+ fi
+
+ started+=("Process $process_name - Command: $command, PID: $pid, Port: $port, Start time: $start_time")
+ done
+ fi
+ done
+
+ # Print information
+ if [[ ${#not_started[@]} -ne 0 ]]; then
+ openim::log::info "Not started processes:"
+ for process_name in "${not_started[@]}"; do
+ openim::log::error "Process $process_name is not started."
+ done
+ fi
+
+ if [[ ${#started[@]} -ne 0 ]]; then
+ echo
+ openim::log::info "Started processes:"
+ for info in "${started[@]}"; do
+ openim::log::info "$info"
+ done
+ fi
+
+ # Return status
+ if [[ ${#not_started[@]} -ne 0 ]]; then
+ echo "++++ OpenIM Log >> cat ${LOG_FILE}"
+ return 1
+ else
+ openim::log::success "All processes are running."
+ return 0
+ fi
+}
+
+# openim::util::check_process_names docker-pr
+
+# The `openim::util::stop_services_on_ports` function stops services running on specified ports.
+# It accepts multiple ports as arguments and performs the following:
+# 1. Attempts to stop any services running on the specified ports.
+# 2. Prints details of services successfully stopped and those that failed to stop.
+# Usage:
+# openim::util::stop_services_on_ports 8080 8081 8082
+# The function returns a status of 1 if any service couldn't be stopped.
+openim::util::stop_services_on_ports() {
+ # An array to collect ports of processes that couldn't be stopped.
+ local not_stopped=()
+
+ # An array to collect information about processes that were stopped.
+ local stopped=()
+
+ openim::log::info "Stopping services on ports: $*"
+ # Iterate over each given port.
+ for port in "$@"; do
+ # Use the `lsof` command to find process information related to the given port.
+ info=$(lsof -i :$port -n -P | grep LISTEN || true)
+
+ # If there's process information, it means the process associated with the port is running.
+ if [[ -n $info ]]; then
+ # Extract the Process ID.
+ while read -r line; do
+ local pid=$(echo $line | awk '{print $2}')
+
+ # Try to stop the service by killing its process.
+ if kill -TERM $pid; then
+ stopped+=($port)
+ else
+ not_stopped+=($port)
+ fi
+ done <<< "$info"
+ fi
+ done
+
+ # Print information about ports whose processes couldn't be stopped.
+ if [[ ${#not_stopped[@]} -ne 0 ]]; then
+ openim::log::info "Ports that couldn't be stopped:"
+ for port in "${not_stopped[@]}"; do
+ openim::log::status "Failed to stop service on port $port."
+ done
+ fi
+
+ # Print information about ports whose processes were successfully stopped.
+ if [[ ${#stopped[@]} -ne 0 ]]; then
+ echo
+ openim::log::info "Stopped services on ports:"
+ for port in "${stopped[@]}"; do
+ openim::log::info "Successfully stopped service on port $port."
+ done
+ fi
+
+ # If any of the processes couldn't be stopped, return a status of 1.
+ if [[ ${#not_stopped[@]} -ne 0 ]]; then
+ return 1
+ else
+ openim::log::success "All specified services were stopped."
+ echo ""
+ return 0
+ fi
+}
+# nc -l -p 12345
+# nc -l -p 123456
+# ps -ef | grep "nc -l"
+# openim::util::stop_services_on_ports 1234 12345
+
+
+# The `openim::util::stop_services_with_name` function stops services with specified names.
+# It accepts multiple service names as arguments and performs the following:
+# 1. Attempts to stop any services with the specified names.
+# 2. Prints details of services successfully stopped and those that failed to stop.
+# Usage:
+# openim::util::stop_services_with_name nginx apache
+# The function returns a status of 1 if any service couldn't be stopped.
+openim::util::stop_services_with_name() {
+ # An array to collect names of processes that couldn't be stopped.
+ local not_stopped=()
+
+ # An array to collect information about processes that were stopped.
+ local stopped=()
+
+ openim::log::info "Stopping services with names: $*"
+ # Iterate over each given service name.
+ for server_name in "$@"; do
+ # Use the `pgrep` command to find process IDs related to the given service name.
+ local pids=$(pgrep -f "$server_name")
+
+ # If no process was found with the name, add it to the not_stopped list
+ if [[ -z $pids ]]; then
+ not_stopped+=("$server_name")
+ continue
+ fi
+ local stopped_this_time=false
+ for pid in $pids; do
+
+ # Exclude the PID of the current script
+ if [[ "$pid" == "$$" ]]; then
+ continue
+ fi
+
+ # If there's a Process ID, it means the service with the name is running.
+ if [[ -n $pid ]]; then
+ # Try to stop the service by killing its process.
+ if kill -TERM $pid 2>/dev/null; then
+ stopped_this_time=true
+ fi
+ fi
+ done
+
+ if $stopped_this_time; then
+ stopped+=("$server_name")
else
- info=$(netstat -ltnp | grep ":$port" || true)
+ not_stopped+=("$server_name")
+ fi
+ done
+
+ # Print information about services whose processes couldn't be stopped.
+ if [[ ${#not_stopped[@]} -ne 0 ]]; then
+ openim::log::info "Services that couldn't be stopped:"
+ for name in "${not_stopped[@]}"; do
+ openim::log::status "Failed to stop the $name service."
+ done
+ fi
+
+ # Print information about services whose processes were successfully stopped.
+ if [[ ${#stopped[@]} -ne 0 ]]; then
+ echo
+ openim::log::info "Stopped services:"
+ for name in "${stopped[@]}"; do
+ openim::log::info "Successfully stopped the $name service."
+ done
+ fi
+
+ openim::log::success "All specified services were stopped."
+ echo ""
+}
+# sleep 333333&
+# sleep 444444&
+# ps -ef | grep "sleep"
+# openim::util::stop_services_with_name "sleep 333333" "sleep 444444"
+
+# This figures out the host platform without relying on golang. We need this as
+# we don't want a golang install to be a prerequisite to building yet we need
+# this info to figure out where the final binaries are placed.
+openim::util::host_platform() {
+ echo "$(openim::util::host_os)/$(openim::util::host_arch)"
+}
+
+# looks for $1 in well-known output locations for the platform ($2)
+# $OPENIM_ROOT must be set
+openim::util::find-binary-for-platform() {
+ local -r lookfor="$1"
+ local -r platform="$2"
+ local locations=(
+ "${OPENIM_ROOT}/_output/bin/${lookfor}"
+ "${OPENIM_ROOT}/_output/${platform}/${lookfor}"
+ "${OPENIM_ROOT}/_output/local/bin/${platform}/${lookfor}"
+ "${OPENIM_ROOT}/_output/platforms/${platform}/${lookfor}"
+ "${OPENIM_ROOT}/_output/platforms/bin/${platform}/${lookfor}"
+ )
+
+ # List most recently-updated location.
+ local -r bin=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
+ echo -n "${bin}"
+}
+
+# looks for $1 in well-known output locations for the host platform
+# $OPENIM_ROOT must be set
+openim::util::find-binary() {
+ openim::util::find-binary-for-platform "$1" "$(openim::util::host_platform)"
+}
+
+# Run all known doc generators (today gendocs and genman for openimctl)
+# $1 is the directory to put those generated documents
+openim::util::gen-docs() {
+ local dest="$1"
+
+ # Find binary
+ gendocs=$(openim::util::find-binary "gendocs")
+ genopenimdocs=$(openim::util::find-binary "genopenimdocs")
+ genman=$(openim::util::find-binary "genman")
+ genyaml=$(openim::util::find-binary "genyaml")
+ genfeddocs=$(openim::util::find-binary "genfeddocs")
+
+ # TODO: If ${genfeddocs} is not used from anywhere (it isn't used at
+ # least from k/k tree), remove it completely.
+ openim::util::sourced_variable "${genfeddocs}"
+
+ mkdir -p "${dest}/docs/guide/en-US/cmd/openimctl/"
+ "${gendocs}" "${dest}/docs/guide/en-US/cmd/openimctl/"
+
+ mkdir -p "${dest}/docs/guide/en-US/cmd/"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-api"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-cmdutils"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-crontask"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-msggateway"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-msgtransfer"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-push"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-auth"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-conversation"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-friend"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-group"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-msg"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-third"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/" "openim-rpc-user"
+ "${genopenimdocs}" "${dest}/docs/guide/en-US/cmd/openimctl" "openimctl"
+
+ mkdir -p "${dest}/docs/man/man1/"
+"${genman}" "${dest}/docs/man/man1/" "openim-api"
+"${genman}" "${dest}/docs/man/man1/" "openim-cmdutils"
+"${genman}" "${dest}/docs/man/man1/" "openim-crontask"
+"${genman}" "${dest}/docs/man/man1/" "openim-msggateway"
+"${genman}" "${dest}/docs/man/man1/" "openim-msgtransfer"
+"${genman}" "${dest}/docs/man/man1/" "openim-push"
+"${genman}" "${dest}/docs/man/man1/" "openim-rpc-auth"
+"${genman}" "${dest}/docs/man/man1/" "openim-rpc-conversation"
+"${genman}" "${dest}/docs/man/man1/" "openim-rpc-friend"
+"${genman}" "${dest}/docs/man/man1/" "openim-rpc-group"
+"${genman}" "${dest}/docs/man/man1/" "openim-rpc-msg"
+"${genman}" "${dest}/docs/man/man1/" "openim-rpc-third"
+"${genman}" "${dest}/docs/man/man1/" "openim-rpc-user"
+
+ mkdir -p "${dest}/docs/guide/en-US/yaml/openimctl/"
+ "${genyaml}" "${dest}/docs/guide/en-US/yaml/openimctl/"
+
+ # create the list of generated files
+ pushd "${dest}" > /dev/null || return 1
+ touch docs/.generated_docs
+ find . -type f | cut -sd / -f 2- | LC_ALL=C sort > docs/.generated_docs
+ popd > /dev/null || return 1
+}
+
+# Removes previously generated docs-- we don't want to check them in. $OPENIM_ROOT
+# must be set.
+openim::util::remove-gen-docs() {
+ if [ -e "${OPENIM_ROOT}/docs/.generated_docs" ]; then
+ # remove all of the old docs; we don't want to check them in.
+ while read -r file; do
+ rm "${OPENIM_ROOT}/${file}" 2>/dev/null || true
+ done <"${OPENIM_ROOT}/docs/.generated_docs"
+ # The docs/.generated_docs file lists itself, so we don't need to explicitly
+ # delete it.
+ fi
+}
+
+# Returns the name of the upstream remote repository name for the local git
+# repo, e.g. "upstream" or "origin".
+openim::util::git_upstream_remote_name() {
+ git remote -v | grep fetch |\
+ grep -E 'github.com[/:]openimsdk/open-im-server|openim.cc/server' |\
+ head -n 1 | awk '{print $1}'
+}
+
+# Exits script if working directory is dirty. If it's run interactively in the terminal
+# the user can commit changes in a second terminal. This script will wait.
+openim::util::ensure_clean_working_dir() {
+ while ! git diff HEAD --exit-code &>/dev/null; do
+ echo -e "\nUnexpected dirty working directory:\n"
+ if tty -s; then
+ git status -s
+ else
+ git diff -a # be more verbose in log files without tty
+ exit 1
+ fi | sed 's/^/ /'
+ echo -e "\nCommit your changes in another terminal and then continue here by pressing enter."
+ read -r
+ done 1>&2
+}
+
+# Find the base commit using:
+# $PULL_BASE_SHA if set (from Prow)
+# current ref from the remote upstream branch
+openim::util::base_ref() {
+ local -r git_branch=$1
+
+ if [[ -n ${PULL_BASE_SHA:-} ]]; then
+ echo "${PULL_BASE_SHA}"
+ return
+ fi
+
+ full_branch="$(openim::util::git_upstream_remote_name)/${git_branch}"
+
+ # make sure the branch is valid, otherwise the check will pass erroneously.
+ if ! git describe "${full_branch}" >/dev/null; then
+ # abort!
+ exit 1
+ fi
+
+ echo "${full_branch}"
+}
+
+# Checks whether there are any files matching pattern $2 changed between the
+# current branch and upstream branch named by $1.
+# Returns 1 (false) if there are no changes
+# 0 (true) if there are changes detected.
+openim::util::has_changes() {
+ local -r git_branch=$1
+ local -r pattern=$2
+ local -r not_pattern=${3:-totallyimpossiblepattern}
+
+ local base_ref
+ base_ref=$(openim::util::base_ref "${git_branch}")
+ echo "Checking for '${pattern}' changes against '${base_ref}'"
+
+ # notice this uses ... to find the first shared ancestor
+ if git diff --name-only "${base_ref}...HEAD" | grep -v -E "${not_pattern}" | grep "${pattern}" > /dev/null; then
+ return 0
+ fi
+ # also check for pending changes
+ if git status --porcelain | grep -v -E "${not_pattern}" | grep "${pattern}" > /dev/null; then
+ echo "Detected '${pattern}' uncommitted changes."
+ return 0
+ fi
+ echo "No '${pattern}' changes detected."
+ return 1
+}
+
+openim::util::download_file() {
+ local -r url=$1
+ local -r destination_file=$2
+
+ rm "${destination_file}" 2&> /dev/null || true
+
+ for i in $(seq 5)
+ do
+ if ! curl -fsSL --retry 3 --keepalive-time 2 "${url}" -o "${destination_file}"; then
+ echo "Downloading ${url} failed. $((5-i)) retries left."
+ sleep 1
+ else
+ echo "Downloading ${url} succeed"
+ return 0
+ fi
+ done
+ return 1
+}
+
+# Test whether openssl is installed.
+# Sets:
+# OPENSSL_BIN: The path to the openssl binary to use
+function openim::util::test_openssl_installed {
+ if ! openssl version >& /dev/null; then
+ echo "Failed to run openssl. Please ensure openssl is installed"
+ exit 1
+ fi
+
+ OPENSSL_BIN=$(command -v openssl)
+}
+
+# creates a client CA, args are sudo, dest-dir, ca-id, purpose
+# purpose is dropped in after "key encipherment", you usually want
+# '"client auth"'
+# '"server auth"'
+# '"client auth","server auth"'
+function openim::util::create_signing_certkey {
+ local sudo=$1
+ local dest_dir=$2
+ local id=$3
+ local purpose=$4
+ # Create client ca
+ ${sudo} /usr/bin/env bash -e < "${dest_dir}/${id}-ca-config.json"
+EOF
+}
+
+# signs a client certificate: args are sudo, dest-dir, CA, filename (roughly), username, groups...
+function openim::util::create_client_certkey {
+ local sudo=$1
+ local dest_dir=$2
+ local ca=$3
+ local id=$4
+ local cn=${5:-$4}
+ local groups=""
+ local SEP=""
+ shift 5
+ while [ -n "${1:-}" ]; do
+ groups+="${SEP}{\"O\":\"$1\"}"
+ SEP=","
+ shift 1
+ done
+ ${sudo} /usr/bin/env bash -e < /dev/null
+apiVersion: v1
+kind: Config
+clusters:
+ - cluster:
+ certificate-authority: ${ca_file}
+ server: https://${api_host}:${api_port}/
+ name: local-up-cluster
+users:
+ - user:
+ token: ${token}
+ client-certificate: ${dest_dir}/client-${client_id}.crt
+ client-key: ${dest_dir}/client-${client_id}.key
+ name: local-up-cluster
+contexts:
+ - context:
+ cluster: local-up-cluster
+ user: local-up-cluster
+ name: local-up-cluster
+current-context: local-up-cluster
+EOF
+
+ # flatten the openimconfig files to make them self contained
+ username=$(whoami)
+ ${sudo} /usr/bin/env bash -e < "/tmp/${client_id}.openimconfig"
+ mv -f "/tmp/${client_id}.openimconfig" "${dest_dir}/${client_id}.openimconfig"
+ chown ${username} "${dest_dir}/${client_id}.openimconfig"
+EOF
+}
+
+# Determines if docker can be run, failures may simply require that the user be added to the docker group.
+function openim::util::ensure_docker_daemon_connectivity {
+ IFS=" " read -ra DOCKER <<< "${DOCKER_OPTS}"
+ # Expand ${DOCKER[@]} only if it's not unset. This is to work around
+ # Bash 3 issue with unbound variable.
+ DOCKER=(docker ${DOCKER[@]:+"${DOCKER[@]}"})
+ if ! "${DOCKER[@]}" info > /dev/null 2>&1 ; then
+ cat <<'EOF' >&2
+Can't connect to 'docker' daemon. please fix and retry.
+
+Possible causes:
+ - Docker Daemon not started
+ - Linux: confirm via your init system
+ - macOS w/ docker-machine: run `docker-machine ls` and `docker-machine start `
+ - macOS w/ Docker for Mac: Check the menu bar and start the Docker application
+ - DOCKER_HOST hasn't been set or is set incorrectly
+ - Linux: domain socket is used, DOCKER_* should be unset. In Bash run `unset ${!DOCKER_*}`
+ - macOS w/ docker-machine: run `eval "$(docker-machine env )"`
+ - macOS w/ Docker for Mac: domain socket is used, DOCKER_* should be unset. In Bash run `unset ${!DOCKER_*}`
+ - Other things to check:
+ - Linux: User isn't in 'docker' group. Add and relogin.
+ - Something like 'sudo usermod -a -G docker ${USER}'
+ - RHEL7 bug and workaround: https://bugzilla.redhat.com/show_bug.cgi?id=1119282#c8
+EOF
+ return 1
+ fi
+}
+
+# Wait for background jobs to finish. Return with
+# an error status if any of the jobs failed.
+openim::util::wait-for-jobs() {
+ local fail=0
+ local job
+ for job in $(jobs -p); do
+ wait "${job}" || fail=$((fail + 1))
+ done
+ return ${fail}
+}
+
+# openim::util::join
+# Concatenates the list elements with the delimiter passed as first parameter
+#
+# Ex: openim::util::join , a b c
+# -> a,b,c
+function openim::util::join {
+ local IFS="$1"
+ shift
+ echo "$*"
+}
+
+# Function: openim::util::list-to-string
+# Description: Converts a list to a string, removing spaces, brackets, and commas.
+# Example input: [1002 3 , 2 32 3 , 3 434 ,]
+# Example output: 10023 2323 3434
+# Example usage:
+# result=$(openim::util::list-to-string "[10023, 2323, 3434]")
+# echo $result
+function openim::util::list-to-string() {
+ # Capture all arguments into a single string
+ ports_list="$*"
+
+ # Use sed for transformations:
+ # 1. Remove spaces
+ # 2. Replace commas with spaces
+ # 3. Remove opening and closing brackets
+ ports_array=$(echo "$ports_list" | sed 's/ //g; s/,/ /g; s/^\[\(.*\)\]$/\1/')
+ # For external use, we might want to echo the result so that it can be captured by callers
+ echo "$ports_array"
+}
+# MSG_GATEWAY_PROM_PORTS=$(openim::util::list-to-string "10023, 2323, 34 34")
+# read -a MSG_GATEWAY_PROM_PORTS <<< $(openim::util::list-to-string "10023, 2323, 34 34")
+# echo ${MSG_GATEWAY_PROM_PORTS}
+# echo "${#MSG_GATEWAY_PROM_PORTS[@]}"
+# Downloads cfssl/cfssljson/cfssl-certinfo into $1 directory if they do not already exist in PATH
+#
+# Assumed vars:
+# $1 (cfssl directory) (optional)
+#
+# Sets:
+# CFSSL_BIN: The path of the installed cfssl binary
+# CFSSLJSON_BIN: The path of the installed cfssljson binary
+# CFSSLCERTINFO_BIN: The path of the installed cfssl-certinfo binary
+#
+function openim::util::ensure-cfssl {
+ if command -v cfssl &>/dev/null && command -v cfssljson &>/dev/null && command -v cfssl-certinfo &>/dev/null; then
+ CFSSL_BIN=$(command -v cfssl)
+ CFSSLJSON_BIN=$(command -v cfssljson)
+ CFSSLCERTINFO_BIN=$(command -v cfssl-certinfo)
+ return 0
+ fi
+
+ host_arch=$(openim::util::host_arch)
+
+ if [[ "${host_arch}" != "amd64" ]]; then
+ echo "Cannot download cfssl on non-amd64 hosts and cfssl does not appear to be installed."
+ echo "Please install cfssl, cfssljson and cfssl-certinfo and verify they are in \$PATH."
+ echo "Hint: export PATH=\$PATH:\$GOPATH/bin; go get -u github.com/cloudflare/cfssl/cmd/..."
+ exit 1
+ fi
+
+ # Create a temp dir for cfssl if no directory was given
+ local cfssldir=${1:-}
+ if [[ -z "${cfssldir}" ]]; then
+ cfssldir="$HOME/bin"
+ fi
+
+ mkdir -p "${cfssldir}"
+ pushd "${cfssldir}" > /dev/null || return 1
+
+ echo "Unable to successfully run 'cfssl' from ${PATH}; downloading instead..."
+ kernel=$(uname -s)
+ case "${kernel}" in
+ Linux)
+ curl --retry 10 -L -o cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
+ curl --retry 10 -L -o cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
+ curl --retry 10 -L -o cfssl-certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
+ ;;
+ Darwin)
+ curl --retry 10 -L -o cfssl https://pkg.cfssl.org/R1.2/cfssl_darwin-amd64
+ curl --retry 10 -L -o cfssljson https://pkg.cfssl.org/R1.2/cfssljson_darwin-amd64
+ curl --retry 10 -L -o cfssl-certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_darwin-amd64
+ ;;
+ *)
+ echo "Unknown, unsupported platform: ${kernel}." >&2
+ echo "Supported platforms: Linux, Darwin." >&2
+ exit 2
+ esac
+
+ chmod +x cfssl || true
+ chmod +x cfssljson || true
+ chmod +x cfssl-certinfo || true
+
+ CFSSL_BIN="${cfssldir}/cfssl"
+ CFSSLJSON_BIN="${cfssldir}/cfssljson"
+ CFSSLCERTINFO_BIN="${cfssldir}/cfssl-certinfo"
+ if [[ ! -x ${CFSSL_BIN} || ! -x ${CFSSLJSON_BIN} || ! -x ${CFSSLCERTINFO_BIN} ]]; then
+ echo "Failed to download 'cfssl'."
+ echo "Please install cfssl, cfssljson and cfssl-certinfo and verify they are in \$PATH."
+ echo "Hint: export PATH=\$PATH:\$GOPATH/bin; go get -u github.com/cloudflare/cfssl/cmd/..."
+ exit 1
+ fi
+ popd > /dev/null || return 1
+}
+
+function openim::util::ensure-docker-buildx {
+ # podman returns 0 on `docker buildx version`, docker on `docker buildx`. One of them must succeed.
+ if docker buildx version >/dev/null 2>&1 || docker buildx >/dev/null 2>&1; then
+ return 0
+ else
+ echo "ERROR: docker buildx not available. Docker 19.03 or higher is required with experimental features enabled"
+ exit 1
+ fi
+}
+
+# openim::util::ensure-bash-version
+# Check if we are using a supported bash version
+#
+function openim::util::ensure-bash-version {
+ # shellcheck disable=SC2004
+ if ((${BASH_VERSINFO[0]}<4)) || ( ((${BASH_VERSINFO[0]}==4)) && ((${BASH_VERSINFO[1]}<2)) ); then
+ echo "ERROR: This script requires a minimum bash version of 4.2, but got version of ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}"
+ if [ "$(uname)" = 'Darwin' ]; then
+ echo "On macOS with homebrew 'brew install bash' is sufficient."
+ fi
+ exit 1
+ fi
+}
+
+# openim::util::ensure-install-nginx
+# Check if nginx is installed
+#
+function openim::util::ensure-install-nginx {
+ if ! command -v nginx &>/dev/null; then
+ echo "ERROR: nginx not found. Please install nginx."
+ exit 1
+ fi
+
+ for port in 80
+ do
+ if echo |telnet 127.0.0.1 $port 2>&1|grep refused &>/dev/null;then
+ exit 1
+ fi
+ done
+}
+
+# openim::util::ensure-gnu-sed
+# Determines which sed binary is gnu-sed on linux/darwin
+#
+# Sets:
+# SED: The name of the gnu-sed binary
+#
+function openim::util::ensure-gnu-sed {
+ # NOTE: the echo below is a workaround to ensure sed is executed before the grep.
+ # see: https://github.com/openimrnetes/openimrnetes/issues/87251
+ sed_help="$(LANG=C sed --help 2>&1 || true)"
+ if echo "${sed_help}" | grep -q "GNU\|BusyBox"; then
+ SED="sed"
+ elif command -v gsed &>/dev/null; then
+ SED="gsed"
+ else
+ openim::log::error "Failed to find GNU sed as sed or gsed. If you are on Mac: brew install gnu-sed." >&2
+ return 1
+ fi
+ openim::util::sourced_variable "${SED}"
+}
+
+# openim::util::ensure-gnu-date
+# Determines which date binary is gnu-date on linux/darwin
+#
+# Sets:
+# DATE: The name of the gnu-date binary
+#
+function openim::util::ensure-gnu-date {
+ # NOTE: the echo below is a workaround to ensure date is executed before the grep.
+ date_help="$(LANG=C date --help 2>&1 || true)"
+ if echo "${date_help}" | grep -q "GNU\|BusyBox"; then
+ DATE="date"
+ elif command -v gdate &>/dev/null; then
+ DATE="gdate"
+ else
+ openim::log::error "Failed to find GNU date as date or gdate. If you are on Mac: brew install coreutils." >&2
+ return 1
+ fi
+ openim::util::sourced_variable "${DATE}"
+}
+
+# openim::util::check-file-in-alphabetical-order
+# Check that the file is in alphabetical order
+#
+function openim::util::check-file-in-alphabetical-order {
+ local failure_file="$1"
+ if ! diff -u "${failure_file}" <(LC_ALL=C sort "${failure_file}"); then
+ {
+ echo
+ echo "${failure_file} is not in alphabetical order. Please sort it:"
+ echo
+ echo " LC_ALL=C sort -o ${failure_file} ${failure_file}"
+ echo
+ } >&2
+ false
+ fi
+}
+
+# openim::util::require-jq
+# Checks whether jq is installed.
+function openim::util::require-jq {
+ if ! command -v jq &>/dev/null; then
+ openim::log::errexit "jq not found. Please install." 1>&2
+ fi
+}
+
+# openim::util::require-dig
+# Checks whether dig is installed and provides installation instructions if it is not.
+function openim::util::require-dig {
+ if ! command -v dig &>/dev/null; then
+ openim::log::error "Please install 'dig' to use this feature. OR Set the environment variable for OPENIM_IP"
+ openim::log::error "Installation instructions:"
+ openim::log::error " For Ubuntu/Debian: sudo apt-get install dnsutils"
+ openim::log::error " For CentOS/RedHat: sudo yum install bind-utils"
+ openim::log::error " For macOS: 'dig' should be preinstalled. If missing, try: brew install bind"
+ openim::log::error " For Windows: Install BIND9 tools from https://www.isc.org/download/"
+ openim::log::error_exit "dig command not found."
+ fi
+ return 0
+}
+
+# outputs md5 hash of $1, works on macOS and Linux
+function openim::util::md5() {
+ if which md5 >/dev/null 2>&1; then
+ md5 -q "$1"
+ else
+ md5sum "$1" | awk '{ print $1 }'
+ fi
+}
+
+# openim::util::read-array
+# Reads in stdin and adds it line by line to the array provided. This can be
+# used instead of "mapfile -t", and is bash 3 compatible.
+#
+# Assumed vars:
+# $1 (name of array to create/modify)
+#
+# Example usage:
+# openim::util::read-array files < <(ls -1)
+#
+function openim::util::read-array {
+ local i=0
+ unset -v "$1"
+ while IFS= read -r "$1[i++]"; do :; done
+ eval "[[ \${$1[--i]} ]]" || unset "$1[i]" # ensures last element isn't empty
+}
+
+# Some useful colors.
+if [[ -z "${color_start-}" ]]; then
+ declare -r color_start="\033["
+ declare -r color_red="${color_start}0;31m"
+ declare -r color_yellow="${color_start}0;33m"
+ declare -r color_green="${color_start}0;32m"
+ declare -r color_blue="${color_start}1;34m"
+ declare -r color_cyan="${color_start}1;36m"
+ declare -r color_norm="${color_start}0m"
+
+ openim::util::sourced_variable "${color_start}"
+ openim::util::sourced_variable "${color_red}"
+ openim::util::sourced_variable "${color_yellow}"
+ openim::util::sourced_variable "${color_green}"
+ openim::util::sourced_variable "${color_blue}"
+ openim::util::sourced_variable "${color_cyan}"
+ openim::util::sourced_variable "${color_norm}"
+fi
+
+# ex: ts=2 sw=2 et filetype=sh
+
+function openim::util::desc() {
+ openim::util:run::maybe_first_prompt
+ rate=25
+ if [ -n "$DEMO_RUN_FAST" ]; then
+ rate=1000
+ fi
+ echo "$blue# $@$reset" | pv -qL $rate#!/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.
+
+# this script is used to check whether the code is formatted by gofmt or not
+#
+# Usage: source scripts/lib/util.sh
+################################################################################
+
+# TODO Debug: Just for testing, please comment out
+# OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P)
+# source "${OPENIM_ROOT}/scripts/lib/logging.sh"
+
+#1、将IP写在一个文件里,比如文件名为hosts_file,一行一个IP地址。
+#2、修改ssh-mutual-trust.sh里面的用户名及密码,默认为root用户及密码123。
+# hosts_file_path="path/to/your/hosts/file"
+# openim:util::setup_ssh_key_copy "$hosts_file_path" "root" "123"
+function openim:util::setup_ssh_key_copy() {
+ local hosts_file="$1"
+ local username="${2:-root}"
+ local password="${3:-123}"
+
+ local sshkey_file=~/.ssh/id_rsa.pub
+
+ # check sshkey file
+ if [[ ! -e $sshkey_file ]]; then
+ expect -c "
+ spawn ssh-keygen -t rsa
+ expect \"Enter*\" { send \"\n\"; exp_continue; }
+ "
+ fi
+
+ # get hosts list
+ local hosts=$(awk '/^[^#]/ {print $1}' "${hosts_file}")
+
+ ssh_key_copy() {
+ local target=$1
+
+ # delete history
+ sed -i "/$target/d" ~/.ssh/known_hosts
+
+ # copy key
+ expect -c "
+ set timeout 100
+ spawn ssh-copy-id $username@$target
+ expect {
+ \"yes/no\" { send \"yes\n\"; exp_continue; }
+ \"*assword\" { send \"$password\n\"; }
+ \"already exist on the remote system\" { exit 1; }
+ }
+ expect eof
+ "
+ }
+
+ # auto sshkey pair
+ for host in $hosts; do
+ if ! ping -i 0.2 -c 3 -W 1 "$host" > /dev/null 2>&1; then
+ echo "[ERROR]: Can't connect $host"
+ continue
+ fi
+
+ local host_entry=$(awk "/$host/"'{print $1, $2}' /etc/hosts)
+ if [[ $host_entry ]]; then
+ local hostaddr=$(echo "$host_entry" | awk '{print $1}')
+ local hostname=$(echo "$host_entry" | awk '{print $2}')
+ ssh_key_copy "$hostaddr"
+ ssh_key_copy "$hostname"
+ else
+ ssh_key_copy "$host"
+ fi
+ done
+}
+
+function openim::util::sourced_variable {
+ # Call this function to tell shellcheck that a variable is supposed to
+ # be used from other calling context. This helps quiet an "unused
+ # variable" warning from shellcheck and also document your code.
+ true
+}
+
+openim::util::sortable_date() {
+ date "+%Y%m%d-%H%M%S"
+}
+
+# arguments: target, item1, item2, item3, ...
+# returns 0 if target is in the given items, 1 otherwise.
+openim::util::array_contains() {
+ local search="$1"
+ local element
+ shift
+ for element; do
+ if [[ "${element}" == "${search}" ]]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+openim::util::wait_for_url() {
+ local url=$1
+ local prefix=${2:-}
+ local wait=${3:-1}
+ local times=${4:-30}
+ local maxtime=${5:-1}
+
+ command -v curl >/dev/null || {
+ openim::log::usage "curl must be installed"
+ exit 1
+ }
+
+ local i
+ for i in $(seq 1 "${times}"); do
+ local out
+ if out=$(curl --max-time "${maxtime}" -gkfs "${url}" 2>/dev/null); then
+ openim::log::status "On try ${i}, ${prefix}: ${out}"
+ return 0
+ fi
+ sleep "${wait}"
+ done
+ openim::log::error "Timed out waiting for ${prefix} to answer at ${url}; tried ${times} waiting ${wait} between each"
+ return 1
+}
+
+# Example: openim::util::wait_for_success 120 5 "openimctl get nodes|grep localhost"
+# arguments: wait time, sleep time, shell command
+# returns 0 if the shell command get output, 1 otherwise.
+openim::util::wait_for_success(){
+ local wait_time="$1"
+ local sleep_time="$2"
+ local cmd="$3"
+ while [ "$wait_time" -gt 0 ]; do
+ if eval "$cmd"; then
+ return 0
+ else
+ sleep "$sleep_time"
+ wait_time=$((wait_time-sleep_time))
+ fi
+ done
+ return 1
+}
+
+# Example: openim::util::trap_add 'echo "in trap DEBUG"' DEBUG
+# See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal
+openim::util::trap_add() {
+ local trap_add_cmd
+ trap_add_cmd=$1
+ shift
+
+ for trap_add_name in "$@"; do
+ local existing_cmd
+ local new_cmd
+
+ # Grab the currently defined trap commands for this trap
+ existing_cmd=$(trap -p "${trap_add_name}" | awk -F"'" '{print $2}')
+
+ if [[ -z "${existing_cmd}" ]]; then
+ new_cmd="${trap_add_cmd}"
+ else
+ new_cmd="${trap_add_cmd};${existing_cmd}"
+ fi
+
+ # Assign the test. Disable the shellcheck warning telling that trap
+ # commands should be single quoted to avoid evaluating them at this
+ # point instead evaluating them at run time. The logic of adding new
+ # commands to a single trap requires them to be evaluated right away.
+ # shellcheck disable=SC2064
+ trap "${new_cmd}" "${trap_add_name}"
+ done
+}
+
+# Opposite of openim::util::ensure-temp-dir()
+openim::util::cleanup-temp-dir() {
+ rm -rf "${OPENIM_TEMP}"
+}
+
+# Create a temp dir that'll be deleted at the end of this bash session.
+#
+# Vars set:
+# OPENIM_TEMP
+openim::util::ensure-temp-dir() {
+ if [[ -z ${OPENIM_TEMP-} ]]; then
+ OPENIM_TEMP=$(mktemp -d 2>/dev/null || mktemp -d -t openimrnetes.XXXXXX)
+ openim::util::trap_add openim::util::cleanup-temp-dir EXIT
+ fi
+}
+
+openim::util::host_os() {
+ local host_os
+ case "$(uname -s)" in
+ Darwin)
+ host_os=darwin
+ ;;
+ Linux)
+ host_os=linux
+ ;;
+ *)
+ openim::log::error "Unsupported host OS. Must be Linux or Mac OS X."
+ exit 1
+ ;;
+ esac
+ echo "${host_os}"
+}
+
+openim::util::host_arch() {
+ local host_arch
+ case "$(uname -m)" in
+ x86_64*)
+ host_arch=amd64
+ ;;
+ i?86_64*)
+ host_arch=amd64
+ ;;
+ amd64*)
+ host_arch=amd64
+ ;;
+ aarch64*)
+ host_arch=arm64
+ ;;
+ arm64*)
+ host_arch=arm64
+ ;;
+ arm*)
+ host_arch=arm
+ ;;
+ i?86*)
+ host_arch=x86
+ ;;
+ s390x*)
+ host_arch=s390x
+ ;;
+ ppc64le*)
+ host_arch=ppc64le
+ ;;
+ *)
+ openim::log::error "Unsupported host arch. Must be x86_64, 386, arm, arm64, s390x or ppc64le."
+ exit 1
+ ;;
+ esac
+ echo "${host_arch}"
+}
+
+# Define a bash function to check the versions of Docker and Docker Compose
+openim::util::check_docker_and_compose_versions() {
+ # Define the required versions of Docker and Docker Compose
+ required_docker_version="20.10.0"
+ required_compose_version="2.0"
+
+ # Get the currently installed Docker version
+ installed_docker_version=$(docker --version | awk '{print $3}' | sed 's/,//')
+
+ # Check if the installed Docker version matches the required version
+ if [[ "$installed_docker_version" < "$required_docker_version" ]]; then
+ echo "Docker version mismatch. Installed: $installed_docker_version, Required: $required_docker_version"
+ return 1
+ fi
+
+ # Check if the docker compose sub-command is available
+ if ! docker compose version &> /dev/null; then
+ echo "Docker does not support the docker compose sub-command"
+ echo "You need to upgrade Docker to the right version"
+ return 1
+ fi
+
+ # Get the currently installed Docker Compose version
+ installed_compose_version=$(docker compose version --short)
+
+ # Check if the installed Docker Compose version matches the required version
+ if [[ "$installed_compose_version" < "$required_compose_version" ]]; then
+ echo "Docker Compose version mismatch. Installed: $installed_compose_version, Required: $required_compose_version"
+ return 1
+ fi
+
+}
+
+
+# The `openim::util::check_ports` function analyzes the state of processes based on given ports.
+# It accepts multiple ports as arguments and prints:
+# 1. The state of the process (whether it's running or not).
+# 2. The start time of the process if it's running.
+# User:
+# openim::util::check_ports 8080 8081 8082
+# The function returns a status of 1 if any of the processes is not running.
+openim::util::check_ports() {
+ # An array to collect ports of processes that are not running.
+ local not_started=()
+
+ # An array to collect information about processes that are running.
+ local started=()
+
+ openim::log::info "Checking ports: $*"
+ # Iterate over each given port.
+ for port in "$@"; do
+ # Initialize variables
+ # Check the OS and use the appropriate command
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ if command -v ss > /dev/null 2>&1; then
+ info=$(ss -ltnp | grep ":$port" || true)
+ echo "!!!!!!!!!!! port=$port"
+ echo "!!!!!!!!!!! info=$info"
+ else
+ info=$(netstat -ltnp | grep ":$port" || true)
+ echo "!!!!!!!!!!! port=$port"
+ echo "!!!!!!!!!!! info=$info"
+ fi
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # For macOS, use lsof
+ info=$(lsof -i:"$port" | grep "\*:$port" || true)
fi
- # If there's no process information, it means the process associated with the port is not running.
+ # Check if any process is using the port
if [[ -z $info ]]; then
not_started+=($port)
else
- # Extract relevant details: Process Name, PID, and FD.
- local details=$(echo $info | sed -n 's/.*users:(("\([^"]*\)",pid=\([^,]*\),fd=\([^)]*\))).*/\1 \2 \3/p')
- local command=$(echo $details | awk '{print $1}')
- local pid=$(echo $details | awk '{print $2}')
- local fd=$(echo $details | awk '{print $3}')
-
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ # Extract relevant details for Linux: Process Name, PID, and FD.
+ details=$(echo $info | sed -n 's/.*users:(("\([^"]*\)",pid=\([^,]*\),fd=\([^)]*\))).*/\1 \2 \3/p')
+ command=$(echo $details | awk '{print $1}')
+ pid=$(echo $details | awk '{print $2}')
+ fd=$(echo $details | awk '{print $3}')
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # Handle extraction for macOS
+ pid=$(echo $info | awk '{print $2}' | cut -d'/' -f1)
+ command=$(ps -p $pid -o comm= | xargs basename)
+ fd=$(echo $info | awk '{print $4}' | cut -d'/' -f1)
+ fi
+
# Get the start time of the process using the PID
if [[ -z $pid ]]; then
- local start_time="N/A"
+ start_time="N/A"
else
- # Get the start time of the process using the PID
- local start_time=$(ps -p $pid -o lstart=)
+ start_time=$(ps -p $pid -o lstart=)
fi
started+=("Port $port - Command: $command, PID: $pid, FD: $fd, Started: $start_time")
@@ -355,6 +1601,7 @@ openim::util::check_ports() {
return 0
fi
}
+
# set +o errexit
# Sample call for testing:
# openim::util::check_ports 10002 1004 12345 13306
@@ -371,12 +1618,15 @@ openim::util::check_process_names() {
# Function to get the port of a process
get_port() {
local pid=$1
- if command -v ss > /dev/null 2>&1; then
- # used ss comment
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ # Linux
ss -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | cut -d ':' -f2
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # macOS
+ lsof -nP -iTCP -sTCP:LISTEN -a -p $pid | awk 'NR>1 {print $9}' | sed 's/.*://'
else
- # used netstat comment replace ss
- netstat -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | sed 's/.*://'
+ echo "Unsupported OS"
+ return 1
fi
}
@@ -457,7 +1707,7 @@ openim::util::stop_services_on_ports() {
for port in "$@"; do
# Use the `lsof` command to find process information related to the given port.
info=$(lsof -i :$port -n -P | grep LISTEN || true)
-
+
# If there's process information, it means the process associated with the port is running.
if [[ -n $info ]]; then
# Extract the Process ID.
@@ -496,6 +1746,7 @@ openim::util::stop_services_on_ports() {
return 1
else
openim::log::success "All specified services were stopped."
+ echo ""
return 0
fi
}
@@ -572,6 +1823,7 @@ openim::util::stop_services_with_name() {
fi
openim::log::success "All specified services were stopped."
+ echo ""
}
# sleep 333333&
# sleep 444444&
@@ -591,11 +1843,11 @@ openim::util::find-binary-for-platform() {
local -r lookfor="$1"
local -r platform="$2"
local locations=(
- ""${OPENIM_ROOT}"/_output/bin/${lookfor}"
- ""${OPENIM_ROOT}"/_output/${platform}/${lookfor}"
- ""${OPENIM_ROOT}"/_output/local/bin/${platform}/${lookfor}"
- ""${OPENIM_ROOT}"/_output/platforms/${platform}/${lookfor}"
- ""${OPENIM_ROOT}"/_output/platforms/bin/${platform}/${lookfor}"
+ "${OPENIM_ROOT}/_output/bin/${lookfor}"
+ "${OPENIM_ROOT}/_output/${platform}/${lookfor}"
+ "${OPENIM_ROOT}/_output/local/bin/${platform}/${lookfor}"
+ "${OPENIM_ROOT}/_output/platforms/${platform}/${lookfor}"
+ "${OPENIM_ROOT}/_output/platforms/bin/${platform}/${lookfor}"
)
# List most recently-updated location.
@@ -672,11 +1924,11 @@ openim::util::gen-docs() {
# Removes previously generated docs-- we don't want to check them in. $OPENIM_ROOT
# must be set.
openim::util::remove-gen-docs() {
- if [ -e ""${OPENIM_ROOT}"/docs/.generated_docs" ]; then
+ if [ -e "${OPENIM_ROOT}/docs/.generated_docs" ]; then
# remove all of the old docs; we don't want to check them in.
while read -r file; do
- rm ""${OPENIM_ROOT}"/${file}" 2>/dev/null || true
- done <""${OPENIM_ROOT}"/docs/.generated_docs"
+ rm "${OPENIM_ROOT}/${file}" 2>/dev/null || true
+ done <"${OPENIM_ROOT}/docs/.generated_docs"
# The docs/.generated_docs file lists itself, so we don't need to explicitly
# delete it.
fi
@@ -1146,7 +2398,7 @@ function openim::util::require-jq {
# Checks whether dig is installed and provides installation instructions if it is not.
function openim::util::require-dig {
if ! command -v dig &>/dev/null; then
- openim::log::error "Please install 'dig' to use this feature."
+ openim::log::error "Please install 'dig' to use this feature. OR Set the environment variable for OPENIM_IP"
openim::log::error "Installation instructions:"
openim::log::error " For Ubuntu/Debian: sudo apt-get install dnsutils"
openim::log::error " For CentOS/RedHat: sudo yum install bind-utils"
@@ -1389,4 +2641,184 @@ function openim::util::gen_os_arch() {
if [[ "$*" =~ openim::util:: ]];then
eval $*
-fi
\ No newline at end of file
+fi
+
+ openim::util:run::prompt
+}
+
+function openim::util:run::prompt() {
+ echo -n "$yellow\$ $reset"
+}
+
+started=""
+function openim::util:run::maybe_first_prompt() {
+ if [ -z "$started" ]; then
+ openim::util:run::prompt
+ started=true
+ fi
+}
+
+# After a `run` this variable will hold the stdout of the command that was run.
+# If the command was interactive, this will likely be garbage.
+DEMO_RUN_STDOUT=""
+
+function openim::util::run() {
+ openim::util:run::maybe_first_prompt
+ rate=25
+ if [ -n "$DEMO_RUN_FAST" ]; then
+ rate=1000
+ fi
+ echo "$green$1$reset" | pv -qL $rate
+ if [ -n "$DEMO_RUN_FAST" ]; then
+ sleep 0.5
+ fi
+ OFILE="$(mktemp -t $(basename $0).XXXXXX)"
+ if [ "$(uname)" == "Darwin" ]; then
+ script -q "$OFILE" $1
+ else
+ script -eq -c "$1" -f "$OFILE"
+ fi
+ r=$?
+ read -d '' -t "${timeout}" -n 10000 # clear stdin
+ openim::util:run::prompt
+ if [ -z "$DEMO_AUTO_RUN" ]; then
+ read -s
+ fi
+ DEMO_RUN_STDOUT="$(tail -n +2 $OFILE | sed 's/\r//g')"
+ return $r
+}
+
+function openim::util::run::relative() {
+ for arg; do
+ echo "$(realpath $(dirname $(which $0)))/$arg" | sed "s|$(realpath $(pwd))|.|"
+ done
+}
+
+# This function retrieves the IP address of the current server.
+# It primarily uses the `curl` command to fetch the public IP address from ifconfig.me.
+# If curl or the service is not available, it falls back
+# to the internal IP address provided by the hostname command.
+# TODO: If a delay is found, the delay needs to be addressed
+function openim::util::get_server_ip() {
+ # Check if the 'curl' command is available
+ if command -v curl &> /dev/null; then
+ # Try to retrieve the public IP address using curl and ifconfig.me
+ IP=$(dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | sed 's/"//g' | tr -d '\n')
+
+ # Check if IP retrieval was successful
+ if [[ -z "$IP" ]]; then
+ # If not, get the internal IP address
+ IP=$(ip addr show | grep 'inet ' | grep -v 127.0.0.1 | awk '{print $2}' | cut -d'/' -f1 | head -n 1)
+ fi
+ else
+ # If curl is not available, get the internal IP address
+ IP=$(ip addr show | grep 'inet ' | grep -v 127.0.0.1 | awk '{print $2}' | cut -d'/' -f1 | head -n 1)
+ fi
+
+ # Return the fetched IP address
+ echo "$IP"
+}
+
+function openim::util::onCtrlC() {
+ echo -e "\n${t_reset}Ctrl+C Press it. It's exiting openim make init..."
+ exit 1
+}
+
+# Function Function: Remove Spaces in the string
+function openim::util::remove_space() {
+ value=$* # 获取传入的参数
+ result=$(echo $value | sed 's/ //g') # 去除空格
+}
+
+function openim::util::gencpu() {
+ # Check the system type
+ system_type=$(uname)
+
+ if [[ "$system_type" == "Darwin" ]]; then
+ # macOS (using sysctl)
+ cpu_count=$(sysctl -n hw.ncpu)
+ elif [[ "$system_type" == "Linux" ]]; then
+ # Linux (using lscpu)
+ cpu_count=$(lscpu --parse | grep -E '^([^#].*,){3}[^#]' | sort -u | wc -l)
+ else
+ echo "Unsupported operating system: $system_type"
+ exit 1
+ fi
+ echo $cpu_count
+}
+
+function openim::util::set_max_fd() {
+ local desired_fd=$1
+ local max_fd_limit
+
+ # Check if we're not on cygwin or darwin.
+ if [ "$(uname -s | tr '[:upper:]' '[:lower:]')" != "cygwin" ] && [ "$(uname -s | tr '[:upper:]' '[:lower:]')" != "darwin" ]; then
+ # Try to get the hard limit.
+ max_fd_limit=$(ulimit -H -n)
+ if [ $? -eq 0 ]; then
+ # If desired_fd is 'maximum' or 'max', set it to the hard limit.
+ if [ "$desired_fd" = "maximum" ] || [ "$desired_fd" = "max" ]; then
+ desired_fd="$max_fd_limit"
+ fi
+
+ # Check if desired_fd is less than or equal to max_fd_limit.
+ if [ "$desired_fd" -le "$max_fd_limit" ]; then
+ ulimit -n "$desired_fd"
+ if [ $? -ne 0 ]; then
+ echo "Warning: Could not set maximum file descriptor limit to $desired_fd"
+ fi
+ else
+ echo "Warning: Desired file descriptor limit ($desired_fd) is greater than the hard limit ($max_fd_limit)"
+ fi
+ else
+ echo "Warning: Could not query the maximum file descriptor hard limit."
+ fi
+ else
+ echo "Warning: Not attempting to modify file descriptor limit on Cygwin or Darwin."
+ fi
+}
+
+
+function openim::util::gen_os_arch() {
+ # Get the current operating system and architecture
+ OS=$(uname -s | tr '[:upper:]' '[:lower:]')
+ ARCH=$(uname -m)
+
+ # Select the repository home directory based on the operating system and architecture
+ if [[ "$OS" == "darwin" ]]; then
+ if [[ "$ARCH" == "x86_64" ]]; then
+ REPO_DIR="darwin/amd64"
+ else
+ REPO_DIR="darwin/386"
+ fi
+ elif [[ "$OS" == "linux" ]]; then
+ if [[ "$ARCH" == "x86_64" ]]; then
+ REPO_DIR="linux/amd64"
+ elif [[ "$ARCH" == "arm64" ]]; then
+ REPO_DIR="linux/arm64"
+ elif [[ "$ARCH" == "mips64" ]]; then
+ REPO_DIR="linux/mips64"
+ elif [[ "$ARCH" == "mips64le" ]]; then
+ REPO_DIR="linux/mips64le"
+ elif [[ "$ARCH" == "ppc64le" ]]; then
+ REPO_DIR="linux/ppc64le"
+ elif [[ "$ARCH" == "s390x" ]]; then
+ REPO_DIR="linux/s390x"
+ else
+ REPO_DIR="linux/386"
+ fi
+ elif [[ "$OS" == "windows" ]]; then
+ if [[ "$ARCH" == "x86_64" ]]; then
+ REPO_DIR="windows/amd64"
+ else
+ REPO_DIR="windows/386"
+ fi
+ else
+ echo -e "${RED_PREFIX}Unsupported OS: $OS${COLOR_SUFFIX}"
+ exit 1
+ fi
+}
+
+if [[ "$*" =~ openim::util:: ]];then
+ eval $*
+fi
diff --git a/scripts/make-rules/common.mk b/scripts/make-rules/common.mk
index c56f9f071..5fda9b927 100644
--- a/scripts/make-rules/common.mk
+++ b/scripts/make-rules/common.mk
@@ -73,7 +73,8 @@ endif
ifeq ($(origin VERSION), undefined)
# VERSION := $(shell git describe --tags --always --match='v*')
# git describe --tags --always --match="v*" --dirty
-VERSION := $(shell git describe --tags --always --match="v*" --dirty | sed 's/-/./g') #v2.3.3.631.g00abdc9b.dirty
+# VERSION := $(shell git describe --tags --always --match="v*" --dirty | sed 's/-/./g') #v2.3.3.631.g00abdc9b.dirty
+VERSION := $(shell git describe --tags --always --match='v*')
# v2.3.3: git tag
endif
@@ -100,7 +101,7 @@ endif
# The OS must be linux when building docker images
# PLATFORMS ?= linux_amd64 linux_arm64
# The OS can be linux/windows/darwin when building binaries
-PLATFORMS ?= linux_s390x linux_mips64 linux_mips64le darwin_amd64 windows_amd64 linux_amd64 linux_arm64 linux_ppc64le # wasip1_wasm
+PLATFORMS ?= linux_s390x linux_mips64 linux_mips64le darwin_amd64 darwin_arm64 windows_amd64 linux_amd64 linux_arm64 linux_ppc64le # wasip1_wasm
# set a specific PLATFORM, defaults to the host platform
ifeq ($(origin PLATFORM), undefined)
diff --git a/scripts/make-rules/tools.mk b/scripts/make-rules/tools.mk
index 7fe7305fb..5f076d6e7 100644
--- a/scripts/make-rules/tools.mk
+++ b/scripts/make-rules/tools.mk
@@ -146,7 +146,7 @@ install.github-release:
# amd64
.PHONY: install.coscli
install.coscli:
- @wget -q https://ghproxy.com/https://github.com/tencentyun/coscli/releases/download/v0.13.0-beta/coscli-linux -O ${TOOLS_DIR}/coscli
+ @wget -q https://github.com/tencentyun/coscli/releases/download/v0.19.0-beta/coscli-linux -O ${TOOLS_DIR}/coscli
@chmod +x ${TOOLS_DIR}/coscli
## install.coscmd: Install coscmd, used to upload files to cos
diff --git a/scripts/release.sh b/scripts/release.sh
index 9e1f99bc4..042a6c3a0 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -13,27 +13,138 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-
+# Description:
+# This script automates the process of building and releasing OpenIM,
+# including tasks like setting up the environment, verifying prerequisites,
+# building commands, packaging tarballs, uploading tarballs, creating GitHub
+# releases, and generating changelogs.
+#
+# Usage:
+# ./scripts/release.sh [options]
+# Options include:
+# -h, --help : Show help message
+# -se, --setup-env : Execute setup environment
+# -vp, --verify-prereqs : Execute prerequisites verification
+# -bc, --build-command : Execute build command
+# -bi, --build-image : Execute build image (default: not executed)
+# -pt, --package-tarballs : Execute package tarballs
+# -ut, --upload-tarballs : Execute upload tarballs
+# -gr, --github-release : Execute GitHub release
+# -gc, --generate-changelog: Execute generate changelog
+#
+# This script can also be executed via the 'make release' command as an alternative.
+#
+# Dependencies:
+# This script depends on external scripts found in the 'scripts' directory and
+# assumes the presence of necessary tools and permissions for building and
+# releasing software.
+#
+# Note:
+# The script uses standard bash script practices with error handling,
+# and it defaults to executing all steps if no specific option is provided.
+#
# Build a OpenIM release. This will build the binaries, create the Docker
# images and other build artifacts.
+# Build a OpenIM release. This script supports various flags for flexible execution control.
set -o errexit
set -o nounset
set -o pipefail
-
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${OPENIM_ROOT}/scripts/common.sh"
source "${OPENIM_ROOT}/scripts/lib/release.sh"
OPENIM_RELEASE_RUN_TESTS=${OPENIM_RELEASE_RUN_TESTS-y}
-openim::golang::setup_env
-openim::build::verify_prereqs
-openim::release::verify_prereqs
-#openim::build::build_image
-openim::build::build_command
-openim::release::package_tarballs
-openim::release::updload_tarballs
-git push origin ${VERSION}
-#openim::release::github_release
-#openim::release::generate_changelog
+# Function to show help message
+show_help() {
+ echo "Usage: $(basename $0) [options]"
+ echo "Options:"
+ echo " -h, --help Show this help message"
+ echo " -se, --setup-env Execute setup environment"
+ echo " -vp, --verify-prereqs Execute prerequisites verification"
+ echo " -bc, --build-command Execute build command"
+ echo " -bi, --build-image Execute build image (default: not executed)"
+ echo " -pt, --package-tarballs Execute package tarballs"
+ echo " -ut, --upload-tarballs Execute upload tarballs"
+ echo " -gr, --github-release Execute GitHub release"
+ echo " -gc, --generate-changelog Execute generate changelog"
+}
+
+# Initialize all actions to false
+perform_setup_env=false
+perform_verify_prereqs=false
+perform_build_command=false
+perform_build_image=false # New flag for build image
+perform_package_tarballs=false
+perform_upload_tarballs=false
+perform_github_release=false
+perform_generate_changelog=false
+
+# Process command-line arguments
+while getopts "hsevpbciptutgrgc-" opt; do
+ case "${opt}" in
+ h) show_help; exit 0 ;;
+ se) perform_setup_env=true ;;
+ vp) perform_verify_prereqs=true ;;
+ bc) perform_build_command=true ;;
+ bi) perform_build_image=true ;; # Handling new option
+ pt) perform_package_tarballs=true ;;
+ ut) perform_upload_tarballs=true ;;
+ gr) perform_github_release=true ;;
+ gc) perform_generate_changelog=true ;;
+ --) case "${OPTARG}" in
+ help) show_help; exit 0 ;;
+ setup-env) perform_setup_env=true ;;
+ verify-prereqs) perform_verify_prereqs=true ;;
+ build-command) perform_build_command=true ;;
+ build-image) perform_build_image=true ;; # Handling new long option
+ package-tarballs) perform_package_tarballs=true ;;
+ upload-tarballs) perform_upload_tarballs=true ;;
+ github-release) perform_github_release=true ;;
+ generate-changelog) perform_generate_changelog=true ;;
+ *) echo "Invalid option: --${OPTARG}"; show_help; exit 1 ;;
+ esac ;;
+ *) show_help; exit 1 ;;
+ esac
+done
+
+# Enable all actions by default if no options are provided
+if [ "$#" -eq 0 ]; then
+ perform_setup_env=true
+ perform_verify_prereqs=true
+ perform_build_command=true
+ perform_package_tarballs=true
+ perform_upload_tarballs=true
+ perform_github_release=true
+ perform_generate_changelog=true
+ # TODO: Not enabling build_image by default
+ # perform_build_image=true
+fi
+
+# Function to perform actions
+perform_action() {
+ local flag=$1
+ local message=$2
+ local command=$3
+
+ if [ "$flag" == true ]; then
+ openim::log::info "## $message..."
+ if ! $command; then
+ openim::log::errexit "Error in $message"
+ fi
+ fi
+}
+
+echo "Starting script execution..."
+
+perform_action $perform_setup_env "Setting up environment" "openim::golang::setup_env"
+perform_action $perform_verify_prereqs "Verifying prerequisites" "openim::build::verify_prereqs && openim::release::verify_prereqs"
+perform_action $perform_build_command "Executing build command" "openim::build::build_command"
+perform_action $perform_build_image "Building image" "openim::build::build_image"
+perform_action $perform_package_tarballs "Packaging tarballs" "openim::release::package_tarballs"
+perform_action $perform_upload_tarballs "Uploading tarballs" "openim::release::upload_tarballs"
+perform_action $perform_github_release "Creating GitHub release" "openim::release::github_release"
+perform_action $perform_generate_changelog "Generating changelog" "openim::release::generate_changelog"
+
+openim::log::success "OpenIM Relase Script Execution Completed."
diff --git a/scripts/stop-all.sh b/scripts/stop-all.sh
index 090c48b0d..692d2d1e4 100755
--- a/scripts/stop-all.sh
+++ b/scripts/stop-all.sh
@@ -34,4 +34,13 @@ openim::util::stop_services_on_ports ${OPENIM_SERVER_PORT_LISTARIES[@]}
echo -e "\n++ Stop all processes in the path ${OPENIM_OUTPUT_HOSTBIN}"
-openim::util::stop_services_with_name "${OPENIM_OUTPUT_HOSTBIN}"
\ No newline at end of file
+openim::util::stop_services_with_name "${OPENIM_OUTPUT_HOSTBIN}"
+
+echo -n "Stopping services 15 seconds."
+for i in {1..15}; do
+ echo -n "."
+ sleep 1
+done
+echo -e "\nServices stopped."
+
+openim::log::success "✨ Wait 15 seconds for all processes to be killed"
\ No newline at end of file
diff --git a/scripts/update-generated-docs.sh b/scripts/update-generated-docs.sh
index 008cf63ed..93f0f86c1 100755
--- a/scripts/update-generated-docs.sh
+++ b/scripts/update-generated-docs.sh
@@ -23,7 +23,7 @@ set -o nounset
set -o pipefail
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
-source "${OPENIM_ROOT}/hack/lib/init.sh"
+source "${OPENIM_ROOT}/scripts/lib/init.sh"
openim::golang::setup_env
diff --git a/scripts/update-yamlfmt.sh b/scripts/update-yamlfmt.sh
index 1e4ad513f..90ec8aa62 100755
--- a/scripts/update-yamlfmt.sh
+++ b/scripts/update-yamlfmt.sh
@@ -19,9 +19,9 @@ set -o nounset
set -o pipefail
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
-source "${OPENIM_ROOT}/hack/lib/init.sh"
+source "${OPENIM_ROOT}/scripts/lib/init.sh"
-kube::golang::setup_env
+openim::golang::setup_env
cd "${OPENIM_ROOT}"
@@ -40,4 +40,4 @@ find_files() {
}
export GO111MODULE=on
-find_files | xargs go run tools/yamlfmt/main.go
\ No newline at end of file
+find_files | xargs go run tools/yamlfmt/yamlfmt.go
\ No newline at end of file
diff --git a/scripts/verify-shellcheck.sh b/scripts/verify-shellcheck.sh
index 12162dd8b..de860115e 100755
--- a/scripts/verify-shellcheck.sh
+++ b/scripts/verify-shellcheck.sh
@@ -113,7 +113,7 @@ if ${HAVE_SHELLCHECK}; then
else
openim::log::info "Using shellcheck ${SHELLCHECK_VERSION} docker image."
"${DOCKER}" run \
- --rm -v ""${OPENIM_ROOT}":"${OPENIM_ROOT}"" -w "${OPENIM_ROOT}" \
+ --rm -v "${OPENIM_ROOT}:"${OPENIM_ROOT}"" -w "${OPENIM_ROOT}" \
"${SHELLCHECK_IMAGE}" \
shellcheck "${SHELLCHECK_OPTIONS[@]}" "${all_shell_scripts[@]}" >&2 || res=$?
fi
diff --git a/scripts/verify-spelling.sh b/scripts/verify-spelling.sh
index f3ed7886d..487c68cde 100755
--- a/scripts/verify-spelling.sh
+++ b/scripts/verify-spelling.sh
@@ -30,12 +30,12 @@ export GOBIN="${KUBE_OUTPUT_BINPATH}"
PATH="${GOBIN}:${PATH}"
# Install tools we need
-pushd ""${OPENIM_ROOT}"/tools" >/dev/null
+pushd "${OPENIM_ROOT}/tools" >/dev/null
GO111MODULE=on go install github.com/client9/misspell/cmd/misspell
popd >/dev/null
# Spell checking
# All the skipping files are defined in scripts/.spelling_failures
-skipping_file=""${OPENIM_ROOT}"/scripts/.spelling_failures"
+skipping_file="${OPENIM_ROOT}/scripts/.spelling_failures"
failing_packages=$(sed "s| | -e |g" "${skipping_file}")
git ls-files | grep -v -e "${failing_packages}" | xargs misspell -i "Creater,creater,ect" -error -o stderr
diff --git a/scripts/verify-yamlfmt.sh b/scripts/verify-yamlfmt.sh
index 82e1c528d..3d0a0180d 100755
--- a/scripts/verify-yamlfmt.sh
+++ b/scripts/verify-yamlfmt.sh
@@ -36,13 +36,13 @@ openim::util::trap_add "git worktree remove -f ${_tmpdir}" EXIT
cd "${_tmpdir}"
# Format YAML files
-hack/update-yamlfmt.sh
+scripts/update-yamlfmt.sh
# Test for diffs
diffs=$(git status --porcelain | wc -l)
if [[ ${diffs} -gt 0 ]]; then
echo "YAML files need to be formatted" >&2
git diff
- echo "Please run 'hack/update-yamlfmt.sh'" >&2
+ echo "Please run 'scripts/update-yamlfmt.sh'" >&2
exit 1
fi
\ No newline at end of file
diff --git a/test/typecheck/typecheck.go b/test/typecheck/typecheck.go
index 83e3c63ed..8f353881b 100644
--- a/test/typecheck/typecheck.go
+++ b/test/typecheck/typecheck.go
@@ -47,23 +47,27 @@ var (
crossPlatforms = []string{
"linux/amd64", "windows/386",
"darwin/amd64", "darwin/arm64",
- "linux/arm", "linux/386",
+ "linux/386",
"windows/amd64", "linux/arm64",
"linux/ppc64le", "linux/s390x",
"windows/arm64",
}
+ // "linux/arm",
+
// directories we always ignore
standardIgnoreDirs = []string{
// Staging code is symlinked from vendor/k8s.io, and uses import
// paths as if it were inside of vendor/. It fails typechecking
// inside of staging/, but works when typechecked as part of vendor/.
"staging",
+ "components",
// OS-specific vendor code tends to be imported by OS-specific
// packages. We recursively typecheck imported vendored packages for
// each OS, but don't typecheck everything for every OS.
"vendor",
"_output",
+ "OpenIMSKD/tools",
// This is a weird one. /testdata/ is *mostly* ignored by Go,
// and this translates to kubernetes/vendor not working.
// edit/record.go doesn't compile without gopkg.in/yaml.v2
@@ -71,7 +75,7 @@ var (
"pkg/kubectl/cmd/testdata/edit",
// Tools we use for maintaining the code base but not necessarily
// ship as part of the release
- "hack/tools",
+ "sopenim::golang::setup_env:tools/yamlfmt/yamlfmt.go:tools",
}
)
diff --git a/test/wrktest.sh b/test/wrktest.sh
index 01617676a..a97ebf043 100755
--- a/test/wrktest.sh
+++ b/test/wrktest.sh
@@ -45,7 +45,7 @@ openim::wrk::setup() {
cmd="wrk -t${threads} -d${duration} -T30s --latency"
}
-# Print usage infomation
+# Print usage
openim::wrk::usage() {
cat << EOF
diff --git a/tools/changelog/changelog.go b/tools/changelog/changelog.go
index 17a9e5404..ff9a7eab9 100644
--- a/tools/changelog/changelog.go
+++ b/tools/changelog/changelog.go
@@ -61,7 +61,7 @@ var (
{"template", "template"},
{"etcd", "server"},
{"pod", "node"},
- {"hack/", "hack"},
+ {"scripts/", "hack"},
{"e2e", "test"},
{"integration", "test"},
{"cluster", "cluster"},
diff --git a/tools/component/component.go b/tools/component/component.go
index 62f2c60ac..220b845ee 100644
--- a/tools/component/component.go
+++ b/tools/component/component.go
@@ -33,19 +33,20 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
- "github.com/minio/minio-go/v7/pkg/credentials"
"github.com/minio/minio-go/v7"
- "github.com/redis/go-redis/v9"
- "gopkg.in/yaml.v3"
+ "github.com/minio/minio-go/v7/pkg/credentials"
+ "github.com/redis/go-redis/v9"
+ "gopkg.in/yaml.v3"
)
const (
// defaultCfgPath is the default path of the configuration file.
defaultCfgPath = "../../../../../config/config.yaml"
minioHealthCheckDuration = 1
- maxRetry = 100
+ maxRetry = 300
componentStartErrCode = 6000
configErrCode = 6001
+ mongoConnTimeout = 30 * time.Second
)
const (
@@ -55,8 +56,7 @@ const (
)
var (
- cfgPath = flag.String("c", defaultCfgPath, "Path to the configuration file")
-
+ cfgPath = flag.String("c", defaultCfgPath, "Path to the configuration file")
ErrComponentStart = errs.NewCodeError(componentStartErrCode, "ComponentStartErr")
ErrConfig = errs.NewCodeError(configErrCode, "Config file is incorrect")
)
@@ -95,7 +95,7 @@ func main() {
for i := 0; i < maxRetry; i++ {
if i != 0 {
- time.Sleep(3 * time.Second)
+ time.Sleep(1 * time.Second)
}
fmt.Printf("Checking components Round %v...\n", i+1)
@@ -141,19 +141,25 @@ func getEnv(key, fallback string) string {
return fallback
}
-// checkMongo checks the MongoDB connection
+// checkMongo checks the MongoDB connection without retries
func checkMongo() (string, error) {
- // Use environment variables or fallback to config
uri := getEnv("MONGO_URI", buildMongoURI())
- client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
+ ctx, cancel := context.WithTimeout(context.Background(), mongoConnTimeout)
+ defer cancel()
+
str := "ths addr is:" + strings.Join(config.Config.Mongo.Address, ",")
+
+ client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
if err != nil {
return "", errs.Wrap(errStr(err, str))
}
- defer client.Disconnect(context.TODO())
+ defer client.Disconnect(context.Background())
+
+ ctx, cancel = context.WithTimeout(context.Background(), mongoConnTimeout)
+ defer cancel()
- if err = client.Ping(context.TODO(), nil); err != nil {
+ if err = client.Ping(ctx, nil); err != nil {
return "", errs.Wrap(errStr(err, str))
}
@@ -222,8 +228,8 @@ func checkMinio() (string, error) {
defer cancel()
if minioClient.IsOffline() {
- // str := fmt.Sprintf("Minio server is offline;%s", str)
- // return "", ErrComponentStart.Wrap(str)
+ str := fmt.Sprintf("Minio server is offline;%s", str)
+ return "", ErrComponentStart.Wrap(str)
}
// Check for localhost in API URL and Minio SignEndpoint
diff --git a/tools/formitychecker/README.md b/tools/formitychecker/README.md
new file mode 100644
index 000000000..7cabf8a66
--- /dev/null
+++ b/tools/formitychecker/README.md
@@ -0,0 +1,102 @@
+# Development of a Go-Based Conformity Checker for Project File and Directory Naming Standards
+
+### 1. Project Overview
+
+#### Project Name
+
+- `GoConformityChecker`
+
+#### Functionality Description
+
+- Checks if the file and subdirectory names in a specified directory adhere to specific naming conventions.
+- Supports specific file types (e.g., `.go`, `.yml`, `.yaml`, `.md`, `.sh`, etc.).
+- Allows users to specify directories to be checked and directories to be ignored.
+- More read https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md
+
+#### Naming Conventions
+
+- Go files: Only underscores are allowed.
+- YAML, YML, and Markdown files: Only hyphens are allowed.
+- Directories: Only underscores are allowed.
+
+### 2. File Structure
+
+- `main.go`: Entry point of the program, handles command-line arguments.
+- `checker/checker.go`: Contains the core logic.
+- `config/config.go`: Parses and stores configuration information.
+
+### 3. Core Code Design
+
+#### main.go
+
+- Parses command-line arguments, including the directory to be checked and directories to be ignored.
+- Calls the `checker` module for checking.
+
+#### config.go
+
+- Defines a configuration structure, such as directories to check and ignore.
+
+#### checker.go
+
+- Iterates through the specified directory.
+- Applies different naming rules based on file types and directory names.
+- Records files or directories that do not conform to the standards.
+
+### 4. Pseudocode Example
+
+#### main.go
+
+```go
+package main
+
+import (
+ "flag"
+ "fmt"
+ "GoConformityChecker/checker"
+)
+
+func main() {
+ // Parse command-line arguments
+ var targetDir string
+ var ignoreDirs string
+ flag.StringVar(&targetDir, "target", ".", "Directory to check")
+ flag.StringVar(&ignoreDirs, "ignore", "", "Directories to ignore")
+ flag.Parse()
+
+ // Call the checker
+ err := checker.CheckDirectory(targetDir, ignoreDirs)
+ if err != nil {
+ fmt.Println("Error:", err)
+ }
+}
+```
+
+#### checker.go
+
+```go
+package checker
+
+import (
+ // Import necessary packages
+)
+
+func CheckDirectory(targetDir, ignoreDirs string) error {
+ // Iterate through the directory, applying rules to check file and directory names
+ // Return any found errors or non-conformities
+ return nil
+}
+```
+
+### 5. Implementation Details
+
+- **File and Directory Traversal**: Use Go's `path/filepath` package to traverse directories and subdirectories.
+- **Naming Rules Checking**: Apply different regex expressions for naming checks based on file extensions.
+- **Error Handling and Reporting**: Record files or directories that do not conform and report to the user.
+
+### 6. Future Development and Extensions
+
+- Support more file types and naming rules.
+- Provide more detailed error reports, such as showing line numbers and specific naming mistakes.
+- Add a graphical or web interface for non-command-line users.
+
+The above is an overview of the entire project's design. Following this design, specific coding implementation can begin. Note that the actual implementation may need adjustments based on real-world conditions.
\ No newline at end of file
diff --git a/tools/formitychecker/checker/checker.go b/tools/formitychecker/checker/checker.go
new file mode 100644
index 000000000..187b509bc
--- /dev/null
+++ b/tools/formitychecker/checker/checker.go
@@ -0,0 +1,97 @@
+package checker
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+
+ "github.com/openimsdk/open-im-server/tools/formitychecker/config"
+)
+
+var (
+ underscoreRegex = regexp.MustCompile(`^[a-zA-Z0-9_]+\.[a-zA-Z0-9]+$`)
+ hyphenRegex = regexp.MustCompile(`^[a-zA-Z0-9\-]+\.[a-zA-Z0-9]+$`)
+)
+
+// CheckDirectoCheckDirectoryries initiates the checking process for the specified directories using configuration from config.Config.
+func CheckDirectory(cfg *config.Config) error {
+ ignoreMap := make(map[string]struct{})
+ for _, dir := range cfg.IgnoreDirs {
+ ignoreMap[dir] = struct{}{}
+ }
+
+ for _, targetDir := range cfg.TargetDirs {
+ err := filepath.Walk(targetDir, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ // Skip if the directory is in the ignore list
+ dirName := filepath.Base(filepath.Dir(path))
+ if _, ok := ignoreMap[dirName]; ok && info.IsDir() {
+ return filepath.SkipDir
+ }
+
+ // Check the naming convention
+ if err := checkNamingConvention(path, info); err != nil {
+ fmt.Println(err)
+ }
+
+ return nil
+ })
+
+ if err != nil {
+ return fmt.Errorf("error checking directory '%s': %w", targetDir, err)
+ }
+ }
+
+ return nil
+}
+
+// checkNamingConvention checks if the file or directory name conforms to the standard naming conventions.
+func checkNamingConvention(path string, info os.FileInfo) error {
+ fileName := info.Name()
+
+ // Handle special cases for directories like .git
+ if info.IsDir() && strings.HasPrefix(fileName, ".") {
+ return nil // Skip special directories
+ }
+
+ // Extract the main part of the name (without extension for files)
+ mainName := fileName
+ if !info.IsDir() {
+ mainName = strings.TrimSuffix(fileName, filepath.Ext(fileName))
+ }
+
+ // Determine the type of file and apply corresponding naming rule
+ switch {
+ case info.IsDir():
+ if !isValidName(mainName, "_") { // Directory names must only contain underscores
+ return fmt.Errorf("!!! invalid directory name: %s", path)
+ }
+ case strings.HasSuffix(fileName, ".go"):
+ if !isValidName(mainName, "_") { // Go files must only contain underscores
+ return fmt.Errorf("!!! invalid Go file name: %s", path)
+ }
+ case strings.HasSuffix(fileName, ".yml"), strings.HasSuffix(fileName, ".yaml"), strings.HasSuffix(fileName, ".md"):
+ if !isValidName(mainName, "-") { // YML, YAML, and Markdown files must only contain hyphens
+ return fmt.Errorf("!!! invalid file name: %s", path)
+ }
+ }
+
+ return nil
+}
+
+// isValidName checks if the file name conforms to the specified rule (underscore or hyphen).
+func isValidName(name, charType string) bool {
+ switch charType {
+ case "_":
+ return underscoreRegex.MatchString(name)
+ case "-":
+ return hyphenRegex.MatchString(name)
+ default:
+ return false
+ }
+}
diff --git a/tools/formitychecker/config/config.go b/tools/formitychecker/config/config.go
new file mode 100644
index 000000000..95bcee346
--- /dev/null
+++ b/tools/formitychecker/config/config.go
@@ -0,0 +1,27 @@
+package config
+
+import (
+ "strings"
+)
+
+// Config holds all the configuration parameters for the checker.
+type Config struct {
+ TargetDirs []string // Directories to check
+ IgnoreDirs []string // Directories to ignore
+}
+
+// NewConfig creates and returns a new Config instance.
+func NewConfig(targetDirs, ignoreDirs string) *Config {
+ return &Config{
+ TargetDirs: parseDirs(targetDirs),
+ IgnoreDirs: parseDirs(ignoreDirs),
+ }
+}
+
+// parseDirs splits a comma-separated string into a slice of directory names.
+func parseDirs(dirs string) []string {
+ if dirs == "" {
+ return nil
+ }
+ return strings.Split(dirs, ",")
+}
diff --git a/tools/formitychecker/formitychecker.go b/tools/formitychecker/formitychecker.go
new file mode 100644
index 000000000..d078009b6
--- /dev/null
+++ b/tools/formitychecker/formitychecker.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+
+ "github.com/openimsdk/open-im-server/tools/formitychecker/checker"
+ "github.com/openimsdk/open-im-server/tools/formitychecker/config"
+)
+
+func main() {
+ defaultTargetDirs := "."
+ defaultIgnoreDirs := "components,.git"
+
+ var targetDirs string
+ var ignoreDirs string
+ flag.StringVar(&targetDirs, "target", defaultTargetDirs, "Directories to check (default: current directory)")
+ flag.StringVar(&ignoreDirs, "ignore", defaultIgnoreDirs, "Directories to ignore (default: A/, B/)")
+ flag.Parse()
+
+ conf := config.NewConfig(targetDirs, ignoreDirs)
+
+ err := checker.CheckDirectory(conf)
+ if err != nil {
+ fmt.Println("Error:", err)
+ }
+}
diff --git a/tools/formitychecker/go.mod b/tools/formitychecker/go.mod
new file mode 100644
index 000000000..698b77647
--- /dev/null
+++ b/tools/formitychecker/go.mod
@@ -0,0 +1,3 @@
+module github.com/openimsdk/open-im-server/tools/formitychecker
+
+go 1.19
diff --git a/tools/imctl/imctl.go b/tools/imctl/imctl.go
new file mode 100644
index 000000000..1a501cafc
--- /dev/null
+++ b/tools/imctl/imctl.go
@@ -0,0 +1,8 @@
+package main
+
+import "fmt"
+
+func main() {
+
+ fmt.Println("imctl")
+}
diff --git a/tools/up35/pkg/convert.go b/tools/up35/pkg/convert.go
index 24d3a2781..53ada0e04 100644
--- a/tools/up35/pkg/convert.go
+++ b/tools/up35/pkg/convert.go
@@ -17,16 +17,16 @@ package pkg
import (
"time"
- mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
- mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
- mongoModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
- mysqlModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mysql"
+ mongomodel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+ mysqlmodel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
+ mongomodelrtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table"
+ mysqlmodelrtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mysql"
)
type convert struct{}
-func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel {
- return mongoModel.UserModel{
+func (convert) User(v mysqlmodel.UserModel) mongomodel.UserModel {
+ return mongomodel.UserModel{
UserID: v.UserID,
Nickname: v.Nickname,
FaceURL: v.FaceURL,
@@ -37,8 +37,8 @@ func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel {
}
}
-func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel {
- return mongoModel.FriendModel{
+func (convert) Friend(v mysqlmodel.FriendModel) mongomodel.FriendModel {
+ return mongomodel.FriendModel{
OwnerUserID: v.OwnerUserID,
FriendUserID: v.FriendUserID,
Remark: v.Remark,
@@ -49,8 +49,8 @@ func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel {
}
}
-func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendRequestModel {
- return mongoModel.FriendRequestModel{
+func (convert) FriendRequest(v mysqlmodel.FriendRequestModel) mongomodel.FriendRequestModel {
+ return mongomodel.FriendRequestModel{
FromUserID: v.FromUserID,
ToUserID: v.ToUserID,
HandleResult: v.HandleResult,
@@ -63,8 +63,8 @@ func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendR
}
}
-func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel {
- return mongoModel.BlackModel{
+func (convert) Black(v mysqlmodel.BlackModel) mongomodel.BlackModel {
+ return mongomodel.BlackModel{
OwnerUserID: v.OwnerUserID,
BlockUserID: v.BlockUserID,
CreateTime: v.CreateTime,
@@ -74,8 +74,8 @@ func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel {
}
}
-func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel {
- return mongoModel.GroupModel{
+func (convert) Group(v mysqlmodel.GroupModel) mongomodel.GroupModel {
+ return mongomodel.GroupModel{
GroupID: v.GroupID,
GroupName: v.GroupName,
Notification: v.Notification,
@@ -94,8 +94,8 @@ func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel {
}
}
-func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMemberModel {
- return mongoModel.GroupMemberModel{
+func (convert) GroupMember(v mysqlmodel.GroupMemberModel) mongomodel.GroupMemberModel {
+ return mongomodel.GroupMemberModel{
GroupID: v.GroupID,
UserID: v.UserID,
Nickname: v.Nickname,
@@ -110,8 +110,8 @@ func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMember
}
}
-func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequestModel {
- return mongoModel.GroupRequestModel{
+func (convert) GroupRequest(v mysqlmodel.GroupRequestModel) mongomodel.GroupRequestModel {
+ return mongomodel.GroupRequestModel{
UserID: v.UserID,
GroupID: v.GroupID,
HandleResult: v.HandleResult,
@@ -126,8 +126,8 @@ func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequ
}
}
-func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.ConversationModel {
- return mongoModel.ConversationModel{
+func (convert) Conversation(v mysqlmodel.ConversationModel) mongomodel.ConversationModel {
+ return mongomodel.ConversationModel{
OwnerUserID: v.OwnerUserID,
ConversationID: v.ConversationID,
ConversationType: v.ConversationType,
@@ -149,9 +149,9 @@ func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.Conversat
}
}
-func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
- return func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
- return mongoModel.ObjectModel{
+func (convert) Object(engine string) func(v mysqlmodel.ObjectModel) mongomodel.ObjectModel {
+ return func(v mysqlmodel.ObjectModel) mongomodel.ObjectModel {
+ return mongomodel.ObjectModel{
Name: v.Name,
UserID: v.UserID,
Hash: v.Hash,
@@ -165,8 +165,8 @@ func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.O
}
}
-func (convert) Log(v mysqlModel.Log) mongoModel.LogModel {
- return mongoModel.LogModel{
+func (convert) Log(v mysqlmodel.Log) mongomodel.LogModel {
+ return mongomodel.LogModel{
LogID: v.LogID,
Platform: v.Platform,
UserID: v.UserID,
@@ -179,8 +179,8 @@ func (convert) Log(v mysqlModel.Log) mongoModel.LogModel {
}
}
-func (convert) SignalModel(v mysqlModelRtc.SignalModel) mongoModelRtc.SignalModel {
- return mongoModelRtc.SignalModel{
+func (convert) SignalModel(v mysqlmodelrtc.SignalModel) mongomodelrtc.SignalModel {
+ return mongomodelrtc.SignalModel{
SID: v.SID,
InviterUserID: v.InviterUserID,
CustomData: v.CustomData,
@@ -202,8 +202,8 @@ func (convert) SignalModel(v mysqlModelRtc.SignalModel) mongoModelRtc.SignalMode
}
}
-func (convert) SignalInvitationModel(v mysqlModelRtc.SignalInvitationModel) mongoModelRtc.SignalInvitationModel {
- return mongoModelRtc.SignalInvitationModel{
+func (convert) SignalInvitationModel(v mysqlmodelrtc.SignalInvitationModel) mongomodelrtc.SignalInvitationModel {
+ return mongomodelrtc.SignalInvitationModel{
SID: v.SID,
UserID: v.UserID,
Status: v.Status,
@@ -212,8 +212,8 @@ func (convert) SignalInvitationModel(v mysqlModelRtc.SignalInvitationModel) mong
}
}
-func (convert) Meeting(v mysqlModelRtc.MeetingInfo) mongoModelRtc.MeetingInfo {
- return mongoModelRtc.MeetingInfo{
+func (convert) Meeting(v mysqlmodelrtc.MeetingInfo) mongomodelrtc.MeetingInfo {
+ return mongomodelrtc.MeetingInfo{
RoomID: v.RoomID,
MeetingName: v.MeetingName,
HostUserID: v.HostUserID,
@@ -225,16 +225,16 @@ func (convert) Meeting(v mysqlModelRtc.MeetingInfo) mongoModelRtc.MeetingInfo {
}
}
-func (convert) MeetingInvitationInfo(v mysqlModelRtc.MeetingInvitationInfo) mongoModelRtc.MeetingInvitationInfo {
- return mongoModelRtc.MeetingInvitationInfo{
+func (convert) MeetingInvitationInfo(v mysqlmodelrtc.MeetingInvitationInfo) mongomodelrtc.MeetingInvitationInfo {
+ return mongomodelrtc.MeetingInvitationInfo{
RoomID: v.RoomID,
UserID: v.UserID,
CreateTime: v.CreateTime,
}
}
-func (convert) MeetingVideoRecord(v mysqlModelRtc.MeetingVideoRecord) mongoModelRtc.MeetingVideoRecord {
- return mongoModelRtc.MeetingVideoRecord{
+func (convert) MeetingVideoRecord(v mysqlmodelrtc.MeetingVideoRecord) mongomodelrtc.MeetingVideoRecord {
+ return mongomodelrtc.MeetingVideoRecord{
RoomID: v.RoomID,
FileURL: v.FileURL,
CreateTime: v.CreateTime,
diff --git a/tools/up35/pkg/pkg.go b/tools/up35/pkg/pkg.go
index 6d16817ec..b7e7c01f5 100644
--- a/tools/up35/pkg/pkg.go
+++ b/tools/up35/pkg/pkg.go
@@ -29,14 +29,14 @@ import (
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
- gormMysql "gorm.io/driver/mysql"
+ gormmysql "gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
- rtcMgo "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/mgo"
+ rtcmgo "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/mgo"
)
const (
@@ -56,7 +56,7 @@ func InitConfig(path string) error {
func GetMysql() (*gorm.DB, error) {
conf := config.Config.Mysql
mysqlDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.Username, conf.Password, conf.Address[0], conf.Database)
- return gorm.Open(gormMysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard})
+ return gorm.Open(gormmysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard})
}
func GetMongo() (*mongo.Database, error) {
@@ -116,11 +116,11 @@ func Main(path string) error {
func() error { return NewTask(mysqlDB, mongoDB, mgo.NewS3Mongo, c.Object(config.Config.Object.Enable)) },
func() error { return NewTask(mysqlDB, mongoDB, mgo.NewLogMongo, c.Log) },
- func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewSignal, c.SignalModel) },
- func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewSignalInvitation, c.SignalInvitationModel) },
- func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeeting, c.Meeting) },
- func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeetingInvitation, c.MeetingInvitationInfo) },
- func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeetingRecord, c.MeetingVideoRecord) },
+ func() error { return NewTask(mysqlDB, mongoDB, rtcmgo.NewSignal, c.SignalModel) },
+ func() error { return NewTask(mysqlDB, mongoDB, rtcmgo.NewSignalInvitation, c.SignalInvitationModel) },
+ func() error { return NewTask(mysqlDB, mongoDB, rtcmgo.NewMeeting, c.Meeting) },
+ func() error { return NewTask(mysqlDB, mongoDB, rtcmgo.NewMeetingInvitation, c.MeetingInvitationInfo) },
+ func() error { return NewTask(mysqlDB, mongoDB, rtcmgo.NewMeetingRecord, c.MeetingVideoRecord) },
)
for _, task := range tasks {
diff --git a/tools/yamlfmt/OWNERS b/tools/yamlfmt/OWNERS
deleted file mode 100644
index b7a5428e7..000000000
--- a/tools/yamlfmt/OWNERS
+++ /dev/null
@@ -1,10 +0,0 @@
-# See the OWNERS docs at https://go.k8s.io/owners
-
-reviewers:
- - cubxxw
- - kubbot
-approvers:
- - cubxxw
-labels:
- - sig/testing
- - sig/contributor-experience
\ No newline at end of file
From 955520471fc47b2315cadc355ebb5c09026a81a9 Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Fri, 12 Jan 2024 18:58:29 +0800
Subject: [PATCH 066/110] Rename devcontainer.json to devcontainer.json (#1756)
---
{.devcontainer => .devcontainer}/devcontainer.json | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename {.devcontainer => .devcontainer}/devcontainer.json (100%)
diff --git a/.devcontainer /devcontainer.json b/.devcontainer/devcontainer.json
similarity index 100%
rename from .devcontainer /devcontainer.json
rename to .devcontainer/devcontainer.json
From 0375361294b4dbc320fd4a795b4f86d6a2491bed Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Fri, 12 Jan 2024 20:12:38 +0800
Subject: [PATCH 067/110] Rename README.md to README.md (#1757)
---
{.devcontainer => .devcontainer}/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename {.devcontainer => .devcontainer}/README.md (99%)
diff --git a/.devcontainer /README.md b/.devcontainer/README.md
similarity index 99%
rename from .devcontainer /README.md
rename to .devcontainer/README.md
index 7abba5ac1..24778f8ee 100644
--- a/.devcontainer /README.md
+++ b/.devcontainer/README.md
@@ -137,4 +137,4 @@ In addition, you can also configure Codespaces secrets on your personal profile
The container comes with VS Code Insiders installed. To run it from an Integrated Terminal use `VSCODE_IPC_HOOK_CLI= /usr/bin/code-insiders .`.
-[def]: https://www.realvnc.com/en/connect/download/viewer/
\ No newline at end of file
+[def]: https://www.realvnc.com/en/connect/download/viewer/
From a24eedb66d57c5301bc00b9b5d264acc412ad52a Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Fri, 12 Jan 2024 21:17:45 +0800
Subject: [PATCH 068/110] Update docker-compose.yml (#1759)
---
docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index de4b30d48..9496fe76a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -119,7 +119,7 @@ services:
- OPENIM_WEB_PORT=${OPENIM_WEB_PORT:-11001}
restart: always
ports:
- - "${OPENIM_WEB_PORT:-11001}:11001"
+ - "${OPENIM_WEB_PORT:-11001}:80"
networks:
server:
ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7}
From fdf055d328627a6bbc0053f11869f3f88a5e531a Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751@qq.com>
Date: Fri, 12 Jan 2024 22:02:56 +0800
Subject: [PATCH 069/110] fix: mac deployment (#1761)
---
scripts/lib/util.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/lib/util.sh b/scripts/lib/util.sh
index 1ec722d8f..f15a26346 100755
--- a/scripts/lib/util.sh
+++ b/scripts/lib/util.sh
@@ -311,7 +311,7 @@ openim::util::check_ports() {
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
# For macOS, use lsof
- info=$(lsof -i:"$port" | grep "\*:$port" || true)
+ info=$(lsof -P -i:"$port" | grep "LISTEN" || true)
fi
# Check if any process is using the port
From 98d36461677dc82b8fb9b1c3dad23ab565f9bbc6 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Sat, 13 Jan 2024 09:38:52 +0800
Subject: [PATCH 070/110] Stability Enhancement: Pin Docker Compose Images for
minio and openim-web (#1762)
* Update docker-compose.yml
* Update docker-compose.yml
* Update docker-compose.yml
---
docker-compose.yml | 53 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 50 insertions(+), 3 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 9496fe76a..78632f163 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -94,7 +94,7 @@ services:
ipv4_address: ${KAFKA_NETWORK_ADDRESS:-172.28.0.4}
minio:
- image: minio/minio:${MINIO_IMAGE_VERSION:-latest}
+ image: minio/minio:${MINIO_IMAGE_VERSION:-RELEASE.2024-01-11T07-46-16Z}
ports:
- "${MINIO_PORT:-10005}:9000"
- "9090:9090"
@@ -112,7 +112,7 @@ services:
ipv4_address: ${MINIO_NETWORK_ADDRESS:-172.28.0.6}
openim-web:
- image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:${OPENIM_WEB_IMAGE_VERSION:-latest}
+ image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:${OPENIM_WEB_IMAGE_VERSION:-v3.5.0-docker}
container_name: openim-web
environment:
- OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH:-/app/dist}
@@ -127,8 +127,55 @@ services:
### TODO: Uncomment, or deploy using openim docker: https://github.com/openimsdk/openim-docker
# Uncomment and configure the following services as needed
+ # openim-server:
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-server:${SERVER_IMAGE_VERSION:-main}
+ # container_name: openim-server
+ # ports:
+ # - "${OPENIM_WS_PORT:-10001}:${OPENIM_WS_PORT:-10001}"
+ # - "${API_OPENIM_PORT:-10002}:${API_OPENIM_PORT:-10002}"
+ # - "${API_PROM_PORT:-20100}:${API_PROM_PORT:-20100}"
+ # - "${USER_PROM_PORT:-20110}:${USER_PROM_PORT:-20110}"
+ # - "${FRIEND_PROM_PORT:-20120}:${FRIEND_PROM_PORT:-20120}"
+ # - "${MESSAGE_PROM_PORT:-20130}:${MESSAGE_PROM_PORT:-20130}"
+ # - "${MSG_GATEWAY_PROM_PORT:-20140}:${MSG_GATEWAY_PROM_PORT:-20140}"
+ # - "${GROUP_PROM_PORT:-20150}:${GROUP_PROM_PORT:-20150}"
+ # - "${AUTH_PROM_PORT:-20160}:${AUTH_PROM_PORT:-20160}"
+ # - "${PUSH_PROM_PORT:-20170}:${PUSH_PROM_PORT:-20170}"
+ # - "${CONVERSATION_PROM_PORT:-20230}:${CONVERSATION_PROM_PORT:-20230}"
+ # - "${RTC_PROM_PORT:-21300}:${RTC_PROM_PORT:-21300}"
+ # - "${THIRD_PROM_PORT:-21301}:${THIRD_PROM_PORT:-21301}"
+ # - "21400-21403:21400-21403"
+ # healthcheck:
+ # test: ["CMD", "/openim/openim-server/scripts/check-all.sh"]
+ # interval: 120s
+ # timeout: 30s
+ # retries: 5
+ # env_file:
+ # - .env
+ # environment:
+ # - OPENIM_IP=${OPENIM_IP:-127.0.0.1}
+ # volumes:
+ # - "${DATA_DIR:-./}/openim-server/logs:/openim/openim-server/logs"
+ # - "${DATA_DIR:-./}/openim-server/_output/logs:/openim/openim-server/_output/logs"
+ # - "${DATA_DIR:-./}/openim-server/config:/openim/openim-server/config"
+ # restart: always
+ # depends_on:
+ # - kafka
+ # - mysql
+ # - mongodb
+ # - redis
+ # - minio
+ # logging:
+ # driver: json-file
+ # options:
+ # max-size: "1g"
+ # max-file: "2"
+ # networks:
+ # server:
+ # ipv4_address: ${OPENIM_SERVER_NETWORK_ADDRESS:-172.28.0.8}
+
# openim-chat:
- # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-chat:${CHAT_IMAGE_VERSION:-latest}
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-chat:${CHAT_IMAGE_VERSION:-main}
# container_name: openim-chat
# healthcheck:
# test: ["CMD", "/openim/openim-chat/scripts/check_all.sh"]
From 64d6b0432087551313a8ea01eab9b28f204b6dfa Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Mon, 15 Jan 2024 16:39:44 +0800
Subject: [PATCH 071/110] feat: add openim docker compose deployment github
comment (#1769)
* feat: add openim v3.4 and v3.5 changelog
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add openim github comment
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix openim docker compose images version form github comment
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix openim docker compose images version form github comment
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
config/templates/env.template | 8 --------
deployments/templates/env-template.yaml | 4 ----
docker-compose.yml | 10 ++--------
scripts/install/environment.sh | 2 --
tools/openim-web/README.md | 1 -
5 files changed, 2 insertions(+), 23 deletions(-)
diff --git a/config/templates/env.template b/config/templates/env.template
index ffcec89e5..a606704c5 100644
--- a/config/templates/env.template
+++ b/config/templates/env.template
@@ -176,18 +176,10 @@ GRAFANA_PORT=13000
# ============ OpenIM Web ===============
# ======================================
-# Path to the OpenIM web distribution.
-# Default: OPENIM_WEB_DIST_PATH=/app/dist
-OPENIM_WEB_DIST_PATH=/app/dist
-
# Port on which OpenIM web service is running.
# Default: OPENIM_WEB_PORT=11001
OPENIM_WEB_PORT=11001
-# Address or hostname for the OpenIM web service.
-# Default: OPENIM_WEB_ADDRESS=172.28.0.1
-OPENIM_WEB_ADDRESS=172.28.0.7
-
# ======================================
# ========= OpenIM Server ==============
# ======================================
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index e7166ff2d..cbe900c19 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -171,10 +171,6 @@ GRAFANA_PORT=${GRAFANA_PORT}
# ============ OpenIM Web ===============
# ======================================
-# Path to the OpenIM web distribution.
-# Default: OPENIM_WEB_DIST_PATH=/app/dist
-OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH}
-
# Port on which OpenIM web service is running.
# Default: OPENIM_WEB_PORT=11001
OPENIM_WEB_PORT=${OPENIM_WEB_PORT}
diff --git a/docker-compose.yml b/docker-compose.yml
index 78632f163..e4449b5ad 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -114,9 +114,6 @@ services:
openim-web:
image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:${OPENIM_WEB_IMAGE_VERSION:-v3.5.0-docker}
container_name: openim-web
- environment:
- - OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH:-/app/dist}
- - OPENIM_WEB_PORT=${OPENIM_WEB_PORT:-11001}
restart: always
ports:
- "${OPENIM_WEB_PORT:-11001}:80"
@@ -201,9 +198,6 @@ services:
# - "${DATA_DIR:-./}/components/openim-chat/config:/openim/openim-chat/config"
# restart: always
# # user: root:root
- # depends_on:
- # openim-server:
- # condition: service_healthy
# logging:
# driver: json-file
# options:
@@ -215,8 +209,8 @@ services:
# openim-admin:
# # https://github.com/openimsdk/open-im-server/issues/1662
- # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin:${ADMIN_FRONT_VERSION:-toc-base-open-docker.35}
- # container_name: openim-admin
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin:${ADMIN_FRONT_VERSION:-toc-base-open-docker.35}
+ # container_name: openim-admin
# restart: always
# ports:
# - "${OPENIM_ADMIN_FRONT_PORT:-11002}:80"
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index f84cb924a..41a70c64d 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -243,8 +243,6 @@ def "KAFKA_CONSUMERGROUPID_PUSH" "push" # `Kafka` 的消费
###################### openim-web 配置信息 ######################
def "OPENIM_WEB_PORT" "11001" # openim-web的端口
-def "OPENIM_WEB_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # openim-web的地址
-def "OPENIM_WEB_DIST_PATH" "/app/dist" # openim-web的dist路径
###################### openim-admin-front 配置信息 ######################
def "OPENIM_ADMIN_FRONT_PORT" "11002" # openim-admin-front的端口
diff --git a/tools/openim-web/README.md b/tools/openim-web/README.md
index afd5e9a96..5794a946d 100644
--- a/tools/openim-web/README.md
+++ b/tools/openim-web/README.md
@@ -37,7 +37,6 @@ Variables can be set as above, Environment variables can also be set
example:
```bash
-$ export OPENIM_WEB_DIST_PATH="/app/dist"
$ export OPENIM_WEB_PPRT="11001"
```
From 080ddb82cd2294902d277b1b2766a152ecbcd62e Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Tue, 16 Jan 2024 14:34:41 +0800
Subject: [PATCH 072/110] fix(main): add more cases for get_users api, so it
accept users in older version. feat(main): also add search functionality
(#1751)
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* fix bugs
* fix bugs
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* Update go.mod
* Update friend.go
* debug
* debug
* debug
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* I cannot solve todo in test.sh
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* Update go.mod
* fix group notification
* fix group notification
* update openimsdk tools
* update openim server remove duplicate code
* update openim server remove duplicate code
* update user command get
* update user command get
* update response of callback response error
* update black ex
* update join group ex
* update user pb2map
* update go sum
* update go sum
* update updateUserInfoEx
* update updateUserInfoEx
* update updateUserInfoEx add callback functions
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* update pin friend to update friend
* fix go mod
* fix err golangci-lint
* fix UserPb2DBMap
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* fix callback
* fix go.mod
* fix debug
* fix bugs
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* fix updateUserInfoEx
* fix updateUserInfoEx
* modify go.mod
* fix updateUserInfoEx
* fix updateUserInfoEx
* fix: fix the bug
* fix: fix the imAdmin permission and searchNoficitaion resp
* fix updateUserInfoEx
* 2023 Annual Summary Reflections and Aspirations
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: dissmissGroup and lack of keyword bug (#1678)
* Update docker-start-all.sh
* Update env-template.yaml
* update user command notification
* Update docker-start-all.sh
* fix openim config mongo passwd env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update user command get all notification
* update user command get all notification
* fix type = 0
* fix type = 0
* fix type = 0
* fix type = 0
* fix type = 0
* fix type = 0
* fix typing cause callback
* add ex to usercommand
* add ex to usercommand
* update updatefriends
* fix updatefriend map
* fix updatefriend FriendsInfoUpdateNotification
* fix push online and offline user, but why typing trigger callback push?
* fix push online and offline user, but why typing trigger callback push?
* update user command record not found and user access check
* update user command get all user access check
* update go.mod
* fix callback name and place
* fix: fix some bug
* fix: group messages sync failed.
* upadtae callback test
* fix callback typing
* fix callback typing
* fix callback typing
* fix callback typing
* fix lint on processusercommand
* fix: fix the valiable name
* fix: fix the getSortedConversation api
* fix: fix the mongo search error
* fix: GroupApplicationAcceptedNotification
(cherry picked from commit 4c3c4555a35ec8e31ffbf3e96a5dba3bceec09ee)
* fix: GroupApplicationAcceptedNotification
* fix update friends
* fix pageFindUser
* fix pageFindUser
* fix pageFindUser
* fix pageFindUser
* Delete .devcontainer directory
* revert
* more powerful PageFindUserWithKeyword
* more powerful PageFindUserWithKeyword
* more powerful PageFindUserWithKeyword
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
Co-authored-by: luhaoling <2198702716@qq.com>
Co-authored-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Co-authored-by: Brabem <69128477+luhaoling@users.noreply.github.com>
Co-authored-by: OpenIM Bot <124379614+kubbot@users.noreply.github.com>
Co-authored-by: OpenIM Robot <139873238+openimbot@users.noreply.github.com>
Co-authored-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
Co-authored-by: withchao <993506633@qq.com>
---
go.mod | 3 +++
internal/rpc/user/user.go | 28 +++++++++++++++-----
pkg/common/db/controller/user.go | 13 +++++++---
pkg/common/db/mgo/user.go | 39 ++++++++++++++++++++++++++--
pkg/common/db/table/relation/user.go | 3 ++-
5 files changed, 73 insertions(+), 13 deletions(-)
diff --git a/go.mod b/go.mod
index 5e8e7275b..b0eda8970 100644
--- a/go.mod
+++ b/go.mod
@@ -156,3 +156,6 @@ require (
golang.org/x/crypto v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
+replace (
+ github.com/OpenIMSDK/protocol v0.0.47 => github.com/AndrewZuo01/protocol v0.0.0-20240112093520-fd9c53e27b94
+)
\ No newline at end of file
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 158e37d70..f647d6686 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -229,11 +229,20 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
}
func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPaginationUsersReq) (resp *pbuser.GetPaginationUsersResp, err error) {
- total, users, err := s.PageFindUser(ctx, constant.IMOrdinaryUser, req.Pagination)
- if err != nil {
- return nil, err
+ if req.UserID == "" && req.UserName == "" {
+ total, users, err := s.PageFindUser(ctx, constant.IMOrdinaryUser, constant.AppOrdinaryUsers, req.Pagination)
+ if err != nil {
+ return nil, err
+ }
+ return &pbuser.GetPaginationUsersResp{Total: int32(total), Users: convert.UsersDB2Pb(users)}, err
+ } else {
+ total, users, err := s.PageFindUserWithKeyword(ctx, constant.IMOrdinaryUser, constant.AppOrdinaryUsers, req.UserID, req.UserName, req.Pagination)
+ if err != nil {
+ return nil, err
+ }
+ return &pbuser.GetPaginationUsersResp{Total: int32(total), Users: convert.UsersDB2Pb(users)}, err
}
- return &pbuser.GetPaginationUsersResp{Total: int32(total), Users: convert.UsersDB2Pb(users)}, err
+
}
func (s *userServer) UserRegister(ctx context.Context, req *pbuser.UserRegisterReq) (resp *pbuser.UserRegisterResp, err error) {
@@ -591,31 +600,38 @@ func (s *userServer) UpdateNotificationAccountInfo(ctx context.Context, req *pbu
}
func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.SearchNotificationAccountReq) (*pbuser.SearchNotificationAccountResp, error) {
+ // Check if user is an admin
if err := authverify.CheckIMAdmin(ctx); err != nil {
return nil, err
}
var users []*relation.UserModel
var err error
+
+ // If a keyword is provided in the request
if req.Keyword != "" {
+ // Find users by keyword
users, err = s.UserDatabase.Find(ctx, []string{req.Keyword})
if err != nil {
return nil, err
}
+
+ // Convert users to response format
resp := s.userModelToResp(users, req.Pagination)
if resp.Total != 0 {
return resp, nil
}
+
+ // Find users by nickname if no users found by keyword
users, err = s.UserDatabase.FindByNickname(ctx, req.Keyword)
if err != nil {
return nil, err
}
resp = s.userModelToResp(users, req.Pagination)
return resp, nil
-
- return resp, nil
}
+ // If no keyword, find users with notification settings
users, err = s.UserDatabase.FindNotification(ctx, constant.AppNotificationAdmin)
if err != nil {
return nil, err
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index cedae5c97..b1cace955 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -48,10 +48,12 @@ type UserDatabase interface {
//Update(ctx context.Context, user *relation.UserModel) (err error)
// UpdateByMap update (zero value) external guarantee userID exists
UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
+ // FindUser
+ PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
+ //FindUser with keyword
+ PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, userName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
// Page If not found, no error is returned
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
- // FindUser
- PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
// IsExist true as long as one exists
IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
// GetAllUserID Get all user IDs
@@ -185,8 +187,11 @@ func (u *userDatabase) Page(ctx context.Context, pagination pagination.Paginatio
return u.userDB.Page(ctx, pagination)
}
-func (u *userDatabase) PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
- return u.userDB.PageFindUser(ctx, level, pagination)
+func (u *userDatabase) PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return u.userDB.PageFindUser(ctx, level1, level2, pagination)
+}
+func (u *userDatabase) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID, userName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return u.userDB.PageFindUserWithKeyword(ctx, level1, level2, userID, userName, pagination)
}
// IsExist Does userIDs exist? As long as there is one, it will be true.
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index b07f82928..3ab71b209 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -18,6 +18,7 @@ import (
"context"
"github.com/OpenIMSDK/protocol/user"
"github.com/OpenIMSDK/tools/errs"
+ "go.mongodb.org/mongo-driver/bson/primitive"
"time"
"github.com/OpenIMSDK/tools/mgoutil"
@@ -78,8 +79,42 @@ func (u *UserMgo) Page(ctx context.Context, pagination pagination.Pagination) (c
return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{}, pagination)
}
-func (u *UserMgo) PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
- return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{"app_manger_level": level}, pagination)
+func (u *UserMgo) PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ query := bson.M{
+ "$or": []bson.M{
+ {"app_manger_level": level1},
+ {"app_manger_level": level2},
+ },
+ }
+
+ return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, query, pagination)
+}
+func (u *UserMgo) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, userName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ // Initialize the base query with level conditions
+ query := bson.M{
+ "$and": []bson.M{
+ {"app_manger_level": bson.M{"$in": []int64{level1, level2}}},
+ },
+ }
+
+ // Add userID and userName conditions to the query if they are provided
+ if userID != "" || userName != "" {
+ userConditions := []bson.M{}
+ if userID != "" {
+ // Use regex for userID
+ regexPattern := primitive.Regex{Pattern: userID, Options: "i"} // 'i' for case-insensitive matching
+ userConditions = append(userConditions, bson.M{"user_id": regexPattern})
+ }
+ if userName != "" {
+ // Use regex for userName
+ regexPattern := primitive.Regex{Pattern: userName, Options: "i"} // 'i' for case-insensitive matching
+ userConditions = append(userConditions, bson.M{"nickname": regexPattern})
+ }
+ query["$and"] = append(query["$and"].([]bson.M), bson.M{"$or": userConditions})
+ }
+
+ // Perform the paginated search
+ return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, query, pagination)
}
func (u *UserMgo) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error) {
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index a1b4269d1..8d40a8f67 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -56,7 +56,8 @@ type UserModelInterface interface {
TakeNotification(ctx context.Context, level int64) (user []*UserModel, err error)
TakeByNickname(ctx context.Context, nickname string) (user []*UserModel, err error)
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
- PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
+ PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
+ PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID, userName string, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
Exist(ctx context.Context, userID string) (exist bool, err error)
GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error)
GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
From 2a5129b1ae9662b0e92d8aa94dbec65ab14c0072 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Tue, 16 Jan 2024 21:49:27 +0800
Subject: [PATCH 073/110] Update docker-compose.yaml support arm/v6, arm/v8
(#1776)
---
docker-compose.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/docker-compose.yml b/docker-compose.yml
index e4449b5ad..24735abe9 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -114,6 +114,7 @@ services:
openim-web:
image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:${OPENIM_WEB_IMAGE_VERSION:-v3.5.0-docker}
container_name: openim-web
+ platform: linux/amd64
restart: always
ports:
- "${OPENIM_WEB_PORT:-11001}:80"
@@ -211,6 +212,7 @@ services:
# # https://github.com/openimsdk/open-im-server/issues/1662
# image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin:${ADMIN_FRONT_VERSION:-toc-base-open-docker.35}
# container_name: openim-admin
+ # platform: linux/amd64
# restart: always
# ports:
# - "${OPENIM_ADMIN_FRONT_PORT:-11002}:80"
From 19f5c94d25838ea1a39e089013fd49f1207a1a82 Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Fri, 19 Jan 2024 23:49:57 +0800
Subject: [PATCH 074/110] fix: update nick name field for get_user (#1786)
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* update set pin friends
* fix bugs
* fix bugs
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* debug
* Update go.mod
* Update friend.go
* debug
* debug
* debug
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* add pin friend test
* I cannot solve todo in test.sh
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* update user command
* Update go.mod
* fix group notification
* fix group notification
* update openimsdk tools
* update openim server remove duplicate code
* update openim server remove duplicate code
* update user command get
* update user command get
* update response of callback response error
* update black ex
* update join group ex
* update user pb2map
* update go sum
* update go sum
* update updateUserInfoEx
* update updateUserInfoEx
* update updateUserInfoEx add callback functions
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* fix dismiss group function
* update pin friend to update friend
* fix go mod
* fix err golangci-lint
* fix UserPb2DBMap
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* update comments, update go.mod check for register username
* fix callback
* fix go.mod
* fix debug
* fix bugs
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* update notification
* fix updateUserInfoEx
* fix updateUserInfoEx
* modify go.mod
* fix updateUserInfoEx
* fix updateUserInfoEx
* fix: fix the bug
* fix: fix the imAdmin permission and searchNoficitaion resp
* fix updateUserInfoEx
* 2023 Annual Summary Reflections and Aspirations
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: dissmissGroup and lack of keyword bug (#1678)
* Update docker-start-all.sh
* Update env-template.yaml
* update user command notification
* Update docker-start-all.sh
* fix openim config mongo passwd env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* update user command get all notification
* update user command get all notification
* fix type = 0
* fix type = 0
* fix type = 0
* fix type = 0
* fix type = 0
* fix type = 0
* fix typing cause callback
* add ex to usercommand
* add ex to usercommand
* update updatefriends
* fix updatefriend map
* fix updatefriend FriendsInfoUpdateNotification
* fix push online and offline user, but why typing trigger callback push?
* fix push online and offline user, but why typing trigger callback push?
* update user command record not found and user access check
* update user command get all user access check
* update go.mod
* fix callback name and place
* fix: fix some bug
* fix: group messages sync failed.
* upadtae callback test
* fix callback typing
* fix callback typing
* fix callback typing
* fix callback typing
* fix lint on processusercommand
* fix: fix the valiable name
* fix: fix the getSortedConversation api
* fix: fix the mongo search error
* fix: GroupApplicationAcceptedNotification
(cherry picked from commit 4c3c4555a35ec8e31ffbf3e96a5dba3bceec09ee)
* fix: GroupApplicationAcceptedNotification
* fix update friends
* fix pageFindUser
* fix pageFindUser
* fix pageFindUser
* fix pageFindUser
* Delete .devcontainer directory
* revert
* more powerful PageFindUserWithKeyword
* more powerful PageFindUserWithKeyword
* more powerful PageFindUserWithKeyword
* bug: update nickname
* bug: update nickname
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
Co-authored-by: luhaoling <2198702716@qq.com>
Co-authored-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Co-authored-by: Brabem <69128477+luhaoling@users.noreply.github.com>
Co-authored-by: OpenIM Bot <124379614+kubbot@users.noreply.github.com>
Co-authored-by: OpenIM Robot <139873238+openimbot@users.noreply.github.com>
Co-authored-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
Co-authored-by: withchao <993506633@qq.com>
---
go.mod | 2 +-
internal/rpc/user/user.go | 4 ++--
pkg/common/db/controller/user.go | 6 +++---
pkg/common/db/mgo/user.go | 8 ++++----
pkg/common/db/table/relation/user.go | 2 +-
5 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/go.mod b/go.mod
index b0eda8970..9a5803519 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.47
+ github.com/OpenIMSDK/protocol v0.0.48
github.com/OpenIMSDK/tools v0.0.23
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index f647d6686..240bea153 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -229,14 +229,14 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
}
func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPaginationUsersReq) (resp *pbuser.GetPaginationUsersResp, err error) {
- if req.UserID == "" && req.UserName == "" {
+ if req.UserID == "" && req.NickName == "" {
total, users, err := s.PageFindUser(ctx, constant.IMOrdinaryUser, constant.AppOrdinaryUsers, req.Pagination)
if err != nil {
return nil, err
}
return &pbuser.GetPaginationUsersResp{Total: int32(total), Users: convert.UsersDB2Pb(users)}, err
} else {
- total, users, err := s.PageFindUserWithKeyword(ctx, constant.IMOrdinaryUser, constant.AppOrdinaryUsers, req.UserID, req.UserName, req.Pagination)
+ total, users, err := s.PageFindUserWithKeyword(ctx, constant.IMOrdinaryUser, constant.AppOrdinaryUsers, req.UserID, req.NickName, req.Pagination)
if err != nil {
return nil, err
}
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index b1cace955..1a3651076 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -51,7 +51,7 @@ type UserDatabase interface {
// FindUser
PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
//FindUser with keyword
- PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, userName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
+ PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, nickName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
// Page If not found, no error is returned
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
// IsExist true as long as one exists
@@ -190,8 +190,8 @@ func (u *userDatabase) Page(ctx context.Context, pagination pagination.Paginatio
func (u *userDatabase) PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
return u.userDB.PageFindUser(ctx, level1, level2, pagination)
}
-func (u *userDatabase) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID, userName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
- return u.userDB.PageFindUserWithKeyword(ctx, level1, level2, userID, userName, pagination)
+func (u *userDatabase) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID, nickName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return u.userDB.PageFindUserWithKeyword(ctx, level1, level2, userID, nickName, pagination)
}
// IsExist Does userIDs exist? As long as there is one, it will be true.
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 3ab71b209..7eed32634 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -89,7 +89,7 @@ func (u *UserMgo) PageFindUser(ctx context.Context, level1 int64, level2 int64,
return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, query, pagination)
}
-func (u *UserMgo) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, userName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+func (u *UserMgo) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, nickName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
// Initialize the base query with level conditions
query := bson.M{
"$and": []bson.M{
@@ -98,16 +98,16 @@ func (u *UserMgo) PageFindUserWithKeyword(ctx context.Context, level1 int64, lev
}
// Add userID and userName conditions to the query if they are provided
- if userID != "" || userName != "" {
+ if userID != "" || nickName != "" {
userConditions := []bson.M{}
if userID != "" {
// Use regex for userID
regexPattern := primitive.Regex{Pattern: userID, Options: "i"} // 'i' for case-insensitive matching
userConditions = append(userConditions, bson.M{"user_id": regexPattern})
}
- if userName != "" {
+ if nickName != "" {
// Use regex for userName
- regexPattern := primitive.Regex{Pattern: userName, Options: "i"} // 'i' for case-insensitive matching
+ regexPattern := primitive.Regex{Pattern: nickName, Options: "i"} // 'i' for case-insensitive matching
userConditions = append(userConditions, bson.M{"nickname": regexPattern})
}
query["$and"] = append(query["$and"].([]bson.M), bson.M{"$or": userConditions})
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index 8d40a8f67..4039257f1 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -57,7 +57,7 @@ type UserModelInterface interface {
TakeByNickname(ctx context.Context, nickname string) (user []*UserModel, err error)
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
- PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID, userName string, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
+ PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID, nickName string, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
Exist(ctx context.Context, userID string) (exist bool, err error)
GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error)
GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
From 907104701aa0a6f36aa9929848886dc76b8b8392 Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Fri, 19 Jan 2024 23:50:33 +0800
Subject: [PATCH 075/110] fix: change the afterSendSingleMsg config and fix
CallbackSingleMsgRead unused problem (#1790)
* fix: open the afterSendSingleMsg config
* fix: fix the CallbackSingleMsgRead unused
---
deployments/templates/openim.yaml | 4 ++--
internal/rpc/msg/as_read.go | 11 +++++++++++
pkg/callbackstruct/message.go | 7 ++++---
3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index 4c84373a5..82087bc4d 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -315,7 +315,7 @@ iosPush:
# Timeout in seconds
# Whether to continue execution if callback fails
callback:
- url: ""
+ url: "http://127.0.0.1:10008/callbackExample"
beforeSendSingleMsg:
enable: ${CALLBACK_ENABLE}
timeout: ${CALLBACK_TIMEOUT}
@@ -329,7 +329,7 @@ callback:
timeout: ${CALLBACK_TIMEOUT}
failedContinue: ${CALLBACK_FAILED_CONTINUE}
afterSendSingleMsg:
- enable: ${CALLBACK_ENABLE}
+ enable: true
timeout: ${CALLBACK_TIMEOUT}
failedContinue: ${CALLBACK_FAILED_CONTINUE}
beforeSendGroupMsg:
diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go
index 71e038b39..e91e2cf34 100644
--- a/internal/rpc/msg/as_read.go
+++ b/internal/rpc/msg/as_read.go
@@ -124,6 +124,17 @@ func (m *msgServer) MarkMsgsAsRead(
return
}
}
+
+ req_callback := &cbapi.CallbackSingleMsgReadReq{
+ ConversationID: conversation.ConversationID,
+ UserID: req.UserID,
+ Seqs: req.Seqs,
+ ContentType: conversation.ConversationType,
+ }
+ if err = CallbackSingleMsgRead(ctx, req_callback); err != nil {
+ return nil, err
+ }
+
if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID,
m.conversationAndGetRecvID(conversation, req.UserID), req.Seqs, hasReadSeq); err != nil {
return
diff --git a/pkg/callbackstruct/message.go b/pkg/callbackstruct/message.go
index ae36d7139..2864e28b1 100644
--- a/pkg/callbackstruct/message.go
+++ b/pkg/callbackstruct/message.go
@@ -94,9 +94,10 @@ type CallbackGroupMsgReadResp struct {
type CallbackSingleMsgReadReq struct {
CallbackCommand `json:"callbackCommand"`
- SendID string `json:"sendID"`
- ReceiveID string `json:"receiveID"`
- ContentType int64 `json:"contentType"`
+ ConversationID string `json:"conversationID"`
+ UserID string `json:"userID"`
+ Seqs []int64 `json:"Seqs"`
+ ContentType int32 `json:"contentType"`
}
type CallbackSingleMsgReadResp struct {
From 7155d1acb792091013c92b628c943a83dff6d46e Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Sun, 21 Jan 2024 10:49:08 +0800
Subject: [PATCH 076/110] feat: Enhance Script Details and Add MacOS
Compatibility with Documentation Updates (#1794)
* feat: fix a portion of get path
* feat: optimize mac deployment scripts
---
.devcontainer/devcontainer.json | 10 -------
assets/colors.md | 11 ++++++++
pkg/common/config/parse.go | 22 +++++++++++----
pkg/util/flag/flag.go | 40 +++++++++++++++++++++++++++
pkg/util/genutil/genutil.go | 27 ++++++++++++++++++
pkg/util/genutil/genutil_test.go | 26 +++++++++++++++++
scripts/docker-start-all.sh | 2 --
scripts/install/openim-msgtransfer.sh | 19 +++++++++----
scripts/install/openim-rpc.sh | 3 +-
scripts/start-all.sh | 2 ++
10 files changed, 138 insertions(+), 24 deletions(-)
create mode 100644 assets/colors.md
create mode 100644 pkg/util/flag/flag.go
create mode 100644 pkg/util/genutil/genutil.go
create mode 100644 pkg/util/genutil/genutil_test.go
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index d8b13d3a4..dc003ca20 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -6,16 +6,6 @@
"build": { "dockerfile": "Dockerfile" },
// Replace with uncommented line below to build your own local copy of the image
// "dockerFile": "../docker/Dockerfile-dev",
- "containerEnv": {
- // Uncomment to overwrite devcontainer .kube/config and .minikube certs with the localhost versions
- // each time the devcontainer starts, if the respective .kube-localhost/config and .minikube-localhost
- // folders respectively are bind mounted to the devcontainer.
- // "SYNC_LOCALHOST_KUBECONFIG": "true"
-
- // Uncomment to disable docker-in-docker and automatically proxy default /var/run/docker.sock to
- // the localhost bind-mount /var/run/docker-host.sock.
- // "BIND_LOCALHOST_DOCKER": "true"
- },
"remoteEnv": {
"GO111MODULE": "on",
"GOPROXY": "https://goproxy.cn",
diff --git a/assets/colors.md b/assets/colors.md
new file mode 100644
index 000000000..cf8777719
--- /dev/null
+++ b/assets/colors.md
@@ -0,0 +1,11 @@
+# Official Colors
+
+The openim logo has an official blue color. When reproducing the logo, please use the official color, when possible.
+
+## Pantone
+
+When possible, the Pantone color is preferred for print material. The official Pantone color is *285C*.
+
+## RGB
+
+When used digitally, the official RGB color code is *#326CE5*.
diff --git a/pkg/common/config/parse.go b/pkg/common/config/parse.go
index 1410a5a4a..64719d6a1 100644
--- a/pkg/common/config/parse.go
+++ b/pkg/common/config/parse.go
@@ -24,6 +24,7 @@ import (
"gopkg.in/yaml.v3"
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
+ "github.com/openimsdk/open-im-server/v3/pkg/util/genutil"
)
//go:embed version
@@ -37,19 +38,30 @@ const (
// return absolude path join ../config/, this is k8s container config path.
func GetDefaultConfigPath() string {
- b, err := filepath.Abs(os.Args[0])
+ executablePath, err := os.Executable()
if err != nil {
- fmt.Println("filepath.Abs error,err=", err)
+ fmt.Println("GetDefaultConfigPath error:", err.Error())
return ""
}
- return filepath.Join(filepath.Dir(b), "../config/")
+
+ configPath, err := genutil.OutDir(filepath.Join(filepath.Dir(executablePath), "../config/"))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err)
+ os.Exit(1)
+ }
+ return configPath
}
// getProjectRoot returns the absolute path of the project root directory.
func GetProjectRoot() string {
- b, _ := filepath.Abs(os.Args[0])
+ executablePath, _ := os.Executable()
- return filepath.Join(filepath.Dir(b), "../../../../..")
+ projectRoot, err := genutil.OutDir(filepath.Join(filepath.Dir(executablePath), "../../../../.."))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err)
+ os.Exit(1)
+ }
+ return projectRoot
}
func GetOptionsByNotification(cfg NotificationConf) msgprocessor.Options {
diff --git a/pkg/util/flag/flag.go b/pkg/util/flag/flag.go
new file mode 100644
index 000000000..7bbacf444
--- /dev/null
+++ b/pkg/util/flag/flag.go
@@ -0,0 +1,40 @@
+package flag
+
+import (
+ goFlag "flag"
+ "log"
+ "strings"
+
+ "github.com/spf13/pflag"
+)
+
+// WordSepNormalizeFunc changes all flags that contain "_" separators.
+func WordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
+ if strings.Contains(name, "_") {
+ return pflag.NormalizedName(strings.ReplaceAll(name, "_", "-"))
+ }
+ return pflag.NormalizedName(name)
+}
+
+// WarnWordSepNormalizeFunc changes and warns for flags that contain "_" separators.
+func WarnWordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
+ if strings.Contains(name, "_") {
+ normalizedName := strings.ReplaceAll(name, "_", "-")
+ log.Printf("WARNING: flag %s has been deprecated and will be removed in a future version. Use %s instead.", name, normalizedName)
+ return pflag.NormalizedName(normalizedName)
+ }
+ return pflag.NormalizedName(name)
+}
+
+// InitFlags normalizes, parses, then logs the command line flags.
+func InitFlags() {
+ pflag.CommandLine.SetNormalizeFunc(WordSepNormalizeFunc)
+ pflag.CommandLine.AddGoFlagSet(goFlag.CommandLine)
+}
+
+// PrintFlags logs the flags in the flagset.
+func PrintFlags(flags *pflag.FlagSet) {
+ flags.VisitAll(func(flag *pflag.Flag) {
+ log.Printf("FLAG: --%s=%q", flag.Name, flag.Value)
+ })
+}
diff --git a/pkg/util/genutil/genutil.go b/pkg/util/genutil/genutil.go
new file mode 100644
index 000000000..36da89bbb
--- /dev/null
+++ b/pkg/util/genutil/genutil.go
@@ -0,0 +1,27 @@
+package genutil
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+// OutDir creates the absolute path name from path and checks path exists.
+// Returns absolute path including trailing '/' or error if path does not exist.
+func OutDir(path string) (string, error) {
+ outDir, err := filepath.Abs(path)
+ if err != nil {
+ return "", err
+ }
+
+ stat, err := os.Stat(outDir)
+ if err != nil {
+ return "", err
+ }
+
+ if !stat.IsDir() {
+ return "", fmt.Errorf("output directory %s is not a directory", outDir)
+ }
+ outDir += "/"
+ return outDir, nil
+}
diff --git a/pkg/util/genutil/genutil_test.go b/pkg/util/genutil/genutil_test.go
new file mode 100644
index 000000000..0ee85df27
--- /dev/null
+++ b/pkg/util/genutil/genutil_test.go
@@ -0,0 +1,26 @@
+package genutil
+
+import (
+ "testing"
+)
+
+func TestValidDir(t *testing.T) {
+ _, err := OutDir("./")
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestInvalidDir(t *testing.T) {
+ _, err := OutDir("./nondir")
+ if err == nil {
+ t.Fatal("expected an error")
+ }
+}
+
+func TestNotDir(t *testing.T) {
+ _, err := OutDir("./genutils_test.go")
+ if err == nil {
+ t.Fatal("expected an error")
+ }
+}
diff --git a/scripts/docker-start-all.sh b/scripts/docker-start-all.sh
index 2616b7bd1..162655553 100755
--- a/scripts/docker-start-all.sh
+++ b/scripts/docker-start-all.sh
@@ -28,8 +28,6 @@ openim::log::info "\n# Use Docker to start all openim service"
trap 'openim::util::onCtrlC' INT
-"${OPENIM_ROOT}"/scripts/init-config.sh --skip
-
"${OPENIM_ROOT}"/scripts/start-all.sh
sleep 5
diff --git a/scripts/install/openim-msgtransfer.sh b/scripts/install/openim-msgtransfer.sh
index 18bbb3c02..f6039637c 100755
--- a/scripts/install/openim-msgtransfer.sh
+++ b/scripts/install/openim-msgtransfer.sh
@@ -12,6 +12,8 @@
# 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.
+# Use:
+# ./scripts/install/openim-msgtransfer.sh openim::msgtransfer::start
# Common utilities, variables and checks for all build scripts.
set -o errexit
@@ -64,15 +66,20 @@ function openim::msgtransfer::check() {
PIDS=$(pgrep -f "${OPENIM_OUTPUT_HOSTBIN}/openim-msgtransfer")
NUM_PROCESSES=$(echo "$PIDS" | wc -l)
- # NUM_PROCESSES=$(($NUM_PROCESSES - 1))
if [ "$NUM_PROCESSES" -eq "$OPENIM_MSGGATEWAY_NUM" ]; then
- openim::log::info "Found $OPENIM_MSGGATEWAY_NUM processes named $OPENIM_OUTPUT_HOSTBIN"
- for PID in $PIDS; do
- ps -p $PID -o pid,cmd
- done
+ openim::log::info "Found $OPENIM_MSGGATEWAY_NUM processes named $OPENIM_OUTPUT_HOSTBIN"
+ for PID in $PIDS; do
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ ps -p $PID -o pid,cmd
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ ps -p $PID -o pid,comm
+ else
+ openim::log::error "Unsupported OS type: $OSTYPE"
+ fi
+ done
else
- openim::log::error_exit "Expected $OPENIM_MSGGATEWAY_NUM openim msgtransfer processes, but found $NUM_PROCESSES msgtransfer processes."
+ openim::log::error_exit "Expected $OPENIM_MSGGATEWAY_NUM openim msgtransfer processes, but found $NUM_PROCESSES msgtransfer processes."
fi
}
diff --git a/scripts/install/openim-rpc.sh b/scripts/install/openim-rpc.sh
index b66004191..db1526d6a 100755
--- a/scripts/install/openim-rpc.sh
+++ b/scripts/install/openim-rpc.sh
@@ -123,12 +123,13 @@ function openim::rpc::start() {
for ((i = 0; i < ${#OPENIM_RPC_SERVICE_LISTARIES[*]}; i++)); do
# openim::util::stop_services_with_name ${OPENIM_RPC_SERVICE_LISTARIES
openim::util::stop_services_on_ports ${OPENIM_RPC_PORT_LISTARIES[$i]}
+
openim::log::info "OpenIM ${OPENIM_RPC_SERVICE_LISTARIES[$i]} config path: ${OPENIM_RPC_CONFIG}"
# Get the service and Prometheus ports.
OPENIM_RPC_SERVICE_PORTS=( $(openim::util::list-to-string ${OPENIM_RPC_PORT_LISTARIES[$i]}) )
read -a OPENIM_RPC_SERVICE_PORTS_ARRAY <<< ${OPENIM_RPC_SERVICE_PORTS}
-
+
OPENIM_RPC_PROM_PORTS=( $(openim::util::list-to-string ${OPENIM_RPC_PROM_PORT_LISTARIES[$i]}) )
read -a OPENIM_RPC_PROM_PORTS_ARRAY <<< ${OPENIM_RPC_PROM_PORTS}
diff --git a/scripts/start-all.sh b/scripts/start-all.sh
index 64b931f50..b1f9b865b 100755
--- a/scripts/start-all.sh
+++ b/scripts/start-all.sh
@@ -32,6 +32,8 @@ if [[ $? -ne 0 ]]; then
fi
set -o errexit
+"${OPENIM_ROOT}"/scripts/init-config.sh --skip
+
echo "You need to start the following scripts in order: ${OPENIM_SERVER_SCRIPTARIES[@]}"
openim::log::install_errexit
From e182d5e7dffe1e3de8bbdb86bf0b411de5d00adf Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Sun, 21 Jan 2024 12:13:31 +0800
Subject: [PATCH 077/110] feat: optimize mac deployment scripts (#1795)
---
docker-compose.yml | 24 ++++++++++-
.../contrib/mac-developer-deployment-guide.md | 43 ++++++++++++++++---
2 files changed, 61 insertions(+), 6 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 24735abe9..6d0f3c25a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -123,7 +123,7 @@ services:
ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7}
### TODO: Uncomment, or deploy using openim docker: https://github.com/openimsdk/openim-docker
- # Uncomment and configure the following services as needed
+### Uncomment and configure the following services as needed
# openim-server:
# image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-server:${SERVER_IMAGE_VERSION:-main}
@@ -172,6 +172,23 @@ services:
# server:
# ipv4_address: ${OPENIM_SERVER_NETWORK_ADDRESS:-172.28.0.8}
+### TODO: mysql is required to deploy the openim-chat component
+ # mysql:
+ # image: mysql:${MYSQL_IMAGE_VERSION:-5.7}
+ # platform: linux/amd64
+ # ports:
+ # - "${MYSQL_PORT:-13306}:3306"
+ # container_name: mysql
+ # volumes:
+ # - "${DATA_DIR:-./}/components/mysql/data:/var/lib/mysql"
+ # - "/etc/localtime:/etc/localtime"
+ # environment:
+ # MYSQL_ROOT_PASSWORD: "${MYSQL_PASSWORD:-openIM123}"
+ # restart: always
+ # networks:
+ # server:
+ # ipv4_address: ${MYSQL_NETWORK_ADDRESS:-172.28.0.15}
+
# openim-chat:
# image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-chat:${CHAT_IMAGE_VERSION:-main}
# container_name: openim-chat
@@ -199,6 +216,11 @@ services:
# - "${DATA_DIR:-./}/components/openim-chat/config:/openim/openim-chat/config"
# restart: always
# # user: root:root
+ # depends_on:
+ # - mysql
+ # - kafka
+ # - redis
+ # - zookeeper
# logging:
# driver: json-file
# options:
diff --git a/docs/contrib/mac-developer-deployment-guide.md b/docs/contrib/mac-developer-deployment-guide.md
index 40ef4b8be..69e4e7503 100644
--- a/docs/contrib/mac-developer-deployment-guide.md
+++ b/docs/contrib/mac-developer-deployment-guide.md
@@ -47,25 +47,58 @@ Homebrew is an essential package manager for macOS. Install it using:
### Forking and Cloning the Repository
-1. Fork the OpenIM repository on GitHub to your account.
-2. Clone your fork to your local machine:
+To optimize and add logic to your instructions, particularly regarding deploying on a Mac, you can modify them as follows:
+
+1. **Fork the OpenIM Repository**: Fork the OpenIM repository on GitHub to your account.
+
+2. **Clone Your Fork to Your Local Machine**:
+ Open your terminal and execute the following commands:
```sh
+ # Clone the repository
git clone https://github.com//open-im-server.git
- # The Docker bridging network mode for Mac is slightly different and needs to be set:
+
+ # Set Docker bridging network mode for Mac
export DOCKER_BRIDGE_SUBNET=127.0.0.0/16
+
# Set OpenIM IP
export OPENIM_IP=
- # Init Config
+
+ # Initialize configuration
make init
- # Start Components
+ # Start components using Docker
docker compose up -d
# Start OpenIM Server
make start
```
+3. **Additional Steps for Mac Deployment**:
+ If you are deploying on a Mac and wish to use the chat feature, you need to modify the `docker-compose` file. Specifically, you'll need to uncomment the sections related to `openim-chat` and `mysql`.
+
+ Here's how to do it:
+
+ - Open the `docker-compose.yml` file in a text editor.
+ - Find the sections for `openim-chat` and `mysql`.
+ - Remove the comment marks (`#`) at the beginning of the lines in these sections to enable them.
+ - Save the file after making these changes.
+
+4. **Update and Restart Services**:
+ After modifying the `docker-compose` file, you need to update and restart the services to apply these changes. Run the following command in your terminal:
+
+ ```sh
+ # Update and restart services
+ docker compose up -d
+
+ # Check openim-chat start
+ docker compose logs openim-chat
+ ```
+
+ This command will re-read the `docker-compose.yml` file, apply the new configuration, and restart the necessary containers.
+
+Remember, replacing `` and `` with your actual GitHub username and desired IP address for OpenIM is crucial. These steps should streamline the setup process, particularly for Mac users wishing to use the chat feature.
+
### Setting Up the Devcontainer
`Devcontainers` provide a Docker-based isolated development environment.
From fa55c441132726c35b84d189eb779a895834ff08 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sun, 21 Jan 2024 16:51:21 +0800
Subject: [PATCH 078/110] feat(deps): bump golang.org/x/crypto from 0.14.0 to
0.17.0 (#1579)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.14.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.14.0...v0.17.0)
---
updated-dependencies:
- dependency-name: golang.org/x/crypto
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
go.mod | 11 +++++------
go.sum | 18 +++++++++---------
2 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/go.mod b/go.mod
index 9a5803519..4332e389c 100644
--- a/go.mod
+++ b/go.mod
@@ -131,8 +131,8 @@ require (
golang.org/x/arch v0.3.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
- golang.org/x/sys v0.14.0 // indirect
- golang.org/x/text v0.13.0 // indirect
+ golang.org/x/sys v0.15.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
@@ -153,9 +153,8 @@ 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.14.0 // indirect
+ golang.org/x/crypto v0.17.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
-replace (
- github.com/OpenIMSDK/protocol v0.0.47 => github.com/AndrewZuo01/protocol v0.0.0-20240112093520-fd9c53e27b94
-)
\ No newline at end of file
+
+replace github.com/OpenIMSDK/protocol v0.0.47 => github.com/AndrewZuo01/protocol v0.0.0-20240112093520-fd9c53e27b94
diff --git a/go.sum b/go.sum
index 80a02d20a..d32a689cb 100644
--- a/go.sum
+++ b/go.sum
@@ -15,11 +15,11 @@ cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/o
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
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/AndrewZuo01/protocol v0.0.0-20240112093520-fd9c53e27b94 h1:o86vkek41ZrQqoBGqyKvS0z6N0uJj64mpzK72OkDZVM=
+github.com/AndrewZuo01/protocol v0.0.0-20240112093520-fd9c53e27b94/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.47 h1:DTJMFSONzqT0i/wa4Q1CtDT/jVATVudIRHcpY1zSWYE=
-github.com/OpenIMSDK/protocol v0.0.47/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.23 h1:xozfrGzhbpNPlDTap5DLVPk+JfgZ/ZyIj4Cuu3/bm9w=
github.com/OpenIMSDK/tools v0.0.23/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
@@ -371,8 +371,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
-golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
+golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg=
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
@@ -438,12 +438,12 @@ 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.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
-golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
+golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -451,8 +451,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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
From d356f7a035aeaaf9f401e21cccd3b82e2fc3c935 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Fri, 26 Jan 2024 10:02:53 +0800
Subject: [PATCH 079/110] =?UTF-8?q?feat(main):=20=F0=9F=9A=80=20Database?=
=?UTF-8?q?=20Name=20Correction=20and=20S3=20Module=20Int32=20Overflow=20F?=
=?UTF-8?q?ix=20with=20Go=20Routine=20Integration=20for=20Automated=20Chec?=
=?UTF-8?q?ks=20and=20Script=20Optimization=20(#1799)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: replace mongo database openIM_v3 to openim_v3
* openim-building-an-efficient-version-control-and-testing-workflow
* feat: complete openim source deployment rpc start timeout
* feat: optimize config
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* feat: add scripts format
* feat: use scripts format code
* fix cos and minio etc to typecheck
* feat: scripts make verify check ci
* fix: make file verify spelling
* fix: make file verify spelling
* Concurrent Type Checking and Cross-Platform Development in Go
* feat: add copyright make lint and format
* feat: add config examples file
Signed-off-by: Xinwei Xiong <3293172751@qq.com>
* feat: add config examples file
Signed-off-by: Xinwei Xiong <3293172751@qq.com>
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Signed-off-by: Xinwei Xiong <3293172751@qq.com>
---
.devcontainer/devcontainer.json | 1 -
.github/workflows/help-comment-issue.yml | 1 +
.github/workflows/openimci.yml | 15 +-
.gitignore | 1 +
CHANGELOG/CHANGELOG-3.5.0.md | 15 -
README.md | 7 +-
config/templates/config.yaml.template | 32 +-
config/templates/env.template | 186 ++-
config/templates/open-im-ng-example.conf | 2 +-
config/templates/prometheus-dashboard.yaml | 2 +-
deployments/Readme.md | 2 +-
deployments/openim-charts.yaml | 1276 -----------------
.../templates/{openim.yaml => config.yaml} | 2 +-
deployments/templates/env-template.yaml | 2 +-
docker-compose.yml | 4 +-
docs/.generated_docs | 2 +-
docs/contrib/environment.md | 2 +-
.../contrib/mac-developer-deployment-guide.md | 178 ++-
go.mod | 4 +-
go.sum | 8 +-
internal/api/user.go | 10 +-
internal/msggateway/n_ws_server.go | 3 +-
internal/push/push_rpc_server.go | 3 +-
internal/push/push_to_client.go | 5 +-
internal/rpc/conversation/conversaion.go | 3 +-
internal/rpc/msg/as_read.go | 1 +
internal/rpc/msg/seq.go | 1 +
internal/rpc/third/s3.go | 6 +-
internal/rpc/user/callback.go | 1 +
internal/rpc/user/user.go | 12 +-
pkg/common/convert/friend.go | 1 +
pkg/common/db/controller/msg_test.go | 2 +-
pkg/common/db/controller/user.go | 13 +-
pkg/common/db/mgo/friend.go | 1 +
pkg/common/db/mgo/user.go | 13 +-
pkg/common/db/s3/cos/cos.go | 8 +-
pkg/common/db/s3/minio/minio.go | 8 +-
pkg/common/db/s3/oss/oss.go | 8 +-
pkg/common/db/s3/s3.go | 2 +-
pkg/common/db/table/relation/user.go | 3 +-
.../kubernetes/kubernetes.go | 8 +-
pkg/rpcclient/msg.go | 1 +
pkg/util/flag/flag.go | 18 +-
pkg/util/genutil/genutil.go | 14 +
pkg/util/genutil/genutil_test.go | 14 +
scripts/advertise.sh | 92 +-
scripts/bash_beautify.py | 173 +++
scripts/build-all-service.sh | 16 +-
scripts/check-all.sh | 36 +-
scripts/cherry-pick.sh | 132 +-
scripts/common.sh | 584 ++++----
scripts/coverage.sh | 12 +-
scripts/demo.sh | 22 +-
scripts/docker-check-service.sh | 96 +-
scripts/ensure-tag.sh | 4 +-
scripts/gen-swagger-docs.sh | 4 +-
scripts/genconfig.sh | 18 +-
scripts/gendoc.sh | 54 +-
scripts/githooks/commit-msg.sh | 38 +-
scripts/githooks/pre-commit.sh | 22 +-
scripts/githooks/pre-push.sh | 10 +-
scripts/init-config.sh | 48 +-
scripts/init-env.sh | 10 +-
scripts/init-githooks.sh | 96 +-
scripts/install-im-server.sh | 18 +-
scripts/install/dependency.sh | 102 +-
scripts/install/environment.sh | 14 +-
scripts/install/install-protobuf.sh | 126 +-
scripts/install/install.sh | 186 +--
scripts/install/openim-api.sh | 152 +-
scripts/install/openim-crontask.sh | 42 +-
scripts/install/openim-man.sh | 64 +-
scripts/install/openim-msggateway.sh | 18 +-
scripts/install/openim-msgtransfer.sh | 110 +-
scripts/install/openim-push.sh | 70 +-
scripts/install/openim-rpc.sh | 8 +-
scripts/install/openim-tools.sh | 11 +-
scripts/install/test.sh | 1225 ++++++++--------
scripts/lib/chat.sh | 40 +-
scripts/lib/color.sh | 112 +-
scripts/lib/logging.sh | 54 +-
scripts/lib/release.sh | 50 +-
scripts/lib/util.sh | 478 +++---
scripts/lib/version.sh | 28 +-
scripts/make-rules/common.mk | 2 +-
scripts/make-rules/golang.mk | 2 +-
scripts/make-rules/tools.mk | 5 +
scripts/release.sh | 116 +-
scripts/start-all.sh | 56 +-
scripts/stop-all.sh | 6 +-
scripts/update-generated-docs.sh | 8 +-
scripts/verify-shellcheck.sh | 70 +-
scripts/verify-spelling.sh | 11 +-
scripts/verify-typecheck.sh | 2 +-
scripts/wait-for-it.sh | 238 +--
test/typecheck/README.md | 61 +-
test/typecheck/typecheck.go | 15 +-
test/wrktest.sh | 13 +-
tools/data-conversion/README.md | 2 +-
.../cmd/conversion-mysql/conversion-mysql.go | 2 +-
tools/data-conversion/openim/common/config.go | 2 +-
tools/data-conversion/openim/mysql/cmd.go | 2 +-
tools/formitychecker/checker/checker.go | 14 +
tools/formitychecker/config/config.go | 14 +
tools/formitychecker/formitychecker.go | 14 +
tools/imctl/.gitignore | 14 -
tools/imctl/imctl.go | 14 +
107 files changed, 3073 insertions(+), 3886 deletions(-)
delete mode 100644 CHANGELOG/CHANGELOG-3.5.0.md
delete mode 100644 deployments/openim-charts.yaml
rename deployments/templates/{openim.yaml => config.yaml} (99%)
create mode 100755 scripts/bash_beautify.py
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index dc003ca20..69a35f66a 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -2,7 +2,6 @@
// Reference Doc: https://code.visualstudio.com/remote/advancedcontainers/overview
"name": "OpenIM Dev Environment",
// Update the container version when you publish dev-container
- "dockerComposeFile": "docker-compose.yml",
"build": { "dockerfile": "Dockerfile" },
// Replace with uncommented line below to build your own local copy of the image
// "dockerFile": "../docker/Dockerfile-dev",
diff --git a/.github/workflows/help-comment-issue.yml b/.github/workflows/help-comment-issue.yml
index 73cf105a8..dce858197 100644
--- a/.github/workflows/help-comment-issue.yml
+++ b/.github/workflows/help-comment-issue.yml
@@ -17,6 +17,7 @@ on:
issues:
types:
- labeled
+
jobs:
add-comment:
if: github.event.label.name == 'help wanted' || github.event.label.name == 'good first issue'
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index dce5649df..8aa38d941 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -23,6 +23,8 @@ on:
- "docs/**"
- "README.md"
- "README_zh-CN.md"
+ - "**.md"
+ - "docs/**"
- "CONTRIBUTING.md"
pull_request:
branches:
@@ -31,7 +33,8 @@ on:
paths-ignore:
- "README.md"
- "README_zh-CN.md"
- - "CONTRIBUTING.md"
+ - "CONTRIBUTING/**"
+ - "**.md"
- "docs/**"
env:
@@ -67,6 +70,9 @@ jobs:
version: '3.x' # If available, use the latest major version that's compatible
repo-token: ${{ secrets.GITHUB_TOKEN }}
+ - name: OpenIM Scripts Verification(make verify)
+ run: sudo make verify
+
- name: Module Operations
run: |
sudo make tidy
@@ -91,13 +97,6 @@ jobs:
- name: Cleanup Build
run: sudo make clean
- - name: Push Changes to Main
- uses: stefanzweifel/git-auto-commit-action@v5
- with:
- commit_message: "cicd: robot automated Change"
- branch: main
- continue-on-error: true
-
- name: Set Current Directory
id: set_directory
run: echo "::set-output name=directory::$(pwd)"
diff --git a/.gitignore b/.gitignore
index fb8d428d2..5142fe551 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,6 +34,7 @@ deployments/charts/generated-configs/
### OpenIM Config ###
.env
config/config.yaml
+config/openim.yaml
config/alertmanager.yml
config/prometheus.yml
config/email.tmpl
diff --git a/CHANGELOG/CHANGELOG-3.5.0.md b/CHANGELOG/CHANGELOG-3.5.0.md
deleted file mode 100644
index 02c28308d..000000000
--- a/CHANGELOG/CHANGELOG-3.5.0.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Version logging for OpenIM
-
-
-
-
-
-
-## [Unreleased]
-
-
-
-## [v3.5.0+3.97baaac] - 2024-01-12
-
-[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.5.0+3.97baaac...HEAD
-[v3.5.0+3.97baaac]: https://github.com/openimsdk/open-im-server/compare/v3.5.0+5.950e970...v3.5.0+3.97baaac
diff --git a/README.md b/README.md
index 551ff27f8..3876fcd7a 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ OpenIM is a service platform specifically designed for integrating chat, audio-v
- 🛡️ API wrapping
- 🌐 Connection management
- ## 📚 Main Modules:
++ 📚 Main Modules:
1. 🚀 Initialization and Login
2. 👤 User Management
@@ -70,11 +70,16 @@ It is built using Golang and supports cross-platform deployment, ensuring a cons
## :rocket: Quick Start
+We support many platforms. Here are the addresses for quick experience on the web side:
+
+👉 **[OpenIM online web demo](https://web-enterprise.rentsoft.cn/)**
+
🤲 To facilitate user experience, we offer various deployment solutions. You can choose your deployment method from the list below:
+ **[Source Code Deployment Guide](https://docs.openim.io/guides/gettingStarted/imSourceCodeDeployment)**
+ **[Docker Deployment Guide](https://docs.openim.io/guides/gettingStarted/dockerCompose)**
+ **[Kubernetes Deployment Guide](https://docs.openim.io/guides/gettingStarted/k8s-deployment)**
++ **[Mac Developer Deployment Guide](https://docs.openim.io/guides/gettingstarted/mac-deployment-guide)**
## :hammer_and_wrench: To Start Developing OpenIM
diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template
index 9954a8863..32ac14361 100644
--- a/config/templates/config.yaml.template
+++ b/config/templates/config.yaml.template
@@ -14,7 +14,7 @@
# -----------------------------------------------------------------
# TODO: This config file is the template file
-# --| source: deployments/templates/openim.yaml
+# --| source: deployments/templates/config.yaml
# --| env: scripts/install/environment
# --| target: config/config.yaml
# -----------------------------------------------------------------
@@ -52,8 +52,8 @@ mongo:
# Default MongoDB database name
# Maximum connection pool size
address: [ 172.28.0.1:37017 ]
- database: openIM_v3
- username: root
+ database: openim_v3
+ username: openIM
password: openIM123
maxPoolSize: 100
@@ -122,14 +122,14 @@ api:
# minio.signEndpoint is minio public network address
object:
enable: "minio"
- apiURL: "http://14.155.64.202:10002"
+ apiURL: "http://172.28.0.1:10002"
minio:
bucket: "openim"
endpoint: "http://172.28.0.1:10005"
accessKeyID: "root"
secretAccessKey: "openIM123"
sessionToken: ''
- signEndpoint: "http://14.155.64.202:10005"
+ signEndpoint: "http://172.28.0.1:10005"
publicRead: false
cos:
bucketURL: https://temp-1252357374.cos.ap-chengdu.myqcloud.com
@@ -193,7 +193,7 @@ rpcRegisterName:
# Whether to output in json format
# Whether to include stack trace in logs
log:
- storageLocation: /data/workspaces/open-im-server/logs/
+ storageLocation: /workspaces/open-im-server/logs/
rotationTime: 24
remainRotationCount: 2
remainLogLevel: 6
@@ -247,6 +247,14 @@ manager:
userID: [ "openIM123456", "openIM654321", "openIMAdmin" ]
nickname: [ "system1", "system2", "system3" ]
+# chatAdmin, use for send notification
+#
+# Built-in app system notification account ID
+# Built-in app system notification account nickname
+im-admin:
+ userID: [ "imAdmin" ]
+ nickname: [ "imAdmin" ]
+
# Multi-platform login policy
# For each platform(Android, iOS, Windows, Mac, web), only one can be online at a time
multiLoginPolicy: 1
@@ -307,21 +315,21 @@ iosPush:
# Timeout in seconds
# Whether to continue execution if callback fails
callback:
- url: ""
+ url: "http://127.0.0.1:10008/callbackExample"
beforeSendSingleMsg:
enable: false
timeout: 5
failedContinue: true
beforeUpdateUserInfoEx:
- enable: false
+ enable: false
timeout: 5
failedContinue: true
afterUpdateUserInfoEx:
- enable: false
+ enable: false
timeout: 5
failedContinue: true
afterSendSingleMsg:
- enable: false
+ enable: true
timeout: 5
failedContinue: true
beforeSendGroupMsg:
@@ -505,8 +513,8 @@ callback:
# The number of Prometheus ports per service needs to correspond to rpcPort
# The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh
prometheus:
- enable: false
- grafanaUrl: 172.28.0.1:13000
+ enable: true
+ grafanaUrl: http://172.28.0.1:13000/
apiPrometheusPort: [20100]
userPrometheusPort: [ 20110 ]
friendPrometheusPort: [ 20120 ]
diff --git a/config/templates/env.template b/config/templates/env.template
index a606704c5..b4f9c868d 100644
--- a/config/templates/env.template
+++ b/config/templates/env.template
@@ -1,4 +1,4 @@
-# Copyright © 2023 OpenIM. All rights reserved.
+# Copyright © 2024 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,31 +12,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# ======================================
-# ========= Basic Configuration ========
-# ======================================
-
-# The user for authentication or system operations.
-# Default: OPENIM_USER=root
-USER=root
-
-# Password associated with the specified user for authentication.
-# Default: PASSWORD=openIM123
-PASSWORD=openIM123
-
-# Base URL for the application programming interface (API).
-# Default: API_URL=http://172.28.0.1:10002
-API_URL=http://14.155.64.202:10002
-
-# Directory path for storing data files or related information.
-# Default: DATA_DIR=./
-DATA_DIR=/data/workspaces/open-im-server
-
-# Choose the appropriate image address, the default is GITHUB image,
-# you can choose docker hub, for Chinese users can choose Ali Cloud
-# export IMAGE_REGISTRY="ghcr.io/openimsdk"
-# export IMAGE_REGISTRY="openim"
-# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
+# -----------------------------------------------------------------------------
+# General Configuration
+# This section contains general configuration options for the entire environment.
+# These options can be set via environment variables. If both environment variables
+# and settings in this .env file exist, the environment variables take precedence.
+# -----------------------------------------------------------------------------
+# ==========================
+# General Configuration
+# ==========================
+# These settings apply to the overall environment.
+
+# Data storage directory for persistent data.
+# Example: DATA_DIR=/path/to/data
+DATA_DIR=/workspaces/open-im-server
+
+# Docker image registry. Uncomment the preferred one.
+# Options: ghcr.io/openimsdk, openim, registry.cn-hangzhou.aliyuncs.com/openimsdk
+# IMAGE_REGISTRY="ghcr.io/openimsdk"
+# IMAGE_REGISTRY="openim"
+# IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
IMAGE_REGISTRY=ghcr.io/openimsdk
# ======================================
@@ -47,10 +42,9 @@ IMAGE_REGISTRY=ghcr.io/openimsdk
# Default: DOCKER_BRIDGE_SUBNET=172.28.0.0/16
DOCKER_BRIDGE_SUBNET=172.28.0.0/16
-# Gateway for the Docker network.
-# Default: DOCKER_BRIDGE_GATEWAY=172.28.0.1
+# Set and specify the IP addresses of some containers. Generally speaking,
+# you do not need to modify these configurations to facilitate debugging
DOCKER_BRIDGE_GATEWAY=172.28.0.1
-
MONGO_NETWORK_ADDRESS=172.28.0.2
REDIS_NETWORK_ADDRESS=172.28.0.3
KAFKA_NETWORK_ADDRESS=172.28.0.4
@@ -65,45 +59,66 @@ NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.12
OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=172.28.0.13
ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.14
-# ===============================================
-# = Component Extension Configuration =
-# ===============================================
+# ==============================================================================
+# Configuration Update Instructions
+# ==============================================================================
+# This header outlines the methods to update common variables in config.yaml and .env files.
+# These instructions are vital for maintaining the OpenIM environment's configuration.
+#
+# METHOD 1: Regenerate All Configurations
+# ----------------------------------------
+# Use this method to regenerate all configurations.
+# Steps:
+# 1. Delete existing config files:
+# - openim-server/config/config.yaml
+# - openim-chat/config/config.yaml
+# 2. Modify the .env file as required.
+# 3. Run 'docker compose up -d'. This will regenerate:
+# - config/config.yaml
+#
+# METHOD 2: Modify Individual Configuration Files
+# -----------------------------------------------
+# Use this method to update specific configuration files.
+# Steps:
+# 1. Modify the .env file as necessary.
+# 2. Update the corresponding entries in:
+# - config/config.yaml
+# 3. Restart the services with 'docker compose up -d'.
+# 4. Special Note: If you modify OPENIM_IP, API_OPENIM_PORT, or MINIO_PORT in .env,
+# ensure to update the corresponding services and configurations accordingly.
+#
+# It is essential to follow these methods to ensure consistent and correct application behavior.
+# ==============================================================================
+# Local IP address of the service. Modify if necessary.
+# Example: OPENIM_IP=172.28.0.1,
+OPENIM_IP=172.28.0.1
-# ============ Component Extension Configuration ==========
# ----- ZooKeeper Configuration -----
-# Address or hostname for the ZooKeeper service.
-# Default: ZOOKEEPER_ADDRESS=172.28.0.1
-ZOOKEEPER_ADDRESS=172.28.0.5
-
# Port for ZooKeeper service.
# Default: ZOOKEEPER_PORT=12181
ZOOKEEPER_PORT=12181
-# ----- MongoDB Configuration -----
-# Address or hostname for the MongoDB service.
-# Default: MONGO_ADDRESS=172.28.0.1
-MONGO_ADDRESS=172.28.0.2
-
-# Port on which MongoDB service is running.
+# MongoDB service port configuration.
# Default: MONGO_PORT=37017
# MONGO_PORT=37017
-# Username to authenticate with the MongoDB service.
-# Default: MONGO_USERNAME=root
-# MONGO_USERNAME=root
-
-# Password to authenticate with the MongoDB service.
+# Password for MongoDB admin user. Used for service authentication.
# Default: MONGO_PASSWORD=openIM123
MONGO_PASSWORD=openIM123
-# Name of the database in MongoDB to be used.
-# Default: MONGO_DATABASE=openIM_v3
-MONGO_DATABASE=openIM_v3
+# Username for a regular OpenIM user in MongoDB.
+# Default: MONGO_OPENIM_USERNAME=openIM
+MONGO_OPENIM_USERNAME=openIM
+
+# Password for a regular OpenIM user in MongoDB.
+# Default: MONGO_OPENIM_PASSWORD=openIM123456
+MONGO_OPENIM_PASSWORD=openIM123
+
+# Specifies the database name to be used within MongoDB.
+# Default: MONGO_DATABASE=openim_v3
+MONGO_DATABASE=openim_v3
# ----- Redis Configuration -----
-# Address or hostname for the Redis service.
-# Default: REDIS_ADDRESS=172.28.0.1
-REDIS_ADDRESS=172.28.0.3
# Port on which Redis in-memory data structure store is running.
# Default: REDIS_PORT=16379
@@ -113,11 +128,6 @@ REDIS_PORT=16379
# Default: REDIS_PASSWORD=openIM123
REDIS_PASSWORD=openIM123
-# ----- Kafka Configuration -----
-# Address or hostname for the Kafka service.
-# Default: KAFKA_ADDRESS=172.28.0.1
-KAFKA_ADDRESS=172.28.0.4
-
# Kakfa username to authenticate with the Kafka service.
# KAFKA_USERNAME=''
@@ -129,20 +139,13 @@ KAFKA_PORT=19094
# Default: KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis
KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis
-# Topic in Kafka for pushing messages (e.g. notifications or updates).
-# Default: KAFKA_MSG_PUSH_TOPIC=msgToPush
-KAFKA_MSG_PUSH_TOPIC=msgToPush
-
-# Topic in Kafka for storing offline messages in MongoDB.
-# Default: KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql
-KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql
-
-# ----- MinIO Configuration ----
-# Address or hostname for the MinIO object storage service.
-# Default: MINIO_ADDRESS=172.28.0.1
-MINIO_ADDRESS=172.28.0.6
-
-# Port on which MinIO object storage service is running.
+# MINIO_PORT
+# ----------
+# MINIO_PORT sets the port for the MinIO object storage service.
+# Upon changing this port, the MinIO endpoint URLs in the file must be updated
+# to reflect this change. The endpoints include both the 'endpoint' and 'signEndpoint'
+# under the MinIO configuration.
+#
# Default: MINIO_PORT=10005
MINIO_PORT=10005
@@ -155,19 +158,11 @@ MINIO_PORT=10005
MINIO_SECRET_KEY=openIM123
# ----- Prometheus Configuration -----
-# Address or hostname for the Prometheus service.
-# Default: PROMETHEUS_ADDRESS=172.28.0.1
-PROMETHEUS_ADDRESS=172.28.0.10
-
# Port on which Prometheus service is running.
# Default: PROMETHEUS_PORT=19090
PROMETHEUS_PORT=19090
# ----- Grafana Configuration -----
-# Address or hostname for the Grafana service.
-# Default: GRAFANA_ADDRESS=172.28.0.1
-GRAFANA_ADDRESS=172.28.0.11
-
# Port on which Grafana service is running.
# Default: GRAFANA_PORT=13000
GRAFANA_PORT=13000
@@ -183,41 +178,34 @@ OPENIM_WEB_PORT=11001
# ======================================
# ========= OpenIM Server ==============
# ======================================
-
-# Address or hostname for the OpenIM server.
-# Default: OPENIM_SERVER_ADDRESS=172.28.0.1
-OPENIM_SERVER_ADDRESS=172.28.0.8
-
# Port for the OpenIM WebSockets.
# Default: OPENIM_WS_PORT=10001
OPENIM_WS_PORT=10001
-# Port for the OpenIM API.
+# API_OPENIM_PORT
+# ---------------
+# This variable defines the port on which the OpenIM API service will listen.
+# When changing this port, it's essential to update the apiURL in the config.yaml file
+# to ensure the API service is accessible at the new port.
+#
# Default: API_OPENIM_PORT=10002
API_OPENIM_PORT=10002
-
# ======================================
# ========== OpenIM Chat ===============
# ======================================
# Branch name for OpenIM chat.
# Default: CHAT_IMAGE_VERSION=main
-# https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md
CHAT_IMAGE_VERSION=main
-# Address or hostname for the OpenIM chat service.
-# Default: OPENIM_CHAT_ADDRESS=172.28.0.1
-OPENIM_CHAT_ADDRESS=172.28.0.9
-
# Port for the OpenIM chat API.
# Default: OPENIM_CHAT_API_PORT=10008
OPENIM_CHAT_API_PORT=10008
-# Directory path for storing data files or related information for OpenIM chat.
-# Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main
-OPENIM_CHAT_DATA_DIR=./openim-chat/main
-
+# Port for the OpenIM admin API.
+# Default: OPENIM_ADMIN_API_PORT=10009
+OPENIM_ADMIN_API_PORT=10009
# ======================================
# ========== OpenIM Admin ==============
@@ -226,10 +214,6 @@ OPENIM_CHAT_DATA_DIR=./openim-chat/main
# Branch name for OpenIM server.
# Default: SERVER_IMAGE_VERSION=main
SERVER_IMAGE_VERSION=main
-
-# Port for the OpenIM admin API.
-# Default: OPENIM_ADMIN_API_PORT=10009
-OPENIM_ADMIN_API_PORT=10009
# Port for the node exporter.
# Default: NODE_EXPORTER_PORT=19100
diff --git a/config/templates/open-im-ng-example.conf b/config/templates/open-im-ng-example.conf
index 10a2ecb52..62befa638 100644
--- a/config/templates/open-im-ng-example.conf
+++ b/config/templates/open-im-ng-example.conf
@@ -169,4 +169,4 @@ server {
proxy_pass http://minio_console_2; # This uses the upstream directive definition to load balance
}
-}
+}
\ No newline at end of file
diff --git a/config/templates/prometheus-dashboard.yaml b/config/templates/prometheus-dashboard.yaml
index e1b569df3..417f3d343 100644
--- a/config/templates/prometheus-dashboard.yaml
+++ b/config/templates/prometheus-dashboard.yaml
@@ -1471,4 +1471,4 @@
"uid": "f5f5de9a-6ec5-499a-841e-6e901c33b1f7",
"version": 16,
"weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/deployments/Readme.md b/deployments/Readme.md
index 03f6d112b..a7b288130 100644
--- a/deployments/Readme.md
+++ b/deployments/Readme.md
@@ -165,7 +165,7 @@ export MINIO_ENDPOINT="http://im-minio:9000"
export MINIO_SIGN_ENDPOINT="https://openim.server.com/im-minio-api"
mkdir ./charts/generated-configs
-../scripts/genconfig.sh ../scripts/install/environment.sh ./templates/openim.yaml > ./charts/generated-configs/config.yaml
+../scripts/genconfig.sh ../scripts/install/environment.sh ./templates/config.yaml > ./charts/generated-configs/config.yaml
cp ../config/notification.yaml ./charts/generated-configs/notification.yaml
../scripts/genconfig.sh ../scripts/install/environment.sh ./templates/helm-image.yaml > ./charts/generated-configs/helm-image.yaml
```
diff --git a/deployments/openim-charts.yaml b/deployments/openim-charts.yaml
deleted file mode 100644
index 2b468dad0..000000000
--- a/deployments/openim-charts.yaml
+++ /dev/null
@@ -1,1276 +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.
-
----
-# Source: openim-api/templates/app-cm.yaml
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: openim-cm
-data:
- config.yaml: |+
- notification.yaml: |+
----
-# Source: openim-api/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-api
- labels:
- helm.sh/chart: openim-api-0.1.0
- app.kubernetes.io/name: openim-api
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-api
- app.kubernetes.io/instance: release-name
----
-# Source: openim-api/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-api
- labels:
- helm.sh/chart: openim-api-0.1.0
- app.kubernetes.io/name: openim-api
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-api
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-api
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-api
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-api/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-api
- labels:
- helm.sh/chart: openim-api-0.1.0
- app.kubernetes.io/name: openim-api
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-api
- port:
- number: 80
----
-# Source: openim-msggateway/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-msggateway
- labels:
- helm.sh/chart: openim-msggateway-0.1.0
- app.kubernetes.io/name: openim-msggateway
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- - port: 88
- targetPort: rpc
- protocol: TCP
- name: rpc
- selector:
- app.kubernetes.io/name: openim-msggateway
- app.kubernetes.io/instance: release-name
----
-# Source: openim-msggateway/templates/deployment.yaml
-# 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.
-
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-msggateway
- labels:
- helm.sh/chart: openim-msggateway-0.1.0
- app.kubernetes.io/name: openim-msggateway
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-msggateway
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-msggateway
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-msggateway
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- - name: rpc
- containerPort: 88
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-msggateway/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-msggateway
- labels:
- helm.sh/chart: openim-msggateway-0.1.0
- app.kubernetes.io/name: openim-msggateway
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-msggateway
- port:
- number: 80
----
-# Source: openim-msgtransfer/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-msgtransfer
- labels:
- helm.sh/chart: openim-msgtransfer-0.1.0
- app.kubernetes.io/name: openim-msgtransfer
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-msgtransfer
- app.kubernetes.io/instance: release-name
----
-# Source: openim-msgtransfer/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-msgtransfer
- labels:
- helm.sh/chart: openim-msgtransfer-0.1.0
- app.kubernetes.io/name: openim-msgtransfer
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-msgtransfer
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-msgtransfer
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-msgtransfer
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-msgtransfer/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-msgtransfer
- labels:
- helm.sh/chart: openim-msgtransfer-0.1.0
- app.kubernetes.io/name: openim-msgtransfer
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-msgtransfer
- port:
- number: 80
----
-# Source: openim-push/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-push
- labels:
- helm.sh/chart: openim-push-0.1.0
- app.kubernetes.io/name: openim-push
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-push
- app.kubernetes.io/instance: release-name
----
-# Source: openim-push/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-push
- labels:
- helm.sh/chart: openim-push-0.1.0
- app.kubernetes.io/name: openim-push
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-push
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-push
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-push
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-push/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-push
- labels:
- helm.sh/chart: openim-push-0.1.0
- app.kubernetes.io/name: openim-push
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-push
- port:
- number: 80
----
-# Source: openim-rpc-auth/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-rpc-auth
- labels:
- helm.sh/chart: openim-rpc-auth-0.1.0
- app.kubernetes.io/name: openim-rpc-auth
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-rpc-auth
- app.kubernetes.io/instance: release-name
----
-# Source: openim-rpc-auth/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-rpc-auth
- labels:
- helm.sh/chart: openim-rpc-auth-0.1.0
- app.kubernetes.io/name: openim-rpc-auth
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-rpc-auth
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-rpc-auth
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-rpc-auth
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-rpc-auth/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-rpc-auth
- labels:
- helm.sh/chart: openim-rpc-auth-0.1.0
- app.kubernetes.io/name: openim-rpc-auth
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-rpc-auth
- port:
- number: 80
----
-# Source: openim-rpc-conversation/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-rpc-conversation
- labels:
- helm.sh/chart: openim-rpc-conversation-0.1.0
- app.kubernetes.io/name: openim-rpc-conversation
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-rpc-conversation
- app.kubernetes.io/instance: release-name
----
-# Source: openim-rpc-conversation/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-rpc-conversation
- labels:
- helm.sh/chart: openim-rpc-conversation-0.1.0
- app.kubernetes.io/name: openim-rpc-conversation
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-rpc-conversation
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-rpc-conversation
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-rpc-conversation
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-rpc-conversation/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-rpc-conversation
- labels:
- helm.sh/chart: openim-rpc-conversation-0.1.0
- app.kubernetes.io/name: openim-rpc-conversation
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-rpc-conversation
- port:
- number: 80
----
-# Source: openim-rpc-friend/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-rpc-friend
- labels:
- helm.sh/chart: openim-rpc-friend-0.1.0
- app.kubernetes.io/name: openim-rpc-friend
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-rpc-friend
- app.kubernetes.io/instance: release-name
----
-# Source: openim-rpc-friend/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-rpc-friend
- labels:
- helm.sh/chart: openim-rpc-friend-0.1.0
- app.kubernetes.io/name: openim-rpc-friend
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-rpc-friend
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-rpc-friend
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-rpc-friend
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-rpc-friend/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-rpc-friend
- labels:
- helm.sh/chart: openim-rpc-friend-0.1.0
- app.kubernetes.io/name: openim-rpc-friend
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-rpc-friend
- port:
- number: 80
----
-# Source: openim-rpc-group/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-rpc-group
- labels:
- helm.sh/chart: openim-rpc-group-0.1.0
- app.kubernetes.io/name: openim-rpc-group
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-rpc-group
- app.kubernetes.io/instance: release-name
----
-# Source: openim-rpc-group/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-rpc-group
- labels:
- helm.sh/chart: openim-rpc-group-0.1.0
- app.kubernetes.io/name: openim-rpc-group
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-rpc-group
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-rpc-group
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-rpc-group
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-rpc-group/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-rpc-group
- labels:
- helm.sh/chart: openim-rpc-group-0.1.0
- app.kubernetes.io/name: openim-rpc-group
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-rpc-group
- port:
- number: 80
----
-# Source: openim-rpc-msg/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-rpc-msg
- labels:
- helm.sh/chart: openim-rpc-msg-0.1.0
- app.kubernetes.io/name: openim-rpc-msg
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-rpc-msg
- app.kubernetes.io/instance: release-name
----
-# Source: openim-rpc-msg/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-rpc-msg
- labels:
- helm.sh/chart: openim-rpc-msg-0.1.0
- app.kubernetes.io/name: openim-rpc-msg
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-rpc-msg
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-rpc-msg
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-rpc-msg
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-rpc-msg/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-rpc-msg
- labels:
- helm.sh/chart: openim-rpc-msg-0.1.0
- app.kubernetes.io/name: openim-rpc-msg
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-rpc-msg
- port:
- number: 80
----
-# Source: openim-rpc-third/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-rpc-third
- labels:
- helm.sh/chart: openim-rpc-third-0.1.0
- app.kubernetes.io/name: openim-rpc-third
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-rpc-third
- app.kubernetes.io/instance: release-name
----
-# Source: openim-rpc-third/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-rpc-third
- labels:
- helm.sh/chart: openim-rpc-third-0.1.0
- app.kubernetes.io/name: openim-rpc-third
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-rpc-third
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-rpc-third
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-rpc-third
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-rpc-third/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-rpc-third
- labels:
- helm.sh/chart: openim-rpc-third-0.1.0
- app.kubernetes.io/name: openim-rpc-third
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-rpc-third
- port:
- number: 80
----
-# Source: openim-rpc-user/templates/service.yaml
-apiVersion: v1
-kind: Service
-metadata:
- name: release-name-openim-rpc-user
- labels:
- helm.sh/chart: openim-rpc-user-0.1.0
- app.kubernetes.io/name: openim-rpc-user
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: http
- protocol: TCP
- name: http
- selector:
- app.kubernetes.io/name: openim-rpc-user
- app.kubernetes.io/instance: release-name
----
-# Source: openim-rpc-user/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: release-name-openim-rpc-user
- labels:
- helm.sh/chart: openim-rpc-user-0.1.0
- app.kubernetes.io/name: openim-rpc-user
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
-spec:
- replicas: 1
- selector:
- matchLabels:
- app.kubernetes.io/name: openim-rpc-user
- app.kubernetes.io/instance: release-name
- template:
- metadata:
- labels:
- app.kubernetes.io/name: openim-rpc-user
- app.kubernetes.io/instance: release-name
- spec:
- serviceAccountName: default
- securityContext:
- {}
- containers:
- - name: openim-rpc-user
- securityContext:
- {}
- image: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api:latest"
- imagePullPolicy: Always
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- #livenessProbe:
- # httpGet:
- # path: /
- # port: http
- #readinessProbe:
- # httpGet:
- # path: /
- # port: http
- resources:
- {}
- volumeMounts:
- - mountPath: /openim/openim-server/config/config.yaml
- name: config
- subPath: config.yaml
- - mountPath: /openim/openim-server/config/
- name: config
- subPath: notification.yaml
- volumes:
- - name: config
- configMap:
- name: openim-cm
----
-# Source: openim-rpc-user/templates/ingress.yaml
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: release-name-openim-rpc-user
- labels:
- helm.sh/chart: openim-rpc-user-0.1.0
- app.kubernetes.io/name: openim-rpc-user
- app.kubernetes.io/instance: release-name
- app.kubernetes.io/version: "1.16.0"
- app.kubernetes.io/managed-by: Helm
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /./templates/helm-image.yaml
- nginx.ingress.kubernetes.io/use-regex: "true"
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - "openim.server.com"
- secretName: webapitls
- rules:
- - host: "openim.server.com"
- http:
- paths:
- - path: /api(/|$)(.*)
- pathType: ImplementationSpecific
- backend:
- service:
- name: release-name-openim-rpc-user
- port:
- number: 80
diff --git a/deployments/templates/openim.yaml b/deployments/templates/config.yaml
similarity index 99%
rename from deployments/templates/openim.yaml
rename to deployments/templates/config.yaml
index 82087bc4d..82f76597c 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/config.yaml
@@ -14,7 +14,7 @@
# -----------------------------------------------------------------
# TODO: This config file is the template file
-# --| source: deployments/templates/openim.yaml
+# --| source: deployments/templates/config.yaml
# --| env: scripts/install/environment
# --| target: config/config.yaml
# -----------------------------------------------------------------
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index cbe900c19..9b21c8c65 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -115,7 +115,7 @@ MONGO_OPENIM_USERNAME=${MONGO_OPENIM_USERNAME}
MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD}
# Specifies the database name to be used within MongoDB.
-# Default: MONGO_DATABASE=openIM_v3
+# Default: MONGO_DATABASE=openim_v3
MONGO_DATABASE=${MONGO_DATABASE}
# ----- Redis Configuration -----
diff --git a/docker-compose.yml b/docker-compose.yml
index 6d0f3c25a..dcf7518e2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -27,7 +27,7 @@ services:
- wiredTigerCacheSizeGB=1
- MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME:-root}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD:-openIM123}
- - MONGO_INITDB_DATABASE=${MONGO_DATABASE:-openIM_v3}
+ - MONGO_INITDB_DATABASE=${MONGO_DATABASE:-openim_v3}
- MONGO_OPENIM_USERNAME=${MONGO_OPENIM_USERNAME:-openIM} # Non-root username
- MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD:-openIM123456} # Non-root password
restart: always
@@ -87,6 +87,7 @@ services:
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@:9093
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}:${KAFKA_PORT:-19094}
+ # - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://127.0.0.1:${KAFKA_PORT:-19094} # Mac Deployment
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
networks:
@@ -213,6 +214,7 @@ services:
# - "${OPENIM_ADMIN_API_PORT:-10009}:10009"
# volumes:
# - "${DATA_DIR:-./}/components/openim-chat/logs:/openim/openim-chat/logs"
+ # - "${DATA_DIR:-./}/components/openim-chat/_output/logs:/openim/openim-chat/_output/logs"
# - "${DATA_DIR:-./}/components/openim-chat/config:/openim/openim-chat/config"
# restart: always
# # user: root:root
diff --git a/docs/.generated_docs b/docs/.generated_docs
index 0867d721c..f9b8da675 100644
--- a/docs/.generated_docs
+++ b/docs/.generated_docs
@@ -31,7 +31,7 @@ docs/guide/en-US/cmd/openim/openim-rpc-user_list.md
docs/guide/en-US/cmd/openim/openim-rpc-user_update.md
docs/guide/en-US/cmd/openim/openim_validate.md
docs/guide/en-US/cmd/openim/openim_version.md
-docs/guide/en-US/yaml/openim/openim.yaml
+docs/guide/en-US/yaml/openim/config.yaml
docs/guide/en-US/yaml/openim/openim_color.yaml
docs/guide/en-US/yaml/openim/openim_completion.yaml
docs/guide/en-US/yaml/openim/openim_info.yaml
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index 7d672eda5..366a1d94f 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -89,7 +89,7 @@ While the first two methods will be our main focus, it's worth noting that the t
### 1.2. Source Code Deployment
-In the source code deployment method, the configuration generation process involves executing `make init`, which fundamentally runs the script `./scripts/init-config.sh`. This script utilizes variables defined in the [`environment.sh`](https://github.com/openimsdk/open-im-server/blob/main/scripts/install/environment.sh) script to render the [`openim.yaml`](https://github.com/openimsdk/open-im-server/blob/main/deployments/templates/openim.yaml) template file, subsequently generating the [`config.yaml`](https://github.com/openimsdk/open-im-server/blob/main/config/config.yaml) configuration file.
+In the source code deployment method, the configuration generation process involves executing `make init`, which fundamentally runs the script `./scripts/init-config.sh`. This script utilizes variables defined in the [`environment.sh`](https://github.com/openimsdk/open-im-server/blob/main/scripts/install/environment.sh) script to render the [`config.yaml`](https://github.com/openimsdk/open-im-server/blob/main/deployments/templates/config.yaml) template file, subsequently generating the [`config.yaml`](https://github.com/openimsdk/open-im-server/blob/main/config/config.yaml) configuration file.
### 1.3. Docker Compose Deployment
diff --git a/docs/contrib/mac-developer-deployment-guide.md b/docs/contrib/mac-developer-deployment-guide.md
index 69e4e7503..af8d0b768 100644
--- a/docs/contrib/mac-developer-deployment-guide.md
+++ b/docs/contrib/mac-developer-deployment-guide.md
@@ -45,86 +45,162 @@ Homebrew is an essential package manager for macOS. Install it using:
git config --global user.email "your.email@example.com"
```
-### Forking and Cloning the Repository
+### Setting Up the Devcontainer
-To optimize and add logic to your instructions, particularly regarding deploying on a Mac, you can modify them as follows:
+`Devcontainers` provide a Docker-based isolated development environment.
-1. **Fork the OpenIM Repository**: Fork the OpenIM repository on GitHub to your account.
+Read [README.md](https://github.com/openimsdk/open-im-server/tree/main/.devcontainer) in the `.devcontainer` directory of the project to learn more about the devcontainer.
-2. **Clone Your Fork to Your Local Machine**:
- Open your terminal and execute the following commands:
+To set it up:
- ```sh
- # Clone the repository
- git clone https://github.com//open-im-server.git
+1. Install Docker Desktop for Mac from [Docker Hub](https://docs.docker.com/desktop/install/mac-install/).
+2. Install Visual Studio Code and the Remote - Containers extension.
+3. Open the cloned OpenIM repository in VS Code.
+4. VS Code will prompt to reopen the project in a container. Accept this to set up the environment automatically.
- # Set Docker bridging network mode for Mac
- export DOCKER_BRIDGE_SUBNET=127.0.0.0/16
+### Installing Go and Dependencies
- # Set OpenIM IP
- export OPENIM_IP=
+Use Homebrew to install Go:
- # Initialize configuration
- make init
+```sh
+brew install go
+```
- # Start components using Docker
- docker compose up -d
+Ensure the version of Go is compatible with the version required by OpenIM (refer to the main documentation for version requirements).
- # Start OpenIM Server
- make start
- ```
+### Additional Tools
-3. **Additional Steps for Mac Deployment**:
- If you are deploying on a Mac and wish to use the chat feature, you need to modify the `docker-compose` file. Specifically, you'll need to uncomment the sections related to `openim-chat` and `mysql`.
+Install other required tools like Docker, Vagrant, and necessary GNU utils as described in the main documentation.
- Here's how to do it:
+## Mac Deployment openim-chat and openim-server
- - Open the `docker-compose.yml` file in a text editor.
- - Find the sections for `openim-chat` and `mysql`.
- - Remove the comment marks (`#`) at the beginning of the lines in these sections to enable them.
- - Save the file after making these changes.
+To integrate the Chinese document into an English document for Linux deployment, we will first translate the content and then adapt it to suit the Linux environment. Here's how the translated and adapted content might look:
-4. **Update and Restart Services**:
- After modifying the `docker-compose` file, you need to update and restart the services to apply these changes. Run the following command in your terminal:
+### Ensure a Clean Environment
- ```sh
- # Update and restart services
- docker compose up -d
+- It's recommended to execute in a new directory.
+- Run `ps -ef | grep openim` to ensure no OpenIM processes are running.
+- Run `ps -ef | grep chat` to check for absence of chat-related processes.
+- Execute `docker ps` to verify there are no related containers running.
- # Check openim-chat start
- docker compose logs openim-chat
- ```
+### Source Code Deployment
- This command will re-read the `docker-compose.yml` file, apply the new configuration, and restart the necessary containers.
+#### Deploying openim-server
-Remember, replacing `` and `` with your actual GitHub username and desired IP address for OpenIM is crucial. These steps should streamline the setup process, particularly for Mac users wishing to use the chat feature.
+Source code deployment is slightly more complex because Docker's networking on Linux differs from Mac.
-### Setting Up the Devcontainer
+```bash
+git clone https://github.com/openimsdk/open-im-server
+cd open-im-server
-`Devcontainers` provide a Docker-based isolated development environment.
+export OPENIM_IP="Your IP" # If it's a cloud server, setting might not be needed
+make init # Generates configuration files
+```
-Read [README.md](https://github.com/openimsdk/open-im-server/tree/main/.devcontainer) in the `.devcontainer` directory of the project to learn more about the devcontainer.
+Before deploying openim-server, modify the Kafka logic in the docker-compose.yml file. Replace:
-To set it up:
+```yaml
+- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}:${KAFKA_PORT:-19094}
+```
-1. Install Docker Desktop for Mac from [Docker Hub](https://docs.docker.com/desktop/install/mac-install/).
-2. Install Visual Studio Code and the Remote - Containers extension.
-3. Open the cloned OpenIM repository in VS Code.
-4. VS Code will prompt to reopen the project in a container. Accept this to set up the environment automatically.
+With:
-### Installing Go and Dependencies
+```yaml
+- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://127.0.0.1:${KAFKA_PORT:-19094}
+```
-Use Homebrew to install Go:
+Then start the service:
-```sh
-brew install go
+```bash
+docker compose up -d
```
-Ensure the version of Go is compatible with the version required by OpenIM (refer to the main documentation for version requirements).
+Before starting the openim-server source, set `config/config.yaml` by replacing all instances of `172.28.0.1` with `127.0.0.1`:
-### Additional Tools
+```bash
+vim config/config.yaml -c "%s/172\.28\.0\.1/127.0.0.1/g" -c "wq"
+```
-Install other required tools like Docker, Vagrant, and necessary GNU utils as described in the main documentation.
+Then start openim-server:
+
+```bash
+make start
+```
+
+To check the startup:
+
+```bash
+make check
+```
+
+
+🚧 To avoid mishaps, it's best to wait five minutes before running `make check` again.
+
+
+
+#### Deploying openim-chat
+
+There are several ways to deploy openim-chat, either by source code or using Docker.
+
+Navigate back to the parent directory:
+
+```bash
+cd ..
+```
+
+First, let's look at deploying chat from source:
+
+```bash
+git clone https://github.com/openimsdk/chat
+cd chat
+make init # Generates configuration files
+```
+
+If openim-chat has not deployed MySQL, you will need to deploy it. Note that the official Docker Hub for MySQL does not support architectures like ARM, so you can use the newer version of the open-source edition:
+
+```bash
+docker run -d \
+ --name mysql \
+ -p 13306:3306 \
+ -p 3306:33060 \
+ -v "$(pwd)/components/mysql/data:/var/lib/mysql" \
+ -v "/etc/localtime:/etc/localtime" \
+ -e MYSQL_ROOT_PASSWORD="openIM123" \
+ --restart always \
+ mariadb:10.6
+```
+
+Before starting the source code of openim-chat, set `config/config.yaml` by replacing all instances of `172.28.0.1` with `127.0.0.1`:
+
+```bash
+vim config/config.yaml -c "%s/172\.28\.0\.1/127.0.0.1/g" -c "wq"
+```
+
+Then start openim-chat from source:
+
+```bash
+make start
+```
+
+To check, ensure the following four processes start successfully:
+
+```bash
+make check
+```
+
+### Docker Deployment
+
+Refer to https://github.com/openimsdk/openim-docker for Docker deployment instructions, which can be followed similarly on Linux.
+
+```bash
+git clone https://github.com/openimsdk/openim-docker
+cd openim-docker
+export OPENIM_IP="Your IP"
+make init
+docker compose up -d
+docker compose logs -f openim-server
+docker compose logs -f openim-chat
+```
## GitHub Development Workflow
diff --git a/go.mod b/go.mod
index 4332e389c..fdc6a58de 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
github.com/OpenIMSDK/protocol v0.0.48
- github.com/OpenIMSDK/tools v0.0.23
+ github.com/OpenIMSDK/tools v0.0.28
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
@@ -38,6 +38,7 @@ require (
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/go-redis/redis v6.15.9+incompatible
github.com/redis/go-redis/v9 v9.2.1
+ github.com/spf13/pflag v1.0.5
github.com/stathat/consistent v1.0.0
github.com/tencentyun/cos-go-sdk-v5 v0.7.45
go.uber.org/automaxprocs v1.5.3
@@ -116,7 +117,6 @@ require (
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/sergi/go-diff v1.0.0 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
github.com/src-d/gcfg v1.4.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
diff --git a/go.sum b/go.sum
index d32a689cb..5539b41fc 100644
--- a/go.sum
+++ b/go.sum
@@ -15,13 +15,13 @@ cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/o
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
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/AndrewZuo01/protocol v0.0.0-20240112093520-fd9c53e27b94 h1:o86vkek41ZrQqoBGqyKvS0z6N0uJj64mpzK72OkDZVM=
-github.com/AndrewZuo01/protocol v0.0.0-20240112093520-fd9c53e27b94/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/tools v0.0.23 h1:xozfrGzhbpNPlDTap5DLVPk+JfgZ/ZyIj4Cuu3/bm9w=
-github.com/OpenIMSDK/tools v0.0.23/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/OpenIMSDK/protocol v0.0.48 h1:8MIMjyzJRsruYhVv2ZKArFiOveroaofDOb3dlAdgjsw=
+github.com/OpenIMSDK/protocol v0.0.48/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/tools v0.0.28 h1:UT0rN1ysCFvsxQXyuxAj2TEkHt4C/sUezy+ChKpgt2Y=
+github.com/OpenIMSDK/tools v0.0.28/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
diff --git a/internal/api/user.go b/internal/api/user.go
index 03d22c354..e7bbd4bfb 100644
--- a/internal/api/user.go
+++ b/internal/api/user.go
@@ -201,27 +201,27 @@ func (u *UserApi) GetSubscribeUsersStatus(c *gin.Context) {
a2r.Call(user.UserClient.GetSubscribeUsersStatus, u.Client, c)
}
-// ProcessUserCommandAdd user general function add
+// ProcessUserCommandAdd user general function add.
func (u *UserApi) ProcessUserCommandAdd(c *gin.Context) {
a2r.Call(user.UserClient.ProcessUserCommandAdd, u.Client, c)
}
-// ProcessUserCommandDelete user general function delete
+// ProcessUserCommandDelete user general function delete.
func (u *UserApi) ProcessUserCommandDelete(c *gin.Context) {
a2r.Call(user.UserClient.ProcessUserCommandDelete, u.Client, c)
}
-// ProcessUserCommandUpdate user general function update
+// ProcessUserCommandUpdate user general function update.
func (u *UserApi) ProcessUserCommandUpdate(c *gin.Context) {
a2r.Call(user.UserClient.ProcessUserCommandUpdate, u.Client, c)
}
-// ProcessUserCommandGet user general function get
+// ProcessUserCommandGet user general function get.
func (u *UserApi) ProcessUserCommandGet(c *gin.Context) {
a2r.Call(user.UserClient.ProcessUserCommandGet, u.Client, c)
}
-// ProcessUserCommandGet user general function get all
+// ProcessUserCommandGet user general function get all.
func (u *UserApi) ProcessUserCommandGetAll(c *gin.Context) {
a2r.Call(user.UserClient.ProcessUserCommandGetAll, u.Client, c)
}
diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go
index 7e8129105..01d92b92a 100644
--- a/internal/msggateway/n_ws_server.go
+++ b/internal/msggateway/n_ws_server.go
@@ -19,7 +19,6 @@ import (
"encoding/json"
"errors"
"fmt"
- "github.com/OpenIMSDK/tools/apiresp"
"net/http"
"os"
"os/signal"
@@ -29,6 +28,8 @@ import (
"syscall"
"time"
+ "github.com/OpenIMSDK/tools/apiresp"
+
"github.com/go-playground/validator/v10"
"github.com/redis/go-redis/v9"
"golang.org/x/sync/errgroup"
diff --git a/internal/push/push_rpc_server.go b/internal/push/push_rpc_server.go
index 9e66f8f73..188ddc0e1 100644
--- a/internal/push/push_rpc_server.go
+++ b/internal/push/push_rpc_server.go
@@ -16,9 +16,10 @@ package push
import (
"context"
- "github.com/OpenIMSDK/tools/utils"
"sync"
+ "github.com/OpenIMSDK/tools/utils"
+
"google.golang.org/grpc"
"github.com/OpenIMSDK/protocol/constant"
diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go
index 7cee7b99d..72deb720d 100644
--- a/internal/push/push_to_client.go
+++ b/internal/push/push_to_client.go
@@ -18,9 +18,10 @@ import (
"context"
"encoding/json"
"errors"
- "google.golang.org/grpc"
"sync"
+ "google.golang.org/grpc"
+
"golang.org/x/sync/errgroup"
"github.com/OpenIMSDK/protocol/constant"
@@ -143,7 +144,7 @@ func (p *Pusher) UnmarshalNotificationElem(bytes []byte, t any) error {
}
/*
-k8s deployment,offline push group messages function
+k8s deployment,offline push group messages function.
*/
func (p *Pusher) k8sOfflinePush2SuperGroup(ctx context.Context, groupID string, msg *sdkws.MsgData, wsResults []*msggateway.SingleMsgToUserResults) error {
diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go
index d0d59547c..40803089c 100644
--- a/internal/rpc/conversation/conversaion.go
+++ b/internal/rpc/conversation/conversaion.go
@@ -17,9 +17,10 @@ package conversation
import (
"context"
"errors"
- "github.com/OpenIMSDK/protocol/sdkws"
"sort"
+ "github.com/OpenIMSDK/protocol/sdkws"
+
"github.com/OpenIMSDK/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go
index e91e2cf34..cb292421e 100644
--- a/internal/rpc/msg/as_read.go
+++ b/internal/rpc/msg/as_read.go
@@ -18,6 +18,7 @@ import (
"context"
utils2 "github.com/OpenIMSDK/tools/utils"
+
cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/redis/go-redis/v9"
diff --git a/internal/rpc/msg/seq.go b/internal/rpc/msg/seq.go
index c12f258b7..dfc2ad0b1 100644
--- a/internal/rpc/msg/seq.go
+++ b/internal/rpc/msg/seq.go
@@ -16,6 +16,7 @@ package msg
import (
"context"
+
pbmsg "github.com/OpenIMSDK/protocol/msg"
)
diff --git a/internal/rpc/third/s3.go b/internal/rpc/third/s3.go
index 2c230f258..3b501d4ad 100644
--- a/internal/rpc/third/s3.go
+++ b/internal/rpc/third/s3.go
@@ -19,12 +19,14 @@ import (
"encoding/base64"
"encoding/hex"
"encoding/json"
- "github.com/google/uuid"
- "github.com/openimsdk/open-im-server/v3/pkg/authverify"
"path"
"strconv"
"time"
+ "github.com/google/uuid"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/authverify"
+
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3"
"github.com/OpenIMSDK/protocol/third"
diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go
index 092a66a07..5276946a4 100644
--- a/internal/rpc/user/callback.go
+++ b/internal/rpc/user/callback.go
@@ -16,6 +16,7 @@ package user
import (
"context"
+
pbuser "github.com/OpenIMSDK/protocol/user"
"github.com/OpenIMSDK/tools/utils"
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 240bea153..50c97f41b 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -17,12 +17,14 @@ package user
import (
"context"
"errors"
- "github.com/OpenIMSDK/tools/pagination"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"math/rand"
"strings"
"time"
+ "github.com/OpenIMSDK/tools/pagination"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+
"github.com/OpenIMSDK/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
@@ -387,7 +389,7 @@ func (s *userServer) GetSubscribeUsersStatus(ctx context.Context,
return &pbuser.GetSubscribeUsersStatusResp{StatusList: onlineStatusList}, nil
}
-// ProcessUserCommandAdd user general function add
+// ProcessUserCommandAdd user general function add.
func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) {
err := authverify.CheckAccessV3(ctx, req.UserID)
if err != nil {
@@ -418,7 +420,7 @@ func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.Proc
return &pbuser.ProcessUserCommandAddResp{}, nil
}
-// ProcessUserCommandDelete user general function delete
+// ProcessUserCommandDelete user general function delete.
func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) {
err := authverify.CheckAccessV3(ctx, req.UserID)
if err != nil {
@@ -440,7 +442,7 @@ func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.P
return &pbuser.ProcessUserCommandDeleteResp{}, nil
}
-// ProcessUserCommandUpdate user general function update
+// ProcessUserCommandUpdate user general function update.
func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) {
err := authverify.CheckAccessV3(ctx, req.UserID)
if err != nil {
diff --git a/pkg/common/convert/friend.go b/pkg/common/convert/friend.go
index 62ce6f95b..27bd595ad 100644
--- a/pkg/common/convert/friend.go
+++ b/pkg/common/convert/friend.go
@@ -17,6 +17,7 @@ package convert
import (
"context"
"fmt"
+
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
diff --git a/pkg/common/db/controller/msg_test.go b/pkg/common/db/controller/msg_test.go
index cfb969b3e..70c055bf3 100644
--- a/pkg/common/db/controller/msg_test.go
+++ b/pkg/common/db/controller/msg_test.go
@@ -146,7 +146,7 @@ func Test_BatchInsertChat2DB(t *testing.T) {
func GetDB() *commonMsgDatabase {
config.Config.Mongo.Address = []string{"203.56.175.233:37017"}
// config.Config.Mongo.Timeout = 60
- config.Config.Mongo.Database = "openIM_v3"
+ config.Config.Mongo.Database = "openim_v3"
// config.Config.Mongo.Source = "admin"
config.Config.Mongo.Username = "root"
config.Config.Mongo.Password = "openIM123"
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index 1a3651076..8ba1c01d3 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -142,12 +142,12 @@ func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*rel
return u.cache.GetUsersInfo(ctx, userIDs)
}
-// Find userInfo By Nickname
+// Find userInfo By Nickname.
func (u *userDatabase) FindByNickname(ctx context.Context, nickname string) (users []*relation.UserModel, err error) {
return u.userDB.TakeByNickname(ctx, nickname)
}
-// Find notificationAccouts
+// Find notificationAccouts.
func (u *userDatabase) FindNotification(ctx context.Context, level int64) (users []*relation.UserModel, err error) {
return u.userDB.TakeNotification(ctx, level)
}
@@ -190,7 +190,14 @@ func (u *userDatabase) Page(ctx context.Context, pagination pagination.Paginatio
func (u *userDatabase) PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
return u.userDB.PageFindUser(ctx, level1, level2, pagination)
}
-func (u *userDatabase) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID, nickName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+
+func (u *userDatabase) PageFindUserWithKeyword(
+ ctx context.Context,
+ level1 int64,
+ level2 int64,
+ userID, nickName string,
+ pagination pagination.Pagination,
+) (count int64, users []*relation.UserModel, err error) {
return u.userDB.PageFindUserWithKeyword(ctx, level1, level2, userID, nickName, pagination)
}
diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go
index b4172d0fb..851db6157 100644
--- a/pkg/common/db/mgo/friend.go
+++ b/pkg/common/db/mgo/friend.go
@@ -16,6 +16,7 @@ package mgo
import (
"context"
+
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/mongo/options"
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 7eed32634..34a25ed08 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -16,10 +16,11 @@ package mgo
import (
"context"
+ "time"
+
"github.com/OpenIMSDK/protocol/user"
"github.com/OpenIMSDK/tools/errs"
"go.mongodb.org/mongo-driver/bson/primitive"
- "time"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
@@ -89,7 +90,15 @@ func (u *UserMgo) PageFindUser(ctx context.Context, level1 int64, level2 int64,
return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, query, pagination)
}
-func (u *UserMgo) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, nickName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+
+func (u *UserMgo) PageFindUserWithKeyword(
+ ctx context.Context,
+ level1 int64,
+ level2 int64,
+ userID string,
+ nickName string,
+ pagination pagination.Pagination,
+) (count int64, users []*relation.UserModel, err error) {
// Initialize the base query with level conditions
query := bson.M{
"$and": []bson.M{
diff --git a/pkg/common/db/s3/cos/cos.go b/pkg/common/db/s3/cos/cos.go
index 7d2c0befe..a82ffe670 100644
--- a/pkg/common/db/s3/cos/cos.go
+++ b/pkg/common/db/s3/cos/cos.go
@@ -36,9 +36,9 @@ import (
)
const (
- minPartSize = 1024 * 1024 * 1 // 1MB
- maxPartSize = 1024 * 1024 * 1024 * 5 // 5GB
- maxNumSize = 1000
+ minPartSize int64 = 1024 * 1024 * 1 // 1MB
+ maxPartSize int64 = 1024 * 1024 * 1024 * 5 // 5GB
+ maxNumSize int64 = 1000
)
const (
@@ -133,7 +133,7 @@ func (c *Cos) PartSize(ctx context.Context, size int64) (int64, error) {
return 0, errors.New("size must be greater than 0")
}
if size > maxPartSize*maxNumSize {
- return 0, fmt.Errorf("size must be less than %db", maxPartSize*maxNumSize)
+ return 0, fmt.Errorf("COS size must be less than the maximum allowed limit")
}
if size <= minPartSize*maxNumSize {
return minPartSize, nil
diff --git a/pkg/common/db/s3/minio/minio.go b/pkg/common/db/s3/minio/minio.go
index 7dfe35b51..5a615dcfd 100644
--- a/pkg/common/db/s3/minio/minio.go
+++ b/pkg/common/db/s3/minio/minio.go
@@ -45,9 +45,9 @@ const (
)
const (
- minPartSize = 1024 * 1024 * 5 // 1MB
- maxPartSize = 1024 * 1024 * 1024 * 5 // 5GB
- maxNumSize = 10000
+ minPartSize int64 = 1024 * 1024 * 5 // 1MB
+ maxPartSize int64 = 1024 * 1024 * 1024 * 5 // 5GB
+ maxNumSize int64 = 10000
)
const (
@@ -240,7 +240,7 @@ func (m *Minio) PartSize(ctx context.Context, size int64) (int64, error) {
return 0, errors.New("size must be greater than 0")
}
if size > maxPartSize*maxNumSize {
- return 0, fmt.Errorf("size must be less than %db", maxPartSize*maxNumSize)
+ return 0, fmt.Errorf("MINIO size must be less than the maximum allowed limit")
}
if size <= minPartSize*maxNumSize {
return minPartSize, nil
diff --git a/pkg/common/db/s3/oss/oss.go b/pkg/common/db/s3/oss/oss.go
index 8fa2a538e..0bba97ee7 100644
--- a/pkg/common/db/s3/oss/oss.go
+++ b/pkg/common/db/s3/oss/oss.go
@@ -37,9 +37,9 @@ import (
)
const (
- minPartSize = 1024 * 1024 * 1 // 1MB
- maxPartSize = 1024 * 1024 * 1024 * 5 // 5GB
- maxNumSize = 10000
+ minPartSize int64 = 1024 * 1024 * 1 // 1MB
+ maxPartSize int64 = 1024 * 1024 * 1024 * 5 // 5GB
+ maxNumSize int64 = 10000
)
const (
@@ -141,7 +141,7 @@ func (o *OSS) PartSize(ctx context.Context, size int64) (int64, error) {
return 0, errors.New("size must be greater than 0")
}
if size > maxPartSize*maxNumSize {
- return 0, fmt.Errorf("size must be less than %db", maxPartSize*maxNumSize)
+ return 0, fmt.Errorf("OSS size must be less than the maximum allowed limit")
}
if size <= minPartSize*maxNumSize {
return minPartSize, nil
diff --git a/pkg/common/db/s3/s3.go b/pkg/common/db/s3/s3.go
index 0352004b5..d3dd90ae9 100644
--- a/pkg/common/db/s3/s3.go
+++ b/pkg/common/db/s3/s3.go
@@ -24,7 +24,7 @@ import (
type PartLimit struct {
MinPartSize int64 `json:"minPartSize"`
MaxPartSize int64 `json:"maxPartSize"`
- MaxNumSize int `json:"maxNumSize"`
+ MaxNumSize int64 `json:"maxNumSize"`
}
type InitiateMultipartUploadResult struct {
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index 4039257f1..dbb2ff464 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -16,9 +16,10 @@ package relation
import (
"context"
- "github.com/OpenIMSDK/protocol/user"
"time"
+ "github.com/OpenIMSDK/protocol/user"
+
"github.com/OpenIMSDK/tools/pagination"
)
diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go
index c10518056..f27ebc805 100644
--- a/pkg/common/discoveryregister/kubernetes/kubernetes.go
+++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go
@@ -18,15 +18,17 @@ import (
"context"
"errors"
"fmt"
- "github.com/stathat/consistent"
"os"
"strconv"
"strings"
+ "github.com/stathat/consistent"
+
"google.golang.org/grpc"
"github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/log"
+
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
)
@@ -102,7 +104,7 @@ func getSelfHost(ctx context.Context) string {
return host
}
-// like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88
+// like openimserver-openim-msggateway-0.openimserver-openim-msggateway-headless.openim-lin.svc.cluster.local:88.
func getMsgGatewayHost(ctx context.Context) []string {
port := 88
instance := "openimserver"
@@ -166,7 +168,7 @@ func (cli *K8sDR) CloseConn(conn *grpc.ClientConn) {
conn.Close()
}
-// do not use this method for call rpc
+// do not use this method for call rpc.
func (cli *K8sDR) GetClientLocalConns() map[string][]*grpc.ClientConn {
fmt.Println("should not call this function!!!!!!!!!!!!!!!!!!!!!!!!!")
return nil
diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go
index abad0075a..56167d7f4 100644
--- a/pkg/rpcclient/msg.go
+++ b/pkg/rpcclient/msg.go
@@ -17,6 +17,7 @@ package rpcclient
import (
"context"
"encoding/json"
+
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"
diff --git a/pkg/util/flag/flag.go b/pkg/util/flag/flag.go
index 7bbacf444..0a8e527ab 100644
--- a/pkg/util/flag/flag.go
+++ b/pkg/util/flag/flag.go
@@ -1,7 +1,21 @@
+// Copyright © 2024 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package flag
import (
- goFlag "flag"
+ "flag"
"log"
"strings"
@@ -29,7 +43,7 @@ func WarnWordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedNam
// InitFlags normalizes, parses, then logs the command line flags.
func InitFlags() {
pflag.CommandLine.SetNormalizeFunc(WordSepNormalizeFunc)
- pflag.CommandLine.AddGoFlagSet(goFlag.CommandLine)
+ pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
}
// PrintFlags logs the flags in the flagset.
diff --git a/pkg/util/genutil/genutil.go b/pkg/util/genutil/genutil.go
index 36da89bbb..0948a7c49 100644
--- a/pkg/util/genutil/genutil.go
+++ b/pkg/util/genutil/genutil.go
@@ -1,3 +1,17 @@
+// Copyright © 2024 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package genutil
import (
diff --git a/pkg/util/genutil/genutil_test.go b/pkg/util/genutil/genutil_test.go
index 0ee85df27..050d14040 100644
--- a/pkg/util/genutil/genutil_test.go
+++ b/pkg/util/genutil/genutil_test.go
@@ -1,3 +1,17 @@
+// Copyright © 2024 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package genutil
import (
diff --git a/scripts/advertise.sh b/scripts/advertise.sh
index 9c8c284ad..3effc4f2b 100755
--- a/scripts/advertise.sh
+++ b/scripts/advertise.sh
@@ -23,7 +23,7 @@ trap 'openim::util::onCtrlC' INT
print_with_delay() {
text="$1"
delay="$2"
-
+
for i in $(seq 0 $((${#text}-1))); do
printf "${text:$i:1}"
sleep $delay
@@ -34,7 +34,7 @@ print_with_delay() {
print_progress() {
total="$1"
delay="$2"
-
+
printf "["
for i in $(seq 1 $total); do
printf "#"
@@ -44,14 +44,14 @@ print_progress() {
}
function openim_logo() {
- # Set text color to cyan for header and URL
- echo -e "\033[0;36m"
+ # Set text color to cyan for header and URL
+ echo -e "\033[0;36m"
+
+ # Display fancy ASCII Art logo
+ # look http://patorjk.com/software/taag/#p=display&h=1&v=1&f=Doh&t=OpenIM
+ print_with_delay '
+
- # Display fancy ASCII Art logo
- # look http://patorjk.com/software/taag/#p=display&h=1&v=1&f=Doh&t=OpenIM
- print_with_delay '
-
-
OOOOOOOOO IIIIIIIIIIMMMMMMMM MMMMMMMM
OO:::::::::OO I::::::::IM:::::::M M:::::::M
OO:::::::::::::OO I::::::::IM::::::::M M::::::::M
@@ -68,45 +68,45 @@ O:::::::OOO:::::::O p:::::ppppp:::::::pe::::::::e n::::n n::::nII:
OO:::::::::::::OO p::::::::::::::::p e::::::::eeeeeeee n::::n n::::nI::::::::IM::::::M M::::::M
OO:::::::::OO p::::::::::::::pp ee:::::::::::::e n::::n n::::nI::::::::IM::::::M M::::::M
OOOOOOOOO p::::::pppppppp eeeeeeeeeeeeee nnnnnn nnnnnnIIIIIIIIIIMMMMMMMM MMMMMMMM
- p:::::p
- p:::::p
- p:::::::p
- p:::::::p
- p:::::::p
- ppppppppp
-
- ' 0.0001
-
- # Display product URL
- print_with_delay "Discover more and contribute at: https://github.com/openimsdk/open-im-server" 0.01
-
- # Reset text color back to normal
- echo -e "\033[0m"
-
- # Set text color to green for product description
- echo -e "\033[1;32m"
-
- print_with_delay "Open-IM-Server: Reinventing Instant Messaging" 0.01
- print_progress 50 0.02
-
- print_with_delay "Open-IM-Server is not just a product; it's a revolution. It's about bringing the power of seamless," 0.01
- print_with_delay "real-time messaging to your fingertips. And it's about joining a global community of developers, dedicated to pushing the boundaries of what's possible." 0.01
-
- print_progress 50 0.02
-
- # Reset text color back to normal
- echo -e "\033[0m"
-
- # Set text color to yellow for the Slack link
- echo -e "\033[1;33m"
-
- print_with_delay "Join our developer community on Slack: https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q" 0.01
-
- # Reset text color back to normal
- echo -e "\033[0m"
+ p:::::p
+ p:::::p
+ p:::::::p
+ p:::::::p
+ p:::::::p
+ ppppppppp
+
+ ' 0.0001
+
+ # Display product URL
+ print_with_delay "Discover more and contribute at: https://github.com/openimsdk/open-im-server" 0.01
+
+ # Reset text color back to normal
+ echo -e "\033[0m"
+
+ # Set text color to green for product description
+ echo -e "\033[1;32m"
+
+ print_with_delay "Open-IM-Server: Reinventing Instant Messaging" 0.01
+ print_progress 50 0.02
+
+ print_with_delay "Open-IM-Server is not just a product; it's a revolution. It's about bringing the power of seamless," 0.01
+ print_with_delay "real-time messaging to your fingertips. And it's about joining a global community of developers, dedicated to pushing the boundaries of what's possible." 0.01
+
+ print_progress 50 0.02
+
+ # Reset text color back to normal
+ echo -e "\033[0m"
+
+ # Set text color to yellow for the Slack link
+ echo -e "\033[1;33m"
+
+ print_with_delay "Join our developer community on Slack: https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q" 0.01
+
+ # Reset text color back to normal
+ echo -e "\033[0m"
}
function main() {
- openim_logo
+ openim_logo
}
main "$@"
diff --git a/scripts/bash_beautify.py b/scripts/bash_beautify.py
new file mode 100755
index 000000000..54c6fa0ad
--- /dev/null
+++ b/scripts/bash_beautify.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#**************************************************************************
+# Copyright (C) 2011, Paul Lutus *
+# *
+# This program is free software; you can redistribute it and/or modify *
+# it under the terms of the GNU General Public License as published by *
+# the Free Software Foundation; either version 2 of the License, or *
+# (at your option) any later version. *
+# *
+# This program is distributed in the hope that it will be useful, *
+# but WITHOUT ANY WARRANTY; without even the implied warranty of *
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+# GNU General Public License for more details. *
+# *
+# You should have received a copy of the GNU General Public License *
+# along with this program; if not, write to the *
+# Free Software Foundation, Inc., *
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+#**************************************************************************
+
+import re
+import sys
+
+PVERSION = '1.0'
+
+
+class BeautifyBash:
+
+ def __init__(self):
+ self.tab_str = ' '
+ self.tab_size = 2
+
+ def read_file(self, fp):
+ with open(fp) as f:
+ return f.read()
+
+ def write_file(self, fp, data):
+ with open(fp, 'w') as f:
+ f.write(data)
+
+ def beautify_string(self, data, path=''):
+ tab = 0
+ case_stack = []
+ in_here_doc = False
+ defer_ext_quote = False
+ in_ext_quote = False
+ ext_quote_string = ''
+ here_string = ''
+ output = []
+ line = 1
+ for record in re.split('\n', data):
+ record = record.rstrip()
+ stripped_record = record.strip()
+
+ # collapse multiple quotes between ' ... '
+ test_record = re.sub(r'\'.*?\'', '', stripped_record)
+ # collapse multiple quotes between " ... "
+ test_record = re.sub(r'".*?"', '', test_record)
+ # collapse multiple quotes between ` ... `
+ test_record = re.sub(r'`.*?`', '', test_record)
+ # collapse multiple quotes between \` ... ' (weird case)
+ test_record = re.sub(r'\\`.*?\'', '', test_record)
+ # strip out any escaped single characters
+ test_record = re.sub(r'\\.', '', test_record)
+ # remove '#' comments
+ test_record = re.sub(r'(\A|\s)(#.*)', '', test_record, 1)
+ if(not in_here_doc):
+ if(re.search('<<-?', test_record)):
+ here_string = re.sub(
+ '.*<<-?\s*[\'|"]?([_|\w]+)[\'|"]?.*', '\\1', stripped_record, 1)
+ in_here_doc = (len(here_string) > 0)
+ if(in_here_doc): # pass on with no changes
+ output.append(record)
+ # now test for here-doc termination string
+ if(re.search(here_string, test_record) and not re.search('<<', test_record)):
+ in_here_doc = False
+ else: # not in here doc
+ if(in_ext_quote):
+ if(re.search(ext_quote_string, test_record)):
+ # provide line after quotes
+ test_record = re.sub(
+ '.*%s(.*)' % ext_quote_string, '\\1', test_record, 1)
+ in_ext_quote = False
+ else: # not in ext quote
+ if(re.search(r'(\A|\s)(\'|")', test_record)):
+ # apply only after this line has been processed
+ defer_ext_quote = True
+ ext_quote_string = re.sub(
+ '.*([\'"]).*', '\\1', test_record, 1)
+ # provide line before quote
+ test_record = re.sub(
+ '(.*)%s.*' % ext_quote_string, '\\1', test_record, 1)
+ if(in_ext_quote):
+ # pass on unchanged
+ output.append(record)
+ else: # not in ext quote
+ inc = len(re.findall(
+ '(\s|\A|;)(case|then|do)(;|\Z|\s)', test_record))
+ inc += len(re.findall('(\{|\(|\[)', test_record))
+ outc = len(re.findall(
+ '(\s|\A|;)(esac|fi|done|elif)(;|\)|\||\Z|\s)', test_record))
+ outc += len(re.findall('(\}|\)|\])', test_record))
+ if(re.search(r'\besac\b', test_record)):
+ if(len(case_stack) == 0):
+ sys.stderr.write(
+ 'File %s: error: "esac" before "case" in line %d.\n' % (
+ path, line)
+ )
+ else:
+ outc += case_stack.pop()
+ # sepcial handling for bad syntax within case ... esac
+ if(len(case_stack) > 0):
+ if(re.search('\A[^(]*\)', test_record)):
+ # avoid overcount
+ outc -= 2
+ case_stack[-1] += 1
+ if(re.search(';;', test_record)):
+ outc += 1
+ case_stack[-1] -= 1
+ # an ad-hoc solution for the "else" keyword
+ else_case = (
+ 0, -1)[re.search('^(else)', test_record) != None]
+ net = inc - outc
+ tab += min(net, 0)
+ extab = tab + else_case
+ extab = max(0, extab)
+ output.append(
+ (self.tab_str * self.tab_size * extab) + stripped_record)
+ tab += max(net, 0)
+ if(defer_ext_quote):
+ in_ext_quote = True
+ defer_ext_quote = False
+ if(re.search(r'\bcase\b', test_record)):
+ case_stack.append(0)
+ line += 1
+ error = (tab != 0)
+ if(error):
+ sys.stderr.write(
+ 'File %s: error: indent/outdent mismatch: %d.\n' % (path, tab))
+ return '\n'.join(output), error
+
+ def beautify_file(self, path):
+ error = False
+ if(path == '-'):
+ data = sys.stdin.read()
+ result, error = self.beautify_string(data, '(stdin)')
+ sys.stdout.write(result)
+ else: # named file
+ data = self.read_file(path)
+ result, error = self.beautify_string(data, path)
+ if(data != result):
+ # make a backup copy
+ self.write_file(path + '~', data)
+ self.write_file(path, result)
+ return error
+
+ def main(self):
+ error = False
+ sys.argv.pop(0)
+ if(len(sys.argv) < 1):
+ sys.stderr.write(
+ 'usage: shell script filenames or \"-\" for stdin.\n')
+ else:
+ for path in sys.argv:
+ error |= self.beautify_file(path)
+ sys.exit((0, 1)[error])
+
+# if not called as a module
+if(__name__ == '__main__'):
+ BeautifyBash().main()
+
diff --git a/scripts/build-all-service.sh b/scripts/build-all-service.sh
index 4b5c0613a..b5578fca6 100755
--- a/scripts/build-all-service.sh
+++ b/scripts/build-all-service.sh
@@ -31,7 +31,7 @@ source "${OPENIM_ROOT}/scripts/lib/init.sh"
# CPU core number
pushd "${OPENIM_ROOT}/tools/ncpu" >/dev/null
- cpu_count=$(go run .)
+cpu_count=$(go run .)
popd >/dev/null
openim::color::echo ${GREEN_PREFIX} "======> cpu_count=$cpu_count"
@@ -42,7 +42,7 @@ compile_count=$((cpu_count / 2))
# For help output
ARGHELP=""
if [[ "$#" -gt 0 ]]; then
- ARGHELP="'$*'"
+ ARGHELP="'$*'"
fi
openim::color::echo $COLOR_CYAN "NOTE: $0 has been replaced by 'make multiarch' or 'make build'"
@@ -61,15 +61,15 @@ echo " ./scripts/build-all-service.sh BINS=openim-api V=1 DEBUG=1"
echo
if [ -z "$*" ]; then
- openim::log::info "no args, build all service"
- make --no-print-directory -C "${OPENIM_ROOT}" -j$compile_count build
+ openim::log::info "no args, build all service"
+ make --no-print-directory -C "${OPENIM_ROOT}" -j$compile_count build
else
- openim::log::info "build service: $*"
- make --no-print-directory -C "${OPENIM_ROOT}" -j$compile_count build "$*"
+ openim::log::info "build service: $*"
+ make --no-print-directory -C "${OPENIM_ROOT}" -j$compile_count build "$*"
fi
if [ $? -eq 0 ]; then
- openim::log::success "all service build success, run 'make start' or './scripts/start-all.sh'"
+ openim::log::success "all service build success, run 'make start' or './scripts/start-all.sh'"
else
- openim::log::error "make build Error, script exits"
+ openim::log::error "make build Error, script exits"
fi
diff --git a/scripts/check-all.sh b/scripts/check-all.sh
index 72a34a5e5..1f6b740e6 100755
--- a/scripts/check-all.sh
+++ b/scripts/check-all.sh
@@ -14,10 +14,10 @@
# limitations under the License.
# This script is check openim service is running normally
-#
+#
# Usage: `scripts/check-all.sh`.
# Encapsulated as: `make check`.
-# READ: https://github.com/openimsdk/open-im-server/tree/main/scripts/install/environment.sh
+# READ: https://github.com/openimsdk/open-im-server/tree/main/scripts/install/environment.sh
set -o errexit
set -o nounset
@@ -34,19 +34,19 @@ openim::log::status "Check all dependent service ports"
# Elegant printing function
# Elegant printing function
print_services_and_ports() {
- local service_names=("$@")
- local half_length=$((${#service_names[@]} / 2))
- local service_ports=("${service_names[@]:half_length}")
-
- echo "+-------------------------+----------+"
- echo "| Service Name | Port |"
- echo "+-------------------------+----------+"
-
- for ((index=0; index < half_length; index++)); do
- printf "| %-23s | %-8s |\n" "${service_names[$index]}" "${service_ports[$index]}"
- done
-
- echo "+-------------------------+----------+"
+ local service_names=("$@")
+ local half_length=$((${#service_names[@]} / 2))
+ local service_ports=("${service_names[@]:half_length}")
+
+ echo "+-------------------------+----------+"
+ echo "| Service Name | Port |"
+ echo "+-------------------------+----------+"
+
+ for ((index=0; index < half_length; index++)); do
+ printf "| %-23s | %-8s |\n" "${service_names[$index]}" "${service_ports[$index]}"
+ done
+
+ echo "+-------------------------+----------+"
}
# Assuming OPENIM_SERVER_NAME_TARGETS and OPENIM_SERVER_PORT_TARGETS are defined
@@ -67,10 +67,10 @@ set +e
# Later, after discarding Docker, the Docker keyword is unreliable, and Kubepods is used
if grep -qE 'docker|kubepods' /proc/1/cgroup || [ -f /.dockerenv ]; then
- openim::color::echo ${COLOR_CYAN} "Environment in the interior of the container"
+ openim::color::echo ${COLOR_CYAN} "Environment in the interior of the container"
else
- openim::color::echo ${COLOR_CYAN} "The environment is outside the container"
- openim::util::check_ports ${OPENIM_DEPENDENCY_PORT_LISTARIES[@]} || return 0
+ openim::color::echo ${COLOR_CYAN} "The environment is outside the container"
+ openim::util::check_ports ${OPENIM_DEPENDENCY_PORT_LISTARIES[@]} || return 0
fi
if [[ $? -ne 0 ]]; then
diff --git a/scripts/cherry-pick.sh b/scripts/cherry-pick.sh
index 5f13ef0e4..8a1f8dd79 100755
--- a/scripts/cherry-pick.sh
+++ b/scripts/cherry-pick.sh
@@ -118,7 +118,7 @@ function return_to_kansas {
openim::log::status "Aborting in-progress git am."
git am --abort >/dev/null 2>&1 || true
fi
-
+
# return to the starting branch and delete the PR text file
if [[ -z "${DRY_RUN}" ]]; then
echo
@@ -137,7 +137,7 @@ function make-a-pr() {
rel="$(basename "${BRANCH}")"
echo
openim::log::status "Creating a pull request on GitHub at ${GITHUB_USER}:${NEWBRANCH}"
-
+
local numandtitle
numandtitle=$(printf '%s\n' "${SUBJECTS[@]}")
prtext=$(cat <&2
- exit 1
- fi
- done
-
- if [[ "${conflicts}" != "true" ]]; then
- echo "!!! git am failed, likely because of an in-progress 'git am' or 'git rebase'"
+curl -o "/tmp/${pull}.patch" -sSL "https://github.com/${MAIN_REPO_ORG}/${MAIN_REPO_NAME}/pull/${pull}.patch"
+echo
+openim::log::status "About to attempt cherry pick of PR. To reattempt:"
+echo " $ git am -3 /tmp/${pull}.patch"
+echo
+git am -3 "/tmp/${pull}.patch" || {
+ conflicts=false
+ while unmerged=$(git status --porcelain | grep ^U) && [[ -n ${unmerged} ]] \
+ || [[ -e "${REBASEMAGIC}" ]]; do
+ conflicts=true # <-- We should have detected conflicts once
+ echo
+ openim::log::status "Conflicts detected:"
+ echo
+ (git status --porcelain | grep ^U) || echo "!!! None. Did you git am --continue?"
+ echo
+ openim::log::status "Please resolve the conflicts in another window (and remember to 'git add / git am --continue')"
+ read -p "+++ Proceed (anything other than 'y' aborts the cherry-pick)? [y/n] " -r
+ echo
+ if ! [[ "${REPLY}" =~ ^[yY]$ ]]; then
+ echo "Aborting." >&2
exit 1
fi
- }
+ done
+
+ if [[ "${conflicts}" != "true" ]]; then
+ echo "!!! git am failed, likely because of an in-progress 'git am' or 'git rebase'"
+ exit 1
+ fi
+}
- # set the subject
- subject=$(grep -m 1 "^Subject" "/tmp/${pull}.patch" | sed -e 's/Subject: \[PATCH//g' | sed 's/.*] //')
- SUBJECTS+=("#${pull}: ${subject}")
+# set the subject
+subject=$(grep -m 1 "^Subject" "/tmp/${pull}.patch" | sed -e 's/Subject: \[PATCH//g' | sed 's/.*] //')
+SUBJECTS+=("#${pull}: ${subject}")
- # remove the patch file from /tmp
- rm -f "/tmp/${pull}.patch"
+# remove the patch file from /tmp
+rm -f "/tmp/${pull}.patch"
done
gitamcleanup=false
# Re-generate docs (if needed)
if [[ -n "${REGENERATE_DOCS}" ]]; then
+echo
+echo "Regenerating docs..."
+if ! scripts/generate-docs.sh; then
echo
- echo "Regenerating docs..."
- if ! scripts/generate-docs.sh; then
- echo
- echo "scripts/gendoc.sh FAILED to complete."
- exit 1
- fi
+ echo "scripts/gendoc.sh FAILED to complete."
+ exit 1
+fi
fi
if [[ -n "${DRY_RUN}" ]]; then
- openim::log::error "!!! Skipping git push and PR creation because you set DRY_RUN."
- echo "To return to the branch you were in when you invoked this script:"
- echo
- echo " git checkout ${STARTINGBRANCH}"
- echo
- echo "To delete this branch:"
- echo
- echo " git branch -D ${NEWBRANCHUNIQ}"
- exit 0
+openim::log::error "!!! Skipping git push and PR creation because you set DRY_RUN."
+echo "To return to the branch you were in when you invoked this script:"
+echo
+echo " git checkout ${STARTINGBRANCH}"
+echo
+echo "To delete this branch:"
+echo
+echo " git branch -D ${NEWBRANCHUNIQ}"
+exit 0
fi
if git remote -v | grep ^"${FORK_REMOTE}" | grep "${MAIN_REPO_ORG}/${MAIN_REPO_NAME}.git"; then
- echo "!!! You have ${FORK_REMOTE} configured as your ${MAIN_REPO_ORG}/${MAIN_REPO_NAME}.git"
- echo "This isn't normal. Leaving you with push instructions:"
- echo
- openim::log::status "First manually push the branch this script created:"
- echo
- echo " git push REMOTE ${NEWBRANCHUNIQ}:${NEWBRANCH}"
- echo
- echo "where REMOTE is your personal fork (maybe ${UPSTREAM_REMOTE}? Consider swapping those.)."
- echo "OR consider setting UPSTREAM_REMOTE and FORK_REMOTE to different values."
- echo
- make-a-pr
- cleanbranch=""
- exit 0
+echo "!!! You have ${FORK_REMOTE} configured as your ${MAIN_REPO_ORG}/${MAIN_REPO_NAME}.git"
+echo "This isn't normal. Leaving you with push instructions:"
+echo
+openim::log::status "First manually push the branch this script created:"
+echo
+echo " git push REMOTE ${NEWBRANCHUNIQ}:${NEWBRANCH}"
+echo
+echo "where REMOTE is your personal fork (maybe ${UPSTREAM_REMOTE}? Consider swapping those.)."
+echo "OR consider setting UPSTREAM_REMOTE and FORK_REMOTE to different values."
+echo
+make-a-pr
+cleanbranch=""
+exit 0
fi
echo
@@ -248,8 +248,8 @@ echo " git push ${FORK_REMOTE} ${NEWBRANCHUNIQ}:${NEWBRANCH}"
echo
read -p "+++ Proceed (anything other than 'y' aborts the cherry-pick)? [y/n] " -r
if ! [[ "${REPLY}" =~ ^[yY]$ ]]; then
- echo "Aborting." >&2
- exit 1
+echo "Aborting." >&2
+exit 1
fi
git push "${FORK_REMOTE}" -f "${NEWBRANCHUNIQ}:${NEWBRANCH}"
diff --git a/scripts/common.sh b/scripts/common.sh
index 882641ae9..d67389d56 100755
--- a/scripts/common.sh
+++ b/scripts/common.sh
@@ -87,28 +87,28 @@ readonly OPENIM_CONTAINER_RSYNC_PORT=8730
#
# $1 - server architecture
openim::build::get_docker_wrapped_binaries() {
- local arch=$1
- local debian_base_version=v2.1.0
- local debian_iptables_version=v12.1.0
- ### If you change any of these lists, please also update DOCKERIZED_BINARIES
- ### in build/BUILD. And openim::golang::server_image_targets
-
- local targets=(
- "openim-api,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-cmdutils,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-crontask,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-msggateway,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-msgtransfer,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-push,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-rpc-auth,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-rpc-conversation,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-rpc-friend,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-rpc-group,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-rpc-msg,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-rpc-third,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- "openim-rpc-user,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
- )
- echo "${targets[@]}"
+local arch=$1
+local debian_base_version=v2.1.0
+local debian_iptables_version=v12.1.0
+### If you change any of these lists, please also update DOCKERIZED_BINARIES
+### in build/BUILD. And openim::golang::server_image_targets
+
+local targets=(
+ "openim-api,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-cmdutils,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-crontask,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-msggateway,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-msgtransfer,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-push,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-rpc-auth,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-rpc-conversation,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-rpc-friend,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-rpc-group,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-rpc-msg,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-rpc-third,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+ "openim-rpc-user,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
+)
+echo "${targets[@]}"
}
# ---------------------------------------------------------------------------
@@ -133,170 +133,170 @@ openim::build::get_docker_wrapped_binaries() {
# DOCKER_MOUNT_ARGS
# LOCAL_OUTPUT_BUILD_CONTEXT
function openim::build::verify_prereqs() {
- local -r require_docker=${1:-true}
- openim::log::status "Verifying Prerequisites...."
- openim::build::ensure_tar || return 1
- openim::build::ensure_rsync || return 1
- if ${require_docker}; then
- openim::build::ensure_docker_in_path || return 1
- openim::util::ensure_docker_daemon_connectivity || return 1
-
- if (( OPENIM_VERBOSE > 6 )); then
- openim::log::status "Docker Version:"
- "${DOCKER[@]}" version | openim::log::info_from_stdin
- fi
+local -r require_docker=${1:-true}
+openim::log::status "Verifying Prerequisites...."
+openim::build::ensure_tar || return 1
+openim::build::ensure_rsync || return 1
+if ${require_docker}; then
+ openim::build::ensure_docker_in_path || return 1
+ openim::util::ensure_docker_daemon_connectivity || return 1
+
+ if (( OPENIM_VERBOSE > 6 )); then
+ openim::log::status "Docker Version:"
+ "${DOCKER[@]}" version | openim::log::info_from_stdin
fi
-
- OPENIM_GIT_BRANCH=$(git symbolic-ref --short -q HEAD 2>/dev/null || true)
- OPENIM_ROOT_HASH=$(openim::build::short_hash "${HOSTNAME:-}:"${OPENIM_ROOT}":${OPENIM_GIT_BRANCH}")
- OPENIM_BUILD_IMAGE_TAG_BASE="build-${OPENIM_ROOT_HASH}"
- #OPENIM_BUILD_IMAGE_TAG="${OPENIM_BUILD_IMAGE_TAG_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
- #OPENIM_BUILD_IMAGE="${OPENIM_BUILD_IMAGE_REPO}:${OPENIM_BUILD_IMAGE_TAG}"
- OPENIM_BUILD_CONTAINER_NAME_BASE="openim-build-${OPENIM_ROOT_HASH}"
- #OPENIM_BUILD_CONTAINER_NAME="${OPENIM_BUILD_CONTAINER_NAME_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
- OPENIM_RSYNC_CONTAINER_NAME_BASE="openim-rsync-${OPENIM_ROOT_HASH}"
- #OPENIM_RSYNC_CONTAINER_NAME="${OPENIM_RSYNC_CONTAINER_NAME_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
- OPENIM_DATA_CONTAINER_NAME_BASE="openim-build-data-${OPENIM_ROOT_HASH}"
- #OPENIM_DATA_CONTAINER_NAME="${OPENIM_DATA_CONTAINER_NAME_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
- #DOCKER_MOUNT_ARGS=(--volumes-from "${OPENIM_DATA_CONTAINER_NAME}")
- #LOCAL_OUTPUT_BUILD_CONTEXT="${LOCAL_OUTPUT_IMAGE_STAGING}/${OPENIM_BUILD_IMAGE}"
-
- openim::version::get_version_vars
- #openim::version::save_version_vars "${OPENIM_ROOT}/.dockerized-openim-version-defs"
+fi
+
+OPENIM_GIT_BRANCH=$(git symbolic-ref --short -q HEAD 2>/dev/null || true)
+OPENIM_ROOT_HASH=$(openim::build::short_hash "${HOSTNAME:-}:${OPENIM_ROOT}:${OPENIM_GIT_BRANCH}")
+OPENIM_BUILD_IMAGE_TAG_BASE="build-${OPENIM_ROOT_HASH}"
+#OPENIM_BUILD_IMAGE_TAG="${OPENIM_BUILD_IMAGE_TAG_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
+#OPENIM_BUILD_IMAGE="${OPENIM_BUILD_IMAGE_REPO}:${OPENIM_BUILD_IMAGE_TAG}"
+OPENIM_BUILD_CONTAINER_NAME_BASE="openim-build-${OPENIM_ROOT_HASH}"
+#OPENIM_BUILD_CONTAINER_NAME="${OPENIM_BUILD_CONTAINER_NAME_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
+OPENIM_RSYNC_CONTAINER_NAME_BASE="openim-rsync-${OPENIM_ROOT_HASH}"
+#OPENIM_RSYNC_CONTAINER_NAME="${OPENIM_RSYNC_CONTAINER_NAME_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
+OPENIM_DATA_CONTAINER_NAME_BASE="openim-build-data-${OPENIM_ROOT_HASH}"
+#OPENIM_DATA_CONTAINER_NAME="${OPENIM_DATA_CONTAINER_NAME_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
+#DOCKER_MOUNT_ARGS=(--volumes-from "${OPENIM_DATA_CONTAINER_NAME}")
+#LOCAL_OUTPUT_BUILD_CONTEXT="${LOCAL_OUTPUT_IMAGE_STAGING}/${OPENIM_BUILD_IMAGE}"
+
+openim::version::get_version_vars
+#openim::version::save_version_vars "${OPENIM_ROOT}/.dockerized-openim-version-defs"
}
# ---------------------------------------------------------------------------
# Utility functions
function openim::build::docker_available_on_osx() {
- if [[ -z "${DOCKER_HOST}" ]]; then
- if [[ -S "/var/run/docker.sock" ]]; then
- openim::log::status "Using Docker for MacOS"
- return 0
- fi
-
- openim::log::status "No docker host is set. Checking options for setting one..."
- if [[ -z "$(which docker-machine)" ]]; then
- openim::log::status "It looks like you're running Mac OS X, yet neither Docker for Mac nor docker-machine can be found."
- openim::log::status "See: https://docs.docker.com/engine/installation/mac/ for installation instructions."
- return 1
+if [[ -z "${DOCKER_HOST}" ]]; then
+ if [[ -S "/var/run/docker.sock" ]]; then
+ openim::log::status "Using Docker for MacOS"
+ return 0
+ fi
+
+ openim::log::status "No docker host is set. Checking options for setting one..."
+ if [[ -z "$(which docker-machine)" ]]; then
+ openim::log::status "It looks like you're running Mac OS X, yet neither Docker for Mac nor docker-machine can be found."
+ openim::log::status "See: https://docs.docker.com/engine/installation/mac/ for installation instructions."
+ return 1
elif [[ -n "$(which docker-machine)" ]]; then
- openim::build::prepare_docker_machine
- fi
+ openim::build::prepare_docker_machine
fi
+fi
}
function openim::build::prepare_docker_machine() {
- openim::log::status "docker-machine was found."
-
- local available_memory_bytes
- available_memory_bytes=$(sysctl -n hw.memsize 2>/dev/null)
-
- local bytes_in_mb=1048576
-
- # Give virtualbox 1/2 the system memory. Its necessary to divide by 2, instead
- # of multiple by .5, because bash can only multiply by ints.
- local memory_divisor=2
-
- local virtualbox_memory_mb=$(( available_memory_bytes / (bytes_in_mb * memory_divisor) ))
-
- docker-machine inspect "${DOCKER_MACHINE_NAME}" &> /dev/null || {
- openim::log::status "Creating a machine to build OPENIM"
- docker-machine create --driver "${DOCKER_MACHINE_DRIVER}" \
- --virtualbox-memory "${virtualbox_memory_mb}" \
- --engine-env HTTP_PROXY="${OPENIMRNETES_HTTP_PROXY:-}" \
- --engine-env HTTPS_PROXY="${OPENIMRNETES_HTTPS_PROXY:-}" \
- --engine-env NO_PROXY="${OPENIMRNETES_NO_PROXY:-127.0.0.1}" \
- "${DOCKER_MACHINE_NAME}" > /dev/null || {
- openim::log::error "Something went wrong creating a machine."
- openim::log::error "Try the following: "
- openim::log::error "docker-machine create -d ${DOCKER_MACHINE_DRIVER} --virtualbox-memory ${virtualbox_memory_mb} ${DOCKER_MACHINE_NAME}"
- return 1
- }
+openim::log::status "docker-machine was found."
+
+local available_memory_bytes
+available_memory_bytes=$(sysctl -n hw.memsize 2>/dev/null)
+
+local bytes_in_mb=1048576
+
+# Give virtualbox 1/2 the system memory. Its necessary to divide by 2, instead
+# of multiple by .5, because bash can only multiply by ints.
+local memory_divisor=2
+
+local virtualbox_memory_mb=$(( available_memory_bytes / (bytes_in_mb * memory_divisor) ))
+
+docker-machine inspect "${DOCKER_MACHINE_NAME}" &> /dev/null || {
+ openim::log::status "Creating a machine to build OPENIM"
+ docker-machine create --driver "${DOCKER_MACHINE_DRIVER}" \
+ --virtualbox-memory "${virtualbox_memory_mb}" \
+ --engine-env HTTP_PROXY="${OPENIMRNETES_HTTP_PROXY:-}" \
+ --engine-env HTTPS_PROXY="${OPENIMRNETES_HTTPS_PROXY:-}" \
+ --engine-env NO_PROXY="${OPENIMRNETES_NO_PROXY:-127.0.0.1}" \
+ "${DOCKER_MACHINE_NAME}" > /dev/null || {
+ openim::log::error "Something went wrong creating a machine."
+ openim::log::error "Try the following: "
+ openim::log::error "docker-machine create -d ${DOCKER_MACHINE_DRIVER} --virtualbox-memory ${virtualbox_memory_mb} ${DOCKER_MACHINE_NAME}"
+ return 1
}
- docker-machine start "${DOCKER_MACHINE_NAME}" &> /dev/null
- # it takes `docker-machine env` a few seconds to work if the machine was just started
- local docker_machine_out
- while ! docker_machine_out=$(docker-machine env "${DOCKER_MACHINE_NAME}" 2>&1); do
- if [[ ${docker_machine_out} =~ "Error checking TLS connection" ]]; then
- echo "${docker_machine_out}"
- docker-machine regenerate-certs "${DOCKER_MACHINE_NAME}"
- else
- sleep 1
- fi
- done
- eval "$(docker-machine env "${DOCKER_MACHINE_NAME}")"
- openim::log::status "A Docker host using docker-machine named '${DOCKER_MACHINE_NAME}' is ready to go!"
- return 0
+}
+docker-machine start "${DOCKER_MACHINE_NAME}" &> /dev/null
+# it takes `docker-machine env` a few seconds to work if the machine was just started
+local docker_machine_out
+while ! docker_machine_out=$(docker-machine env "${DOCKER_MACHINE_NAME}" 2>&1); do
+ if [[ ${docker_machine_out} =~ "Error checking TLS connection" ]]; then
+ echo "${docker_machine_out}"
+ docker-machine regenerate-certs "${DOCKER_MACHINE_NAME}"
+ else
+ sleep 1
+ fi
+done
+eval "$(docker-machine env "${DOCKER_MACHINE_NAME}")"
+openim::log::status "A Docker host using docker-machine named '${DOCKER_MACHINE_NAME}' is ready to go!"
+return 0
}
function openim::build::is_gnu_sed() {
- [[ $(sed --version 2>&1) == *GNU* ]]
+[[ $(sed --version 2>&1) == *GNU* ]]
}
function openim::build::ensure_rsync() {
- if [[ -z "$(which rsync)" ]]; then
- openim::log::error "Can't find 'rsync' in PATH, please fix and retry."
- return 1
- fi
+if [[ -z "$(which rsync)" ]]; then
+ openim::log::error "Can't find 'rsync' in PATH, please fix and retry."
+ return 1
+fi
}
function openim::build::update_dockerfile() {
- if openim::build::is_gnu_sed; then
- sed_opts=(-i)
- else
- sed_opts=(-i '')
- fi
- sed "${sed_opts[@]}" "s/OPENIM_BUILD_IMAGE_CROSS_TAG/${OPENIM_BUILD_IMAGE_CROSS_TAG}/" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
+if openim::build::is_gnu_sed; then
+ sed_opts=(-i)
+else
+ sed_opts=(-i '')
+fi
+sed "${sed_opts[@]}" "s/OPENIM_BUILD_IMAGE_CROSS_TAG/${OPENIM_BUILD_IMAGE_CROSS_TAG}/" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
}
function openim::build::set_proxy() {
- if [[ -n "${OPENIMRNETES_HTTPS_PROXY:-}" ]]; then
- echo "ENV https_proxy $OPENIMRNETES_HTTPS_PROXY" >> "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
- fi
- if [[ -n "${OPENIMRNETES_HTTP_PROXY:-}" ]]; then
- echo "ENV http_proxy $OPENIMRNETES_HTTP_PROXY" >> "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
- fi
- if [[ -n "${OPENIMRNETES_NO_PROXY:-}" ]]; then
- echo "ENV no_proxy $OPENIMRNETES_NO_PROXY" >> "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
- fi
+if [[ -n "${OPENIMRNETES_HTTPS_PROXY:-}" ]]; then
+ echo "ENV https_proxy $OPENIMRNETES_HTTPS_PROXY" >> "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
+fi
+if [[ -n "${OPENIMRNETES_HTTP_PROXY:-}" ]]; then
+ echo "ENV http_proxy $OPENIMRNETES_HTTP_PROXY" >> "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
+fi
+if [[ -n "${OPENIMRNETES_NO_PROXY:-}" ]]; then
+ echo "ENV no_proxy $OPENIMRNETES_NO_PROXY" >> "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
+fi
}
function openim::build::ensure_docker_in_path() {
- if [[ -z "$(which docker)" ]]; then
- openim::log::error "Can't find 'docker' in PATH, please fix and retry."
- openim::log::error "See https://docs.docker.com/installation/#installation for installation instructions."
- return 1
- fi
+if [[ -z "$(which docker)" ]]; then
+ openim::log::error "Can't find 'docker' in PATH, please fix and retry."
+ openim::log::error "See https://docs.docker.com/installation/#installation for installation instructions."
+ return 1
+fi
}
function openim::build::ensure_tar() {
- if [[ -n "${TAR:-}" ]]; then
- return
- fi
-
- # Find gnu tar if it is available, bomb out if not.
- TAR=tar
- if which gtar &>/dev/null; then
- TAR=gtar
- else
- if which gnutar &>/dev/null; then
- TAR=gnutar
- fi
- fi
- if ! "${TAR}" --version | grep -q GNU; then
- echo " !!! Cannot find GNU tar. Build on Linux or install GNU tar"
- echo " on Mac OS X (brew install gnu-tar)."
- return 1
+if [[ -n "${TAR:-}" ]]; then
+ return
+fi
+
+# Find gnu tar if it is available, bomb out if not.
+TAR=tar
+if which gtar &>/dev/null; then
+ TAR=gtar
+else
+ if which gnutar &>/dev/null; then
+ TAR=gnutar
fi
+fi
+if ! "${TAR}" --version | grep -q GNU; then
+ echo " !!! Cannot find GNU tar. Build on Linux or install GNU tar"
+ echo " on Mac OS X (brew install gnu-tar)."
+ return 1
+fi
}
function openim::build::has_docker() {
- which docker &> /dev/null
+which docker &> /dev/null
}
function openim::build::has_ip() {
- which ip &> /dev/null && ip -Version | grep 'iproute2' &> /dev/null
+which ip &> /dev/null && ip -Version | grep 'iproute2' &> /dev/null
}
# Detect if a specific image exists
@@ -304,12 +304,12 @@ function openim::build::has_ip() {
# $1 - image repo name
# $2 - image tag
function openim::build::docker_image_exists() {
- [[ -n $1 && -n $2 ]] || {
- openim::log::error "Internal error. Image not specified in docker_image_exists."
- exit 2
- }
+[[ -n $1 && -n $2 ]] || {
+ openim::log::error "Internal error. Image not specified in docker_image_exists."
+ exit 2
+}
- [[ $("${DOCKER[@]}" images -q "${1}:${2}") ]]
+[[ $("${DOCKER[@]}" images -q "${1}:${2}") ]]
}
# Delete all images that match a tag prefix except for the "current" version
@@ -318,21 +318,21 @@ function openim::build::docker_image_exists() {
# $2: The tag base. We consider any image that matches $2*
# $3: The current image not to delete if provided
function openim::build::docker_delete_old_images() {
- # In Docker 1.12, we can replace this with
- # docker images "$1" --format "{{.Tag}}"
- for tag in $("${DOCKER[@]}" images "${1}" | tail -n +2 | awk '{print $2}') ; do
- if [[ "${tag}" != "${2}"* ]] ; then
- V=3 openim::log::status "Keeping image ${1}:${tag}"
- continue
- fi
-
- if [[ -z "${3:-}" || "${tag}" != "${3}" ]] ; then
- V=2 openim::log::status "Deleting image ${1}:${tag}"
- "${DOCKER[@]}" rmi "${1}:${tag}" >/dev/null
- else
- V=3 openim::log::status "Keeping image ${1}:${tag}"
- fi
- done
+# In Docker 1.12, we can replace this with
+# docker images "$1" --format "{{.Tag}}"
+for tag in $("${DOCKER[@]}" images "${1}" | tail -n +2 | awk '{print $2}') ; do
+ if [[ "${tag}" != "${2}"* ]] ; then
+ V=3 openim::log::status "Keeping image ${1}:${tag}"
+ continue
+ fi
+
+ if [[ -z "${3:-}" || "${tag}" != "${3}" ]] ; then
+ V=2 openim::log::status "Deleting image ${1}:${tag}"
+ "${DOCKER[@]}" rmi "${1}:${tag}" >/dev/null
+ else
+ V=3 openim::log::status "Keeping image ${1}:${tag}"
+ fi
+done
}
# Stop and delete all containers that match a pattern
@@ -340,36 +340,36 @@ function openim::build::docker_delete_old_images() {
# $1: The base container prefix
# $2: The current container to keep, if provided
function openim::build::docker_delete_old_containers() {
- # In Docker 1.12 we can replace this line with
- # docker ps -a --format="{{.Names}}"
- for container in $("${DOCKER[@]}" ps -a | tail -n +2 | awk '{print $NF}') ; do
- if [[ "${container}" != "${1}"* ]] ; then
- V=3 openim::log::status "Keeping container ${container}"
- continue
- fi
- if [[ -z "${2:-}" || "${container}" != "${2}" ]] ; then
- V=2 openim::log::status "Deleting container ${container}"
- openim::build::destroy_container "${container}"
- else
- V=3 openim::log::status "Keeping container ${container}"
- fi
- done
+# In Docker 1.12 we can replace this line with
+# docker ps -a --format="{{.Names}}"
+for container in $("${DOCKER[@]}" ps -a | tail -n +2 | awk '{print $NF}') ; do
+ if [[ "${container}" != "${1}"* ]] ; then
+ V=3 openim::log::status "Keeping container ${container}"
+ continue
+ fi
+ if [[ -z "${2:-}" || "${container}" != "${2}" ]] ; then
+ V=2 openim::log::status "Deleting container ${container}"
+ openim::build::destroy_container "${container}"
+ else
+ V=3 openim::log::status "Keeping container ${container}"
+ fi
+done
}
# Takes $1 and computes a short has for it. Useful for unique tag generation
function openim::build::short_hash() {
- [[ $# -eq 1 ]] || {
- openim::log::error "Internal error. No data based to short_hash."
- exit 2
- }
+[[ $# -eq 1 ]] || {
+ openim::log::error "Internal error. No data based to short_hash."
+ exit 2
+}
- local short_hash
- if which md5 >/dev/null 2>&1; then
- short_hash=$(md5 -q -s "$1")
- else
- short_hash=$(echo -n "$1" | md5sum)
- fi
- echo "${short_hash:0:10}"
+local short_hash
+if which md5 >/dev/null 2>&1; then
+ short_hash=$(md5 -q -s "$1")
+else
+ short_hash=$(echo -n "$1" | md5sum)
+fi
+echo "${short_hash:0:10}"
}
# Pedantically kill, wait-on and remove a container. The -f -v options
@@ -377,15 +377,15 @@ function openim::build::short_hash() {
# container, wait to ensure it's stopped, then try the remove. This is
# a workaround for bug https://github.com/docker/docker/issues/3968.
function openim::build::destroy_container() {
- "${DOCKER[@]}" kill "$1" >/dev/null 2>&1 || true
- if [[ $("${DOCKER[@]}" version --format '{{.Server.Version}}') = 17.06.0* ]]; then
- # Workaround https://github.com/moby/moby/issues/33948.
- # TODO: remove when 17.06.0 is not relevant anymore
- DOCKER_API_VERSION=v1.29 "${DOCKER[@]}" wait "$1" >/dev/null 2>&1 || true
- else
- "${DOCKER[@]}" wait "$1" >/dev/null 2>&1 || true
- fi
- "${DOCKER[@]}" rm -f -v "$1" >/dev/null 2>&1 || true
+"${DOCKER[@]}" kill "$1" >/dev/null 2>&1 || true
+if [[ $("${DOCKER[@]}" version --format '{{.Server.Version}}') = 17.06.0* ]]; then
+ # Workaround https://github.com/moby/moby/issues/33948.
+ # TODO: remove when 17.06.0 is not relevant anymore
+ DOCKER_API_VERSION=v1.29 "${DOCKER[@]}" wait "$1" >/dev/null 2>&1 || true
+else
+ "${DOCKER[@]}" wait "$1" >/dev/null 2>&1 || true
+fi
+"${DOCKER[@]}" rm -f -v "$1" >/dev/null 2>&1 || true
}
# ---------------------------------------------------------------------------
@@ -393,47 +393,47 @@ function openim::build::destroy_container() {
function openim::build::clean() {
- if openim::build::has_docker ; then
- openim::build::docker_delete_old_containers "${OPENIM_BUILD_CONTAINER_NAME_BASE}"
- openim::build::docker_delete_old_containers "${OPENIM_RSYNC_CONTAINER_NAME_BASE}"
- openim::build::docker_delete_old_containers "${OPENIM_DATA_CONTAINER_NAME_BASE}"
- openim::build::docker_delete_old_images "${OPENIM_BUILD_IMAGE_REPO}" "${OPENIM_BUILD_IMAGE_TAG_BASE}"
-
- V=2 openim::log::status "Cleaning all untagged docker images"
- "${DOCKER[@]}" rmi "$("${DOCKER[@]}" images -q --filter 'dangling=true')" 2> /dev/null || true
- fi
-
- if [[ -d "${LOCAL_OUTPUT_ROOT}" ]]; then
- openim::log::status "Removing _output directory"
- rm -rf "${LOCAL_OUTPUT_ROOT}"
- fi
+if openim::build::has_docker ; then
+ openim::build::docker_delete_old_containers "${OPENIM_BUILD_CONTAINER_NAME_BASE}"
+ openim::build::docker_delete_old_containers "${OPENIM_RSYNC_CONTAINER_NAME_BASE}"
+ openim::build::docker_delete_old_containers "${OPENIM_DATA_CONTAINER_NAME_BASE}"
+ openim::build::docker_delete_old_images "${OPENIM_BUILD_IMAGE_REPO}" "${OPENIM_BUILD_IMAGE_TAG_BASE}"
+
+ V=2 openim::log::status "Cleaning all untagged docker images"
+ "${DOCKER[@]}" rmi "$("${DOCKER[@]}" images -q --filter 'dangling=true')" 2> /dev/null || true
+fi
+
+if [[ -d "${LOCAL_OUTPUT_ROOT}" ]]; then
+ openim::log::status "Removing _output directory"
+ rm -rf "${LOCAL_OUTPUT_ROOT}"
+fi
}
# Set up the context directory for the openim-build image and build it.
function openim::build::build_image() {
- mkdir -p "${LOCAL_OUTPUT_BUILD_CONTEXT}"
- # Make sure the context directory owned by the right user for syncing sources to container.
- chown -R "${USER_ID}":"${GROUP_ID}" "${LOCAL_OUTPUT_BUILD_CONTEXT}"
+mkdir -p "${LOCAL_OUTPUT_BUILD_CONTEXT}"
+# Make sure the context directory owned by the right user for syncing sources to container.
+chown -R "${USER_ID}":"${GROUP_ID}" "${LOCAL_OUTPUT_BUILD_CONTEXT}"
- cp /etc/localtime "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
+cp /etc/localtime "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
- cp "${OPENIM_ROOT}/build/build-image/Dockerfile" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
- cp "${OPENIM_ROOT}/build/build-image/rsyncd.sh" "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
- dd if=/dev/urandom bs=512 count=1 2>/dev/null | LC_ALL=C tr -dc 'A-Za-z0-9' | dd bs=32 count=1 2>/dev/null > "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
- chmod go= "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
+cp "${OPENIM_ROOT}/build/build-image/Dockerfile" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
+cp "${OPENIM_ROOT}/build/build-image/rsyncd.sh" "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
+dd if=/dev/urandom bs=512 count=1 2>/dev/null | LC_ALL=C tr -dc 'A-Za-z0-9' | dd bs=32 count=1 2>/dev/null > "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
+chmod go= "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
- openim::build::update_dockerfile
- openim::build::set_proxy
- openim::build::docker_build "${OPENIM_BUILD_IMAGE}" "${LOCAL_OUTPUT_BUILD_CONTEXT}" 'false'
+openim::build::update_dockerfile
+openim::build::set_proxy
+openim::build::docker_build "${OPENIM_BUILD_IMAGE}" "${LOCAL_OUTPUT_BUILD_CONTEXT}" 'false'
- # Clean up old versions of everything
- openim::build::docker_delete_old_containers "${OPENIM_BUILD_CONTAINER_NAME_BASE}" "${OPENIM_BUILD_CONTAINER_NAME}"
- openim::build::docker_delete_old_containers "${OPENIM_RSYNC_CONTAINER_NAME_BASE}" "${OPENIM_RSYNC_CONTAINER_NAME}"
- openim::build::docker_delete_old_containers "${OPENIM_DATA_CONTAINER_NAME_BASE}" "${OPENIM_DATA_CONTAINER_NAME}"
- openim::build::docker_delete_old_images "${OPENIM_BUILD_IMAGE_REPO}" "${OPENIM_BUILD_IMAGE_TAG_BASE}" "${OPENIM_BUILD_IMAGE_TAG}"
+# Clean up old versions of everything
+openim::build::docker_delete_old_containers "${OPENIM_BUILD_CONTAINER_NAME_BASE}" "${OPENIM_BUILD_CONTAINER_NAME}"
+openim::build::docker_delete_old_containers "${OPENIM_RSYNC_CONTAINER_NAME_BASE}" "${OPENIM_RSYNC_CONTAINER_NAME}"
+openim::build::docker_delete_old_containers "${OPENIM_DATA_CONTAINER_NAME_BASE}" "${OPENIM_DATA_CONTAINER_NAME}"
+openim::build::docker_delete_old_images "${OPENIM_BUILD_IMAGE_REPO}" "${OPENIM_BUILD_IMAGE_TAG_BASE}" "${OPENIM_BUILD_IMAGE_TAG}"
- openim::build::ensure_data_container
- openim::build::sync_to_container
+openim::build::ensure_data_container
+openim::build::sync_to_container
}
# Build a docker image from a Dockerfile.
@@ -441,14 +441,14 @@ function openim::build::build_image() {
# $2 is the location of the "context" directory, with the Dockerfile at the root.
# $3 is the value to set the --pull flag for docker build; true by default
function openim::build::docker_build() {
- local -r image=$1
- local -r context_dir=$2
- local -r pull="${3:-true}"
- local -ra build_cmd=("${DOCKER[@]}" build -t "${image}" "--pull=${pull}" "${context_dir}")
-
- openim::log::status "Building Docker image ${image}"
- local docker_output
- docker_output=$("${build_cmd[@]}" 2>&1) || {
+local -r image=$1
+local -r context_dir=$2
+local -r pull="${3:-true}"
+local -ra build_cmd=("${DOCKER[@]}" build -t "${image}" "--pull=${pull}" "${context_dir}")
+
+openim::log::status "Building Docker image ${image}"
+local docker_output
+docker_output=$("${build_cmd[@]}" 2>&1) || {
cat <&2
+++ Docker build command failed for ${image}
@@ -459,61 +459,61 @@ To retry manually, run:
${build_cmd[*]}
EOF
- return 1
- }
+ return 1
+}
}
function openim::build::ensure_data_container() {
- # If the data container exists AND exited successfully, we can use it.
- # Otherwise nuke it and start over.
- local ret=0
- local code=0
-
- code=$(docker inspect \
- -f '{{.State.ExitCode}}' \
- "${OPENIM_DATA_CONTAINER_NAME}" 2>/dev/null) || ret=$?
- if [[ "${ret}" == 0 && "${code}" != 0 ]]; then
- openim::build::destroy_container "${OPENIM_DATA_CONTAINER_NAME}"
- ret=1
- fi
- if [[ "${ret}" != 0 ]]; then
- openim::log::status "Creating data container ${OPENIM_DATA_CONTAINER_NAME}"
- # We have to ensure the directory exists, or else the docker run will
- # create it as root.
- mkdir -p "${LOCAL_OUTPUT_GOPATH}"
- # We want this to run as root to be able to chown, so non-root users can
- # later use the result as a data container. This run both creates the data
- # container and chowns the GOPATH.
- #
- # The data container creates volumes for all of the directories that store
- # intermediates for the Go build. This enables incremental builds across
- # Docker sessions. The *_cgo paths are re-compiled versions of the go std
- # libraries for true static building.
- local -ra docker_cmd=(
- "${DOCKER[@]}" run
- --volume "${REMOTE_ROOT}" # white-out the whole output dir
- --volume /usr/local/go/pkg/linux_386_cgo
- --volume /usr/local/go/pkg/linux_amd64_cgo
- --volume /usr/local/go/pkg/linux_arm_cgo
- --volume /usr/local/go/pkg/linux_arm64_cgo
- --volume /usr/local/go/pkg/linux_ppc64le_cgo
- --volume /usr/local/go/pkg/darwin_amd64_cgo
- --volume /usr/local/go/pkg/darwin_386_cgo
- --volume /usr/local/go/pkg/windows_amd64_cgo
- --volume /usr/local/go/pkg/windows_386_cgo
- --name "${OPENIM_DATA_CONTAINER_NAME}"
- --hostname "${HOSTNAME}"
- "${OPENIM_BUILD_IMAGE}"
- chown -R "${USER_ID}":"${GROUP_ID}"
- "${REMOTE_ROOT}"
- /usr/local/go/pkg/
- )
- "${docker_cmd[@]}"
- fi
+# If the data container exists AND exited successfully, we can use it.
+# Otherwise nuke it and start over.
+local ret=0
+local code=0
+
+code=$(docker inspect \
+ -f '{{.State.ExitCode}}' \
+"${OPENIM_DATA_CONTAINER_NAME}" 2>/dev/null) || ret=$?
+if [[ "${ret}" == 0 && "${code}" != 0 ]]; then
+ openim::build::destroy_container "${OPENIM_DATA_CONTAINER_NAME}"
+ ret=1
+fi
+if [[ "${ret}" != 0 ]]; then
+ openim::log::status "Creating data container ${OPENIM_DATA_CONTAINER_NAME}"
+ # We have to ensure the directory exists, or else the docker run will
+ # create it as root.
+ mkdir -p "${LOCAL_OUTPUT_GOPATH}"
+ # We want this to run as root to be able to chown, so non-root users can
+ # later use the result as a data container. This run both creates the data
+ # container and chowns the GOPATH.
+ #
+ # The data container creates volumes for all of the directories that store
+ # intermediates for the Go build. This enables incremental builds across
+ # Docker sessions. The *_cgo paths are re-compiled versions of the go std
+ # libraries for true static building.
+ local -ra docker_cmd=(
+ "${DOCKER[@]}" run
+ --volume "${REMOTE_ROOT}" # white-out the whole output dir
+ --volume /usr/local/go/pkg/linux_386_cgo
+ --volume /usr/local/go/pkg/linux_amd64_cgo
+ --volume /usr/local/go/pkg/linux_arm_cgo
+ --volume /usr/local/go/pkg/linux_arm64_cgo
+ --volume /usr/local/go/pkg/linux_ppc64le_cgo
+ --volume /usr/local/go/pkg/darwin_amd64_cgo
+ --volume /usr/local/go/pkg/darwin_386_cgo
+ --volume /usr/local/go/pkg/windows_amd64_cgo
+ --volume /usr/local/go/pkg/windows_386_cgo
+ --name "${OPENIM_DATA_CONTAINER_NAME}"
+ --hostname "${HOSTNAME}"
+ "${OPENIM_BUILD_IMAGE}"
+ chown -R "${USER_ID}":"${GROUP_ID}"
+ "${REMOTE_ROOT}"
+ /usr/local/go/pkg/
+ )
+ "${docker_cmd[@]}"
+fi
}
# Build all openim commands.
function openim::build::build_command() {
- openim::log::status "Running build command..."
- make -C "${OPENIM_ROOT}" multiarch
+openim::log::status "Running build command..."
+make -C "${OPENIM_ROOT}" multiarch
}
diff --git a/scripts/coverage.sh b/scripts/coverage.sh
index ae5283671..e5cef0b5d 100755
--- a/scripts/coverage.sh
+++ b/scripts/coverage.sh
@@ -19,11 +19,11 @@
echo "mode: atomic" > coverage.txt
for d in $(find ./* -maxdepth 10 -type d); do
- if ls $d/*.go &> /dev/null; then
- go test -coverprofile=profile.out -covermode=atomic $d
- if [ -f profile.out ]; then
- cat profile.out | grep -v "mode: " >> /tmp/coverage.txt
- rm profile.out
- fi
+ if ls $d/*.go &> /dev/null; then
+ go test -coverprofile=profile.out -covermode=atomic $d
+ if [ -f profile.out ]; then
+ cat profile.out | grep -v "mode: " >> /tmp/coverage.txt
+ rm profile.out
fi
+ fi
done
diff --git a/scripts/demo.sh b/scripts/demo.sh
index 5f8a2023a..4b877b9ed 100755
--- a/scripts/demo.sh
+++ b/scripts/demo.sh
@@ -15,16 +15,16 @@
if ! command -v pv &> /dev/null
then
- echo "pv not found, installing..."
- if [ -e /etc/debian_version ]; then
- sudo apt-get update
- sudo apt-get install -y pv
+ echo "pv not found, installing..."
+ if [ -e /etc/debian_version ]; then
+ sudo apt-get update
+ sudo apt-get install -y pv
elif [ -e /etc/redhat-release ]; then
- sudo yum install -y pv
- else
- echo "Unsupported OS, please install pv manually."
- exit 1
- fi
+ sudo yum install -y pv
+ else
+ echo "Unsupported OS, please install pv manually."
+ exit 1
+ fi
fi
readonly t_reset=$(tput sgr0)
@@ -42,8 +42,8 @@ openim::util::ensure-bash-version
trap 'openim::util::onCtrlC' INT
function openim::util::onCtrlC() {
- echo -e "\n${t_reset}Ctrl+C Press it. It's exiting openim make init..."
- exit 0
+ echo -e "\n${t_reset}Ctrl+C Press it. It's exiting openim make init..."
+ exit 0
}
openim::util::desc "========> Welcome to the OpenIM Demo"
diff --git a/scripts/docker-check-service.sh b/scripts/docker-check-service.sh
index adf383436..30ca89b5a 100755
--- a/scripts/docker-check-service.sh
+++ b/scripts/docker-check-service.sh
@@ -22,61 +22,61 @@ cd "$OPENIM_ROOT"
openim::util::check_docker_and_compose_versions
progress() {
- local _main_pid="$1"
- local _length=20
- local _ratio=1
- local _colors=("31" "32" "33" "34" "35" "36" "37")
- local _wave=("▁" "▂" "▃" "▄" "▅" "▆" "▇" "█" "▇" "▆" "▅" "▄" "▃" "▂")
-
- while pgrep -P "$_main_pid" &> /dev/null; do
- local _mark='>'
- local _progress_bar=
- for ((i = 1; i <= _length; i++)); do
- if ((i > _ratio)); then
- _mark='-'
- fi
- _progress_bar="${_progress_bar}${_mark}"
- done
-
- local _color_idx=$((_ratio % ${#_colors[@]}))
- local _color_prefix="\033[${_colors[_color_idx]}m"
- local _reset_suffix="\033[0m"
-
- local _wave_idx=$((_ratio % ${#_wave[@]}))
- local _wave_progress=${_wave[_wave_idx]}
-
- printf "Progress: ${_color_prefix}${_progress_bar}${_reset_suffix} ${_wave_progress} Countdown: %2ds \r" "$_countdown"
- ((_ratio++))
- ((_ratio > _length)) && _ratio=1
- sleep 0.1
+ local _main_pid="$1"
+ local _length=20
+ local _ratio=1
+ local _colors=("31" "32" "33" "34" "35" "36" "37")
+ local _wave=("▁" "▂" "▃" "▄" "▅" "▆" "▇" "█" "▇" "▆" "▅" "▄" "▃" "▂")
+
+ while pgrep -P "$_main_pid" &> /dev/null; do
+ local _mark='>'
+ local _progress_bar=
+ for ((i = 1; i <= _length; i++)); do
+ if ((i > _ratio)); then
+ _mark='-'
+ fi
+ _progress_bar="${_progress_bar}${_mark}"
done
+
+ local _color_idx=$((_ratio % ${#_colors[@]}))
+ local _color_prefix="\033[${_colors[_color_idx]}m"
+ local _reset_suffix="\033[0m"
+
+ local _wave_idx=$((_ratio % ${#_wave[@]}))
+ local _wave_progress=${_wave[_wave_idx]}
+
+ printf "Progress: ${_color_prefix}${_progress_bar}${_reset_suffix} ${_wave_progress} Countdown: %2ds \r" "$_countdown"
+ ((_ratio++))
+ ((_ratio > _length)) && _ratio=1
+ sleep 0.1
+ done
}
countdown() {
- local _duration="$1"
-
- for ((i = _duration; i >= 1; i--)); do
- printf "\rCountdown: %2ds \r" "$i"
- sleep 1
- done
- printf "\rCountdown: %2ds \r" "$_duration"
+ local _duration="$1"
+
+ for ((i = _duration; i >= 1; i--)); do
+ printf "\rCountdown: %2ds \r" "$i"
+ sleep 1
+ done
+ printf "\rCountdown: %2ds \r" "$_duration"
}
do_sth() {
- echo "++++++++++++++++++++++++"
- progress $$ &
- local _progress_pid=$!
- local _countdown=30
-
- countdown "$_countdown" &
- local _countdown_pid=$!
-
- sleep 30
-
- kill "$_progress_pid" "$_countdown_pid"
-
- "${SCRIPTS_ROOT}/check-all.sh"
- echo -e "${PURPLE_PREFIX}=========> Check docker-compose status ${COLOR_SUFFIX} \n"
+ echo "++++++++++++++++++++++++"
+ progress $$ &
+ local _progress_pid=$!
+ local _countdown=30
+
+ countdown "$_countdown" &
+ local _countdown_pid=$!
+
+ sleep 30
+
+ kill "$_progress_pid" "$_countdown_pid"
+
+ "${SCRIPTS_ROOT}/check-all.sh"
+ echo -e "${PURPLE_PREFIX}=========> Check docker-compose status ${COLOR_SUFFIX} \n"
}
set -e
diff --git a/scripts/ensure-tag.sh b/scripts/ensure-tag.sh
index 2847342f4..5fedf7019 100755
--- a/scripts/ensure-tag.sh
+++ b/scripts/ensure-tag.sh
@@ -18,9 +18,9 @@ OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
version="${VERSION}"
if [ "${version}" == "" ];then
- version=v`${OPENIM_ROOT}/_output/tools/gsemver bump`
+ version=v$(${OPENIM_ROOT}/_output/tools/gsemver bump)
fi
-if [ -z "`git tag -l ${version}`" ];then
+if [ -z "$(git tag -l ${version})" ];then
git tag -a -m "release version ${version}" ${version}
fi
diff --git a/scripts/gen-swagger-docs.sh b/scripts/gen-swagger-docs.sh
index ccf5eaeaa..68410e79c 100755
--- a/scripts/gen-swagger-docs.sh
+++ b/scripts/gen-swagger-docs.sh
@@ -67,7 +67,7 @@ echo -e "=== any\nRepresents an untyped JSON map - see the description of the fi
asciidoctor definitions.adoc
asciidoctor paths.adoc
-cp ${OPENIM_OUTPUT_TMP}/definitions.html ${OPENIM_OUTPUT_TMP}/_output/
-cp ${OPENIM_OUTPUT_TMP}/paths.html ${OPENIM_OUTPUT_TMP}/_output/operations.html
+cp "$OPENIM_OUTPUT_TMP/definitions.html" "$OPENIM_OUTPUT_TMP/_output/"
+cp "$OPENIM_OUTPUT_TMP/paths.html" "$OPENIM_OUTPUT_TMP/_output/operations.html"
success "SUCCESS"
\ No newline at end of file
diff --git a/scripts/genconfig.sh b/scripts/genconfig.sh
index 659e8f4be..498b0b908 100755
--- a/scripts/genconfig.sh
+++ b/scripts/genconfig.sh
@@ -25,12 +25,12 @@ OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${OPENIM_ROOT}/scripts/lib/init.sh"
if [ $# -ne 2 ];then
- openim::log::error "Usage: scripts/genconfig.sh scripts/environment.sh configs/openim-api.yaml"
- exit 1
+ openim::log::error "Usage: scripts/genconfig.sh scripts/environment.sh configs/config.yaml"
+ exit 1
fi
if [ -z "${OPENIM_IP}" ]; then
- openim::util::require-dig
+ openim::util::require-dig
fi
source "${env_file}"
@@ -40,15 +40,15 @@ 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
+ 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
+ openim::log::error "You may run 'source scripts/environment.sh' to set these environment"
+ exit 1
fi
eval "cat << EOF
diff --git a/scripts/gendoc.sh b/scripts/gendoc.sh
index c948fcdf9..ece090190 100755
--- a/scripts/gendoc.sh
+++ b/scripts/gendoc.sh
@@ -14,43 +14,43 @@
# limitations under the License.
DEFAULT_DIRS=(
- "pkg"
- "internal/pkg"
+ "pkg"
+ "internal/pkg"
)
BASE_URL="github.com/openimsdk/open-im-server"
usage() {
- echo "Usage: $0 [OPTIONS]"
- echo
- echo "This script iterates over directories and generates doc.go if necessary."
- echo "By default, it processes 'pkg' and 'internal/pkg' directories."
- echo
- echo "Options:"
- echo " -d DIRS, --dirs DIRS Specify the directories to be processed, separated by commas. E.g., 'pkg,internal/pkg'."
- echo " -u URL, --url URL Set the base URL for the import path. Default is '$BASE_URL'."
- echo " -h, --help Show this help message."
- echo
+ echo "Usage: $0 [OPTIONS]"
+ echo
+ echo "This script iterates over directories and generates doc.go if necessary."
+ echo "By default, it processes 'pkg' and 'internal/pkg' directories."
+ echo
+ echo "Options:"
+ echo " -d DIRS, --dirs DIRS Specify the directories to be processed, separated by commas. E.g., 'pkg,internal/pkg'."
+ echo " -u URL, --url URL Set the base URL for the import path. Default is '$BASE_URL'."
+ echo " -h, --help Show this help message."
+ echo
}
process_dir() {
- local dir=$1
- local base_url=$2
-
- for d in $(find $dir -type d); do
- if [ ! -f $d/doc.go ]; then
- if ls $d/*.go > /dev/null 2>&1; then
- echo $d/doc.go
- echo "package $(basename $d) // import \"$base_url/$d\"" > $d/doc.go
- fi
- fi
- done
+ local dir=$1
+ local base_url=$2
+
+ for d in $(find $dir -type d); do
+ if [ ! -f $d/doc.go ]; then
+ if ls $d/*.go > /dev/null 2>&1; then
+ echo $d/doc.go
+ echo "package $(basename $d) // import \"$base_url/$d\"" > $d/doc.go
+ fi
+ fi
+ done
}
while [[ $# -gt 0 ]]; do
- key="$1"
-
- case $key in
- -d|--dirs)
+ key="$1"
+
+ case $key in
+ -d|--dirs)
IFS=',' read -ra DIRS <<< "$2"
shift # shift past argument
shift # shift past value
diff --git a/scripts/githooks/commit-msg.sh b/scripts/githooks/commit-msg.sh
index efff13fd0..d2d96645b 100644
--- a/scripts/githooks/commit-msg.sh
+++ b/scripts/githooks/commit-msg.sh
@@ -34,15 +34,15 @@ RED="\e[31m"
ENDCOLOR="\e[0m"
printMessage() {
- printf "${YELLOW}OpenIM : $1${ENDCOLOR}\n"
+ printf "${YELLOW}OpenIM : $1${ENDCOLOR}\n"
}
printSuccess() {
- printf "${GREEN}OpenIM : $1${ENDCOLOR}\n"
+ printf "${GREEN}OpenIM : $1${ENDCOLOR}\n"
}
printError() {
- printf "${RED}OpenIM : $1${ENDCOLOR}\n"
+ printf "${RED}OpenIM : $1${ENDCOLOR}\n"
}
printMessage "Running the OpenIM commit-msg hook."
@@ -50,9 +50,9 @@ printMessage "Running the OpenIM commit-msg hook."
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
- sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
- echo >&2 Duplicate Signed-off-by lines.
- exit 1
+sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
+echo >&2 Duplicate Signed-off-by lines.
+exit 1
}
# TODO: go-gitlint dir set
@@ -60,21 +60,21 @@ OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/../..
GITLINT_DIR="$OPENIM_ROOT/_output/tools/go-gitlint"
$GITLINT_DIR \
- --msg-file=$1 \
- --subject-regex="^(build|chore|ci|docs|feat|feature|fix|perf|refactor|revert|style|bot|test)(.*)?:\s?.*" \
- --subject-maxlen=150 \
- --subject-minlen=10 \
- --body-regex=".*" \
- --max-parents=1
+--msg-file=$1 \
+--subject-regex="^(build|chore|ci|docs|feat|feature|fix|perf|refactor|revert|style|bot|test)(.*)?:\s?.*" \
+--subject-maxlen=150 \
+--subject-minlen=10 \
+--body-regex=".*" \
+--max-parents=1
if [ $? -ne 0 ]
then
- if ! command -v $GITLINT_DIR &>/dev/null; then
- printError "$GITLINT_DIR not found. Please run 'make tools' OR 'make tools.verify.go-gitlint' make verto install it."
- fi
- printError "Please fix your commit message to match kubecub coding standards"
- printError "https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694#file-githook-md"
- exit 1
+if ! command -v $GITLINT_DIR &>/dev/null; then
+ printError "$GITLINT_DIR not found. Please run 'make tools' OR 'make tools.verify.go-gitlint' make verto install it."
+fi
+printError "Please fix your commit message to match kubecub coding standards"
+printError "https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694#file-githook-md"
+exit 1
fi
### Add Sign-off-by line to the end of the commit message
@@ -88,5 +88,5 @@ SIGNED_OFF_BY_EXISTS=$?
# Add "Signed-off-by" line if it doesn't exist
if [ $SIGNED_OFF_BY_EXISTS -ne 0 ]; then
- echo -e "\nSigned-off-by: $NAME <$EMAIL>" >> "$1"
+echo -e "\nSigned-off-by: $NAME <$EMAIL>" >> "$1"
fi
\ No newline at end of file
diff --git a/scripts/githooks/pre-commit.sh b/scripts/githooks/pre-commit.sh
index 7fd21593c..cc756c9ad 100644
--- a/scripts/githooks/pre-commit.sh
+++ b/scripts/githooks/pre-commit.sh
@@ -34,15 +34,15 @@ RED="\e[31m"
ENDCOLOR="\e[0m"
printMessage() {
- printf "${YELLOW}openim : $1${ENDCOLOR}\n"
+ printf "${YELLOW}openim : $1${ENDCOLOR}\n"
}
printSuccess() {
- printf "${GREEN}openim : $1${ENDCOLOR}\n"
+ printf "${GREEN}openim : $1${ENDCOLOR}\n"
}
printError() {
- printf "${RED}openim : $1${ENDCOLOR}\n"
+ printf "${RED}openim : $1${ENDCOLOR}\n"
}
printMessage "Running local openim pre-commit hook."
@@ -55,9 +55,9 @@ limit=${GIT_FILE_SIZE_LIMIT:-2000000} # Default 2MB
limitInMB=$(( $limit / 1000000 ))
function file_too_large(){
- filename=$0
- filesize=$(( $1 / 2**20 ))
-
+ filename=$0
+ filesize=$(( $1 / 2**20 ))
+
cat < /dev/null 2>&1
then
- against=HEAD
+ against=HEAD
else
- against="$empty_tree"
+ against="$empty_tree"
fi
# Set split so that for loop below can handle spaces in file names by splitting on line breaks
@@ -104,7 +104,7 @@ fi
if [[ ! $local_branch =~ $valid_branch_regex ]]
then
- printError "There is something wrong with your branch name. Branch names in this project must adhere to this contract: $valid_branch_regex.
+ printError "There is something wrong with your branch name. Branch names in this project must adhere to this contract: $valid_branch_regex.
Your commit will be rejected. You should rename your branch to a valid name(feat/name OR bug/name) and try again."
printError "For more on this, read on: https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694"
exit 1
diff --git a/scripts/githooks/pre-push.sh b/scripts/githooks/pre-push.sh
index e341cf4f2..9bd938915 100644
--- a/scripts/githooks/pre-push.sh
+++ b/scripts/githooks/pre-push.sh
@@ -25,20 +25,20 @@ local_branch="$(git rev-parse --abbrev-ref HEAD)"
valid_branch_regex="^(main|master|develop|release(-[a-zA-Z0-9._-]+)?)$|(feature|feat|openim|hotfix|test|bug|ci|cicd|style|)\/[a-z0-9._-]+$|^HEAD$"
printMessage() {
- printf "${YELLOW}OpenIM : $1${ENDCOLOR}\n"
+ printf "${YELLOW}OpenIM : $1${ENDCOLOR}\n"
}
printSuccess() {
- printf "${GREEN}OpenIM : $1${ENDCOLOR}\n"
+ printf "${GREEN}OpenIM : $1${ENDCOLOR}\n"
}
printError() {
- printf "${RED}OpenIM : $1${ENDCOLOR}\n"
+ printf "${RED}OpenIM : $1${ENDCOLOR}\n"
}
printMessage "Running local OpenIM pre-push hook."
-if [[ `git status --porcelain` ]]; then
+if [[ $(git status --porcelain) ]]; then
printError "This scripts needs to run against committed code only. Please commit or stash you changes."
exit 1
fi
@@ -101,7 +101,7 @@ print_color "Deleted Files: ${deleted_files}" "${BACKGROUND_GREEN}"
if [[ ! $local_branch =~ $valid_branch_regex ]]
then
- printError "There is something wrong with your branch name. Branch names in this project must adhere to this contract: $valid_branch_regex.
+ printError "There is something wrong with your branch name. Branch names in this project must adhere to this contract: $valid_branch_regex.
Your commit will be rejected. You should rename your branch to a valid name(feat/name OR fix/name) and try again."
printError "For more on this, read on: https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694"
exit 1
diff --git a/scripts/init-config.sh b/scripts/init-config.sh
index c75fc5502..82eefbb54 100755
--- a/scripts/init-config.sh
+++ b/scripts/init-config.sh
@@ -31,7 +31,7 @@ readonly ENV_FILE=${ENV_FILE:-"${OPENIM_ROOT}/scripts/install/environment.sh"}
# Templates for configuration files
declare -A TEMPLATES=(
["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/.env"
- ["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/config.yaml"
+ ["${OPENIM_ROOT}/deployments/templates/config.yaml"]="${OPENIM_ROOT}/config/config.yaml"
["${OPENIM_ROOT}/deployments/templates/prometheus.yml"]="${OPENIM_ROOT}/config/prometheus.yml"
["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/alertmanager.yml"
)
@@ -39,7 +39,7 @@ declare -A TEMPLATES=(
# Templates for example files
declare -A EXAMPLES=(
["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/config/templates/env.template"
- ["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/templates/config.yaml.template"
+ ["${OPENIM_ROOT}/deployments/templates/config.yaml"]="${OPENIM_ROOT}/config/templates/config.yaml.template"
["${OPENIM_ROOT}/deployments/templates/prometheus.yml"]="${OPENIM_ROOT}/config/templates/prometheus.yml.template"
["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/templates/alertmanager.yml.template"
)
@@ -84,7 +84,7 @@ generate_config_files() {
local output_file="${TEMPLATES[$template]}"
process_file "$template" "$output_file" true
done
-
+
# Handle COPY_TEMPLATES array
for template in "${!COPY_TEMPLATES[@]}"; do
local output_file="${COPY_TEMPLATES[$template]}"
@@ -95,22 +95,25 @@ generate_config_files() {
# Function to generate example files
generate_example_files() {
env_cmd="env -i"
+
+ env_vars["OPENIM_IP"]="127.0.0.1"
+ env_vars["LOG_STORAGE_LOCATION"]="../../"
+
for var in "${!env_vars[@]}"; do
- env_cmd+=" $var='${env_vars[$var]}'"
+ env_cmd+=" $var='${env_vars[$var]}'"
done
-
+
# Processing EXAMPLES array
for template in "${!EXAMPLES[@]}"; do
local example_file="${EXAMPLES[$template]}"
process_file "$template" "$example_file" true
done
-
+
# Processing COPY_EXAMPLES array
for template in "${!COPY_EXAMPLES[@]}"; do
local example_file="${COPY_EXAMPLES[$template]}"
process_file "$template" "$example_file" false
done
-
}
# Function to process a single file, either by generating or copying
@@ -118,11 +121,11 @@ process_file() {
local template=$1
local output_file=$2
local use_genconfig=$3
-
+
if [[ -f "${output_file}" ]]; then
if [[ "${FORCE_OVERWRITE}" == true ]]; then
openim::log::info "Force overwriting ${output_file}."
- elif [[ "${SKIP_EXISTING}" == true ]]; then
+ elif [[ "${SKIP_EXISTING}" == true ]]; then
openim::log::info "Skipping generation of ${output_file} as it already exists."
return
else
@@ -139,7 +142,7 @@ process_file() {
openim::log::info "Generating ${output_file} as it does not exist."
fi
fi
-
+
if [[ "$use_genconfig" == true ]]; then
openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..."
if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
@@ -147,15 +150,15 @@ process_file() {
exit 1
fi
if [[ -n "${env_cmd}" ]]; then
- eval "$env_cmd ${OPENIM_ROOT}/scripts/genconfig.sh '${ENV_FILE}' '${template}' > '${output_file}'" || {
+ eval "$env_cmd ${OPENIM_ROOT}/scripts/genconfig.sh '${ENV_FILE}' '${template}' > '${output_file}'" || {
openim::log::error "Error processing template file ${template}"
exit 1
- }
+ }
else
- "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
+ "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
openim::log::error "Error processing template file ${template}"
exit 1
- }
+ }
fi
else
openim::log::info "📋 Copying ${template} to ${output_file}..."
@@ -164,7 +167,7 @@ process_file() {
exit 1
}
fi
-
+
sleep 0.5
}
@@ -181,7 +184,6 @@ clean_config_files() {
# Function to clean example files
clean_example_files() {
- # 合并 EXAMPLES 和 COPY_EXAMPLES 数组
local all_examples=("${EXAMPLES[@]}" "${COPY_EXAMPLES[@]}")
for example_file in "${all_examples[@]}"; do
@@ -197,32 +199,32 @@ while [[ $# -gt 0 ]]; do
-h|--help)
show_help
exit 0
- ;;
+ ;;
--force)
FORCE_OVERWRITE=true
shift
- ;;
+ ;;
--skip)
SKIP_EXISTING=true
shift
- ;;
+ ;;
--examples)
GENERATE_EXAMPLES=true
shift
- ;;
+ ;;
--clean-config)
CLEAN_CONFIG=true
shift
- ;;
+ ;;
--clean-examples)
CLEAN_EXAMPLES=true
shift
- ;;
+ ;;
*)
echo "Unknown option: $1"
show_help
exit 1
- ;;
+ ;;
esac
done
diff --git a/scripts/init-env.sh b/scripts/init-env.sh
index ca0c471ad..75b871b08 100755
--- a/scripts/init-env.sh
+++ b/scripts/init-env.sh
@@ -25,9 +25,9 @@ source "${OPENIM_ROOT}/scripts/install/common.sh"
openim::log::info "\n# Begin Install OpenIM Config"
for file in "${OPENIM_SERVER_TARGETS[@]}"; do
- VARNAME="$(echo $file | tr '[:lower:]' '[:upper:]' | tr '.' '_' | tr '-' '_')"
- VARVALUE="$OPENIM_OUTPUT_HOSTBIN/$file"
- # /etc/profile.d/openim-env.sh
- echo "export $VARNAME=$VARVALUE" > /etc/profile.d/openim-env.sh
- source /etc/profile.d/openim-env.sh
+ VARNAME="$(echo $file | tr '[:lower:]' '[:upper:]' | tr '.' '_' | tr '-' '_')"
+ VARVALUE="$OPENIM_OUTPUT_HOSTBIN/$file"
+ # /etc/profile.d/openim-env.sh
+ echo "export $VARNAME=$VARVALUE" > /etc/profile.d/openim-env.sh
+ source /etc/profile.d/openim-env.sh
done
diff --git a/scripts/init-githooks.sh b/scripts/init-githooks.sh
index 399054bb8..4ee470742 100755
--- a/scripts/init-githooks.sh
+++ b/scripts/init-githooks.sh
@@ -39,62 +39,62 @@ OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
HOOKS_DIR="${OPENIM_ROOT}/.git/hooks"
help_info() {
- echo "Usage: $0 [options]"
- echo
- echo "This script helps to manage git hooks."
- echo
- echo "Options:"
- echo " -h, --help Show this help message and exit."
- echo " -d, --delete Delete the hooks that have been added."
- echo " By default, it will prompt to enable git hooks."
+ echo "Usage: $0 [options]"
+ echo
+ echo "This script helps to manage git hooks."
+ echo
+ echo "Options:"
+ echo " -h, --help Show this help message and exit."
+ echo " -d, --delete Delete the hooks that have been added."
+ echo " By default, it will prompt to enable git hooks."
}
delete_hooks() {
- for file in ${OPENIM_ROOT}/scripts/githooks/*.sh; do
- hook_name=$(basename "$file" .sh) # This removes the .sh extension
- rm -f "$HOOKS_DIR/$hook_name"
- done
- echo "Git hooks have been deleted."
+ for file in "${OPENIM_ROOT}"/scripts/githooks/*.sh; do
+ hook_name=$(basename "$file" .sh) # This removes the .sh extension
+ rm -f "$HOOKS_DIR/$hook_name"
+ done
+ echo "Git hooks have been deleted."
}
enable_hooks() {
- echo "Would you like to:"
- echo "1) Enable git hooks mode"
- echo "2) Delete existing git hooks"
- echo "Please select a number (or any other key to exit):"
- read -r choice
-
- case "$choice" in
- 1)
- for file in ${OPENIM_ROOT}/scripts/githooks/*.sh; do
- hook_name=$(basename "$file" .sh) # This removes the .sh extension
- cp -f "$file" "$HOOKS_DIR/$hook_name"
- done
-
- chmod +x $HOOKS_DIR/*
-
- echo "Git hooks mode has been enabled."
- echo "With git hooks enabled, every time you perform a git action (e.g. git commit), the corresponding hooks script will be triggered automatically."
- echo "This means that if the size of the file you're committing exceeds the set limit (e.g. 42MB), the commit will be rejected."
- ;;
- 2)
- delete_hooks
- ;;
- *)
- echo "Exiting without making changes."
- ;;
- esac
+ echo "Would you like to:"
+ echo "1) Enable git hooks mode"
+ echo "2) Delete existing git hooks"
+ echo "Please select a number (or any other key to exit):"
+ read -r choice
+
+ case "$choice" in
+ 1)
+ for file in ${OPENIM_ROOT}/scripts/githooks/*.sh; do
+ hook_name=$(basename "$file" .sh) # This removes the .sh extension
+ cp -f "$file" "$HOOKS_DIR/$hook_name"
+ done
+
+ chmod +x $HOOKS_DIR/*
+
+ echo "Git hooks mode has been enabled."
+ echo "With git hooks enabled, every time you perform a git action (e.g. git commit), the corresponding hooks script will be triggered automatically."
+ echo "This means that if the size of the file you're committing exceeds the set limit (e.g. 42MB), the commit will be rejected."
+ ;;
+ 2)
+ delete_hooks
+ ;;
+ *)
+ echo "Exiting without making changes."
+ ;;
+ esac
}
case "$1" in
- -h|--help)
- help_info
- ;;
- -d|--delete)
- delete_hooks
- ;;
- *)
- enable_hooks
- ;;
+ -h|--help)
+ help_info
+ ;;
+ -d|--delete)
+ delete_hooks
+ ;;
+ *)
+ enable_hooks
+ ;;
esac
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index 9afbb97c9..9588032d7 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -49,10 +49,10 @@ DOCKER_COMPOSE_COMMAND=
# Check if docker-compose command is available
openim::util::check_docker_and_compose_versions
if command -v docker compose &> /dev/null; then
- openim::log::info "docker compose command is available"
- DOCKER_COMPOSE_COMMAND="docker compose"
+ openim::log::info "docker compose command is available"
+ DOCKER_COMPOSE_COMMAND="docker compose"
else
- DOCKER_COMPOSE_COMMAND="docker-compose"
+ DOCKER_COMPOSE_COMMAND="docker-compose"
fi
export SERVER_IMAGE_VERSION
@@ -67,12 +67,12 @@ ${DOCKER_COMPOSE_COMMAND} up -d
# Function to check container status
check_containers() {
- if ! ${DOCKER_COMPOSE_COMMAND} ps | grep -q 'Up'; then
- echo "Error: One or more docker containers failed to start."
- ${DOCKER_COMPOSE_COMMAND} logs
- return 1
- fi
- return 0
+ if ! ${DOCKER_COMPOSE_COMMAND} ps | grep -q 'Up'; then
+ echo "Error: One or more docker containers failed to start."
+ ${DOCKER_COMPOSE_COMMAND} logs
+ return 1
+ fi
+ return 0
}
# Wait for a short period to allow containers to initialize
diff --git a/scripts/install/dependency.sh b/scripts/install/dependency.sh
index 78995bcf9..e7c7eb426 100755
--- a/scripts/install/dependency.sh
+++ b/scripts/install/dependency.sh
@@ -24,66 +24,66 @@ OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P)
# Start MongoDB service
docker run -d \
- --name mongo \
- -p 37017:27017 \
- -v "${DATA_DIR}/components/mongodb/data/db:/data/db" \
- -v "${DATA_DIR}/components/mongodb/data/logs:/data/logs" \
- -v "${DATA_DIR}/components/mongodb/data/conf:/etc/mongo" \
- -v "./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro" \
- -e TZ=Asia/Shanghai \
- -e wiredTigerCacheSizeGB=1 \
- -e MONGO_INITDB_ROOT_USERNAME=${OPENIM_USER} \
- -e MONGO_INITDB_ROOT_PASSWORD=${PASSWORD} \
- -e MONGO_INITDB_DATABASE=openIM \
- -e MONGO_OPENIM_USERNAME=${OPENIM_USER} \
- -e MONGO_OPENIM_PASSWORD=${PASSWORD} \
- --restart always \
- mongo:6.0.2 --wiredTigerCacheSizeGB 1 --auth
+--name mongo \
+-p 37017:27017 \
+-v "${DATA_DIR}/components/mongodb/data/db:/data/db" \
+-v "${DATA_DIR}/components/mongodb/data/logs:/data/logs" \
+-v "${DATA_DIR}/components/mongodb/data/conf:/etc/mongo" \
+-v "./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro" \
+-e TZ=Asia/Shanghai \
+-e wiredTigerCacheSizeGB=1 \
+-e MONGO_INITDB_ROOT_USERNAME=${OPENIM_USER} \
+-e MONGO_INITDB_ROOT_PASSWORD=${PASSWORD} \
+-e MONGO_INITDB_DATABASE=openim_v3 \
+-e MONGO_OPENIM_USERNAME=${OPENIM_USER} \
+-e MONGO_OPENIM_PASSWORD=${PASSWORD} \
+--restart always \
+mongo:6.0.2 --wiredTigerCacheSizeGB 1 --auth
# Start Redis service
docker run -d \
- --name redis \
- -p 16379:6379 \
- -v "${DATA_DIR}/components/redis/data:/data" \
- -v "${DATA_DIR}/components/redis/config/redis.conf:/usr/local/redis/config/redis.conf" \
- -e TZ=Asia/Shanghai \
- --sysctl net.core.somaxconn=1024 \
- --restart always \
- redis:7.0.0 redis-server --requirepass ${PASSWORD} --appendonly yes
+--name redis \
+-p 16379:6379 \
+-v "${DATA_DIR}/components/redis/data:/data" \
+-v "${DATA_DIR}/components/redis/config/redis.conf:/usr/local/redis/config/redis.conf" \
+-e TZ=Asia/Shanghai \
+--sysctl net.core.somaxconn=1024 \
+--restart always \
+redis:7.0.0 redis-server --requirepass ${PASSWORD} --appendonly yes
# Start Zookeeper service
docker run -d \
- --name zookeeper \
- -p 2181:2181 \
- -v "/etc/localtime:/etc/localtime" \
- -e TZ=Asia/Shanghai \
- --restart always \
- wurstmeister/zookeeper
+--name zookeeper \
+-p 2181:2181 \
+-v "/etc/localtime:/etc/localtime" \
+-e TZ=Asia/Shanghai \
+--restart always \
+wurstmeister/zookeeper
# Start Kafka service
docker run -d \
- --name kafka \
- -p 9092:9092 \
- -e TZ=Asia/Shanghai \
- -e KAFKA_BROKER_ID=0 \
- -e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 \
- -e KAFKA_CREATE_TOPICS="latestMsgToRedis:8:1,msgToPush:8:1,offlineMsgToMongoMysql:8:1" \
- -e KAFKA_ADVERTISED_LISTENERS="INSIDE://127.0.0.1:9092,OUTSIDE://103.116.45.174:9092" \
- -e KAFKA_LISTENERS="INSIDE://:9092,OUTSIDE://:9093" \
- -e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP="INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT" \
- -e KAFKA_INTER_BROKER_LISTENER_NAME=INSIDE \
- --restart always \
- --link zookeeper \
- wurstmeister/kafka
+--name kafka \
+-p 9092:9092 \
+-e TZ=Asia/Shanghai \
+-e KAFKA_BROKER_ID=0 \
+-e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 \
+-e KAFKA_CREATE_TOPICS="latestMsgToRedis:8:1,msgToPush:8:1,offlineMsgToMongoMysql:8:1" \
+-e KAFKA_ADVERTISED_LISTENERS="INSIDE://127.0.0.1:9092,OUTSIDE://103.116.45.174:9092" \
+-e KAFKA_LISTENERS="INSIDE://:9092,OUTSIDE://:9093" \
+-e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP="INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT" \
+-e KAFKA_INTER_BROKER_LISTENER_NAME=INSIDE \
+--restart always \
+--link zookeeper \
+wurstmeister/kafka
# Start MinIO service
docker run -d \
- --name minio \
- -p 10005:9000 \
- -p 9090:9090 \
- -v "/mnt/data:/data" \
- -v "/mnt/config:/root/.minio" \
- -e MINIO_ROOT_USER=${OPENIM_USER} \
- -e MINIO_ROOT_PASSWORD=${PASSWORD} \
- --restart always \
- minio/minio server /data --console-address ':9090'
+--name minio \
+-p 10005:9000 \
+-p 9090:9090 \
+-v "/mnt/data:/data" \
+-v "/mnt/config:/root/.minio" \
+-e MINIO_ROOT_USER=${OPENIM_USER} \
+-e MINIO_ROOT_PASSWORD=${PASSWORD} \
+--restart always \
+minio/minio server /data --console-address ':9090'
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index 41a70c64d..aeb4fcc36 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -28,7 +28,7 @@ source "${OPENIM_ROOT}/scripts/lib/init.sh"
#TODO: Access to the OPENIM_IP networks outside, or you want to use the OPENIM_IP network
# OPENIM_IP=127.0.0.1
if [ -z "${OPENIM_IP}" ]; then
- OPENIM_IP=$(openim::util::get_server_ip)
+ OPENIM_IP=$(openim::util::get_server_ip)
fi
# config.gateway custom bridge modes
@@ -37,9 +37,9 @@ fi
# fi
function def() {
- local var_name="$1"
- local default_value="${2:-}"
- eval "readonly $var_name=\"\${$var_name:-$(printf '%q' "$default_value")}\""
+ local var_name="$1"
+ local default_value="${2:-}"
+ eval "readonly $var_name=\"\${$var_name:-$(printf '%q' "$default_value")}\""
}
# OpenIM Docker Compose 数据存储的默认路径
@@ -52,7 +52,7 @@ def "OPENIM_USER" "root"
readonly PASSWORD=${PASSWORD:-'openIM123'}
# 设置统一的数据库名称,方便管理
-def "DATABASE_NAME" "openIM_v3"
+def "DATABASE_NAME" "openim_v3"
# Linux系统 openim 用户
def "LINUX_USERNAME" "openim"
@@ -89,8 +89,8 @@ SUBNET=$(echo $DOCKER_BRIDGE_SUBNET | cut -d '/' -f 2)
LAST_OCTET=$(echo $IP_PREFIX | cut -d '.' -f 4)
generate_ip() {
- local NEW_IP="$(echo $IP_PREFIX | cut -d '.' -f 1-3).$((LAST_OCTET++))"
- echo $NEW_IP
+ local NEW_IP="$(echo $IP_PREFIX | cut -d '.' -f 1-3).$((LAST_OCTET++))"
+ echo $NEW_IP
}
LAST_OCTET=$((LAST_OCTET + 1))
DOCKER_BRIDGE_GATEWAY=$(generate_ip)
diff --git a/scripts/install/install-protobuf.sh b/scripts/install/install-protobuf.sh
index 33ceaeb0d..838b390b5 100755
--- a/scripts/install/install-protobuf.sh
+++ b/scripts/install/install-protobuf.sh
@@ -21,17 +21,17 @@
# This tool is customized to meet the specific needs of OpenIM and resides in its separate repository.
# It can be downloaded from the following link:
# https://github.com/OpenIMSDK/Open-IM-Protoc/releases/tag/v1.0.0
-#
+#
# About the tool:
# https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md
# Download link (Windows): https://github.com/OpenIMSDK/Open-IM-Protoc/releases/download/v1.0.0/windows.zip
# Download link (Linux): https://github.com/OpenIMSDK/Open-IM-Protoc/releases/download/v1.0.0/linux.zip
-#
+#
# Installation steps (taking Windows as an example):
# 1. Visit the above link and download the version suitable for Windows.
# 2. Extract the downloaded file.
# 3. Add the extracted tool to your PATH environment variable so that it can be run directly from the command line.
-#
+#
# Note: The specific installation and usage instructions may vary based on the tool's actual implementation. It's advised to refer to official documentation.
# --------------------------------------------------------------
@@ -40,79 +40,79 @@ DOWNLOAD_DIR="/tmp/openim-protoc"
INSTALL_DIR="/usr/local/bin"
function help_message {
- echo "Usage: ./install-protobuf.sh [option]"
- echo "Options:"
- echo "-i, --install Install the OpenIM Protoc tool."
- echo "-u, --uninstall Uninstall the OpenIM Protoc tool."
- echo "-r, --reinstall Reinstall the OpenIM Protoc tool."
- echo "-c, --check Check if the OpenIM Protoc tool is installed."
- echo "-h, --help Display this help message."
+ echo "Usage: ./install-protobuf.sh [option]"
+ echo "Options:"
+ echo "-i, --install Install the OpenIM Protoc tool."
+ echo "-u, --uninstall Uninstall the OpenIM Protoc tool."
+ echo "-r, --reinstall Reinstall the OpenIM Protoc tool."
+ echo "-c, --check Check if the OpenIM Protoc tool is installed."
+ echo "-h, --help Display this help message."
}
function install_protobuf {
- echo "Installing OpenIM Protoc tool..."
-
- # Create temporary directory and download the zip file
- mkdir -p $DOWNLOAD_DIR
- wget $PROTOC_DOWNLOAD_URL -O $DOWNLOAD_DIR/linux.zip
-
- # Unzip the file
- unzip -o $DOWNLOAD_DIR/linux.zip -d $DOWNLOAD_DIR
-
- # Move binaries to the install directory and make them executable
- sudo cp $DOWNLOAD_DIR/linux/protoc $INSTALL_DIR/
- sudo cp $DOWNLOAD_DIR/linux/protoc-gen-go $INSTALL_DIR/
- sudo chmod +x $INSTALL_DIR/protoc
- sudo chmod +x $INSTALL_DIR/protoc-gen-go
-
- # Clean up
- rm -rf $DOWNLOAD_DIR
-
- echo "OpenIM Protoc tool installed successfully!"
+ echo "Installing OpenIM Protoc tool..."
+
+ # Create temporary directory and download the zip file
+ mkdir -p $DOWNLOAD_DIR
+ wget $PROTOC_DOWNLOAD_URL -O $DOWNLOAD_DIR/linux.zip
+
+ # Unzip the file
+ unzip -o $DOWNLOAD_DIR/linux.zip -d $DOWNLOAD_DIR
+
+ # Move binaries to the install directory and make them executable
+ sudo cp $DOWNLOAD_DIR/linux/protoc $INSTALL_DIR/
+ sudo cp $DOWNLOAD_DIR/linux/protoc-gen-go $INSTALL_DIR/
+ sudo chmod +x $INSTALL_DIR/protoc
+ sudo chmod +x $INSTALL_DIR/protoc-gen-go
+
+ # Clean up
+ rm -rf $DOWNLOAD_DIR
+
+ echo "OpenIM Protoc tool installed successfully!"
}
function uninstall_protobuf {
- echo "Uninstalling OpenIM Protoc tool..."
-
- # Removing binaries from the install directory
- sudo rm -f $INSTALL_DIR/protoc
- sudo rm -f $INSTALL_DIR/protoc-gen-go
-
- echo "OpenIM Protoc tool uninstalled successfully!"
+ echo "Uninstalling OpenIM Protoc tool..."
+
+ # Removing binaries from the install directory
+ sudo rm -f $INSTALL_DIR/protoc
+ sudo rm -f $INSTALL_DIR/protoc-gen-go
+
+ echo "OpenIM Protoc tool uninstalled successfully!"
}
function reinstall_protobuf {
- echo "Reinstalling OpenIM Protoc tool..."
- uninstall_protobuf
- install_protobuf
+ echo "Reinstalling OpenIM Protoc tool..."
+ uninstall_protobuf
+ install_protobuf
}
function check_protobuf {
- echo "Checking for OpenIM Protoc tool installation..."
-
- which protoc > /dev/null 2>&1
- if [ $? -eq 0 ]; then
- echo "OpenIM Protoc tool is installed."
- else
- echo "OpenIM Protoc tool is not installed."
- fi
+ echo "Checking for OpenIM Protoc tool installation..."
+
+ which protoc > /dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ echo "OpenIM Protoc tool is installed."
+ else
+ echo "OpenIM Protoc tool is not installed."
+ fi
}
while [ "$1" != "" ]; do
- case $1 in
- -i | --install ) install_protobuf
- ;;
- -u | --uninstall ) uninstall_protobuf
- ;;
- -r | --reinstall ) reinstall_protobuf
- ;;
- -c | --check ) check_protobuf
- ;;
- -h | --help ) help_message
- exit
- ;;
- * ) help_message
- exit 1
- esac
- shift
+ case $1 in
+ -i | --install ) install_protobuf
+ ;;
+ -u | --uninstall ) uninstall_protobuf
+ ;;
+ -r | --reinstall ) reinstall_protobuf
+ ;;
+ -c | --check ) check_protobuf
+ ;;
+ -h | --help ) help_message
+ exit
+ ;;
+ * ) help_message
+ exit 1
+ esac
+ shift
done
diff --git a/scripts/install/install.sh b/scripts/install/install.sh
index b88fe9083..d5ec5b7f7 100755
--- a/scripts/install/install.sh
+++ b/scripts/install/install.sh
@@ -14,38 +14,38 @@
# limitations under the License.
#
# OpenIM Server Installation Script
-#
+#
# Description:
-# This script is designed to handle the installation, Is a deployment solution
+# This script is designed to handle the installation, Is a deployment solution
# that uses the Linux systen extension. uninstallation, and
# status checking of OpenIM components on the server. OpenIM is a presumed
# communication or messaging platform based on the context.
-#
+#
# Usage:
-# To utilize this script, you need to invoke it with specific commands
+# To utilize this script, you need to invoke it with specific commands
# and options as detailed below.
-#
+#
# Commands:
-# -i, --install : Use this command to initiate the installation of all
+# -i, --install : Use this command to initiate the installation of all
# OpenIM components.
-# -u, --uninstall : Use this command to uninstall or remove all
+# -u, --uninstall : Use this command to uninstall or remove all
# OpenIM components from the server.
-# -s, --status : This command can be used to check and report the
+# -s, --status : This command can be used to check and report the
# current operational status of the installed OpenIM components.
# -h, --help : For any assistance or to view the available commands,
# use this command to display the help menu.
-#
+#
# Example Usage:
# To install all OpenIM components:
-# ./scripts/install/install.sh -i
-# or
-# ./scripts/install/install.sh --install
-#
+# ./scripts/install/install.sh -i
+# or
+# ./scripts/install/install.sh --install
+#
# Note:
# Ensure you have the necessary privileges to execute installation or
-# uninstallation operations. It's generally recommended to take a backup
+# uninstallation operations. It's generally recommended to take a backup
# before making major changes.
-#
+#
###############################################################################
OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P)
@@ -57,99 +57,99 @@ ${OPENIM_ROOT}/scripts/install/test.sh
# Detailed help function
function openim::install::show_help() {
- echo "OpenIM Installer"
- echo "Usage: $0 [options]"
- echo ""
- echo "Commands:"
- echo " -i, --install Install all OpenIM components."
- echo " -u, --uninstall Remove all OpenIM components."
- echo " -s, --status Check the current status of OpenIM components."
- echo " -h, --help Show this help menu."
- echo ""
- echo "Example: "
- echo " $0 -i Will install all OpenIM components."
- echo " $0 --install Same as above."
+ echo "OpenIM Installer"
+ echo "Usage: $0 [options]"
+ echo ""
+ echo "Commands:"
+ echo " -i, --install Install all OpenIM components."
+ echo " -u, --uninstall Remove all OpenIM components."
+ echo " -s, --status Check the current status of OpenIM components."
+ echo " -h, --help Show this help menu."
+ echo ""
+ echo "Example: "
+ echo " $0 -i Will install all OpenIM components."
+ echo " $0 --install Same as above."
}
function openim::install::install_openim() {
- openim::common::sudo "mkdir -p ${OPENIM_DATA_DIR} ${OPENIM_INSTALL_DIR} ${OPENIM_CONFIG_DIR} ${OPENIM_LOG_DIR}"
- openim::log::info "check openim dependency"
- openim::common::sudo "cp -r ${OPENIM_ROOT}/config/* ${OPENIM_CONFIG_DIR}/"
-
- ${OPENIM_ROOT}/scripts/genconfig.sh ${ENV_FILE} ${OPENIM_ROOT}/deployments/templates/openim.yaml > ${OPENIM_CONFIG_DIR}/config.yaml
- ${OPENIM_ROOT}/scripts/genconfig.sh ${ENV_FILE} ${OPENIM_ROOT}/deployments/templates/prometheus.yml > ${OPENIM_CONFIG_DIR}/prometheus.yml
-
- openim::util::check_ports ${OPENIM_DEPENDENCY_PORT_LISTARIES[@]}
-
- ${OPENIM_ROOT}/scripts/install/openim-msggateway.sh openim::msggateway::install || return 1
- ${OPENIM_ROOT}/scripts/install/openim-msgtransfer.sh openim::msgtransfer::install || return 1
- ${OPENIM_ROOT}/scripts/install/openim-push.sh openim::push::install || return 1
- ${OPENIM_ROOT}/scripts/install/openim-crontask.sh openim::crontask::install || return 1
- ${OPENIM_ROOT}/scripts/install/openim-rpc.sh openim::rpc::install || return 1
- ${OPENIM_ROOT}/scripts/install/openim-api.sh openim::api::install || return 1
-
- openim::common::sudo "cp -r ${OPENIM_ROOT}/deployments/templates/openim.target /etc/systemd/system/openim.target"
- openim::common::sudo "systemctl daemon-reload"
- openim::common::sudo "systemctl restart openim.target"
- openim::common::sudo "systemctl enable openim.target"
- openim::log::success "openim install success"
+ openim::common::sudo "mkdir -p ${OPENIM_DATA_DIR} ${OPENIM_INSTALL_DIR} ${OPENIM_CONFIG_DIR} ${OPENIM_LOG_DIR}"
+ openim::log::info "check openim dependency"
+ openim::common::sudo "cp -r ${OPENIM_ROOT}/config/* ${OPENIM_CONFIG_DIR}/"
+
+ ${OPENIM_ROOT}/scripts/genconfig.sh ${ENV_FILE} ${OPENIM_ROOT}/deployments/templates/config.yaml > ${OPENIM_CONFIG_DIR}/config.yaml
+ ${OPENIM_ROOT}/scripts/genconfig.sh ${ENV_FILE} ${OPENIM_ROOT}/deployments/templates/prometheus.yml > ${OPENIM_CONFIG_DIR}/prometheus.yml
+
+ openim::util::check_ports ${OPENIM_DEPENDENCY_PORT_LISTARIES[@]}
+
+ ${OPENIM_ROOT}/scripts/install/openim-msggateway.sh openim::msggateway::install || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-msgtransfer.sh openim::msgtransfer::install || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-push.sh openim::push::install || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-crontask.sh openim::crontask::install || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-rpc.sh openim::rpc::install || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-api.sh openim::api::install || return 1
+
+ openim::common::sudo "cp -r ${OPENIM_ROOT}/deployments/templates/openim.target /etc/systemd/system/openim.target"
+ openim::common::sudo "systemctl daemon-reload"
+ openim::common::sudo "systemctl restart openim.target"
+ openim::common::sudo "systemctl enable openim.target"
+ openim::log::success "openim install success"
}
function openim::uninstall::uninstall_openim() {
- openim::log::info "uninstall openim"
-
- ${OPENIM_ROOT}/scripts/install/openim-msggateway.sh openim::msggateway::uninstall || return 1
- ${OPENIM_ROOT}/scripts/install/openim-msgtransfer.sh openim::msgtransfer::uninstall || return 1
- ${OPENIM_ROOT}/scripts/install/openim-push.sh openim::push::uninstall || return 1
- ${OPENIM_ROOT}/scripts/install/openim-crontask.sh openim::crontask::uninstall || return 1
- ${OPENIM_ROOT}/scripts/install/openim-rpc.sh openim::rpc::uninstall || return 1
- ${OPENIM_ROOT}/scripts/install/openim-api.sh openim::api::uninstall || return 1
-
- set +o errexit
- openim::common::sudo "systemctl stop openim.target"
- openim::common::sudo "systemctl disable openim.target"
- openim::common::sudo "rm -f /etc/systemd/system/openim.target"
- set -o errexit
- openim::log::success "openim uninstall success"
+ openim::log::info "uninstall openim"
+
+ ${OPENIM_ROOT}/scripts/install/openim-msggateway.sh openim::msggateway::uninstall || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-msgtransfer.sh openim::msgtransfer::uninstall || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-push.sh openim::push::uninstall || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-crontask.sh openim::crontask::uninstall || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-rpc.sh openim::rpc::uninstall || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-api.sh openim::api::uninstall || return 1
+
+ set +o errexit
+ openim::common::sudo "systemctl stop openim.target"
+ openim::common::sudo "systemctl disable openim.target"
+ openim::common::sudo "rm -f /etc/systemd/system/openim.target"
+ set -o errexit
+ openim::log::success "openim uninstall success"
}
function openim::install::status() {
- openim::log::info "check openim status"
-
- ${OPENIM_ROOT}/scripts/install/openim-msggateway.sh openim::msggateway::status || return 1
- ${OPENIM_ROOT}/scripts/install/openim-msgtransfer.sh openim::msgtransfer::status || return 1
- ${OPENIM_ROOT}/scripts/install/openim-push.sh openim::push::status || return 1
- ${OPENIM_ROOT}/scripts/install/openim-crontask.sh openim::crontask::status || return 1
- ${OPENIM_ROOT}/scripts/install/openim-rpc.sh openim::rpc::status || return 1
- ${OPENIM_ROOT}/scripts/install/openim-api.sh openim::api::status || return 1
-
- openim::log::success "openim status success"
+ openim::log::info "check openim status"
+
+ ${OPENIM_ROOT}/scripts/install/openim-msggateway.sh openim::msggateway::status || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-msgtransfer.sh openim::msgtransfer::status || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-push.sh openim::push::status || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-crontask.sh openim::crontask::status || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-rpc.sh openim::rpc::status || return 1
+ ${OPENIM_ROOT}/scripts/install/openim-api.sh openim::api::status || return 1
+
+ openim::log::success "openim status success"
}
# If no arguments are provided, show help
if [[ $# -eq 0 ]]; then
- openim::install::show_help
- exit 0
+ openim::install::show_help
+ exit 0
fi
# Argument parsing to call functions based on user input
while (( "$#" )); do
- case "$1" in
- -i|--install)
- openim::install::install_openim
- shift
- ;;
- -u|--uninstall)
- openim::uninstall::uninstall_openim
- shift
- ;;
- -s|--status)
- openim::install::status
- shift
- ;;
- -h|--help|*)
- openim::install::show_help
- exit 0
- ;;
- esac
+ case "$1" in
+ -i|--install)
+ openim::install::install_openim
+ shift
+ ;;
+ -u|--uninstall)
+ openim::uninstall::uninstall_openim
+ shift
+ ;;
+ -s|--status)
+ openim::install::status
+ shift
+ ;;
+ -h|--help|*)
+ openim::install::show_help
+ exit 0
+ ;;
+ esac
done
\ No newline at end of file
diff --git a/scripts/install/openim-api.sh b/scripts/install/openim-api.sh
index 9f66d0ba0..2c3c19afb 100755
--- a/scripts/install/openim-api.sh
+++ b/scripts/install/openim-api.sh
@@ -34,55 +34,55 @@ readonly OPENIM_API_SERVICE_TARGETS=(
readonly OPENIM_API_SERVICE_LISTARIES=("${OPENIM_API_SERVICE_TARGETS[@]##*/}")
function openim::api::start() {
- echo "++ OPENIM_API_SERVICE_LISTARIES: ${OPENIM_API_SERVICE_LISTARIES[@]}"
- echo "++ OPENIM_API_PORT_LISTARIES: ${OPENIM_API_PORT_LISTARIES[@]}"
- echo "++ OpenIM API config path: ${OPENIM_API_CONFIG}"
-
- openim::log::info "Starting ${SERVER_NAME} ..."
-
- printf "+------------------------+--------------+\n"
- printf "| Service Name | Port |\n"
- printf "+------------------------+--------------+\n"
-
- length=${#OPENIM_API_SERVICE_LISTARIES[@]}
-
- for ((i=0; i<$length; i++)); do
+ echo "++ OPENIM_API_SERVICE_LISTARIES: ${OPENIM_API_SERVICE_LISTARIES[@]}"
+ echo "++ OPENIM_API_PORT_LISTARIES: ${OPENIM_API_PORT_LISTARIES[@]}"
+ echo "++ OpenIM API config path: ${OPENIM_API_CONFIG}"
+
+ openim::log::info "Starting ${SERVER_NAME} ..."
+
+ printf "+------------------------+--------------+\n"
+ printf "| Service Name | Port |\n"
+ printf "+------------------------+--------------+\n"
+
+ length=${#OPENIM_API_SERVICE_LISTARIES[@]}
+
+ for ((i=0; i<$length; i++)); do
printf "| %-22s | %6s |\n" "${OPENIM_API_SERVICE_LISTARIES[$i]}" "${OPENIM_API_PORT_LISTARIES[$i]}"
printf "+------------------------+--------------+\n"
- done
- # start all api services
- for ((i = 0; i < ${#OPENIM_API_SERVICE_LISTARIES[*]}; i++)); do
+ done
+ # start all api services
+ for ((i = 0; i < ${#OPENIM_API_SERVICE_LISTARIES[*]}; i++)); do
openim::util::stop_services_on_ports ${OPENIM_API_PORT_LISTARIES[$i]}
openim::log::info "OpenIM ${OPENIM_API_SERVICE_LISTARIES[$i]} config path: ${OPENIM_API_CONFIG}"
-
+
# Get the service and Prometheus ports.
OPENIM_API_SERVICE_PORTS=( $(openim::util::list-to-string ${OPENIM_API_PORT_LISTARIES[$i]}) )
-
+
# TODO Only one port is supported. An error occurs on multiple ports
if [ ${#OPENIM_API_SERVICE_PORTS[@]} -ne 1 ]; then
- openim::log::error_exit "Set only one port for ${OPENIM_API_SERVICE_LISTARIES[$i]} service."
+ openim::log::error_exit "Set only one port for ${OPENIM_API_SERVICE_LISTARIES[$i]} service."
fi
-
+
for ((j = 0; j < ${#OPENIM_API_SERVICE_PORTS[@]}; j++)); do
- openim::log::info "Starting ${OPENIM_API_SERVICE_LISTARIES[$i]} service, port: ${OPENIM_API_SERVICE_PORTS[j]}, binary root: ${OPENIM_OUTPUT_HOSTBIN}/${OPENIM_API_SERVICE_LISTARIES[$i]}"
- openim::api::start_service "${OPENIM_API_SERVICE_LISTARIES[$i]}" "${OPENIM_API_PORT_LISTARIES[j]}"
- sleep 2
- done
+ openim::log::info "Starting ${OPENIM_API_SERVICE_LISTARIES[$i]} service, port: ${OPENIM_API_SERVICE_PORTS[j]}, binary root: ${OPENIM_OUTPUT_HOSTBIN}/${OPENIM_API_SERVICE_LISTARIES[$i]}"
+ openim::api::start_service "${OPENIM_API_SERVICE_LISTARIES[$i]}" "${OPENIM_API_PORT_LISTARIES[j]}"
+ sleep 2
done
-
- OPENIM_API_PORT_STRINGARIES=( $(openim::util::list-to-string ${OPENIM_API_PORT_LISTARIES[@]}) )
- openim::util::check_ports ${OPENIM_API_PORT_STRINGARIES[@]}
+ done
+
+ OPENIM_API_PORT_STRINGARIES=( $(openim::util::list-to-string ${OPENIM_API_PORT_LISTARIES[@]}) )
+ openim::util::check_ports ${OPENIM_API_PORT_STRINGARIES[@]}
}
function openim::api::start_service() {
local binary_name="$1"
local service_port="$2"
local prometheus_port="$3"
-
+
local cmd="${OPENIM_OUTPUT_HOSTBIN}/${binary_name} --port ${service_port} -c ${OPENIM_API_CONFIG}"
-
+
nohup ${cmd} >> "${LOG_FILE}" 2>&1 &
-
+
if [ $? -ne 0 ]; then
openim::log::error_exit "Failed to start ${binary_name} on port ${service_port}."
fi
@@ -100,61 +100,61 @@ EOF
# install openim-api
function openim::api::install() {
- openim::log::info "Installing ${SERVER_NAME} ..."
-
- pushd "${OPENIM_ROOT}"
-
- # 1. Build openim-api
- make build BINS=${SERVER_NAME}
- openim::common::sudo "cp -r ${OPENIM_OUTPUT_HOSTBIN}/${SERVER_NAME} ${OPENIM_INSTALL_DIR}/${SERVER_NAME}"
- openim::log::status "${SERVER_NAME} binary: ${OPENIM_INSTALL_DIR}/${SERVER_NAME}/${SERVER_NAME}"
-
- # 2. Generate and install the openim-api configuration file (config)
- openim::log::status "${SERVER_NAME} config file: ${OPENIM_CONFIG_DIR}/config.yaml"
-
- # 3. Create and install the ${SERVER_NAME} systemd unit file
- echo ${LINUX_PASSWORD} | sudo -S bash -c \
- "SERVER_NAME=${SERVER_NAME} ./scripts/genconfig.sh ${ENV_FILE} deployments/templates/openim.service > ${SYSTEM_FILE_PATH}"
- openim::log::status "${SERVER_NAME} systemd file: ${SYSTEM_FILE_PATH}"
-
- # 4. Start the openim-api service
- openim::common::sudo "systemctl daemon-reload"
- openim::common::sudo "systemctl restart ${SERVER_NAME}"
- openim::common::sudo "systemctl enable ${SERVER_NAME}"
- openim::api::status || return 1
- openim::api::info
-
- openim::log::info "install ${SERVER_NAME} successfully"
- popd
+ openim::log::info "Installing ${SERVER_NAME} ..."
+
+ pushd "${OPENIM_ROOT}"
+
+ # 1. Build openim-api
+ make build BINS=${SERVER_NAME}
+ openim::common::sudo "cp -r ${OPENIM_OUTPUT_HOSTBIN}/${SERVER_NAME} ${OPENIM_INSTALL_DIR}/${SERVER_NAME}"
+ openim::log::status "${SERVER_NAME} binary: ${OPENIM_INSTALL_DIR}/${SERVER_NAME}/${SERVER_NAME}"
+
+ # 2. Generate and install the openim-api configuration file (config)
+ openim::log::status "${SERVER_NAME} config file: ${OPENIM_CONFIG_DIR}/config.yaml"
+
+ # 3. Create and install the ${SERVER_NAME} systemd unit file
+ echo ${LINUX_PASSWORD} | sudo -S bash -c \
+ "SERVER_NAME=${SERVER_NAME} ./scripts/genconfig.sh ${ENV_FILE} deployments/templates/openim.service > ${SYSTEM_FILE_PATH}"
+ openim::log::status "${SERVER_NAME} systemd file: ${SYSTEM_FILE_PATH}"
+
+ # 4. Start the openim-api service
+ openim::common::sudo "systemctl daemon-reload"
+ openim::common::sudo "systemctl restart ${SERVER_NAME}"
+ openim::common::sudo "systemctl enable ${SERVER_NAME}"
+ openim::api::status || return 1
+ openim::api::info
+
+ openim::log::info "install ${SERVER_NAME} successfully"
+ popd
}
# Unload
function openim::api::uninstall() {
- openim::log::info "Uninstalling ${SERVER_NAME} ..."
-
- set +o errexit
- openim::common::sudo "systemctl stop ${SERVER_NAME}"
- openim::common::sudo "systemctl disable ${SERVER_NAME}"
- openim::common::sudo "rm -f ${OPENIM_INSTALL_DIR}/${SERVER_NAME}"
- openim::common::sudo "rm -f ${OPENIM_CONFIG_DIR}/${SERVER_NAME}.yaml"
- openim::common::sudo "rm -f /etc/systemd/system/${SERVER_NAME}.service"
- set -o errexit
- openim::log::info "uninstall ${SERVER_NAME} successfully"
+ openim::log::info "Uninstalling ${SERVER_NAME} ..."
+
+ set +o errexit
+ openim::common::sudo "systemctl stop ${SERVER_NAME}"
+ openim::common::sudo "systemctl disable ${SERVER_NAME}"
+ openim::common::sudo "rm -f ${OPENIM_INSTALL_DIR}/${SERVER_NAME}"
+ openim::common::sudo "rm -f ${OPENIM_CONFIG_DIR}/${SERVER_NAME}.yaml"
+ openim::common::sudo "rm -f /etc/systemd/system/${SERVER_NAME}.service"
+ set -o errexit
+ openim::log::info "uninstall ${SERVER_NAME} successfully"
}
# Status Check
function openim::api::status() {
- openim::log::info "Checking ${SERVER_NAME} status ..."
-
- # Check the running status of the ${SERVER_NAME}. If active (running) is displayed, the ${SERVER_NAME} is started successfully.
- systemctl status ${SERVER_NAME}|grep -q 'active' || {
- openim::log::error "${SERVER_NAME} failed to start, maybe not installed properly"
- return 1
- }
-
- openim::util::check_ports ${OPENIM_API_PORT_LISTARIES[@]}
+ openim::log::info "Checking ${SERVER_NAME} status ..."
+
+ # Check the running status of the ${SERVER_NAME}. If active (running) is displayed, the ${SERVER_NAME} is started successfully.
+ systemctl status ${SERVER_NAME}|grep -q 'active' || {
+ openim::log::error "${SERVER_NAME} failed to start, maybe not installed properly"
+ return 1
+ }
+
+ openim::util::check_ports ${OPENIM_API_PORT_LISTARIES[@]}
}
if [[ "$*" =~ openim::api:: ]];then
- eval $*
+ eval $*
fi
diff --git a/scripts/install/openim-crontask.sh b/scripts/install/openim-crontask.sh
index 26dc1a47f..cc9e686ff 100755
--- a/scripts/install/openim-crontask.sh
+++ b/scripts/install/openim-crontask.sh
@@ -13,12 +13,12 @@
# 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.
-#
+#
# OpenIM CronTask Control Script
-#
+#
# Description:
# This script provides a control interface for the OpenIM CronTask service within a Linux environment. It supports two installation methods: installation via function calls to systemctl, and direct installation through background processes.
-#
+#
# Features:
# 1. Robust error handling leveraging Bash built-ins such as 'errexit', 'nounset', and 'pipefail'.
# 2. Capability to source common utility functions and configurations, ensuring environmental consistency.
@@ -30,13 +30,13 @@
# 1. Direct Script Execution:
# This will start the OpenIM CronTask directly through a background process.
# Example: ./openim-crontask.sh openim::crontask::start
-#
+#
# 2. Controlling through Functions for systemctl operations:
# Specific operations like installation, uninstallation, and status check can be executed by passing the respective function name as an argument to the script.
# Example: ./openim-crontask.sh openim::crontask::install
-#
+#
# Note: Ensure that the appropriate permissions and environmental variables are set prior to script execution.
-#
+#
OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P)
[[ -z ${COMMON_SOURCED} ]] && source "${OPENIM_ROOT}"/scripts/install/common.sh
@@ -44,14 +44,14 @@ OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P)
SERVER_NAME="openim-crontask"
function openim::crontask::start() {
- openim::log::info "Start OpenIM Cron, binary root: ${SERVER_NAME}"
- openim::log::status "Start OpenIM Cron, path: ${OPENIM_CRONTASK_BINARY}"
-
- openim::util::stop_services_with_name ${OPENIM_CRONTASK_BINARY}
-
- openim::log::status "start cron_task process, path: ${OPENIM_CRONTASK_BINARY}"
- nohup ${OPENIM_CRONTASK_BINARY} -c ${OPENIM_PUSH_CONFIG} >> ${LOG_FILE} 2>&1 &
- openim::util::check_process_names ${SERVER_NAME}
+ openim::log::info "Start OpenIM Cron, binary root: ${SERVER_NAME}"
+ openim::log::status "Start OpenIM Cron, path: ${OPENIM_CRONTASK_BINARY}"
+
+ openim::util::stop_services_with_name ${OPENIM_CRONTASK_BINARY}
+
+ openim::log::status "start cron_task process, path: ${OPENIM_CRONTASK_BINARY}"
+ nohup ${OPENIM_CRONTASK_BINARY} -c ${OPENIM_PUSH_CONFIG} >> ${LOG_FILE} 2>&1 &
+ openim::util::check_process_names ${SERVER_NAME}
}
###################################### Linux Systemd ######################################
@@ -67,28 +67,28 @@ EOF
# install openim-crontask
function openim::crontask::install() {
pushd "${OPENIM_ROOT}"
-
+
# 1. Build openim-crontask
make build BINS=${SERVER_NAME}
-
+
openim::common::sudo "cp -r ${OPENIM_OUTPUT_HOSTBIN}/${SERVER_NAME} ${OPENIM_INSTALL_DIR}/${SERVER_NAME}"
openim::log::status "${SERVER_NAME} binary: ${OPENIM_INSTALL_DIR}/${SERVER_NAME}/${SERVER_NAME}"
-
+
# 2. Generate and install the openim-crontask configuration file (openim-crontask.yaml)
openim::log::status "${SERVER_NAME} config file: ${OPENIM_CONFIG_DIR}/config.yaml"
-
+
# 3. Create and install the ${SERVER_NAME} systemd unit file
echo ${LINUX_PASSWORD} | sudo -S bash -c \
- "SERVER_NAME=${SERVER_NAME} ./scripts/genconfig.sh ${ENV_FILE} deployments/templates/openim.service > ${SYSTEM_FILE_PATH}"
+ "SERVER_NAME=${SERVER_NAME} ./scripts/genconfig.sh ${ENV_FILE} deployments/templates/openim.service > ${SYSTEM_FILE_PATH}"
openim::log::status "${SERVER_NAME} systemd file: ${SYSTEM_FILE_PATH}"
-
+
# 4. Start the openim-crontask service
openim::common::sudo "systemctl daemon-reload"
openim::common::sudo "systemctl restart ${SERVER_NAME}"
openim::common::sudo "systemctl enable ${SERVER_NAME}"
openim::crontask::status || return 1
openim::crontask::info
-
+
openim::log::info "install ${SERVER_NAME} successfully"
popd
}
diff --git a/scripts/install/openim-man.sh b/scripts/install/openim-man.sh
index f23c54a20..fac5cebea 100755
--- a/scripts/install/openim-man.sh
+++ b/scripts/install/openim-man.sh
@@ -17,7 +17,7 @@
#
# Description:
# This script manages the man pages for the OpenIM software suite.
-# It provides facilities to install, uninstall, and verify the
+# It provides facilities to install, uninstall, and verify the
# installation status of the man pages related to OpenIM components.
#
# Usage:
@@ -26,15 +26,15 @@
# ./openim-man.sh openim::man::status - Check installation status
#
# Dependencies:
-# - Assumes there's a common.sh in "${OPENIM_ROOT}/scripts/install/"
+# - Assumes there's a common.sh in "${OPENIM_ROOT}/scripts/install/"
# containing shared functions and variables.
-# - Relies on the script "${OPENIM_ROOT}/scripts/update-generated-docs.sh"
+# - Relies on the script "${OPENIM_ROOT}/scripts/update-generated-docs.sh"
# to generate the man pages.
#
# Notes:
-# - This script must be run with appropriate permissions to modify the
+# - This script must be run with appropriate permissions to modify the
# system man directories.
-# - Always ensure you're in the script's directory or provide the correct
+# - Always ensure you're in the script's directory or provide the correct
# path when executing.
################################################################################
@@ -54,43 +54,43 @@ EOF
# Install the man pages for openim
function openim::man::install() {
- # Navigate to the openim root directory
- pushd "${OPENIM_ROOT}" > /dev/null
-
- # Generate man pages for each component
- "${OPENIM_ROOT}/scripts/update-generated-docs.sh"
- openim::common::sudo "cp docs/man/man1/* /usr/share/man/man1/"
-
- # Verify installation status
- if openim::man::status; then
- openim::log::info "Installed openim-server man page successfully"
- openim::man::info
- fi
-
- # Return to the original directory
- popd > /dev/null
+ # Navigate to the openim root directory
+ pushd "${OPENIM_ROOT}" > /dev/null
+
+ # Generate man pages for each component
+ "${OPENIM_ROOT}/scripts/update-generated-docs.sh"
+ openim::common::sudo "cp docs/man/man1/* /usr/share/man/man1/"
+
+ # Verify installation status
+ if openim::man::status; then
+ openim::log::info "Installed openim-server man page successfully"
+ openim::man::info
+ fi
+
+ # Return to the original directory
+ popd > /dev/null
}
# Uninstall the man pages for openim
function openim::man::uninstall() {
- # Turn off exit-on-error temporarily to handle non-existing files gracefully
- set +o errexit
- openim::common::sudo "rm -f /usr/share/man/man1/openim-*"
- set -o errexit
-
- openim::log::info "Uninstalled openim man pages successfully"
+ # Turn off exit-on-error temporarily to handle non-existing files gracefully
+ set +o errexit
+ openim::common::sudo "rm -f /usr/share/man/man1/openim-*"
+ set -o errexit
+
+ openim::log::info "Uninstalled openim man pages successfully"
}
# Check the installation status of the man pages
function openim::man::status() {
- if ! ls /usr/share/man/man1/openim-* &> /dev/null; then
- openim::log::error "OpenIM man files not found. Perhaps they were not installed correctly."
- return 1
- fi
- return 0
+ if ! ls /usr/share/man/man1/openim-* &> /dev/null; then
+ openim::log::error "OpenIM man files not found. Perhaps they were not installed correctly."
+ return 1
+ fi
+ return 0
}
# Execute the appropriate function based on the given arguments
if [[ "$*" =~ openim::man:: ]]; then
- eval "$*"
+ eval "$*"
fi
diff --git a/scripts/install/openim-msggateway.sh b/scripts/install/openim-msggateway.sh
index 2b2a84b12..d9fec4928 100755
--- a/scripts/install/openim-msggateway.sh
+++ b/scripts/install/openim-msggateway.sh
@@ -26,19 +26,19 @@ openim::util::set_max_fd 200000
SERVER_NAME="openim-msggateway"
function openim::msggateway::start() {
- openim::log::info "Start OpenIM Msggateway, binary root: ${SERVER_NAME}"
- openim::log::status "Start OpenIM Msggateway, path: ${OPENIM_MSGGATEWAY_BINARY}"
-
- openim::util::stop_services_with_name ${OPENIM_MSGGATEWAY_BINARY}
-
- # OpenIM message gateway service port
- OPENIM_MESSAGE_GATEWAY_PORTS=$(openim::util::list-to-string ${OPENIM_MESSAGE_GATEWAY_PORT} )
+ openim::log::info "Start OpenIM Msggateway, binary root: ${SERVER_NAME}"
+ openim::log::status "Start OpenIM Msggateway, path: ${OPENIM_MSGGATEWAY_BINARY}"
+
+ openim::util::stop_services_with_name ${OPENIM_MSGGATEWAY_BINARY}
+
+ # OpenIM message gateway service port
+ OPENIM_MESSAGE_GATEWAY_PORTS=$(openim::util::list-to-string ${OPENIM_MESSAGE_GATEWAY_PORT} )
read -a OPENIM_MSGGATEWAY_PORTS_ARRAY <<< ${OPENIM_MESSAGE_GATEWAY_PORTS}
openim::util::stop_services_on_ports ${OPENIM_MSGGATEWAY_PORTS_ARRAY[*]}
# OpenIM WS port
OPENIM_WS_PORTS=$(openim::util::list-to-string ${OPENIM_WS_PORT} )
read -a OPENIM_WS_PORTS_ARRAY <<< ${OPENIM_WS_PORTS}
-
+
# Message Gateway Prometheus port of the service
MSG_GATEWAY_PROM_PORTS=$(openim::util::list-to-string ${MSG_GATEWAY_PROM_PORT} )
read -a MSG_GATEWAY_PROM_PORTS_ARRAY <<< ${MSG_GATEWAY_PROM_PORTS}
@@ -123,7 +123,7 @@ function openim::msggateway::status() {
# Check the running status of the ${SERVER_NAME}. If active (running) is displayed, the ${SERVER_NAME} is started successfully.
systemctl status ${SERVER_NAME}|grep -q 'active' || {
openim::log::error "${SERVER_NAME} failed to start, maybe not installed properly"
-
+
return 1
}
diff --git a/scripts/install/openim-msgtransfer.sh b/scripts/install/openim-msgtransfer.sh
index f6039637c..1cead3a9a 100755
--- a/scripts/install/openim-msgtransfer.sh
+++ b/scripts/install/openim-msgtransfer.sh
@@ -28,59 +28,59 @@ openim::util::set_max_fd 200000
SERVER_NAME="openim-msgtransfer"
function openim::msgtransfer::start() {
- openim::log::info "Start OpenIM Msggateway, binary root: ${SERVER_NAME}"
- openim::log::status "Start OpenIM Msggateway, path: ${OPENIM_MSGTRANSFER_BINARY}"
-
- openim::util::stop_services_with_name ${OPENIM_MSGTRANSFER_BINARY}
-
- # Message Transfer Prometheus port list
- MSG_TRANSFER_PROM_PORTS=(openim::util::list-to-string ${MSG_TRANSFER_PROM_PORT} )
-
- openim::log::status "OpenIM Prometheus ports: ${MSG_TRANSFER_PROM_PORTS[*]}"
-
- openim::log::status "OpenIM Msggateway config path: ${OPENIM_MSGTRANSFER_CONFIG}"
-
- openim::log::info "openim maggateway num: ${OPENIM_MSGGATEWAY_NUM}"
-
- if [ "${OPENIM_MSGGATEWAY_NUM}" -lt 1 ]; then
+ openim::log::info "Start OpenIM Msggateway, binary root: ${SERVER_NAME}"
+ openim::log::status "Start OpenIM Msggateway, path: ${OPENIM_MSGTRANSFER_BINARY}"
+
+ openim::util::stop_services_with_name ${OPENIM_MSGTRANSFER_BINARY}
+
+ # Message Transfer Prometheus port list
+ MSG_TRANSFER_PROM_PORTS=(openim::util::list-to-string ${MSG_TRANSFER_PROM_PORT} )
+
+ openim::log::status "OpenIM Prometheus ports: ${MSG_TRANSFER_PROM_PORTS[*]}"
+
+ openim::log::status "OpenIM Msggateway config path: ${OPENIM_MSGTRANSFER_CONFIG}"
+
+ openim::log::info "openim maggateway num: ${OPENIM_MSGGATEWAY_NUM}"
+
+ if [ "${OPENIM_MSGGATEWAY_NUM}" -lt 1 ]; then
opeim::log::error_exit "OPENIM_MSGGATEWAY_NUM must be greater than 0"
- fi
-
- if [ ${OPENIM_MSGGATEWAY_NUM} -ne $((${#MSG_TRANSFER_PROM_PORTS[@]} - 1)) ]; then
+ fi
+
+ if [ ${OPENIM_MSGGATEWAY_NUM} -ne $((${#MSG_TRANSFER_PROM_PORTS[@]} - 1)) ]; then
openim::log::error_exit "OPENIM_MSGGATEWAY_NUM must be equal to the number of MSG_TRANSFER_PROM_PORTS"
+ fi
+
+ for (( i=0; i<$OPENIM_MSGGATEWAY_NUM; i++ )) do
+ openim::log::info "prometheus port: ${MSG_TRANSFER_PROM_PORTS[$i]}"
+ PROMETHEUS_PORT_OPTION=""
+ if [[ -n "${OPENIM_PROMETHEUS_PORTS[$i]}" ]]; then
+ PROMETHEUS_PORT_OPTION="--prometheus_port ${OPENIM_PROMETHEUS_PORTS[$i]}"
fi
-
- for (( i=0; i<$OPENIM_MSGGATEWAY_NUM; i++ )) do
- openim::log::info "prometheus port: ${MSG_TRANSFER_PROM_PORTS[$i]}"
- PROMETHEUS_PORT_OPTION=""
- if [[ -n "${OPENIM_PROMETHEUS_PORTS[$i]}" ]]; then
- PROMETHEUS_PORT_OPTION="--prometheus_port ${OPENIM_PROMETHEUS_PORTS[$i]}"
- fi
- nohup ${OPENIM_MSGTRANSFER_BINARY} ${PROMETHEUS_PORT_OPTION} -c ${OPENIM_MSGTRANSFER_CONFIG} -n ${i}>> ${LOG_FILE} 2>&1 &
- done
-
- openim::util::check_process_names "${OPENIM_OUTPUT_HOSTBIN}/${SERVER_NAME}"
+ nohup ${OPENIM_MSGTRANSFER_BINARY} ${PROMETHEUS_PORT_OPTION} -c ${OPENIM_MSGTRANSFER_CONFIG} -n ${i}>> ${LOG_FILE} 2>&1 &
+ done
+
+ openim::util::check_process_names "${OPENIM_OUTPUT_HOSTBIN}/${SERVER_NAME}"
}
function openim::msgtransfer::check() {
- PIDS=$(pgrep -f "${OPENIM_OUTPUT_HOSTBIN}/openim-msgtransfer")
-
- NUM_PROCESSES=$(echo "$PIDS" | wc -l)
-
- if [ "$NUM_PROCESSES" -eq "$OPENIM_MSGGATEWAY_NUM" ]; then
- openim::log::info "Found $OPENIM_MSGGATEWAY_NUM processes named $OPENIM_OUTPUT_HOSTBIN"
- for PID in $PIDS; do
- if [[ "$OSTYPE" == "linux-gnu"* ]]; then
- ps -p $PID -o pid,cmd
- elif [[ "$OSTYPE" == "darwin"* ]]; then
- ps -p $PID -o pid,comm
- else
- openim::log::error "Unsupported OS type: $OSTYPE"
- fi
- done
- else
- openim::log::error_exit "Expected $OPENIM_MSGGATEWAY_NUM openim msgtransfer processes, but found $NUM_PROCESSES msgtransfer processes."
- fi
+ PIDS=$(pgrep -f "${OPENIM_OUTPUT_HOSTBIN}/openim-msgtransfer")
+
+ NUM_PROCESSES=$(echo "$PIDS" | wc -l)
+
+ if [ "$NUM_PROCESSES" -eq "$OPENIM_MSGGATEWAY_NUM" ]; then
+ openim::log::info "Found $OPENIM_MSGGATEWAY_NUM processes named $OPENIM_OUTPUT_HOSTBIN"
+ for PID in $PIDS; do
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ ps -p $PID -o pid,cmd
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ ps -p $PID -o pid,comm
+ else
+ openim::log::error "Unsupported OS type: $OSTYPE"
+ fi
+ done
+ else
+ openim::log::error_exit "Expected $OPENIM_MSGGATEWAY_NUM openim msgtransfer processes, but found $NUM_PROCESSES msgtransfer processes."
+ fi
}
###################################### Linux Systemd ######################################
@@ -96,30 +96,30 @@ EOF
# install openim-msgtransfer
function openim::msgtransfer::install() {
pushd "${OPENIM_ROOT}"
-
+
# 1. Build openim-msgtransfer
make build BINS=${SERVER_NAME}
-
+
openim::common::sudo "cp -r ${OPENIM_OUTPUT_HOSTBIN}/${SERVER_NAME} ${OPENIM_INSTALL_DIR}/${SERVER_NAME}"
openim::log::status "${SERVER_NAME} binary: ${OPENIM_INSTALL_DIR}/${SERVER_NAME}/${SERVER_NAME}"
-
+
openim::log::status "${SERVER_NAME} binary: ${OPENIM_INSTALL_DIR}/bin/${SERVER_NAME}"
-
+
# 2. Generate and install the openim-msgtransfer configuration file (openim-msgtransfer.yaml)
# nono
-
+
# 3. Create and install the ${SERVER_NAME} systemd unit file
echo ${LINUX_PASSWORD} | sudo -S bash -c \
- "SERVER_NAME=${SERVER_NAME} ./scripts/genconfig.sh ${ENV_FILE} deployments/templates/openim.service > ${SYSTEM_FILE_PATH}"
+ "SERVER_NAME=${SERVER_NAME} ./scripts/genconfig.sh ${ENV_FILE} deployments/templates/openim.service > ${SYSTEM_FILE_PATH}"
openim::log::status "${SERVER_NAME} systemd file: ${SYSTEM_FILE_PATH}"
-
+
# 4. Start the openim-msgtransfer service
openim::common::sudo "systemctl daemon-reload"
openim::common::sudo "systemctl restart ${SERVER_NAME}"
openim::common::sudo "systemctl enable ${SERVER_NAME}"
openim::msgtransfer::status || return 1
openim::msgtransfer::info
-
+
openim::log::info "install ${SERVER_NAME} successfully"
popd
}
diff --git a/scripts/install/openim-push.sh b/scripts/install/openim-push.sh
index c17b80e67..d43743e4f 100755
--- a/scripts/install/openim-push.sh
+++ b/scripts/install/openim-push.sh
@@ -14,10 +14,10 @@
# limitations under the License.
#
# OpenIM Push Control Script
-#
+#
# Description:
# This script provides a control interface for the OpenIM Push service within a Linux environment. It supports two installation methods: installation via function calls to systemctl, and direct installation through background processes.
-#
+#
# Features:
# 1. Robust error handling leveraging Bash built-ins such as 'errexit', 'nounset', and 'pipefail'.
# 2. Capability to source common utility functions and configurations, ensuring environmental consistency.
@@ -29,7 +29,7 @@
# 1. Direct Script Execution:
# This will start the OpenIM push directly through a background process.
# Example: ./openim-push.sh
-#
+#
# 2. Controlling through Functions for systemctl operations:
# Specific operations like installation, uninstallation, and status check can be executed by passing the respective function name as an argument to the script.
# Example: ./openim-push.sh openim::push::install
@@ -39,7 +39,7 @@
# export OPENIM_PUSH_PORT="9090 9091 9092"
#
# Note: Ensure that the appropriate permissions and environmental variables are set prior to script execution.
-#
+#
set -o errexit
set +o nounset
set -o pipefail
@@ -50,30 +50,30 @@ OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P)
SERVER_NAME="openim-push"
function openim::push::start() {
- openim::log::status "Start OpenIM Push, binary root: ${SERVER_NAME}"
- openim::log::info "Start OpenIM Push, path: ${OPENIM_PUSH_BINARY}"
-
- openim::log::status "prepare start push process, path: ${OPENIM_PUSH_BINARY}"
- openim::log::status "prepare start push process, port: ${OPENIM_PUSH_PORT}, prometheus port: ${PUSH_PROM_PORT}"
-
- OPENIM_PUSH_PORTS_ARRAY=$(openim::util::list-to-string ${OPENIM_PUSH_PORT} )
- PUSH_PROM_PORTS_ARRAY=$(openim::util::list-to-string ${PUSH_PROM_PORT} )
-
- openim::util::stop_services_with_name ${SERVER_NAME}
-
- openim::log::status "push port list: ${OPENIM_PUSH_PORTS_ARRAY[@]}"
- openim::log::status "prometheus port list: ${PUSH_PROM_PORTS_ARRAY[@]}"
-
- if [ ${#OPENIM_PUSH_PORTS_ARRAY[@]} -ne ${#PUSH_PROM_PORTS_ARRAY[@]} ]; then
- openim::log::error_exit "The length of the two port lists is different!"
- fi
-
- for (( i=0; i<${#OPENIM_PUSH_PORTS_ARRAY[@]}; i++ )); do
- openim::log::info "start push process, port: ${OPENIM_PUSH_PORTS_ARRAY[$i]}, prometheus port: ${PUSH_PROM_PORTS_ARRAY[$i]}"
- nohup ${OPENIM_PUSH_BINARY} --port ${OPENIM_PUSH_PORTS_ARRAY[$i]} -c ${OPENIM_PUSH_CONFIG} --prometheus_port ${PUSH_PROM_PORTS_ARRAY[$i]} >> ${LOG_FILE} 2>&1 &
- done
-
- openim::util::check_process_names ${SERVER_NAME}
+ openim::log::status "Start OpenIM Push, binary root: ${SERVER_NAME}"
+ openim::log::info "Start OpenIM Push, path: ${OPENIM_PUSH_BINARY}"
+
+ openim::log::status "prepare start push process, path: ${OPENIM_PUSH_BINARY}"
+ openim::log::status "prepare start push process, port: ${OPENIM_PUSH_PORT}, prometheus port: ${PUSH_PROM_PORT}"
+
+ OPENIM_PUSH_PORTS_ARRAY=$(openim::util::list-to-string ${OPENIM_PUSH_PORT} )
+ PUSH_PROM_PORTS_ARRAY=$(openim::util::list-to-string ${PUSH_PROM_PORT} )
+
+ openim::util::stop_services_with_name ${SERVER_NAME}
+
+ openim::log::status "push port list: ${OPENIM_PUSH_PORTS_ARRAY[@]}"
+ openim::log::status "prometheus port list: ${PUSH_PROM_PORTS_ARRAY[@]}"
+
+ if [ ${#OPENIM_PUSH_PORTS_ARRAY[@]} -ne ${#PUSH_PROM_PORTS_ARRAY[@]} ]; then
+ openim::log::error_exit "The length of the two port lists is different!"
+ fi
+
+ for (( i=0; i<${#OPENIM_PUSH_PORTS_ARRAY[@]}; i++ )); do
+ openim::log::info "start push process, port: ${OPENIM_PUSH_PORTS_ARRAY[$i]}, prometheus port: ${PUSH_PROM_PORTS_ARRAY[$i]}"
+ nohup ${OPENIM_PUSH_BINARY} --port ${OPENIM_PUSH_PORTS_ARRAY[$i]} -c ${OPENIM_PUSH_CONFIG} --prometheus_port ${PUSH_PROM_PORTS_ARRAY[$i]} >> ${LOG_FILE} 2>&1 &
+ done
+
+ openim::util::check_process_names ${SERVER_NAME}
}
###################################### Linux Systemd ######################################
@@ -89,27 +89,27 @@ EOF
# install openim-push
function openim::push::install() {
pushd "${OPENIM_ROOT}"
-
+
# 1. Build openim-push
make build BINS=${SERVER_NAME}
openim::common::sudo "cp -r ${OPENIM_OUTPUT_HOSTBIN}/${SERVER_NAME} ${OPENIM_INSTALL_DIR}/${SERVER_NAME}"
openim::log::status "${SERVER_NAME} binary: ${OPENIM_INSTALL_DIR}/${SERVER_NAME}/${SERVER_NAME}"
-
+
# 2. Generate and install the openim-push configuration file (config)
openim::log::status "${SERVER_NAME} config file: ${OPENIM_CONFIG_DIR}/config.yaml"
-
+
# 3. Create and install the ${SERVER_NAME} systemd unit file
echo ${LINUX_PASSWORD} | sudo -S bash -c \
- "SERVER_NAME=${SERVER_NAME} ./scripts/genconfig.sh ${ENV_FILE} deployments/templates/openim.service > ${SYSTEM_FILE_PATH}"
+ "SERVER_NAME=${SERVER_NAME} ./scripts/genconfig.sh ${ENV_FILE} deployments/templates/openim.service > ${SYSTEM_FILE_PATH}"
openim::log::status "${SERVER_NAME} systemd file: ${SYSTEM_FILE_PATH}"
-
+
# 4. Start the openim-push service
openim::common::sudo "systemctl daemon-reload"
openim::common::sudo "systemctl restart ${SERVER_NAME}"
openim::common::sudo "systemctl enable ${SERVER_NAME}"
openim::push::status || return 1
openim::push::info
-
+
openim::log::info "install ${SERVER_NAME} successfully"
popd
}
@@ -133,7 +133,7 @@ function openim::push::status() {
openim::log::error "${SERVER_NAME} failed to start, maybe not installed properly"
return 1
}
-
+
# The listening port is hardcode in the configuration file
if echo | telnet ${OPENIM_MSGGATEWAY_HOST} ${OPENIM_PUSH_PORT} 2>&1|grep refused &>/dev/null;then # Assuming a different port for push
openim::log::error "cannot access health check port, ${SERVER_NAME} maybe not startup"
diff --git a/scripts/install/openim-rpc.sh b/scripts/install/openim-rpc.sh
index db1526d6a..966eef928 100755
--- a/scripts/install/openim-rpc.sh
+++ b/scripts/install/openim-rpc.sh
@@ -15,10 +15,10 @@
# limitations under the License.
#
# OpenIM RPC Service Control Script
-#
+#
# Description:
# This script provides a control interface for the OpenIM RPC service within a Linux environment. It offers functionalities to start multiple RPC services, each denoted by their respective names under openim::rpc::service_name.
-#
+#
# Features:
# 1. Robust error handling using Bash built-ins like 'errexit', 'nounset', and 'pipefail'.
# 2. The capability to source common utility functions and configurations to ensure uniform environmental settings.
@@ -125,7 +125,7 @@ function openim::rpc::start() {
openim::util::stop_services_on_ports ${OPENIM_RPC_PORT_LISTARIES[$i]}
openim::log::info "OpenIM ${OPENIM_RPC_SERVICE_LISTARIES[$i]} config path: ${OPENIM_RPC_CONFIG}"
-
+
# Get the service and Prometheus ports.
OPENIM_RPC_SERVICE_PORTS=( $(openim::util::list-to-string ${OPENIM_RPC_PORT_LISTARIES[$i]}) )
read -a OPENIM_RPC_SERVICE_PORTS_ARRAY <<< ${OPENIM_RPC_SERVICE_PORTS}
@@ -139,7 +139,7 @@ function openim::rpc::start() {
done
done
- sleep 1
+ sleep 5
openim::util::check_ports ${OPENIM_RPC_PORT_TARGETS[@]}
# openim::util::check_ports ${OPENIM_RPC_PROM_PORT_TARGETS[@]}
diff --git a/scripts/install/openim-tools.sh b/scripts/install/openim-tools.sh
index 385df64f5..ac60a5f45 100755
--- a/scripts/install/openim-tools.sh
+++ b/scripts/install/openim-tools.sh
@@ -18,9 +18,9 @@
#
# Description:
# This script is responsible for managing the lifecycle of OpenIM tools, which include starting, stopping,
-# and handling pre and post operations. It's designed to be modular and extensible, ensuring that the
+# and handling pre and post operations. It's designed to be modular and extensible, ensuring that the
# individual operations can be managed separately, and integrated seamlessly with Linux systemd.
-#
+#
# Features:
# 1. Robust error handling using Bash built-ins like 'errexit', 'nounset', and 'pipefail'.
# 2. The capability to source common utility functions and configurations to ensure uniform environmental settings.
@@ -104,12 +104,7 @@ function openim::tools::start_service() {
cmd="${cmd} --prometheus_port ${prometheus_port}"
fi
openim::log::status "Starting ${binary_name}..."
- # Later, after discarding Docker, the Docker keyword is unreliable, and Kubepods is used
- if grep -qE 'docker|kubepods' /proc/1/cgroup || [ -f /.dockerenv ]; then
- ${cmd} >> "${LOG_FILE}" 2>&1
- else
- ${cmd} | tee -a "${LOG_FILE}"
- fi
+ ${cmd} | tee -a "${LOG_FILE}"
}
function openim::tools::start() {
diff --git a/scripts/install/test.sh b/scripts/install/test.sh
index 93a39f298..4a78e4504 100755
--- a/scripts/install/test.sh
+++ b/scripts/install/test.sh
@@ -15,19 +15,19 @@
# limitations under the License.
#
# OpenIM RPC Service Test Control Script
-#
+#
# This control script is designed to conduct various tests on the OpenIM RPC services.
# It includes functions to perform smoke tests, API tests, and comprehensive service tests.
# The script is intended to be used in a Linux environment with appropriate permissions and
# environmental variables set.
-#
+#
# It provides robust error handling and logging to facilitate debugging and service monitoring.
# Functions within the script can be called directly or passed as arguments to perform
# systematic testing, ensuring the integrity of the RPC services.
-#
+#
# Test Functions:
# - openim::test::smoke: Runs basic tests to ensure the fundamental functionality of the service.
-# - openim::test::api: Executes a series of API tests covering authentication, user, friend,
+# - openim::test::api: Executes a series of API tests covering authentication, user, friend,
# group, and message functionalities.
# - openim::test::test: Performs a complete test suite, invoking utility checks and all defined
# test cases, and reports on their success.
@@ -40,78 +40,80 @@ IAM_ROOT=$(dirname "${BASH_SOURCE[0]}")/../..
# API Server API Address:Port
INSECURE_OPENIMAPI="http://${OPENIM_API_HOST}:${API_OPENIM_PORT}"
INSECURE_OPENIMAUTO=${OPENIM_RPC_AUTH_HOST}:${OPENIM_AUTH_PORT}
-CCURL="curl -f -s -XPOST" # Create
-UCURL="curl -f -s -XPUT" # Update
-RCURL="curl -f -s -XGET" # Retrieve
+CCURL="curl -f -s -XPOST" # Create
+UCURL="curl -f -s -XPUT" # Update
+RCURL="curl -f -s -XGET" # Retrieve
DCURL="curl -f -s -XDELETE" # Delete
openim::test::check_error() {
- local response=$1
- local err_code=$(echo "$response" | jq '.errCode')
- openim::log::status "Response from user registration: $response"
- if [[ "$err_code" != "0" ]]; then
- openim::log::error_exit "Error occurred: $response, You can read the error code in the API documentation https://docs.openim.io/restapi/errcode"
- else
- openim::log::success "Operation was successful."
- fi
+ local response=$1
+ local err_code=$(echo "$response" | jq '.errCode')
+ openim::log::status "Response from user registration: $response"
+ if [[ "$err_code" != "0" ]]; then
+ openim::log::error_exit "Error occurred: $response, You can read the error code in the API documentation https://docs.openim.io/restapi/errcode"
+ else
+ openim::log::success "Operation was successful."
+ fi
}
# The `openim::test::auth` function serves as a test suite for authentication-related operations.
function openim::test::auth() {
- # 1. Retrieve and set the authentication token.
- openim::test::get_token
-
- # 2. Force logout the test user from a specific platform.
- openim::test::force_logout
-
- # Log the completion of the auth test suite.
- openim::log::success "Auth test suite completed successfully."
+ # 1. Retrieve and set the authentication token.
+ openim::test::get_token
+
+ # 2. Force logout the test user from a specific platform.
+ openim::test::force_logout
+
+ # Log the completion of the auth test suite.
+ openim::log::success "Auth test suite completed successfully."
}
#################################### Auth Module ####################################
# Define a function to get a token for a specific user
openim::test::get_token() {
- local user_id="${1:-openIM123456}" # Default user ID if not provided
- token_response=$(${CCURL} "${OperationID}" "${Header}" ${INSECURE_OPENIMAPI}/auth/user_token \
- -d'{"secret": "'"$SECRET"'","platformID": 1,"userID": "'$user_id'"}')
- token=$(echo $token_response | grep -Po 'token[" :]+\K[^"]+')
- echo "$token"
+ local user_id="${1:-openIM123456}" # Default user ID if not provided
+ token_response=$(
+ ${CCURL} "${OperationID}" "${Header}" ${INSECURE_OPENIMAPI}/auth/user_token \
+ -d'{"secret": "'"$SECRET"'","platformID": 1,"userID": "'$user_id'"}'
+ )
+ token=$(echo $token_response | grep -Po 'token[" :]+\K[^"]+')
+ echo "$token"
}
-
Header="-HContent-Type: application/json"
OperationID="-HoperationID: 1646445464564"
Token="-Htoken: $(openim::test::get_token)"
# Forces a user to log out from the specified platform by user ID.
openim::test::force_logout() {
- local request_body=$(cat < /dev/null && ss -Version | grep 'iproute2' &> /dev/null; then
port_check_command="ss"
- elif command -v netstat &>/dev/null; then
+ elif command -v netstat &>/dev/null; then
port_check_command="netstat"
else
openim::log::usage "unable to identify if chat is bound to port ${CHAT_PORT}. unable to find ss or netstat utilities."
@@ -46,24 +46,24 @@ openim::chat::validate() {
openim::log::usage "$(${port_check_command} -nat | grep "LISTEN" | grep "[\.:]${CHAT_PORT:?}")"
exit 1
fi
-
+
# need set the env of "CHAT_UNSUPPORTED_ARCH" on unstable arch.
arch=$(uname -m)
if [[ $arch =~ arm* ]]; then
- export CHAT_UNSUPPORTED_ARCH=arm
+ export CHAT_UNSUPPORTED_ARCH=arm
fi
# validate installed version is at least equal to minimum
version=$(chat --version | grep Version | head -n 1 | cut -d " " -f 3)
if [[ $(openim::chat::version "${CHAT_VERSION}") -gt $(openim::chat::version "${version}") ]]; then
- export PATH="${OPENIM_ROOT}"/third_party/chat:${PATH}
- hash chat
- echo "${PATH}"
- version=$(chat --version | grep Version | head -n 1 | cut -d " " -f 3)
- if [[ $(openim::chat::version "${CHAT_VERSION}") -gt $(openim::chat::version "${version}") ]]; then
- openim::log::usage "chat version ${CHAT_VERSION} or greater required."
- openim::log::info "You can use 'scripts/install-chat.sh' to install a copy in third_party/."
- exit 1
- fi
+ export PATH="${OPENIM_ROOT}"/third_party/chat:${PATH}
+ hash chat
+ echo "${PATH}"
+ version=$(chat --version | grep Version | head -n 1 | cut -d " " -f 3)
+ if [[ $(openim::chat::version "${CHAT_VERSION}") -gt $(openim::chat::version "${version}") ]]; then
+ openim::log::usage "chat version ${CHAT_VERSION} or greater required."
+ openim::log::info "You can use 'scripts/install-chat.sh' to install a copy in third_party/."
+ exit 1
+ fi
fi
}
@@ -74,7 +74,7 @@ openim::chat::version() {
openim::chat::start() {
# validate before running
openim::chat::validate
-
+
# Start chat
CHAT_DIR=${CHAT_DIR:-$(mktemp -d 2>/dev/null || mktemp -d -t test-chat.XXXXXX)}
if [[ -d "${ARTIFACTS:-}" ]]; then
@@ -85,7 +85,7 @@ openim::chat::start() {
openim::log::info "chat --advertise-client-urls ${OPENIM_INTEGRATION_CHAT_URL} --data-dir ${CHAT_DIR} --listen-client-urls http://${CHAT_HOST}:${CHAT_PORT} --log-level=${CHAT_LOGLEVEL} 2> \"${CHAT_LOGFILE}\" >/dev/null"
chat --advertise-client-urls "${OPENIM_INTEGRATION_CHAT_URL}" --data-dir "${CHAT_DIR}" --listen-client-urls "${OPENIM_INTEGRATION_CHAT_URL}" --log-level="${CHAT_LOGLEVEL}" 2> "${CHAT_LOGFILE}" >/dev/null &
CHAT_PID=$!
-
+
echo "Waiting for chat to come up."
openim::util::wait_for_url "${OPENIM_INTEGRATION_CHAT_URL}/health" "chat: " 0.25 80
curl -fs -X POST "${OPENIM_INTEGRATION_CHAT_URL}/v3/kv/put" -d '{"key": "X3Rlc3Q=", "value": ""}'
@@ -108,7 +108,7 @@ openim::chat::start_scraping() {
}
openim::chat::scrape() {
- curl -s -S "${OPENIM_INTEGRATION_CHAT_URL}/metrics" > "${CHAT_SCRAPE_DIR}/next" && mv "${CHAT_SCRAPE_DIR}/next" "${CHAT_SCRAPE_DIR}/$(date +%s).scrape"
+ curl -s -S "${OPENIM_INTEGRATION_CHAT_URL}/metrics" > "${CHAT_SCRAPE_DIR}/next" && mv "${CHAT_SCRAPE_DIR}/next" "${CHAT_SCRAPE_DIR}/$(date +%s).scrape"
}
openim::chat::stop() {
@@ -144,17 +144,17 @@ openim::chat::install() {
(
local os
local arch
-
+
os=$(openim::util::host_os)
arch=$(openim::util::host_arch)
-
+
cd "${OPENIM_ROOT}/third_party" || return 1
if [[ $(readlink chat) == chat-v${CHAT_VERSION}-${os}-* ]]; then
openim::log::info "chat v${CHAT_VERSION} already installed. To use:"
openim::log::info "export PATH=\"$(pwd)/chat:\${PATH}\""
return #already installed
fi
-
+
if [[ ${os} == "darwin" ]]; then
download_file="chat-v${CHAT_VERSION}-${os}-${arch}.zip"
url="https://github.com/chat-io/chat/releases/download/v${CHAT_VERSION}/${download_file}"
@@ -162,7 +162,7 @@ openim::chat::install() {
unzip -o "${download_file}"
ln -fns "chat-v${CHAT_VERSION}-${os}-${arch}" chat
rm "${download_file}"
- elif [[ ${os} == "linux" ]]; then
+ elif [[ ${os} == "linux" ]]; then
url="https://github.com/coreos/chat/releases/download/v${CHAT_VERSION}/chat-v${CHAT_VERSION}-${os}-${arch}.tar.gz"
download_file="chat-v${CHAT_VERSION}-${os}-${arch}.tar.gz"
openim::util::download_file "${url}" "${download_file}"
diff --git a/scripts/lib/color.sh b/scripts/lib/color.sh
index 4d69c1771..744fccf5a 100755
--- a/scripts/lib/color.sh
+++ b/scripts/lib/color.sh
@@ -21,24 +21,24 @@
# shellcheck disable=SC2034
if [ -z "${COLOR_OPEN+x}" ]; then
- COLOR_OPEN=1
+ COLOR_OPEN=1
fi
# Function for colored echo
openim::color::echo() {
- COLOR=$1
- [ $COLOR_OPEN -eq 1 ] && echo -e "${COLOR} $(date '+%Y-%m-%d %H:%M:%S') $@ ${COLOR_SUFFIX}"
- shift
+ COLOR=$1
+ [ $COLOR_OPEN -eq 1 ] && echo -e "${COLOR} $(date '+%Y-%m-%d %H:%M:%S') $@ ${COLOR_SUFFIX}"
+ shift
}
# Define color variables
-# --- Feature ---
+# --- Feature ---
COLOR_NORMAL='\033[0m';COLOR_BOLD='\033[1m';COLOR_DIM='\033[2m';COLOR_UNDER='\033[4m';
COLOR_ITALIC='\033[3m';COLOR_NOITALIC='\033[23m';COLOR_BLINK='\033[5m';
COLOR_REVERSE='\033[7m';COLOR_CONCEAL='\033[8m';COLOR_NOBOLD='\033[22m';
COLOR_NOUNDER='\033[24m';COLOR_NOBLINK='\033[25m';
-# --- Front color ---
+# --- Front color ---
COLOR_BLACK='\033[30m';
COLOR_RED='\033[31m';
COLOR_GREEN='\033[32m';
@@ -48,13 +48,13 @@ COLOR_MAGENTA='\033[35m';
COLOR_CYAN='\033[36m';
COLOR_WHITE='\033[37m';
-# --- background color ---
+# --- background color ---
COLOR_BBLACK='\033[40m';COLOR_BRED='\033[41m';
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 definitions ---
# Color definitions
COLOR_SUFFIX="\033[0m" # End all colors and special effects
BLACK_PREFIX="\033[30m" # Black prefix
@@ -86,54 +86,54 @@ openim::color::print_color() {
# test functions
openim::color::test() {
- echo "Starting the color tests..."
-
- echo "Testing normal echo without color"
- openim::color::echo $COLOR_NORMAL "This is a normal text"
-
- echo "Testing bold echo"
- openim::color::echo $COLOR_BOLD "This is bold text"
-
- echo "Testing dim echo"
- openim::color::echo $COLOR_DIM "This is dim text"
-
- echo "Testing underlined echo"
- openim::color::echo $COLOR_UNDER "This is underlined text"
-
- echo "Testing italic echo"
- openim::color::echo $COLOR_ITALIC "This is italic text"
-
- echo "Testing red color"
- openim::color::echo $COLOR_RED "This is red text"
-
- echo "Testing green color"
- openim::color::echo $COLOR_GREEN "This is green text"
-
- echo "Testing yellow color"
- openim::color::echo $COLOR_YELLOW "This is yellow text"
-
- echo "Testing blue color"
- openim::color::echo $COLOR_BLUE "This is blue text"
-
- echo "Testing magenta color"
- openim::color::echo $COLOR_MAGENTA "This is magenta text"
-
- echo "Testing cyan color"
- openim::color::echo $COLOR_CYAN "This is cyan text"
-
- echo "Testing black background"
- openim::color::echo $COLOR_BBLACK "This is text with black background"
-
- echo "Testing red background"
- openim::color::echo $COLOR_BRED "This is text with red background"
-
- echo "Testing green background"
- openim::color::echo $COLOR_BGREEN "This is text with green background"
-
- echo "Testing blue background"
- openim::color::echo $COLOR_BBLUE "This is text with blue background"
-
- echo "All tests completed!"
+ echo "Starting the color tests..."
+
+ echo "Testing normal echo without color"
+ openim::color::echo $COLOR_NORMAL "This is a normal text"
+
+ echo "Testing bold echo"
+ openim::color::echo $COLOR_BOLD "This is bold text"
+
+ echo "Testing dim echo"
+ openim::color::echo $COLOR_DIM "This is dim text"
+
+ echo "Testing underlined echo"
+ openim::color::echo $COLOR_UNDER "This is underlined text"
+
+ echo "Testing italic echo"
+ openim::color::echo $COLOR_ITALIC "This is italic text"
+
+ echo "Testing red color"
+ openim::color::echo $COLOR_RED "This is red text"
+
+ echo "Testing green color"
+ openim::color::echo $COLOR_GREEN "This is green text"
+
+ echo "Testing yellow color"
+ openim::color::echo $COLOR_YELLOW "This is yellow text"
+
+ echo "Testing blue color"
+ openim::color::echo $COLOR_BLUE "This is blue text"
+
+ echo "Testing magenta color"
+ openim::color::echo $COLOR_MAGENTA "This is magenta text"
+
+ echo "Testing cyan color"
+ openim::color::echo $COLOR_CYAN "This is cyan text"
+
+ echo "Testing black background"
+ openim::color::echo $COLOR_BBLACK "This is text with black background"
+
+ echo "Testing red background"
+ openim::color::echo $COLOR_BRED "This is text with red background"
+
+ echo "Testing green background"
+ openim::color::echo $COLOR_BGREEN "This is text with green background"
+
+ echo "Testing blue background"
+ openim::color::echo $COLOR_BBLUE "This is text with blue background"
+
+ echo "All tests completed!"
}
# openim::color::test
diff --git a/scripts/lib/logging.sh b/scripts/lib/logging.sh
index 8e7d5b09a..eb83c526d 100755
--- a/scripts/lib/logging.sh
+++ b/scripts/lib/logging.sh
@@ -21,24 +21,24 @@ ENABLE_LOGGING="${ENABLE_LOGGING:-true}"
# If OPENIM_OUTPUT is not set, set it to the default value
if [ -z "${OPENIM_OUTPUT+x}" ]; then
- OPENIM_OUTPUT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../_output" && pwd -P)"
+ OPENIM_OUTPUT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../_output" && pwd -P)"
fi
# Set the log file path
LOG_FILE="${OPENIM_OUTPUT}/logs/openim_$(date '+%Y%m%d').log"
if [[ ! -d "${OPENIM_OUTPUT}/logs" ]]; then
- mkdir -p "${OPENIM_OUTPUT}/logs"
- touch "$LOG_FILE"
+ mkdir -p "${OPENIM_OUTPUT}/logs"
+ touch "$LOG_FILE"
fi
# Define the logging function
function echo_log() {
- if $ENABLE_LOGGING; then
- echo -e "$@" | tee -a "${LOG_FILE}"
- else
- echo -e "$@"
- fi
+ if $ENABLE_LOGGING; then
+ echo -e "$@" | tee -a "${LOG_FILE}"
+ else
+ echo -e "$@"
+ fi
}
# MAX_LOG_SIZE=10485760 # 10MB
@@ -50,11 +50,11 @@ function echo_log() {
# Borrowed from https://gist.github.com/ahendrix/7030300
openim::log::errexit() {
local err="${PIPESTATUS[*]}"
-
+
# If the shell we are in doesn't have errexit set (common in subshells) then
# don't dump stacks.
set +o | grep -qe "-o errexit" || return
-
+
set +o xtrace
local code="${1:-1}"
# Print out the stack trace described by $function_stack
@@ -73,7 +73,7 @@ openim::log::install_errexit() {
# trap ERR to provide an error handler whenever a command exits nonzero this
# is a more verbose version of set -o errexit
trap 'openim::log::errexit' ERR
-
+
# setting errtrace allows our ERR trap handler to be propagated to functions,
# expansions and subshells
set -o errtrace
@@ -110,7 +110,7 @@ openim::log::error_exit() {
local code="${2:-1}"
local stack_skip="${3:-0}"
stack_skip=$((stack_skip + 1))
-
+
if [[ ${OPENIM_VERBOSE} -ge 4 ]]; then
local source_file=${BASH_SOURCE[${stack_skip}]}
local source_line=${BASH_LINENO[$((stack_skip - 1))]}
@@ -118,12 +118,12 @@ openim::log::error_exit() {
[[ -z ${1-} ]] || {
echo_log " ${1}" >&2
}
-
+
openim::log::stack ${stack_skip}
-
+
echo_log "Exiting with status ${code}" >&2
fi
-
+
exit "${code}"
}
@@ -152,7 +152,7 @@ openim::log::usage_from_stdin() {
while read -r line; do
messages+=("${line}")
done
-
+
openim::log::usage "${messages[@]}"
}
@@ -162,7 +162,7 @@ openim::log::info() {
if [[ ${OPENIM_VERBOSE} < ${V} ]]; then
return
fi
-
+
for message; do
echo_log "${message}"
done
@@ -181,7 +181,7 @@ openim::log::info_from_stdin() {
while read -r line; do
messages+=("${line}")
done
-
+
openim::log::info "${messages[@]}"
}
@@ -191,7 +191,7 @@ openim::log::status() {
if [[ ${OPENIM_VERBOSE} < ${V} ]]; then
return
fi
-
+
timestamp=$(date +"[%m%d %H:%M:%S]")
echo_log "+++ ${timestamp} ${1}"
shift
@@ -203,20 +203,20 @@ openim::log::status() {
openim::log::success() {
local V="${V:-0}"
if [[ ${OPENIM_VERBOSE} < ${V} ]]; then
- return
+ return
fi
timestamp=$(date +"%m%d %H:%M:%S")
echo_log -e "${COLOR_GREEN}[success ${timestamp}] ${COLOR_SUFFIX}==> " "$@"
}
function openim::log::test_log() {
- echo_log "test log"
- openim::log::info "openim::log::info"
- openim::log::progress "openim::log::progress"
- openim::log::status "openim::log::status"
- openim::log::success "openim::log::success"
- openim::log::error "openim::log::error"
- openim::log::error_exit "openim::log::error_exit"
+ echo_log "test log"
+ openim::log::info "openim::log::info"
+ openim::log::progress "openim::log::progress"
+ openim::log::status "openim::log::status"
+ openim::log::success "openim::log::success"
+ openim::log::error "openim::log::error"
+ openim::log::error_exit "openim::log::error_exit"
}
# openim::log::test_log
\ No newline at end of file
diff --git a/scripts/lib/release.sh b/scripts/lib/release.sh
index 16f2cd97a..2a525f12c 100755
--- a/scripts/lib/release.sh
+++ b/scripts/lib/release.sh
@@ -46,11 +46,11 @@ OPENIM_BUILD_CONFORMANCE=${OPENIM_BUILD_CONFORMANCE:-y}
OPENIM_BUILD_PULL_LATEST_IMAGES=${OPENIM_BUILD_PULL_LATEST_IMAGES:-y}
if [ -z "${OPENIM_ROOT}" ]; then
- OPENIM_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)"
+ OPENIM_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)"
fi
if [ -z "${TOOLS_DIR}" ]; then
- TOOLS_DIR="${OPENIM_ROOT}/_output/tools"
+ TOOLS_DIR="${OPENIM_ROOT}/_output/tools"
fi
# Validate a ci version
@@ -77,10 +77,10 @@ function openim::release::parse_and_validate_ci_version() {
openim::log::error "Invalid ci version: '${version}', must match regex ${version_regex}"
return 1
}
-
+
# The VERSION variables are used when this file is sourced, hence
# the shellcheck SC2034 'appears unused' warning is to be ignored.
-
+
# shellcheck disable=SC2034
VERSION_MAJOR="${BASH_REMATCH[1]}"
# shellcheck disable=SC2034
@@ -115,7 +115,7 @@ function openim::release::package_tarballs() {
openim::release::package_openim_manifests_tarball &
openim::release::package_server_tarballs &
openim::util::wait-for-jobs || { openim::log::error "previous tarball phase failed"; return 1; }
-
+
openim::release::package_final_tarball & # _final depends on some of the previous phases
openim::util::wait-for-jobs || { openim::log::error "previous tarball phase failed"; return 1; }
}
@@ -143,24 +143,24 @@ function openim::release::package_src_tarball() {
git archive -o "${src_tarball}" HEAD
else
find "${OPENIM_ROOT}" -mindepth 1 -maxdepth 1 \
- ! \( \
- \( -path "${OPENIM_ROOT}"/_\* -o \
- -path "${OPENIM_ROOT}"/.git\* -o \
- -path "${OPENIM_ROOT}"/.github\* -o \
- -path "${OPENIM_ROOT}"/components\* -o \
- -path "${OPENIM_ROOT}"/logs\* -o \
- -path "${OPENIM_ROOT}"/.gitignore\* -o \
- -path "${OPENIM_ROOT}"/.gsemver.yml\* -o \
- -path "${OPENIM_ROOT}"/.config\* -o \
- -path "${OPENIM_ROOT}"/.chglog\* -o \
- -path "${OPENIM_ROOT}"/.gitlint -o \
- -path "${OPENIM_ROOT}"/.golangci.yml -o \
- -path "${OPENIM_ROOT}"/build/goreleaser.yaml -o \
- -path "${OPENIM_ROOT}"/.note.md -o \
- -path "${OPENIM_ROOT}"/.todo.md \
- \) -prune \
- \) -print0 \
- | "${TAR}" czf "${src_tarball}" --transform "s|${OPENIM_ROOT#/*}|openim|" --null -T -
+ ! \( \
+ \( -path "${OPENIM_ROOT}"/_\* -o \
+ -path "${OPENIM_ROOT}"/.git\* -o \
+ -path "${OPENIM_ROOT}"/.github\* -o \
+ -path "${OPENIM_ROOT}"/components\* -o \
+ -path "${OPENIM_ROOT}"/logs\* -o \
+ -path "${OPENIM_ROOT}"/.gitignore\* -o \
+ -path "${OPENIM_ROOT}"/.gsemver.yml\* -o \
+ -path "${OPENIM_ROOT}"/.config\* -o \
+ -path "${OPENIM_ROOT}"/.chglog\* -o \
+ -path "${OPENIM_ROOT}"/.gitlint -o \
+ -path "${OPENIM_ROOT}"/.golangci.yml -o \
+ -path "${OPENIM_ROOT}"/build/goreleaser.yaml -o \
+ -path "${OPENIM_ROOT}"/.note.md -o \
+ -path "${OPENIM_ROOT}"/.todo.md \
+ \) -prune \
+ \) -print0 \
+ | "${TAR}" czf "${src_tarball}" --transform "s|${OPENIM_ROOT#/*}|openim|" --null -T -
fi
}
@@ -168,7 +168,7 @@ function openim::release::package_src_tarball() {
function openim::release::package_server_tarballs() {
# Find all of the built client binaries
local long_platforms=("${LOCAL_OUTPUT_BINPATH}"/*/*)
-
+
if [[ -n ${OPENIM_BUILD_PLATFORMS-} ]]; then
read -ra long_platforms <<< "${OPENIM_BUILD_PLATFORMS}"
fi
@@ -636,7 +636,7 @@ function openim::release::github_release() {
for file in ${RELEASE_TARS}/*.tar.gz; do
if [[ -f "$file" ]]; then
filename=$(basename "$file")
- openim::log::info "Update file ${filename} to release vertion ${OPENIM_GIT_VERSION}"
+ openim::log::info "Update file ${filename} to release vertion ${OPENIM_GIT_VERSION}"
${TOOLS_DIR}/github-release upload \
--user ${OPENIM_GITHUB_ORG} \
--repo ${OPENIM_GITHUB_REPO} \
diff --git a/scripts/lib/util.sh b/scripts/lib/util.sh
index f15a26346..a40668d70 100755
--- a/scripts/lib/util.sh
+++ b/scripts/lib/util.sh
@@ -30,27 +30,27 @@ function openim:util::setup_ssh_key_copy() {
local hosts_file="$1"
local username="${2:-root}"
local password="${3:-123}"
-
+
local sshkey_file=~/.ssh/id_rsa.pub
-
- # check sshkey file
+
+ # check sshkey file
if [[ ! -e $sshkey_file ]]; then
expect -c "
spawn ssh-keygen -t rsa
expect \"Enter*\" { send \"\n\"; exp_continue; }
"
fi
-
+
# get hosts list
local hosts=$(awk '/^[^#]/ {print $1}' "${hosts_file}")
-
+
ssh_key_copy() {
local target=$1
-
+
# delete history
sed -i "/$target/d" ~/.ssh/known_hosts
-
- # copy key
+
+ # copy key
expect -c "
set timeout 100
spawn ssh-copy-id $username@$target
@@ -62,14 +62,14 @@ function openim:util::setup_ssh_key_copy() {
expect eof
"
}
-
+
# auto sshkey pair
for host in $hosts; do
if ! ping -i 0.2 -c 3 -W 1 "$host" > /dev/null 2>&1; then
echo "[ERROR]: Can't connect $host"
continue
fi
-
+
local host_entry=$(awk "/$host/"'{print $1, $2}' /etc/hosts)
if [[ $host_entry ]]; then
local hostaddr=$(echo "$host_entry" | awk '{print $1}')
@@ -102,7 +102,7 @@ openim::util::array_contains() {
for element; do
if [[ "${element}" == "${search}" ]]; then
return 0
- fi
+ fi
done
return 1
}
@@ -113,12 +113,12 @@ openim::util::wait_for_url() {
local wait=${3:-1}
local times=${4:-30}
local maxtime=${5:-1}
-
+
command -v curl >/dev/null || {
openim::log::usage "curl must be installed"
exit 1
}
-
+
local i
for i in $(seq 1 "${times}"); do
local out
@@ -156,20 +156,20 @@ openim::util::trap_add() {
local trap_add_cmd
trap_add_cmd=$1
shift
-
+
for trap_add_name in "$@"; do
local existing_cmd
local new_cmd
-
+
# Grab the currently defined trap commands for this trap
existing_cmd=$(trap -p "${trap_add_name}" | awk -F"'" '{print $2}')
-
+
if [[ -z "${existing_cmd}" ]]; then
new_cmd="${trap_add_cmd}"
else
new_cmd="${trap_add_cmd};${existing_cmd}"
fi
-
+
# Assign the test. Disable the shellcheck warning telling that trap
# commands should be single quoted to avoid evaluating them at this
# point instead evaluating them at run time. The logic of adding new
@@ -200,14 +200,14 @@ openim::util::host_os() {
case "$(uname -s)" in
Darwin)
host_os=darwin
- ;;
+ ;;
Linux)
host_os=linux
- ;;
+ ;;
*)
openim::log::error "Unsupported host OS. Must be Linux or Mac OS X."
exit 1
- ;;
+ ;;
esac
echo "${host_os}"
}
@@ -217,70 +217,70 @@ openim::util::host_arch() {
case "$(uname -m)" in
x86_64*)
host_arch=amd64
- ;;
+ ;;
i?86_64*)
host_arch=amd64
- ;;
+ ;;
amd64*)
host_arch=amd64
- ;;
+ ;;
aarch64*)
host_arch=arm64
- ;;
+ ;;
arm64*)
host_arch=arm64
- ;;
+ ;;
arm*)
host_arch=arm
- ;;
+ ;;
i?86*)
host_arch=x86
- ;;
+ ;;
s390x*)
host_arch=s390x
- ;;
+ ;;
ppc64le*)
host_arch=ppc64le
- ;;
+ ;;
*)
openim::log::error "Unsupported host arch. Must be x86_64, 386, arm, arm64, s390x or ppc64le."
exit 1
- ;;
+ ;;
esac
echo "${host_arch}"
}
# Define a bash function to check the versions of Docker and Docker Compose
openim::util::check_docker_and_compose_versions() {
- # Define the required versions of Docker and Docker Compose
- required_docker_version="20.10.0"
- required_compose_version="2.0"
-
- # Get the currently installed Docker version
- installed_docker_version=$(docker --version | awk '{print $3}' | sed 's/,//')
-
- # Check if the installed Docker version matches the required version
- if [[ "$installed_docker_version" < "$required_docker_version" ]]; then
- echo "Docker version mismatch. Installed: $installed_docker_version, Required: $required_docker_version"
- return 1
- fi
-
- # Check if the docker compose sub-command is available
- if ! docker compose version &> /dev/null; then
- echo "Docker does not support the docker compose sub-command"
- echo "You need to upgrade Docker to the right version"
- return 1
- fi
-
- # Get the currently installed Docker Compose version
- installed_compose_version=$(docker compose version --short)
-
- # Check if the installed Docker Compose version matches the required version
- if [[ "$installed_compose_version" < "$required_compose_version" ]]; then
- echo "Docker Compose version mismatch. Installed: $installed_compose_version, Required: $required_compose_version"
- return 1
- fi
-
+ # Define the required versions of Docker and Docker Compose
+ required_docker_version="20.10.0"
+ required_compose_version="2.0"
+
+ # Get the currently installed Docker version
+ installed_docker_version=$(docker --version | awk '{print $3}' | sed 's/,//')
+
+ # Check if the installed Docker version matches the required version
+ if [[ "$installed_docker_version" < "$required_docker_version" ]]; then
+ echo "Docker version mismatch. Installed: $installed_docker_version, Required: $required_docker_version"
+ return 1
+ fi
+
+ # Check if the docker compose sub-command is available
+ if ! docker compose version &> /dev/null; then
+ echo "Docker does not support the docker compose sub-command"
+ echo "You need to upgrade Docker to the right version"
+ return 1
+ fi
+
+ # Get the currently installed Docker Compose version
+ installed_compose_version=$(docker compose version --short)
+
+ # Check if the installed Docker Compose version matches the required version
+ if [[ "$installed_compose_version" < "$required_compose_version" ]]; then
+ echo "Docker Compose version mismatch. Installed: $installed_compose_version, Required: $required_compose_version"
+ return 1
+ fi
+
}
@@ -292,80 +292,80 @@ openim::util::check_docker_and_compose_versions() {
# openim::util::check_ports 8080 8081 8082
# The function returns a status of 1 if any of the processes is not running.
openim::util::check_ports() {
- # An array to collect ports of processes that are not running.
- local not_started=()
-
- # An array to collect information about processes that are running.
- local started=()
-
- openim::log::info "Checking ports: $*"
- # Iterate over each given port.
- for port in "$@"; do
- # Initialize variables
- # Check the OS and use the appropriate command
- if [[ "$OSTYPE" == "linux-gnu"* ]]; then
- if command -v ss > /dev/null 2>&1; then
- info=$(ss -ltnp | grep ":$port" || true)
- else
- info=$(netstat -ltnp | grep ":$port" || true)
- fi
- elif [[ "$OSTYPE" == "darwin"* ]]; then
- # For macOS, use lsof
- info=$(lsof -P -i:"$port" | grep "LISTEN" || true)
- fi
-
- # Check if any process is using the port
- if [[ -z $info ]]; then
- not_started+=($port)
- else
- if [[ "$OSTYPE" == "linux-gnu"* ]]; then
- # Extract relevant details for Linux: Process Name, PID, and FD.
- details=$(echo $info | sed -n 's/.*users:(("\([^"]*\)",pid=\([^,]*\),fd=\([^)]*\))).*/\1 \2 \3/p')
- command=$(echo $details | awk '{print $1}')
- pid=$(echo $details | awk '{print $2}')
- fd=$(echo $details | awk '{print $3}')
- elif [[ "$OSTYPE" == "darwin"* ]]; then
- # Handle extraction for macOS
- pid=$(echo $info | awk '{print $2}' | cut -d'/' -f1)
- command=$(ps -p $pid -o comm= | xargs basename)
- fd=$(echo $info | awk '{print $4}' | cut -d'/' -f1)
- fi
-
- # Get the start time of the process using the PID
- if [[ -z $pid ]]; then
- start_time="N/A"
- else
- start_time=$(ps -p $pid -o lstart=)
- fi
-
- started+=("Port $port - Command: $command, PID: $pid, FD: $fd, Started: $start_time")
- fi
- done
-
- # Print information about ports whose processes are not running.
- if [[ ${#not_started[@]} -ne 0 ]]; then
- openim::log::info "\n### Not started ports:"
- for port in "${not_started[@]}"; do
- openim::log::error "Port $port is not started."
- done
+ # An array to collect ports of processes that are not running.
+ local not_started=()
+
+ # An array to collect information about processes that are running.
+ local started=()
+
+ openim::log::info "Checking ports: $*"
+ # Iterate over each given port.
+ for port in "$@"; do
+ # Initialize variables
+ # Check the OS and use the appropriate command
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ if command -v ss > /dev/null 2>&1; then
+ info=$(ss -ltnp | grep ":$port" || true)
+ else
+ info=$(netstat -ltnp | grep ":$port" || true)
+ fi
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # For macOS, use lsof
+ info=$(lsof -P -i:"$port" | grep "LISTEN" || true)
fi
-
- # Print information about ports whose processes are running.
- if [[ ${#started[@]} -ne 0 ]]; then
- openim::log::info "\n### Started ports:"
- for info in "${started[@]}"; do
- openim::log::info "$info"
- done
- fi
-
- # If any of the processes is not running, return a status of 1.
- if [[ ${#not_started[@]} -ne 0 ]]; then
- echo "++++ OpenIM Log >> cat ${LOG_FILE}"
- return 1
+
+ # Check if any process is using the port
+ if [[ -z $info ]]; then
+ not_started+=($port)
else
- openim::log::success "All specified processes are running."
- return 0
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ # Extract relevant details for Linux: Process Name, PID, and FD.
+ details=$(echo $info | sed -n 's/.*users:(("\([^"]*\)",pid=\([^,]*\),fd=\([^)]*\))).*/\1 \2 \3/p')
+ command=$(echo $details | awk '{print $1}')
+ pid=$(echo $details | awk '{print $2}')
+ fd=$(echo $details | awk '{print $3}')
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # Handle extraction for macOS
+ pid=$(echo $info | awk '{print $2}' | cut -d'/' -f1)
+ command=$(ps -p $pid -o comm= | xargs basename)
+ fd=$(echo $info | awk '{print $4}' | cut -d'/' -f1)
+ fi
+
+ # Get the start time of the process using the PID
+ if [[ -z $pid ]]; then
+ start_time="N/A"
+ else
+ start_time=$(ps -p $pid -o lstart=)
+ fi
+
+ started+=("Port $port - Command: $command, PID: $pid, FD: $fd, Started: $start_time")
fi
+ done
+
+ # Print information about ports whose processes are not running.
+ if [[ ${#not_started[@]} -ne 0 ]]; then
+ openim::log::info "\n### Not started ports:"
+ for port in "${not_started[@]}"; do
+ openim::log::error "Port $port is not started."
+ done
+ fi
+
+ # Print information about ports whose processes are running.
+ if [[ ${#started[@]} -ne 0 ]]; then
+ openim::log::info "\n### Started ports:"
+ for info in "${started[@]}"; do
+ openim::log::info "$info"
+ done
+ fi
+
+ # If any of the processes is not running, return a status of 1.
+ if [[ ${#not_started[@]} -ne 0 ]]; then
+ echo "++++ OpenIM Log >> cat ${LOG_FILE}"
+ return 1
+ else
+ openim::log::success "All specified processes are running."
+ return 0
+ fi
}
# set +o errexit
@@ -381,75 +381,75 @@ openim::util::check_ports() {
# openim::util::check_process_names nginx mysql redis
# The function returns a status of 1 if any of the processes is not running.
openim::util::check_process_names() {
- # Function to get the port of a process
- get_port() {
- local pid=$1
- if [[ "$OSTYPE" == "linux-gnu"* ]]; then
- # Linux
- ss -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | cut -d ':' -f2
- elif [[ "$OSTYPE" == "darwin"* ]]; then
- # macOS
- lsof -nP -iTCP -sTCP:LISTEN -a -p $pid | awk 'NR>1 {print $9}' | sed 's/.*://'
- else
- echo "Unsupported OS"
- return 1
- fi
- }
-
- # Arrays to collect details of processes
- local not_started=()
- local started=()
-
- openim::log::info "Checking processes: $*"
- # Iterate over each given process name
- for process_name in "$@"; do
- # Use `pgrep` to find process IDs related to the given process name
- local pids=($(pgrep -f $process_name))
-
- # Check if any process IDs were found
- if [[ ${#pids[@]} -eq 0 ]]; then
- not_started+=($process_name)
- else
- # If there are PIDs, loop through each one
- for pid in "${pids[@]}"; do
- local command=$(ps -p $pid -o cmd=)
- local start_time=$(ps -p $pid -o lstart=)
- local port=$(get_port $pid)
-
- # Check if port information was found for the PID
- if [[ -z $port ]]; then
- port="N/A"
- fi
-
- started+=("Process $process_name - Command: $command, PID: $pid, Port: $port, Start time: $start_time")
- done
- fi
- done
-
- # Print information
- if [[ ${#not_started[@]} -ne 0 ]]; then
- openim::log::info "Not started processes:"
- for process_name in "${not_started[@]}"; do
- openim::log::error "Process $process_name is not started."
- done
- fi
-
- if [[ ${#started[@]} -ne 0 ]]; then
- echo
- openim::log::info "Started processes:"
- for info in "${started[@]}"; do
- openim::log::info "$info"
- done
+ # Function to get the port of a process
+ get_port() {
+ local pid=$1
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ # Linux
+ ss -ltnp 2>/dev/null | grep $pid | awk '{print $4}' | cut -d ':' -f2
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # macOS
+ lsof -nP -iTCP -sTCP:LISTEN -a -p $pid | awk 'NR>1 {print $9}' | sed 's/.*://'
+ else
+ echo "Unsupported OS"
+ return 1
fi
-
- # Return status
- if [[ ${#not_started[@]} -ne 0 ]]; then
- echo "++++ OpenIM Log >> cat ${LOG_FILE}"
- return 1
+ }
+
+ # Arrays to collect details of processes
+ local not_started=()
+ local started=()
+
+ openim::log::info "Checking processes: $*"
+ # Iterate over each given process name
+ for process_name in "$@"; do
+ # Use `pgrep` to find process IDs related to the given process name
+ local pids=($(pgrep -f $process_name))
+
+ # Check if any process IDs were found
+ if [[ ${#pids[@]} -eq 0 ]]; then
+ not_started+=($process_name)
else
- openim::log::success "All processes are running."
- return 0
+ # If there are PIDs, loop through each one
+ for pid in "${pids[@]}"; do
+ local command=$(ps -p $pid -o cmd=)
+ local start_time=$(ps -p $pid -o lstart=)
+ local port=$(get_port $pid)
+
+ # Check if port information was found for the PID
+ if [[ -z $port ]]; then
+ port="N/A"
+ fi
+
+ started+=("Process $process_name - Command: $command, PID: $pid, Port: $port, Start time: $start_time")
+ done
fi
+ done
+
+ # Print information
+ if [[ ${#not_started[@]} -ne 0 ]]; then
+ openim::log::info "Not started processes:"
+ for process_name in "${not_started[@]}"; do
+ openim::log::error "Process $process_name is not started."
+ done
+ fi
+
+ if [[ ${#started[@]} -ne 0 ]]; then
+ echo
+ openim::log::info "Started processes:"
+ for info in "${started[@]}"; do
+ openim::log::info "$info"
+ done
+ fi
+
+ # Return status
+ if [[ ${#not_started[@]} -ne 0 ]]; then
+ echo "++++ OpenIM Log >> cat ${LOG_FILE}"
+ return 1
+ else
+ openim::log::success "All processes are running."
+ return 0
+ fi
}
# openim::util::check_process_names docker-pr
@@ -462,30 +462,30 @@ openim::util::check_process_names() {
# openim::util::stop_services_on_ports 8080 8081 8082
# The function returns a status of 1 if any service couldn't be stopped.
openim::util::stop_services_on_ports() {
- # An array to collect ports of processes that couldn't be stopped.
- local not_stopped=()
-
- # An array to collect information about processes that were stopped.
- local stopped=()
-
- openim::log::info "Stopping services on ports: $*"
- # Iterate over each given port.
- for port in "$@"; do
- # Use the `lsof` command to find process information related to the given port.
- info=$(lsof -i :$port -n -P | grep LISTEN || true)
-
- # If there's process information, it means the process associated with the port is running.
- if [[ -n $info ]]; then
- # Extract the Process ID.
- while read -r line; do
- local pid=$(echo $line | awk '{print $2}')
-
- # Try to stop the service by killing its process.
- if kill -TERM $pid; then
- stopped+=($port)
- else
- not_stopped+=($port)
- fi
+ # An array to collect ports of processes that couldn't be stopped.
+ local not_stopped=()
+
+ # An array to collect information about processes that were stopped.
+ local stopped=()
+
+ openim::log::info "Stopping services on ports: $*"
+ # Iterate over each given port.
+ for port in "$@"; do
+ # Use the `lsof` command to find process information related to the given port.
+ info=$(lsof -i :$port -n -P | grep LISTEN || true)
+
+ # If there's process information, it means the process associated with the port is running.
+ if [[ -n $info ]]; then
+ # Extract the Process ID.
+ while read -r line; do
+ local pid=$(echo $line | awk '{print $2}')
+
+ # Try to stop the service by killing its process.
+ if kill -TERM $pid; then
+ stopped+=($port)
+ else
+ not_stopped+=($port)
+ fi
done <<< "$info"
fi
done
@@ -519,7 +519,7 @@ openim::util::stop_services_on_ports() {
# nc -l -p 12345
# nc -l -p 123456
# ps -ef | grep "nc -l"
-# openim::util::stop_services_on_ports 1234 12345
+# openim::util::stop_services_on_ports 1234 12345
# The `openim::util::stop_services_with_name` function stops services with specified names.
@@ -1086,7 +1086,7 @@ function openim::util::ensure-install-nginx {
exit 1
fi
- for port in 80
+ for port in "80"
do
if echo |telnet 127.0.0.1 $port 2>&1|grep refused &>/dev/null;then
exit 1
@@ -1263,7 +1263,7 @@ function openim:util::setup_ssh_key_copy() {
local sshkey_file=~/.ssh/id_rsa.pub
- # check sshkey file
+ # check sshkey file
if [[ ! -e $sshkey_file ]]; then
expect -c "
spawn ssh-keygen -t rsa
@@ -1280,7 +1280,7 @@ function openim:util::setup_ssh_key_copy() {
# delete history
sed -i "/$target/d" ~/.ssh/known_hosts
- # copy key
+ # copy key
expect -c "
set timeout 100
spawn ssh-copy-id $username@$target
@@ -1571,7 +1571,7 @@ openim::util::check_ports() {
else
start_time=$(ps -p $pid -o lstart=)
fi
-
+
started+=("Port $port - Command: $command, PID: $pid, FD: $fd, Started: $start_time")
fi
done
@@ -1639,7 +1639,7 @@ openim::util::check_process_names() {
for process_name in "$@"; do
# Use `pgrep` to find process IDs related to the given process name
local pids=($(pgrep -f $process_name))
-
+
# Check if any process IDs were found
if [[ ${#pids[@]} -eq 0 ]]; then
not_started+=($process_name)
@@ -1713,7 +1713,7 @@ openim::util::stop_services_on_ports() {
# Extract the Process ID.
while read -r line; do
local pid=$(echo $line | awk '{print $2}')
-
+
# Try to stop the service by killing its process.
if kill -TERM $pid; then
stopped+=($port)
@@ -1753,7 +1753,7 @@ openim::util::stop_services_on_ports() {
# nc -l -p 12345
# nc -l -p 123456
# ps -ef | grep "nc -l"
-# openim::util::stop_services_on_ports 1234 12345
+# openim::util::stop_services_on_ports 1234 12345
# The `openim::util::stop_services_with_name` function stops services with specified names.
@@ -2320,7 +2320,7 @@ function openim::util::ensure-install-nginx {
exit 1
fi
- for port in 80
+ for port in "80"
do
if echo |telnet 127.0.0.1 $port 2>&1|grep refused &>/dev/null;then
exit 1
@@ -2467,7 +2467,7 @@ function openim::util::desc() {
}
function openim::util:run::prompt() {
- echo -n "$yellow\$ $reset"
+ echo -n "${yellow}\$ ${reset}"
}
started=""
@@ -2488,7 +2488,7 @@ function openim::util::run() {
if [ -n "$DEMO_RUN_FAST" ]; then
rate=1000
fi
- echo "$green$1$reset" | pv -qL $rate
+ echo "${green}$1${reset}" | pv -qL "$rate"
if [ -n "$DEMO_RUN_FAST" ]; then
sleep 0.5
fi
@@ -2516,7 +2516,7 @@ function openim::util::run::relative() {
# This function retrieves the IP address of the current server.
# It primarily uses the `curl` command to fetch the public IP address from ifconfig.me.
-# If curl or the service is not available, it falls back
+# If curl or the service is not available, it falls back
# to the internal IP address provided by the hostname command.
# TODO: If a delay is found, the delay needs to be addressed
function openim::util::get_server_ip() {
@@ -2524,7 +2524,7 @@ function openim::util::get_server_ip() {
if command -v curl &> /dev/null; then
# Try to retrieve the public IP address using curl and ifconfig.me
IP=$(dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | sed 's/"//g' | tr -d '\n')
-
+
# Check if IP retrieval was successful
if [[ -z "$IP" ]]; then
# If not, get the internal IP address
@@ -2534,7 +2534,7 @@ function openim::util::get_server_ip() {
# If curl is not available, get the internal IP address
IP=$(ip addr show | grep 'inet ' | grep -v 127.0.0.1 | awk '{print $2}' | cut -d'/' -f1 | head -n 1)
fi
-
+
# Return the fetched IP address
echo "$IP"
}
@@ -2580,7 +2580,7 @@ function openim::util::set_max_fd() {
if [ "$desired_fd" = "maximum" ] || [ "$desired_fd" = "max" ]; then
desired_fd="$max_fd_limit"
fi
-
+
# Check if desired_fd is less than or equal to max_fd_limit.
if [ "$desired_fd" -le "$max_fd_limit" ]; then
ulimit -n "$desired_fd"
@@ -2696,7 +2696,7 @@ function openim::util::run::relative() {
# This function retrieves the IP address of the current server.
# It primarily uses the `curl` command to fetch the public IP address from ifconfig.me.
-# If curl or the service is not available, it falls back
+# If curl or the service is not available, it falls back
# to the internal IP address provided by the hostname command.
# TODO: If a delay is found, the delay needs to be addressed
function openim::util::get_server_ip() {
@@ -2704,7 +2704,7 @@ function openim::util::get_server_ip() {
if command -v curl &> /dev/null; then
# Try to retrieve the public IP address using curl and ifconfig.me
IP=$(dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | sed 's/"//g' | tr -d '\n')
-
+
# Check if IP retrieval was successful
if [[ -z "$IP" ]]; then
# If not, get the internal IP address
@@ -2714,7 +2714,7 @@ function openim::util::get_server_ip() {
# If curl is not available, get the internal IP address
IP=$(ip addr show | grep 'inet ' | grep -v 127.0.0.1 | awk '{print $2}' | cut -d'/' -f1 | head -n 1)
fi
-
+
# Return the fetched IP address
echo "$IP"
}
@@ -2760,7 +2760,7 @@ function openim::util::set_max_fd() {
if [ "$desired_fd" = "maximum" ] || [ "$desired_fd" = "max" ]; then
desired_fd="$max_fd_limit"
fi
-
+
# Check if desired_fd is less than or equal to max_fd_limit.
if [ "$desired_fd" -le "$max_fd_limit" ]; then
ulimit -n "$desired_fd"
diff --git a/scripts/lib/version.sh b/scripts/lib/version.sh
index 04eb89b09..cb47136fb 100755
--- a/scripts/lib/version.sh
+++ b/scripts/lib/version.sh
@@ -12,7 +12,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
+
# -----------------------------------------------------------------------------
# Version management helpers. These functions help to set, save and load the
# following variables:
@@ -35,7 +35,7 @@ openim::version::get_version_vars() {
openim::version::load_version_vars "${OPENIM_GIT_VERSION_FILE}"
return
fi
-
+
# If the iamrnetes source was exported through git archive, then
# we likely don't have a git tree, but these magic values may be filled in.
# shellcheck disable=SC2016,SC2050
@@ -48,12 +48,12 @@ openim::version::get_version_vars() {
# something like 'HEAD -> release-1.8, tag: v1.8.3' where then 'tag: '
# can be extracted from it.
if [[ '$Format:%D$' =~ tag:\ (v[^ ,]+) ]]; then
- OPENIM_GIT_VERSION="${BASH_REMATCH[1]}"
+ OPENIM_GIT_VERSION="${BASH_REMATCH[1]}"
fi
fi
-
+
local git=(git --work-tree "${OPENIM_ROOT}")
-
+
if [[ -n ${OPENIM_GIT_COMMIT-} ]] || OPENIM_GIT_COMMIT=$("${git[@]}" rev-parse "HEAD^{commit}" 2>/dev/null); then
if [[ -z ${OPENIM_GIT_TREE_STATE-} ]]; then
# Check if the tree is dirty. default to dirty
@@ -63,7 +63,7 @@ openim::version::get_version_vars() {
OPENIM_GIT_TREE_STATE="dirty"
fi
fi
-
+
# Use git describe to find the version based on tags.
if [[ -n ${OPENIM_GIT_VERSION-} ]] || OPENIM_GIT_VERSION=$("${git[@]}" describe --tags --always --match='v*' 2>/dev/null); then
# This translates the "git describe" to an actual semver.org
@@ -81,7 +81,7 @@ openim::version::get_version_vars() {
# shellcheck disable=SC2001
# We have distance to subversion (v1.1.0-subversion-1-gCommitHash)
OPENIM_GIT_VERSION=$(echo "${OPENIM_GIT_VERSION}" | sed "s/-\([0-9]\{1,\}\)-g\([0-9a-f]\{14\}\)$/.\1\+\2/")
- elif [[ "${DASHES_IN_VERSION}" == "--" ]] ; then
+ elif [[ "${DASHES_IN_VERSION}" == "--" ]] ; then
# shellcheck disable=SC2001
# We have distance to base tag (v1.1.0-1-gCommitHash)
OPENIM_GIT_VERSION=$(echo "${OPENIM_GIT_VERSION}" | sed "s/-g\([0-9a-f]\{14\}\)$/+\1/")
@@ -94,7 +94,7 @@ openim::version::get_version_vars() {
#OPENIM_GIT_VERSION+="-dirty"
:
fi
-
+
# Try to match the "git describe" output to a regex to try to extract
# the "major" and "minor" versions and whether this is the exact tagged
# version or whether the tree is between two tagged versions.
@@ -105,12 +105,12 @@ openim::version::get_version_vars() {
OPENIM_GIT_MINOR+="+"
fi
fi
-
+
# If OPENIM_GIT_VERSION is not a valid Semantic Version, then refuse to build.
if ! [[ "${OPENIM_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
- echo "OPENIM_GIT_VERSION should be a valid Semantic Version. Current value: ${OPENIM_GIT_VERSION}"
- echo "Please see more details here: https://semver.org"
- exit 1
+ echo "OPENIM_GIT_VERSION should be a valid Semantic Version. Current value: ${OPENIM_GIT_VERSION}"
+ echo "Please see more details here: https://semver.org"
+ exit 1
fi
fi
fi
@@ -123,7 +123,7 @@ openim::version::save_version_vars() {
echo "!!! Internal error. No file specified in openim::version::save_version_vars"
return 1
}
-
+
cat <"${version_file}"
OPENIM_GIT_COMMIT='${OPENIM_GIT_COMMIT-}'
OPENIM_GIT_TREE_STATE='${OPENIM_GIT_TREE_STATE-}'
@@ -140,6 +140,6 @@ openim::version::load_version_vars() {
echo "!!! Internal error. No file specified in openim::version::load_version_vars"
return 1
}
-
+
source "${version_file}"
}
diff --git a/scripts/make-rules/common.mk b/scripts/make-rules/common.mk
index 5fda9b927..f8537b6ca 100644
--- a/scripts/make-rules/common.mk
+++ b/scripts/make-rules/common.mk
@@ -126,7 +126,7 @@ APIROOT=$(ROOT_DIR)/pkg/proto
# Linux command settings
# TODO: Whether you need to join utils?
-FIND := find . ! -path './utils/*' ! -path './vendor/*' ! -path './third_party/*'
+FIND := find . ! -path './utils/*' ! -path './vendor/*' ! -path './third_party/*' ! -path './components/*' ! -path './logs/*'
XARGS := xargs -r --no-run-if-empty
# Linux command settings-CODE DIRS Copyright
diff --git a/scripts/make-rules/golang.mk b/scripts/make-rules/golang.mk
index 44918d01c..915639b61 100644
--- a/scripts/make-rules/golang.mk
+++ b/scripts/make-rules/golang.mk
@@ -244,7 +244,7 @@ go.imports: tools.verify.goimports
## go.verify: execute all verity scripts.
.PHONY: go.verify
-go.verify:
+go.verify: tools.verify.misspell
@echo "Starting verification..."
@scripts_list=$$(find $(ROOT_DIR)/scripts -type f -name 'verify-*' | sort); \
for script in $$scripts_list; do \
diff --git a/scripts/make-rules/tools.mk b/scripts/make-rules/tools.mk
index 5f076d6e7..5d39258ea 100644
--- a/scripts/make-rules/tools.mk
+++ b/scripts/make-rules/tools.mk
@@ -217,6 +217,11 @@ install.depth:
install.go-callvis:
@$(GO) install github.com/ofabry/go-callvis@latest
+## install.misspell
+.PHONY: install.misspell
+install.misspell:
+ @$(GO) install github.com/client9/misspell/cmd/misspell@latest
+
## install.gothanks: Install gothanks, used to thank go dependencies
.PHONY: install.gothanks
install.gothanks:
diff --git a/scripts/release.sh b/scripts/release.sh
index 042a6c3a0..4984b2166 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -14,9 +14,9 @@
# limitations under the License.
# Description:
-# This script automates the process of building and releasing OpenIM,
+# This script automates the process of building and releasing OpenIM,
# including tasks like setting up the environment, verifying prerequisites,
-# building commands, packaging tarballs, uploading tarballs, creating GitHub
+# building commands, packaging tarballs, uploading tarballs, creating GitHub
# releases, and generating changelogs.
#
# Usage:
@@ -35,12 +35,12 @@
# This script can also be executed via the 'make release' command as an alternative.
#
# Dependencies:
-# This script depends on external scripts found in the 'scripts' directory and
-# assumes the presence of necessary tools and permissions for building and
+# This script depends on external scripts found in the 'scripts' directory and
+# assumes the presence of necessary tools and permissions for building and
# releasing software.
#
# Note:
-# The script uses standard bash script practices with error handling,
+# The script uses standard bash script practices with error handling,
# and it defaults to executing all steps if no specific option is provided.
#
# Build a OpenIM release. This will build the binaries, create the Docker
@@ -58,17 +58,17 @@ OPENIM_RELEASE_RUN_TESTS=${OPENIM_RELEASE_RUN_TESTS-y}
# Function to show help message
show_help() {
- echo "Usage: $(basename $0) [options]"
- echo "Options:"
- echo " -h, --help Show this help message"
- echo " -se, --setup-env Execute setup environment"
- echo " -vp, --verify-prereqs Execute prerequisites verification"
- echo " -bc, --build-command Execute build command"
- echo " -bi, --build-image Execute build image (default: not executed)"
- echo " -pt, --package-tarballs Execute package tarballs"
- echo " -ut, --upload-tarballs Execute upload tarballs"
- echo " -gr, --github-release Execute GitHub release"
- echo " -gc, --generate-changelog Execute generate changelog"
+ echo "Usage: $(basename $0) [options]"
+ echo "Options:"
+ echo " -h, --help Show this help message"
+ echo " -se, --setup-env Execute setup environment"
+ echo " -vp, --verify-prereqs Execute prerequisites verification"
+ echo " -bc, --build-command Execute build command"
+ echo " -bi, --build-image Execute build image (default: not executed)"
+ echo " -pt, --package-tarballs Execute package tarballs"
+ echo " -ut, --upload-tarballs Execute upload tarballs"
+ echo " -gr, --github-release Execute GitHub release"
+ echo " -gc, --generate-changelog Execute generate changelog"
}
# Initialize all actions to false
@@ -83,57 +83,57 @@ perform_generate_changelog=false
# Process command-line arguments
while getopts "hsevpbciptutgrgc-" opt; do
- case "${opt}" in
- h) show_help; exit 0 ;;
- se) perform_setup_env=true ;;
- vp) perform_verify_prereqs=true ;;
- bc) perform_build_command=true ;;
- bi) perform_build_image=true ;; # Handling new option
- pt) perform_package_tarballs=true ;;
- ut) perform_upload_tarballs=true ;;
- gr) perform_github_release=true ;;
- gc) perform_generate_changelog=true ;;
- --) case "${OPTARG}" in
- help) show_help; exit 0 ;;
- setup-env) perform_setup_env=true ;;
- verify-prereqs) perform_verify_prereqs=true ;;
- build-command) perform_build_command=true ;;
- build-image) perform_build_image=true ;; # Handling new long option
- package-tarballs) perform_package_tarballs=true ;;
- upload-tarballs) perform_upload_tarballs=true ;;
- github-release) perform_github_release=true ;;
- generate-changelog) perform_generate_changelog=true ;;
- *) echo "Invalid option: --${OPTARG}"; show_help; exit 1 ;;
- esac ;;
- *) show_help; exit 1 ;;
- esac
+ case "${opt}" in
+ h) show_help; exit 0 ;;
+ se) perform_setup_env=true ;;
+ vp) perform_verify_prereqs=true ;;
+ bc) perform_build_command=true ;;
+ bi) perform_build_image=true ;; # Handling new option
+ pt) perform_package_tarballs=true ;;
+ ut) perform_upload_tarballs=true ;;
+ gr) perform_github_release=true ;;
+ gc) perform_generate_changelog=true ;;
+ --) case "${OPTARG}" in
+ help) show_help; exit 0 ;;
+ setup-env) perform_setup_env=true ;;
+ verify-prereqs) perform_verify_prereqs=true ;;
+ build-command) perform_build_command=true ;;
+ build-image) perform_build_image=true ;; # Handling new long option
+ package-tarballs) perform_package_tarballs=true ;;
+ upload-tarballs) perform_upload_tarballs=true ;;
+ github-release) perform_github_release=true ;;
+ generate-changelog) perform_generate_changelog=true ;;
+ *) echo "Invalid option: --${OPTARG}"; show_help; exit 1 ;;
+ esac ;;
+ *) show_help; exit 1 ;;
+ esac
done
# Enable all actions by default if no options are provided
if [ "$#" -eq 0 ]; then
- perform_setup_env=true
- perform_verify_prereqs=true
- perform_build_command=true
- perform_package_tarballs=true
- perform_upload_tarballs=true
- perform_github_release=true
- perform_generate_changelog=true
- # TODO: Not enabling build_image by default
- # perform_build_image=true
+ perform_setup_env=true
+ perform_verify_prereqs=true
+ perform_build_command=true
+ perform_package_tarballs=true
+ perform_upload_tarballs=true
+ perform_github_release=true
+ perform_generate_changelog=true
+ # TODO: Not enabling build_image by default
+ # perform_build_image=true
fi
# Function to perform actions
perform_action() {
- local flag=$1
- local message=$2
- local command=$3
-
- if [ "$flag" == true ]; then
- openim::log::info "## $message..."
- if ! $command; then
- openim::log::errexit "Error in $message"
- fi
+ local flag=$1
+ local message=$2
+ local command=$3
+
+ if [ "$flag" == true ]; then
+ openim::log::info "## $message..."
+ if ! $command; then
+ openim::log::errexit "Error in $message"
fi
+ fi
}
echo "Starting script execution..."
diff --git a/scripts/start-all.sh b/scripts/start-all.sh
index b1f9b865b..5f34cbdbe 100755
--- a/scripts/start-all.sh
+++ b/scripts/start-all.sh
@@ -39,34 +39,34 @@ openim::log::install_errexit
# Function to execute the scripts.
function execute_scripts() {
- for script_path in "${OPENIM_SERVER_SCRIPT_START_LIST[@]}"; do
- # Extract the script name without extension for argument generation.
- script_name_with_prefix=$(basename "$script_path" .sh)
-
- # Remove the "openim-" prefix.
- script_name=${script_name_with_prefix#openim-}
-
- # Construct the argument based on the script name.
- arg="openim::${script_name}::start"
-
- # Check if the script file exists and is executable.
- if [[ -x "$script_path" ]]; then
- openim::log::status "Starting script: ${script_path##*/}" # Log the script name.
-
- # Execute the script with the constructed argument.
- "$script_path" "$arg"
-
- # Check if the script executed successfully.
- if [[ $? -eq 0 ]]; then
- openim::log::info "${script_path##*/} executed successfully."
- else
- openim::log::errexit "Error executing ${script_path##*/}."
- fi
- else
- openim::log::errexit "Script ${script_path##*/} is missing or not executable."
- fi
- done
- sleep 0.5
+ for script_path in "${OPENIM_SERVER_SCRIPT_START_LIST[@]}"; do
+ # Extract the script name without extension for argument generation.
+ script_name_with_prefix=$(basename "$script_path" .sh)
+
+ # Remove the "openim-" prefix.
+ script_name=${script_name_with_prefix#openim-}
+
+ # Construct the argument based on the script name.
+ arg="openim::${script_name}::start"
+
+ # Check if the script file exists and is executable.
+ if [[ -x "$script_path" ]]; then
+ openim::log::status "Starting script: ${script_path##*/}" # Log the script name.
+
+ # Execute the script with the constructed argument.
+ "$script_path" "$arg"
+
+ # Check if the script executed successfully.
+ if [[ $? -eq 0 ]]; then
+ openim::log::info "${script_path##*/} executed successfully."
+ else
+ openim::log::errexit "Error executing ${script_path##*/}."
+ fi
+ else
+ openim::log::errexit "Script ${script_path##*/} is missing or not executable."
+ fi
+ done
+ sleep 0.5
}
diff --git a/scripts/stop-all.sh b/scripts/stop-all.sh
index 692d2d1e4..1d2eddd78 100755
--- a/scripts/stop-all.sh
+++ b/scripts/stop-all.sh
@@ -14,7 +14,7 @@
# limitations under the License.
# This script is stop all openim service
-#
+#
# Usage: `scripts/stop.sh`.
# Encapsulated as: `make stop`.
@@ -38,8 +38,8 @@ openim::util::stop_services_with_name "${OPENIM_OUTPUT_HOSTBIN}"
echo -n "Stopping services 15 seconds."
for i in {1..15}; do
- echo -n "."
- sleep 1
+ echo -n "."
+ sleep 1
done
echo -e "\nServices stopped."
diff --git a/scripts/update-generated-docs.sh b/scripts/update-generated-docs.sh
index 93f0f86c1..c37c4a1f9 100755
--- a/scripts/update-generated-docs.sh
+++ b/scripts/update-generated-docs.sh
@@ -28,10 +28,10 @@ source "${OPENIM_ROOT}/scripts/lib/init.sh"
openim::golang::setup_env
BINS=(
- gendocs
- genopenimdocs
- genman
- genyaml
+ gendocs
+ genopenimdocs
+ genman
+ genyaml
)
make -C "${OPENIM_ROOT}" WHAT="${BINS[*]}"
diff --git a/scripts/verify-shellcheck.sh b/scripts/verify-shellcheck.sh
index de860115e..8a5ad7321 100755
--- a/scripts/verify-shellcheck.sh
+++ b/scripts/verify-shellcheck.sh
@@ -43,6 +43,54 @@ disabled=(
1091
# this lint prefers command -v to which, they are not the same
2230
+ # Error SC2155 indicates that you should separate variable declaration and assignment to avoid masking the return value of the command.
+ # In Bash scripts, when you declare and assign a local variable at the same time a command is executed, you only get the output of the command, but not the exit status (return value) of the command. #
+ 2155
+ # ShellCheck issues SC2086 warnings when you refer to a variable in a script but don't put it in double quotes.This can lead to unexpected behavior when scripts encounter Spaces,
+ # newlines, and wildcards in file names or other data.
+ 2086
+ 2206
+
+ # TODO: 需要修复,然后开启
+ 2034
+ 2048
+ 2148
+ 2059
+ 2214
+ 2145
+ 2128
+ 2550
+ 2046
+ 2181
+ 1102
+ 2045
+ 2068
+ 2145
+ 2207
+ 2231
+ 2013
+ 2154
+ 2120
+ 1083
+ 2001
+ 2012
+ 2016
+ 2164
+ 2223
+ 2166
+ 2119
+ 2162
+ 2295
+ 2002
+ 2004
+ 2202
+ 2178
+ 2064
+ 2260
+ 2043
+ 2178
+ 2044
+ 2153
)
# comma separate for passing to shellcheck
join_by() {
@@ -65,14 +113,18 @@ cd "${OPENIM_ROOT}"
# forked should be linted and fixed.
all_shell_scripts=()
while IFS=$'\n' read -r script;
- do git check-ignore -q "$script" || all_shell_scripts+=("$script");
-done < <(find . -name "*.sh" \
+do git check-ignore -q "$script" || all_shell_scripts+=("$script");
+ done < <(find . -name "*.sh" \
-not \( \
- -path ./_\* -o \
- -path ./.git\* -o \
- -path ./vendor\* -o \
- \( -path ./third_party\* -a -not -path ./third_party/forked\* \) \
- \))
+ -path ./_\* -o \
+ -path ./.git\* -o \
+ -path ./Godeps\* -o \
+ -path ./_output\* -o \
+ -path ./components\* -o \
+ -path ./logs\* -o \
+ -path ./vendor\* -o \
+ \( -path ./third_party\* -a -not -path ./third_party/forked\* \) \
+\) -print 2>/dev/null)
# detect if the host machine has the required shellcheck version installed
# if so, we will use that instead.
@@ -113,8 +165,8 @@ if ${HAVE_SHELLCHECK}; then
else
openim::log::info "Using shellcheck ${SHELLCHECK_VERSION} docker image."
"${DOCKER}" run \
- --rm -v "${OPENIM_ROOT}:"${OPENIM_ROOT}"" -w "${OPENIM_ROOT}" \
- "${SHELLCHECK_IMAGE}" \
+ --rm -v "${OPENIM_ROOT}:${OPENIM_ROOT}" -w "${OPENIM_ROOT}" \
+ "${SHELLCHECK_IMAGE}" \
shellcheck "${SHELLCHECK_OPTIONS[@]}" "${all_shell_scripts[@]}" >&2 || res=$?
fi
diff --git a/scripts/verify-spelling.sh b/scripts/verify-spelling.sh
index 487c68cde..2c02dccf7 100755
--- a/scripts/verify-spelling.sh
+++ b/scripts/verify-spelling.sh
@@ -25,17 +25,8 @@ OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
export OPENIM_ROOT
source "${OPENIM_ROOT}/scripts/lib/init.sh"
-# Ensure that we find the binaries we build before anything else.
-export GOBIN="${KUBE_OUTPUT_BINPATH}"
-PATH="${GOBIN}:${PATH}"
-
-# Install tools we need
-pushd "${OPENIM_ROOT}/tools" >/dev/null
- GO111MODULE=on go install github.com/client9/misspell/cmd/misspell
-popd >/dev/null
-
# Spell checking
# All the skipping files are defined in scripts/.spelling_failures
skipping_file="${OPENIM_ROOT}/scripts/.spelling_failures"
failing_packages=$(sed "s| | -e |g" "${skipping_file}")
-git ls-files | grep -v -e "${failing_packages}" | xargs misspell -i "Creater,creater,ect" -error -o stderr
+git ls-files | grep -v -e "${failing_packages}" | xargs "$OPENIM_ROOT/_output/tools/misspell" -i "Creater,creater,ect" -error -o stderr
diff --git a/scripts/verify-typecheck.sh b/scripts/verify-typecheck.sh
index a0b818135..62fca4049 100755
--- a/scripts/verify-typecheck.sh
+++ b/scripts/verify-typecheck.sh
@@ -33,7 +33,7 @@ cd "${OPENIM_ROOT}"
ret=0
TYPECHECK_SERIAL="${TYPECHECK_SERIAL:-false}"
scripts/run-in-gopath.sh \
- go run test/typecheck/typecheck.go "$@" "--serial=$TYPECHECK_SERIAL" || ret=$?
+go run test/typecheck/typecheck.go "$@" "--serial=$TYPECHECK_SERIAL" || ret=$?
if [[ $ret -ne 0 ]]; then
openim::log::error "Type Check has failed. This may cause cross platform build failures." >&2
openim::log::error "Please see https://github.com/openimsdk/open-im-server/tree/main/test/typecheck for more information." >&2
diff --git a/scripts/wait-for-it.sh b/scripts/wait-for-it.sh
index 99a36affe..c05b85678 100755
--- a/scripts/wait-for-it.sh
+++ b/scripts/wait-for-it.sh
@@ -30,119 +30,119 @@ Usage:
Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGE
- exit 1
+ exit 1
}
wait_for() {
- if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
- echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
+ 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
- echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
+ (echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
+ WAITFORIT_result=$?
fi
- WAITFORIT_start_ts=$(date +%s)
- while :
- do
- if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
- nc -z $WAITFORIT_HOST $WAITFORIT_PORT
- WAITFORIT_result=$?
- else
- (echo -n > /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
+ 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
}
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
+ # 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
- ;;
- *)
- echoerr "Unknown argument: $1"
- usage
- ;;
- esac
+ 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
+ ;;
+ *)
+ echoerr "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
+ echoerr "Error: you need to provide a host and port to test."
+ usage
fi
WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
@@ -156,36 +156,36 @@ WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlin
WAITFORIT_BUSYTIMEFLAG=""
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
- WAITFORIT_ISBUSY=1
- # Check if busybox timeout uses -t flag
- # (recent Alpine versions don't support -t anymore)
- if timeout &>/dev/stdout | grep -q -e '-t '; then
- WAITFORIT_BUSYTIMEFLAG="-t"
- fi
+ WAITFORIT_ISBUSY=1
+ # Check if busybox timeout uses -t flag
+ # (recent Alpine versions don't support -t anymore)
+ if timeout &>/dev/stdout | grep -q -e '-t '; then
+ WAITFORIT_BUSYTIMEFLAG="-t"
+ fi
else
- WAITFORIT_ISBUSY=0
+ WAITFORIT_ISBUSY=0
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=$?
- exit $WAITFORIT_RESULT
-else
- if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
- wait_for_wrapper
- WAITFORIT_RESULT=$?
- else
- wait_for
- WAITFORIT_RESULT=$?
- fi
+ 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
+ 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
diff --git a/test/typecheck/README.md b/test/typecheck/README.md
index 6ba462ec9..e5b76d4c6 100644
--- a/test/typecheck/README.md
+++ b/test/typecheck/README.md
@@ -1,27 +1,52 @@
-# OpenIM Typecheck
+# OpenIM Typecheck: Cross-Platform Source Code Type Checking for Go
-OpenIM Typecheck 为所有 Go 构建平台进行跨平台源代码类型检查。
+## Introduction
-## 优点
+OpenIM Typecheck is a robust tool designed for cross-platform source code type checking across all Go build platforms. This utility leverages Go’s built-in parsing and type-check libraries (`go/parser` and `go/types`) to deliver efficient and reliable code analysis.
-- **速度**:OpenIM 完整编译大约需要 3 分钟,而使用 Typecheck 只需数秒。
-- **资源消耗**:与需要 >40GB 的 RAM 不同,Typecheck 只需 <8GB 的 RAM。
+## Advantages
-## 实现
+- **Speed**: A complete compilation with OpenIM can take approximately 3 minutes. In contrast, OpenIM Typecheck achieves this in mere seconds, significantly enhancing productivity.
+- **Resource Efficiency**: Unlike the typical requirement of over 40GB of RAM for standard processes, Typecheck operates effectively with less than 8GB of RAM. This reduction in resource consumption makes it highly suitable for a variety of systems, reducing overheads and facilitating smoother operations.
-OpenIM Typecheck 使用 Go 内置的解析和类型检查库 (`go/parser` 和 `go/types`)。然而,这些库并不是 go 编译器所使用的。偶尔会出现不匹配的情况,但总的来说,它们是相当接近的。
+## Implementation
-## 错误处理
+OpenIM Typecheck employs Go's native parsing and type-checking libraries (`go/parser` and `go/types`). However, it's important to note that these libraries aren't identical to those used by the Go compiler. While occasional mismatches may occur, these libraries generally provide close approximations to the compiler's functionality, offering a reliable basis for type checking.
-如果错误不会阻止构建,可以忽略。
+## Error Handling
-**`go/types` 报告的错误,但 `go build` 不会**:
-- **真正的错误**(根据规范):
- - 应尽量修复。如果无法修复或正在进行中(例如,已被外部引用的代码),则可以忽略。
- - 例如:闭包中的未使用变量
-- **不真实的错误**:
- - 应忽略并在适当的情况下向上游报告。
- - 例如:staging 和 generated 类型之间的类型检查不匹配
+Typecheck's approach to error handling is pragmatic, focusing on practicality and build continuity.
-**`go build` 报告的错误,但我们不会**:
-- CGo 错误,包括语法和链接器错误。
+**Errors reported by `go/types` but not by `go build`**:
+- **Actual Errors** (as per the specification):
+ - These should ideally be rectified. If rectification is not feasible, such as in cases of ongoing work or external dependencies in the code, these errors can be overlooked.
+ - Example: Unused variables within a closure.
+- **False Positives**:
+ - These errors should be ignored and, where appropriate, reported upstream for resolution.
+ - Example: Type mismatches between staging and generated types.
+
+**Errors reported by `go build` but not by us**:
+- CGo-related errors, including both syntax and linker issues, are outside our scope.
+
+## Usage
+
+### Locally
+
+To run Typecheck locally, simply use the following command:
+
+```bash
+make verify
+```
+
+### Continuous Integration (CI)
+
+In CI environments, Typecheck can be integrated into the workflow as follows:
+
+```yaml
+- name: Typecheck
+ run: make verify
+```
+
+This streamlined process facilitates efficient error detection and resolution, ensuring a robust and reliable build pipeline.
+
+More to learn about typecheck [share blog](https://nsddd.top/posts/concurrent-type-checking-and-cross-platform-development-in-go/)
\ No newline at end of file
diff --git a/test/typecheck/typecheck.go b/test/typecheck/typecheck.go
index 8f353881b..975ce988d 100644
--- a/test/typecheck/typecheck.go
+++ b/test/typecheck/typecheck.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// do a fast type check of kubernetes code, for all platforms.
+// do a fast type check of openim code, for all platforms.
package main
import (
@@ -47,14 +47,12 @@ var (
crossPlatforms = []string{
"linux/amd64", "windows/386",
"darwin/amd64", "darwin/arm64",
- "linux/386",
+ "linux/386", "linux/arm",
"windows/amd64", "linux/arm64",
"linux/ppc64le", "linux/s390x",
"windows/arm64",
}
- // "linux/arm",
-
// directories we always ignore
standardIgnoreDirs = []string{
// Staging code is symlinked from vendor/k8s.io, and uses import
@@ -62,17 +60,14 @@ var (
// inside of staging/, but works when typechecked as part of vendor/.
"staging",
"components",
+ "logs",
// OS-specific vendor code tends to be imported by OS-specific
// packages. We recursively typecheck imported vendored packages for
// each OS, but don't typecheck everything for every OS.
"vendor",
+ "test",
"_output",
- "OpenIMSKD/tools",
- // This is a weird one. /testdata/ is *mostly* ignored by Go,
- // and this translates to kubernetes/vendor not working.
- // edit/record.go doesn't compile without gopkg.in/yaml.v2
- // in $GOSRC/$GOROOT (both typecheck and the shell script).
- "pkg/kubectl/cmd/testdata/edit",
+ "*/mw/rpc_server_interceptor.go",
// Tools we use for maintaining the code base but not necessarily
// ship as part of the release
"sopenim::golang::setup_env:tools/yamlfmt/yamlfmt.go:tools",
diff --git a/test/wrktest.sh b/test/wrktest.sh
index a97ebf043..10a41121f 100755
--- a/test/wrktest.sh
+++ b/test/wrktest.sh
@@ -34,7 +34,7 @@ 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`))
+threads=$((3 * $(grep -c processor /proc/cpuinfo)))
source "${openim_root}/scripts/lib/color.sh"
@@ -122,7 +122,7 @@ if (s ~ "s") {
# Remove existing data file
function openim::wrk::prepare() {
- rm -f ${wrkdir}/${datfile}
+ rm -f "${wrkdir}"/"${datfile}"
}
# Plot according to gunplot data file
@@ -216,7 +216,7 @@ openim::wrk::start_performance_test() {
do
wrkcmd="${cmd} -c ${c} $1"
echo "Running wrk command: ${wrkcmd}"
- result=`eval ${wrkcmd}`
+ result=$(eval "${wrkcmd}")
openim::wrk::convert_plot_data "${result}"
done
@@ -241,9 +241,10 @@ while getopts "hd:n:" opt;do
esac
done
-shift $(($OPTIND-1))
+shift $((OPTIND-1))
+
+mkdir -p "${wrkdir}"
-mkdir -p ${wrkdir}
case $1 in
"diff")
if [ "$#" -lt 3 ];then
@@ -255,7 +256,7 @@ case $1 in
t2=$(basename $3|sed 's/.dat//g') # 对比图中粉色线条名称
join $2 $3 > /tmp/plot_diff.dat
- openim::wrk::plot_diff `basename $2` `basename $3`
+ openim::wrk::plot_diff "$(basename "$2")" "$(basename "$3")"
exit 0
;;
*)
diff --git a/tools/data-conversion/README.md b/tools/data-conversion/README.md
index 22126e4d8..71387af7f 100644
--- a/tools/data-conversion/README.md
+++ b/tools/data-conversion/README.md
@@ -31,7 +31,7 @@ var (
usernameV3 = "root"
passwordV3 = "openIM123"
addrV3 = "127.0.0.1:13306"
- databaseV3 = "openIM_v3"
+ databaseV3 = "openim_v3"
)
```
diff --git a/tools/data-conversion/openim/cmd/conversion-mysql/conversion-mysql.go b/tools/data-conversion/openim/cmd/conversion-mysql/conversion-mysql.go
index 8992e12c4..8a951e16f 100644
--- a/tools/data-conversion/openim/cmd/conversion-mysql/conversion-mysql.go
+++ b/tools/data-conversion/openim/cmd/conversion-mysql/conversion-mysql.go
@@ -38,7 +38,7 @@ func main() {
usernameV3 = "root" // v3版本mysql用户名
passwordV3 = "openIM123" // v3版本mysql密码
addrV3 = "127.0.0.1:13306" // v3版本mysql地址
- databaseV3 = "openIM_v3" // v3版本mysql数据库名字
+ databaseV3 = "openim_v3" // v3版本mysql数据库名字
)
var concurrency = 1 // 并发数量
diff --git a/tools/data-conversion/openim/common/config.go b/tools/data-conversion/openim/common/config.go
index e2bd14a05..e993038d1 100644
--- a/tools/data-conversion/openim/common/config.go
+++ b/tools/data-conversion/openim/common/config.go
@@ -44,7 +44,7 @@ const (
UsernameV3 = "root"
PasswordV3 = "openIM123"
IpV3 = "43.134.63.160:13306"
- DatabaseV3 = "openIM_v3"
+ DatabaseV3 = "openim_v3"
)
// V3 chat.
diff --git a/tools/data-conversion/openim/mysql/cmd.go b/tools/data-conversion/openim/mysql/cmd.go
index f5a23facb..ab3857fba 100644
--- a/tools/data-conversion/openim/mysql/cmd.go
+++ b/tools/data-conversion/openim/mysql/cmd.go
@@ -38,7 +38,7 @@ func Cmd() {
usernameV3 = "root"
passwordV3 = "openIM123"
addrV3 = "203.56.175.233:13306"
- databaseV3 = "openIM_v3"
+ databaseV3 = "openim_v3"
)
log.SetFlags(log.LstdFlags | log.Llongfile)
dsnV2 := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", usernameV2, passwordV2, addrV2, databaseV2)
diff --git a/tools/formitychecker/checker/checker.go b/tools/formitychecker/checker/checker.go
index 187b509bc..7a1643358 100644
--- a/tools/formitychecker/checker/checker.go
+++ b/tools/formitychecker/checker/checker.go
@@ -1,3 +1,17 @@
+// Copyright © 2024 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package checker
import (
diff --git a/tools/formitychecker/config/config.go b/tools/formitychecker/config/config.go
index 95bcee346..0c4f6a16b 100644
--- a/tools/formitychecker/config/config.go
+++ b/tools/formitychecker/config/config.go
@@ -1,3 +1,17 @@
+// Copyright © 2024 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package config
import (
diff --git a/tools/formitychecker/formitychecker.go b/tools/formitychecker/formitychecker.go
index d078009b6..2bedbfb32 100644
--- a/tools/formitychecker/formitychecker.go
+++ b/tools/formitychecker/formitychecker.go
@@ -1,3 +1,17 @@
+// Copyright © 2024 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package main
import (
diff --git a/tools/imctl/.gitignore b/tools/imctl/.gitignore
index a2e773394..72ff17ca9 100644
--- a/tools/imctl/.gitignore
+++ b/tools/imctl/.gitignore
@@ -36,20 +36,6 @@ config/config.yaml
.env
./.env
-### OpenIM deploy ###
-deploy/openim_demo
-deploy/openim-api
-deploy/openim-rpc-msg_gateway
-deploy/openim-msgtransfer
-deploy/openim-push
-deploy/openim_timer_task
-deploy/openim-rpc-user
-deploy/openim-rpc-friend
-deploy/openim-rpc-group
-deploy/openim-rpc-msg
-deploy/openim-rpc-auth
-deploy/Open-IM-SDK-Core
-
# files used by the developer
.idea.md
.todo.md
diff --git a/tools/imctl/imctl.go b/tools/imctl/imctl.go
index 1a501cafc..91161326e 100644
--- a/tools/imctl/imctl.go
+++ b/tools/imctl/imctl.go
@@ -1,3 +1,17 @@
+// Copyright © 2024 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package main
import "fmt"
From 9527278239959019306fa7b15e269665204178ee Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Fri, 26 Jan 2024 12:05:17 +0800
Subject: [PATCH 080/110] feat: fix openim logs and ci (#1817)
---
.github/workflows/pull-request.yml | 3 ---
.github/workflows/sync-release.yml | 3 ++-
.github/workflows/sync.yml | 5 +++--
scripts/lib/logging.sh | 4 ++--
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index a03eade82..828d30d7d 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -78,9 +78,6 @@ jobs:
echo "Run unit test and get test coverage successfully"
continue-on-error: true
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
-
- name: OpenIM verify copyright
run: |
sudo make verify-copyright
diff --git a/.github/workflows/sync-release.yml b/.github/workflows/sync-release.yml
index 2a29f6218..e156e07d8 100644
--- a/.github/workflows/sync-release.yml
+++ b/.github/workflows/sync-release.yml
@@ -3,7 +3,7 @@
# you may not use this file except in compliance with the License.
# https://github.com/BetaHuhn/repo-file-sync-action
-name: Synchronize kubecub public code to other repositories
+name: Synchronize OpenIM Release Branch Public Code To Other Repositories
on:
push:
paths:
@@ -41,3 +41,4 @@ jobs:
automerge
ASSIGNEES: |
kubbot
+ continue-on-error: true
\ No newline at end of file
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
index 6e5c79799..77ed2f881 100644
--- a/.github/workflows/sync.yml
+++ b/.github/workflows/sync.yml
@@ -3,7 +3,7 @@
# you may not use this file except in compliance with the License.
# https://github.com/BetaHuhn/repo-file-sync-action
-name: Synchronize kubecub public code to other repositories
+name: Synchronize OpenIM Main Branch Public Code To Other Repositories
on:
push:
branches:
@@ -36,4 +36,5 @@ jobs:
file-sync
automerge
ASSIGNEES: |
- kubbot
\ No newline at end of file
+ kubbot
+ continue-on-error: true
\ No newline at end of file
diff --git a/scripts/lib/logging.sh b/scripts/lib/logging.sh
index eb83c526d..c520850e8 100755
--- a/scripts/lib/logging.sh
+++ b/scripts/lib/logging.sh
@@ -129,7 +129,7 @@ openim::log::error_exit() {
# Log an error but keep going. Don't dump the stack or exit.
openim::log::error() {
- timestamp=$(date +"[%m%d %H:%M:%S]")
+ timestamp=$(date +"[%Y-%m-%d %H:%M:%S %Z]")
echo_log "!!! ${timestamp} ${1-}" >&2
shift
for message; do
@@ -192,7 +192,7 @@ openim::log::status() {
return
fi
- timestamp=$(date +"[%m%d %H:%M:%S]")
+ timestamp=$(date +"[%Y-%m-%d %H:%M:%S %Z]")
echo_log "+++ ${timestamp} ${1}"
shift
for message; do
From 05e66e9f8d309fd878363a991df2cd30592bf804 Mon Sep 17 00:00:00 2001
From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com>
Date: Fri, 26 Jan 2024 14:39:53 +0800
Subject: [PATCH 081/110] Feature: add direct connect mode with zookeeper,
etcd, and k8s (#1775)
* fix: fix the bug
* fix: fix the imAdmin permission and searchNoficitaion resp
* 2023 Annual Summary Reflections and Aspirations
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: dissmissGroup and lack of keyword bug (#1678)
* Update docker-start-all.sh
* Update env-template.yaml
* Update docker-start-all.sh
* fix openim config mongo passwd env
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* fix: fix some bug
* fix: group messages sync failed.
* fix: fix the valiable name
* fix: fix the getSortedConversation api
* fix: fix the mongo search error
* fix: GroupApplicationAcceptedNotification
(cherry picked from commit 4c3c4555a35ec8e31ffbf3e96a5dba3bceec09ee)
* fix: GroupApplicationAcceptedNotification
* fix update friends
* fix pageFindUser
* Delete .devcontainer directory
* fix find user
* Your commit message here
* feat: direct conn
* fix: direct conn message gateway array exceed length
* fix: direct conn message gateway array exceed length
* fix: direct conn cannot find name
* fix: direct conn cannot find name
* fix: direct conn cannot find name
* fix: direct conn cannot find name
* fix: direct conn cannot find name
* fix: direct conn cannot find name
* fix: direct conn cannot find name
* fix: direct conn cannot find name
* fix: direct conn cannot find name
* fix: operation id invalid
* feat: multiple address
* feat: multiple address
* feat: multiple address
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: multiple addresses
* feat: direct conn with multiple ports
* Update user.go
* feat: direct conn with multiple ports
* feat: remove checkServiceHealth
* feat: update fmt error
* feat: update .devcontainer
* feat: update .devcontainer
* feat: update fmt.Errorf(
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Co-authored-by: luhaoling <2198702716@qq.com>
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
Co-authored-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
Co-authored-by: Brabem <69128477+luhaoling@users.noreply.github.com>
Co-authored-by: OpenIM Bot <124379614+kubbot@users.noreply.github.com>
Co-authored-by: OpenIM Robot <139873238+openimbot@users.noreply.github.com>
Co-authored-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
Co-authored-by: withchao <993506633@qq.com>
---
internal/api/route.go | 3 +-
internal/msgtransfer/init.go | 2 +-
internal/rpc/user/user.go | 4 +
internal/tools/msg.go | 2 +-
.../direct/directResolver.go | 81 +++++++++
.../discoveryregister/direct/directconn.go | 154 ++++++++++++++++++
.../discoveryregister/discoveryregister.go | 3 +
.../discoveryregister_test.go | 1 +
.../kubernetes/kubernetes.go | 20 +++
pkg/common/startrpc/start.go | 2 +-
10 files changed, 268 insertions(+), 4 deletions(-)
create mode 100644 pkg/common/discoveryregister/direct/directResolver.go
create mode 100644 pkg/common/discoveryregister/direct/directconn.go
diff --git a/internal/api/route.go b/internal/api/route.go
index 3f16d3e50..10907d086 100644
--- a/internal/api/route.go
+++ b/internal/api/route.go
@@ -16,6 +16,7 @@ package api
import (
"context"
+ "fmt"
"net/http"
"github.com/OpenIMSDK/protocol/constant"
@@ -43,7 +44,7 @@ import (
)
func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.UniversalClient) *gin.Engine {
- discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials())) // 默认RPC中间件
+ discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin"))) // 默认RPC中间件
gin.SetMode(gin.ReleaseMode)
r := gin.New()
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
diff --git a/internal/msgtransfer/init.go b/internal/msgtransfer/init.go
index a8d10799f..7d692662d 100644
--- a/internal/msgtransfer/init.go
+++ b/internal/msgtransfer/init.go
@@ -66,7 +66,7 @@ func StartTransfer(prometheusPort int) error {
if err := client.CreateRpcRootNodes(config.Config.GetServiceNames()); err != nil {
return err
}
- client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
+ client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
msgModel := cache.NewMsgCacheModel(rdb)
msgDocModel := unrelation.NewMsgMongoDriver(mongo.GetDatabase())
msgDatabase := controller.NewCommonMsgDatabase(msgDocModel, msgModel)
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 50c97f41b..981e0ccc4 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -61,6 +61,7 @@ type userServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
+
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis()
if err != nil {
@@ -243,6 +244,7 @@ func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPagi
return nil, err
}
return &pbuser.GetPaginationUsersResp{Total: int32(total), Users: convert.UsersDB2Pb(users)}, err
+
}
}
@@ -439,6 +441,7 @@ func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.P
if err != nil {
return nil, err
}
+
return &pbuser.ProcessUserCommandDeleteResp{}, nil
}
@@ -475,6 +478,7 @@ func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.P
}
func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) {
+
err := authverify.CheckAccessV3(ctx, req.UserID)
if err != nil {
return nil, err
diff --git a/internal/tools/msg.go b/internal/tools/msg.go
index 97bb2988e..30006670e 100644
--- a/internal/tools/msg.go
+++ b/internal/tools/msg.go
@@ -79,7 +79,7 @@ func InitMsgTool() (*MsgTool, error) {
if err != nil {
return nil, err
}
- discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
+ discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
userDB, err := mgo.NewUserMongo(mongo.GetDatabase())
if err != nil {
return nil, err
diff --git a/pkg/common/discoveryregister/direct/directResolver.go b/pkg/common/discoveryregister/direct/directResolver.go
new file mode 100644
index 000000000..285f55112
--- /dev/null
+++ b/pkg/common/discoveryregister/direct/directResolver.go
@@ -0,0 +1,81 @@
+package direct
+
+import (
+ "context"
+ "github.com/OpenIMSDK/tools/log"
+ "google.golang.org/grpc/resolver"
+ "math/rand"
+ "strings"
+)
+
+const (
+ slashSeparator = "/"
+ // EndpointSepChar is the separator char in endpoints.
+ EndpointSepChar = ','
+
+ subsetSize = 32
+ scheme = "direct"
+)
+
+type ResolverDirect struct {
+}
+
+func NewResolverDirect() *ResolverDirect {
+ return &ResolverDirect{}
+}
+
+func (rd *ResolverDirect) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (
+ resolver.Resolver, error) {
+ log.ZDebug(context.Background(), "Build", "target", target)
+ endpoints := strings.FieldsFunc(GetEndpoints(target), func(r rune) bool {
+ return r == EndpointSepChar
+ })
+ endpoints = subset(endpoints, subsetSize)
+ addrs := make([]resolver.Address, 0, len(endpoints))
+
+ for _, val := range endpoints {
+ addrs = append(addrs, resolver.Address{
+ Addr: val,
+ })
+ }
+ if err := cc.UpdateState(resolver.State{
+ Addresses: addrs,
+ }); err != nil {
+ return nil, err
+ }
+
+ return &nopResolver{cc: cc}, nil
+}
+func init() {
+ resolver.Register(&ResolverDirect{})
+}
+func (rd *ResolverDirect) Scheme() string {
+ return scheme // return your custom scheme name
+}
+
+// GetEndpoints returns the endpoints from the given target.
+func GetEndpoints(target resolver.Target) string {
+ return strings.Trim(target.URL.Path, slashSeparator)
+}
+func subset(set []string, sub int) []string {
+ rand.Shuffle(len(set), func(i, j int) {
+ set[i], set[j] = set[j], set[i]
+ })
+ if len(set) <= sub {
+ return set
+ }
+
+ return set[:sub]
+}
+
+type nopResolver struct {
+ cc resolver.ClientConn
+}
+
+func (n nopResolver) ResolveNow(options resolver.ResolveNowOptions) {
+
+}
+
+func (n nopResolver) Close() {
+
+}
diff --git a/pkg/common/discoveryregister/direct/directconn.go b/pkg/common/discoveryregister/direct/directconn.go
new file mode 100644
index 000000000..3eaa6fa19
--- /dev/null
+++ b/pkg/common/discoveryregister/direct/directconn.go
@@ -0,0 +1,154 @@
+package direct
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "github.com/OpenIMSDK/tools/errs"
+ config2 "github.com/openimsdk/open-im-server/v3/pkg/common/config"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials/insecure"
+)
+
+type ServiceAddresses map[string][]int
+
+func getServiceAddresses() ServiceAddresses {
+ return ServiceAddresses{
+ config2.Config.RpcRegisterName.OpenImUserName: config2.Config.RpcPort.OpenImUserPort,
+ config2.Config.RpcRegisterName.OpenImFriendName: config2.Config.RpcPort.OpenImFriendPort,
+ config2.Config.RpcRegisterName.OpenImMsgName: config2.Config.RpcPort.OpenImMessagePort,
+ config2.Config.RpcRegisterName.OpenImMessageGatewayName: config2.Config.LongConnSvr.OpenImMessageGatewayPort,
+ config2.Config.RpcRegisterName.OpenImGroupName: config2.Config.RpcPort.OpenImGroupPort,
+ config2.Config.RpcRegisterName.OpenImAuthName: config2.Config.RpcPort.OpenImAuthPort,
+ config2.Config.RpcRegisterName.OpenImPushName: config2.Config.RpcPort.OpenImPushPort,
+ config2.Config.RpcRegisterName.OpenImConversationName: config2.Config.RpcPort.OpenImConversationPort,
+ config2.Config.RpcRegisterName.OpenImThirdName: config2.Config.RpcPort.OpenImThirdPort,
+ }
+}
+
+type ConnDirect struct {
+ additionalOpts []grpc.DialOption
+ currentServiceAddress string
+ conns map[string][]*grpc.ClientConn
+ resolverDirect *ResolverDirect
+}
+
+func (cd *ConnDirect) GetClientLocalConns() map[string][]*grpc.ClientConn {
+ return nil
+}
+
+func (cd *ConnDirect) GetUserIdHashGatewayHost(ctx context.Context, userId string) (string, error) {
+ return "", nil
+}
+
+func (cd *ConnDirect) Register(serviceName, host string, port int, opts ...grpc.DialOption) error {
+ return nil
+}
+
+func (cd *ConnDirect) UnRegister() error {
+ return nil
+}
+
+func (cd *ConnDirect) CreateRpcRootNodes(serviceNames []string) error {
+ return nil
+}
+
+func (cd *ConnDirect) RegisterConf2Registry(key string, conf []byte) error {
+ return nil
+}
+
+func (cd *ConnDirect) GetConfFromRegistry(key string) ([]byte, error) {
+ return nil, nil
+}
+
+func (cd *ConnDirect) Close() {
+
+}
+
+func NewConnDirect() (*ConnDirect, error) {
+ return &ConnDirect{
+ conns: make(map[string][]*grpc.ClientConn),
+ resolverDirect: NewResolverDirect(),
+ }, nil
+}
+
+func (cd *ConnDirect) GetConns(ctx context.Context,
+ serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
+
+ if conns, exists := cd.conns[serviceName]; exists {
+ return conns, nil
+ }
+ ports := getServiceAddresses()[serviceName]
+ var connections []*grpc.ClientConn
+ for _, port := range ports {
+ conn, err := cd.dialServiceWithoutResolver(ctx, fmt.Sprintf(config2.Config.Rpc.ListenIP+":%d", port), append(cd.additionalOpts, opts...)...)
+ if err != nil {
+ fmt.Printf("connect to port %d failed,serviceName %s, IP %s\n", port, serviceName, config2.Config.Rpc.ListenIP)
+ }
+ connections = append(connections, conn)
+ }
+
+ if len(connections) == 0 {
+ return nil, fmt.Errorf("no connections found for service: %s", serviceName)
+ }
+ return connections, nil
+}
+
+func (cd *ConnDirect) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
+ // Get service addresses
+ addresses := getServiceAddresses()
+ address, ok := addresses[serviceName]
+ if !ok {
+ return nil, errs.Wrap(errors.New("unknown service name"), "serviceName", serviceName)
+ }
+ var result string
+ for _, addr := range address {
+ if result != "" {
+ result = result + "," + fmt.Sprintf(config2.Config.Rpc.ListenIP+":%d", addr)
+ } else {
+ result = fmt.Sprintf(config2.Config.Rpc.ListenIP+":%d", addr)
+ }
+ }
+ // Try to dial a new connection
+ conn, err := cd.dialService(ctx, result, append(cd.additionalOpts, opts...)...)
+ if err != nil {
+ return nil, errs.Wrap(err, "address", result)
+ }
+
+ // Store the new connection
+ cd.conns[serviceName] = append(cd.conns[serviceName], conn)
+ return conn, nil
+}
+
+func (cd *ConnDirect) GetSelfConnTarget() string {
+ return cd.currentServiceAddress
+}
+
+func (cd *ConnDirect) AddOption(opts ...grpc.DialOption) {
+ cd.additionalOpts = append(cd.additionalOpts, opts...)
+}
+
+func (cd *ConnDirect) CloseConn(conn *grpc.ClientConn) {
+ if conn != nil {
+ conn.Close()
+ }
+}
+
+func (cd *ConnDirect) dialService(ctx context.Context, address string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
+ options := append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
+ conn, err := grpc.DialContext(ctx, cd.resolverDirect.Scheme()+":///"+address, options...)
+
+ if err != nil {
+ return nil, err
+ }
+ return conn, nil
+}
+func (cd *ConnDirect) dialServiceWithoutResolver(ctx context.Context, address string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
+ options := append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
+ conn, err := grpc.DialContext(ctx, address, options...)
+
+ if err != nil {
+ return nil, err
+ }
+ return conn, nil
+}
diff --git a/pkg/common/discoveryregister/discoveryregister.go b/pkg/common/discoveryregister/discoveryregister.go
index c14323027..76c8fb267 100644
--- a/pkg/common/discoveryregister/discoveryregister.go
+++ b/pkg/common/discoveryregister/discoveryregister.go
@@ -16,6 +16,7 @@ package discoveryregister
import (
"errors"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/direct"
"os"
"github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/kubernetes"
@@ -36,6 +37,8 @@ func NewDiscoveryRegister(envType string) (discoveryregistry.SvcDiscoveryRegistr
return zookeeper.NewZookeeperDiscoveryRegister()
case "k8s":
return kubernetes.NewK8sDiscoveryRegister()
+ case "direct":
+ return direct.NewConnDirect()
default:
return nil, errors.New("envType not correct")
}
diff --git a/pkg/common/discoveryregister/discoveryregister_test.go b/pkg/common/discoveryregister/discoveryregister_test.go
index d83da1285..5317db5c6 100644
--- a/pkg/common/discoveryregister/discoveryregister_test.go
+++ b/pkg/common/discoveryregister/discoveryregister_test.go
@@ -40,6 +40,7 @@ func TestNewDiscoveryRegister(t *testing.T) {
}{
{"zookeeper", false, true},
{"k8s", false, true}, // 假设 k8s 配置也已正确设置
+ {"direct", false, true},
{"invalid", true, false},
}
diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go
index f27ebc805..7c40399a3 100644
--- a/pkg/common/discoveryregister/kubernetes/kubernetes.go
+++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go
@@ -132,20 +132,40 @@ func getMsgGatewayHost(ctx context.Context) []string {
// GetConns returns the gRPC client connections to the specified service.
func (cli *K8sDR) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
+ // This conditional checks if the serviceName is not the OpenImMessageGatewayName.
+ // It seems to handle a special case for the OpenImMessageGateway.
if serviceName != config.Config.RpcRegisterName.OpenImMessageGatewayName {
+ // DialContext creates a client connection to the given target (serviceName) using the specified context.
+ // 'cli.options' are likely default or common options for all connections in this struct.
+ // 'opts...' allows for additional gRPC dial options to be passed and used.
conn, err := grpc.DialContext(ctx, serviceName, append(cli.options, opts...)...)
+
+ // The function returns a slice of client connections with the new connection, or an error if occurred.
return []*grpc.ClientConn{conn}, err
} else {
+ // This block is executed if the serviceName is OpenImMessageGatewayName.
+ // 'ret' will accumulate the connections to return.
var ret []*grpc.ClientConn
+
+ // getMsgGatewayHost presumably retrieves hosts for the message gateway service.
+ // The context is passed, likely for cancellation and timeout control.
gatewayHosts := getMsgGatewayHost(ctx)
+
+ // Iterating over the retrieved gateway hosts.
for _, host := range gatewayHosts {
+ // Establishes a connection to each host.
+ // Again, appending cli.options with any additional opts provided.
conn, err := grpc.DialContext(ctx, host, append(cli.options, opts...)...)
+
+ // If there's an error while dialing any host, the function returns immediately with the error.
if err != nil {
return nil, err
} else {
+ // If the connection is successful, it is added to the 'ret' slice.
ret = append(ret, conn)
}
}
+ // After all hosts are processed, the slice of connections is returned.
return ret, nil
}
}
diff --git a/pkg/common/startrpc/start.go b/pkg/common/startrpc/start.go
index 01076bbbb..8295404d3 100644
--- a/pkg/common/startrpc/start.go
+++ b/pkg/common/startrpc/start.go
@@ -71,7 +71,7 @@ func Start(
}
defer client.Close()
- client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
+ client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
registerIP, err := network.GetRpcRegisterIP(config.Config.Rpc.RegisterIP)
if err != nil {
return err
From e2650add402d9377cc0f8a5246d5dabcced73de0 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Fri, 26 Jan 2024 20:53:25 +0800
Subject: [PATCH 082/110] feat: Enhanced Automation for OpenIM Advanced CICD
and GitOps Support (#1819)
* feat: add advanced version cicd
* fix: fix openim server deployment
---
build/images/openim-rpc-encryption/Dockerfile | 45 +++++++++++++++++++
build/images/openim-rpc-extend-msg/Dockerfile | 45 +++++++++++++++++++
scripts/install-im-server.sh | 9 ++--
scripts/lib/release.sh | 5 ++-
scripts/make-rules/image.mk | 3 +-
scripts/release.sh | 2 +-
6 files changed, 102 insertions(+), 7 deletions(-)
create mode 100644 build/images/openim-rpc-encryption/Dockerfile
create mode 100644 build/images/openim-rpc-extend-msg/Dockerfile
diff --git a/build/images/openim-rpc-encryption/Dockerfile b/build/images/openim-rpc-encryption/Dockerfile
new file mode 100644
index 000000000..e3f232eaf
--- /dev/null
+++ b/build/images/openim-rpc-encryption/Dockerfile
@@ -0,0 +1,45 @@
+# 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.
+
+# OpenIM base image: https://github.com/openim-sigs/openim-base-image
+
+# Set go mod installation source and proxy
+
+FROM golang:1.20 AS builder
+
+ARG GO111MODULE=on
+ARG GOPROXY=https://goproxy.cn,direct
+
+WORKDIR /openim/openim-server
+
+ENV GO111MODULE=$GO111MODULE
+ENV GOPROXY=$GOPROXY
+
+COPY go.mod go.sum ./
+RUN go mod download
+
+COPY . .
+
+RUN make build BINS=openim-rpc-encryption
+
+RUN cp /openim/openim-server/_output/bin/platforms/$(go env GOOS)/$(go env GOARCH)/openim-rpc-encryption /usr/bin/openim-rpc-encryption
+
+# FROM ghcr.io/openim-sigs/openim-bash-image:latest
+FROM ghcr.io/openim-sigs/openim-bash-image:latest
+
+WORKDIR /openim/openim-server
+
+COPY --from=builder /usr/bin/openim-rpc-encryption ./bin/openim-rpc-encryption
+
+ENTRYPOINT ["./bin/openim-rpc-encryption"]
\ No newline at end of file
diff --git a/build/images/openim-rpc-extend-msg/Dockerfile b/build/images/openim-rpc-extend-msg/Dockerfile
new file mode 100644
index 000000000..3ed94019b
--- /dev/null
+++ b/build/images/openim-rpc-extend-msg/Dockerfile
@@ -0,0 +1,45 @@
+# 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.
+
+# OpenIM base image: https://github.com/openim-sigs/openim-base-image
+
+# Set go mod installation source and proxy
+
+FROM golang:1.20 AS builder
+
+ARG GO111MODULE=on
+ARG GOPROXY=https://goproxy.cn,direct
+
+WORKDIR /openim/openim-server
+
+ENV GO111MODULE=$GO111MODULE
+ENV GOPROXY=$GOPROXY
+
+COPY go.mod go.sum ./
+RUN go mod download
+
+COPY . .
+
+RUN make build BINS=openim-rpc-extend-msg
+
+RUN cp /openim/openim-server/_output/bin/platforms/$(go env GOOS)/$(go env GOARCH)/openim-rpc-extend-msg /usr/bin/openim-rpc-extend-msg
+
+# FROM ghcr.io/openim-sigs/openim-bash-image:latest
+FROM ghcr.io/openim-sigs/openim-bash-image:latest
+
+WORKDIR /openim/openim-server
+
+COPY --from=builder /usr/bin/openim-rpc-extend-msg ./bin/openim-rpc-extend-msg
+
+ENTRYPOINT ["./bin/openim-rpc-extend-msg"]
\ No newline at end of file
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index 9588032d7..c1224e30c 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -69,17 +69,18 @@ ${DOCKER_COMPOSE_COMMAND} up -d
check_containers() {
if ! ${DOCKER_COMPOSE_COMMAND} ps | grep -q 'Up'; then
echo "Error: One or more docker containers failed to start."
- ${DOCKER_COMPOSE_COMMAND} logs
+ ${DOCKER_COMPOSE_COMMAND} logs openim-server
+ ${DOCKER_COMPOSE_COMMAND} logs openim-chat
return 1
fi
return 0
}
# Wait for a short period to allow containers to initialize
-sleep 30
-check_containers
+sleep 100
-${DOCKER_COMPOSE_COMMAND} logs openim-server
${DOCKER_COMPOSE_COMMAND} ps
+check_containers
+
popd
\ No newline at end of file
diff --git a/scripts/lib/release.sh b/scripts/lib/release.sh
index 2a525f12c..521e5cedc 100755
--- a/scripts/lib/release.sh
+++ b/scripts/lib/release.sh
@@ -25,6 +25,7 @@
readonly BUCKET="openim-1306374445"
readonly REGION="ap-guangzhou"
readonly COS_RELEASE_DIR="openim-release"
+# readonly COS_RELEASE_DIR="openim-advanced-release" # !pro
# default cos command tool coscli or coscmd
readonly COSTOOL="coscli"
@@ -37,9 +38,11 @@ readonly RELEASE_IMAGES="${LOCAL_OUTPUT_ROOT}/release-images"
# OpenIM github account info
readonly OPENIM_GITHUB_ORG=openimsdk
readonly OPENIM_GITHUB_REPO=open-im-server
-readonly CHAT_GITHUB_REPO=chat
+# readonly OPENIM_GITHUB_REPO=open-im-server-enterprise # !pro
readonly ARTIFACT=openim.tar.gz
+# readonly ARTIFACT=openim-enterprise.tar.gz # !pro
+
readonly CHECKSUM=${ARTIFACT}.sha1sum
OPENIM_BUILD_CONFORMANCE=${OPENIM_BUILD_CONFORMANCE:-y}
diff --git a/scripts/make-rules/image.mk b/scripts/make-rules/image.mk
index 14a4b2c31..eaec4a127 100644
--- a/scripts/make-rules/image.mk
+++ b/scripts/make-rules/image.mk
@@ -45,7 +45,8 @@ endif
IMAGES_DIR ?= $(wildcard ${ROOT_DIR}/build/images/*)
# Determine images names by stripping out the dir names, and filter out the undesired directories
# IMAGES ?= $(filter-out Dockerfile,$(foreach image,${IMAGES_DIR},$(notdir ${image})))
-IMAGES ?= $(filter-out Dockerfile openim-tools openim-cmdutils,$(foreach image,${IMAGES_DIR},$(notdir ${image})))
+IMAGES ?= $(filter-out Dockerfile openim-tools openim-rpc-extend-msg openim-rpc-encryption openim-cmdutils,$(foreach image,${IMAGES_DIR},$(notdir ${image})))
+# IMAGES ?= $(filter-out Dockerfile openim-tools openim-cmdutils,$(foreach image,${IMAGES_DIR},$(notdir ${image}))) # !pro
ifeq (${IMAGES},)
$(error Could not determine IMAGES, set ROOT_DIR or run in source dir)
diff --git a/scripts/release.sh b/scripts/release.sh
index 4984b2166..a34d5ee22 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -130,7 +130,7 @@ perform_action() {
if [ "$flag" == true ]; then
openim::log::info "## $message..."
- if ! $command; then
+ if ! eval "$command"; then
openim::log::errexit "Error in $message"
fi
fi
From c86df88b59157cc52cc87add2d4a5b4eaeb18d7f Mon Sep 17 00:00:00 2001
From: chao <48119764+withchao@users.noreply.github.com>
Date: Fri, 26 Jan 2024 20:55:37 +0800
Subject: [PATCH 083/110] fix: conversation aggregate find error (#1822)
* fix: GroupApplicationAcceptedNotification
* fix: GroupApplicationAcceptedNotification
* fix: NotificationUserInfoUpdate
* cicd: robot automated Change
* fix: conversation aggregate find error
---------
Co-authored-by: withchao
---
go.mod | 4 ++--
go.sum | 8 ++++----
pkg/common/db/mgo/conversation.go | 3 ++-
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/go.mod b/go.mod
index fdc6a58de..c709e9ba4 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
github.com/OpenIMSDK/protocol v0.0.48
- github.com/OpenIMSDK/tools v0.0.28
+ github.com/OpenIMSDK/tools v0.0.29
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
@@ -127,7 +127,7 @@ require (
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.opencensus.io v0.24.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
- go.uber.org/multierr v1.6.0 // indirect
+ go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
diff --git a/go.sum b/go.sum
index 5539b41fc..b7b40632f 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,8 @@ github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
github.com/OpenIMSDK/protocol v0.0.48 h1:8MIMjyzJRsruYhVv2ZKArFiOveroaofDOb3dlAdgjsw=
github.com/OpenIMSDK/protocol v0.0.48/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.28 h1:UT0rN1ysCFvsxQXyuxAj2TEkHt4C/sUezy+ChKpgt2Y=
-github.com/OpenIMSDK/tools v0.0.28/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/OpenIMSDK/tools v0.0.29 h1:NS4PEwYl9sX3SWsMjDOLVxMo3LcTWREMr+2cjzWjcqc=
+github.com/OpenIMSDK/tools v0.0.29/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
@@ -356,8 +356,8 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
-go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
-go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
diff --git a/pkg/common/db/mgo/conversation.go b/pkg/common/db/mgo/conversation.go
index bf5d1a145..1614cfec5 100644
--- a/pkg/common/db/mgo/conversation.go
+++ b/pkg/common/db/mgo/conversation.go
@@ -114,7 +114,8 @@ func (c *ConversationMgo) GetAllConversationIDs(ctx context.Context) ([]string,
func (c *ConversationMgo) GetAllConversationIDsNumber(ctx context.Context) (int64, error) {
counts, err := mgoutil.Aggregate[int64](ctx, c.coll, []bson.M{
{"$group": bson.M{"_id": "$conversation_id"}},
- {"$project": bson.M{"_id": 0, "conversation_id": "$_id"}},
+ {"$group": bson.M{"_id": nil, "count": bson.M{"$sum": 1}}},
+ {"$project": bson.M{"_id": 0}},
})
if err != nil {
return 0, err
From e79532aa936ec31a63db9ddf1e5e11b0cb0f1732 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Sat, 27 Jan 2024 00:10:42 +0800
Subject: [PATCH 084/110] feat: add pull request set workflows (#1824)
* feat: add pull request set workflows
* Update pull-request.yml
---
.github/workflows/pull-request.yml | 39 +++++++++++++-----------------
1 file changed, 17 insertions(+), 22 deletions(-)
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index 828d30d7d..065bcfa8c 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -14,13 +14,8 @@
name: Github Pull Request
on:
- push:
- branches: [main]
- paths-ignore:
- - 'README.md'
- - 'CONTRIBUTING.md'
- - 'docs/**'
workflow_dispatch:
+ push:
schedule:
- cron: '0 2 * * *'
@@ -37,24 +32,18 @@ jobs:
with:
fetch-depth: 0
- - name: Get League branch Patch
- run: |
- git config user.name 'openimbot'
- git config user.email 'openimsdk@qq.com'
- BRANCH_NAME="auto-pr-$(date +'%Y%m%d%H%M%S')"
- git checkout -b $BRANCH_NAME
-
- uses: actions/setup-node@v4
- name: Setup Go
uses: actions/setup-go@v4
- name: Run go modules tidy
run: |
+ sudo apt-get install jq
sudo make tidy
sudo make tools.verify.go-gitlint
echo "Run go modules tidy successfully"
continue-on-error: true
- - name: Run go format
+ - name: Run go format and lint
run: |
sudo make format
echo "Run go format successfully"
@@ -69,7 +58,14 @@ jobs:
- name: Generate all necessary files, such as error code files
run: |
make generate
- echo "Generate all necessary files successfully"
+ ./scripts/init-config.sh --examples --force
+ echo "Generate all necessary files successfully"
+ continue-on-error: true
+
+ - name: Generate Vertions
+ run: |
+ latest_tag=$(git describe --tags `git rev-list --tags --max-count=1` | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
+ echo $latest_tag > pkg/common/config/version
continue-on-error: true
- name: Run unit test and get test coverage
@@ -90,13 +86,13 @@ jobs:
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
commit-message: "cicd: bump League Patch"
- author: kubbot
- signoff: false
- draft: false
- branch: ''
+ author: kubbot <3293172751ysy@gmail.com>
+ committer: kubbot <3293172751ysy@gmail.com>
+ # signoff: false
+ # draft: false
+ branch: "asf-auto-updates"
assignees: cubxxw
reviewers: cubxxw
- delete-branch: true
title: "Bump League Patch auto PR: $(date +'%Y%m%d')"
body: |
Review criteria:
@@ -105,8 +101,7 @@ jobs:
This is an automated PR. @ $(date +'%Y%m%d')
[workflow](https://github.com/openimsdk/open-im-server/blob/main/.github/workflows/pull-request.yml).
- base: main
labels: |
kind/documentation
enhancement
- report
\ No newline at end of file
+ report
From 19ffde31961cfc63efc1160846eca333961ec769 Mon Sep 17 00:00:00 2001
From: OpenIM Bot <124379614+kubbot@users.noreply.github.com>
Date: Sat, 27 Jan 2024 00:49:37 +0800
Subject: [PATCH 085/110] cicd: bump League Patch (#1825)
---
internal/rpc/user/user.go | 1 -
pkg/common/config/version | 2 +-
pkg/common/discoveryregister/direct/directResolver.go | 5 +++--
pkg/common/discoveryregister/direct/directconn.go | 4 +++-
pkg/common/discoveryregister/discoveryregister.go | 3 ++-
5 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 981e0ccc4..0be5f97f4 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -61,7 +61,6 @@ type userServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
-
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis()
if err != nil {
diff --git a/pkg/common/config/version b/pkg/common/config/version
index 4d0729e54..d5c0c9914 100644
--- a/pkg/common/config/version
+++ b/pkg/common/config/version
@@ -1 +1 @@
-v3.5.0
\ No newline at end of file
+3.5.1
diff --git a/pkg/common/discoveryregister/direct/directResolver.go b/pkg/common/discoveryregister/direct/directResolver.go
index 285f55112..d5482ab62 100644
--- a/pkg/common/discoveryregister/direct/directResolver.go
+++ b/pkg/common/discoveryregister/direct/directResolver.go
@@ -2,10 +2,11 @@ package direct
import (
"context"
- "github.com/OpenIMSDK/tools/log"
- "google.golang.org/grpc/resolver"
"math/rand"
"strings"
+
+ "github.com/OpenIMSDK/tools/log"
+ "google.golang.org/grpc/resolver"
)
const (
diff --git a/pkg/common/discoveryregister/direct/directconn.go b/pkg/common/discoveryregister/direct/directconn.go
index 3eaa6fa19..6589e3aba 100644
--- a/pkg/common/discoveryregister/direct/directconn.go
+++ b/pkg/common/discoveryregister/direct/directconn.go
@@ -4,10 +4,12 @@ import (
"context"
"errors"
"fmt"
+
"github.com/OpenIMSDK/tools/errs"
- config2 "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
+
+ config2 "github.com/openimsdk/open-im-server/v3/pkg/common/config"
)
type ServiceAddresses map[string][]int
diff --git a/pkg/common/discoveryregister/discoveryregister.go b/pkg/common/discoveryregister/discoveryregister.go
index 76c8fb267..23a9e3245 100644
--- a/pkg/common/discoveryregister/discoveryregister.go
+++ b/pkg/common/discoveryregister/discoveryregister.go
@@ -16,9 +16,10 @@ package discoveryregister
import (
"errors"
- "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/direct"
"os"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/direct"
+
"github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/kubernetes"
"github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/zookeeper"
From 7ef32bf8a0a6171f09fc1114d0f0f36b3c92f6c6 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Sat, 27 Jan 2024 00:50:11 +0800
Subject: [PATCH 086/110] [Auto PR] Bump League Patch in '"base branch' (#1827)
---
.github/workflows/pull-request.yml | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index 065bcfa8c..6f39c93b2 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -15,7 +15,6 @@
name: Github Pull Request
on:
workflow_dispatch:
- push:
schedule:
- cron: '0 2 * * *'
@@ -58,6 +57,13 @@ jobs:
- name: Generate all necessary files, such as error code files
run: |
make generate
+ echo "Generate all necessary files successfully"
+ continue-on-error: true
+
+ - name: make init
+ run: |
+ export OPENIM_IP=127.0.0.1
+ export LOG_STORAGE_LOCATION="../logs/"
./scripts/init-config.sh --examples --force
echo "Generate all necessary files successfully"
continue-on-error: true
@@ -76,7 +82,6 @@ jobs:
- name: OpenIM verify copyright
run: |
- sudo make verify-copyright
sudo make add-copyright
echo "OpenIM verify successfully"
continue-on-error: true
@@ -93,13 +98,19 @@ jobs:
branch: "asf-auto-updates"
assignees: cubxxw
reviewers: cubxxw
- title: "Bump League Patch auto PR: $(date +'%Y%m%d')"
+ title: "[Auto PR 🤖] Bump League Patch auto PR"
body: |
+ I am a PR generated by robot automation.
+
Review criteria:
- [ ] Disenchanter can connect and issue actions
+
+ Github Actions Status:
+
+ [](https://github.com/openimsdk/open-im-server/actions/workflows/pull-request.yml)
- This is an automated PR. @ $(date +'%Y%m%d')
+ This is an automated PR.
[workflow](https://github.com/openimsdk/open-im-server/blob/main/.github/workflows/pull-request.yml).
labels: |
kind/documentation
From 1d5732c97e3f86789d82ee2816c42b0f2ccf506c Mon Sep 17 00:00:00 2001
From: OpenIM Bot <124379614+kubbot@users.noreply.github.com>
Date: Sat, 27 Jan 2024 10:50:25 +0800
Subject: [PATCH 087/110] cicd: bump League Patch (#1828)
---
.../discoveryregister/direct/directResolver.go | 14 ++++++++++++++
pkg/common/discoveryregister/direct/directconn.go | 14 ++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/pkg/common/discoveryregister/direct/directResolver.go b/pkg/common/discoveryregister/direct/directResolver.go
index d5482ab62..a706ce5e4 100644
--- a/pkg/common/discoveryregister/direct/directResolver.go
+++ b/pkg/common/discoveryregister/direct/directResolver.go
@@ -1,3 +1,17 @@
+// Copyright © 2024 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package direct
import (
diff --git a/pkg/common/discoveryregister/direct/directconn.go b/pkg/common/discoveryregister/direct/directconn.go
index 6589e3aba..84f173ea6 100644
--- a/pkg/common/discoveryregister/direct/directconn.go
+++ b/pkg/common/discoveryregister/direct/directconn.go
@@ -1,3 +1,17 @@
+// Copyright © 2024 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package direct
import (
From b14c0475d28bb192e5764c64757c2c4f677f6c80 Mon Sep 17 00:00:00 2001
From: a3d21 <93191329+a3d21@users.noreply.github.com>
Date: Sat, 27 Jan 2024 10:52:13 +0800
Subject: [PATCH 088/110] fix duplicated offline push (#1816)
---
internal/push/push_to_client.go | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go
index 72deb720d..caa39e618 100644
--- a/internal/push/push_to_client.go
+++ b/internal/push/push_to_client.go
@@ -118,18 +118,25 @@ func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.Msg
return nil
}
- for _, v := range wsResults {
- if !v.OnlinePush && msg.SendID == v.UserID {
- if err = callbackOfflinePush(ctx, userIDs, msg, &[]string{}); err != nil {
- return err
- }
+ if len(wsResults) == 0 {
+ return nil
+ }
+ onlinePushSuccUserIDSet := utils.SliceSet(utils.Filter(wsResults, func(e *msggateway.SingleMsgToUserResults) (string, bool) {
+ return e.UserID, e.OnlinePush && e.UserID != ""
+ }))
+ offlinePushUserIDList := utils.Filter(wsResults, func(e *msggateway.SingleMsgToUserResults) (string, bool) {
+ _, exist := onlinePushSuccUserIDSet[e.UserID]
+ return e.UserID, !exist && e.UserID != "" && e.UserID != msg.SendID
+ })
- err = p.offlinePushMsg(ctx, msg.SendID, msg, []string{v.UserID})
- if err != nil {
- return err
- }
+ if len(offlinePushUserIDList) > 0 {
+ if err = callbackOfflinePush(ctx, offlinePushUserIDList, msg, &[]string{}); err != nil {
+ return err
+ }
+ err = p.offlinePushMsg(ctx, msg.SendID, msg, offlinePushUserIDList)
+ if err != nil {
+ return err
}
-
}
return nil
}
From 34551a82a2fb8e35931b0e9cd0011b6aa2d134e3 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sun, 28 Jan 2024 18:30:51 +0800
Subject: [PATCH 089/110] chore(deps): bump golang.org/x/crypto in
/tools/data-conversion (#1580)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.16.0...v0.17.0)
---
updated-dependencies:
- dependency-name: golang.org/x/crypto
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
tools/data-conversion/go.mod | 2 +-
tools/data-conversion/go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/data-conversion/go.mod b/tools/data-conversion/go.mod
index 37d1776c2..963755923 100644
--- a/tools/data-conversion/go.mod
+++ b/tools/data-conversion/go.mod
@@ -63,7 +63,7 @@ require (
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/arch v0.3.0 // indirect
- golang.org/x/crypto v0.16.0 // indirect
+ golang.org/x/crypto v0.17.0 // indirect
golang.org/x/image v0.13.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
diff --git a/tools/data-conversion/go.sum b/tools/data-conversion/go.sum
index 66f85785b..d6dc23742 100644
--- a/tools/data-conversion/go.sum
+++ b/tools/data-conversion/go.sum
@@ -146,8 +146,8 @@ golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
-golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
-golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
+golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg=
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
From f94d8af737439e9c6ec2b5c937e430eb970bff5d Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sun, 28 Jan 2024 18:32:34 +0800
Subject: [PATCH 090/110] chore(deps): bump google.golang.org/grpc in
/tools/url2im (#1283)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.56.2 to 1.56.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.56.2...v1.56.3)
---
updated-dependencies:
- dependency-name: google.golang.org/grpc
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
tools/url2im/go.mod | 2 +-
tools/url2im/go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/url2im/go.mod b/tools/url2im/go.mod
index 236af91c7..b6011909d 100644
--- a/tools/url2im/go.mod
+++ b/tools/url2im/go.mod
@@ -15,6 +15,6 @@ require (
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
- google.golang.org/grpc v1.56.2 // indirect
+ google.golang.org/grpc v1.56.3 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
diff --git a/tools/url2im/go.sum b/tools/url2im/go.sum
index 071d9c3aa..1970dce2c 100644
--- a/tools/url2im/go.sum
+++ b/tools/url2im/go.sum
@@ -24,8 +24,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
-google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI=
-google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
+google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
+google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
From 32cd79044bbdd00ff28eea1272ea46c9c528038f Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Mon, 29 Jan 2024 19:57:37 +0800
Subject: [PATCH 091/110] feat: del the manager configure and it's
initializestatement (#1830)
* fix: del the manager config and manger init statement
* fix: fix the Manger judge condition
* fix: fix revokeMsg error
* fix: find erors
* fix: find error
* fix: fix the AdminAccount error
* fix: del the debug statement
---
deployments/templates/config.yaml | 7 ++++---
docs/contrib/environment.md | 6 ------
internal/push/push_to_client.go | 3 +++
internal/rpc/msg/revoke.go | 9 ++++++++-
internal/rpc/msg/verify.go | 10 ++++++++--
internal/rpc/user/user.go | 6 ------
pkg/authverify/token.go | 11 +++++------
scripts/install/environment.sh | 6 ------
8 files changed, 28 insertions(+), 30 deletions(-)
diff --git a/deployments/templates/config.yaml b/deployments/templates/config.yaml
index 82f76597c..cc318adcd 100644
--- a/deployments/templates/config.yaml
+++ b/deployments/templates/config.yaml
@@ -243,9 +243,10 @@ push:
#
# Built-in app manager user IDs
# Built-in app manager nicknames
+# Attention, this configure is discarded. If you have used him before, configure your own
manager:
- userID: [ "${MANAGER_USERID_1}", "${MANAGER_USERID_2}", "${MANAGER_USERID_3}" ]
- nickname: [ "${NICKNAME_1}", "${NICKNAME_2}", "${NICKNAME_3}" ]
+ userID:
+ nickname:
# chatAdmin, use for send notification
#
@@ -329,7 +330,7 @@ callback:
timeout: ${CALLBACK_TIMEOUT}
failedContinue: ${CALLBACK_FAILED_CONTINUE}
afterSendSingleMsg:
- enable: true
+ enable: ${CALLBACK_ENABLE}
timeout: ${CALLBACK_TIMEOUT}
failedContinue: ${CALLBACK_FAILED_CONTINUE}
beforeSendGroupMsg:
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index 366a1d94f..fb696eb54 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -477,12 +477,6 @@ This section involves setting up additional configuration variables for Websocke
| JPNS_MASTER_SECRET | [User Defined] | JPNS Master Secret |
| JPNS_PUSH_URL | [User Defined] | JPNS Push Notification URL |
| JPNS_PUSH_INTENT | [User Defined] | JPNS Push Intent |
-| MANAGER_USERID_1 | "openIM123456" | Administrator ID 1 |
-| MANAGER_USERID_2 | "openIM654321" | Administrator ID 2 |
-| MANAGER_USERID_3 | "openIMAdmin" | Administrator ID 3 |
-| NICKNAME_1 | "system1" | Nickname 1 |
-| NICKNAME_2 | "system2" | Nickname 2 |
-| NICKNAME_3 | "system3" | Nickname 3 |
| IM_ADMIN_USERID | "imAdmin" | IM Administrator ID |
| IM_ADMIN_NAME | "imAdmin" | IM Administrator Nickname |
| MULTILOGIN_POLICY | "1" | Multi-login Policy |
diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go
index caa39e618..5fce34e83 100644
--- a/internal/push/push_to_client.go
+++ b/internal/push/push_to_client.go
@@ -238,6 +238,9 @@ func (p *Pusher) Push2SuperGroup(ctx context.Context, groupID string, msg *sdkws
if len(config.Config.Manager.UserID) > 0 {
ctx = mcontext.WithOpUserIDContext(ctx, config.Config.Manager.UserID[0])
}
+ if len(config.Config.Manager.UserID) == 0 && len(config.Config.IMAdmin.UserID) > 0 {
+ ctx = mcontext.WithOpUserIDContext(ctx, config.Config.IMAdmin.UserID[0])
+ }
defer func(groupID string) {
if err = p.groupRpcClient.DismissGroup(ctx, groupID); err != nil {
log.ZError(ctx, "DismissGroup Notification clear members", err, "groupID", groupID)
diff --git a/internal/rpc/msg/revoke.go b/internal/rpc/msg/revoke.go
index d7362d339..0a24753b2 100644
--- a/internal/rpc/msg/revoke.go
+++ b/internal/rpc/msg/revoke.go
@@ -111,6 +111,13 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
return nil, err
}
revokerUserID := mcontext.GetOpUserID(ctx)
+ var flag bool
+ if len(config.Config.Manager.UserID) > 0 {
+ flag = utils.Contain(revokerUserID, config.Config.Manager.UserID...)
+ }
+ if len(config.Config.Manager.UserID) == 0 && len(config.Config.IMAdmin.UserID) > 0 {
+ flag = utils.Contain(revokerUserID, config.Config.IMAdmin.UserID...)
+ }
tips := sdkws.RevokeMsgTips{
RevokerUserID: revokerUserID,
ClientMsgID: msgs[0].ClientMsgID,
@@ -118,7 +125,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
Seq: req.Seq,
SesstionType: msgs[0].SessionType,
ConversationID: req.ConversationID,
- IsAdminRevoke: utils.Contain(revokerUserID, config.Config.Manager.UserID...),
+ IsAdminRevoke: flag,
}
var recvID string
if msgs[0].SessionType == constant.SuperGroupChatType {
diff --git a/internal/rpc/msg/verify.go b/internal/rpc/msg/verify.go
index 2837cb944..0080b6fdb 100644
--- a/internal/rpc/msg/verify.go
+++ b/internal/rpc/msg/verify.go
@@ -51,7 +51,10 @@ type MessageRevoked struct {
func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgReq) error {
switch data.MsgData.SessionType {
case constant.SingleChatType:
- if utils.IsContain(data.MsgData.SendID, config.Config.Manager.UserID) {
+ if len(config.Config.Manager.UserID) > 0 && utils.IsContain(data.MsgData.SendID, config.Config.Manager.UserID) {
+ return nil
+ }
+ if utils.IsContain(data.MsgData.SendID, config.Config.IMAdmin.UserID) {
return nil
}
if data.MsgData.ContentType <= constant.NotificationEnd &&
@@ -88,7 +91,10 @@ func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgRe
if groupInfo.GroupType == constant.SuperGroup {
return nil
}
- if utils.IsContain(data.MsgData.SendID, config.Config.Manager.UserID) {
+ if len(config.Config.Manager.UserID) > 0 && utils.IsContain(data.MsgData.SendID, config.Config.Manager.UserID) {
+ return nil
+ }
+ if utils.IsContain(data.MsgData.SendID, config.Config.IMAdmin.UserID) {
return nil
}
if data.MsgData.ContentType <= constant.NotificationEnd &&
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 0be5f97f4..e5567f436 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -71,12 +71,6 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
return err
}
users := make([]*tablerelation.UserModel, 0)
- if len(config.Config.Manager.UserID) != len(config.Config.Manager.Nickname) {
- return errors.New("len(config.Config.Manager.AppManagerUid) != len(config.Config.Manager.Nickname)")
- }
- for k, v := range config.Config.Manager.UserID {
- users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.Manager.Nickname[k], AppMangerLevel: constant.AppAdmin})
- }
if len(config.Config.IMAdmin.UserID) != len(config.Config.IMAdmin.Nickname) {
return errors.New("len(config.Config.AppNotificationAdmin.AppManagerUid) != len(config.Config.AppNotificationAdmin.Nickname)")
}
diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go
index 4c71224ee..224693f85 100644
--- a/pkg/authverify/token.go
+++ b/pkg/authverify/token.go
@@ -17,7 +17,6 @@ package authverify
import (
"context"
"fmt"
-
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/tokenverify"
@@ -35,7 +34,7 @@ func Secret() jwt.Keyfunc {
func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
opUserID := mcontext.GetOpUserID(ctx)
- if utils.IsContain(opUserID, config.Config.Manager.UserID) {
+ if len(config.Config.Manager.UserID) > 0 && utils.IsContain(opUserID, config.Config.Manager.UserID) {
return nil
}
if utils.IsContain(opUserID, config.Config.IMAdmin.UserID) {
@@ -48,11 +47,11 @@ func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
}
func IsAppManagerUid(ctx context.Context) bool {
- return utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) || utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID)
+ return (len(config.Config.Manager.UserID) > 0 && utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID)) || utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID)
}
func CheckAdmin(ctx context.Context) error {
- if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) {
+ if len(config.Config.Manager.UserID) > 0 && utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) {
return nil
}
if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID) {
@@ -64,7 +63,7 @@ func CheckIMAdmin(ctx context.Context) error {
if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID) {
return nil
}
- if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) {
+ if len(config.Config.Manager.UserID) > 0 && utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) {
return nil
}
return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not CheckIMAdmin userID", mcontext.GetOpUserID(ctx)))
@@ -75,7 +74,7 @@ func ParseRedisInterfaceToken(redisToken any) (*tokenverify.Claims, error) {
}
func IsManagerUserID(opUserID string) bool {
- return utils.IsContain(opUserID, config.Config.Manager.UserID) || utils.IsContain(opUserID, config.Config.IMAdmin.UserID)
+ return (len(config.Config.Manager.UserID) > 0 && utils.IsContain(opUserID, config.Config.Manager.UserID)) || utils.IsContain(opUserID, config.Config.IMAdmin.UserID)
}
func WsVerifyToken(token, userID string, platformID int) error {
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index aeb4fcc36..b1d2354b9 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -349,12 +349,6 @@ def "JPNS_APP_KEY" "" # JPNS应用密钥
def "JPNS_MASTER_SECRET" "" # JPNS主密钥
def "JPNS_PUSH_URL" "" # JPNS推送URL
def "JPNS_PUSH_INTENT" "" # JPNS推送意图
-def "MANAGER_USERID_1" "openIM123456" # 管理员ID 1
-def "MANAGER_USERID_2" "openIM654321" # 管理员ID 2
-def "MANAGER_USERID_3" "openIMAdmin" # 管理员ID 3
-def "NICKNAME_1" "system1" # 昵称1
-def "NICKNAME_2" "system2" # 昵称2
-def "NICKNAME_3" "system3" # 昵称3
def "IM_ADMIN_USERID" "imAdmin" # IM管理员ID
def "IM_ADMIN_NAME" "imAdmin" # IM管理员昵称
def "MULTILOGIN_POLICY" "1" # 多登录策略
From bd9e50d9e08edc9d6a87fa8c443cf8f0bf825117 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Mon, 29 Jan 2024 19:58:19 +0800
Subject: [PATCH 092/110] fix(docker-compose): Update the env template to
uncomment the mongo port (#1833)
---
deployments/templates/env-template.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index 9b21c8c65..1044dd6bc 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -100,7 +100,7 @@ ZOOKEEPER_PORT=${ZOOKEEPER_PORT}
# MongoDB service port configuration.
# Default: MONGO_PORT=37017
-# MONGO_PORT=${MONGO_PORT}
+MONGO_PORT=${MONGO_PORT}
# Password for MongoDB admin user. Used for service authentication.
# Default: MONGO_PASSWORD=openIM123
From 0a245df2f8cf60f5fd0767c840dc66399a668f33 Mon Sep 17 00:00:00 2001
From: OpenIM Bot <124379614+kubbot@users.noreply.github.com>
Date: Wed, 31 Jan 2024 14:14:03 +0800
Subject: [PATCH 093/110] cicd: bump League Patch (#1837)
---
pkg/authverify/token.go | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go
index 224693f85..97bb03391 100644
--- a/pkg/authverify/token.go
+++ b/pkg/authverify/token.go
@@ -17,6 +17,7 @@ package authverify
import (
"context"
"fmt"
+
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/tokenverify"
@@ -47,7 +48,8 @@ func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
}
func IsAppManagerUid(ctx context.Context) bool {
- return (len(config.Config.Manager.UserID) > 0 && utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID)) || utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID)
+ return (len(config.Config.Manager.UserID) > 0 && utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID)) ||
+ utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID)
}
func CheckAdmin(ctx context.Context) error {
From 4ded2cffed2bd3abfb29e777e048c628d569294f Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Wed, 31 Jan 2024 14:16:09 +0800
Subject: [PATCH 094/110] Delete build/images/openim-rpc-extend-msg directory
(#1841)
---
build/images/openim-rpc-extend-msg/Dockerfile | 45 -------------------
1 file changed, 45 deletions(-)
delete mode 100644 build/images/openim-rpc-extend-msg/Dockerfile
diff --git a/build/images/openim-rpc-extend-msg/Dockerfile b/build/images/openim-rpc-extend-msg/Dockerfile
deleted file mode 100644
index 3ed94019b..000000000
--- a/build/images/openim-rpc-extend-msg/Dockerfile
+++ /dev/null
@@ -1,45 +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.
-
-# OpenIM base image: https://github.com/openim-sigs/openim-base-image
-
-# Set go mod installation source and proxy
-
-FROM golang:1.20 AS builder
-
-ARG GO111MODULE=on
-ARG GOPROXY=https://goproxy.cn,direct
-
-WORKDIR /openim/openim-server
-
-ENV GO111MODULE=$GO111MODULE
-ENV GOPROXY=$GOPROXY
-
-COPY go.mod go.sum ./
-RUN go mod download
-
-COPY . .
-
-RUN make build BINS=openim-rpc-extend-msg
-
-RUN cp /openim/openim-server/_output/bin/platforms/$(go env GOOS)/$(go env GOARCH)/openim-rpc-extend-msg /usr/bin/openim-rpc-extend-msg
-
-# FROM ghcr.io/openim-sigs/openim-bash-image:latest
-FROM ghcr.io/openim-sigs/openim-bash-image:latest
-
-WORKDIR /openim/openim-server
-
-COPY --from=builder /usr/bin/openim-rpc-extend-msg ./bin/openim-rpc-extend-msg
-
-ENTRYPOINT ["./bin/openim-rpc-extend-msg"]
\ No newline at end of file
From 18047859b8f46098b79189d04888845d12202ca1 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Wed, 31 Jan 2024 14:16:19 +0800
Subject: [PATCH 095/110] Delete build/images/openim-rpc-encryption directory
(#1842)
---
build/images/openim-rpc-encryption/Dockerfile | 45 -------------------
1 file changed, 45 deletions(-)
delete mode 100644 build/images/openim-rpc-encryption/Dockerfile
diff --git a/build/images/openim-rpc-encryption/Dockerfile b/build/images/openim-rpc-encryption/Dockerfile
deleted file mode 100644
index e3f232eaf..000000000
--- a/build/images/openim-rpc-encryption/Dockerfile
+++ /dev/null
@@ -1,45 +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.
-
-# OpenIM base image: https://github.com/openim-sigs/openim-base-image
-
-# Set go mod installation source and proxy
-
-FROM golang:1.20 AS builder
-
-ARG GO111MODULE=on
-ARG GOPROXY=https://goproxy.cn,direct
-
-WORKDIR /openim/openim-server
-
-ENV GO111MODULE=$GO111MODULE
-ENV GOPROXY=$GOPROXY
-
-COPY go.mod go.sum ./
-RUN go mod download
-
-COPY . .
-
-RUN make build BINS=openim-rpc-encryption
-
-RUN cp /openim/openim-server/_output/bin/platforms/$(go env GOOS)/$(go env GOARCH)/openim-rpc-encryption /usr/bin/openim-rpc-encryption
-
-# FROM ghcr.io/openim-sigs/openim-bash-image:latest
-FROM ghcr.io/openim-sigs/openim-bash-image:latest
-
-WORKDIR /openim/openim-server
-
-COPY --from=builder /usr/bin/openim-rpc-encryption ./bin/openim-rpc-encryption
-
-ENTRYPOINT ["./bin/openim-rpc-encryption"]
\ No newline at end of file
From c205013436b219c0ec629aec425bee23d10bce2f Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Wed, 31 Jan 2024 14:16:32 +0800
Subject: [PATCH 096/110] Update offline-deployment.md openim offine deployment
docs (#1843)
---
docs/contrib/offline-deployment.md | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/docs/contrib/offline-deployment.md b/docs/contrib/offline-deployment.md
index a96f82d4a..5e44318c4 100644
--- a/docs/contrib/offline-deployment.md
+++ b/docs/contrib/offline-deployment.md
@@ -1,5 +1,3 @@
-
-
# OpenIM Offline Deployment Design
## 1. Base Images
@@ -10,7 +8,7 @@ Below are the base images and their versions you'll need:
- [ ] redis:7.0.0
- [ ] mongo:6.0.2
- [ ] bitnami/zookeeper:3.8
-- [ ] minio/minio:latest
+- [ ] minio/minio:RELEASE.2024-01-11T07-46-16Z
> [!IMPORTANT]
> It is important to note that OpenIM removed mysql components from versions v3.5.0 (release-v3.5) and above, so mysql can be deployed without this requirement or above
@@ -22,10 +20,10 @@ OpenIM:
> [!TIP]
> If you need to install more IM components or monitoring products [images.md](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md)
-- [ ] ghcr.io/openimsdk/openim-web:latest
-- [ ] ghcr.io/openimsdk/openim-admin:latest
-- [ ] ghcr.io/openimsdk/openim-chat:latest
-- [ ] ghcr.io/openimsdk/openim-server:latest
+- [ ] ghcr.io/openimsdk/openim-web:
+- [ ] ghcr.io/openimsdk/openim-admin:
+- [ ] ghcr.io/openimsdk/openim-chat:
+- [ ] ghcr.io/openimsdk/openim-server:
Monitoring:
@@ -42,9 +40,9 @@ Use the following commands to pull these base images:
docker pull bitnami/kafka:3.5.1
docker pull redis:7.0.0
docker pull mongo:6.0.2
-docker pull mysql:5.7
+docker pull mariadb:10.6
docker pull bitnami/zookeeper:3.8
-docker pull minio/minio:latest
+docker pull minio/minio:2024-01-11T07-46-16Z
```
If you need to install more IM components or monitoring products:
@@ -177,4 +175,4 @@ docker compose ps # Verify
- [openimsdk Issue #432](https://github.com/openimsdk/open-im-server/issues/432)
- [Notion Link](https://nsddd.notion.site/435ee747c0bc44048da9300a2d745ad3?pvs=25)
-- [openimsdk Issue #474](https://github.com/openimsdk/open-im-server/issues/474)
\ No newline at end of file
+- [openimsdk Issue #474](https://github.com/openimsdk/open-im-server/issues/474)
From 42a3084a6f6dadc7097906b76d6d9cc7b4523c94 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Wed, 31 Jan 2024 17:58:24 +0800
Subject: [PATCH 097/110] Update environment.md fix environment mongo username
(#1847)
---
docs/contrib/environment.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index fb696eb54..e18246afa 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -311,7 +311,7 @@ This section involves setting up MongoDB, including its port, address, and crede
| MONGO_ADDRESS | [Generated IP] | IP address for MongoDB. |
| MONGO_USERNAME | [User Defined] | Admin Username for MongoDB. |
| MONGO_PASSWORD | [User Defined] | Admin Password for MongoDB. |
-| MONGO_OPENIM_PASSWORD | [User Defined] | OpenIM Username for MongoDB. |
+| MONGO_OPENIM_USERNAME | [User Defined] | OpenIM Username for MongoDB. |
| MONGO_OPENIM_PASSWORD | [User Defined] | OpenIM Password for MongoDB. |
### 2.8. Tencent Cloud COS Configuration
From 4c0121849d8240c471a1eb2a18e56d046ff506dd Mon Sep 17 00:00:00 2001
From: Seal Bell <495950007@qq.com>
Date: Thu, 1 Feb 2024 09:38:21 +0800
Subject: [PATCH 098/110] docs:Add multi-language README.md in ./docs/ file
(#1852)
* Add Simplified Chinese README.md
* Add Ukrainian README.md
* Add Traditional Chinese README.md
* Add Czech README.md
* Add Hungarian README.md
* Add spanish README.md
* Add Persian README.md
* Add French README.md
* Add German README.md
* Add Japanese README.md
* Add Polish README.md
* Add Indonesian README.md
* Add Finnish README.md
* Add Malayalam README.md
* Add Dutch README.md
* Add Italian README.md
* Add Russian README.md
* Added Brazilian Portuguese README.md
* Add Esperanto README.md
* Add Korean README.md
* Add Vietnamese README.md
* Add Arabic README.md
* Add Danish README.md
* Add Greek README.md
* Add Turkish README.md
---
docs/README_ar.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_cs.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_da.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_de.md | 66 +++++++++++++++++++++++++++++++++++++++++++
docs/README_el.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_eo.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_es.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_fa.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_fi.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_fr.md | 66 +++++++++++++++++++++++++++++++++++++++++++
docs/README_hu.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_id.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_it.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_ja.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_ko.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_ml.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_nl.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_pl.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_pt_BR.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_ru.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_tr.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_ua.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_vi.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_zh_CN.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
docs/README_zh_TW.md | 67 ++++++++++++++++++++++++++++++++++++++++++++
25 files changed, 1673 insertions(+)
create mode 100644 docs/README_ar.md
create mode 100644 docs/README_cs.md
create mode 100644 docs/README_da.md
create mode 100644 docs/README_de.md
create mode 100644 docs/README_el.md
create mode 100644 docs/README_eo.md
create mode 100644 docs/README_es.md
create mode 100644 docs/README_fa.md
create mode 100644 docs/README_fi.md
create mode 100644 docs/README_fr.md
create mode 100644 docs/README_hu.md
create mode 100644 docs/README_id.md
create mode 100644 docs/README_it.md
create mode 100644 docs/README_ja.md
create mode 100644 docs/README_ko.md
create mode 100644 docs/README_ml.md
create mode 100644 docs/README_nl.md
create mode 100644 docs/README_pl.md
create mode 100644 docs/README_pt_BR.md
create mode 100644 docs/README_ru.md
create mode 100644 docs/README_tr.md
create mode 100644 docs/README_ua.md
create mode 100644 docs/README_vi.md
create mode 100644 docs/README_zh_CN.md
create mode 100644 docs/README_zh_TW.md
diff --git a/docs/README_ar.md b/docs/README_ar.md
new file mode 100644
index 000000000..bdd616e6a
--- /dev/null
+++ b/docs/README_ar.md
@@ -0,0 +1,67 @@
+# وثائق OpenIM Server
+
+مرحبًا بكم في مركز وثائق OpenIM! يوفر هذا المركز مجموعة شاملة من الأدلة والكتيبات التي صُممت لمساعدتك في الاستفادة القصوى من تجربة OpenIM الخاصة بك.
+
+## جدول المحتويات
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - إرشادات حول المساهمة والتكوينات للمطورين
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - اتفاقيات الكود، سياسات التسجيل، وأدوات التحويل الأخرى
+
+------
+
+## مساهمة
+
+هذا القسم يقدم للمطورين دليلاً مفصلاً حول كيفية المساهمة في الكود، إعداد بيئتهم، واتباع العمليات المرتبطة.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - قواعد واتفاقيات لكتابة الكود في OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - دليل حول كيفية القيام بالتطوير داخل OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - إرشادات حول عمليات اختيار الجيت.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - سير عمل الجيت في OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - إرشادات حول إعداد وتهيئة OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - كيفية تثبيت الدوكر على جهازك.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - دليل لإعداد بيئة التطوير على لينكس.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - إرشادات حول كيفية القيام ببعض الأعمال الشائعة محليًا.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - طرق توظيف OpenIM دون اتصال.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - دليل حول استخدام أدوات بروتوك.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - أدوات ومكتبات في OpenIM للغة Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - أفضل الممارسات والأدوات لملفات الصيانة.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - أفضل الممارسات والأدوات للسكربتات.
+
+## التحويلات
+
+يقدم هذا القسم مختلف الاتفاقيات والسياسات داخل OpenIM، التي تشمل الكود، السجلات، الإصدارات، والمزيد.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - إرشادات وطرق لتحويلات API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - سياسات واتفاقيات التسجيل في OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - إجراءات واتفاقيات لـ CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - اتفاقيات لالتزامات الكود في OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - هيكل الدليل واتفاقياته داخل OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - قائمة وأوصاف رموز الخطأ.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - اتفاقيات وتحويلات لكود Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - استراتيجيات إدارة صور الدوكر في OpenIM، تشمل عدة معماريات ومستودعات الصور.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - اتفاقيات أكثر تفصيلاً حول التسجيل.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - استراتيجيات التسمية والإدارة لإصدارات OpenIM.
+
+
+## للمطورين والمساهمين ومشرفي المجتمع
+
+### المطورون والمساهمون
+
+إذا كنت مطورًا أو شخصًا حريصًا على المساهمة:
+
+- تعرف على [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) و[Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) لضمان سلاسة المساهمات.
+- اغمر نفسك في [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) للتعرف على ممارسات التطوير في OpenIM.
+
+### مشرفو المجتمع
+
+كمشرف على المجتمع:
+
+- تأكد من أن المساهمات تتوافق مع المعايير الموضحة في وثائقنا.
+- راجع بانتظام [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) و[Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) للبقاء على اطلاع.
+
+## للمستخدمين
+
+يجب أن يولي المستخدمون اهتمامًا خاصًا لـ:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - ضروري إذا كنت تخطط لاستخدام صور الدوكر لـ OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - لفهم الصور المختلفة المتاحة وكيفية اختيار ال
diff --git a/docs/README_cs.md b/docs/README_cs.md
new file mode 100644
index 000000000..0c40b63b1
--- /dev/null
+++ b/docs/README_cs.md
@@ -0,0 +1,67 @@
+# Dokumenty serveru OpenIM
+
+Vítejte v centru dokumentace OpenIM! Toto centrum poskytuje komplexní řadu průvodců a manuálů navržených tak, aby vám pomohly co nejlépe využít vaše zkušenosti s OpenIM.
+
+## Obsah
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Pokyny pro přispívání a konfigurace pro vývojáře
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Konvence kódování, zásady protokolování a další transformační nástroje
+
+------
+
+## Contrib
+
+Tato část nabízí vývojářům podrobný návod, jak přispívat kódem, nastavovat prostředí a sledovat související procesy.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Pravidla a konvence pro psaní kódu v OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Návod, jak provádět vývoj v rámci OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Pokyny pro operace sběru třešní.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Pracovní postup git v OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Pokyny k nastavení a inicializaci OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Jak nainstalovat Docker na váš počítač.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Průvodce nastavením vývojového prostředí na Linuxu.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Pokyny k provádění určitých společných akcí na místní úrovni.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metody nasazení OpenIM offline.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Průvodce používáním protokolových nástrojů.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Nástroje a knihovny v OpenIM for Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Osvědčené postupy a nástroje pro Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Doporučené postupy a nástroje pro skripty.
+
+## Konverze
+
+Tato část představuje různé konvence a zásady v rámci OpenIM, zahrnující kód, protokoly, verze a další.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Pokyny a metody pro konverze API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Zásady a konvence protokolování v OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Postupy a konvence pro CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konvence pro odevzdání kódu v OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Struktura adresářů a konvence v rámci OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Seznam a popisy chybových kódů.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konvence a převody pro kód Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Strategie správy pro obrazy OpenIM Docker, zahrnující různé architektury a úložiště obrazů.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Další podrobné konvence o protokolování.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategie pojmenování a správy verzí OpenIM.
+
+
+## Pro vývojáře, přispěvatele a správce komunity
+
+### Vývojáři a přispěvatelé
+
+Pokud jste vývojář nebo někdo, kdo má zájem přispívat:
+
+- Seznamte se s našimi [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) a [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md), abyste zajistili hladké příspěvky.
+- Ponořte se do [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), abyste se seznámili s vývojovými postupy v OpenIM.
+
+### Správci komunity
+
+Jako správce komunity:
+
+- Zajistěte, aby příspěvky odpovídaly standardům uvedeným v naší dokumentaci.
+- Pravidelně kontrolujte [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) a [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) , abyste zůstali aktuální.
+
+## Pro uživatele
+
+Uživatelé by měli věnovat zvláštní pozornost:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Nezbytné, pokud plánujete používat obrazy OpenIM Docker.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Chcete-li porozumět různým dostupným obrázkům a jak vybrat ten správný pro vaši architekturu.
\ No newline at end of file
diff --git a/docs/README_da.md b/docs/README_da.md
new file mode 100644
index 000000000..d14c6adb5
--- /dev/null
+++ b/docs/README_da.md
@@ -0,0 +1,67 @@
+# OpenIM Server Dokumentation
+
+Velkommen til OpenIM Dokumentationscentret! Dette center indeholder en omfattende række vejledninger og manualer, der er designet til at hjælpe dig med at få mest muligt ud af din OpenIM-oplevelse.
+
+## Indholdsfortegnelse
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Vejledning om bidrag og konfigurationer for udviklere
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Kodningskonventioner, logningspolitikker og andre transformationsværktøjer
+
+------
+
+## Bidrag
+
+Denne sektion tilbyder udviklere en detaljeret vejledning om, hvordan de kan bidrage med kode, konfigurere deres miljø og følge de tilknyttede processer.
+
+- [Kodekonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regler og konventioner for at skrive kode i OpenIM.
+- [Udviklingsguide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - En guide om, hvordan man udfører udvikling inden for OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Retningslinjer for cherry-picking-operationer.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Git-workflowen i OpenIM.
+- [Initialiseringskonfigurationer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Vejledning om opsætning og initialisering af OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Sådan installeres Docker på din maskine.
+- [Linux Udviklingsmiljø](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guide til opsætning af udviklingsmiljøet på Linux.
+- [Lokale handlinger](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Retningslinjer for, hvordan man udfører visse almindelige handlinger lokalt.
+- [Offline-deploering](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metoder til at udrulle OpenIM offline.
+- [Protoc-værktøjer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guide til brug af protoc-værktøjer.
+- [Go-værktøjer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Værktøjer og biblioteker i OpenIM til Go.
+- [Makefile-værktøjer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Bedste praksis og værktøjer til Makefile.
+- [Scriptværktøjer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Bedste praksis og værktøjer til scripts.
+
+## Konverteringer
+
+Denne sektion introducerer forskellige konventioner og politikker inden for OpenIM, herunder kode, logfiler, versioner og meget mere.
+
+- [API-konverteringer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Retningslinjer og metoder til API-konverteringer.
+- [Logningspolitik](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Politikker og konventioner for logning i OpenIM.
+- [CI/CD-handlinger](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedurer og konventioner for CI/CD.
+- [Commit-konventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konventioner for kodeforpligtelser i OpenIM.
+- [Mappekonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Mappens struktur og konventioner inden for OpenIM.
+- [Fejlkoder](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Liste og beskrivelser af fejlkoder.
+- [Go-kodekonverteringer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konventioner og konverteringer for Go-kode.
+- [Docker Image-strategi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Styringsstrategier for OpenIM Docker-billeder, der dækker flere arkitekturer og billedarkiver.
+- [Logningskonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Yderligere detaljerede konventioner om logning.
+- [Versionkonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Navngivnings- og styringsstrategier for OpenIM-versioner.
+
+
+## For udviklere, bidragsydere og samfundsvedligeholdere
+
+### Udviklere og bidragsydere
+
+Hvis du er en udvikler eller nogen, der gerne vil bidrage:
+
+- Gør dig fortrolig med vores [Kodekonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) og [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) for at sikre en problemfri bidragelse.
+- Dyk ned i [Udviklingsguiden](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) for at få en idé om udviklingspraksis i OpenIM.
+
+### Samfundsvedligeholdere
+
+Som samfundsvedligeholder:
+
+- Sørg for, at bidrag stemmer overens med standarderne beskrevet i vores dokumentation.
+- Gennemgå regelmæssigt [Logningspolitikken](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) og [Fejlkoderne](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) for at holde dig opdateret.
+
+## For brugere
+
+Brugere bør være opmærksomme på følgende:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Nødvendigt, hvis du planlægger at bruge Docker-billeder af OpenIM.
+- [Docker Image-strategi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - For at forstå de forskellige tilgængelige billeder og hvordan man vælger det rigtige for din arkitektur.
diff --git a/docs/README_de.md b/docs/README_de.md
new file mode 100644
index 000000000..101eba41b
--- /dev/null
+++ b/docs/README_de.md
@@ -0,0 +1,66 @@
+# OpenIM-Serverdokumente
+
+Willkommen im OpenIM-Dokumentationshub! Dieses Zentrum bietet eine umfassende Auswahl an Leitfäden und Handbüchern, die Ihnen dabei helfen sollen, das Beste aus Ihrem OpenIM-Erlebnis herauszuholen.
+
+## Inhaltsverzeichnis
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Anleitung zu Beiträgen und Konfigurationen für Entwickler
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Codierungskonventionen, Protokollierungsrichtlinien und andere Transformationstools
+
+------
+
+## Beitrag
+
+Dieser Abschnitt bietet Entwicklern eine detaillierte Anleitung zum Beitragen von Code, zum Einrichten ihrer Umgebung und zum Befolgen der zugehörigen Prozesse.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regeln und Konventionen zum Schreiben von Code in OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Eine Anleitung zur Durchführung der Entwicklung innerhalb von OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Richtlinien zur Rosinenpickerei.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Der Git-Workflow in OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Anleitung zum Einrichten und Initialisieren von OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - So installieren Sie Docker auf Ihrem Computer.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Anleitung zum Einrichten der Entwicklungsumgebung unter Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Richtlinien zur Durchführung bestimmter allgemeiner Aktionen vor Ort.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Methoden zur Offline-Bereitstellung von OpenIM.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Anleitung zur Verwendung von Protokolltools.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Tools und Bibliotheken in OpenIM für Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Best Practices und Tools für Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Best Practices und Tools für Skripte.
+
+## Konvertierungen
+
+In diesem Abschnitt werden verschiedene Konventionen und Richtlinien innerhalb von OpenIM vorgestellt, die Code, Protokolle, Versionen und mehr umfassen.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Richtlinien und Methoden für API-Konvertierungen.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Protokollierungsrichtlinien und -konventionen in OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Verfahren und Konventionen für CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konventionen für Code-Commits in OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Verzeichnisstruktur und Konventionen innerhalb von OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Liste und Beschreibungen der Fehlercodes.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konventionen und Konvertierungen für Go-Code.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Verwaltungsstrategien für OpenIM-Docker-Images, die mehrere Architekturen und Image-Repositorys umfassen.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Weitere detaillierte Konventionen zur Protokollierung.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Benennungs- und Verwaltungsstrategien für OpenIM-Versionen.
+
+
+## Für Entwickler, Mitwirkende und Community-Betreuer
+
+### Entwickler und Mitwirkende
+
+Wenn Sie Entwickler sind oder gerne einen Beitrag leisten möchten:
+- Machen Sie sich mit unseren [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) und unserem [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) vertraut, um reibungslose Beiträge zu gewährleisten.
+- Tauchen Sie ein in den [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), um sich mit den Entwicklungspraktiken in OpenIM vertraut zu machen.
+
+### Community-Betreuer
+
+Als Community-Betreuer:
+
+- Stellen Sie sicher, dass die Beiträge den in unserer Dokumentation dargelegten Standards entsprechen.
+- Überprüfen Sie regelmäßig die [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) und die [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), um auf dem Laufenden zu bleiben.
+
+## Für Benutzer
+
+Benutzer sollten besonders auf Folgendes achten:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Erforderlich, wenn Sie Docker-Images von OpenIM verwenden möchten.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Um die verschiedenen verfügbaren Bilder zu verstehen und wie Sie das richtige für Ihre Architektur auswählen.
\ No newline at end of file
diff --git a/docs/README_el.md b/docs/README_el.md
new file mode 100644
index 000000000..68438628f
--- /dev/null
+++ b/docs/README_el.md
@@ -0,0 +1,67 @@
+# Έγγραφα διακομιστή OpenIM
+
+Καλώς ήρθατε στο κέντρο τεκμηρίωσης OpenIM! Αυτό το κέντρο παρέχει μια ολοκληρωμένη σειρά οδηγών και εγχειριδίων που έχουν σχεδιαστεί για να σας βοηθήσουν να αξιοποιήσετε στο έπακρο την εμπειρία σας στο OpenIM.
+
+## Πίνακας περιεχομένων
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Οδηγίες για τη συνεισφορά και τις διαμορφώσεις για προγραμματιστές
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Συμβάσεις κωδικοποίησης, πολιτικές καταγραφής και άλλα εργαλεία μετασχηματισμού
+
+------
+
+## Συνεισφορά
+
+Αυτή η ενότητα προσφέρει στους προγραμματιστές έναν λεπτομερή οδηγό για το πώς να συνεισφέρουν κώδικα, να ρυθμίσουν το περιβάλλον τους και να ακολουθήσουν τις σχετικές διαδικασίες.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Κανόνες και συμβάσεις για τη σύνταξη κώδικα στο OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Ένας οδηγός για το πώς να πραγματοποιήσετε ανάπτυξη στο OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Οδηγίες για τις εργασίες συλλογής κερασιών.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Η ροή εργασίας git στο OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Οδηγίες για τη ρύθμιση και την προετοιμασία του OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Πώς να εγκαταστήσετε το Docker στο μηχάνημά σας.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Οδηγός για τη ρύθμιση του περιβάλλοντος ανάπτυξης στο Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Οδηγίες για τον τρόπο εκτέλεσης ορισμένων κοινών ενεργειών σε τοπικό επίπεδο.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Μέθοδοι ανάπτυξης OpenIM εκτός σύνδεσης.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Οδηγός χρήσης εργαλείων πρωτοκόλλου.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Εργαλεία και βιβλιοθήκες στο OpenIM for Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Βέλτιστες πρακτικές και εργαλεία για το Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Βέλτιστες πρακτικές και εργαλεία για σενάρια.
+
+## Μετατροπές
+
+Αυτή η ενότητα εισάγει διάφορες συμβάσεις και πολιτικές στο OpenIM, που περιλαμβάνουν κώδικα, αρχεία καταγραφής, εκδόσεις και άλλα.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Οδηγίες και μέθοδοι για μετατροπές API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Πολιτικές και συμβάσεις καταγραφής στο OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Διαδικασίες και συμβάσεις για CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Συμβάσεις για δεσμεύσεις κώδικα στο OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Δομή καταλόγου και συμβάσεις στο OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Λίστα και περιγραφές κωδικών σφαλμάτων.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Συμβάσεις και μετατροπές για τον κώδικα Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Στρατηγικές διαχείρισης για εικόνες OpenIM Docker, που εκτείνονται σε πολλαπλές αρχιτεκτονικές και αποθετήρια εικόνων.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Περαιτέρω λεπτομερείς συμβάσεις για την υλοτομία.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Στρατηγικές ονομασίας και διαχείρισης για εκδόσεις OpenIM.
+
+
+## Για προγραμματιστές, συνεισφέροντες και συντηρητές κοινότητας
+
+### Προγραμματιστές & Συνεισφέροντες
+
+Εάν είστε προγραμματιστής ή κάποιος που επιθυμεί να συνεισφέρει:
+
+- Εξοικειωθείτε με τις [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) και [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) για να εξασφαλίσετε ομαλή συνεισφορά.
+- Βουτήξτε στον [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) για να δείτε τις πρακτικές ανάπτυξης στο OpenIM.
+
+### Συντηρητές της Κοινότητας
+
+Ως συντηρητής κοινότητας:
+
+- Βεβαιωθείτε ότι οι συνεισφορές ευθυγραμμίζονται με τα πρότυπα που περιγράφονται στην τεκμηρίωσή μας.
+- Να ελέγχετε τακτικά την [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) και τους [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) για να ενημερώνεστε.
+
+## Για Χρήστες
+
+Οι χρήστες θα πρέπει να δώσουν ιδιαίτερη προσοχή:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Απαραίτητο εάν σκοπεύετε να χρησιμοποιήσετε εικόνες Docker του OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Για να κατανοήσετε τις διάφορες διαθέσιμες εικόνες και πώς να επιλέξετε τη σωστή για την αρχιτεκτονική σας.
\ No newline at end of file
diff --git a/docs/README_eo.md b/docs/README_eo.md
new file mode 100644
index 000000000..d7ae8c08c
--- /dev/null
+++ b/docs/README_eo.md
@@ -0,0 +1,67 @@
+# OpenIM Server Docs
+
+Bonvenon al la OpenIM Dokumenta nabo! Ĉi tiu centro disponigas ampleksan gamon da gvidiloj kaj manlibroj desegnitaj por helpi vin eltiri la plej grandan parton de via OpenIM-sperto.
+
+## Enhavtabelo
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Gvidilo pri kontribuado kaj agordoj por programistoj
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Kodigaj konvencioj, registradaj politikoj kaj aliaj transformaj iloj
+
+------
+
+## Kontribui
+
+Ĉi tiu sekcio ofertas al programistoj detalan gvidilon pri kiel kontribui kodon, agordi sian medion kaj sekvi la rilatajn procezojn.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Reguloj kaj konvencioj por skribi kodon en OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Gvidilo pri kiel efektivigi disvolviĝon ene de OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Gvidlinioj pri ĉeriz-plukaj operacioj.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - La git-laborfluo en OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Gvidilo pri agordo kaj pravalorigo de OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Kiel instali Docker sur via maŝino.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Gvidilo por agordi la evolumedion en Linukso.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Gvidlinioj pri kiel efektivigi certajn komunajn agojn loke.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metodoj por disfaldi OpenIM eksterrete.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Gvidilo pri uzado de protokaj iloj.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Iloj kaj bibliotekoj en OpenIM for Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Plej bonaj praktikoj kaj iloj por Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Plej bonaj praktikoj kaj iloj por skriptoj.
+
+## Konvertiĝoj
+
+Ĉi tiu sekcio enkondukas diversajn konvenciojn kaj politikojn ene de OpenIM, ampleksante kodon, protokolojn, versiojn kaj pli.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Gvidlinioj kaj metodoj por API-konvertoj.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Registrado de politikoj kaj konvencioj en OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Proceduroj kaj konvencioj por CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konvencioj por kodoj en OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Dosierujo-strukturo kaj konvencioj ene de OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Listo kaj priskriboj de erarkodoj.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konvencioj kaj konvertiĝoj por Go-kodo.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Administradstrategioj por OpenIM Docker-bildoj, ampleksante plurajn arkitekturojn kaj bilddeponejojn.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Pliaj detalaj konvencioj pri arbohakado.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategioj pri nomado kaj administrado por OpenIM-versioj.
+
+
+## Por Programistoj, Kontribuantoj kaj Komunumaj Prizorgantoj
+
+### Programistoj kaj Kontribuantoj
+
+Se vi estas programisto aŭ iu fervora kontribui:
+
+- Familiariĝu kun niaj [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) por certigi glatajn kontribuojn.
+- Plonĝu en la[Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) por ekkompreni la evolupraktikojn en OpenIM.
+
+### Komunumaj Prizorgantoj
+
+Kiel komunuma prizorganto:
+
+- Certigu, ke kontribuoj kongruas kun la normoj skizitaj en nia dokumentaro.
+- Regule reviziu la [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) kaj [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) por resti ĝisdatigita.
+
+## Por Uzantoj
+
+Uzantoj devas aparte atenti:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Necesas se vi planas uzi Docker-bildojn de OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Por kompreni la malsamajn bildojn disponeblajn kaj kiel elekti la ĝustan por via arkitekturo.
\ No newline at end of file
diff --git a/docs/README_es.md b/docs/README_es.md
new file mode 100644
index 000000000..96523120a
--- /dev/null
+++ b/docs/README_es.md
@@ -0,0 +1,67 @@
+# Documentos del servidor OpenIM
+
+¡Bienvenido al centro de documentación de OpenIM! Este centro proporciona una amplia gama de guías y manuales diseñados para ayudarle a aprovechar al máximo su experiencia OpenIM.
+
+## Tabla de contenido
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Orientación sobre contribuciones y configuraciones para desarrolladores
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Convenciones de codificación, políticas de registro y otras herramientas de transformación
+
+------
+
+## Contribuir
+
+Esta sección ofrece a los desarrolladores una guía detallada sobre cómo contribuir con código, configurar su entorno y seguir los procesos asociados.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Reglas y convenciones para escribir código en OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Una guía sobre cómo realizar el desarrollo dentro de OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Directrices sobre operaciones de selección selectiva.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - El flujo de trabajo de git en OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Orientación sobre la configuración e inicialización de OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Cómo instalar Docker en su máquina.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guía para configurar el entorno de desarrollo en Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Lineamientos sobre cómo llevar a cabo determinadas acciones comunes a nivel local.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Métodos de implementación de OpenIM sin conexión.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guía sobre el uso de herramientas de protocolo.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Herramientas y bibliotecas en OpenIM for Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Mejores prácticas y herramientas para Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Mejores prácticas y herramientas para scripts.
+
+## Conversiones
+
+Esta sección presenta varias convenciones y políticas dentro de OpenIM, que abarcan código, registros, versiones y más.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Directrices y métodos para conversiones de API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Políticas y convenciones de registro en OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedimientos y convenciones para CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Convenciones para confirmaciones de código en OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Estructura de directorios y convenciones dentro de OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Lista y descripciones de códigos de error.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Convenciones y conversiones para código Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Estrategias de gestión para imágenes OpenIM Docker, que abarcan múltiples arquitecturas y repositorios de imágenes.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Convenciones más detalladas sobre el registro.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Estrategias de nomenclatura y gestión de versiones OpenIM.
+
+
+## Para desarrolladores, contribuyentes y mantenedores de la comunidad
+
+### Desarrolladores y colaboradores
+
+Si eres desarrollador o alguien interesado en contribuir:
+
+- Familiarícese con nuestras [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) y [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) to ensure smooth contributions.
+- Sumérgete en la [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) para familiarizarte con las prácticas de desarrollo en OpenIM.
+
+### Mantenedores de la comunidad
+
+Como mantenedor de la comunidad:
+
+- Asegúrese de que las contribuciones se alineen con los estándares descritos en nuestra documentación.
+- Revise periódicamente la [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) y los [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) para mantenerse actualizado.
+
+## Para usuarios
+
+Los usuarios deben prestar especial atención a:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Necesario si planea utilizar imágenes Docker de OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Comprender las diferentes imágenes disponibles y cómo elegir la adecuada para su arquitectura.
\ No newline at end of file
diff --git a/docs/README_fa.md b/docs/README_fa.md
new file mode 100644
index 000000000..43056647a
--- /dev/null
+++ b/docs/README_fa.md
@@ -0,0 +1,67 @@
+# اسناد سرور OpenIM
+
+به مرکز اسناد OpenIM خوش آمدید! این مرکز طیف گسترده ای از راهنماها و راهنماها را ارائه می دهد که به شما کمک می کند تا از تجربه OpenIM خود بیشترین بهره را ببرید.
+
+## فهرست مطالب
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - راهنمایی در مورد مشارکت و تنظیمات برای توسعه دهندگان
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - کنوانسیون های کدگذاری، سیاست های ورود به سیستم و سایر ابزارهای تبدیل
+
+------
+
+## مشارکت
+
+این بخش به توسعه دهندگان راهنمای دقیقی در مورد نحوه مشارکت کد، تنظیم محیط خود و پیروی از فرآیندهای مرتبط ارائه می دهد.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - قوانین و مقررات برای نوشتن کد در OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - راهنمای نحوه انجام توسعه در OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - دستورالعمل عملیات چیدن گیلاس
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - گردش کار git در OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - راهنمایی در مورد راه اندازی و مقداردهی اولیه OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - چگونه داکر را روی دستگاه خود نصب کنیم.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - راهنمای راه اندازی محیط توسعه در لینوکس.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - رهنمودهایی در مورد نحوه انجام برخی از اقدامات مشترک به صورت محلی.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - روش های استقرار OpenIM به صورت آفلاین
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - راهنمای استفاده از ابزار پروتک
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - ابزارها و کتابخانه ها در OpenIM for Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - بهترین روش ها و ابزارها برای Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - بهترین روش ها و ابزارها برای اسکریپت ها.
+
+## تبدیل ها
+
+این بخش قراردادها و سیاستهای مختلفی را در OpenIM معرفی میکند که شامل کد، گزارشها، نسخهها و موارد دیگر میشود.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - دستورالعمل ها و روش های تبدیل API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - سیاستهای ورود به سیستم و قراردادها در OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - رویه ها و قراردادها برای CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - کنوانسیونها برای تعهدات کد در OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - ساختار دایرکتوری و قراردادها در OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - لیست و توضیحات کدهای خطا
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - کنوانسیون ها و تبدیل ها برای کد Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - استراتژی های مدیریتی برای تصاویر OpenIM Docker، شامل چندین معماری و مخازن تصویر.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - کنوانسیون های دقیق تر در مورد ورود به سیستم.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - استراتژی های نامگذاری و مدیریت برای نسخه های OpenIM.
+
+
+## برای توسعهدهندگان، مشارکتکنندگان و نگهبانان انجمن
+
+### توسعه دهندگان و مشارکت کنندگان
+
+اگر توسعهدهنده هستید یا کسی که مشتاق مشارکت است:
+
+- - برای اطمینان از مشارکت های روان، با [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) و [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) ما آشنا شوید.
+- - در [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) شیرجه بزنید تا از شیوه های توسعه در OpenIM مطلع شوید.
+
+### نگهبانان جامعه
+
+به عنوان یک نگهدارنده جامعه:
+
+- اطمینان حاصل کنید که مشارکت ها با استانداردهای ذکر شده در اسناد ما مطابقت دارند.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) و [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) را بهطور مرتب مرور کنید تا بهروز بمانید.
+
+## برای کاربران
+
+کاربران باید توجه ویژه ای به موارد زیر داشته باشند:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - اگر قصد دارید از تصاویر Docker OpenIM استفاده کنید، ضروری است.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - برای درک تصاویر مختلف موجود و نحوه انتخاب تصویر مناسب برای معماری خود.
\ No newline at end of file
diff --git a/docs/README_fi.md b/docs/README_fi.md
new file mode 100644
index 000000000..9678763d9
--- /dev/null
+++ b/docs/README_fi.md
@@ -0,0 +1,67 @@
+# OpenIM Server Docs
+
+Tervetuloa OpenIM-dokumentaatiokeskukseen! Tämä keskus tarjoaa kattavan valikoiman oppaita ja oppaita, jotka on suunniteltu auttamaan sinua saamaan kaiken irti OpenIM-kokemuksestasi.
+
+## Sisällysluettelo
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Ohjeita kehittäjille osallistumiseen ja määrityksiin
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Koodauskäytännöt, lokikäytännöt ja muut muunnostyökalut
+
+------
+
+## Contrib
+
+Tämä osio tarjoaa kehittäjille yksityiskohtaisen oppaan koodin lisäämisestä, ympäristön määrittämisestä ja siihen liittyvien prosessien seuraamisesta.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Säännöt ja käytännöt koodin kirjoittamiselle OpenIM:ssä.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Opas kehitystyön toteuttamiseen OpenIM:ssä.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Kirsikoiden poimimista koskevat ohjeet.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Git-työnkulku OpenIM:ssä.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Ohjeita OpenIM:n käyttöönottoon ja alustamiseen.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Kuinka asentaa Docker koneellesi.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Ohje kehitysympäristön määrittämiseen Linuxissa.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Ohjeita tiettyjen yhteisten toimien toteuttamiseen paikallisesti.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - OpenIM:n offline-käyttöönottomenetelmät.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Opas protokollatyökalujen käyttöön.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - OpenIM for Go -työkalut ja kirjastot.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefilen parhaat käytännöt ja työkalut.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Skriptien parhaat käytännöt ja työkalut.
+
+## Tulokset
+
+Tässä osiossa esitellään erilaisia OpenIM:n käytäntöjä ja käytäntöjä, jotka kattavat koodin, lokit, versiot ja paljon muuta.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Ohjeita ja menetelmiä API-muunnoksille.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Kirjauskäytännöt ja käytännöt OpenIM:ssä.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD:n menettelyt ja käytännöt.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM:n koodisitoumusten käytännöt.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Hakemistorakenne ja käytännöt OpenIM:ssä.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Luettelo ja kuvaukset virhekoodeista.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go-koodin sopimukset ja muunnokset.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Hallintastrategiat OpenIM Docker -kuville, jotka kattavat useita arkkitehtuureja ja kuvavarastoja.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Tarkemmat hakkuiden käytännöt.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Nimeämis- ja hallintastrategiat OpenIM-versioille.
+
+
+## Kehittäjille, avustajille ja yhteisön ylläpitäjille
+
+### Kehittäjät ja avustajat
+
+Jos olet kehittäjä tai joku, joka haluaa osallistua:
+
+- Tutustu [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md)- ja [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) -käytäntöihimme varmistaaksesi sujuvan osallistumisen.
+- Sukella [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) saadaksesi tietoa OpenIM:n kehityskäytännöistä.
+
+### Yhteisön ylläpitäjät
+
+Yhteisön ylläpitäjänä:
+
+- Varmista, että osallistumiset ovat asiakirjoissamme esitettyjen standardien mukaisia.
+- Tarkista säännöllisesti [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) ja [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) pysyäksesi ajan tasalla.
+
+## Käyttäjille
+
+Käyttäjien tulee kiinnittää erityistä huomiota:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Välttämätön, jos aiot käyttää OpenIM:n Docker-kuvia.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Ymmärtääksesi saatavilla olevat erilaiset kuvat ja kuinka valita oikea arkkitehtuuriisi.
\ No newline at end of file
diff --git a/docs/README_fr.md b/docs/README_fr.md
new file mode 100644
index 000000000..747ef5349
--- /dev/null
+++ b/docs/README_fr.md
@@ -0,0 +1,66 @@
+# Documentation du serveur OpenIM
+
+Bienvenue dans le hub de documentation OpenIM ! Ce centre propose une gamme complète de guides et de manuels conçus pour vous aider à tirer le meilleur parti de votre expérience OpenIM.
+
+## Table des matières
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Conseils sur la contribution et les configurations pour les développeurs
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Conventions de codage, politiques de journalisation et autres outils de transformation
+
+------
+
+## Contribuer
+
+Cette section propose aux développeurs un guide détaillé sur la façon de contribuer au code, de configurer leur environnement et de suivre les processus associés.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Règles et conventions pour écrire du code dans OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Un guide sur la façon de réaliser du développement au sein d'OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Lignes directrices sur les opérations de triage.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Le flux de travail git dans OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Conseils sur la configuration et l’initialisation d’OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Comment installer Docker sur votre machine.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guide pour configurer l'environnement de développement sous Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Des lignes directrices pour mener localement certaines actions communes.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Méthodes de déploiement d'OpenIM hors ligne.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guide sur l'utilisation des outils de protocole.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Outils et bibliothèques dans OpenIM for Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Meilleures pratiques et outils pour Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Meilleures pratiques et outils pour les scripts.
+
+## Conversions
+
+Cette section présente diverses conventions et politiques au sein d'OpenIM, englobant le code, les journaux, les versions, etc.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Lignes directrices et méthodes pour les conversions API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Politiques et conventions de journalisation dans OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Politiques et conventions de journalisation dans OpenIM.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Politiques et conventions de journalisation dans OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Structure de répertoire et conventions au sein d'OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Liste et descriptions des codes d'erreur.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Conventions et conversions pour le code Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Stratégies de gestion des images OpenIM Docker, couvrant plusieurs architectures et référentiels d'images.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Conventions plus détaillées sur la journalisation.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Stratégies de nommage et de gestion pour les versions OpenIM.
+
+
+## Pour les développeurs, les contributeurs et les responsables de la communauté
+
+### Développeurs et contributeurs
+
+Si vous êtes un développeur ou quelqu'un désireux de contribuer :
+- Familiarisez-vous avec nos [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) et notre [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) pour garantir des contributions fluides.
+- Plongez dans le [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) pour vous familiariser avec les pratiques de développement dans OpenIM.
+
+### Responsables de la communauté
+
+En tant que responsable de la communauté :
+
+- EAssurez-vous que les contributions sont conformes aux normes décrites dans notre documentation.
+- onsultez régulièrement la [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) et les [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) pour rester à jour.
+
+## Pour les utilisateurs
+
+Les utilisateurs doivent prêter une attention particulière à :
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Nécessaire si vous prévoyez d'utiliser des images Docker d'OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Pour comprendre les différentes images disponibles et comment choisir celle qui convient à votre architecture.
\ No newline at end of file
diff --git a/docs/README_hu.md b/docs/README_hu.md
new file mode 100644
index 000000000..62cb54bb2
--- /dev/null
+++ b/docs/README_hu.md
@@ -0,0 +1,67 @@
+# OpenIM Server Docs
+
+Üdvözöljük az OpenIM dokumentációs központjában! Ez a központ útmutatók és kézikönyvek átfogó választékát kínálja, amelyek célja, hogy a legtöbbet hozza ki az OpenIM-élményből.
+
+## Tartalomjegyzék
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Útmutató a fejlesztőknek a hozzájáruláshoz és a konfigurációkhoz
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Kódolási konvenciók, naplózási szabályzatok és egyéb átalakítási eszközök
+
+------
+
+## Contrib
+
+Ez a rész részletes útmutatót nyújt a fejlesztőknek a kód hozzáadásával, a környezet beállításával és a kapcsolódó folyamatok követésével kapcsolatban.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Az OpenIM kódírásának szabályai és konvenciói.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Útmutató az OpenIM-en belüli fejlesztés végrehajtásához.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Útmutató a cseresznyeszedési műveletekhez.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - A git munkafolyamat az OpenIM-ben.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Útmutató az OpenIM beállításához és inicializálásához.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - A Docker telepítése a gépére.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guide to set up the development environment on Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Útmutató a fejlesztői környezet beállításához Linuxon.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Az OpenIM offline üzembe helyezésének módszerei.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Útmutató a protokolleszközök használatához.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Eszközök és könyvtárak az OpenIM for Go-ban.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - A Makefile legjobb gyakorlatai és eszközei.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Bevált módszerek és eszközök a szkriptekhez.
+
+## Conversions
+
+Ez a rész az OpenIM különféle konvencióit és szabályzatait mutatja be, beleértve a kódot, a naplókat, a verziókat és egyebeket.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Irányelvek és módszerek az API-konverziókhoz.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Naplózási szabályzatok és konvenciók az OpenIM-ben.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD eljárások és konvenciók.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - A kód véglegesítésének konvenciói az OpenIM-ben.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Címtárszerkezet és konvenciók az OpenIM-en belül.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - A hibakódok listája és leírása.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konvenciók és átalakítások a Go kódhoz.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Kezelési stratégiák az OpenIM Docker-képekhez, amelyek több architektúrára és képtárra is kiterjednek.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - További részletes egyezmények a fakitermelésről.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Elnevezési és kezelési stratégiák az OpenIM verziókhoz.
+
+
+## Fejlesztőknek, közreműködőknek és közösségi fenntartóknak
+
+### Fejlesztők és közreműködők
+
+Ha Ön fejlesztő vagy valaki, aki szeretne hozzájárulni:
+
+- A zökkenőmentes hozzájárulás érdekében ismerkedjen meg [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) és [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md)-val.
+- Merüljön el a [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), hogy megismerje az OpenIM fejlesztési gyakorlatát.
+
+### Közösségfenntartók
+
+Közösségfenntartóként:
+
+- Győződjön meg arról, hogy a hozzájárulások megfelelnek a dokumentációnkban felvázolt szabványoknak.
+- Rendszeresen tekintse át a [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) és a [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), hogy naprakész maradjon.
+
+## Felhasználóknak
+
+A felhasználóknak különös figyelmet kell fordítaniuk a következőkre:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Szükséges, ha az OpenIM Docker-képeit szeretné használni.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Hogy megértse a rendelkezésre álló különböző képeket, és hogyan válassza ki a megfelelőt az építészetéhez.
\ No newline at end of file
diff --git a/docs/README_id.md b/docs/README_id.md
new file mode 100644
index 000000000..988e25efe
--- /dev/null
+++ b/docs/README_id.md
@@ -0,0 +1,67 @@
+# Dokumen Server OpenIM
+
+Selamat datang di pusat Dokumentasi OpenIM! Pusat ini menyediakan berbagai panduan dan manual yang komprehensif untuk membantu Anda memaksimalkan pengalaman Anda dengan OpenIM.
+
+## Daftar Isi
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Panduan tentang kontribusi dan konfigurasi untuk pengembang
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Konvensi pengkodean, kebijakan logging, dan alat transformasi lainnya
+
+------
+
+## Contrib
+
+Bagian ini menawarkan panduan rinci bagi pengembang tentang cara berkontribusi kode, menyiapkan lingkungan mereka, dan mengikuti proses yang terkait.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Aturan dan konvensi untuk menulis kode di OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Panduan tentang cara melakukan pengembangan di dalam OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Pedoman tentang operasi cherry-picking.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Alur kerja git di OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Panduan untuk mengatur dan menginisialisasi OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Cara memasang Docker di mesin Anda.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Panduan untuk menyiapkan lingkungan pengembangan di Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Pedoman tentang cara melakukan beberapa tindakan umum secara lokal.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metode penyebaran OpenIM secara offline.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Panduan tentang menggunakan alat protoc.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Alat dan perpustakaan di OpenIM untuk Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Praktik terbaik dan alat untuk Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Praktik terbaik dan alat untuk skrip.
+
+## Conversions
+
+Bagian ini memperkenalkan berbagai konvensi dan kebijakan dalam OpenIM, meliputi kode, log, versi, dan lainnya.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Pedoman dan metode untuk konversi API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Kebijakan dan konvensi logging di OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Prosedur dan konvensi untuk CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konvensi untuk commit kode di OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Struktur direktori dan konvensi dalam OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Daftar dan deskripsi kode kesalahan.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konvensi dan konversi untuk kode Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Strategi manajemen gambar Docker OpenIM, mencakup berbagai arsitektur dan repositori gambar.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Konvensi logging yang lebih detail.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategi penamaan dan manajemen versi OpenIM.
+
+
+## Untuk Pengembang, Kontributor, dan Pemelihara Komunitas
+
+### Pengembang & Kontributor
+
+Jika Anda seorang pengembang atau seseorang yang ingin berkontribusi:
+
+- Kenali [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) dan [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) kami untuk memastikan kontribusi yang lancar.
+- Pelajari [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) untuk memahami praktik pengembangan di OpenIM.
+
+### Pemelihara Komunitas
+
+Sebagai pemelihara komunitas:
+
+- Pastikan kontribusi sesuai dengan standar yang diuraikan dalam dokumentasi kami.
+- Tinjau secara teratur [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) dan [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) untuk tetap terupdate.
+
+## Untuk Pengguna
+
+Pengguna harus memberikan perhatian khusus kepada:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Diperlukan jika Anda berencana menggunakan gambar Docker dari OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Untuk memahami gambar yang tersedia dan bagaimana memilih yang tepat untuk arsitektur Anda.
diff --git a/docs/README_it.md b/docs/README_it.md
new file mode 100644
index 000000000..76e41b5e7
--- /dev/null
+++ b/docs/README_it.md
@@ -0,0 +1,67 @@
+# Documentazione del Server OpenIM
+
+Benvenuti al centro documentazione di OpenIM! Questo centro offre una gamma completa di guide e manuali progettati per aiutarvi a ottenere il massimo dalla vostra esperienza con OpenIM.
+
+## Indice dei Contenuti
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Guida al contributo e alle configurazioni per gli sviluppatori
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Convenzioni di codifica, politiche di registrazione e altri strumenti di trasformazione
+
+------
+
+## Contrib
+
+Questa sezione offre agli sviluppatori una guida dettagliata su come contribuire al codice, configurare il loro ambiente e seguire i processi associati.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regole e convenzioni per scrivere codice in OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Una guida su come svolgere lo sviluppo all'interno di OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Linee guida sulle operazioni di cherry-picking.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Il flusso di lavoro git in OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Guida per configurare e inizializzare OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Come installare Docker sul tuo dispositivo.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guida per configurare l'ambiente di sviluppo su Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Linee guida su come eseguire determinate azioni comuni localmente.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metodi per distribuire OpenIM offline.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guida all'uso degli strumenti protoc.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Strumenti e librerie in OpenIM per Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Migliori pratiche e strumenti per Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Migliori pratiche e strumenti per gli script.
+
+## Conversions
+
+Questa sezione introduce varie convenzioni e politiche all'interno di OpenIM, che comprendono codice, registrazioni, versioni e altro.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Linee guida e metodi per le conversioni API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Politiche e convenzioni di registrazione in OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedure e convenzioni per CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Convenzioni per i commit di codice in OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Struttura delle directory e convenzioni all'interno di OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Elenco e descrizioni dei codici di errore.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Convenzioni e conversioni per il codice Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Strategie di gestione delle immagini Docker di OpenIM, che coprono più architetture e repository di immagini.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Ulteriori dettagliate convenzioni sulla registrazione.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategie di denominazione e gestione delle versioni di OpenIM.
+
+
+## Per Sviluppatori, Contributori e Manutentori della Comunità
+
+### Sviluppatori & Contributori
+
+Se sei uno sviluppatore o qualcuno interessato a contribuire:
+
+- Familiarizza con le nostre [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) e [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) per garantire contributi fluidi.
+- Approfondisci la [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) per ottenere una conoscenza delle pratiche di sviluppo in OpenIM.
+
+### Manutentori della Comunità
+
+Come manutentore della comunità:
+
+- Assicurati che i contributi siano in linea con gli standard delineati nella nostra documentazione.
+- Rivedi regolarmente la [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) e [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) per rimanere aggiornato.
+
+## Per gli Utenti
+
+Gli utenti dovrebbero prestare particolare attenzione a:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Necessario se si prevede di utilizzare le immagini Docker di OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Per comprendere le diverse immagini disponibili e come scegliere quella giusta per la propria architettura.
diff --git a/docs/README_ja.md b/docs/README_ja.md
new file mode 100644
index 000000000..3971037fb
--- /dev/null
+++ b/docs/README_ja.md
@@ -0,0 +1,67 @@
+# OpenIMサーバードキュメンテーション
+
+OpenIMドキュメンテーションハブへようこそ!このセンターでは、OpenIM体験を最大限に活用するための包括的なガイドとマニュアルを提供しています。
+
+## 目次
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 開発者向けの貢献と設定に関するガイダンス
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - コーディング規約、ログポリシー、その他の変換ツール
+
+------
+
+## 投稿
+
+このセクションでは、開発者がコードを貢献し、環境を設定し、関連するプロセスに従う方法についての詳細なガイドを提供します。
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIMでのコード記述のルールと規約。
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - OpenIM内での開発を行うためのガイド。
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - チェリーピッキング操作のガイドライン。
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIMにおけるGitのワークフロー。
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - OpenIMの設定と初期化に関するガイダンス。
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - マシンにDockerをインストールする方法。
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Linux上での開発環境の設定ガイド。
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - ローカルで一般的なアクションを実行する方法に関するガイドライン。
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - OpenIMをオフラインでデプロイする方法。
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - protocツールの使用ガイド。
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - GoのためのOpenIM内のツールとライブラリ。
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefileのベストプラクティスとツール。
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - スクリプトのベストプラクティスとツール。
+
+## Conversions
+
+このセクションでは、OpenIM内のさまざまな規約とポリシーを紹介します。これには、コード、ログ、バージョンなどが含まれます。
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API変換のためのガイドラインと方法。
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIMにおけるログポリシーと規約。
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CDの手順と規約。
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIMでのコードコミットのための規約。
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM内のディレクトリ構造と規約。
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - エラーコードのリストと説明。
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Goコードのための規約と変換。
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 複数のアーキテクチャとイメージリポジトリにまたがるOpenIM Dockerイメージの管理戦略。
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - ロギングに関するさらに詳細な規約。
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIMバージョンの命名と管理戦略。
+
+
+## 開発者、コントリビューター、コミュニティメンテナー向け
+
+### 開発者およびコントリビューター
+
+開発者または貢献に熱心な方へ:
+
+- スムーズな貢献を確実にするために、私たちの[Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md)と[Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md)に慣れ親しみましょう。
+- OpenIMの開発実践に慣れるために、[Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md)をご覧ください。
+
+### コミュニティメンテナー
+
+コミュニティメンテナーとして:
+
+- 貢献が私たちのドキュメンテーションで概説された基準に沿っていることを確認してください。
+- 最新の情報を得るために、定期的に[Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md)と[Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md)をレビューしてください。
+
+## ユーザー向け
+
+ユーザーは特に以下の点に注意してください:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - OpenIMのDockerイメージを使用する予定の場合に必要です。
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 利用可能なさまざまなイメージを理解し、アーキテクチャに適したものを選択する方法。
diff --git a/docs/README_ko.md b/docs/README_ko.md
new file mode 100644
index 000000000..9cd728c5d
--- /dev/null
+++ b/docs/README_ko.md
@@ -0,0 +1,67 @@
+# OpenIM 서버 문서
+
+OpenIM 문서 허브에 오신 것을 환영합니다! 이 센터는 OpenIM 경험을 최대한 활용하는 데 도움이 되도록 다양한 가이드와 매뉴얼을 제공합니다.
+
+## 목차
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 개발자를 위한 기여 및 구성에 대한 안내
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 코딩 규칙, 로깅 정책 및 기타 변환 도구
+
+------
+
+## 기여
+
+이 섹션은 개발자들에게 코드를 기여하는 방법, 환경을 설정하는 방법 및 관련 프로세스를 따르는 방법에 대한 자세한 가이드를 제공합니다.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIM에서 코드를 작성하기 위한 규칙 및 규약.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - OpenIM 내에서 개발을 수행하는 방법에 대한 가이드.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - 체리피킹 작업에 대한 지침.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM에서의 깃 워크플로우.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - OpenIM 설정 및 초기화에 대한 안내.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 컴퓨터에 도커를 설치하는 방법.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - 리눅스에서 개발 환경을 설정하는 가이드.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - 일부 일반적인 작업을 로컬에서 수행하는 방법에 대한 지침.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - 오프라인에서 OpenIM을 배포하는 방법.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - 프로토콜 도구 사용에 대한 가이드.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Go용 OpenIM 도구 및 라이브러리.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - 메이크파일을 위한 모범 사례 및 도구.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - 스크립트를 위한 모범 사례 및 도구.
+
+## 전환
+
+이 섹션에서는 코드, 로그, 버전 등을 포함하는 OpenIM 내의 다양한 규칙과 정책을 소개합니다.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API 변환을 위한 지침 및 방법.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM의 로깅 정책 및 관습.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD 절차 및 관습.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM에서 코드 커밋을 위한 관습.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM 내의 디렉토리 구조 및 관습.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - 오류 코드 목록 및 설명.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go 코드를 위한 관습 및 변환.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 다양한 아키텍처 및 이미지 저장소를 아우르는 OpenIM Docker 이미지 관리 전략.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - 로깅에 대한 추가적인 상세한 관습.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM 버전의 명명 및 관리 전략.
+
+
+## 개발자, 기여자 및 커뮤니티 관리자를 위한 정보
+
+### 개발자 및 기여자
+
+개발자이거나 기여에 관심이 있다면:
+
+- 원활한 기여를 위해 [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) 및 [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md)에 익숙해지십시오.
+- OpenIM에서의 개발 관행을 파악하려면 [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md)를 참조하십시오.
+
+### 커뮤니티 관리자
+
+커뮤니티 관리자로서:
+
+- 기여가 우리 문서에 명시된 표준에 부합하는지 확인하십시오.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) 및 [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md)를 정기적으로 검토하여 최신 정보를 유지하십시오.
+
+## 사용자를 위한 정보
+
+사용자는 특히 다음 사항에 주의를 기울여야 합니다:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - OpenIM의 Docker 이미지를 사용할 계획이라면 필요합니다.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 사용 가능한 다양한 이미지를 이해하고 아키텍처에 적합한 이미지를 선택하는 방법.
diff --git a/docs/README_ml.md b/docs/README_ml.md
new file mode 100644
index 000000000..7f3aa8c0d
--- /dev/null
+++ b/docs/README_ml.md
@@ -0,0 +1,67 @@
+# OpenIM സെർവർ ഡോക്യുമെന്റേഷൻ
+
+OpenIM ഡോക്യുമെന്റേഷൻ ഹബ്ബിലേക്ക് സ്വാഗതം! ഈ കേന്ദ്രം OpenIM അനുഭവത്തിൽ നിന്ന് പരമാവധി ഉപയോഗം നേടാൻ സഹായിക്കുന്ന വ്യാപകമായ നിർദേശങ്ങളുടെയും മാനുവലുകളുടെയും ശ്രേണി നൽകുന്നു.
+
+## ഉള്ളടക്കം
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - ഡെവലപ്പർമാർക്കുള്ള സംഭാവനകൾ നൽകുന്നതിനും കോൺഫിഗറേഷനുകൾക്കുള്ള നിർദേശങ്ങൾ
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - കോഡിംഗ് കൺവെൻഷനുകൾ, ലോഗ്ഗിംഗ് നയങ്ങൾ, മറ്റ് പരിവർത്തന ഉപകരണങ്ങൾ
+
+------
+
+## Contrib
+
+ഈ ഭാഗം ഡെവലപ്പർമാർക്ക് കോഡ് സംഭാവന നൽകുന്നതിന്റെയും അവരുടെ പരിസ്ഥിതി സജ്ജമാക്കുന്നതിന്റെയും ബന്ധപ്പെട്ട പ്രക്രിയകൾ പിന്തുടരുന്നതിന്റെയും വിശദമായ ഗൈഡ് നൽകുന്നു.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIM-ൽ കോഡ് എഴുതുന്നതിന്റെ നിയമങ്ങൾ കൺവെൻഷനുകൾ.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - OpenIM-ൽ വികസനം നടത്തുന്നതിന്റെ ഗൈഡ്.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - ചെറി-പിക്കിംഗ് ഓപ്പറേഷനുകൾക്കുള്ള മാർഗ്ഗനിർദേശങ്ങൾ.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM-ൽ ഗിറ്റിന്റെ വർക്ക്ഫ്ലോ.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - OpenIM സജ്ജമാക്കുന്നതിനും ആരംഭിക്കുന്നതിനും നിർദേശങ്ങൾ.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - നിങ്ങളുടെ യന്ത്രത്തിൽ ഡോക്കർ ഇൻസ്റ്റാൾ ചെയ്യുന്ന രീതി.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - ലിനക്സിൽ വികസന പരിസ്ഥിതി സജ്ജമാക്കുന്നതിന്റെ ഗൈഡ്.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - ചില പൊതുവായ നടപടികൾ പ്രദേശികമായി നടത്തുന്നതിന്റെ മാർഗ്ഗനിർദേശങ്ങൾ.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - OpenIM ഓഫ്ലൈൻ ഡിപ്ലോയ് ചെയ്യുന്ന രീതികൾ.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - പ്രോട്ടോക് ഉപകരണങ്ങൾ ഉപയോഗിക്കുന്ന ഗൈഡ്.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Go വേണ്ടി OpenIM-ൽ ഉള്ള ഉപകരണങ്ങളും ലൈബ്രറികളും.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefile ഉപകരണങ്ങളുടെയും മികച്ച പ്രാക്ടീസുകളുടെയും ഗൈഡ്.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - സ്ക്രിപ്റ്റുകൾക്കുള്ള മികച്ച പ്രാക്ടീസുകളും ഉപകരണങ്ങളും.
+
+## Conversions
+
+ഈ ഭാഗം OpenIM-ൽ ഉള്ള വിവിധ കൺവെൻഷനുകളെയും നയങ്ങളെയും ആവിഷ്കരിക്കുന്നു, ഇതിൽ കോഡ്, ലോഗുകൾ, പതിപ്പുകൾ എന്നിവ ഉൾപ്പെടുന്നു.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API കൺവെർഷനുകൾക്കുള്ള നിർദേശങ്ങൾ രീതികൾ.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM-ൽ ലോഗ്ഗിംഗ് നയങ്ങൾ കൺവെൻഷനുകൾ.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD പ്രക്രിയകൾ കൺവെൻഷനുകൾ.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM-ൽ കോഡ് കമ്മിറ്റുകൾക്കുള്ള കൺവെൻഷനുകൾ.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM-ൽ ഡയറക്ടറി ഘടന കൺവെൻഷനുകൾ.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - പിശക് കോഡുകളുടെ പട്ടിക വിവരണങ്ങൾ.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go കോഡിനുള്ള കൺവെൻഷനുകൾ പരിവർത്തനങ്ങൾ.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - വിവിധ ആർക്കിടെക്ചറുകൾ ഇമേജ് റെപ്പോസിറ്ററികൾ ഉൾപ്പെടുന്ന OpenIM Docker ഇമേജുകളുടെ മാനേജ്മെന്റ് സ്ട്രാറ്റജീസ്.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - ലോഗ്ഗിംഗിന്റെ കൂടുതൽ വിശദമായ കൺവെൻഷനുകൾ.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM പതിപ്പുകൾക്കുള്ള നാമകരണ മാനേജ്മെന്റ് സ്ട്രാറ്റജീസ്.
+
+
+## ഡെവലപ്പർമാർക്കും, സംഭാവനകൾ നൽകുന്നവർക്കും, കമ്മ്യൂണിറ്റി മെയിന്റെയിനർമാർക്കും
+
+### ഡെവലപ്പർമാർ & സംഭാവനകൾ നൽകുന്നവർ
+
+നിങ്ങൾ ഒരു ഡെവലപ്പർ അല്ലെങ്കിൽ സംഭാവനകൾ നൽകാൻ ആഗ്രഹിക്കുന്ന ആളാണെങ്കിൽ:
+
+- നിരവധി സംഭാവനകൾ ഉറപ്പാക്കാൻ ഞങ്ങളുടെ [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) എന്നിവയുമായി പരിചിതരാകുക.
+- OpenIM-ൽ വികസന പ്രാക്ടീസുകൾ ലഭ്യമാക്കാൻ [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) അന്വേഷിക്കുക.
+
+### കമ്മ്യൂണിറ്റി മെയിന്റെയിനർമാർ
+
+ഒരു കമ്മ്യൂണിറ്റി മെയിന്റെയിനറായി:
+
+- സംഭാവനകൾ ഞങ്ങളുടെ ഡോക്യുമെന്റേഷനിൽ വിവരിച്ച മാനദണ്ഡങ്ങൾക്ക് അനുസൃതമാണെന്ന് ഉറപ്പാക്കുക.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) എന്നിവ പുതുക്കി വായിക്കുക.
+
+## ഉപയോക്താക്കൾക്ക്
+
+ഉപയോക്താക്കൾ പ്രത്യേകം ശ്രദ്ധിക്കേണ്ട കാര്യങ്ങൾ:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - OpenIM-ന്റെ ഡോക്കർ ഇമേജുകൾ ഉപയോഗിക്കാൻ പദ്ധതിയിടുന്നെങ്കിൽ ആവശ്യമാണ്.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - ലഭ്യമായ വിവിധ ഇമേജുകൾ മനസ്സിലാക്കുകയും നിങ്ങളുടെ ആർക്കിടെക്ചറിന് അനുയോജ്യമായത് എങ്ങനെ തിരഞ്ഞെടുക്കണം എന്ന് അറിയുക.
diff --git a/docs/README_nl.md b/docs/README_nl.md
new file mode 100644
index 000000000..755145e6f
--- /dev/null
+++ b/docs/README_nl.md
@@ -0,0 +1,67 @@
+# OpenIM Server-documenten
+
+Welkom bij de OpenIM-documentatiehub! Dit centrum biedt een uitgebreide reeks handleidingen en handleidingen die zijn ontworpen om u te helpen het meeste uit uw OpenIM-ervaring te halen.
+
+## Inhoudsopgave
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Richtlijnen voor bijdragen en configuraties voor ontwikkelaars
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Codeerconventies, logboekbeleid en andere transformatietools
+
+------
+
+## Draag bij
+
+Deze sectie biedt ontwikkelaars een gedetailleerde handleiding over hoe ze code kunnen bijdragen, hun omgeving kunnen instellen en de bijbehorende processen kunnen volgen.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regels en conventies voor het schrijven van code in OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Een handleiding voor het uitvoeren van ontwikkelingen binnen OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Richtlijnen voor kersenplukoperaties.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - De git-workflow in OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Begeleiding bij het instellen en initialiseren van OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Hoe Docker op uw machine te installeren.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Handleiding voor het opzetten van de ontwikkelomgeving op Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Richtlijnen voor het lokaal uitvoeren van bepaalde gemeenschappelijke acties.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Methoden voor het offline inzetten van OpenIM.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Handleiding voor het gebruik van protocoltools.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Tools en bibliotheken in OpenIM for Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Best practices en tools voor Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Best practices en tools voor scripts.
+
+## Conversies
+
+In deze sectie worden verschillende conventies en beleidsregels binnen OpenIM geïntroduceerd, waaronder code, logs, versies en meer.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Richtlijnen en methoden voor API-conversies.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Logboekbeleid en -conventies in OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedures en conventies voor CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Conventies voor code-commits in OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Directorystructuur en conventies binnen OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Lijst en beschrijvingen van foutcodes.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Conventies en conversies voor Go-code.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Beheerstrategieën voor OpenIM Docker-images, verspreid over meerdere architecturen en image-opslagplaatsen.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Verdere gedetailleerde conventies over houtkap.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Naamgevings- en beheerstrategieën voor OpenIM-versies.
+
+
+## Voor ontwikkelaars, bijdragers en communitybeheerders
+
+### Ontwikkelaars en bijdragers
+
+Als u een ontwikkelaar bent of iemand die graag een bijdrage wil leveren:
+
+- Maak uzelf vertrouwd met onze [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) en [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) om soepele bijdragen te garanderen.
+- Duik in de [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) om de ontwikkelpraktijken in OpenIM onder de knie te krijgen.
+
+### Gemeenschapsbeheerders
+
+Als gemeenschapsbeheerder:
+
+- Zorg ervoor dat bijdragen in overeenstemming zijn met de normen die in onze documentatie worden beschreven.
+- Controleer regelmatig het [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) en de [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) om op de hoogte te blijven.
+
+## Voor gebruikers
+
+Gebruikers moeten bijzondere aandacht besteden aan:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Noodzakelijk als u van plan bent Docker-images van OpenIM te gebruiken.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Om de verschillende beschikbare afbeeldingen te begrijpen en hoe u de juiste voor uw architectuur kiest.
\ No newline at end of file
diff --git a/docs/README_pl.md b/docs/README_pl.md
new file mode 100644
index 000000000..9e89c9dae
--- /dev/null
+++ b/docs/README_pl.md
@@ -0,0 +1,67 @@
+# Dokumentacja serwera OpenIM
+
+Witamy w centrum dokumentacji OpenIM! Centrum to zapewnia kompleksową gamę przewodników i podręczników zaprojektowanych, aby pomóc Ci w pełni wykorzystać możliwości OpenIM.
+
+## Spis treści
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Wskazówki dotyczące współtworzenia i konfiguracji dla programistów
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Konwencje kodowania, zasady rejestrowania i inne narzędzia do transformacji
+
+------
+
+## Wkład
+
+W tej sekcji deweloperzy mogą znaleźć szczegółowy przewodnik dotyczący udostępniania kodu, konfigurowania środowiska i wykonywania powiązanych procesów.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Zasady i konwencje pisania kodu w OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Poradnik dotyczący programowania w OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Wytyczne dotyczące operacji zbierania wiśni.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Przepływ pracy git w OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Wskazówki dotyczące konfigurowania i inicjowania OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Jak zainstalować Docker na swoim komputerze.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Przewodnik po konfigurowaniu środowiska programistycznego w systemie Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Wytyczne dotyczące sposobu przeprowadzania niektórych typowych działań lokalnie.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metody wdrażania OpenIM offline.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Przewodnik dotyczący korzystania z narzędzi protoc.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Narzędzia i biblioteki w OpenIM for Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Najlepsze praktyki i narzędzia dla Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Najlepsze praktyki i narzędzia dotyczące skryptów.
+
+## Konwersje
+
+W tej sekcji przedstawiono różne konwencje i zasady w OpenIM, obejmujące kod, dzienniki, wersje i nie tylko.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Wytyczne i metody konwersji API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Zasady i konwencje rejestrowania w OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedury i konwencje dotyczące CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konwencje dotyczące zatwierdzania kodu w OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Struktura katalogów i konwencje w OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Lista i opisy kodów błędów.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konwencje i konwersje dla kodu Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Strategie zarządzania obrazami Dockera OpenIM obejmujące wiele architektur i repozytoriów obrazów.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Dalsze szczegółowe konwencje dotyczące pozyskiwania drewna.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategie nazewnictwa i zarządzania wersjami OpenIM.
+
+
+## Dla programistów, współpracowników i opiekunów społeczności
+
+### Programiści i współpracownicy
+
+Jeśli jesteś programistą lub osobą, która chce wnieść swój wkład:
+
+- Zapoznaj się z naszymi [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) i [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md), aby zapewnić płynną współpracę.
+- Zajrzyj do [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), aby zapoznać się z praktykami programistycznymi w OpenIM.
+
+### Opiekunowie społeczności
+
+Jako opiekun społeczności:
+
+- Upewnij się, że wkład jest zgodny ze standardami określonymi w naszej dokumentacji.
+- Regularnie przeglądaj [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) i [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), aby być na bieżąco.
+
+## Dla Użytkowników
+
+Użytkownicy powinni zwrócić szczególną uwagę na:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Niezbędne, jeśli planujesz używać obrazów Dockera OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Aby zrozumieć różne dostępne obrazy i dowiedzieć się, jak wybrać odpowiedni dla swojej architektury.
\ No newline at end of file
diff --git a/docs/README_pt_BR.md b/docs/README_pt_BR.md
new file mode 100644
index 000000000..e28db74a6
--- /dev/null
+++ b/docs/README_pt_BR.md
@@ -0,0 +1,67 @@
+# Documentação do Servidor OpenIM
+
+Bem-vindo ao centro de documentação do OpenIM! Este centro oferece uma ampla gama de guias e manuais projetados para ajudá-lo a aproveitar ao máximo sua experiência com o OpenIM.
+
+## Índice de Conteúdos
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Orientações sobre contribuições e configurações para desenvolvedores
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Convenções de codificação, políticas de registro e outras ferramentas de transformação
+
+------
+
+## Contrib
+
+Esta seção oferece aos desenvolvedores um guia detalhado sobre como contribuir com código, configurar seu ambiente e seguir os processos associados.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regras e convenções para escrever código no OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Um guia sobre como realizar o desenvolvimento dentro do OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Diretrizes sobre operações de cherry-picking.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - O fluxo de trabalho git no OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Orientações sobre configuração e inicialização do OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Como instalar o Docker em sua máquina.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guia para configurar o ambiente de desenvolvimento no Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Diretrizes sobre como realizar certas ações comuns localmente.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Métodos para implantar o OpenIM offline.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guia sobre o uso de ferramentas protoc.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Ferramentas e bibliotecas no OpenIM para Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Melhores práticas e ferramentas para Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Melhores práticas e ferramentas para scripts.
+
+## Conversions
+
+Esta seção apresenta várias convenções e políticas dentro do OpenIM, abrangendo código, logs, versões e mais.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Diretrizes e métodos para conversões de API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Políticas e convenções de registro no OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedimentos e convenções para CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Convenções para commits de código no OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Estrutura de diretórios e convenções dentro do OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Lista e descrições de códigos de erro.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Convenções e conversões para código Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Estratégias de gerenciamento para imagens Docker do OpenIM, abrangendo várias arquiteturas e repositórios de imagens.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Convenções mais detalhadas sobre registro.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Estratégias de nomeação e gerenciamento para versões do OpenIM.
+
+
+## Para Desenvolvedores, Contribuidores e Mantenedores da Comunidade
+
+### Desenvolvedores & Contribuidores
+
+Se você é um desenvolvedor ou alguém interessado em contribuir:
+
+- Familiarize-se com nossas [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) e [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) para garantir contribuições suaves.
+- Mergulhe no [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) para se familiarizar com as práticas de desenvolvimento no OpenIM.
+
+### Mantenedores da Comunidade
+
+Como mantenedor da comunidade:
+
+- Garanta que as contribuições estejam alinhadas com os padrões descritos em nossa documentação.
+- Reveja regularmente a [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) e [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) para se manter atualizado.
+
+## Para Usuários
+
+Os usuários devem prestar atenção especial a:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Necessário se você planeja usar imagens Docker do OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Para entender as diferentes imagens disponíveis e como escolher a certa para a sua arquitetura.
diff --git a/docs/README_ru.md b/docs/README_ru.md
new file mode 100644
index 000000000..0e89df7c7
--- /dev/null
+++ b/docs/README_ru.md
@@ -0,0 +1,67 @@
+# Документация по серверу OpenIM
+
+Добро пожаловать в центр документации OpenIM! Этот центр предоставляет широкий спектр руководств и руководств, призванных помочь вам максимально эффективно использовать возможности OpenIM.
+
+## Оглавление
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Руководство по участию и настройке для разработчиков
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Соглашения по кодированию, политики ведения журналов и другие инструменты преобразования.
+
+------
+
+## Вклад
+
+В этом разделе разработчикам предлагается подробное руководство о том, как добавлять код, настраивать среду и следовать соответствующим процессам.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Правила и соглашения по написанию кода в OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Руководство о том, как вести разработку в OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Руководство по сбору урожая.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Рабочий процесс git в OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Руководство по настройке и инициализации OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Как установить Docker на свой компьютер.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Руководство по настройке среды разработки в Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Рекомендации о том, как выполнять определенные общие действия на местном уровне.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Способы развертывания OpenIM в автономном режиме.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Руководство по использованию инструментов протокола.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Инструменты и библиотеки в OpenIM для Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Лучшие практики и инструменты для Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Лучшие практики и инструменты для сценариев.
+
+## Конверсии
+
+В этом разделе представлены различные соглашения и политики OpenIM, включая код, журналы, версии и многое другое.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Рекомендации и методы преобразования API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Политики и соглашения ведения журналов в OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Процедуры и соглашения для CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Соглашения о фиксации кода в OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Структура каталогов и соглашения в OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Список и описание кодов ошибок.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Соглашения и преобразования для кода Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Стратегии управления образами OpenIM Docker, охватывающими несколько архитектур и репозиториев изображений.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Дальнейшие подробные соглашения о ведении журнала.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Стратегии именования и управления версиями OpenIM.
+
+
+## Для разработчиков, участников и сопровождающих сообщества
+
+### Разработчики и участники
+
+Если вы разработчик или кто-то хочет внести свой вклад:
+
+- Ознакомьтесь с нашими [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) и [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md), чтобы обеспечить бесперебойную работу.
+- Погрузитесь в [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), чтобы ознакомиться с методами разработки в OpenIM.
+
+### Сопровождающие сообщества
+
+Как администратор сообщества:
+
+- Убедитесь, что вклады соответствуют стандартам, изложенным в нашей документации.
+- Регулярно просматривайте [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) и [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), чтобы оставаться в курсе событий.
+
+## Для пользователей
+
+Пользователям следует обратить особое внимание на:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Необходимо, если вы планируете использовать Docker-образы OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Чтобы понять различные доступные изображения и как выбрать подходящее для вашей архитектуры.
\ No newline at end of file
diff --git a/docs/README_tr.md b/docs/README_tr.md
new file mode 100644
index 000000000..d2bd119e4
--- /dev/null
+++ b/docs/README_tr.md
@@ -0,0 +1,67 @@
+# OpenIM Sunucu Belgeleri
+
+OpenIM Belgeleri merkezine hoş geldiniz! Bu merkez, OpenIM deneyiminizden en iyi şekilde faydalanmanıza yardımcı olmak için tasarlanmış kapsamlı bir rehber ve kılavuzlar koleksiyonu sunar.
+
+## İçindekiler
+
+1. [Katılım](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Geliştiriciler için katkıda bulunma ve yapılandırma rehberi
+2. [Dönüşümler](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Kodlama kuralları, günlükleme politikaları ve diğer dönüşüm araçları
+
+------
+
+## Katılım
+
+Bu bölüm, geliştiricilere kod katkısında bulunma, çevrelerini kurma ve ilişkilendirilmiş süreçleri takip etme konusunda detaylı bir rehber sunar.
+
+- [Kod Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIM'de kod yazma kuralları ve gelenekleri.
+- [Geliştirme Rehberi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - OpenIM içinde geliştirme nasıl yapılır konusunda bir rehber.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Cherry-pick işlemleri için yönergeler.
+- [Git Çalışma Akışı](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM'deki git çalışma akışı.
+- [Başlangıç Yapılandırmaları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - OpenIM'i kurma ve başlatma konusunda rehberlik.
+- [Docker Kurulumu](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Makinenize Docker nasıl kurulur.
+- [Linux Geliştirme Ortamı](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Linux üzerinde geliştirme ortamını kurma kılavuzu.
+- [Yerel İşlemler](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Yerelde belirli yaygın işlemleri nasıl gerçekleştireceğiniz hakkında yönergeler.
+- [Çevrimdışı Dağıtım](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - OpenIM'in çevrimdışı nasıl dağıtılacağı yöntemleri.
+- [Protoc Araçları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Protoc araçlarını kullanma rehberi.
+- [Go Araçları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Go için OpenIM'deki araçlar ve kütüphaneler.
+- [Makefile Araçları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefile için en iyi uygulamalar ve araçlar.
+- [Betik Araçları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Betikler için en iyi uygulamalar ve araçlar.
+
+## Dönüşümler
+
+Bu bölüm, kod, günlükler, sürümler ve daha fazlasını içeren çeşitli OpenIM içindeki kuralları ve politikaları tanıtır.
+
+- [API Dönüşümleri](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API dönüşümleri için yönergeler ve yöntemler.
+- [Günlükleme Politikası](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM'deki günlükleme politikaları ve gelenekleri.
+- [CI/CD İşlemleri](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD için prosedürler ve gelenekler.
+- [Taahhüt Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM'deki kod taahhütleri için kurallar.
+- [Dizin Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM içindeki dizin yapısı ve kurallar.
+- [Hata Kodları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Hata kodlarının listesi ve açıklamaları.
+- [Go Kod Dönüşümleri](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go kodu için kurallar ve dönüşümler.
+- [Docker İmaj Stratejisi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - OpenIM Docker imajlarının yönetim stratejileri, birden fazla mimariyi ve imaj depolarını kapsar.
+- [Günlükleme Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Günlükleme hakkında daha fazla ayrıntılı kurallar.
+- [Sürüm Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM sürümleri için adlandırma ve yönetim stratejileri.
+
+
+## Geliştiriciler, Katkıda Bulunanlar ve Topluluk Bakımı
+
+### Geliştiriciler & Katkıda Bulunanlar
+
+Eğer bir geliştirici veya katkıda bulunmaya hevesli biriyseniz:
+
+- Katkılarınızı düzgün bir şekilde yapmak için [Kod Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) ve [Git Çalışma Akışı](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) ile tanışın.
+- OpenIM'deki geliştirme uygulamalarını anlamak için [Geliştirme Rehberi'ne](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) göz atın.
+
+### Topluluk Bakımı
+
+Topluluk bakımı olarak:
+
+- Katkıların belirtilen standartlarla uyumlu olduğundan emin olun.
+- [Günlükleme Politikası](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) ve [Hata Kodları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) sık sık gözden geçirerek güncel kalın.
+
+## Kullanıcılar İçin
+
+Kullanıcılar, özellikle dikkat etmelidir:
+
+- [Docker Kurulumu](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - OpenIM Docker imajlarını kullanmayı planlıyorsanız gereklidir.
+- [Docker İmaj Stratejisi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Mevcut farklı imajları anlamak ve mimarinize uygun olanı nasıl seçeceğinizi öğrenmek için.
diff --git a/docs/README_ua.md b/docs/README_ua.md
new file mode 100644
index 000000000..1eaf6b5d1
--- /dev/null
+++ b/docs/README_ua.md
@@ -0,0 +1,67 @@
+# OpenIM Server документ
+
+Ласкаво просимо до Центру документації OpenIM! Цей центр надає вичерпні посібники та посібники, розроблені, щоб допомогти вам отримати максимальну віддачу від роботи з OpenIM.
+
+## Зміст
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Посібник із внесків і налаштування для розробників
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Інструкції з кодування, політики журналювання та інші інструменти перетворення
+
+------
+
+## Посібник із внесків
+
+Цей розділ надає розробникам докладні вказівки щодо того, як додати код, налаштувати своє середовище та дотримуватися пов’язаних процесів.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Правила та умовності для написання коду в OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Посібник з розробки в OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Ретельно підібрані інструкції.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - робочий процес git у OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Посібник із налаштування та ініціалізації OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Як встановити Docker на вашу машину.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Посібник із налаштування середовища розробки в Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Посібник із виконання деяких типових операцій локально.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Як розгорнути OpenIM офлайн.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Посібник із використання інструменту protoc.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Інструменти та бібліотеки для Go в OpenIM.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Найкращі практики та інструменти для Makefiles.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Найкращі практики та інструменти для створення сценаріїв.
+
+## Методи внеску
+
+У цьому розділі описано різні практики та політики в OpenIM, зокрема код, журнали, версії тощо.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Рекомендації та методи перетворення API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Політика та практика журналювання в OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Процедури та практики CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Конвенції для подання коду в OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Конвенції для подання коду в OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Перелік і опис кодів помилок.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Конвенції та перетворення коду Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Стратегія керування зображеннями OpenIM Docker, що охоплює кілька архітектур і сховищ зображень.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Більш детальні умови для журналювання.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Стратегії іменування та керування для версій OpenIM.
+
+
+## Для розробників, співавторів і супроводжувачів спільноти
+
+### Розробники та учасники
+
+Якщо ви розробник або бажаєте зробити внесок:
+
+- знайомі з нами [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) і [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md), щоб забезпечити плавний внесок.
+- зрозуміти глибше [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), освоїти практики розробки OpenIM.
+
+### супроводжувач спільноти
+
+Як супроводжувач спільноти:
+
+- Переконайтеся, що внески відповідають стандартам, викладеним у нашій документації.
+- Регулярно перевіряйте [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) i [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), щоб бути в курсі подій.
+
+## Для користувачів
+
+Користувачам слід звернути особливу увагу на:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Це буде необхідно, якщо ви плануєте використовувати образ Docker OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Дізнайтеся про доступні зображення та про те, як вибрати правильний для вашої архітектури.
diff --git a/docs/README_vi.md b/docs/README_vi.md
new file mode 100644
index 000000000..55a99b8e5
--- /dev/null
+++ b/docs/README_vi.md
@@ -0,0 +1,67 @@
+# Tài liệu Máy chủ OpenIM
+
+Chào mừng bạn đến với trung tâm tài liệu OpenIM! Trung tâm này cung cấp một loạt các hướng dẫn và hướng dẫn chi tiết được thiết kế để giúp bạn tận dụng tối đa trải nghiệm OpenIM của mình.
+
+## Mục lục
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Hướng dẫn về đóng góp và cấu hình cho các nhà phát triển
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Quy ước mã hóa, chính sách ghi nhật ký và các công cụ chuyển đổi khác
+
+------
+
+## Đóng góp
+
+Phần này cung cấp cho các nhà phát triển một hướng dẫn chi tiết về cách đóng góp mã, thiết lập môi trường của họ và tuân theo các quy trình liên quan.
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Quy tắc và quy ước viết mã trong OpenIM.
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Hướng dẫn về cách thực hiện phát triển trong OpenIM.
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Hướng dẫn về các hoạt động chọn lọc.
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Quy trình làm việc git trong OpenIM.
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Hướng dẫn về thiết lập và khởi tạo OpenIM.
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Cách cài đặt Docker trên máy của bạn.
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Hướng dẫn thiết lập môi trường phát triển trên Linux.
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Hướng dẫn về cách thực hiện một số hành động phổ biến ở cấp địa phương.
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Các phương pháp triển khai OpenIM ngoại tuyến.
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Hướng dẫn sử dụng công cụ protoc.
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Công cụ và thư viện trong OpenIM cho Go.
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Thực hành tốt nhất và công cụ cho Makefile.
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Thực hành tốt nhất và công cụ cho kịch bản.
+
+## Chuyển đổi
+
+Phần này giới thiệu các quy ước và chính sách khác nhau trong OpenIM, bao gồm mã, nhật ký, phiên bản và hơn thế nữa.
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Hướng dẫn và phương pháp chuyển đổi API.
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Chính sách và quy ước ghi nhật ký trong OpenIM.
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Quy trình và quy ước cho CI/CD.
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Quy ước cho các cam kết mã trong OpenIM.
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Cấu trúc thư mục và quy ước trong OpenIM.
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Danh sách và mô tả các mã lỗi.
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Quy ước và chuyển đổi cho mã Go.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Chiến lược quản lý hình ảnh Docker của OpenIM, bao gồm nhiều kiến trúc và kho lưu trữ hình ảnh.
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Quy ước chi tiết hơn về ghi nhật ký.
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Chiến lược đặt tên và quản lý phiên bản OpenIM.
+
+
+## Dành cho Nhà phát triển, Người đóng góp và Người duy trì Cộng đồng
+
+### Nhà phát triển & Người đóng góp
+
+Nếu bạn là nhà phát triển hoặc ai đó muốn đóng góp:
+
+- Làm quen với [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) và [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) của chúng tôi để đảm bảo đóng góp trôi chảy.
+- Tìm hiểu [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) để nắm bắt các thực hành phát triển trong OpenIM.
+
+### Người duy trì Cộng đồng
+
+Là người duy trì cộng đồng:
+
+- Đảm bảo rằng các đóng góp phù hợp với các tiêu chuẩn được nêu trong tài liệu của chúng tôi.
+- Thường xuyên xem lại [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) và [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) để cập nhật thông tin.
+
+## Dành cho Người dùng
+
+Người dùng nên chú ý đặc biệt đến:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Cần thiết nếu bạn dự định sử dụng hình ảnh Docker của OpenIM.
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Để hiểu các hình ảnh khác nhau có sẵn và cách chọn hình ảnh phù hợp cho kiến trúc của bạn.
diff --git a/docs/README_zh_CN.md b/docs/README_zh_CN.md
new file mode 100644
index 000000000..413d5dfa1
--- /dev/null
+++ b/docs/README_zh_CN.md
@@ -0,0 +1,67 @@
+# OpenIM Server 文档
+
+欢迎来到 OpenIM 文档中心!本中心提供全面的指南和手册,旨在帮助您最大限度地利用 OpenIM 体验。
+
+## 目录
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 为开发者提供的贡献指南和配置
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 编码规范、日志策略和其他转换工具
+
+------
+
+## 贡献指南
+
+本节为开发人员提供了如何贡献代码、设置环境以及遵循相关流程的详细指南。
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIM 中编写代码的规则和惯例。
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - 关于如何在 OpenIM 内进行开发的指南。
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - 精挑细选的操作指南。
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM 中的 git 工作流程。
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - 设置和初始化 OpenIM 的指南。
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 如何在您的机器上安装 Docker。
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - 在 Linux 上设置开发环境的指南。
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - 关于如何在本地执行某些常见操作的指南。
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - 离线部署 OpenIM 的方法。
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - 使用 protoc 工具的指南。
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - OpenIM 中 Go 的工具和库。
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefile 的最佳实践和工具。
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - 脚本的最佳实践和工具。
+
+## 贡献方法
+
+本节介绍 OpenIM 内的各种惯例和政策,包括代码、日志、版本等。
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API 转换的指南和方法。
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM 中的日志策略和惯例。
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD 的程序和惯例。
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM 中代码提交的惯例。
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM 内的目录结构和惯例。
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - 错误代码的列表和描述。
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go 代码的惯例和转换。
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - OpenIM Docker 镜像的管理策略,涵盖多个架构和镜像仓库。
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - 有关日志的更详细的惯例。
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM 版本的命名和管理策略。
+
+
+## 对于开发者、贡献者和社区维护者
+
+### 开发者和贡献者
+
+如果您是一名开发者或热衷于贡献:
+
+- 熟悉我们的 [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) 和 [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md),以确保顺利贡献。
+- 深入了解 [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md),掌握 OpenIM 的开发实践。
+
+### 社区维护者
+
+作为社区维护者:
+
+- 确保贡献符合我们文档中概述的标准。
+- 定期查看 [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) 和 [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md),以保持最新状态。
+
+## 对于用户
+
+用户应特别注意:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 如果您计划使用 OpenIM 的 Docker 镜像,那么这个将会是必须的。
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 了解可用的镜像以及如何为您的架构选择正确的镜像。
diff --git a/docs/README_zh_TW.md b/docs/README_zh_TW.md
new file mode 100644
index 000000000..8ca00ba17
--- /dev/null
+++ b/docs/README_zh_TW.md
@@ -0,0 +1,67 @@
+# OpenIM 伺服器文檔
+
+歡迎來到 OpenIM 文件中心! 該中心提供全面的指南和手冊,旨在幫助您充分利用 OpenIM 體驗。
+
+## 目錄
+
+1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 開發人員貢獻和配置指南
+2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 編碼約定、日誌記錄策略和其他轉換工具
+
+------
+
+## 貢獻
+
+本節為開發人員提供了有關如何貢獻程式碼、設定環境以及遵循相關流程的詳細指南。
+
+- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - 在 OpenIM 中編寫程式碼的規則和約定。
+- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - 有關如何在 OpenIM 中進行開發的指南。
+- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - 精挑細選操作指南。
+- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM 中的 git 工作流程。
+- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - 設定和初始化 OpenIM 的指南。
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 如何在您的電腦上安裝 Docker。
+- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Linux 上的開發環境設定指南。
+- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - 關於如何在當地進行某些共同行動的指南。
+- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - 離線部署OpenIM的方法。
+- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - 協議工具使用指南。
+- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - OpenIM 在 Go 中的工具和函式庫。
+- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefile 的最佳實務和工具。
+- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - 腳本的最佳實踐和工具。
+
+## 轉換
+
+本節介紹 OpenIM 中的各種約定和策略,包括程式碼、日誌、版本等。
+
+- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API 轉換的指南和方法。
+- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM 中的日誌記錄策略和約定。
+- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD 的程序和約定。
+- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM 中程式碼提交的約定。
+- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM 中的目錄結構和約定。
+- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - 錯誤代碼的清單和描述。
+- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go 程式碼的約定和轉換。
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - OpenIM Docker 映像的管理策略,跨越多種架構和映像儲存庫。
+- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - 有關日誌記錄的更詳細約定。
+- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM 版本的命名與管理策略。
+
+
+## 對於開發者、貢獻者和社區維護者
+
+### 開發者和貢獻者
+
+如果您是開發人員或熱衷於做出貢獻的人:
+
+- 熟悉我們的 [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) 和 [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) 以確保順利貢獻。
+- 深入閱讀 [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) ,掌握 OpenIM 的開發實務。
+
+### 社區維護者
+
+作為社區維護者:
+
+- 確保貢獻符合我們文件中概述的標準。
+- 定期查看 [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) 和 [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) 以保持更新。
+
+## 對於用戶
+
+使用者應特別注意:
+
+- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 如果您打算使用 OpenIM 的 Docker 映像,則這是必要的。
+- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 了解可用的不同影像以及如何為您的架構選擇正確的影像。
\ No newline at end of file
From 551781a0ee4ddbfbe9af64b7431866f2d0ee69b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=9B=E8=9B=8B=E7=99=BD?=
Date: Thu, 1 Feb 2024 10:10:38 +0800
Subject: [PATCH 099/110] fix document parameter errors (#1848)
Co-authored-by: Xinwei Xiong <3293172751NSS@gmail.com>
---
docs/contrib/environment.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index e18246afa..dc11a3c7b 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -305,6 +305,7 @@ Feel free to explore the MinIO documentation for more advanced configurations an
This section involves setting up MongoDB, including its port, address, and credentials.
+
| Parameter | Example Value | Description |
| -------------- | -------------- | ----------------------- |
| MONGO_PORT | "27017" | Port used by MongoDB. |
From 55ca661d138e548dbd94ad2e557f11482d286ad1 Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Thu, 1 Feb 2024 10:11:22 +0800
Subject: [PATCH 100/110] Bug: replace the component check func by tools pkg
(#1846)
* fix: del the manager config and manger init statement
* fix: fix the Manger judge condition
* fix: fix revokeMsg error
* fix: find erors
* fix: find error
* fix: fix the AdminAccount error
* fix: del the debug statement
* fix: fix the component check func
* fix: fix the get zkAddress error
* fix: fix the kafka client close error
* fix: add env in minio connected
* fix: del the minio env
* fix: fix the go.mod tools version
* fix: del get env in minio conneted
---
go.mod | 12 +-
go.sum | 25 ++-
pkg/rpcclient/third.go | 4 +-
tools/component/component.go | 300 ++++++++++++-----------------------
4 files changed, 123 insertions(+), 218 deletions(-)
diff --git a/go.mod b/go.mod
index c709e9ba4..a5fecb5ee 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
github.com/OpenIMSDK/protocol v0.0.48
- github.com/OpenIMSDK/tools v0.0.29
+ github.com/OpenIMSDK/tools v0.0.31
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
@@ -31,7 +31,7 @@ require (
gopkg.in/yaml.v3 v3.0.1
)
-require github.com/google/uuid v1.3.1
+require github.com/google/uuid v1.5.0
require (
github.com/IBM/sarama v1.41.3
@@ -94,8 +94,8 @@ require (
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect
- github.com/klauspost/compress v1.16.7 // indirect
- github.com/klauspost/cpuid/v2 v2.2.5 // indirect
+ github.com/klauspost/compress v1.17.4 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/lithammer/shortuuid v3.0.0+incompatible // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
@@ -129,7 +129,7 @@ require (
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.3.0 // indirect
- golang.org/x/net v0.17.0 // indirect
+ golang.org/x/net v0.19.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
@@ -141,7 +141,7 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
- gorm.io/gorm v1.23.8 // indirect
+ gorm.io/gorm v1.25.4 // indirect
stathat.com/c/consistent v1.0.0 // indirect
)
diff --git a/go.sum b/go.sum
index b7b40632f..fbd9366c3 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,8 @@ github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
github.com/OpenIMSDK/protocol v0.0.48 h1:8MIMjyzJRsruYhVv2ZKArFiOveroaofDOb3dlAdgjsw=
github.com/OpenIMSDK/protocol v0.0.48/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.29 h1:NS4PEwYl9sX3SWsMjDOLVxMo3LcTWREMr+2cjzWjcqc=
-github.com/OpenIMSDK/tools v0.0.29/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/OpenIMSDK/tools v0.0.31 h1:fSrhcPTvHEMTSyrJZDupe730mL4nuhvSOUP/BaZiHaY=
+github.com/OpenIMSDK/tools v0.0.31/go.mod h1:wBfR5CYmEyvxl03QJbTkhz1CluK6J4/lX0lviu8JAjE=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
@@ -152,8 +152,8 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
-github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
+github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ=
github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
@@ -194,7 +194,6 @@ github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
-github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
@@ -205,12 +204,12 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
+github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
-github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
-github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
+github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -402,8 +401,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
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.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
@@ -531,8 +530,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE=
-gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
+gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
+gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/pkg/rpcclient/third.go b/pkg/rpcclient/third.go
index 48a537112..0d5708fc8 100755
--- a/pkg/rpcclient/third.go
+++ b/pkg/rpcclient/third.go
@@ -16,12 +16,10 @@ package rpcclient
import (
"context"
- "net/url"
-
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
-
"google.golang.org/grpc"
+ "net/url"
"github.com/OpenIMSDK/protocol/third"
"github.com/OpenIMSDK/tools/discoveryregistry"
diff --git a/tools/component/component.go b/tools/component/component.go
index 220b845ee..4200b46f5 100644
--- a/tools/component/component.go
+++ b/tools/component/component.go
@@ -15,44 +15,26 @@
package main
import (
- "context"
"errors"
"flag"
"fmt"
- "net"
- "net/url"
"os"
"strings"
"time"
- "github.com/IBM/sarama"
+ "github.com/OpenIMSDK/tools/component"
"github.com/OpenIMSDK/tools/errs"
- "github.com/go-zookeeper/zk"
- "go.mongodb.org/mongo-driver/mongo"
- "go.mongodb.org/mongo-driver/mongo/options"
-
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
- "github.com/minio/minio-go/v7"
- "github.com/minio/minio-go/v7/pkg/credentials"
- "github.com/redis/go-redis/v9"
"gopkg.in/yaml.v3"
)
const (
// defaultCfgPath is the default path of the configuration file.
- defaultCfgPath = "../../../../../config/config.yaml"
- minioHealthCheckDuration = 1
- maxRetry = 300
- componentStartErrCode = 6000
- configErrCode = 6001
- mongoConnTimeout = 30 * time.Second
-)
-
-const (
- colorRed = 31
- colorGreen = 32
- colorYellow = 33
+ defaultCfgPath = "../../../../../config/config.yaml"
+ maxRetry = 300
+ componentStartErrCode = 6000
+ configErrCode = 6001
)
var (
@@ -103,16 +85,16 @@ func main() {
for _, check := range checks {
str, err := check.function()
if err != nil {
- errorPrint(fmt.Sprintf("Starting %s failed, %v", check.name, err))
+ component.ErrorPrint(fmt.Sprintf("Starting %s failed, %v", check.name, err))
allSuccess = false
break
} else {
- successPrint(fmt.Sprintf("%s connected successfully, %s", check.name, str))
+ component.SuccessPrint(fmt.Sprintf("%s connected successfully, %s", check.name, str))
}
}
if allSuccess {
- successPrint("All components started successfully!")
+ component.SuccessPrint("All components started successfully!")
return
}
@@ -120,19 +102,6 @@ func main() {
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
-}
-
// Helper function to get environment variable or default value
func getEnv(key, fallback string) string {
if value, exists := os.LookupEnv(key); exists {
@@ -143,45 +112,23 @@ func getEnv(key, fallback string) string {
// checkMongo checks the MongoDB connection without retries
func checkMongo() (string, error) {
- uri := getEnv("MONGO_URI", buildMongoURI())
-
- ctx, cancel := context.WithTimeout(context.Background(), mongoConnTimeout)
- defer cancel()
-
- str := "ths addr is:" + strings.Join(config.Config.Mongo.Address, ",")
-
- client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
- if err != nil {
- return "", errs.Wrap(errStr(err, str))
+ mongo := &component.Mongo{
+ Address: config.Config.Mongo.Address,
+ Database: config.Config.Mongo.Database,
+ Username: config.Config.Mongo.Username,
+ Password: config.Config.Mongo.Password,
+ MaxPoolSize: config.Config.Mongo.MaxPoolSize,
}
- defer client.Disconnect(context.Background())
-
- ctx, cancel = context.WithTimeout(context.Background(), mongoConnTimeout)
- defer cancel()
-
- if err = client.Ping(ctx, nil); err != nil {
- return "", errs.Wrap(errStr(err, str))
+ uri, uriExist := os.LookupEnv("MONGO_URI")
+ if uriExist {
+ mongo.URL = uri
}
- return str, nil
-}
-
-// buildMongoURI constructs the MongoDB URI using configuration settings
-func buildMongoURI() string {
- // Fallback to config if environment variables are not set
- username := config.Config.Mongo.Username
- password := config.Config.Mongo.Password
- database := config.Config.Mongo.Database
- maxPoolSize := config.Config.Mongo.MaxPoolSize
-
- mongodbHosts := strings.Join(config.Config.Mongo.Address, ",")
-
- if username != "" && password != "" {
- return fmt.Sprintf("mongodb://%s:%s@%s/%s?maxPoolSize=%d",
- username, password, mongodbHosts, database, maxPoolSize)
+ str, err := component.CheckMongo(mongo)
+ if err != nil {
+ return "", err
}
- return fmt.Sprintf("mongodb://%s/%s?maxPoolSize=%d",
- mongodbHosts, database, maxPoolSize)
+ return str, nil
}
// checkMinio checks the MinIO connection
@@ -191,52 +138,24 @@ func checkMinio() (string, error) {
return "", nil
}
- // Prioritize environment variables
- endpoint := getEnv("MINIO_ENDPOINT", config.Config.Object.Minio.Endpoint)
- accessKeyID := getEnv("MINIO_ACCESS_KEY_ID", config.Config.Object.Minio.AccessKeyID)
- secretAccessKey := getEnv("MINIO_SECRET_ACCESS_KEY", config.Config.Object.Minio.SecretAccessKey)
- useSSL := getEnv("MINIO_USE_SSL", "false") // Assuming SSL is not used by default
-
- if endpoint == "" || accessKeyID == "" || secretAccessKey == "" {
- return "", ErrConfig.Wrap("MinIO configuration missing")
- }
-
- // Parse endpoint URL to determine if SSL is enabled
- u, err := url.Parse(endpoint)
+ endpoint, err := getMinioAddr("MINIO_ENDPOINT", "MINIO_ADDRESS", "MINIO_PORT", config.Config.Object.Minio.Endpoint)
if err != nil {
- str := "the endpoint is:" + endpoint
- return "", errs.Wrap(errStr(err, str))
- }
- secure := u.Scheme == "https" || useSSL == "true"
-
- // Initialize MinIO client
- minioClient, err := minio.New(u.Host, &minio.Options{
- Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
- Secure: secure,
- })
- str := "ths addr is:" + u.Host
- if err != nil {
- strs := fmt.Sprintf("%v;host:%s,accessKeyID:%s,secretAccessKey:%s,Secure:%v", err, u.Host, accessKeyID, secretAccessKey, secure)
- return "", errs.Wrap(err, strs)
+ return "", err
}
- // Perform health check
- cancel, err := minioClient.HealthCheck(time.Duration(minioHealthCheckDuration) * time.Second)
- if err != nil {
- return "", errs.Wrap(errStr(err, str))
+ minio := &component.Minio{
+ ApiURL: config.Config.Object.ApiURL,
+ Endpoint: endpoint,
+ AccessKeyID: getEnv("MINIO_ACCESS_KEY_ID", config.Config.Object.Minio.AccessKeyID),
+ SecretAccessKey: getEnv("MINIO_SECRET_ACCESS_KEY", config.Config.Object.Minio.SecretAccessKey),
+ SignEndpoint: config.Config.Object.Minio.SignEndpoint,
+ UseSSL: getEnv("MINIO_USE_SSL", "false"),
}
- defer cancel()
- if minioClient.IsOffline() {
- str := fmt.Sprintf("Minio server is offline;%s", str)
- return "", ErrComponentStart.Wrap(str)
- }
-
- // Check for localhost in API URL and Minio SignEndpoint
- if exactIP(config.Config.Object.ApiURL) == "127.0.0.1" || exactIP(config.Config.Object.Minio.SignEndpoint) == "127.0.0.1" {
- return "", ErrConfig.Wrap("apiURL or Minio SignEndpoint endpoint contain 127.0.0.1")
+ str, err := component.CheckMinio(minio)
+ if err != nil {
+ return "", err
}
-
return str, nil
}
@@ -247,76 +166,48 @@ func checkRedis() (string, error) {
username := getEnv("REDIS_USERNAME", config.Config.Redis.Username)
password := getEnv("REDIS_PASSWORD", config.Config.Redis.Password)
- // Split address to handle multiple addresses for cluster setup
- redisAddresses := strings.Split(address, ",")
-
- var redisClient redis.UniversalClient
- if len(redisAddresses) > 1 {
- // Use cluster client for multiple addresses
- redisClient = redis.NewClusterClient(&redis.ClusterOptions{
- Addrs: redisAddresses,
- Username: username,
- Password: password,
- })
- } else {
- // Use regular client for single address
- redisClient = redis.NewClient(&redis.Options{
- Addr: redisAddresses[0],
- Username: username,
- Password: password,
- })
+ redis := &component.Redis{
+ Address: strings.Split(address, ","),
+ Username: username,
+ Password: password,
}
- defer redisClient.Close()
- // Ping Redis to check connectivity
- _, err := redisClient.Ping(context.Background()).Result()
- str := "the addr is:" + strings.Join(redisAddresses, ",")
+ addresses, err := getAddress("REDIS_ADDRESS", "REDIS_PORT", config.Config.Redis.Address)
if err != nil {
- return "", errs.Wrap(errStr(err, str))
+ return "", err
}
+ redis.Address = addresses
+ str, err := component.CheckRedis(redis)
+ if err != nil {
+ return "", err
+ }
return str, nil
}
// checkZookeeper checks the Zookeeper connection
func checkZookeeper() (string, error) {
// Prioritize environment variables
- schema := getEnv("ZOOKEEPER_SCHEMA", "digest")
+
address := getEnv("ZOOKEEPER_ADDRESS", strings.Join(config.Config.Zookeeper.ZkAddr, ","))
- username := getEnv("ZOOKEEPER_USERNAME", config.Config.Zookeeper.Username)
- password := getEnv("ZOOKEEPER_PASSWORD", config.Config.Zookeeper.Password)
- // Split addresses to handle multiple Zookeeper nodes
- zookeeperAddresses := strings.Split(address, ",")
+ zk := &component.Zookeeper{
+ Schema: getEnv("ZOOKEEPER_SCHEMA", "digest"),
+ ZkAddr: strings.Split(address, ","),
+ Username: getEnv("ZOOKEEPER_USERNAME", config.Config.Zookeeper.Username),
+ Password: getEnv("ZOOKEEPER_PASSWORD", config.Config.Zookeeper.Password),
+ }
- // Connect to Zookeeper
- str := "the addr is:" + address
- c, eventChan, err := zk.Connect(zookeeperAddresses, time.Second) // Adjust the timeout as necessary
+ addresses, err := getAddress("ZOOKEEPER_ADDRESS", "ZOOKEEPER_PORT", config.Config.Zookeeper.ZkAddr)
if err != nil {
- return "", errs.Wrap(errStr(err, str))
- }
- timeout := time.After(5 * time.Second)
- for {
- select {
- case event := <-eventChan:
- if event.State == zk.StateConnected {
- fmt.Println("Connected to Zookeeper")
- goto Connected
- }
- case <-timeout:
- return "", errs.Wrap(errors.New("timeout waiting for Zookeeper connection"), "Zookeeper Addr: "+strings.Join(config.Config.Zookeeper.ZkAddr, " "))
- }
+ return "", nil
}
-Connected:
- defer c.Close()
+ zk.ZkAddr = addresses
- // Set authentication if username and password are provided
- if username != "" && password != "" {
- if err := c.AddAuth(schema, []byte(username+":"+password)); err != nil {
- return "", errs.Wrap(errStr(err, str))
- }
+ str, err := component.CheckZookeeper(zk)
+ if err != nil {
+ return "", err
}
-
return str, nil
}
@@ -327,24 +218,21 @@ func checkKafka() (string, error) {
password := getEnv("KAFKA_PASSWORD", config.Config.Kafka.Password)
address := getEnv("KAFKA_ADDRESS", strings.Join(config.Config.Kafka.Addr, ","))
- // Split addresses to handle multiple Kafka brokers
- kafkaAddresses := strings.Split(address, ",")
+ kafka := &component.Kafka{
+ Username: username,
+ Password: password,
+ Addr: strings.Split(address, ","),
+ }
- // Configure Kafka client
- cfg := sarama.NewConfig()
- if username != "" && password != "" {
- cfg.Net.SASL.Enable = true
- cfg.Net.SASL.User = username
- cfg.Net.SASL.Password = password
+ addresses, err := getAddress("KAFKA_ADDRESS", "KAFKA_PORT", config.Config.Kafka.Addr)
+ if err != nil {
+ return "", nil
}
- // Additional Kafka setup (e.g., TLS configuration) can be added here
- // kafka.SetupTLSConfig(cfg)
+ kafka.Addr = addresses
- // Create Kafka client
- str := "the addr is:" + address
- kafkaClient, err := sarama.NewClient(kafkaAddresses, cfg)
+ str, kafkaClient, err := component.CheckKafka(kafka)
if err != nil {
- return "", errs.Wrap(errStr(err, str))
+ return "", err
}
defer kafkaClient.Close()
@@ -379,22 +267,42 @@ func isTopicPresent(topic string, topics []string) bool {
return false
}
-func colorPrint(colorCode int, format string, a ...interface{}) {
- fmt.Printf("\x1b[%dm%s\x1b[0m\n", colorCode, fmt.Sprintf(format, a...))
-}
-
-func errorPrint(s string) {
- colorPrint(colorRed, "%v", s)
-}
-
-func successPrint(s string) {
- colorPrint(colorGreen, "%v", s)
-}
+func getAddress(key1, key2 string, fallback []string) ([]string, error) {
+ address, addrExist := os.LookupEnv(key1)
+ port, portExist := os.LookupEnv(key2)
-func warningPrint(s string) {
- colorPrint(colorYellow, "Warning: But %v", s)
+ if addrExist && portExist {
+ addresses := strings.Split(address, ",")
+ for i, addr := range addresses {
+ addresses[i] = addr + ":" + port
+ }
+ return addresses, nil
+ } else if !addrExist && portExist {
+ result := make([]string, len(config.Config.Redis.Address))
+ for i, addr := range config.Config.Redis.Address {
+ add := strings.Split(addr, ":")
+ result[i] = add[0] + ":" + port
+ }
+ return result, nil
+ } else if addrExist && !portExist {
+ return nil, errs.Wrap(errors.New("the ZOOKEEPER_PORT of minio is empty"))
+ }
+ return fallback, nil
}
-func errStr(err error, str string) error {
- return fmt.Errorf("%v;%s", err, str)
-}
+func getMinioAddr(key1, key2, key3, fallback string) (string, error) {
+ // Prioritize environment variables
+ endpoint := getEnv(key1, fallback)
+ address, addressExist := os.LookupEnv(key2)
+ port, portExist := os.LookupEnv(key3)
+ if portExist && addressExist {
+ endpoint = "http://" + address + ":" + port
+ } else if !portExist && addressExist {
+ return "", errs.Wrap(errors.New("the MINIO_PORT of minio is empty"))
+ } else if portExist && !addressExist {
+ arr := strings.Split(config.Config.Object.Minio.Endpoint, ":")
+ arr[2] = port
+ endpoint = strings.Join(arr, ":")
+ }
+ return endpoint, nil
+}
\ No newline at end of file
From c55e03dc70b0fbe9091e9c8d4123546348ecb30f Mon Sep 17 00:00:00 2001
From: OpenIM-Gordon <46924906+FGadvancer@users.noreply.github.com>
Date: Fri, 2 Feb 2024 10:11:13 +0800
Subject: [PATCH 101/110] fix: process add errors wrap. (#1862)
* fix: process add errors wrap.
* fix: process add errors wrap.
---
cmd/openim-api/main.go | 25 ++--------
internal/msgtransfer/init.go | 49 +++++++++++--------
.../msgtransfer/online_history_msg_handler.go | 7 +--
.../online_msg_to_mongo_handler.go | 21 +++++---
internal/push/consumer_init.go | 17 ++++---
internal/push/push_handler.go | 10 ++--
internal/push/push_rpc_server.go | 5 +-
internal/rpc/msg/server.go | 5 +-
internal/tools/cron_task.go | 14 +++---
internal/tools/msg.go | 5 +-
pkg/common/db/cache/init_redis.go | 4 +-
pkg/common/db/controller/msg.go | 27 +++++++---
pkg/common/db/mgo/conversation.go | 3 +-
pkg/common/db/mgo/group.go | 3 +-
pkg/common/db/mgo/group_member.go | 3 +-
pkg/common/db/mgo/group_request.go | 3 +-
pkg/common/db/mgo/user.go | 2 +-
pkg/common/db/unrelation/mongo.go | 8 ++-
pkg/common/kafka/consumer_group.go | 16 +++---
pkg/common/kafka/producer.go | 9 ++--
pkg/common/startrpc/start.go | 16 +++---
21 files changed, 142 insertions(+), 110 deletions(-)
diff --git a/cmd/openim-api/main.go b/cmd/openim-api/main.go
index f0b62e31f..59e0b7f9e 100644
--- a/cmd/openim-api/main.go
+++ b/cmd/openim-api/main.go
@@ -17,6 +17,7 @@ package main
import (
"context"
"fmt"
+ "github.com/OpenIMSDK/tools/errs"
"net"
"net/http"
_ "net/http/pprof"
@@ -28,8 +29,6 @@ import (
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/discoveryregistry"
- "github.com/OpenIMSDK/tools/log"
-
"github.com/openimsdk/open-im-server/v3/internal/api"
"github.com/openimsdk/open-im-server/v3/pkg/common/cmd"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
@@ -44,55 +43,42 @@ func main() {
apiCmd.AddPortFlag()
apiCmd.AddApi(run)
if err := apiCmd.Execute(); err != nil {
- log.ZError(context.Background(), "API command execution failed", err)
panic(err.Error())
}
}
func run(port int, proPort int) error {
- log.ZInfo(context.Background(), "Openim api port:", "port", port, "proPort", proPort)
-
if port == 0 || proPort == 0 {
err := "port or proPort is empty:" + strconv.Itoa(port) + "," + strconv.Itoa(proPort)
- log.ZError(context.Background(), err, nil)
- return fmt.Errorf(err)
+ return errs.Wrap(fmt.Errorf(err))
}
-
rdb, err := cache.NewRedis()
if err != nil {
- log.ZError(context.Background(), "Failed to initialize Redis", err)
return err
}
- log.ZInfo(context.Background(), "api start init discov client")
var client discoveryregistry.SvcDiscoveryRegistry
// Determine whether zk is passed according to whether it is a clustered deployment
client, err = kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery)
if err != nil {
- log.ZError(context.Background(), "Failed to initialize discovery register", err)
- return err
+ return errs.Wrap(err, "register discovery err")
}
if err = client.CreateRpcRootNodes(config.Config.GetServiceNames()); err != nil {
- log.ZError(context.Background(), "Failed to create RPC root nodes", err)
- return err
+ return errs.Wrap(err, "create rpc root nodes error")
}
- log.ZInfo(context.Background(), "api register public config to discov")
if err = client.RegisterConf2Registry(constant.OpenIMCommonConfigKey, config.Config.EncodeConfig()); err != nil {
- log.ZError(context.Background(), "Failed to register public config to discov", err)
return err
}
- log.ZInfo(context.Background(), "api register public config to discov success")
router := api.NewGinRouter(client, rdb)
if config.Config.Prometheus.Enable {
p := ginprom.NewPrometheus("app", prommetrics.GetGinCusMetrics("Api"))
p.SetListenAddress(fmt.Sprintf(":%d", proPort))
p.Use(router)
}
- log.ZInfo(context.Background(), "api init router success")
var address string
if config.Config.Api.ListenIP != "" {
@@ -100,13 +86,11 @@ func run(port int, proPort int) error {
} else {
address = net.JoinHostPort("0.0.0.0", strconv.Itoa(port))
}
- log.ZInfo(context.Background(), "start api server", "address", address, "OpenIM version", config.Version)
server := http.Server{Addr: address, Handler: router}
go func() {
err = server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
- log.ZError(context.Background(), "api run failed", err, "address", address)
os.Exit(1)
}
}()
@@ -120,7 +104,6 @@ func run(port int, proPort int) error {
// graceful shutdown operation.
if err := server.Shutdown(ctx); err != nil {
- log.ZError(context.Background(), "failed to api-server shutdown", err)
return err
}
diff --git a/internal/msgtransfer/init.go b/internal/msgtransfer/init.go
index 7d692662d..969761a9d 100644
--- a/internal/msgtransfer/init.go
+++ b/internal/msgtransfer/init.go
@@ -15,8 +15,10 @@
package msgtransfer
import (
+ "context"
"errors"
"fmt"
+ "github.com/OpenIMSDK/tools/errs"
"log"
"net/http"
"sync"
@@ -69,40 +71,47 @@ func StartTransfer(prometheusPort int) error {
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
msgModel := cache.NewMsgCacheModel(rdb)
msgDocModel := unrelation.NewMsgMongoDriver(mongo.GetDatabase())
- msgDatabase := controller.NewCommonMsgDatabase(msgDocModel, msgModel)
+ msgDatabase, err := controller.NewCommonMsgDatabase(msgDocModel, msgModel)
+ if err != nil {
+ return err
+ }
conversationRpcClient := rpcclient.NewConversationRpcClient(client)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
- msgTransfer := NewMsgTransfer(msgDatabase, &conversationRpcClient, &groupRpcClient)
+ msgTransfer, err := NewMsgTransfer(msgDatabase, &conversationRpcClient, &groupRpcClient)
+ if err != nil {
+ return err
+ }
return msgTransfer.Start(prometheusPort)
}
-func NewMsgTransfer(msgDatabase controller.CommonMsgDatabase, conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient) *MsgTransfer {
- return &MsgTransfer{
- historyCH: NewOnlineHistoryRedisConsumerHandler(msgDatabase, conversationRpcClient, groupRpcClient),
- historyMongoCH: NewOnlineHistoryMongoConsumerHandler(msgDatabase),
+func NewMsgTransfer(msgDatabase controller.CommonMsgDatabase, conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient) (*MsgTransfer, error) {
+ historyCH, err := NewOnlineHistoryRedisConsumerHandler(msgDatabase, conversationRpcClient, groupRpcClient)
+ if err != nil {
+ return nil, err
}
+ historyMongoCH, err := NewOnlineHistoryMongoConsumerHandler(msgDatabase)
+ if err != nil {
+ return nil, err
+ }
+
+ return &MsgTransfer{
+ historyCH: historyCH,
+ historyMongoCH: historyMongoCH,
+ }, nil
}
func (m *MsgTransfer) Start(prometheusPort int) error {
+ ctx := context.Background()
var wg sync.WaitGroup
wg.Add(1)
fmt.Println("start msg transfer", "prometheusPort:", prometheusPort)
if prometheusPort <= 0 {
- return errors.New("prometheusPort not correct")
- }
- if config.Config.ChatPersistenceMysql {
- // go m.persistentCH.persistentConsumerGroup.RegisterHandleAndConsumer(m.persistentCH)
- } else {
- fmt.Println("msg transfer not start mysql consumer")
+ return errs.Wrap(errors.New("prometheusPort not correct"))
}
- go m.historyCH.historyConsumerGroup.RegisterHandleAndConsumer(m.historyCH)
- go m.historyMongoCH.historyConsumerGroup.RegisterHandleAndConsumer(m.historyMongoCH)
- // go m.modifyCH.modifyMsgConsumerGroup.RegisterHandleAndConsumer(m.modifyCH)
- /*err := prome.StartPrometheusSrv(prometheusPort)
- if err != nil {
- return err
- }*/
- ////////////////////////////
+
+ go m.historyCH.historyConsumerGroup.RegisterHandleAndConsumer(ctx, m.historyCH)
+ go m.historyMongoCH.historyConsumerGroup.RegisterHandleAndConsumer(ctx, m.historyMongoCH)
+
if config.Config.Prometheus.Enable {
reg := prometheus.NewRegistry()
reg.MustRegister(
diff --git a/internal/msgtransfer/online_history_msg_handler.go b/internal/msgtransfer/online_history_msg_handler.go
index 127cede71..35af330c9 100644
--- a/internal/msgtransfer/online_history_msg_handler.go
+++ b/internal/msgtransfer/online_history_msg_handler.go
@@ -87,7 +87,7 @@ func NewOnlineHistoryRedisConsumerHandler(
database controller.CommonMsgDatabase,
conversationRpcClient *rpcclient.ConversationRpcClient,
groupRpcClient *rpcclient.GroupRpcClient,
-) *OnlineHistoryRedisConsumerHandler {
+) (*OnlineHistoryRedisConsumerHandler, error) {
var och OnlineHistoryRedisConsumerHandler
och.msgDatabase = database
och.msgDistributionCh = make(chan Cmd2Value) // no buffer channel
@@ -98,14 +98,15 @@ func NewOnlineHistoryRedisConsumerHandler(
}
och.conversationRpcClient = conversationRpcClient
och.groupRpcClient = groupRpcClient
- och.historyConsumerGroup = kafka.NewMConsumerGroup(&kafka.MConsumerGroupConfig{
+ var err error
+ och.historyConsumerGroup, err = kafka.NewMConsumerGroup(&kafka.MConsumerGroupConfig{
KafkaVersion: sarama.V2_0_0_0,
OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
}, []string{config.Config.Kafka.LatestMsgToRedis.Topic},
config.Config.Kafka.Addr, config.Config.Kafka.ConsumerGroupID.MsgToRedis)
// statistics.NewStatistics(&och.singleMsgSuccessCount, config.Config.ModuleName.MsgTransferName, fmt.Sprintf("%d
// second singleMsgCount insert to mongo", constant.StatisticsTimeInterval), constant.StatisticsTimeInterval)
- return &och
+ return &och, err
}
func (och *OnlineHistoryRedisConsumerHandler) Run(channelID int) {
diff --git a/internal/msgtransfer/online_msg_to_mongo_handler.go b/internal/msgtransfer/online_msg_to_mongo_handler.go
index 8ef15fe72..6e6c4c819 100644
--- a/internal/msgtransfer/online_msg_to_mongo_handler.go
+++ b/internal/msgtransfer/online_msg_to_mongo_handler.go
@@ -34,16 +34,21 @@ type OnlineHistoryMongoConsumerHandler struct {
msgDatabase controller.CommonMsgDatabase
}
-func NewOnlineHistoryMongoConsumerHandler(database controller.CommonMsgDatabase) *OnlineHistoryMongoConsumerHandler {
+func NewOnlineHistoryMongoConsumerHandler(database controller.CommonMsgDatabase) (*OnlineHistoryMongoConsumerHandler, error) {
+ historyConsumerGroup, err := kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{
+ KafkaVersion: sarama.V2_0_0_0,
+ OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
+ }, []string{config.Config.Kafka.MsgToMongo.Topic},
+ config.Config.Kafka.Addr, config.Config.Kafka.ConsumerGroupID.MsgToMongo)
+ if err != nil {
+ return nil, err
+ }
+
mc := &OnlineHistoryMongoConsumerHandler{
- historyConsumerGroup: kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{
- KafkaVersion: sarama.V2_0_0_0,
- OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
- }, []string{config.Config.Kafka.MsgToMongo.Topic},
- config.Config.Kafka.Addr, config.Config.Kafka.ConsumerGroupID.MsgToMongo),
- msgDatabase: database,
+ historyConsumerGroup: historyConsumerGroup,
+ msgDatabase: database,
}
- return mc
+ return mc, nil
}
func (mc *OnlineHistoryMongoConsumerHandler) handleChatWs2Mongo(
diff --git a/internal/push/consumer_init.go b/internal/push/consumer_init.go
index b72c32bb1..ceab86165 100644
--- a/internal/push/consumer_init.go
+++ b/internal/push/consumer_init.go
@@ -14,19 +14,24 @@
package push
+import "context"
+
type Consumer struct {
pushCh ConsumerHandler
successCount uint64
}
-func NewConsumer(pusher *Pusher) *Consumer {
- return &Consumer{
- pushCh: *NewConsumerHandler(pusher),
+func NewConsumer(pusher *Pusher) (*Consumer, error) {
+ c, err := NewConsumerHandler(pusher)
+ if err != nil {
+ return nil, err
}
+ return &Consumer{
+ pushCh: *c,
+ }, nil
}
func (c *Consumer) Start() {
- // statistics.NewStatistics(&c.successCount, config.Config.ModuleName.PushName, fmt.Sprintf("%d second push to
- // msg_gateway count", constant.StatisticsTimeInterval), constant.StatisticsTimeInterval)
- go c.pushCh.pushConsumerGroup.RegisterHandleAndConsumer(&c.pushCh)
+
+ go c.pushCh.pushConsumerGroup.RegisterHandleAndConsumer(context.Background(), &c.pushCh)
}
diff --git a/internal/push/push_handler.go b/internal/push/push_handler.go
index c91206ecc..19d42ebb9 100644
--- a/internal/push/push_handler.go
+++ b/internal/push/push_handler.go
@@ -35,15 +35,19 @@ type ConsumerHandler struct {
pusher *Pusher
}
-func NewConsumerHandler(pusher *Pusher) *ConsumerHandler {
+func NewConsumerHandler(pusher *Pusher) (*ConsumerHandler, error) {
var consumerHandler ConsumerHandler
consumerHandler.pusher = pusher
- consumerHandler.pushConsumerGroup = kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{
+ var err error
+ consumerHandler.pushConsumerGroup, err = kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{
KafkaVersion: sarama.V2_0_0_0,
OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
}, []string{config.Config.Kafka.MsgToPush.Topic}, config.Config.Kafka.Addr,
config.Config.Kafka.ConsumerGroupID.MsgToPush)
- return &consumerHandler
+ if err != nil {
+ return nil, err
+ }
+ return &consumerHandler, nil
}
func (c *ConsumerHandler) handleMs2PsChat(ctx context.Context, msg []byte) {
diff --git a/internal/push/push_rpc_server.go b/internal/push/push_rpc_server.go
index 188ddc0e1..c1226ce6b 100644
--- a/internal/push/push_rpc_server.go
+++ b/internal/push/push_rpc_server.go
@@ -66,9 +66,12 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
pusher: pusher,
})
}()
+ consumer, err := NewConsumer(pusher)
+ if err != nil {
+ return err
+ }
go func() {
defer wg.Done()
- consumer := NewConsumer(pusher)
consumer.Start()
}()
wg.Wait()
diff --git a/internal/rpc/msg/server.go b/internal/rpc/msg/server.go
index 88be287fd..fe1baa453 100644
--- a/internal/rpc/msg/server.go
+++ b/internal/rpc/msg/server.go
@@ -80,7 +80,10 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
userRpcClient := rpcclient.NewUserRpcClient(client)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
friendRpcClient := rpcclient.NewFriendRpcClient(client)
- msgDatabase := controller.NewCommonMsgDatabase(msgDocModel, cacheModel)
+ msgDatabase, err := controller.NewCommonMsgDatabase(msgDocModel, cacheModel)
+ if err != nil {
+ return err
+ }
s := &msgServer{
Conversation: &conversationClient,
User: &userRpcClient,
diff --git a/internal/tools/cron_task.go b/internal/tools/cron_task.go
index e22504bbb..cf2068d8e 100644
--- a/internal/tools/cron_task.go
+++ b/internal/tools/cron_task.go
@@ -17,6 +17,7 @@ package tools
import (
"context"
"fmt"
+ "github.com/OpenIMSDK/tools/errs"
"os"
"os/signal"
"syscall"
@@ -25,14 +26,13 @@ import (
"github.com/redis/go-redis/v9"
"github.com/robfig/cron/v3"
- "github.com/OpenIMSDK/tools/log"
-
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
)
func StartTask() error {
fmt.Println("cron task start, config", config.Config.ChatRecordsClearTime)
+
msgTool, err := InitMsgTool()
if err != nil {
return err
@@ -47,18 +47,16 @@ func StartTask() error {
// register cron tasks
var crontab = cron.New()
- log.ZInfo(context.Background(), "start chatRecordsClearTime cron task", "cron config", config.Config.ChatRecordsClearTime)
+ fmt.Println("start chatRecordsClearTime cron task", "cron config", config.Config.ChatRecordsClearTime)
_, err = crontab.AddFunc(config.Config.ChatRecordsClearTime, cronWrapFunc(rdb, "cron_clear_msg_and_fix_seq", msgTool.AllConversationClearMsgAndFixSeq))
if err != nil {
- log.ZError(context.Background(), "start allConversationClearMsgAndFixSeq cron failed", err)
- panic(err)
+ return errs.Wrap(err)
}
- log.ZInfo(context.Background(), "start msgDestruct cron task", "cron config", config.Config.MsgDestructTime)
+ fmt.Println("start msgDestruct cron task", "cron config", config.Config.MsgDestructTime)
_, err = crontab.AddFunc(config.Config.MsgDestructTime, cronWrapFunc(rdb, "cron_conversations_destruct_msgs", msgTool.ConversationsDestructMsgs))
if err != nil {
- log.ZError(context.Background(), "start conversationsDestructMsgs cron failed", err)
- panic(err)
+ return errs.Wrap(err)
}
// start crontab
diff --git a/internal/tools/msg.go b/internal/tools/msg.go
index 30006670e..1ec1e03a2 100644
--- a/internal/tools/msg.go
+++ b/internal/tools/msg.go
@@ -84,7 +84,10 @@ func InitMsgTool() (*MsgTool, error) {
if err != nil {
return nil, err
}
- msgDatabase := controller.InitCommonMsgDatabase(rdb, mongo.GetDatabase())
+ msgDatabase, err := controller.InitCommonMsgDatabase(rdb, mongo.GetDatabase())
+ if err != nil {
+ return nil, err
+ }
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
ctxTx := tx.NewMongo(mongo.GetClient())
userDatabase := controller.NewUserDatabase(
diff --git a/pkg/common/db/cache/init_redis.go b/pkg/common/db/cache/init_redis.go
index 1308e9649..c593089e6 100644
--- a/pkg/common/db/cache/init_redis.go
+++ b/pkg/common/db/cache/init_redis.go
@@ -49,7 +49,7 @@ func NewRedis() (redis.UniversalClient, error) {
overrideConfigFromEnv()
if len(config.Config.Redis.Address) == 0 {
- return nil, errors.New("redis address is empty")
+ return nil, errs.Wrap(errors.New("redis address is empty"))
}
specialerror.AddReplace(redis.Nil, errs.ErrRecordNotFound)
var rdb redis.UniversalClient
@@ -77,7 +77,7 @@ func NewRedis() (redis.UniversalClient, error) {
defer cancel()
err = rdb.Ping(ctx).Err()
if err != nil {
- return nil, fmt.Errorf("redis ping %w", err)
+ return nil, errs.Wrap(fmt.Errorf("redis ping %w", err))
}
redisClient = rdb
diff --git a/pkg/common/db/controller/msg.go b/pkg/common/db/controller/msg.go
index dfff5c61d..b841a7d31 100644
--- a/pkg/common/db/controller/msg.go
+++ b/pkg/common/db/controller/msg.go
@@ -126,21 +126,32 @@ type CommonMsgDatabase interface {
ConvertMsgsDocLen(ctx context.Context, conversationIDs []string)
}
-func NewCommonMsgDatabase(msgDocModel unrelationtb.MsgDocModelInterface, cacheModel cache.MsgModel) CommonMsgDatabase {
+func NewCommonMsgDatabase(msgDocModel unrelationtb.MsgDocModelInterface, cacheModel cache.MsgModel) (CommonMsgDatabase, error) {
+ producerToRedis, err := kafka.NewKafkaProducer(config.Config.Kafka.Addr, config.Config.Kafka.LatestMsgToRedis.Topic)
+ if err != nil {
+ return nil, err
+ }
+ producerToMongo, err := kafka.NewKafkaProducer(config.Config.Kafka.Addr, config.Config.Kafka.MsgToMongo.Topic)
+ if err != nil {
+ return nil, err
+ }
+ producerToPush, err := kafka.NewKafkaProducer(config.Config.Kafka.Addr, config.Config.Kafka.MsgToPush.Topic)
+ if err != nil {
+ return nil, err
+ }
return &commonMsgDatabase{
msgDocDatabase: msgDocModel,
cache: cacheModel,
- producer: kafka.NewKafkaProducer(config.Config.Kafka.Addr, config.Config.Kafka.LatestMsgToRedis.Topic),
- producerToMongo: kafka.NewKafkaProducer(config.Config.Kafka.Addr, config.Config.Kafka.MsgToMongo.Topic),
- producerToPush: kafka.NewKafkaProducer(config.Config.Kafka.Addr, config.Config.Kafka.MsgToPush.Topic),
- }
+ producer: producerToRedis,
+ producerToMongo: producerToMongo,
+ producerToPush: producerToPush,
+ }, nil
}
-func InitCommonMsgDatabase(rdb redis.UniversalClient, database *mongo.Database) CommonMsgDatabase {
+func InitCommonMsgDatabase(rdb redis.UniversalClient, database *mongo.Database) (CommonMsgDatabase, error) {
cacheModel := cache.NewMsgCacheModel(rdb)
msgDocModel := unrelation.NewMsgMongoDriver(database)
- CommonMsgDatabase := NewCommonMsgDatabase(msgDocModel, cacheModel)
- return CommonMsgDatabase
+ return NewCommonMsgDatabase(msgDocModel, cacheModel)
}
type commonMsgDatabase struct {
diff --git a/pkg/common/db/mgo/conversation.go b/pkg/common/db/mgo/conversation.go
index 1614cfec5..0b8d597dc 100644
--- a/pkg/common/db/mgo/conversation.go
+++ b/pkg/common/db/mgo/conversation.go
@@ -16,6 +16,7 @@ package mgo
import (
"context"
+ "github.com/OpenIMSDK/tools/errs"
"time"
"github.com/OpenIMSDK/protocol/constant"
@@ -38,7 +39,7 @@ func NewConversationMongo(db *mongo.Database) (*ConversationMgo, error) {
Options: options.Index().SetUnique(true),
})
if err != nil {
- return nil, err
+ return nil, errs.Wrap(err)
}
return &ConversationMgo{coll: coll}, nil
}
diff --git a/pkg/common/db/mgo/group.go b/pkg/common/db/mgo/group.go
index a9c6d1eb8..9a4c660a6 100644
--- a/pkg/common/db/mgo/group.go
+++ b/pkg/common/db/mgo/group.go
@@ -16,6 +16,7 @@ package mgo
import (
"context"
+ "github.com/OpenIMSDK/tools/errs"
"time"
"github.com/OpenIMSDK/tools/mgoutil"
@@ -36,7 +37,7 @@ func NewGroupMongo(db *mongo.Database) (relation.GroupModelInterface, error) {
Options: options.Index().SetUnique(true),
})
if err != nil {
- return nil, err
+ return nil, errs.Wrap(err)
}
return &GroupMgo{coll: coll}, nil
}
diff --git a/pkg/common/db/mgo/group_member.go b/pkg/common/db/mgo/group_member.go
index 8e3dd1efa..fce79830e 100644
--- a/pkg/common/db/mgo/group_member.go
+++ b/pkg/common/db/mgo/group_member.go
@@ -16,6 +16,7 @@ package mgo
import (
"context"
+ "github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/mgoutil"
@@ -37,7 +38,7 @@ func NewGroupMember(db *mongo.Database) (relation.GroupMemberModelInterface, err
Options: options.Index().SetUnique(true),
})
if err != nil {
- return nil, err
+ return nil, errs.Wrap(err)
}
return &GroupMemberMgo{coll: coll}, nil
}
diff --git a/pkg/common/db/mgo/group_request.go b/pkg/common/db/mgo/group_request.go
index cb04d2308..dce0878ee 100644
--- a/pkg/common/db/mgo/group_request.go
+++ b/pkg/common/db/mgo/group_request.go
@@ -16,6 +16,7 @@ package mgo
import (
"context"
+ "github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
@@ -36,7 +37,7 @@ func NewGroupRequestMgo(db *mongo.Database) (relation.GroupRequestModelInterface
Options: options.Index().SetUnique(true),
})
if err != nil {
- return nil, err
+ return nil, errs.Wrap(err)
}
return &GroupRequestMgo{coll: coll}, nil
}
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 34a25ed08..2797bc53f 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -40,7 +40,7 @@ func NewUserMongo(db *mongo.Database) (relation.UserModelInterface, error) {
Options: options.Index().SetUnique(true),
})
if err != nil {
- return nil, err
+ return nil, errs.Wrap(err)
}
return &UserMgo{coll: coll}, nil
}
diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go
index b8184d767..e07c5b7f4 100644
--- a/pkg/common/db/unrelation/mongo.go
+++ b/pkg/common/db/unrelation/mongo.go
@@ -27,8 +27,6 @@ import (
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/mw/specialerror"
- "github.com/OpenIMSDK/tools/utils"
-
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
)
@@ -63,9 +61,9 @@ func NewMongo() (*Mongo, error) {
time.Sleep(time.Second) // exponential backoff could be implemented here
continue
}
- return nil, err
+ return nil, errs.Wrap(err)
}
- return nil, err
+ return nil, errs.Wrap(err)
}
func buildMongoURI() string {
@@ -150,7 +148,7 @@ func (m *Mongo) createMongoIndex(collection string, isUnique bool, keys ...strin
_, err := indexView.CreateOne(context.Background(), index, opts)
if err != nil {
- return utils.Wrap(err, "CreateIndex")
+ return errs.Wrap(err, "CreateIndex")
}
return nil
}
diff --git a/pkg/common/kafka/consumer_group.go b/pkg/common/kafka/consumer_group.go
index 1eb7b522a..05006f582 100644
--- a/pkg/common/kafka/consumer_group.go
+++ b/pkg/common/kafka/consumer_group.go
@@ -16,6 +16,8 @@ package kafka
import (
"context"
+ "github.com/OpenIMSDK/tools/errs"
+ "strings"
"github.com/OpenIMSDK/tools/log"
@@ -36,7 +38,7 @@ type MConsumerGroupConfig struct {
IsReturnErr bool
}
-func NewMConsumerGroup(consumerConfig *MConsumerGroupConfig, topics, addrs []string, groupID string) *MConsumerGroup {
+func NewMConsumerGroup(consumerConfig *MConsumerGroupConfig, topics, addrs []string, groupID string) (*MConsumerGroup, error) {
consumerGroupConfig := sarama.NewConfig()
consumerGroupConfig.Version = consumerConfig.KafkaVersion
consumerGroupConfig.Consumer.Offsets.Initial = consumerConfig.OffsetsInitial
@@ -49,26 +51,28 @@ func NewMConsumerGroup(consumerConfig *MConsumerGroupConfig, topics, addrs []str
SetupTLSConfig(consumerGroupConfig)
consumerGroup, err := sarama.NewConsumerGroup(addrs, groupID, consumerGroupConfig)
if err != nil {
- panic(err.Error())
+ return nil, errs.Wrap(err, strings.Join(topics, ","), strings.Join(addrs, ","), groupID)
}
return &MConsumerGroup{
consumerGroup,
groupID,
topics,
- }
+ }, nil
}
func (mc *MConsumerGroup) GetContextFromMsg(cMsg *sarama.ConsumerMessage) context.Context {
return GetContextWithMQHeader(cMsg.Headers)
}
-func (mc *MConsumerGroup) RegisterHandleAndConsumer(handler sarama.ConsumerGroupHandler) {
+func (mc *MConsumerGroup) RegisterHandleAndConsumer(ctx context.Context, handler sarama.ConsumerGroupHandler) {
log.ZDebug(context.Background(), "register consumer group", "groupID", mc.groupID)
- ctx := context.Background()
for {
err := mc.ConsumerGroup.Consume(ctx, mc.topics, handler)
if err != nil {
- panic(err.Error())
+ log.ZWarn(ctx, "consume err", err, "topic", mc.topics, "groupID", mc.groupID)
+ }
+ if ctx.Err() != nil {
+ return
}
}
}
diff --git a/pkg/common/kafka/producer.go b/pkg/common/kafka/producer.go
index 06b1e2b4c..b9f0b4656 100644
--- a/pkg/common/kafka/producer.go
+++ b/pkg/common/kafka/producer.go
@@ -18,6 +18,7 @@ import (
"bytes"
"context"
"errors"
+ "github.com/OpenIMSDK/tools/errs"
"strings"
"time"
@@ -44,7 +45,7 @@ type Producer struct {
}
// NewKafkaProducer initializes a new Kafka producer.
-func NewKafkaProducer(addr []string, topic string) *Producer {
+func NewKafkaProducer(addr []string, topic string) (*Producer, error) {
p := Producer{
addr: addr,
topic: topic,
@@ -87,17 +88,17 @@ func NewKafkaProducer(addr []string, topic string) *Producer {
for i := 0; i <= maxRetry; i++ {
p.producer, err = sarama.NewSyncProducer(p.addr, p.config)
if err == nil {
- return &p
+ return &p, nil
}
time.Sleep(1 * time.Second) // Wait before retrying
}
// Panic if unable to create producer after retries
if err != nil {
- panic("Failed to create Kafka producer: " + err.Error())
+ return nil, errs.Wrap(errors.New("failed to create Kafka producer: " + err.Error()))
}
- return &p
+ return &p, nil
}
// configureProducerAck configures the producer's acknowledgement level.
diff --git a/pkg/common/startrpc/start.go b/pkg/common/startrpc/start.go
index 8295404d3..31fe4fdd5 100644
--- a/pkg/common/startrpc/start.go
+++ b/pkg/common/startrpc/start.go
@@ -17,6 +17,7 @@ package startrpc
import (
"errors"
"fmt"
+ "github.com/OpenIMSDK/tools/errs"
"log"
"net"
"net/http"
@@ -43,7 +44,6 @@ import (
"github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/mw"
"github.com/OpenIMSDK/tools/network"
- "github.com/OpenIMSDK/tools/utils"
)
// Start rpc server.
@@ -61,20 +61,20 @@ func Start(
net.JoinHostPort(network.GetListenIP(config.Config.Rpc.ListenIP), strconv.Itoa(rpcPort)),
)
if err != nil {
- return err
+ return errs.Wrap(err, network.GetListenIP(config.Config.Rpc.ListenIP), strconv.Itoa(rpcPort))
}
defer listener.Close()
client, err := kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery)
if err != nil {
- return utils.Wrap1(err)
+ return errs.Wrap(err)
}
defer client.Close()
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
registerIP, err := network.GetRpcRegisterIP(config.Config.Rpc.RegisterIP)
if err != nil {
- return err
+ return errs.Wrap(err)
}
var reg *prometheus.Registry
@@ -96,7 +96,7 @@ func Start(
err = rpcFn(client, srv)
if err != nil {
- return utils.Wrap1(err)
+ return errs.Wrap(err)
}
err = client.Register(
rpcRegisterName,
@@ -105,7 +105,7 @@ func Start(
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
- return utils.Wrap1(err)
+ return errs.Wrap(err)
}
var wg errgroup.Group
@@ -123,7 +123,7 @@ func Start(
})
wg.Go(func() error {
- return utils.Wrap1(srv.Serve(listener))
+ return errs.Wrap(srv.Serve(listener))
})
sigs := make(chan os.Signal, 1)
@@ -146,7 +146,7 @@ func Start(
return gerr
case <-time.After(15 * time.Second):
- return utils.Wrap1(errors.New("timeout exit"))
+ return errs.Wrap(errors.New("timeout exit"))
}
}
From bb862bd20768d0b2701cca1ef8d1e3fd3322169e Mon Sep 17 00:00:00 2001
From: OpenIM Bot <124379614+kubbot@users.noreply.github.com>
Date: Fri, 2 Feb 2024 11:41:01 +0800
Subject: [PATCH 102/110] cicd: bump League Patch (#1863)
---
pkg/rpcclient/third.go | 3 ++-
tools/component/component.go | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/pkg/rpcclient/third.go b/pkg/rpcclient/third.go
index 0d5708fc8..73d874005 100755
--- a/pkg/rpcclient/third.go
+++ b/pkg/rpcclient/third.go
@@ -16,10 +16,11 @@ package rpcclient
import (
"context"
+ "net/url"
+
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"google.golang.org/grpc"
- "net/url"
"github.com/OpenIMSDK/protocol/third"
"github.com/OpenIMSDK/tools/discoveryregistry"
diff --git a/tools/component/component.go b/tools/component/component.go
index 4200b46f5..823d8174b 100644
--- a/tools/component/component.go
+++ b/tools/component/component.go
@@ -24,6 +24,7 @@ import (
"github.com/OpenIMSDK/tools/component"
"github.com/OpenIMSDK/tools/errs"
+
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"gopkg.in/yaml.v3"
@@ -305,4 +306,4 @@ func getMinioAddr(key1, key2, key3, fallback string) (string, error) {
endpoint = strings.Join(arr, ":")
}
return endpoint, nil
-}
\ No newline at end of file
+}
From f551b50e7909f012457add662c42937be10dd6d7 Mon Sep 17 00:00:00 2001
From: Brabem <69128477+luhaoling@users.noreply.github.com>
Date: Fri, 2 Feb 2024 16:21:14 +0800
Subject: [PATCH 103/110] fix: Refactoring the code for component detection
(#1868)
* feat: add component check func
* fix: fix the outpu error
* fix: fix the stderr outpu
* fix: fix the component check func
* fix: fix the error
* fix: fix the output error
* fix: del the disruptions code
* fix the log output format
* fix: fix the tools version
---
go.mod | 2 +-
go.sum | 4 +-
pkg/common/db/cache/init_redis.go | 5 +-
pkg/common/db/unrelation/mongo.go | 4 +-
.../discoveryregister/zookeeper/zookeeper.go | 14 +-
pkg/common/kafka/consumer_group.go | 2 +-
tools/component/component.go | 249 +++++++-----------
7 files changed, 115 insertions(+), 165 deletions(-)
diff --git a/go.mod b/go.mod
index a5fecb5ee..16a10a945 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
github.com/OpenIMSDK/protocol v0.0.48
- github.com/OpenIMSDK/tools v0.0.31
+ github.com/OpenIMSDK/tools v0.0.32
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
diff --git a/go.sum b/go.sum
index fbd9366c3..136035cef 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,8 @@ github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
github.com/OpenIMSDK/protocol v0.0.48 h1:8MIMjyzJRsruYhVv2ZKArFiOveroaofDOb3dlAdgjsw=
github.com/OpenIMSDK/protocol v0.0.48/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.31 h1:fSrhcPTvHEMTSyrJZDupe730mL4nuhvSOUP/BaZiHaY=
-github.com/OpenIMSDK/tools v0.0.31/go.mod h1:wBfR5CYmEyvxl03QJbTkhz1CluK6J4/lX0lviu8JAjE=
+github.com/OpenIMSDK/tools v0.0.32 h1:b8KwtxXKZTsyyHUcZ4OtSo6s/vVXx4HjMuPxH7Kb7Gg=
+github.com/OpenIMSDK/tools v0.0.32/go.mod h1:wBfR5CYmEyvxl03QJbTkhz1CluK6J4/lX0lviu8JAjE=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
diff --git a/pkg/common/db/cache/init_redis.go b/pkg/common/db/cache/init_redis.go
index c593089e6..3cec73be5 100644
--- a/pkg/common/db/cache/init_redis.go
+++ b/pkg/common/db/cache/init_redis.go
@@ -77,9 +77,10 @@ func NewRedis() (redis.UniversalClient, error) {
defer cancel()
err = rdb.Ping(ctx).Err()
if err != nil {
- return nil, errs.Wrap(fmt.Errorf("redis ping %w", err))
+ uriFormat := "address:%s, username:%s, password:%s, clusterMode:%t, enablePipeline:%t"
+ errMsg := fmt.Sprintf(uriFormat, config.Config.Redis.Address, config.Config.Redis.Username, config.Config.Redis.Password, config.Config.Redis.ClusterMode, config.Config.Redis.EnablePipeline)
+ return nil, errs.Wrap(err, errMsg)
}
-
redisClient = rdb
return rdb, err
}
diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go
index e07c5b7f4..fe89c6b8a 100644
--- a/pkg/common/db/unrelation/mongo.go
+++ b/pkg/common/db/unrelation/mongo.go
@@ -61,9 +61,9 @@ func NewMongo() (*Mongo, error) {
time.Sleep(time.Second) // exponential backoff could be implemented here
continue
}
- return nil, errs.Wrap(err)
+ return nil, errs.Wrap(err, uri)
}
- return nil, errs.Wrap(err)
+ return nil, errs.Wrap(err, uri)
}
func buildMongoURI() string {
diff --git a/pkg/common/discoveryregister/zookeeper/zookeeper.go b/pkg/common/discoveryregister/zookeeper/zookeeper.go
index db1a5c6c4..0082e9833 100644
--- a/pkg/common/discoveryregister/zookeeper/zookeeper.go
+++ b/pkg/common/discoveryregister/zookeeper/zookeeper.go
@@ -15,6 +15,8 @@
package zookeeper
import (
+ "fmt"
+ "github.com/OpenIMSDK/tools/errs"
"os"
"strings"
"time"
@@ -33,7 +35,7 @@ func NewZookeeperDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, er
username := getEnv("ZOOKEEPER_USERNAME", config.Config.Zookeeper.Username)
password := getEnv("ZOOKEEPER_PASSWORD", config.Config.Zookeeper.Password)
- return openkeeper.NewClient(
+ zk, err := openkeeper.NewClient(
zkAddr,
schema,
openkeeper.WithFreq(time.Hour),
@@ -42,6 +44,16 @@ func NewZookeeperDiscoveryRegister() (discoveryregistry.SvcDiscoveryRegistry, er
openkeeper.WithTimeout(10),
openkeeper.WithLogger(log.NewZkLogger()),
)
+ if err != nil {
+ uriFormat := "address:%s, username :%s, password :%s, schema:%s."
+ errInfo := fmt.Sprintf(uriFormat,
+ config.Config.Zookeeper.ZkAddr,
+ config.Config.Zookeeper.Username,
+ config.Config.Zookeeper.Password,
+ config.Config.Zookeeper.Schema)
+ return nil, errs.Wrap(err, errInfo)
+ }
+ return zk, nil
}
// getEnv returns the value of an environment variable if it exists, otherwise it returns the fallback value.
diff --git a/pkg/common/kafka/consumer_group.go b/pkg/common/kafka/consumer_group.go
index 05006f582..87e6d5686 100644
--- a/pkg/common/kafka/consumer_group.go
+++ b/pkg/common/kafka/consumer_group.go
@@ -51,7 +51,7 @@ func NewMConsumerGroup(consumerConfig *MConsumerGroupConfig, topics, addrs []str
SetupTLSConfig(consumerGroupConfig)
consumerGroup, err := sarama.NewConsumerGroup(addrs, groupID, consumerGroupConfig)
if err != nil {
- return nil, errs.Wrap(err, strings.Join(topics, ","), strings.Join(addrs, ","), groupID)
+ return nil, errs.Wrap(err, strings.Join(topics, ","), strings.Join(addrs, ","), groupID, config.Config.Kafka.Username, config.Config.Kafka.Password)
}
return &MConsumerGroup{
consumerGroup,
diff --git a/tools/component/component.go b/tools/component/component.go
index 823d8174b..787ca8af6 100644
--- a/tools/component/component.go
+++ b/tools/component/component.go
@@ -15,9 +15,13 @@
package main
import (
- "errors"
"flag"
"fmt"
+ "github.com/IBM/sarama"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/zookeeper"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/kafka"
"os"
"strings"
"time"
@@ -32,16 +36,12 @@ import (
const (
// defaultCfgPath is the default path of the configuration file.
- defaultCfgPath = "../../../../../config/config.yaml"
- maxRetry = 300
- componentStartErrCode = 6000
- configErrCode = 6001
+ defaultCfgPath = "../../../../../config/config.yaml"
+ maxRetry = 300
)
var (
- cfgPath = flag.String("c", defaultCfgPath, "Path to the configuration file")
- ErrComponentStart = errs.NewCodeError(componentStartErrCode, "ComponentStartErr")
- ErrConfig = errs.NewCodeError(configErrCode, "Config file is incorrect")
+ cfgPath = flag.String("c", defaultCfgPath, "Path to the configuration file")
)
func initCfg() error {
@@ -55,7 +55,7 @@ func initCfg() error {
type checkFunc struct {
name string
- function func() (string, error)
+ function func() error
}
func main() {
@@ -67,11 +67,13 @@ func main() {
return
}
+ configGetEnv()
+
checks := []checkFunc{
//{name: "Mysql", function: checkMysql},
{name: "Mongo", function: checkMongo},
- {name: "Minio", function: checkMinio},
{name: "Redis", function: checkRedis},
+ {name: "Minio", function: checkMinio},
{name: "Zookeeper", function: checkZookeeper},
{name: "Kafka", function: checkKafka},
}
@@ -82,165 +84,81 @@ func main() {
}
fmt.Printf("Checking components Round %v...\n", i+1)
+ var err error
allSuccess := true
for _, check := range checks {
- str, err := check.function()
+ err = check.function()
if err != nil {
- component.ErrorPrint(fmt.Sprintf("Starting %s failed, %v", check.name, err))
+ component.ErrorPrint(fmt.Sprintf("Starting %s failed:%v.", check.name, err))
allSuccess = false
- break
} else {
- component.SuccessPrint(fmt.Sprintf("%s connected successfully, %s", check.name, str))
+ component.SuccessPrint(fmt.Sprintf("%s connected successfully", check.name))
}
}
if allSuccess {
component.SuccessPrint("All components started successfully!")
-
return
}
}
- os.Exit(1)
-}
-
-// Helper function to get environment variable or default value
-func getEnv(key, fallback string) string {
- if value, exists := os.LookupEnv(key); exists {
- return value
- }
- return fallback
}
// checkMongo checks the MongoDB connection without retries
-func checkMongo() (string, error) {
- mongo := &component.Mongo{
- Address: config.Config.Mongo.Address,
- Database: config.Config.Mongo.Database,
- Username: config.Config.Mongo.Username,
- Password: config.Config.Mongo.Password,
- MaxPoolSize: config.Config.Mongo.MaxPoolSize,
- }
- uri, uriExist := os.LookupEnv("MONGO_URI")
- if uriExist {
- mongo.URL = uri
- }
+func checkMongo() error {
+ _, err := unrelation.NewMongo()
+ return err
+}
- str, err := component.CheckMongo(mongo)
- if err != nil {
- return "", err
- }
- return str, nil
+// checkRedis checks the Redis connection
+func checkRedis() error {
+ _, err := cache.NewRedis()
+ return err
}
// checkMinio checks the MinIO connection
-func checkMinio() (string, error) {
+func checkMinio() error {
+
// Check if MinIO is enabled
if config.Config.Object.Enable != "minio" {
- return "", nil
+ return nil
}
-
- endpoint, err := getMinioAddr("MINIO_ENDPOINT", "MINIO_ADDRESS", "MINIO_PORT", config.Config.Object.Minio.Endpoint)
- if err != nil {
- return "", err
- }
-
minio := &component.Minio{
ApiURL: config.Config.Object.ApiURL,
- Endpoint: endpoint,
- AccessKeyID: getEnv("MINIO_ACCESS_KEY_ID", config.Config.Object.Minio.AccessKeyID),
- SecretAccessKey: getEnv("MINIO_SECRET_ACCESS_KEY", config.Config.Object.Minio.SecretAccessKey),
+ Endpoint: config.Config.Object.Minio.Endpoint,
+ AccessKeyID: config.Config.Object.Minio.AccessKeyID,
+ SecretAccessKey: config.Config.Object.Minio.SecretAccessKey,
SignEndpoint: config.Config.Object.Minio.SignEndpoint,
UseSSL: getEnv("MINIO_USE_SSL", "false"),
}
-
- str, err := component.CheckMinio(minio)
- if err != nil {
- return "", err
- }
- return str, nil
-}
-
-// checkRedis checks the Redis connection
-func checkRedis() (string, error) {
- // Prioritize environment variables
- address := getEnv("REDIS_ADDRESS", strings.Join(config.Config.Redis.Address, ","))
- username := getEnv("REDIS_USERNAME", config.Config.Redis.Username)
- password := getEnv("REDIS_PASSWORD", config.Config.Redis.Password)
-
- redis := &component.Redis{
- Address: strings.Split(address, ","),
- Username: username,
- Password: password,
- }
-
- addresses, err := getAddress("REDIS_ADDRESS", "REDIS_PORT", config.Config.Redis.Address)
- if err != nil {
- return "", err
- }
- redis.Address = addresses
-
- str, err := component.CheckRedis(redis)
- if err != nil {
- return "", err
- }
- return str, nil
+ _, err := component.CheckMinio(minio)
+ return err
}
// checkZookeeper checks the Zookeeper connection
-func checkZookeeper() (string, error) {
- // Prioritize environment variables
-
- address := getEnv("ZOOKEEPER_ADDRESS", strings.Join(config.Config.Zookeeper.ZkAddr, ","))
-
- zk := &component.Zookeeper{
- Schema: getEnv("ZOOKEEPER_SCHEMA", "digest"),
- ZkAddr: strings.Split(address, ","),
- Username: getEnv("ZOOKEEPER_USERNAME", config.Config.Zookeeper.Username),
- Password: getEnv("ZOOKEEPER_PASSWORD", config.Config.Zookeeper.Password),
- }
-
- addresses, err := getAddress("ZOOKEEPER_ADDRESS", "ZOOKEEPER_PORT", config.Config.Zookeeper.ZkAddr)
- if err != nil {
- return "", nil
- }
- zk.ZkAddr = addresses
-
- str, err := component.CheckZookeeper(zk)
- if err != nil {
- return "", err
- }
- return str, nil
+func checkZookeeper() error {
+ _, err := zookeeper.NewZookeeperDiscoveryRegister()
+ return err
}
// checkKafka checks the Kafka connection
-func checkKafka() (string, error) {
+func checkKafka() error {
// Prioritize environment variables
- username := getEnv("KAFKA_USERNAME", config.Config.Kafka.Username)
- password := getEnv("KAFKA_PASSWORD", config.Config.Kafka.Password)
- address := getEnv("KAFKA_ADDRESS", strings.Join(config.Config.Kafka.Addr, ","))
-
- kafka := &component.Kafka{
- Username: username,
- Password: password,
- Addr: strings.Split(address, ","),
+ kafkaStu := &component.Kafka{
+ Username: config.Config.Kafka.Username,
+ Password: config.Config.Kafka.Password,
+ Addr: config.Config.Kafka.Addr,
}
- addresses, err := getAddress("KAFKA_ADDRESS", "KAFKA_PORT", config.Config.Kafka.Addr)
+ _, kafkaClient, err := component.CheckKafka(kafkaStu)
if err != nil {
- return "", nil
- }
- kafka.Addr = addresses
-
- str, kafkaClient, err := component.CheckKafka(kafka)
- if err != nil {
- return "", err
+ return err
}
defer kafkaClient.Close()
// Verify if necessary topics exist
topics, err := kafkaClient.Topics()
if err != nil {
- return "", errs.Wrap(err)
+ return errs.Wrap(err)
}
requiredTopics := []string{
@@ -251,11 +169,38 @@ func checkKafka() (string, error) {
for _, requiredTopic := range requiredTopics {
if !isTopicPresent(requiredTopic, topics) {
- return "", ErrComponentStart.Wrap(fmt.Sprintf("Kafka doesn't contain topic: %v", requiredTopic))
+ return errs.Wrap(err, fmt.Sprintf("Kafka doesn't contain topic: %v", requiredTopic))
}
}
- return str, nil
+ _, err = kafka.NewMConsumerGroup(&kafka.MConsumerGroupConfig{
+ KafkaVersion: sarama.V2_0_0_0,
+ OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
+ }, []string{config.Config.Kafka.LatestMsgToRedis.Topic},
+ config.Config.Kafka.Addr, config.Config.Kafka.ConsumerGroupID.MsgToRedis)
+ if err != nil {
+ return err
+ }
+
+ _, err = kafka.NewMConsumerGroup(&kafka.MConsumerGroupConfig{
+ KafkaVersion: sarama.V2_0_0_0,
+ OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
+ }, []string{config.Config.Kafka.MsgToPush.Topic},
+ config.Config.Kafka.Addr, config.Config.Kafka.ConsumerGroupID.MsgToMongo)
+ if err != nil {
+ return err
+ }
+
+ kafka.NewMConsumerGroup(&kafka.MConsumerGroupConfig{
+ KafkaVersion: sarama.V2_0_0_0,
+ OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
+ }, []string{config.Config.Kafka.MsgToPush.Topic}, config.Config.Kafka.Addr,
+ config.Config.Kafka.ConsumerGroupID.MsgToPush)
+ if err != nil {
+ return err
+ }
+
+ return nil
}
// isTopicPresent checks if a topic is present in the list of topics
@@ -268,42 +213,34 @@ func isTopicPresent(topic string, topics []string) bool {
return false
}
-func getAddress(key1, key2 string, fallback []string) ([]string, error) {
- address, addrExist := os.LookupEnv(key1)
- port, portExist := os.LookupEnv(key2)
-
- if addrExist && portExist {
- addresses := strings.Split(address, ",")
- for i, addr := range addresses {
- addresses[i] = addr + ":" + port
- }
- return addresses, nil
- } else if !addrExist && portExist {
- result := make([]string, len(config.Config.Redis.Address))
- for i, addr := range config.Config.Redis.Address {
- add := strings.Split(addr, ":")
- result[i] = add[0] + ":" + port
- }
- return result, nil
- } else if addrExist && !portExist {
- return nil, errs.Wrap(errors.New("the ZOOKEEPER_PORT of minio is empty"))
- }
- return fallback, nil
+func configGetEnv() {
+ config.Config.Object.Minio.AccessKeyID = getEnv("MINIO_ACCESS_KEY_ID", config.Config.Object.Minio.AccessKeyID)
+ config.Config.Object.Minio.SecretAccessKey = getEnv("MINIO_SECRET_ACCESS_KEY", config.Config.Object.Minio.SecretAccessKey)
+ config.Config.Mongo.Uri = getEnv("MONGO_URI", config.Config.Mongo.Uri)
+ config.Config.Mongo.Username = getEnv("MONGO_OPENIM_USERNAME", config.Config.Mongo.Username)
+ config.Config.Mongo.Password = getEnv("MONGO_OPENIM_PASSWORD", config.Config.Mongo.Password)
+ config.Config.Kafka.Username = getEnv("KAFKA_USERNAME", config.Config.Kafka.Username)
+ config.Config.Kafka.Password = getEnv("KAFKA_PASSWORD", config.Config.Kafka.Password)
+ config.Config.Kafka.Addr = strings.Split(getEnv("KAFKA_ADDRESS", strings.Join(config.Config.Kafka.Addr, ",")), ",")
+ config.Config.Object.Minio.Endpoint = getMinioAddr("MINIO_ENDPOINT", "MINIO_ADDRESS", "MINIO_PORT", config.Config.Object.Minio.Endpoint)
}
-func getMinioAddr(key1, key2, key3, fallback string) (string, error) {
+func getMinioAddr(key1, key2, key3, fallback string) string {
// Prioritize environment variables
endpoint := getEnv(key1, fallback)
address, addressExist := os.LookupEnv(key2)
port, portExist := os.LookupEnv(key3)
if portExist && addressExist {
endpoint = "http://" + address + ":" + port
- } else if !portExist && addressExist {
- return "", errs.Wrap(errors.New("the MINIO_PORT of minio is empty"))
- } else if portExist && !addressExist {
- arr := strings.Split(config.Config.Object.Minio.Endpoint, ":")
- arr[2] = port
- endpoint = strings.Join(arr, ":")
+ return endpoint
}
- return endpoint, nil
+ return endpoint
+}
+
+// Helper function to get environment variable or default value
+func getEnv(key, fallback string) string {
+ if value, exists := os.LookupEnv(key); exists {
+ return value
+ }
+ return fallback
}
From af878a96cfca897906a57363c0754efe117dbeea Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <3293172751NSS@gmail.com>
Date: Fri, 2 Feb 2024 19:47:16 +0800
Subject: [PATCH 104/110] feat: add architecture layers (#1860)
* feat: add architecture layers
* feat: add architecture layers
* feat: add architecture layers
* feat: add .gitignore file
* feat: add .gitignore file
* feat: fix openim logs and ci
* feat: fix openim logs and ci
* feat: support openim readme docs
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
* Update main.go
---------
Signed-off-by: Xinwei Xiong (cubxxw) <3293172751nss@gmail.com>
---
CONTRIBUTING-zh_CN.md | 33 ++++
CONTRIBUTING.md | 211 +++++++++++++++++-----
README-zh_CN.md | 58 ++++--
README.md | 39 +++-
docs/README.md | 1 -
docs/README_ar.md | 67 -------
docs/README_cs.md | 67 -------
docs/README_da.md | 67 -------
docs/README_de.md | 66 -------
docs/README_el.md | 67 -------
docs/README_eo.md | 67 -------
docs/README_es.md | 67 -------
docs/README_fa.md | 67 -------
docs/README_fi.md | 67 -------
docs/README_fr.md | 66 -------
docs/README_hu.md | 67 -------
docs/README_id.md | 67 -------
docs/README_it.md | 67 -------
docs/README_ja.md | 67 -------
docs/README_ko.md | 67 -------
docs/README_ml.md | 67 -------
docs/README_nl.md | 67 -------
docs/README_pl.md | 67 -------
docs/README_pt_BR.md | 67 -------
docs/README_ru.md | 67 -------
docs/README_tr.md | 67 -------
docs/README_ua.md | 67 -------
docs/README_vi.md | 67 -------
docs/README_zh_CN.md | 67 -------
docs/README_zh_TW.md | 67 -------
docs/contributing/CONTRIBUTING-JP.md | 33 ++++
docs/contributing/CONTRIBUTING-PL.md | 33 ++++
docs/images/Open-IM-Servers-on-System.png | Bin 21614 -> 0 bytes
docs/images/Open-IM-Servers-on-docker.png | Bin 10172 -> 0 bytes
docs/images/architecture-layers.png | Bin 0 -> 293222 bytes
docs/images/build.png | Bin 62555 -> 0 bytes
docs/images/docker_build.png | Bin 58699 -> 0 bytes
docs/readme/README-UA.md | 7 +
38 files changed, 346 insertions(+), 1742 deletions(-)
create mode 100644 CONTRIBUTING-zh_CN.md
delete mode 100644 docs/README_ar.md
delete mode 100644 docs/README_cs.md
delete mode 100644 docs/README_da.md
delete mode 100644 docs/README_de.md
delete mode 100644 docs/README_el.md
delete mode 100644 docs/README_eo.md
delete mode 100644 docs/README_es.md
delete mode 100644 docs/README_fa.md
delete mode 100644 docs/README_fi.md
delete mode 100644 docs/README_fr.md
delete mode 100644 docs/README_hu.md
delete mode 100644 docs/README_id.md
delete mode 100644 docs/README_it.md
delete mode 100644 docs/README_ja.md
delete mode 100644 docs/README_ko.md
delete mode 100644 docs/README_ml.md
delete mode 100644 docs/README_nl.md
delete mode 100644 docs/README_pl.md
delete mode 100644 docs/README_pt_BR.md
delete mode 100644 docs/README_ru.md
delete mode 100644 docs/README_tr.md
delete mode 100644 docs/README_ua.md
delete mode 100644 docs/README_vi.md
delete mode 100644 docs/README_zh_CN.md
delete mode 100644 docs/README_zh_TW.md
create mode 100644 docs/contributing/CONTRIBUTING-JP.md
create mode 100644 docs/contributing/CONTRIBUTING-PL.md
delete mode 100644 docs/images/Open-IM-Servers-on-System.png
delete mode 100644 docs/images/Open-IM-Servers-on-docker.png
create mode 100644 docs/images/architecture-layers.png
delete mode 100644 docs/images/build.png
delete mode 100644 docs/images/docker_build.png
create mode 100644 docs/readme/README-UA.md
diff --git a/CONTRIBUTING-zh_CN.md b/CONTRIBUTING-zh_CN.md
new file mode 100644
index 000000000..ee3c0b8f8
--- /dev/null
+++ b/CONTRIBUTING-zh_CN.md
@@ -0,0 +1,33 @@
+# How do I contribute code to OpenIM
+
+
+ Englist ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
+
+
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ee275e7ad..f7d2c0749 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,6 +1,38 @@
-# Contributing to Open-IM-Server
-
-So, you want to hack on Open-IM-Server? Yay!
+# How do I contribute code to OpenIM
+
+
+ Englist ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
+
+
+
+
+So, you want to hack on open-im-server? Yay!
First of all, thank you for considering contributing to our project! We appreciate your time and effort, and we value any contribution, whether it's reporting a bug, suggesting a new feature, or submitting a pull request.
@@ -12,7 +44,7 @@ This document provides guidelines and best practices to help you contribute effe
## 📇Topics
-- [Contributing to Open-IM-Server](#contributing-to-open-im-server)
+- [How do I contribute code to OpenIM](#how-do-i-contribute-code-to-openim)
- [📇Topics](#topics)
- [What we expect of you](#what-we-expect-of-you)
- [Code of ConductCode of Conduct](#code-of-conductcode-of-conduct)
@@ -32,13 +64,13 @@ This document provides guidelines and best practices to help you contribute effe
## What we expect of you
-We hope that anyone can join Open-IM-Server , even if you are a student, writer, translator
+We hope that anyone can join open-im-server , even if you are a student, writer, translator
-Please meet the minimum version of the Go language published in [go.mod](./go.mod). If you want to manage the Go language version, we provide tools to install [gvm](https://github.com/moovweb/gvm) in our [Makefile](./Makefile)
+Please meet the minimum version of the Go language published in [go.mod](./go.mod). If you want to manage the Go language version, we provide tools tHow do I contribute code to OpenIMo install [gvm](https://github.com/moovweb/gvm) in our [Makefile](./Makefile)
-You'd better use Linux OR WSL as the development environment, Linux with [Makefile](./Makefile) can help you quickly build and test Open-IM-Server project.
+You'd better use Linux OR WSL as the development environment, Linux with [Makefile](./Makefile) can help you quickly build and test open-im-server project.
-If you are familiar with [Makefile](./Makefile) , you can easily see the clever design of the Open-IM-Server Makefile. Storing the necessary tools such as golangci in the `/tools` directory can avoid some tool version issues.
+If you are familiar with [Makefile](./Makefile) , you can easily see the clever design of the open-im-server Makefile. Storing the necessary tools such as golangci in the `/tools` directory can avoid some tool version issues.
The [Makefile](./Makefile) is for every developer, even if you don't know how to use the Makefile tool, don't worry, we provide two great commands to get you up to speed with the Makefile architecture, `make help` and `make help-all`, it can reduce problems of the developing environment.
@@ -52,7 +84,7 @@ In accordance with the naming conventions adopted by OpenIM and drawing referenc
#### Code and doc contribution
-Every action to make project Open-IM-Server better is encouraged. On GitHub, every improvement for Open-IM-Server could be via a [PR](https://github.com/openimsdk/open-im-server/pulls) (short for pull request).
+Every action to make project open-im-server better is encouraged. On GitHub, every improvement for open-im-server could be via a [PR](https://github.com/openimsdk/open-im-server/pulls) (short for pull request).
+ If you find a typo, try to fix it!
+ If you find a bug, try to fix it!
@@ -67,8 +99,8 @@ Every action to make project Open-IM-Server better is encouraged. On GitHub, eve
#### Where should I start?
-+ If you are new to the project, don't know how to contribute Open-IM-Server, please check out the [good first issue](https://github.com/openimsdk/open-im-server/issues?q=is%3Aopen+label%3A"good+first+issue"+sort%3Aupdated-desc) label.
-+ You should be good at filtering the Open-IM-Server issue tags and finding the ones you like, such as [RFC](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) for big initiatives, features for [feature](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+label%3Afeature) proposals, and [bug](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+label%3Abug+) fixes.
++ If you are new to the project, don't know how to contribute open-im-server, please check out the [good first issue](https://github.com/openimsdk/open-im-server/issues?q=is%3Aopen+label%3A"good+first+issue"+sort%3Aupdated-desc) label.
++ You should be good at filtering the open-im-server issue tags and finding the ones you like, such as [RFC](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) for big initiatives, features for [feature](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+label%3Afeature) proposals, and [bug](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+label%3Abug+) fixes.
+ If you are looking for something to work on, check out our [open issues](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
+ If you have an idea for a new feature, please [open an issue](https://github.com/openimsdk/open-im-server/issues/new/choose), and we can discuss it.
@@ -85,7 +117,7 @@ When documenting a new design, we recommend a 2-step approach:
1. Use the short-form RFC template to outline your ideas and get early feedback.
2. Once you have received sufficient feedback and consensus, you may use the longer-form design doc template to specify and discuss your design in more details.
-In order to contribute a feature to Open-IM-Server you'll need to go through the following steps:
+In order to contribute a feature to open-im-server you'll need to go through the following steps:
+ Discuss your idea with the appropriate [working groups](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q) on the working group's Slack channel.
+ Once there is general agreement that the feature is useful, create a GitHub issue to track the discussion. The issue should include information about the requirements and use cases that it is trying to address.
@@ -95,13 +127,27 @@ But keep in mind that there is no guarantee of it being accepted and so it is us
## Getting Started
-To propose PR for the Open-IM-Server item, we assume you have registered a GitHub ID. Then you could finish the preparation in the following steps:
+To propose PR for the open-im-server item, we assume you have registered a GitHub ID. Then you could finish the preparation in the following steps:
+
+1. Fork the repository(open-im-server)
+
+2. **CLONE** your own repository to main locally. Use `git clone https://github.com//open-im-server.git` to clone repository to your local machine. Then you can create new branches to finish the change you wish to make.
+
+3. **Initialize Git Hooks with `make init-githooks`**
+
+ After cloning the repository, it's recommended to set up Git hooks to streamline your workflow and ensure your contributions adhere to OpenIM's community standards. Git hooks are scripts that run automatically every time a particular event occurs in a Git repository, such as before a commit or push. To initialize Git hooks for the OpenIM server repository, use the `make init-githooks` command.
-1. Fork the repository(Open-IM-Server)
+ - **Enabling Git Hooks Mode**: By running `make init-githooks` and entering `1` when prompted, you enable Git hooks mode. This action will generate a series of hooks within the `.git/hooks/` directory. These hooks impose certain checks on your commits and pushes, ensuring they meet the quality and standards expected by the OpenIM community. For instance, commit hooks might enforce a specific commit message format, while push hooks could check for code style or linting issues.
-2. **CLONE** your own repository to main locally. Use `git clone https://github.com//Open-IM-Server.git` to clone repository to your local machine. Then you can create new branches to finish the change you wish to make.
+ - **Benefits for First-Time Contributors**: This setup is especially beneficial for new contributors. It guides you to make professional, community-standard-compliant Pull Requests (PRs) and PR descriptions right from your first contribution. By automating checks and balances, it reduces the chances of common mistakes and speeds up the review process.
-3. **Set Remote** upstream to be `https://github.com/openimsdk/open-im-server.git` using the following two commands:
+ - **Disabling Git Hooks**: If for any reason you wish to remove the Git hooks, simply run `make init-githooks` again and enter `2` when prompted. This will delete the existing Git hooks, removing the automatic checks and constraints from your Git operations. However, keep in mind that manually ensuring your contributions adhere to community standards without the aid of Git hooks requires diligence.
+
+ > [!NOTE] Utilizing Git hooks through the `make init-githooks` command is a straightforward yet powerful way to ensure your contributions are consistent and high-quality. It's a step towards fostering a professional and efficient development environment in the OpenIM project.
+
+
+
+4. **Set Remote** upstream to be `https://github.com/openimsdk/open-im-server.git` using the following two commands:
```bash
❯ git remote add upstream https://github.com/openimsdk/open-im-server.git
@@ -112,18 +158,18 @@ To propose PR for the Open-IM-Server item, we assume you have registered a GitHu
```bash
❯ git remote -v
- origin https://github.com//Open-IM-Server.git (fetch)
- origin https://github.com//Open-IM-Server.git (push)
+ origin https://github.com//open-im-server.git (fetch)
+ origin https://github.com//open-im-server.git (push)
upstream https://github.com/openimsdk/open-im-server.git (fetch)
upstream no-pushing (push)
```
Adding this, we can easily synchronize local branches with upstream branches.
-4. Create a new branch for your changes (use a descriptive name, such as `fix-bug-123` or `add-new-feature`).
+5. Create a new branch for your changes (use a descriptive name, such as `fix-bug-123` or `add-new-feature`).
```bash
- ❯ cd Open-IM-Server
+ ❯ cd open-im-server
❯ git fetch upstream
❯ git checkout upstream/main
```
@@ -136,7 +182,8 @@ To propose PR for the Open-IM-Server item, we assume you have registered a GitHu
Make any change on the `new-branch` then use [Makefile](./Makefile) build and test your codes.
-5. **Commit your changes** to your local branch, lint before committing and commit with sign-off
+
+6. **Commit your changes** to your local branch, lint before committing and commit with sign-off
```bash
❯ git rebase upstream/main
@@ -145,7 +192,7 @@ To propose PR for the Open-IM-Server item, we assume you have registered a GitHu
❯ git commit -a -s -m "message for your changes" # -s adds a Signed-off-by trailer
```
-6. **Push your branch** to your forked repository, it is recommended to have only one commit for a PR.
+7. **Push your branch** to your forked repository, it is recommended to have only one commit for a PR.
```bash
# sync up with upstream
@@ -177,12 +224,78 @@ To propose PR for the Open-IM-Server item, we assume you have registered a GitHu
❯ git rebase upstream/main # rebase the current branch to upstream/main branch
❯ git add -A
❯ git commit -m -s "feat: feature two"
- # then create pull request, and merge
```
-7. **Open a pull request** to `openimsdk/open-im-server:main`
+ **Verifying Your Pull Request with `make all` Command**
+
+ Before verifying, you may need to complete the basic deployment of OpenIM to get familiar with the deployment status of OpenIM. Please read [this deployment document](https://docs.openim.io/zh-Hans/guides/gettingStarted/imSourceCodeDeployment), which will tell you how to deploy OpenIM middleware and OpenIM services in detail
+
+ Before submitting your Pull Request (PR), it's crucial to ensure that it passes all the necessary checks and verifications to maintain the quality and integrity of the OpenIM server project. To facilitate this process, we have encapsulated a series of validation steps into the `make all` command.
+
+ - **Purpose of `make all` Command**: The `make all` command serves as a comprehensive pre-PR verification tool. It sequentially executes a variety of tasks designed to scrutinize your changes from multiple angles, ensuring they are ready for submission.
+
+ - **Included Commands**:
+ - `tidy`: Cleans up the module by removing unused dependencies.
+ - `gen`: Generates necessary files from templates or specifications, ensuring that your codebase is up-to-date with its dependencies.
+ - `add-copyright`: Checks for and adds copyright notices to files, ensuring compliance with legal requirements.
+ - `verify`: Verifies the integrity and consistency of the code, dependencies, and various checks.
+ - `test-api`: Runs API tests to ensure that your changes do not break any existing functionality and adhere to the expected behaviors.
+ - `lint`: Analyzes the code for potential stylistic or programming errors, enforcing the project's coding standards.
+ - `cover`: Measures the code coverage of tests, helping you understand how much of the code is being tested.
+ - `restart`: (Optionally) restarts services or applications to ensure that changes are correctly applied and functioning in a live environment.
+
+ - **Executing the Command**: To run the `make all` command, simply navigate to the root directory of your cloned repository in your terminal and execute:
+ ```bash
+ make all
+ ```
+ This command will sequentially perform all the listed actions, outputting any warnings or errors encountered during the process. It's a vital step to catch any issues early and ensure your contribution meets the quality standards set by the OpenIM community.
+
+ - **Benefits**: By using `make all` for pre-PR verification, you significantly increase the likelihood of your PR being accepted on the first review. It not only demonstrates your commitment to quality but also streamlines the review process by minimizing back-and-forth due to common issues that can be caught automatically.
+
+
+ **Troubleshooting Git Push Failures**
+
+ When working with Git, encountering errors during push operations is not uncommon. Two primary reasons you might face push failures are due to firewall restrictions or authentication issues. Here’s how you can troubleshoot and resolve these problems.
+
+ **Firewall Errors**
+
+ If you're behind a corporate firewall or your network restricts certain types of traffic, you might encounter issues when trying to push your changes via HTTPS. This is because firewalls can block the ports used by the HTTPS protocol. To resolve this issue, you can configure Git to use a proxy.
+
+ If you have a local proxy server set up, you can direct Git to use it by setting the `https_proxy` and `http_proxy` environment variables. Open your terminal or command prompt and run the following commands:
+
+ ```bash
+ export https_proxy="http://127.0.0.1:7890"
+ export http_proxy="http://127.0.0.1:7890"
+ ```
+
+ Replace `127.0.0.1:7890` with the address and port of your proxy server. These commands set the proxy for the current session. If you want to make these changes permanent, add them to your `.bashrc`, `.bash_profile`, or equivalent shell configuration file.
+
+ **Using SSH Instead of HTTPS**
+
+ An alternative to using HTTPS is to set up an SSH connection for Git operations. SSH connections are often not blocked by firewalls and do not require proxy settings. Additionally, SSH provides a secure channel and can simplify the authentication process since it relies on SSH keys rather than username and password credentials.
+
+ To use SSH with Git, you first need to generate an SSH key pair and add the public key to your GitHub account (or another Git hosting service).
+
+ 1. **Generate SSH Key Pair**: Open your terminal and run `ssh-keygen -t rsa -b 4096 -C "your_email@example.com"`, replacing `your_email@example.com` with your email. Press enter to accept the default file location and passphrase prompts.
+
+ 2. **Add SSH Key to SSH-Agent**: Ensure the ssh-agent is running with `eval "$(ssh-agent -s)"` and then add your SSH private key to the ssh-agent using `ssh-add ~/.ssh/id_rsa`.
+
+ 3. **Add SSH Key to GitHub**: Copy your SSH public key to your clipboard with `cat ~/.ssh/id_rsa.pub | clip` (Windows) or `pbcopy < ~/.ssh/id_rsa.pub` (Mac). Go to GitHub, navigate to Settings > SSH and GPG keys, and add a new SSH key, pasting your key into the field provided.
+
+ 4. **Switch to SSH in Your Repository**: Change your repository's remote URL from HTTPS to SSH. You can find the SSH URL in your repository settings on GitHub and use `git remote set-url origin git@github.com:username/repository.git` to switch.
+
+ **Authentication Errors**
+
+ If you're experiencing authentication errors, it might be due to missing or incorrect credentials. Ensure you have added your SSH key to your Git hosting service. You can test your SSH connection with `ssh -T git@github.com` (replace `github.com` with your Git hosting service's domain). If successful, you'll receive a welcome message.
+
+ For HTTPS users, check that your username and password (or personal access token for services like GitHub that no longer accept password authentication for Git operations) are correct.
+
+8. **Open a pull request** to `openimsdk/open-im-server:main`
It is recommended to review your changes before filing a pull request. Check if your code doesn't conflict with the main branch and no redundant code is included.
+
+ > [!TIP] There is a [good blog post documenting](https://nsddd.top/posts/participating-in-this-project/) the entire push contribution process.
+
## Style and Specification
@@ -190,15 +303,15 @@ We divide the problem into security and general problems:
#### Reporting security issues
-Security issues are always treated seriously. As our usual principle, we discourage anyone to spread security issues. If you find a security issue of Open-IM-Server, please do not discuss it in public and even do not open a public issue.
+Security issues are always treated seriously. As our usual principle, we discourage anyone to spread security issues. If you find a security issue of open-im-server, please do not discuss it in public and even do not open a public issue.
Instead we encourage you to send us a private email to info@openim.io to report this.
#### Reporting general issues
-To be honest, we regard every user of Open-IM-Serveras a very kind contributor. After experiencing Open-IM-Server, you may have some feedback for the project. Then feel free to open an issue via [NEW ISSUE](https://github.com/openimsdk/open-im-server/issues/new/choose).
+To be honest, we regard every user of open-im-serveras a very kind contributor. After experiencing open-im-server, you may have some feedback for the project. Then feel free to open an issue via [NEW ISSUE](https://github.com/openimsdk/open-im-server/issues/new/choose).
-Since we collaborate project Open-IM-Server in a distributed way, we appreciate **WELL-WRITTEN**, **DETAILED**, **EXPLICIT** issue reports. To make the communication more efficient, we wish everyone could search if your issue is an existing one in the searching list. If you find it existing, please add your details in comments under the existing issue instead of opening a brand new one.
+Since we collaborate project open-im-server in a distributed way, we appreciate **WELL-WRITTEN**, **DETAILED**, **EXPLICIT** issue reports. To make the communication more efficient, we wish everyone could search if your issue is an existing one in the searching list. If you find it existing, please add your details in comments under the existing issue instead of opening a brand new one.
To make the issue details as standard as possible, we setup an [ISSUE TEMPLATE](https://github.com/OpenIMSDK/.github/tree/main/.github/ISSUE_TEMPLATE) for issue reporters. You can find three kinds of issue templates there: question, bug report and feature request. Please **BE SURE** to follow the instructions to fill fields in template.
@@ -206,20 +319,20 @@ To make the issue details as standard as possible, we setup an [ISSUE TEMPLATE](
+ bug report
+ feature request
-+ Open-IM-Server performance issues
++ open-im-server performance issues
+ feature proposal
+ feature design
+ help wanted
+ doc incomplete
+ test improvement
-+ any questions on Open-IM-Server project
++ any questions on open-im-server project
+ and so on
-Also, we must be reminded when submitting a new question about Open-IM-Server, please remember to remove the sensitive data from your post. Sensitive data could be password, secret key, network locations, private business data and so on.
+Also, we must be reminded when submitting a new question about open-im-server, please remember to remove the sensitive data from your post. Sensitive data could be password, secret key, network locations, private business data and so on.
#### Commit Rules
-Actually in Open-IM-Server, we take two rules serious when committing:
+Actually in open-im-server, we take two rules serious when committing:
**🥇 Commit Message:**
@@ -262,7 +375,7 @@ An example for this could be:
#### PR Description
-PR is the only way to make change to Open-IM-Server project files. To help reviewers better get your purpose, PR description could not be too detailed. We encourage contributors to follow the [PR template](https://github.com/OpenIMSDK/.github/tree/main/.github/PULL_REQUEST_TEMPLATE.md) to finish the pull request.
+PR is the only way to make change to open-im-server project files. To help reviewers better get your purpose, PR description could not be too detailed. We encourage contributors to follow the [PR template](https://github.com/OpenIMSDK/.github/tree/main/.github/PULL_REQUEST_TEMPLATE.md) to finish the pull request.
You can find some very formal PR in [RFC](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) issues and learn about them.
@@ -311,11 +424,11 @@ git() {
#### Docs Contribution
-The documentation for Open-IM-Server includes:
+The documentation for open-im-server includes:
-+ [README.md](https://github.com/openimsdk/open-im-server/blob/main/README.md): This file includes the basic information and instructions for getting started with Open-IM-Server.
-+ [CONTRIBUTING.md](https://github.com/openimsdk/open-im-server/blob/main/CONTRIBUTING.md): This file contains guidelines for contributing to Open-IM-Server's codebase, such as how to submit issues, pull requests, and code reviews.
-+ [Official Documentation](https://doc.rentsoft.cn/): This is the official documentation for Open-IM-Server, which includes comprehensive information on all of its features, configuration options, and troubleshooting tips.
++ [README.md](https://github.com/openimsdk/open-im-server/blob/main/README.md): This file includes the basic information and instructions for getting started with open-im-server.
++ [CONTRIBUTING.md](https://github.com/openimsdk/open-im-server/blob/main/CONTRIBUTING.md): This file contains guidelines for contributing to open-im-server's codebase, such as how to submit issues, pull requests, and code reviews.
++ [Official Documentation](https://doc.rentsoft.cn/): This is the official documentation for open-im-server, which includes comprehensive information on all of its features, configuration options, and troubleshooting tips.
Please obey the following rules to better format the docs, which would greatly improve the reading experience.
@@ -328,20 +441,20 @@ Please obey the following rules to better format the docs, which would greatly i
## Engage to help anything
-We choose GitHub as the primary place for Open-IM-Server to collaborate. So the latest updates of Open-IM-Server are always here. Although contributions via PR is an explicit way to help, we still call for any other ways.
+We choose GitHub as the primary place for open-im-server to collaborate. So the latest updates of open-im-server are always here. Although contributions via PR is an explicit way to help, we still call for any other ways.
+ reply to other's [issues](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) if you could;
+ help solve other user's problems;
+ help review other's [PR](https://github.com/openimsdk/open-im-server/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc) design;
-+ discuss about Open-IM-Server to make things clearer;
-+ advocate [Open-IM-Server](https://google.com/search?q=Open-IM-Server) technology beyond GitHub;
-+ write blogs on Open-IM-Server and so on.
++ discuss about open-im-server to make things clearer;
++ advocate [open-im-server](https://google.com/search?q=open-im-server) technology beyond GitHub;
++ write blogs on open-im-server and so on.
In a word, **ANY HELP IS CONTRIBUTION.**
## Release version
-Releases of Open-IM-Server are done using [Release Please](https://github.com/googleapis/release-please) and [GoReleaser](https://goreleaser.com/). The workflow looks like this:
+Releases of open-im-server are done using [Release Please](https://github.com/googleapis/release-please) and [GoReleaser](https://goreleaser.com/). The workflow looks like this:
🎯 A PR is merged to the `main` branch:
@@ -366,17 +479,23 @@ Such a commit can get produced as follows:
❯ git commit --allow-empty -m "chore: release 0.0.3" -m "Release-As: 0.0.3
````
+For the complex release process, in fact, and encapsulation as CICD, you only need to tag locally, and then publish the tag to OpenIM github to complete the entire OpenIM release process.
+
+In addition to CICD, we also do a complex release command locally, which can help you complete the full platform compilation, testing, and release to Minio, just by using the `make release` command.
+Please [read the detailed documents](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/release.md)
+
+
## Contact Us
-We value close connections with our users, developers, and contributors here at Open-IM-Server. With a large community and maintainer team, we're always here to help and support you. Whether you're looking to join our community or have any questions or suggestions, we welcome you to get in touch with us.
+We value close connections with our users, developers, and contributors here at open-im-server. With a large community and maintainer team, we're always here to help and support you. Whether you're looking to join our community or have any questions or suggestions, we welcome you to get in touch with us.
-Our most recommended way to get in touch is through [Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q). Even if you're in China, Slack is usually not blocked by firewalls, making it an easy way to connect with us. Our Slack community is the ideal place to discuss and share ideas and suggestions with other users and developers of Open-IM-Server. You can ask technical questions, seek help, or share your experiences with other users of Open-IM-Server.
+Our most recommended way to get in touch is through [Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q). Even if you're in China, Slack is usually not blocked by firewalls, making it an easy way to connect with us. Our Slack community is the ideal place to discuss and share ideas and suggestions with other users and developers of open-im-server. You can ask technical questions, seek help, or share your experiences with other users of open-im-server.
In addition to Slack, we also offer the following ways to get in touch:
-+ : We also have Slack channels for you to communicate and discuss. To join, visit https://slack.com/ and join our [👀 Open-IM-Server slack](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q) team channel.
++ : We also have Slack channels for you to communicate and discuss. To join, visit https://slack.com/ and join our [👀 open-im-server slack](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q) team channel.
+ : Get in touch with us on [Gmail](info@openim.io). If you have any questions or issues that need resolving, or any suggestions and feedback for our open source projects, please feel free to contact us via email.
-+ : Read our [blog](https://doc.rentsoft.cn/). Our blog is a great place to stay up-to-date with Open-IM-Server projects and trends. On the blog, we share our latest developments, tech trends, and other interesting information.
-+ : Add [Wechat](https://github.com/OpenIMSDK/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of Open-IM-Server. We will process your request as soon as possible.
++ : Read our [blog](https://doc.rentsoft.cn/). Our blog is a great place to stay up-to-date with open-im-server projects and trends. On the blog, we share our latest developments, tech trends, and other interesting information.
++ : Add [Wechat](https://github.com/OpenIMSDK/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of open-im-server. We will process your request as soon as possible.
Whether you're looking to join our community or have any questions or suggestions, we welcome you to get in touch with us.
diff --git a/README-zh_CN.md b/README-zh_CN.md
index 12a56d4f6..e33768881 100644
--- a/README-zh_CN.md
+++ b/README-zh_CN.md
@@ -4,29 +4,51 @@
-
- ⭐️ Open source Instant Messaging Server ⭐️
-
-
-
-
-
-
-
-
-
-
-
+
+
+[](https://github.com/openimsdk/open-im-server/stargazers)
+[](https://github.com/openimsdk/open-im-server/network/members)
+[](https://app.codecov.io/gh/openimsdk/open-im-server)
+[](https://goreportcard.com/report/github.com/openimsdk/open-im-server)
+[](https://pkg.go.dev/github.com/openimsdk/open-im-server/v3)
+[](https://github.com/openimsdk/open-im-server/blob/main/LICENSE)
+[](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q)
+[](https://www.bestpractices.dev/projects/8045)
+[](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22)
+[](https://golang.org/)
-
- English •
- 简体中文 •
- Docs
+ Englist ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
## 🟢 扫描微信进群交流
@@ -39,8 +61,6 @@ OpenIM 是一个专门设计用于在应用程序中集成聊天、音视频通
-
-

## 🚀 关于 OpenIMSDK
diff --git a/README.md b/README.md
index 3876fcd7a..8721bf2ce 100644
--- a/README.md
+++ b/README.md
@@ -17,9 +17,35 @@
[](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22)
[](https://golang.org/)
-[**English**](./README.md) •
-[**简体中文**](./README-zh_CN.md) •
-[**Docs**](https://openim.io/en)
+
+
+ Englist ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
@@ -68,6 +94,13 @@ It is built using Golang and supports cross-platform deployment, ensuring a cons
👉 **[Learn more](https://docs.openim.io/guides/introduction/product)**
+## :building_construction: Overall Architecture
+
+Delve into the heart of Open-IM-Server's functionality with our architecture diagram.
+
+
+
+
## :rocket: Quick Start
We support many platforms. Here are the addresses for quick experience on the web side:
diff --git a/docs/README.md b/docs/README.md
index 32fc8d015..92ba2c620 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -7,7 +7,6 @@ Welcome to the OpenIM Documentation hub! This center provides a comprehensive ra
1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Guidance on contributing and configurations for developers
2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Coding conventions, logging policies, and other transformation tools
-------
## Contrib
diff --git a/docs/README_ar.md b/docs/README_ar.md
deleted file mode 100644
index bdd616e6a..000000000
--- a/docs/README_ar.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# وثائق OpenIM Server
-
-مرحبًا بكم في مركز وثائق OpenIM! يوفر هذا المركز مجموعة شاملة من الأدلة والكتيبات التي صُممت لمساعدتك في الاستفادة القصوى من تجربة OpenIM الخاصة بك.
-
-## جدول المحتويات
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - إرشادات حول المساهمة والتكوينات للمطورين
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - اتفاقيات الكود، سياسات التسجيل، وأدوات التحويل الأخرى
-
-------
-
-## مساهمة
-
-هذا القسم يقدم للمطورين دليلاً مفصلاً حول كيفية المساهمة في الكود، إعداد بيئتهم، واتباع العمليات المرتبطة.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - قواعد واتفاقيات لكتابة الكود في OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - دليل حول كيفية القيام بالتطوير داخل OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - إرشادات حول عمليات اختيار الجيت.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - سير عمل الجيت في OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - إرشادات حول إعداد وتهيئة OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - كيفية تثبيت الدوكر على جهازك.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - دليل لإعداد بيئة التطوير على لينكس.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - إرشادات حول كيفية القيام ببعض الأعمال الشائعة محليًا.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - طرق توظيف OpenIM دون اتصال.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - دليل حول استخدام أدوات بروتوك.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - أدوات ومكتبات في OpenIM للغة Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - أفضل الممارسات والأدوات لملفات الصيانة.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - أفضل الممارسات والأدوات للسكربتات.
-
-## التحويلات
-
-يقدم هذا القسم مختلف الاتفاقيات والسياسات داخل OpenIM، التي تشمل الكود، السجلات، الإصدارات، والمزيد.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - إرشادات وطرق لتحويلات API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - سياسات واتفاقيات التسجيل في OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - إجراءات واتفاقيات لـ CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - اتفاقيات لالتزامات الكود في OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - هيكل الدليل واتفاقياته داخل OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - قائمة وأوصاف رموز الخطأ.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - اتفاقيات وتحويلات لكود Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - استراتيجيات إدارة صور الدوكر في OpenIM، تشمل عدة معماريات ومستودعات الصور.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - اتفاقيات أكثر تفصيلاً حول التسجيل.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - استراتيجيات التسمية والإدارة لإصدارات OpenIM.
-
-
-## للمطورين والمساهمين ومشرفي المجتمع
-
-### المطورون والمساهمون
-
-إذا كنت مطورًا أو شخصًا حريصًا على المساهمة:
-
-- تعرف على [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) و[Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) لضمان سلاسة المساهمات.
-- اغمر نفسك في [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) للتعرف على ممارسات التطوير في OpenIM.
-
-### مشرفو المجتمع
-
-كمشرف على المجتمع:
-
-- تأكد من أن المساهمات تتوافق مع المعايير الموضحة في وثائقنا.
-- راجع بانتظام [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) و[Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) للبقاء على اطلاع.
-
-## للمستخدمين
-
-يجب أن يولي المستخدمون اهتمامًا خاصًا لـ:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - ضروري إذا كنت تخطط لاستخدام صور الدوكر لـ OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - لفهم الصور المختلفة المتاحة وكيفية اختيار ال
diff --git a/docs/README_cs.md b/docs/README_cs.md
deleted file mode 100644
index 0c40b63b1..000000000
--- a/docs/README_cs.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Dokumenty serveru OpenIM
-
-Vítejte v centru dokumentace OpenIM! Toto centrum poskytuje komplexní řadu průvodců a manuálů navržených tak, aby vám pomohly co nejlépe využít vaše zkušenosti s OpenIM.
-
-## Obsah
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Pokyny pro přispívání a konfigurace pro vývojáře
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Konvence kódování, zásady protokolování a další transformační nástroje
-
-------
-
-## Contrib
-
-Tato část nabízí vývojářům podrobný návod, jak přispívat kódem, nastavovat prostředí a sledovat související procesy.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Pravidla a konvence pro psaní kódu v OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Návod, jak provádět vývoj v rámci OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Pokyny pro operace sběru třešní.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Pracovní postup git v OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Pokyny k nastavení a inicializaci OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Jak nainstalovat Docker na váš počítač.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Průvodce nastavením vývojového prostředí na Linuxu.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Pokyny k provádění určitých společných akcí na místní úrovni.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metody nasazení OpenIM offline.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Průvodce používáním protokolových nástrojů.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Nástroje a knihovny v OpenIM for Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Osvědčené postupy a nástroje pro Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Doporučené postupy a nástroje pro skripty.
-
-## Konverze
-
-Tato část představuje různé konvence a zásady v rámci OpenIM, zahrnující kód, protokoly, verze a další.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Pokyny a metody pro konverze API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Zásady a konvence protokolování v OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Postupy a konvence pro CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konvence pro odevzdání kódu v OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Struktura adresářů a konvence v rámci OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Seznam a popisy chybových kódů.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konvence a převody pro kód Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Strategie správy pro obrazy OpenIM Docker, zahrnující různé architektury a úložiště obrazů.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Další podrobné konvence o protokolování.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategie pojmenování a správy verzí OpenIM.
-
-
-## Pro vývojáře, přispěvatele a správce komunity
-
-### Vývojáři a přispěvatelé
-
-Pokud jste vývojář nebo někdo, kdo má zájem přispívat:
-
-- Seznamte se s našimi [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) a [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md), abyste zajistili hladké příspěvky.
-- Ponořte se do [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), abyste se seznámili s vývojovými postupy v OpenIM.
-
-### Správci komunity
-
-Jako správce komunity:
-
-- Zajistěte, aby příspěvky odpovídaly standardům uvedeným v naší dokumentaci.
-- Pravidelně kontrolujte [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) a [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) , abyste zůstali aktuální.
-
-## Pro uživatele
-
-Uživatelé by měli věnovat zvláštní pozornost:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Nezbytné, pokud plánujete používat obrazy OpenIM Docker.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Chcete-li porozumět různým dostupným obrázkům a jak vybrat ten správný pro vaši architekturu.
\ No newline at end of file
diff --git a/docs/README_da.md b/docs/README_da.md
deleted file mode 100644
index d14c6adb5..000000000
--- a/docs/README_da.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM Server Dokumentation
-
-Velkommen til OpenIM Dokumentationscentret! Dette center indeholder en omfattende række vejledninger og manualer, der er designet til at hjælpe dig med at få mest muligt ud af din OpenIM-oplevelse.
-
-## Indholdsfortegnelse
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Vejledning om bidrag og konfigurationer for udviklere
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Kodningskonventioner, logningspolitikker og andre transformationsværktøjer
-
-------
-
-## Bidrag
-
-Denne sektion tilbyder udviklere en detaljeret vejledning om, hvordan de kan bidrage med kode, konfigurere deres miljø og følge de tilknyttede processer.
-
-- [Kodekonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regler og konventioner for at skrive kode i OpenIM.
-- [Udviklingsguide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - En guide om, hvordan man udfører udvikling inden for OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Retningslinjer for cherry-picking-operationer.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Git-workflowen i OpenIM.
-- [Initialiseringskonfigurationer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Vejledning om opsætning og initialisering af OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Sådan installeres Docker på din maskine.
-- [Linux Udviklingsmiljø](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guide til opsætning af udviklingsmiljøet på Linux.
-- [Lokale handlinger](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Retningslinjer for, hvordan man udfører visse almindelige handlinger lokalt.
-- [Offline-deploering](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metoder til at udrulle OpenIM offline.
-- [Protoc-værktøjer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guide til brug af protoc-værktøjer.
-- [Go-værktøjer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Værktøjer og biblioteker i OpenIM til Go.
-- [Makefile-værktøjer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Bedste praksis og værktøjer til Makefile.
-- [Scriptværktøjer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Bedste praksis og værktøjer til scripts.
-
-## Konverteringer
-
-Denne sektion introducerer forskellige konventioner og politikker inden for OpenIM, herunder kode, logfiler, versioner og meget mere.
-
-- [API-konverteringer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Retningslinjer og metoder til API-konverteringer.
-- [Logningspolitik](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Politikker og konventioner for logning i OpenIM.
-- [CI/CD-handlinger](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedurer og konventioner for CI/CD.
-- [Commit-konventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konventioner for kodeforpligtelser i OpenIM.
-- [Mappekonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Mappens struktur og konventioner inden for OpenIM.
-- [Fejlkoder](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Liste og beskrivelser af fejlkoder.
-- [Go-kodekonverteringer](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konventioner og konverteringer for Go-kode.
-- [Docker Image-strategi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Styringsstrategier for OpenIM Docker-billeder, der dækker flere arkitekturer og billedarkiver.
-- [Logningskonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Yderligere detaljerede konventioner om logning.
-- [Versionkonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Navngivnings- og styringsstrategier for OpenIM-versioner.
-
-
-## For udviklere, bidragsydere og samfundsvedligeholdere
-
-### Udviklere og bidragsydere
-
-Hvis du er en udvikler eller nogen, der gerne vil bidrage:
-
-- Gør dig fortrolig med vores [Kodekonventioner](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) og [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) for at sikre en problemfri bidragelse.
-- Dyk ned i [Udviklingsguiden](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) for at få en idé om udviklingspraksis i OpenIM.
-
-### Samfundsvedligeholdere
-
-Som samfundsvedligeholder:
-
-- Sørg for, at bidrag stemmer overens med standarderne beskrevet i vores dokumentation.
-- Gennemgå regelmæssigt [Logningspolitikken](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) og [Fejlkoderne](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) for at holde dig opdateret.
-
-## For brugere
-
-Brugere bør være opmærksomme på følgende:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Nødvendigt, hvis du planlægger at bruge Docker-billeder af OpenIM.
-- [Docker Image-strategi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - For at forstå de forskellige tilgængelige billeder og hvordan man vælger det rigtige for din arkitektur.
diff --git a/docs/README_de.md b/docs/README_de.md
deleted file mode 100644
index 101eba41b..000000000
--- a/docs/README_de.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# OpenIM-Serverdokumente
-
-Willkommen im OpenIM-Dokumentationshub! Dieses Zentrum bietet eine umfassende Auswahl an Leitfäden und Handbüchern, die Ihnen dabei helfen sollen, das Beste aus Ihrem OpenIM-Erlebnis herauszuholen.
-
-## Inhaltsverzeichnis
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Anleitung zu Beiträgen und Konfigurationen für Entwickler
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Codierungskonventionen, Protokollierungsrichtlinien und andere Transformationstools
-
-------
-
-## Beitrag
-
-Dieser Abschnitt bietet Entwicklern eine detaillierte Anleitung zum Beitragen von Code, zum Einrichten ihrer Umgebung und zum Befolgen der zugehörigen Prozesse.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regeln und Konventionen zum Schreiben von Code in OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Eine Anleitung zur Durchführung der Entwicklung innerhalb von OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Richtlinien zur Rosinenpickerei.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Der Git-Workflow in OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Anleitung zum Einrichten und Initialisieren von OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - So installieren Sie Docker auf Ihrem Computer.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Anleitung zum Einrichten der Entwicklungsumgebung unter Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Richtlinien zur Durchführung bestimmter allgemeiner Aktionen vor Ort.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Methoden zur Offline-Bereitstellung von OpenIM.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Anleitung zur Verwendung von Protokolltools.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Tools und Bibliotheken in OpenIM für Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Best Practices und Tools für Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Best Practices und Tools für Skripte.
-
-## Konvertierungen
-
-In diesem Abschnitt werden verschiedene Konventionen und Richtlinien innerhalb von OpenIM vorgestellt, die Code, Protokolle, Versionen und mehr umfassen.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Richtlinien und Methoden für API-Konvertierungen.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Protokollierungsrichtlinien und -konventionen in OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Verfahren und Konventionen für CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konventionen für Code-Commits in OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Verzeichnisstruktur und Konventionen innerhalb von OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Liste und Beschreibungen der Fehlercodes.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konventionen und Konvertierungen für Go-Code.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Verwaltungsstrategien für OpenIM-Docker-Images, die mehrere Architekturen und Image-Repositorys umfassen.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Weitere detaillierte Konventionen zur Protokollierung.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Benennungs- und Verwaltungsstrategien für OpenIM-Versionen.
-
-
-## Für Entwickler, Mitwirkende und Community-Betreuer
-
-### Entwickler und Mitwirkende
-
-Wenn Sie Entwickler sind oder gerne einen Beitrag leisten möchten:
-- Machen Sie sich mit unseren [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) und unserem [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) vertraut, um reibungslose Beiträge zu gewährleisten.
-- Tauchen Sie ein in den [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), um sich mit den Entwicklungspraktiken in OpenIM vertraut zu machen.
-
-### Community-Betreuer
-
-Als Community-Betreuer:
-
-- Stellen Sie sicher, dass die Beiträge den in unserer Dokumentation dargelegten Standards entsprechen.
-- Überprüfen Sie regelmäßig die [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) und die [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), um auf dem Laufenden zu bleiben.
-
-## Für Benutzer
-
-Benutzer sollten besonders auf Folgendes achten:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Erforderlich, wenn Sie Docker-Images von OpenIM verwenden möchten.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Um die verschiedenen verfügbaren Bilder zu verstehen und wie Sie das richtige für Ihre Architektur auswählen.
\ No newline at end of file
diff --git a/docs/README_el.md b/docs/README_el.md
deleted file mode 100644
index 68438628f..000000000
--- a/docs/README_el.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Έγγραφα διακομιστή OpenIM
-
-Καλώς ήρθατε στο κέντρο τεκμηρίωσης OpenIM! Αυτό το κέντρο παρέχει μια ολοκληρωμένη σειρά οδηγών και εγχειριδίων που έχουν σχεδιαστεί για να σας βοηθήσουν να αξιοποιήσετε στο έπακρο την εμπειρία σας στο OpenIM.
-
-## Πίνακας περιεχομένων
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Οδηγίες για τη συνεισφορά και τις διαμορφώσεις για προγραμματιστές
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Συμβάσεις κωδικοποίησης, πολιτικές καταγραφής και άλλα εργαλεία μετασχηματισμού
-
-------
-
-## Συνεισφορά
-
-Αυτή η ενότητα προσφέρει στους προγραμματιστές έναν λεπτομερή οδηγό για το πώς να συνεισφέρουν κώδικα, να ρυθμίσουν το περιβάλλον τους και να ακολουθήσουν τις σχετικές διαδικασίες.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Κανόνες και συμβάσεις για τη σύνταξη κώδικα στο OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Ένας οδηγός για το πώς να πραγματοποιήσετε ανάπτυξη στο OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Οδηγίες για τις εργασίες συλλογής κερασιών.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Η ροή εργασίας git στο OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Οδηγίες για τη ρύθμιση και την προετοιμασία του OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Πώς να εγκαταστήσετε το Docker στο μηχάνημά σας.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Οδηγός για τη ρύθμιση του περιβάλλοντος ανάπτυξης στο Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Οδηγίες για τον τρόπο εκτέλεσης ορισμένων κοινών ενεργειών σε τοπικό επίπεδο.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Μέθοδοι ανάπτυξης OpenIM εκτός σύνδεσης.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Οδηγός χρήσης εργαλείων πρωτοκόλλου.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Εργαλεία και βιβλιοθήκες στο OpenIM for Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Βέλτιστες πρακτικές και εργαλεία για το Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Βέλτιστες πρακτικές και εργαλεία για σενάρια.
-
-## Μετατροπές
-
-Αυτή η ενότητα εισάγει διάφορες συμβάσεις και πολιτικές στο OpenIM, που περιλαμβάνουν κώδικα, αρχεία καταγραφής, εκδόσεις και άλλα.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Οδηγίες και μέθοδοι για μετατροπές API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Πολιτικές και συμβάσεις καταγραφής στο OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Διαδικασίες και συμβάσεις για CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Συμβάσεις για δεσμεύσεις κώδικα στο OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Δομή καταλόγου και συμβάσεις στο OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Λίστα και περιγραφές κωδικών σφαλμάτων.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Συμβάσεις και μετατροπές για τον κώδικα Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Στρατηγικές διαχείρισης για εικόνες OpenIM Docker, που εκτείνονται σε πολλαπλές αρχιτεκτονικές και αποθετήρια εικόνων.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Περαιτέρω λεπτομερείς συμβάσεις για την υλοτομία.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Στρατηγικές ονομασίας και διαχείρισης για εκδόσεις OpenIM.
-
-
-## Για προγραμματιστές, συνεισφέροντες και συντηρητές κοινότητας
-
-### Προγραμματιστές & Συνεισφέροντες
-
-Εάν είστε προγραμματιστής ή κάποιος που επιθυμεί να συνεισφέρει:
-
-- Εξοικειωθείτε με τις [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) και [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) για να εξασφαλίσετε ομαλή συνεισφορά.
-- Βουτήξτε στον [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) για να δείτε τις πρακτικές ανάπτυξης στο OpenIM.
-
-### Συντηρητές της Κοινότητας
-
-Ως συντηρητής κοινότητας:
-
-- Βεβαιωθείτε ότι οι συνεισφορές ευθυγραμμίζονται με τα πρότυπα που περιγράφονται στην τεκμηρίωσή μας.
-- Να ελέγχετε τακτικά την [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) και τους [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) για να ενημερώνεστε.
-
-## Για Χρήστες
-
-Οι χρήστες θα πρέπει να δώσουν ιδιαίτερη προσοχή:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Απαραίτητο εάν σκοπεύετε να χρησιμοποιήσετε εικόνες Docker του OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Για να κατανοήσετε τις διάφορες διαθέσιμες εικόνες και πώς να επιλέξετε τη σωστή για την αρχιτεκτονική σας.
\ No newline at end of file
diff --git a/docs/README_eo.md b/docs/README_eo.md
deleted file mode 100644
index d7ae8c08c..000000000
--- a/docs/README_eo.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM Server Docs
-
-Bonvenon al la OpenIM Dokumenta nabo! Ĉi tiu centro disponigas ampleksan gamon da gvidiloj kaj manlibroj desegnitaj por helpi vin eltiri la plej grandan parton de via OpenIM-sperto.
-
-## Enhavtabelo
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Gvidilo pri kontribuado kaj agordoj por programistoj
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Kodigaj konvencioj, registradaj politikoj kaj aliaj transformaj iloj
-
-------
-
-## Kontribui
-
-Ĉi tiu sekcio ofertas al programistoj detalan gvidilon pri kiel kontribui kodon, agordi sian medion kaj sekvi la rilatajn procezojn.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Reguloj kaj konvencioj por skribi kodon en OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Gvidilo pri kiel efektivigi disvolviĝon ene de OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Gvidlinioj pri ĉeriz-plukaj operacioj.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - La git-laborfluo en OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Gvidilo pri agordo kaj pravalorigo de OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Kiel instali Docker sur via maŝino.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Gvidilo por agordi la evolumedion en Linukso.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Gvidlinioj pri kiel efektivigi certajn komunajn agojn loke.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metodoj por disfaldi OpenIM eksterrete.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Gvidilo pri uzado de protokaj iloj.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Iloj kaj bibliotekoj en OpenIM for Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Plej bonaj praktikoj kaj iloj por Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Plej bonaj praktikoj kaj iloj por skriptoj.
-
-## Konvertiĝoj
-
-Ĉi tiu sekcio enkondukas diversajn konvenciojn kaj politikojn ene de OpenIM, ampleksante kodon, protokolojn, versiojn kaj pli.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Gvidlinioj kaj metodoj por API-konvertoj.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Registrado de politikoj kaj konvencioj en OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Proceduroj kaj konvencioj por CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konvencioj por kodoj en OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Dosierujo-strukturo kaj konvencioj ene de OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Listo kaj priskriboj de erarkodoj.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konvencioj kaj konvertiĝoj por Go-kodo.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Administradstrategioj por OpenIM Docker-bildoj, ampleksante plurajn arkitekturojn kaj bilddeponejojn.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Pliaj detalaj konvencioj pri arbohakado.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategioj pri nomado kaj administrado por OpenIM-versioj.
-
-
-## Por Programistoj, Kontribuantoj kaj Komunumaj Prizorgantoj
-
-### Programistoj kaj Kontribuantoj
-
-Se vi estas programisto aŭ iu fervora kontribui:
-
-- Familiariĝu kun niaj [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) por certigi glatajn kontribuojn.
-- Plonĝu en la[Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) por ekkompreni la evolupraktikojn en OpenIM.
-
-### Komunumaj Prizorgantoj
-
-Kiel komunuma prizorganto:
-
-- Certigu, ke kontribuoj kongruas kun la normoj skizitaj en nia dokumentaro.
-- Regule reviziu la [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) kaj [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) por resti ĝisdatigita.
-
-## Por Uzantoj
-
-Uzantoj devas aparte atenti:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Necesas se vi planas uzi Docker-bildojn de OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Por kompreni la malsamajn bildojn disponeblajn kaj kiel elekti la ĝustan por via arkitekturo.
\ No newline at end of file
diff --git a/docs/README_es.md b/docs/README_es.md
deleted file mode 100644
index 96523120a..000000000
--- a/docs/README_es.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Documentos del servidor OpenIM
-
-¡Bienvenido al centro de documentación de OpenIM! Este centro proporciona una amplia gama de guías y manuales diseñados para ayudarle a aprovechar al máximo su experiencia OpenIM.
-
-## Tabla de contenido
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Orientación sobre contribuciones y configuraciones para desarrolladores
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Convenciones de codificación, políticas de registro y otras herramientas de transformación
-
-------
-
-## Contribuir
-
-Esta sección ofrece a los desarrolladores una guía detallada sobre cómo contribuir con código, configurar su entorno y seguir los procesos asociados.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Reglas y convenciones para escribir código en OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Una guía sobre cómo realizar el desarrollo dentro de OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Directrices sobre operaciones de selección selectiva.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - El flujo de trabajo de git en OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Orientación sobre la configuración e inicialización de OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Cómo instalar Docker en su máquina.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guía para configurar el entorno de desarrollo en Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Lineamientos sobre cómo llevar a cabo determinadas acciones comunes a nivel local.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Métodos de implementación de OpenIM sin conexión.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guía sobre el uso de herramientas de protocolo.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Herramientas y bibliotecas en OpenIM for Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Mejores prácticas y herramientas para Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Mejores prácticas y herramientas para scripts.
-
-## Conversiones
-
-Esta sección presenta varias convenciones y políticas dentro de OpenIM, que abarcan código, registros, versiones y más.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Directrices y métodos para conversiones de API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Políticas y convenciones de registro en OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedimientos y convenciones para CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Convenciones para confirmaciones de código en OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Estructura de directorios y convenciones dentro de OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Lista y descripciones de códigos de error.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Convenciones y conversiones para código Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Estrategias de gestión para imágenes OpenIM Docker, que abarcan múltiples arquitecturas y repositorios de imágenes.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Convenciones más detalladas sobre el registro.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Estrategias de nomenclatura y gestión de versiones OpenIM.
-
-
-## Para desarrolladores, contribuyentes y mantenedores de la comunidad
-
-### Desarrolladores y colaboradores
-
-Si eres desarrollador o alguien interesado en contribuir:
-
-- Familiarícese con nuestras [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) y [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) to ensure smooth contributions.
-- Sumérgete en la [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) para familiarizarte con las prácticas de desarrollo en OpenIM.
-
-### Mantenedores de la comunidad
-
-Como mantenedor de la comunidad:
-
-- Asegúrese de que las contribuciones se alineen con los estándares descritos en nuestra documentación.
-- Revise periódicamente la [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) y los [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) para mantenerse actualizado.
-
-## Para usuarios
-
-Los usuarios deben prestar especial atención a:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Necesario si planea utilizar imágenes Docker de OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Comprender las diferentes imágenes disponibles y cómo elegir la adecuada para su arquitectura.
\ No newline at end of file
diff --git a/docs/README_fa.md b/docs/README_fa.md
deleted file mode 100644
index 43056647a..000000000
--- a/docs/README_fa.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# اسناد سرور OpenIM
-
-به مرکز اسناد OpenIM خوش آمدید! این مرکز طیف گسترده ای از راهنماها و راهنماها را ارائه می دهد که به شما کمک می کند تا از تجربه OpenIM خود بیشترین بهره را ببرید.
-
-## فهرست مطالب
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - راهنمایی در مورد مشارکت و تنظیمات برای توسعه دهندگان
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - کنوانسیون های کدگذاری، سیاست های ورود به سیستم و سایر ابزارهای تبدیل
-
-------
-
-## مشارکت
-
-این بخش به توسعه دهندگان راهنمای دقیقی در مورد نحوه مشارکت کد، تنظیم محیط خود و پیروی از فرآیندهای مرتبط ارائه می دهد.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - قوانین و مقررات برای نوشتن کد در OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - راهنمای نحوه انجام توسعه در OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - دستورالعمل عملیات چیدن گیلاس
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - گردش کار git در OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - راهنمایی در مورد راه اندازی و مقداردهی اولیه OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - چگونه داکر را روی دستگاه خود نصب کنیم.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - راهنمای راه اندازی محیط توسعه در لینوکس.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - رهنمودهایی در مورد نحوه انجام برخی از اقدامات مشترک به صورت محلی.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - روش های استقرار OpenIM به صورت آفلاین
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - راهنمای استفاده از ابزار پروتک
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - ابزارها و کتابخانه ها در OpenIM for Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - بهترین روش ها و ابزارها برای Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - بهترین روش ها و ابزارها برای اسکریپت ها.
-
-## تبدیل ها
-
-این بخش قراردادها و سیاستهای مختلفی را در OpenIM معرفی میکند که شامل کد، گزارشها، نسخهها و موارد دیگر میشود.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - دستورالعمل ها و روش های تبدیل API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - سیاستهای ورود به سیستم و قراردادها در OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - رویه ها و قراردادها برای CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - کنوانسیونها برای تعهدات کد در OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - ساختار دایرکتوری و قراردادها در OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - لیست و توضیحات کدهای خطا
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - کنوانسیون ها و تبدیل ها برای کد Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - استراتژی های مدیریتی برای تصاویر OpenIM Docker، شامل چندین معماری و مخازن تصویر.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - کنوانسیون های دقیق تر در مورد ورود به سیستم.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - استراتژی های نامگذاری و مدیریت برای نسخه های OpenIM.
-
-
-## برای توسعهدهندگان، مشارکتکنندگان و نگهبانان انجمن
-
-### توسعه دهندگان و مشارکت کنندگان
-
-اگر توسعهدهنده هستید یا کسی که مشتاق مشارکت است:
-
-- - برای اطمینان از مشارکت های روان، با [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) و [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) ما آشنا شوید.
-- - در [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) شیرجه بزنید تا از شیوه های توسعه در OpenIM مطلع شوید.
-
-### نگهبانان جامعه
-
-به عنوان یک نگهدارنده جامعه:
-
-- اطمینان حاصل کنید که مشارکت ها با استانداردهای ذکر شده در اسناد ما مطابقت دارند.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) و [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) را بهطور مرتب مرور کنید تا بهروز بمانید.
-
-## برای کاربران
-
-کاربران باید توجه ویژه ای به موارد زیر داشته باشند:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - اگر قصد دارید از تصاویر Docker OpenIM استفاده کنید، ضروری است.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - برای درک تصاویر مختلف موجود و نحوه انتخاب تصویر مناسب برای معماری خود.
\ No newline at end of file
diff --git a/docs/README_fi.md b/docs/README_fi.md
deleted file mode 100644
index 9678763d9..000000000
--- a/docs/README_fi.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM Server Docs
-
-Tervetuloa OpenIM-dokumentaatiokeskukseen! Tämä keskus tarjoaa kattavan valikoiman oppaita ja oppaita, jotka on suunniteltu auttamaan sinua saamaan kaiken irti OpenIM-kokemuksestasi.
-
-## Sisällysluettelo
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Ohjeita kehittäjille osallistumiseen ja määrityksiin
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Koodauskäytännöt, lokikäytännöt ja muut muunnostyökalut
-
-------
-
-## Contrib
-
-Tämä osio tarjoaa kehittäjille yksityiskohtaisen oppaan koodin lisäämisestä, ympäristön määrittämisestä ja siihen liittyvien prosessien seuraamisesta.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Säännöt ja käytännöt koodin kirjoittamiselle OpenIM:ssä.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Opas kehitystyön toteuttamiseen OpenIM:ssä.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Kirsikoiden poimimista koskevat ohjeet.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Git-työnkulku OpenIM:ssä.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Ohjeita OpenIM:n käyttöönottoon ja alustamiseen.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Kuinka asentaa Docker koneellesi.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Ohje kehitysympäristön määrittämiseen Linuxissa.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Ohjeita tiettyjen yhteisten toimien toteuttamiseen paikallisesti.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - OpenIM:n offline-käyttöönottomenetelmät.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Opas protokollatyökalujen käyttöön.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - OpenIM for Go -työkalut ja kirjastot.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefilen parhaat käytännöt ja työkalut.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Skriptien parhaat käytännöt ja työkalut.
-
-## Tulokset
-
-Tässä osiossa esitellään erilaisia OpenIM:n käytäntöjä ja käytäntöjä, jotka kattavat koodin, lokit, versiot ja paljon muuta.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Ohjeita ja menetelmiä API-muunnoksille.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Kirjauskäytännöt ja käytännöt OpenIM:ssä.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD:n menettelyt ja käytännöt.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM:n koodisitoumusten käytännöt.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Hakemistorakenne ja käytännöt OpenIM:ssä.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Luettelo ja kuvaukset virhekoodeista.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go-koodin sopimukset ja muunnokset.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Hallintastrategiat OpenIM Docker -kuville, jotka kattavat useita arkkitehtuureja ja kuvavarastoja.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Tarkemmat hakkuiden käytännöt.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Nimeämis- ja hallintastrategiat OpenIM-versioille.
-
-
-## Kehittäjille, avustajille ja yhteisön ylläpitäjille
-
-### Kehittäjät ja avustajat
-
-Jos olet kehittäjä tai joku, joka haluaa osallistua:
-
-- Tutustu [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md)- ja [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) -käytäntöihimme varmistaaksesi sujuvan osallistumisen.
-- Sukella [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) saadaksesi tietoa OpenIM:n kehityskäytännöistä.
-
-### Yhteisön ylläpitäjät
-
-Yhteisön ylläpitäjänä:
-
-- Varmista, että osallistumiset ovat asiakirjoissamme esitettyjen standardien mukaisia.
-- Tarkista säännöllisesti [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) ja [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) pysyäksesi ajan tasalla.
-
-## Käyttäjille
-
-Käyttäjien tulee kiinnittää erityistä huomiota:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Välttämätön, jos aiot käyttää OpenIM:n Docker-kuvia.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Ymmärtääksesi saatavilla olevat erilaiset kuvat ja kuinka valita oikea arkkitehtuuriisi.
\ No newline at end of file
diff --git a/docs/README_fr.md b/docs/README_fr.md
deleted file mode 100644
index 747ef5349..000000000
--- a/docs/README_fr.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Documentation du serveur OpenIM
-
-Bienvenue dans le hub de documentation OpenIM ! Ce centre propose une gamme complète de guides et de manuels conçus pour vous aider à tirer le meilleur parti de votre expérience OpenIM.
-
-## Table des matières
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Conseils sur la contribution et les configurations pour les développeurs
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Conventions de codage, politiques de journalisation et autres outils de transformation
-
-------
-
-## Contribuer
-
-Cette section propose aux développeurs un guide détaillé sur la façon de contribuer au code, de configurer leur environnement et de suivre les processus associés.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Règles et conventions pour écrire du code dans OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Un guide sur la façon de réaliser du développement au sein d'OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Lignes directrices sur les opérations de triage.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Le flux de travail git dans OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Conseils sur la configuration et l’initialisation d’OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Comment installer Docker sur votre machine.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guide pour configurer l'environnement de développement sous Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Des lignes directrices pour mener localement certaines actions communes.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Méthodes de déploiement d'OpenIM hors ligne.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guide sur l'utilisation des outils de protocole.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Outils et bibliothèques dans OpenIM for Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Meilleures pratiques et outils pour Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Meilleures pratiques et outils pour les scripts.
-
-## Conversions
-
-Cette section présente diverses conventions et politiques au sein d'OpenIM, englobant le code, les journaux, les versions, etc.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Lignes directrices et méthodes pour les conversions API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Politiques et conventions de journalisation dans OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Politiques et conventions de journalisation dans OpenIM.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Politiques et conventions de journalisation dans OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Structure de répertoire et conventions au sein d'OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Liste et descriptions des codes d'erreur.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Conventions et conversions pour le code Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Stratégies de gestion des images OpenIM Docker, couvrant plusieurs architectures et référentiels d'images.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Conventions plus détaillées sur la journalisation.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Stratégies de nommage et de gestion pour les versions OpenIM.
-
-
-## Pour les développeurs, les contributeurs et les responsables de la communauté
-
-### Développeurs et contributeurs
-
-Si vous êtes un développeur ou quelqu'un désireux de contribuer :
-- Familiarisez-vous avec nos [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) et notre [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) pour garantir des contributions fluides.
-- Plongez dans le [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) pour vous familiariser avec les pratiques de développement dans OpenIM.
-
-### Responsables de la communauté
-
-En tant que responsable de la communauté :
-
-- EAssurez-vous que les contributions sont conformes aux normes décrites dans notre documentation.
-- onsultez régulièrement la [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) et les [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) pour rester à jour.
-
-## Pour les utilisateurs
-
-Les utilisateurs doivent prêter une attention particulière à :
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Nécessaire si vous prévoyez d'utiliser des images Docker d'OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Pour comprendre les différentes images disponibles et comment choisir celle qui convient à votre architecture.
\ No newline at end of file
diff --git a/docs/README_hu.md b/docs/README_hu.md
deleted file mode 100644
index 62cb54bb2..000000000
--- a/docs/README_hu.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM Server Docs
-
-Üdvözöljük az OpenIM dokumentációs központjában! Ez a központ útmutatók és kézikönyvek átfogó választékát kínálja, amelyek célja, hogy a legtöbbet hozza ki az OpenIM-élményből.
-
-## Tartalomjegyzék
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Útmutató a fejlesztőknek a hozzájáruláshoz és a konfigurációkhoz
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Kódolási konvenciók, naplózási szabályzatok és egyéb átalakítási eszközök
-
-------
-
-## Contrib
-
-Ez a rész részletes útmutatót nyújt a fejlesztőknek a kód hozzáadásával, a környezet beállításával és a kapcsolódó folyamatok követésével kapcsolatban.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Az OpenIM kódírásának szabályai és konvenciói.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Útmutató az OpenIM-en belüli fejlesztés végrehajtásához.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Útmutató a cseresznyeszedési műveletekhez.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - A git munkafolyamat az OpenIM-ben.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Útmutató az OpenIM beállításához és inicializálásához.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - A Docker telepítése a gépére.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guide to set up the development environment on Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Útmutató a fejlesztői környezet beállításához Linuxon.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Az OpenIM offline üzembe helyezésének módszerei.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Útmutató a protokolleszközök használatához.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Eszközök és könyvtárak az OpenIM for Go-ban.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - A Makefile legjobb gyakorlatai és eszközei.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Bevált módszerek és eszközök a szkriptekhez.
-
-## Conversions
-
-Ez a rész az OpenIM különféle konvencióit és szabályzatait mutatja be, beleértve a kódot, a naplókat, a verziókat és egyebeket.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Irányelvek és módszerek az API-konverziókhoz.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Naplózási szabályzatok és konvenciók az OpenIM-ben.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD eljárások és konvenciók.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - A kód véglegesítésének konvenciói az OpenIM-ben.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Címtárszerkezet és konvenciók az OpenIM-en belül.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - A hibakódok listája és leírása.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konvenciók és átalakítások a Go kódhoz.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Kezelési stratégiák az OpenIM Docker-képekhez, amelyek több architektúrára és képtárra is kiterjednek.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - További részletes egyezmények a fakitermelésről.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Elnevezési és kezelési stratégiák az OpenIM verziókhoz.
-
-
-## Fejlesztőknek, közreműködőknek és közösségi fenntartóknak
-
-### Fejlesztők és közreműködők
-
-Ha Ön fejlesztő vagy valaki, aki szeretne hozzájárulni:
-
-- A zökkenőmentes hozzájárulás érdekében ismerkedjen meg [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) és [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md)-val.
-- Merüljön el a [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), hogy megismerje az OpenIM fejlesztési gyakorlatát.
-
-### Közösségfenntartók
-
-Közösségfenntartóként:
-
-- Győződjön meg arról, hogy a hozzájárulások megfelelnek a dokumentációnkban felvázolt szabványoknak.
-- Rendszeresen tekintse át a [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) és a [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), hogy naprakész maradjon.
-
-## Felhasználóknak
-
-A felhasználóknak különös figyelmet kell fordítaniuk a következőkre:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Szükséges, ha az OpenIM Docker-képeit szeretné használni.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Hogy megértse a rendelkezésre álló különböző képeket, és hogyan válassza ki a megfelelőt az építészetéhez.
\ No newline at end of file
diff --git a/docs/README_id.md b/docs/README_id.md
deleted file mode 100644
index 988e25efe..000000000
--- a/docs/README_id.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Dokumen Server OpenIM
-
-Selamat datang di pusat Dokumentasi OpenIM! Pusat ini menyediakan berbagai panduan dan manual yang komprehensif untuk membantu Anda memaksimalkan pengalaman Anda dengan OpenIM.
-
-## Daftar Isi
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Panduan tentang kontribusi dan konfigurasi untuk pengembang
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Konvensi pengkodean, kebijakan logging, dan alat transformasi lainnya
-
-------
-
-## Contrib
-
-Bagian ini menawarkan panduan rinci bagi pengembang tentang cara berkontribusi kode, menyiapkan lingkungan mereka, dan mengikuti proses yang terkait.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Aturan dan konvensi untuk menulis kode di OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Panduan tentang cara melakukan pengembangan di dalam OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Pedoman tentang operasi cherry-picking.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Alur kerja git di OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Panduan untuk mengatur dan menginisialisasi OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Cara memasang Docker di mesin Anda.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Panduan untuk menyiapkan lingkungan pengembangan di Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Pedoman tentang cara melakukan beberapa tindakan umum secara lokal.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metode penyebaran OpenIM secara offline.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Panduan tentang menggunakan alat protoc.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Alat dan perpustakaan di OpenIM untuk Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Praktik terbaik dan alat untuk Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Praktik terbaik dan alat untuk skrip.
-
-## Conversions
-
-Bagian ini memperkenalkan berbagai konvensi dan kebijakan dalam OpenIM, meliputi kode, log, versi, dan lainnya.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Pedoman dan metode untuk konversi API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Kebijakan dan konvensi logging di OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Prosedur dan konvensi untuk CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konvensi untuk commit kode di OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Struktur direktori dan konvensi dalam OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Daftar dan deskripsi kode kesalahan.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konvensi dan konversi untuk kode Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Strategi manajemen gambar Docker OpenIM, mencakup berbagai arsitektur dan repositori gambar.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Konvensi logging yang lebih detail.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategi penamaan dan manajemen versi OpenIM.
-
-
-## Untuk Pengembang, Kontributor, dan Pemelihara Komunitas
-
-### Pengembang & Kontributor
-
-Jika Anda seorang pengembang atau seseorang yang ingin berkontribusi:
-
-- Kenali [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) dan [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) kami untuk memastikan kontribusi yang lancar.
-- Pelajari [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) untuk memahami praktik pengembangan di OpenIM.
-
-### Pemelihara Komunitas
-
-Sebagai pemelihara komunitas:
-
-- Pastikan kontribusi sesuai dengan standar yang diuraikan dalam dokumentasi kami.
-- Tinjau secara teratur [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) dan [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) untuk tetap terupdate.
-
-## Untuk Pengguna
-
-Pengguna harus memberikan perhatian khusus kepada:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Diperlukan jika Anda berencana menggunakan gambar Docker dari OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Untuk memahami gambar yang tersedia dan bagaimana memilih yang tepat untuk arsitektur Anda.
diff --git a/docs/README_it.md b/docs/README_it.md
deleted file mode 100644
index 76e41b5e7..000000000
--- a/docs/README_it.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Documentazione del Server OpenIM
-
-Benvenuti al centro documentazione di OpenIM! Questo centro offre una gamma completa di guide e manuali progettati per aiutarvi a ottenere il massimo dalla vostra esperienza con OpenIM.
-
-## Indice dei Contenuti
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Guida al contributo e alle configurazioni per gli sviluppatori
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Convenzioni di codifica, politiche di registrazione e altri strumenti di trasformazione
-
-------
-
-## Contrib
-
-Questa sezione offre agli sviluppatori una guida dettagliata su come contribuire al codice, configurare il loro ambiente e seguire i processi associati.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regole e convenzioni per scrivere codice in OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Una guida su come svolgere lo sviluppo all'interno di OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Linee guida sulle operazioni di cherry-picking.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Il flusso di lavoro git in OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Guida per configurare e inizializzare OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Come installare Docker sul tuo dispositivo.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guida per configurare l'ambiente di sviluppo su Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Linee guida su come eseguire determinate azioni comuni localmente.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metodi per distribuire OpenIM offline.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guida all'uso degli strumenti protoc.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Strumenti e librerie in OpenIM per Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Migliori pratiche e strumenti per Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Migliori pratiche e strumenti per gli script.
-
-## Conversions
-
-Questa sezione introduce varie convenzioni e politiche all'interno di OpenIM, che comprendono codice, registrazioni, versioni e altro.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Linee guida e metodi per le conversioni API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Politiche e convenzioni di registrazione in OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedure e convenzioni per CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Convenzioni per i commit di codice in OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Struttura delle directory e convenzioni all'interno di OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Elenco e descrizioni dei codici di errore.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Convenzioni e conversioni per il codice Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Strategie di gestione delle immagini Docker di OpenIM, che coprono più architetture e repository di immagini.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Ulteriori dettagliate convenzioni sulla registrazione.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategie di denominazione e gestione delle versioni di OpenIM.
-
-
-## Per Sviluppatori, Contributori e Manutentori della Comunità
-
-### Sviluppatori & Contributori
-
-Se sei uno sviluppatore o qualcuno interessato a contribuire:
-
-- Familiarizza con le nostre [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) e [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) per garantire contributi fluidi.
-- Approfondisci la [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) per ottenere una conoscenza delle pratiche di sviluppo in OpenIM.
-
-### Manutentori della Comunità
-
-Come manutentore della comunità:
-
-- Assicurati che i contributi siano in linea con gli standard delineati nella nostra documentazione.
-- Rivedi regolarmente la [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) e [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) per rimanere aggiornato.
-
-## Per gli Utenti
-
-Gli utenti dovrebbero prestare particolare attenzione a:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Necessario se si prevede di utilizzare le immagini Docker di OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Per comprendere le diverse immagini disponibili e come scegliere quella giusta per la propria architettura.
diff --git a/docs/README_ja.md b/docs/README_ja.md
deleted file mode 100644
index 3971037fb..000000000
--- a/docs/README_ja.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIMサーバードキュメンテーション
-
-OpenIMドキュメンテーションハブへようこそ!このセンターでは、OpenIM体験を最大限に活用するための包括的なガイドとマニュアルを提供しています。
-
-## 目次
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 開発者向けの貢献と設定に関するガイダンス
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - コーディング規約、ログポリシー、その他の変換ツール
-
-------
-
-## 投稿
-
-このセクションでは、開発者がコードを貢献し、環境を設定し、関連するプロセスに従う方法についての詳細なガイドを提供します。
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIMでのコード記述のルールと規約。
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - OpenIM内での開発を行うためのガイド。
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - チェリーピッキング操作のガイドライン。
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIMにおけるGitのワークフロー。
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - OpenIMの設定と初期化に関するガイダンス。
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - マシンにDockerをインストールする方法。
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Linux上での開発環境の設定ガイド。
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - ローカルで一般的なアクションを実行する方法に関するガイドライン。
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - OpenIMをオフラインでデプロイする方法。
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - protocツールの使用ガイド。
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - GoのためのOpenIM内のツールとライブラリ。
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefileのベストプラクティスとツール。
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - スクリプトのベストプラクティスとツール。
-
-## Conversions
-
-このセクションでは、OpenIM内のさまざまな規約とポリシーを紹介します。これには、コード、ログ、バージョンなどが含まれます。
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API変換のためのガイドラインと方法。
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIMにおけるログポリシーと規約。
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CDの手順と規約。
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIMでのコードコミットのための規約。
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM内のディレクトリ構造と規約。
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - エラーコードのリストと説明。
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Goコードのための規約と変換。
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 複数のアーキテクチャとイメージリポジトリにまたがるOpenIM Dockerイメージの管理戦略。
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - ロギングに関するさらに詳細な規約。
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIMバージョンの命名と管理戦略。
-
-
-## 開発者、コントリビューター、コミュニティメンテナー向け
-
-### 開発者およびコントリビューター
-
-開発者または貢献に熱心な方へ:
-
-- スムーズな貢献を確実にするために、私たちの[Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md)と[Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md)に慣れ親しみましょう。
-- OpenIMの開発実践に慣れるために、[Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md)をご覧ください。
-
-### コミュニティメンテナー
-
-コミュニティメンテナーとして:
-
-- 貢献が私たちのドキュメンテーションで概説された基準に沿っていることを確認してください。
-- 最新の情報を得るために、定期的に[Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md)と[Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md)をレビューしてください。
-
-## ユーザー向け
-
-ユーザーは特に以下の点に注意してください:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - OpenIMのDockerイメージを使用する予定の場合に必要です。
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 利用可能なさまざまなイメージを理解し、アーキテクチャに適したものを選択する方法。
diff --git a/docs/README_ko.md b/docs/README_ko.md
deleted file mode 100644
index 9cd728c5d..000000000
--- a/docs/README_ko.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM 서버 문서
-
-OpenIM 문서 허브에 오신 것을 환영합니다! 이 센터는 OpenIM 경험을 최대한 활용하는 데 도움이 되도록 다양한 가이드와 매뉴얼을 제공합니다.
-
-## 목차
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 개발자를 위한 기여 및 구성에 대한 안내
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 코딩 규칙, 로깅 정책 및 기타 변환 도구
-
-------
-
-## 기여
-
-이 섹션은 개발자들에게 코드를 기여하는 방법, 환경을 설정하는 방법 및 관련 프로세스를 따르는 방법에 대한 자세한 가이드를 제공합니다.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIM에서 코드를 작성하기 위한 규칙 및 규약.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - OpenIM 내에서 개발을 수행하는 방법에 대한 가이드.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - 체리피킹 작업에 대한 지침.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM에서의 깃 워크플로우.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - OpenIM 설정 및 초기화에 대한 안내.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 컴퓨터에 도커를 설치하는 방법.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - 리눅스에서 개발 환경을 설정하는 가이드.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - 일부 일반적인 작업을 로컬에서 수행하는 방법에 대한 지침.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - 오프라인에서 OpenIM을 배포하는 방법.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - 프로토콜 도구 사용에 대한 가이드.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Go용 OpenIM 도구 및 라이브러리.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - 메이크파일을 위한 모범 사례 및 도구.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - 스크립트를 위한 모범 사례 및 도구.
-
-## 전환
-
-이 섹션에서는 코드, 로그, 버전 등을 포함하는 OpenIM 내의 다양한 규칙과 정책을 소개합니다.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API 변환을 위한 지침 및 방법.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM의 로깅 정책 및 관습.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD 절차 및 관습.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM에서 코드 커밋을 위한 관습.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM 내의 디렉토리 구조 및 관습.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - 오류 코드 목록 및 설명.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go 코드를 위한 관습 및 변환.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 다양한 아키텍처 및 이미지 저장소를 아우르는 OpenIM Docker 이미지 관리 전략.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - 로깅에 대한 추가적인 상세한 관습.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM 버전의 명명 및 관리 전략.
-
-
-## 개발자, 기여자 및 커뮤니티 관리자를 위한 정보
-
-### 개발자 및 기여자
-
-개발자이거나 기여에 관심이 있다면:
-
-- 원활한 기여를 위해 [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) 및 [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md)에 익숙해지십시오.
-- OpenIM에서의 개발 관행을 파악하려면 [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md)를 참조하십시오.
-
-### 커뮤니티 관리자
-
-커뮤니티 관리자로서:
-
-- 기여가 우리 문서에 명시된 표준에 부합하는지 확인하십시오.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) 및 [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md)를 정기적으로 검토하여 최신 정보를 유지하십시오.
-
-## 사용자를 위한 정보
-
-사용자는 특히 다음 사항에 주의를 기울여야 합니다:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - OpenIM의 Docker 이미지를 사용할 계획이라면 필요합니다.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 사용 가능한 다양한 이미지를 이해하고 아키텍처에 적합한 이미지를 선택하는 방법.
diff --git a/docs/README_ml.md b/docs/README_ml.md
deleted file mode 100644
index 7f3aa8c0d..000000000
--- a/docs/README_ml.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM സെർവർ ഡോക്യുമെന്റേഷൻ
-
-OpenIM ഡോക്യുമെന്റേഷൻ ഹബ്ബിലേക്ക് സ്വാഗതം! ഈ കേന്ദ്രം OpenIM അനുഭവത്തിൽ നിന്ന് പരമാവധി ഉപയോഗം നേടാൻ സഹായിക്കുന്ന വ്യാപകമായ നിർദേശങ്ങളുടെയും മാനുവലുകളുടെയും ശ്രേണി നൽകുന്നു.
-
-## ഉള്ളടക്കം
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - ഡെവലപ്പർമാർക്കുള്ള സംഭാവനകൾ നൽകുന്നതിനും കോൺഫിഗറേഷനുകൾക്കുള്ള നിർദേശങ്ങൾ
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - കോഡിംഗ് കൺവെൻഷനുകൾ, ലോഗ്ഗിംഗ് നയങ്ങൾ, മറ്റ് പരിവർത്തന ഉപകരണങ്ങൾ
-
-------
-
-## Contrib
-
-ഈ ഭാഗം ഡെവലപ്പർമാർക്ക് കോഡ് സംഭാവന നൽകുന്നതിന്റെയും അവരുടെ പരിസ്ഥിതി സജ്ജമാക്കുന്നതിന്റെയും ബന്ധപ്പെട്ട പ്രക്രിയകൾ പിന്തുടരുന്നതിന്റെയും വിശദമായ ഗൈഡ് നൽകുന്നു.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIM-ൽ കോഡ് എഴുതുന്നതിന്റെ നിയമങ്ങൾ കൺവെൻഷനുകൾ.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - OpenIM-ൽ വികസനം നടത്തുന്നതിന്റെ ഗൈഡ്.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - ചെറി-പിക്കിംഗ് ഓപ്പറേഷനുകൾക്കുള്ള മാർഗ്ഗനിർദേശങ്ങൾ.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM-ൽ ഗിറ്റിന്റെ വർക്ക്ഫ്ലോ.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - OpenIM സജ്ജമാക്കുന്നതിനും ആരംഭിക്കുന്നതിനും നിർദേശങ്ങൾ.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - നിങ്ങളുടെ യന്ത്രത്തിൽ ഡോക്കർ ഇൻസ്റ്റാൾ ചെയ്യുന്ന രീതി.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - ലിനക്സിൽ വികസന പരിസ്ഥിതി സജ്ജമാക്കുന്നതിന്റെ ഗൈഡ്.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - ചില പൊതുവായ നടപടികൾ പ്രദേശികമായി നടത്തുന്നതിന്റെ മാർഗ്ഗനിർദേശങ്ങൾ.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - OpenIM ഓഫ്ലൈൻ ഡിപ്ലോയ് ചെയ്യുന്ന രീതികൾ.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - പ്രോട്ടോക് ഉപകരണങ്ങൾ ഉപയോഗിക്കുന്ന ഗൈഡ്.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Go വേണ്ടി OpenIM-ൽ ഉള്ള ഉപകരണങ്ങളും ലൈബ്രറികളും.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefile ഉപകരണങ്ങളുടെയും മികച്ച പ്രാക്ടീസുകളുടെയും ഗൈഡ്.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - സ്ക്രിപ്റ്റുകൾക്കുള്ള മികച്ച പ്രാക്ടീസുകളും ഉപകരണങ്ങളും.
-
-## Conversions
-
-ഈ ഭാഗം OpenIM-ൽ ഉള്ള വിവിധ കൺവെൻഷനുകളെയും നയങ്ങളെയും ആവിഷ്കരിക്കുന്നു, ഇതിൽ കോഡ്, ലോഗുകൾ, പതിപ്പുകൾ എന്നിവ ഉൾപ്പെടുന്നു.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API കൺവെർഷനുകൾക്കുള്ള നിർദേശങ്ങൾ രീതികൾ.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM-ൽ ലോഗ്ഗിംഗ് നയങ്ങൾ കൺവെൻഷനുകൾ.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD പ്രക്രിയകൾ കൺവെൻഷനുകൾ.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM-ൽ കോഡ് കമ്മിറ്റുകൾക്കുള്ള കൺവെൻഷനുകൾ.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM-ൽ ഡയറക്ടറി ഘടന കൺവെൻഷനുകൾ.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - പിശക് കോഡുകളുടെ പട്ടിക വിവരണങ്ങൾ.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go കോഡിനുള്ള കൺവെൻഷനുകൾ പരിവർത്തനങ്ങൾ.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - വിവിധ ആർക്കിടെക്ചറുകൾ ഇമേജ് റെപ്പോസിറ്ററികൾ ഉൾപ്പെടുന്ന OpenIM Docker ഇമേജുകളുടെ മാനേജ്മെന്റ് സ്ട്രാറ്റജീസ്.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - ലോഗ്ഗിംഗിന്റെ കൂടുതൽ വിശദമായ കൺവെൻഷനുകൾ.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM പതിപ്പുകൾക്കുള്ള നാമകരണ മാനേജ്മെന്റ് സ്ട്രാറ്റജീസ്.
-
-
-## ഡെവലപ്പർമാർക്കും, സംഭാവനകൾ നൽകുന്നവർക്കും, കമ്മ്യൂണിറ്റി മെയിന്റെയിനർമാർക്കും
-
-### ഡെവലപ്പർമാർ & സംഭാവനകൾ നൽകുന്നവർ
-
-നിങ്ങൾ ഒരു ഡെവലപ്പർ അല്ലെങ്കിൽ സംഭാവനകൾ നൽകാൻ ആഗ്രഹിക്കുന്ന ആളാണെങ്കിൽ:
-
-- നിരവധി സംഭാവനകൾ ഉറപ്പാക്കാൻ ഞങ്ങളുടെ [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) എന്നിവയുമായി പരിചിതരാകുക.
-- OpenIM-ൽ വികസന പ്രാക്ടീസുകൾ ലഭ്യമാക്കാൻ [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) അന്വേഷിക്കുക.
-
-### കമ്മ്യൂണിറ്റി മെയിന്റെയിനർമാർ
-
-ഒരു കമ്മ്യൂണിറ്റി മെയിന്റെയിനറായി:
-
-- സംഭാവനകൾ ഞങ്ങളുടെ ഡോക്യുമെന്റേഷനിൽ വിവരിച്ച മാനദണ്ഡങ്ങൾക്ക് അനുസൃതമാണെന്ന് ഉറപ്പാക്കുക.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) എന്നിവ പുതുക്കി വായിക്കുക.
-
-## ഉപയോക്താക്കൾക്ക്
-
-ഉപയോക്താക്കൾ പ്രത്യേകം ശ്രദ്ധിക്കേണ്ട കാര്യങ്ങൾ:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - OpenIM-ന്റെ ഡോക്കർ ഇമേജുകൾ ഉപയോഗിക്കാൻ പദ്ധതിയിടുന്നെങ്കിൽ ആവശ്യമാണ്.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - ലഭ്യമായ വിവിധ ഇമേജുകൾ മനസ്സിലാക്കുകയും നിങ്ങളുടെ ആർക്കിടെക്ചറിന് അനുയോജ്യമായത് എങ്ങനെ തിരഞ്ഞെടുക്കണം എന്ന് അറിയുക.
diff --git a/docs/README_nl.md b/docs/README_nl.md
deleted file mode 100644
index 755145e6f..000000000
--- a/docs/README_nl.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM Server-documenten
-
-Welkom bij de OpenIM-documentatiehub! Dit centrum biedt een uitgebreide reeks handleidingen en handleidingen die zijn ontworpen om u te helpen het meeste uit uw OpenIM-ervaring te halen.
-
-## Inhoudsopgave
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Richtlijnen voor bijdragen en configuraties voor ontwikkelaars
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Codeerconventies, logboekbeleid en andere transformatietools
-
-------
-
-## Draag bij
-
-Deze sectie biedt ontwikkelaars een gedetailleerde handleiding over hoe ze code kunnen bijdragen, hun omgeving kunnen instellen en de bijbehorende processen kunnen volgen.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regels en conventies voor het schrijven van code in OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Een handleiding voor het uitvoeren van ontwikkelingen binnen OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Richtlijnen voor kersenplukoperaties.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - De git-workflow in OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Begeleiding bij het instellen en initialiseren van OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Hoe Docker op uw machine te installeren.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Handleiding voor het opzetten van de ontwikkelomgeving op Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Richtlijnen voor het lokaal uitvoeren van bepaalde gemeenschappelijke acties.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Methoden voor het offline inzetten van OpenIM.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Handleiding voor het gebruik van protocoltools.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Tools en bibliotheken in OpenIM for Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Best practices en tools voor Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Best practices en tools voor scripts.
-
-## Conversies
-
-In deze sectie worden verschillende conventies en beleidsregels binnen OpenIM geïntroduceerd, waaronder code, logs, versies en meer.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Richtlijnen en methoden voor API-conversies.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Logboekbeleid en -conventies in OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedures en conventies voor CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Conventies voor code-commits in OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Directorystructuur en conventies binnen OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Lijst en beschrijvingen van foutcodes.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Conventies en conversies voor Go-code.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Beheerstrategieën voor OpenIM Docker-images, verspreid over meerdere architecturen en image-opslagplaatsen.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Verdere gedetailleerde conventies over houtkap.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Naamgevings- en beheerstrategieën voor OpenIM-versies.
-
-
-## Voor ontwikkelaars, bijdragers en communitybeheerders
-
-### Ontwikkelaars en bijdragers
-
-Als u een ontwikkelaar bent of iemand die graag een bijdrage wil leveren:
-
-- Maak uzelf vertrouwd met onze [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) en [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) om soepele bijdragen te garanderen.
-- Duik in de [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) om de ontwikkelpraktijken in OpenIM onder de knie te krijgen.
-
-### Gemeenschapsbeheerders
-
-Als gemeenschapsbeheerder:
-
-- Zorg ervoor dat bijdragen in overeenstemming zijn met de normen die in onze documentatie worden beschreven.
-- Controleer regelmatig het [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) en de [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) om op de hoogte te blijven.
-
-## Voor gebruikers
-
-Gebruikers moeten bijzondere aandacht besteden aan:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Noodzakelijk als u van plan bent Docker-images van OpenIM te gebruiken.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Om de verschillende beschikbare afbeeldingen te begrijpen en hoe u de juiste voor uw architectuur kiest.
\ No newline at end of file
diff --git a/docs/README_pl.md b/docs/README_pl.md
deleted file mode 100644
index 9e89c9dae..000000000
--- a/docs/README_pl.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Dokumentacja serwera OpenIM
-
-Witamy w centrum dokumentacji OpenIM! Centrum to zapewnia kompleksową gamę przewodników i podręczników zaprojektowanych, aby pomóc Ci w pełni wykorzystać możliwości OpenIM.
-
-## Spis treści
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Wskazówki dotyczące współtworzenia i konfiguracji dla programistów
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Konwencje kodowania, zasady rejestrowania i inne narzędzia do transformacji
-
-------
-
-## Wkład
-
-W tej sekcji deweloperzy mogą znaleźć szczegółowy przewodnik dotyczący udostępniania kodu, konfigurowania środowiska i wykonywania powiązanych procesów.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Zasady i konwencje pisania kodu w OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Poradnik dotyczący programowania w OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Wytyczne dotyczące operacji zbierania wiśni.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Przepływ pracy git w OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Wskazówki dotyczące konfigurowania i inicjowania OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Jak zainstalować Docker na swoim komputerze.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Przewodnik po konfigurowaniu środowiska programistycznego w systemie Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Wytyczne dotyczące sposobu przeprowadzania niektórych typowych działań lokalnie.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Metody wdrażania OpenIM offline.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Przewodnik dotyczący korzystania z narzędzi protoc.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Narzędzia i biblioteki w OpenIM for Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Najlepsze praktyki i narzędzia dla Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Najlepsze praktyki i narzędzia dotyczące skryptów.
-
-## Konwersje
-
-W tej sekcji przedstawiono różne konwencje i zasady w OpenIM, obejmujące kod, dzienniki, wersje i nie tylko.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Wytyczne i metody konwersji API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Zasady i konwencje rejestrowania w OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedury i konwencje dotyczące CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Konwencje dotyczące zatwierdzania kodu w OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Struktura katalogów i konwencje w OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Lista i opisy kodów błędów.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Konwencje i konwersje dla kodu Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Strategie zarządzania obrazami Dockera OpenIM obejmujące wiele architektur i repozytoriów obrazów.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Dalsze szczegółowe konwencje dotyczące pozyskiwania drewna.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Strategie nazewnictwa i zarządzania wersjami OpenIM.
-
-
-## Dla programistów, współpracowników i opiekunów społeczności
-
-### Programiści i współpracownicy
-
-Jeśli jesteś programistą lub osobą, która chce wnieść swój wkład:
-
-- Zapoznaj się z naszymi [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) i [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md), aby zapewnić płynną współpracę.
-- Zajrzyj do [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), aby zapoznać się z praktykami programistycznymi w OpenIM.
-
-### Opiekunowie społeczności
-
-Jako opiekun społeczności:
-
-- Upewnij się, że wkład jest zgodny ze standardami określonymi w naszej dokumentacji.
-- Regularnie przeglądaj [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) i [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), aby być na bieżąco.
-
-## Dla Użytkowników
-
-Użytkownicy powinni zwrócić szczególną uwagę na:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Niezbędne, jeśli planujesz używać obrazów Dockera OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Aby zrozumieć różne dostępne obrazy i dowiedzieć się, jak wybrać odpowiedni dla swojej architektury.
\ No newline at end of file
diff --git a/docs/README_pt_BR.md b/docs/README_pt_BR.md
deleted file mode 100644
index e28db74a6..000000000
--- a/docs/README_pt_BR.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Documentação do Servidor OpenIM
-
-Bem-vindo ao centro de documentação do OpenIM! Este centro oferece uma ampla gama de guias e manuais projetados para ajudá-lo a aproveitar ao máximo sua experiência com o OpenIM.
-
-## Índice de Conteúdos
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Orientações sobre contribuições e configurações para desenvolvedores
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Convenções de codificação, políticas de registro e outras ferramentas de transformação
-
-------
-
-## Contrib
-
-Esta seção oferece aos desenvolvedores um guia detalhado sobre como contribuir com código, configurar seu ambiente e seguir os processos associados.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Regras e convenções para escrever código no OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Um guia sobre como realizar o desenvolvimento dentro do OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Diretrizes sobre operações de cherry-picking.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - O fluxo de trabalho git no OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Orientações sobre configuração e inicialização do OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Como instalar o Docker em sua máquina.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Guia para configurar o ambiente de desenvolvimento no Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Diretrizes sobre como realizar certas ações comuns localmente.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Métodos para implantar o OpenIM offline.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Guia sobre o uso de ferramentas protoc.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Ferramentas e bibliotecas no OpenIM para Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Melhores práticas e ferramentas para Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Melhores práticas e ferramentas para scripts.
-
-## Conversions
-
-Esta seção apresenta várias convenções e políticas dentro do OpenIM, abrangendo código, logs, versões e mais.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Diretrizes e métodos para conversões de API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Políticas e convenções de registro no OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Procedimentos e convenções para CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Convenções para commits de código no OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Estrutura de diretórios e convenções dentro do OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Lista e descrições de códigos de erro.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Convenções e conversões para código Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Estratégias de gerenciamento para imagens Docker do OpenIM, abrangendo várias arquiteturas e repositórios de imagens.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Convenções mais detalhadas sobre registro.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Estratégias de nomeação e gerenciamento para versões do OpenIM.
-
-
-## Para Desenvolvedores, Contribuidores e Mantenedores da Comunidade
-
-### Desenvolvedores & Contribuidores
-
-Se você é um desenvolvedor ou alguém interessado em contribuir:
-
-- Familiarize-se com nossas [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) e [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) para garantir contribuições suaves.
-- Mergulhe no [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) para se familiarizar com as práticas de desenvolvimento no OpenIM.
-
-### Mantenedores da Comunidade
-
-Como mantenedor da comunidade:
-
-- Garanta que as contribuições estejam alinhadas com os padrões descritos em nossa documentação.
-- Reveja regularmente a [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) e [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) para se manter atualizado.
-
-## Para Usuários
-
-Os usuários devem prestar atenção especial a:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Necessário se você planeja usar imagens Docker do OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Para entender as diferentes imagens disponíveis e como escolher a certa para a sua arquitetura.
diff --git a/docs/README_ru.md b/docs/README_ru.md
deleted file mode 100644
index 0e89df7c7..000000000
--- a/docs/README_ru.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Документация по серверу OpenIM
-
-Добро пожаловать в центр документации OpenIM! Этот центр предоставляет широкий спектр руководств и руководств, призванных помочь вам максимально эффективно использовать возможности OpenIM.
-
-## Оглавление
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Руководство по участию и настройке для разработчиков
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Соглашения по кодированию, политики ведения журналов и другие инструменты преобразования.
-
-------
-
-## Вклад
-
-В этом разделе разработчикам предлагается подробное руководство о том, как добавлять код, настраивать среду и следовать соответствующим процессам.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Правила и соглашения по написанию кода в OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Руководство о том, как вести разработку в OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Руководство по сбору урожая.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Рабочий процесс git в OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Руководство по настройке и инициализации OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Как установить Docker на свой компьютер.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Руководство по настройке среды разработки в Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Рекомендации о том, как выполнять определенные общие действия на местном уровне.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Способы развертывания OpenIM в автономном режиме.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Руководство по использованию инструментов протокола.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Инструменты и библиотеки в OpenIM для Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Лучшие практики и инструменты для Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Лучшие практики и инструменты для сценариев.
-
-## Конверсии
-
-В этом разделе представлены различные соглашения и политики OpenIM, включая код, журналы, версии и многое другое.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Рекомендации и методы преобразования API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Политики и соглашения ведения журналов в OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Процедуры и соглашения для CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Соглашения о фиксации кода в OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Структура каталогов и соглашения в OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Список и описание кодов ошибок.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Соглашения и преобразования для кода Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Стратегии управления образами OpenIM Docker, охватывающими несколько архитектур и репозиториев изображений.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Дальнейшие подробные соглашения о ведении журнала.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Стратегии именования и управления версиями OpenIM.
-
-
-## Для разработчиков, участников и сопровождающих сообщества
-
-### Разработчики и участники
-
-Если вы разработчик или кто-то хочет внести свой вклад:
-
-- Ознакомьтесь с нашими [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) и [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md), чтобы обеспечить бесперебойную работу.
-- Погрузитесь в [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), чтобы ознакомиться с методами разработки в OpenIM.
-
-### Сопровождающие сообщества
-
-Как администратор сообщества:
-
-- Убедитесь, что вклады соответствуют стандартам, изложенным в нашей документации.
-- Регулярно просматривайте [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) и [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), чтобы оставаться в курсе событий.
-
-## Для пользователей
-
-Пользователям следует обратить особое внимание на:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Необходимо, если вы планируете использовать Docker-образы OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Чтобы понять различные доступные изображения и как выбрать подходящее для вашей архитектуры.
\ No newline at end of file
diff --git a/docs/README_tr.md b/docs/README_tr.md
deleted file mode 100644
index d2bd119e4..000000000
--- a/docs/README_tr.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM Sunucu Belgeleri
-
-OpenIM Belgeleri merkezine hoş geldiniz! Bu merkez, OpenIM deneyiminizden en iyi şekilde faydalanmanıza yardımcı olmak için tasarlanmış kapsamlı bir rehber ve kılavuzlar koleksiyonu sunar.
-
-## İçindekiler
-
-1. [Katılım](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Geliştiriciler için katkıda bulunma ve yapılandırma rehberi
-2. [Dönüşümler](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Kodlama kuralları, günlükleme politikaları ve diğer dönüşüm araçları
-
-------
-
-## Katılım
-
-Bu bölüm, geliştiricilere kod katkısında bulunma, çevrelerini kurma ve ilişkilendirilmiş süreçleri takip etme konusunda detaylı bir rehber sunar.
-
-- [Kod Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIM'de kod yazma kuralları ve gelenekleri.
-- [Geliştirme Rehberi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - OpenIM içinde geliştirme nasıl yapılır konusunda bir rehber.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Cherry-pick işlemleri için yönergeler.
-- [Git Çalışma Akışı](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM'deki git çalışma akışı.
-- [Başlangıç Yapılandırmaları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - OpenIM'i kurma ve başlatma konusunda rehberlik.
-- [Docker Kurulumu](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Makinenize Docker nasıl kurulur.
-- [Linux Geliştirme Ortamı](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Linux üzerinde geliştirme ortamını kurma kılavuzu.
-- [Yerel İşlemler](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Yerelde belirli yaygın işlemleri nasıl gerçekleştireceğiniz hakkında yönergeler.
-- [Çevrimdışı Dağıtım](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - OpenIM'in çevrimdışı nasıl dağıtılacağı yöntemleri.
-- [Protoc Araçları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Protoc araçlarını kullanma rehberi.
-- [Go Araçları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Go için OpenIM'deki araçlar ve kütüphaneler.
-- [Makefile Araçları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefile için en iyi uygulamalar ve araçlar.
-- [Betik Araçları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Betikler için en iyi uygulamalar ve araçlar.
-
-## Dönüşümler
-
-Bu bölüm, kod, günlükler, sürümler ve daha fazlasını içeren çeşitli OpenIM içindeki kuralları ve politikaları tanıtır.
-
-- [API Dönüşümleri](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API dönüşümleri için yönergeler ve yöntemler.
-- [Günlükleme Politikası](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM'deki günlükleme politikaları ve gelenekleri.
-- [CI/CD İşlemleri](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD için prosedürler ve gelenekler.
-- [Taahhüt Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM'deki kod taahhütleri için kurallar.
-- [Dizin Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM içindeki dizin yapısı ve kurallar.
-- [Hata Kodları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Hata kodlarının listesi ve açıklamaları.
-- [Go Kod Dönüşümleri](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go kodu için kurallar ve dönüşümler.
-- [Docker İmaj Stratejisi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - OpenIM Docker imajlarının yönetim stratejileri, birden fazla mimariyi ve imaj depolarını kapsar.
-- [Günlükleme Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Günlükleme hakkında daha fazla ayrıntılı kurallar.
-- [Sürüm Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM sürümleri için adlandırma ve yönetim stratejileri.
-
-
-## Geliştiriciler, Katkıda Bulunanlar ve Topluluk Bakımı
-
-### Geliştiriciler & Katkıda Bulunanlar
-
-Eğer bir geliştirici veya katkıda bulunmaya hevesli biriyseniz:
-
-- Katkılarınızı düzgün bir şekilde yapmak için [Kod Kuralları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) ve [Git Çalışma Akışı](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) ile tanışın.
-- OpenIM'deki geliştirme uygulamalarını anlamak için [Geliştirme Rehberi'ne](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) göz atın.
-
-### Topluluk Bakımı
-
-Topluluk bakımı olarak:
-
-- Katkıların belirtilen standartlarla uyumlu olduğundan emin olun.
-- [Günlükleme Politikası](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) ve [Hata Kodları](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) sık sık gözden geçirerek güncel kalın.
-
-## Kullanıcılar İçin
-
-Kullanıcılar, özellikle dikkat etmelidir:
-
-- [Docker Kurulumu](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - OpenIM Docker imajlarını kullanmayı planlıyorsanız gereklidir.
-- [Docker İmaj Stratejisi](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Mevcut farklı imajları anlamak ve mimarinize uygun olanı nasıl seçeceğinizi öğrenmek için.
diff --git a/docs/README_ua.md b/docs/README_ua.md
deleted file mode 100644
index 1eaf6b5d1..000000000
--- a/docs/README_ua.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM Server документ
-
-Ласкаво просимо до Центру документації OpenIM! Цей центр надає вичерпні посібники та посібники, розроблені, щоб допомогти вам отримати максимальну віддачу від роботи з OpenIM.
-
-## Зміст
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Посібник із внесків і налаштування для розробників
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Інструкції з кодування, політики журналювання та інші інструменти перетворення
-
-------
-
-## Посібник із внесків
-
-Цей розділ надає розробникам докладні вказівки щодо того, як додати код, налаштувати своє середовище та дотримуватися пов’язаних процесів.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Правила та умовності для написання коду в OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Посібник з розробки в OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Ретельно підібрані інструкції.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - робочий процес git у OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Посібник із налаштування та ініціалізації OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Як встановити Docker на вашу машину.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Посібник із налаштування середовища розробки в Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Посібник із виконання деяких типових операцій локально.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Як розгорнути OpenIM офлайн.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Посібник із використання інструменту protoc.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Інструменти та бібліотеки для Go в OpenIM.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Найкращі практики та інструменти для Makefiles.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Найкращі практики та інструменти для створення сценаріїв.
-
-## Методи внеску
-
-У цьому розділі описано різні практики та політики в OpenIM, зокрема код, журнали, версії тощо.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Рекомендації та методи перетворення API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Політика та практика журналювання в OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Процедури та практики CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Конвенції для подання коду в OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Конвенції для подання коду в OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Перелік і опис кодів помилок.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Конвенції та перетворення коду Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Стратегія керування зображеннями OpenIM Docker, що охоплює кілька архітектур і сховищ зображень.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Більш детальні умови для журналювання.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Стратегії іменування та керування для версій OpenIM.
-
-
-## Для розробників, співавторів і супроводжувачів спільноти
-
-### Розробники та учасники
-
-Якщо ви розробник або бажаєте зробити внесок:
-
-- знайомі з нами [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) і [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md), щоб забезпечити плавний внесок.
-- зрозуміти глибше [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md), освоїти практики розробки OpenIM.
-
-### супроводжувач спільноти
-
-Як супроводжувач спільноти:
-
-- Переконайтеся, що внески відповідають стандартам, викладеним у нашій документації.
-- Регулярно перевіряйте [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) i [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md), щоб бути в курсі подій.
-
-## Для користувачів
-
-Користувачам слід звернути особливу увагу на:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Це буде необхідно, якщо ви плануєте використовувати образ Docker OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Дізнайтеся про доступні зображення та про те, як вибрати правильний для вашої архітектури.
diff --git a/docs/README_vi.md b/docs/README_vi.md
deleted file mode 100644
index 55a99b8e5..000000000
--- a/docs/README_vi.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Tài liệu Máy chủ OpenIM
-
-Chào mừng bạn đến với trung tâm tài liệu OpenIM! Trung tâm này cung cấp một loạt các hướng dẫn và hướng dẫn chi tiết được thiết kế để giúp bạn tận dụng tối đa trải nghiệm OpenIM của mình.
-
-## Mục lục
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Hướng dẫn về đóng góp và cấu hình cho các nhà phát triển
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - Quy ước mã hóa, chính sách ghi nhật ký và các công cụ chuyển đổi khác
-
-------
-
-## Đóng góp
-
-Phần này cung cấp cho các nhà phát triển một hướng dẫn chi tiết về cách đóng góp mã, thiết lập môi trường của họ và tuân theo các quy trình liên quan.
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - Quy tắc và quy ước viết mã trong OpenIM.
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - Hướng dẫn về cách thực hiện phát triển trong OpenIM.
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - Hướng dẫn về các hoạt động chọn lọc.
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - Quy trình làm việc git trong OpenIM.
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - Hướng dẫn về thiết lập và khởi tạo OpenIM.
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Cách cài đặt Docker trên máy của bạn.
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Hướng dẫn thiết lập môi trường phát triển trên Linux.
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - Hướng dẫn về cách thực hiện một số hành động phổ biến ở cấp địa phương.
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - Các phương pháp triển khai OpenIM ngoại tuyến.
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - Hướng dẫn sử dụng công cụ protoc.
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - Công cụ và thư viện trong OpenIM cho Go.
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Thực hành tốt nhất và công cụ cho Makefile.
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - Thực hành tốt nhất và công cụ cho kịch bản.
-
-## Chuyển đổi
-
-Phần này giới thiệu các quy ước và chính sách khác nhau trong OpenIM, bao gồm mã, nhật ký, phiên bản và hơn thế nữa.
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - Hướng dẫn và phương pháp chuyển đổi API.
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - Chính sách và quy ước ghi nhật ký trong OpenIM.
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - Quy trình và quy ước cho CI/CD.
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - Quy ước cho các cam kết mã trong OpenIM.
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - Cấu trúc thư mục và quy ước trong OpenIM.
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - Danh sách và mô tả các mã lỗi.
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Quy ước và chuyển đổi cho mã Go.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Chiến lược quản lý hình ảnh Docker của OpenIM, bao gồm nhiều kiến trúc và kho lưu trữ hình ảnh.
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - Quy ước chi tiết hơn về ghi nhật ký.
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - Chiến lược đặt tên và quản lý phiên bản OpenIM.
-
-
-## Dành cho Nhà phát triển, Người đóng góp và Người duy trì Cộng đồng
-
-### Nhà phát triển & Người đóng góp
-
-Nếu bạn là nhà phát triển hoặc ai đó muốn đóng góp:
-
-- Làm quen với [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) và [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) của chúng tôi để đảm bảo đóng góp trôi chảy.
-- Tìm hiểu [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) để nắm bắt các thực hành phát triển trong OpenIM.
-
-### Người duy trì Cộng đồng
-
-Là người duy trì cộng đồng:
-
-- Đảm bảo rằng các đóng góp phù hợp với các tiêu chuẩn được nêu trong tài liệu của chúng tôi.
-- Thường xuyên xem lại [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) và [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) để cập nhật thông tin.
-
-## Dành cho Người dùng
-
-Người dùng nên chú ý đặc biệt đến:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - Cần thiết nếu bạn dự định sử dụng hình ảnh Docker của OpenIM.
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - Để hiểu các hình ảnh khác nhau có sẵn và cách chọn hình ảnh phù hợp cho kiến trúc của bạn.
diff --git a/docs/README_zh_CN.md b/docs/README_zh_CN.md
deleted file mode 100644
index 413d5dfa1..000000000
--- a/docs/README_zh_CN.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM Server 文档
-
-欢迎来到 OpenIM 文档中心!本中心提供全面的指南和手册,旨在帮助您最大限度地利用 OpenIM 体验。
-
-## 目录
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 为开发者提供的贡献指南和配置
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 编码规范、日志策略和其他转换工具
-
-------
-
-## 贡献指南
-
-本节为开发人员提供了如何贡献代码、设置环境以及遵循相关流程的详细指南。
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - OpenIM 中编写代码的规则和惯例。
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - 关于如何在 OpenIM 内进行开发的指南。
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - 精挑细选的操作指南。
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM 中的 git 工作流程。
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - 设置和初始化 OpenIM 的指南。
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 如何在您的机器上安装 Docker。
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - 在 Linux 上设置开发环境的指南。
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - 关于如何在本地执行某些常见操作的指南。
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - 离线部署 OpenIM 的方法。
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - 使用 protoc 工具的指南。
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - OpenIM 中 Go 的工具和库。
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefile 的最佳实践和工具。
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - 脚本的最佳实践和工具。
-
-## 贡献方法
-
-本节介绍 OpenIM 内的各种惯例和政策,包括代码、日志、版本等。
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API 转换的指南和方法。
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM 中的日志策略和惯例。
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD 的程序和惯例。
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM 中代码提交的惯例。
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM 内的目录结构和惯例。
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - 错误代码的列表和描述。
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go 代码的惯例和转换。
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - OpenIM Docker 镜像的管理策略,涵盖多个架构和镜像仓库。
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - 有关日志的更详细的惯例。
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM 版本的命名和管理策略。
-
-
-## 对于开发者、贡献者和社区维护者
-
-### 开发者和贡献者
-
-如果您是一名开发者或热衷于贡献:
-
-- 熟悉我们的 [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) 和 [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md),以确保顺利贡献。
-- 深入了解 [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md),掌握 OpenIM 的开发实践。
-
-### 社区维护者
-
-作为社区维护者:
-
-- 确保贡献符合我们文档中概述的标准。
-- 定期查看 [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) 和 [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md),以保持最新状态。
-
-## 对于用户
-
-用户应特别注意:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 如果您计划使用 OpenIM 的 Docker 镜像,那么这个将会是必须的。
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 了解可用的镜像以及如何为您的架构选择正确的镜像。
diff --git a/docs/README_zh_TW.md b/docs/README_zh_TW.md
deleted file mode 100644
index 8ca00ba17..000000000
--- a/docs/README_zh_TW.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# OpenIM 伺服器文檔
-
-歡迎來到 OpenIM 文件中心! 該中心提供全面的指南和手冊,旨在幫助您充分利用 OpenIM 體驗。
-
-## 目錄
-
-1. [Contrib](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 開發人員貢獻和配置指南
-2. [Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib) - 編碼約定、日誌記錄策略和其他轉換工具
-
-------
-
-## 貢獻
-
-本節為開發人員提供了有關如何貢獻程式碼、設定環境以及遵循相關流程的詳細指南。
-
-- [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) - 在 OpenIM 中編寫程式碼的規則和約定。
-- [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) - 有關如何在 OpenIM 中進行開發的指南。
-- [Git Cherry Pick](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/gitcherry-pick.md) - 精挑細選操作指南。
-- [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) - OpenIM 中的 git 工作流程。
-- [Initialization Configurations](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md) - 設定和初始化 OpenIM 的指南。
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 如何在您的電腦上安裝 Docker。
-- [Linux Development Environment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/linux-development.md) - Linux 上的開發環境設定指南。
-- [Local Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/local-actions.md) - 關於如何在當地進行某些共同行動的指南。
-- [Offline Deployment](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/offline-deployment.md) - 離線部署OpenIM的方法。
-- [Protoc Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/protoc-tools.md) - 協議工具使用指南。
-- [Go Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-go.md) - OpenIM 在 Go 中的工具和函式庫。
-- [Makefile Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-makefile.md) - Makefile 的最佳實務和工具。
-- [Script Tools](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/util-scripts.md) - 腳本的最佳實踐和工具。
-
-## 轉換
-
-本節介紹 OpenIM 中的各種約定和策略,包括程式碼、日誌、版本等。
-
-- [API Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/api.md) - API 轉換的指南和方法。
-- [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) - OpenIM 中的日誌記錄策略和約定。
-- [CI/CD Actions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/cicd-actions.md) - CI/CD 的程序和約定。
-- [Commit Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md) - OpenIM 中程式碼提交的約定。
-- [Directory Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md) - OpenIM 中的目錄結構和約定。
-- [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) - 錯誤代碼的清單和描述。
-- [Go Code Conversions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md) - Go 程式碼的約定和轉換。
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - OpenIM Docker 映像的管理策略,跨越多種架構和映像儲存庫。
-- [Logging Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/logging.md) - 有關日誌記錄的更詳細約定。
-- [Version Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md) - OpenIM 版本的命名與管理策略。
-
-
-## 對於開發者、貢獻者和社區維護者
-
-### 開發者和貢獻者
-
-如果您是開發人員或熱衷於做出貢獻的人:
-
-- 熟悉我們的 [Code Conventions](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md) 和 [Git Workflow](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/git-workflow.md) 以確保順利貢獻。
-- 深入閱讀 [Development Guide](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/development.md) ,掌握 OpenIM 的開發實務。
-
-### 社區維護者
-
-作為社區維護者:
-
-- 確保貢獻符合我們文件中概述的標準。
-- 定期查看 [Logging Policy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/bash-log.md) 和 [Error Codes](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/error-code.md) 以保持更新。
-
-## 對於用戶
-
-使用者應特別注意:
-
-- [Docker Installation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-docker.md) - 如果您打算使用 OpenIM 的 Docker 映像,則這是必要的。
-- [Docker Image Strategy](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) - 了解可用的不同影像以及如何為您的架構選擇正確的影像。
\ No newline at end of file
diff --git a/docs/contributing/CONTRIBUTING-JP.md b/docs/contributing/CONTRIBUTING-JP.md
new file mode 100644
index 000000000..86bbfefcd
--- /dev/null
+++ b/docs/contributing/CONTRIBUTING-JP.md
@@ -0,0 +1,33 @@
+# How do I contribute code to OpenIM
+
+
+ Englist ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/contributing/CONTRIBUTING-PL.md b/docs/contributing/CONTRIBUTING-PL.md
new file mode 100644
index 000000000..86bbfefcd
--- /dev/null
+++ b/docs/contributing/CONTRIBUTING-PL.md
@@ -0,0 +1,33 @@
+# How do I contribute code to OpenIM
+
+
+ Englist ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/images/Open-IM-Servers-on-System.png b/docs/images/Open-IM-Servers-on-System.png
deleted file mode 100644
index 3c8a1020214a2cfcb9e5cc6c5beb339b7e2be67d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 21614
zcmc(nc_5T~|NapjYj(0^&sGd$OWCr^mLv%?$)K{+VkcR$WvpWmS+Xxh)(qK)A)@S&
zZDil~?RO8I=k%PXbIx;~=llKs{)%wB-OJ~CU)THf{sdjsQKKMbCdI?UqtH-SzJ`ZK
zfW*VYCnF{R{^v{xX(t}ubqNjS%hz2X^DlHG$JL*&?=v|1eYCt$(MtB#a*!q8Nur5t
z4ZrEUedoJs1-oV&9X-ntl^r&y2Iv{#@>E6C_16u=ds;Wn(mZHB!K&kToj!D<>~N=$
zVP(9x=5T*DP}Y5FumkG7$FjFPJ5_c$N)$8nSl)X}b8$#Jw)wTa{Nd}V&pec~yKCVB
zZ*yU7o_*m)L&;s<=ZR!9cmzFDC+0l)RV&rKGr2#f6do*3O)fH6lPQMKh$L^l$k|O?
zJn`U@*F|IlxgM7m*BWO>z-E9WtnTqu;^n$6jB9_EW}9D)idvSz-nx~Y*QI?FJX~4D
zZSN6BT6yTDQ9rvDSj_6H#30@Y@B_(DD&ZntyfO39ZKS(IRAar{riImF->luEy7Cc0
z-U?>}8z0Hncqta~zc7Fd6(Pz{4TzC~Rf`t})wBkmlIz(97B3SX@SB~|kX&fsd>kAm
zbVX)#j7^ID6k*&5{zULdf|eR`V`bdsd|-ZBstdJm`iN3E~eZ)SGvQ6JPi?0?!KSGP8!
zm2Wy%5k964WkLj!R~7VZB^bg7PDQ+_ZM=P|hJz)t0?F+u8?u<=w6tRf(zyKj%iOda
zub#b5{dCusQIPxgKBr@i*U)ao?4*m_@HnR}WwBckrdzw&*|=DC;LR(K^g?07fj~)h
z(}ZnmN%Tz&8>37h6fWChf{Cb3BCA|Uko_{c(|3pEWB|(KgF>4=c$@mM4@hMQW90#Y
zCK<_WZA@p>_>`=#8OcT#o-Do$NvjD3^UnE6hNIfwDHb4l(Vh$zvRq0X8yNvZ0goB6
z9Ujz7$e@rZKTmb70H2+tUkLFnE<$whEiKwtuFHKyvYccKvwk1|#9@yQ*nbA?CXt_sTO%WfWrLD4ZA{`0mrwhdsJJEpV;b9Rfq`2M0VBOz`vGUdJ(-qUx
z(tdfRl2>|dllpaOQYgsT#WV3E$oU}Nur#niLdYUK;hBq0Um&5pfz*V^>ZQirC|I=U
zJt!eK_}MRJr?&lA8Xk+WE2=J+JDgqs8I8TR5@%F#QT+<8+(K%g2_s$YS{oAdAXaf^
z6dA;x6G}cXz
zwhu?p6>PdA?b#0k*c8X=GQfq@`n=VeeSv;9f;3KXu7w^kF5Z#ALt6vkghd;Hp3hP*<_7oJf
zB0ylG%DAX0mc*azih>}6p7G_9!$+4P!uCFFI&`F}c#D%fEMYyW&gLN{dGnKtUnKV)
zE@dVVN9CwjsNs1Qi)8fV^677yqMN$QI4{uG7?#l6*Ry$|$1paFA*9H-XIsJ-TiAZM
zXLKH;RMRgeE@+%p1B
z;(-FwQrr8vzOXzG$E0(&26TBnN#rCY;>JTTX%MuiCd63zJ@&bin2s1pn4wwkm-f~g
z?A8{@q8VcLAW2PEq%F*plCau%qF~;7i#e`129#_g&4z1-YMY
zjd9YV-E6bM1fUl4=r#ew7i^TF0ST{|h(wNvCf(wsP>1U5=aWX??)ar6YGkUCg75H^
zH{Y8$wYB52+_+qIAUm^8&oGW#?H^B!M;yAnMtQV2;=bZi`&Nwqd{Z_ALbqrVxyYhh
zo89Pr1#-x?zC#+~_+j8kCsOf#uNQwPC@|FC;J%qnc;=f5d4(%%-KCD#?c5$d-+T3(
z+tb1XJK`4qtr!WpeE*Vi(@Dms(tEx(>R8L?YwPFH&LiMG^8vX9X~m^i&`iuyHlQJ8
z$u$RC>*K>nQ$yZx-I0re5@*6?@EzgYv+KZ$U+|XF7G5d2%54LG6Duq10?3kkWJN3>
zON@KxFRZ*D*f3mkS|)m-tFfXs#45+`2ufZyb)D#l&u3QA^2WCg!5TGQtc$3wltEGE
zx9^3#w$e*VsvkS&5DOVj+Uy&T8fHCZiIa>THu;-k!EyZECeht{KhunoOMqr%90tF)
zEoZuY(8d@Mfh@-@B5Md6UVfS)@(4tdw7z-+Efegz{;a=y^V_!pwOPhWS#E=@ks1m^KAc=IBF`MX;D1jpY-RsaE{L10R6&F!NPfCp
zBMa|-gKe&$`z?NoH--Go)Ic?5L+-N@BbkLPDq3{YIHAHvz*GD31GGK%ET>%D;C_dDt)E=9BnBGQJNz5^`Sf6OXWrTM729N
zo^LYCcW!k#Fqu|?Xu!2rawZ^iuCW%u6R3G;-Q$1$uBcB?f^Vhwh3meWyNvwxhI
zD~Wc4vsU*rg>>7V&hh~dlZDm*b)6~c$)^Gox%I)HdA
zq|QjvTUo(hC+6D=-==7>Jf*}N=Zbb?it-K;Ft+e&*xwne%{-AKJ^n=18=QWbo&Qz&wzL(SHlOfyh=m^v|*_nMb3(Z)dwjib5VTRd2<
z79S5ew|gNrZu}p
zB(zEV(w?E|lbZ@R%WbNnJXix<{xeu5%hwx
z8()Qv>Fou9pVUS1j_x?i(WnT7C41!n3Yti3$v*GFlc8kQ7*%Fkl*skWr43fw_8)&AJWFVe5}fr
zE~X@8)_=Ftsr70fa>ET@1}2s{JOhX%`{+zGnrWZl3%t0^o=O)6*VB$^7s{bc6usAs
zqzEDKIAsh$4dM!tI<<&$k704Ddqv7Uxs(1MvqH(oLISloW=m2eGdyBSxWzI}9wq2P
z*cYEXzlHhAX+>%l|B3S}s%jGV&=X`oQB-%^#?*&o@IUf>_gZy?70L>#zK~R@Mz3}a
zFb~5KlO*
z{EKiHfes&epB@~)XM??$w{1S)MOl$>P<|-kq#_xd0C~afJwJi7Alqe0ygPUqKd~TW
zD??Jg1!WZeo0o%pb0psV!M#rDg;T!5fPmcMFm+~OkLK^jG!lJ~
zZyZ+}x&}d(BRaMqNry(o?D7b07c)&Y(QfGbfl2Qh{b3G(r_o(hvKBk!nlp;doO-=Q
z$~uIRf0l0lNy!#Im>itK=dmiv}*P&_i}(*`fflv}V5O8w{%Tre`h4APJ8KN5l&yuPQ_!m&H2Gb-fY29hStgnzt4e*&;
zfRc5;j*O_!hRMbLlJ+dfm%ht_4-;BKscj26$gNZ`)`N|IBk20oihPRlI+QfA;(-zR
z@88}yiCYYc(y^BLcVu)T1BmMqMgIO6>g2BGhkAO}4C0T&BRr`||5*0gNeR=|mWa0`akNmy46u
z16#ii1|%U5tPr5RF#$#z<&gCzAjms~P
zv8S2J^8(lNPApZ(fJ945O}I}9#@+*2KRX`kg-tr8xdDza58SH0+slc$YqjyEKFlB
zU__R-TaquQz3qMp6l5TbEECaO4p&pNt%mF7STtPNeB5J&4)LPgpbcGu5
zaxT#LW##R*S)A*YF|zO>KlDd=;GV9nNz_nyBx`As3+~3@lxOf;Z*8%v7ax10mY)Xw
z+aYeBYNONovqCjCK9^nQTmQEBocfQ%=QevUrYxv8?Lp8O%8?VkR+@Bl7d70rQQ5+J
z$uGv6-)?grvYq}c`s%ixqqPXx5SEl!+hcp=Q)2%w1Yy~Vo_904yg=trcx**TefxDl
z*uotiUYQ8>dSZt*!b&~k1EaGtTCohDNj}8A9d8Rz!IujZDjc>QdxxYPO;b0KvuA!L
zZp1bFd8O{|b=8y0jY_=m^?|D_zDy>FZ#uOw|vZbr>B`ug++WI)~BKS4e`WLzRy^%Qzz5?IKCN*IX@b2xz
zmDW5>X8nUbUCiUemi$$Wd~J%lv6bEvwgMNgii0wH-Hx
zi3)pGfePc52Qsd$3EmBGQHmRj`duM>XSHU?!3ulTr??=HUD`UFosmyiDP-UDT5xmS
z*;vrgxdjkK`bOxR{L>qwQ64Qw>@S?i@LF5XkE_v37Mps=2LCOEAuaBHx6*ON2@
zQ5I-(SkioQkJL8?HMDWdJ@2adyunNy;Dq)%@9llHyweR;weSylQ|4-jUSDC(KAqR|
zj9iu_m}bhpz8!DXs`^=ITSKFB-HW`M8{o?kaEoVEYi&qHt|T-^TKp~0T!_iy*IqK~ch7zZqc)Vlr(!CP@@)
z{Ic#x?#Gg6LJBVCvx1E1?hu%*N3M-&F&N&Bd~`wfR87Y=UCn5gDk3s&0DPbJMI2AP
zBEM1t8C4-=BckIZ79kPyN*pBQ^j+4vdUm%;hdj?y0;MET1cxF_yXy(7e}-h{bdGT6
zjlAv)7e5ZzyI<&<&C$GC3FHt^r$BPXZ&A-(({lbzK
zACYfLM}>u7KX&&xA8>R3V5hn&!XGoQpYAz&wT2G}k7j}Js2UfHB(E5pJZ-JhI?$;QLuq3<&|vG4mke9w|^&@79whL;&X77%o1M
zTOD;{qNUco!NgI|>+XbX3!PaJ+ftr3j(QSTH$z`#Lt_|AQ8Bl2;c1kUqhwA+oAtAn
zm*$(fdDVrtV6Ow0p$K~)EN+#qSCV&CdtG?K#Dp48T
zke>ML7`$N}PH%pwml(&-!`LuENddfUXwolO
z6k*i}#^fSQ^RBu{7X2!-sKwa3ye}<2|1-AiqHy#A1D3tUan3=5f^KyBKbZRrQb@!+<|
zZ%XDnNn7n7++EN{AE{`mM=a)bdi;JUeq17wY;h5q8xwfcYq{U`IaA|!<%F=q<9eG>
zt5Y?QGJX{w++%RBiFQ(~@Tfq;MY1x(m@q}>zHgD#`ZrO&2yNi`r7l$x2(pQOa{iSl
z6Let4&?rHXDaEB$m%rrW-GKy_bI0M|*25)s`Oo8Ku_JGy^gb!aUB8TxCE)m&lD*!=
z1DHC<%WJa^f?kF9&kYC2?!X%vvAyzoSJ1eZ@T11Yk9FHuvOx7kp5AP-HsLx8YephJ
zX`avTv^}I&Ibn3+WIdsS_3`&a@JlUBF0kr?nsMdZmYW4H*D&$w#rB&Vh?X#jWOTJ0
zYe>}bD`*i_USz{@&yua8&@zqL^vaz`FswD3rgKUqymY#IXo&ZT)z%hv0r*K*`I
z@CDapUx6FTJG;5ZvV6|H7S$?!tjlt=g*7$*Wt2DoWUb@bj##5S;Q9SgmMydvvNhs=
z<_q`JMXFAEOJBLNz#zNXE_O3jw}sQo)ZO;#Q_|*T@J8Sx5l7JB#%eG7_cqmjb7swB
ztUnOjWQURrN_Is)srH(`2?36s;@TrX_k4u3yv|XPX*bQ9
z-Pwu^(EQNF$uIKO8&lcxmx`rzRjF}iu}a<=rFNmq5MgD@X=aOs`pJf@tg$jcpOozP
z&E*-e%=^$tXup-62$SbrHzGxa&N4Ik8IX+B1Fx{V?Ss83Jm-s*Gy8xHZ}khgQ-vRZ
zTjO5S4#?c7eh>-R$7@_S52%^kN~I(wB!|dFys;r@w3dks-;m;tyC5wciBSMrvm;S}
z=Qx92uiHq7?V-|&)K>Q>;R&=gl6=ZpW+Kxf^CX-LEL?1D;*hY(c%4L@nPZkHcMCkt
z1qMF@v4NlD^#%<1yzV4~n{{JSm=5V=ovgawe9M{LA=QkYfa{))_n`e;@-b3RG3&Ju
zqYBi)xtH7Al&N2^tO`51bG4-#@E23GTbokdZjGzO{ZkHyVd|*
zE&ADu&mq$DWwNZ(Zl5L6fshg;0)&()RN8tpz#4USP*K4h|I2ZzWC7P(dewcYotHq^
z_#Kc2a%LZwrnpuA_0Imfr>hk?VlY#Ew=Ts?7xrMe7g+d@@_zZrTyl|~#ORhxBk8(j
z-4c%U!B!?+Y}{9n`wy@{TU_d2c0ZLQ#e}IqM!z;Xu&d98t5v=`StMI-?Ph@
za|bd^-UCPettgx9(}YgKK+y#m>(v5_t^1wdn88Qt>dS^xS3hI*CH;rToj7?7)$O8)
zbuJrYphD=xoF?fHce8tQ&&8zw!1uPNRD*jM`=9l?vV`U91)*j^qz7(bGX}75H%Qh>
z^2%3Id@%1_M(|KpBUO-po)gBJE$$6_a}z|4)}u}`GruJ+DCmw;reR3jMCXVa@HDaj
za$1?E7r{AI=t|_GZqj{iqde%@)RNG|4?!!KcRoZxm3kStw8;)nx9qS=Xnr=vQ}z32
zHRl%5@0F>OsDYlGmn9AO2`niAylffW%Vc>|IEn|#zUUd))3OLW7}uA2qezP3VTyUa
z@Gu&%e^LBO7jH8D0k^-jIJl0Uy6)1T+Up{mpjH;0c-q2$Clx+H6D2R6*M7-p<$Kae
zCY+~28AR4-1>w%n@<7;-J^8mAW2QWR-WbD$iw{0O^z=U~xHa42CpSFpIDGh4G<#)9
zN#qJK{fawCrdr55Zy7A!1mhJC49FWu#Hg_D8>-rxCh3XlBAH&F?BFl8S@mB0VG^AkQhm
zkf%O$|3c5k%BJ1m_Ctr>NZ@*MY300}WW#^$1PJMhFiuF{U4#8zNCW>uNJ|_310mIz
zf>XRIlrn!;T}MN|w+^d24}+FW}SIz|KhmKafTwZ>;
z`dn6PWDk@+fNL%vb?FTx%d&JFn$pi$NuDQNlD2VOx1$|t_aJ6h8C!AfR!DE5F)EB@
zR89L~VT)Ta=y~3j=+tj3=jvJYOQqz4*k_vIx1fP3kR=3s=VJBi#$}qNrLs
zVYx$*+eFvicbuJ`1W|Ul>&+29HVdn+sk#6G%<98%H>1iIyP-$Tw>B%H)$Yv@1S=zy
zwIhVF%@C_Bj|j)P)ZvdK*cSziNw@Yg(--tW#MP9^sf#lmAB@~x_2^Xe=w1T43jCXx
zFf$2!rs8M^#IL{yjTN}o9q_?a#;@Oyhwy$UA3DD*F1h)OdU5mHFYFtox3}qfVRTae
z5Y7pyi@ZDJX+M)qAWr>Y7S4uwFGjgG`=G_!a}07YKUFC2wO_vJ+>2Rl&isYaj($b2
z?Sae+VZ-I;=UcfwA69fF)Sb+>7L%_#$z?mM+aR>X(2mhS3xuI=#6^^(2ycz^a6
zo43MPX=~z9f$hU*yGIn4XA|N`)!r1C^L*@BTQdFQQtZtJuoU_~$(@$QXD2W=D
zk~_Afo;J2MZx|kGY0>SaBW1r`@djEieI&MQ?g@|mO+bYayXQ$CChirltZSyytlM-0L>ra$dXKyiON<9j}#3yrcqLFhgM5sB>DaH+Ex??fC44vjj4+8cIa-{0L224a#id3X8YL)RzdXK|*o$9P1bZRWnd@d8)JKx-%119kr^
zwjKebX%!@pp`?#)x9d6
z5H*7F*jfs@+i=99Y_F4Yrd2tKnc;eimdiY=eh$%;
zS9Vtlh^DzlZ%N^3lqF_x4QGFw8JbXx(gBtslZ(>5uK@L`l6peiV2GjjU8-J|_#U%*O1o+$$OtTa
zS=&7{PtO0yZ+E5EZM^4pPj!1Eb-atkubsY^Kk4-058gcYKkoQmC`AV<^qdRPw0u{=
z8+OhUjRossbM^egVw(-Qabi^%n%YNVr@`#$?BQ6oHRe+NRd$9fVDI90QiNJgHLl|q
z5aid?mA#gceEVV65iF8g_)A9}4i@?KXA(<}6iEgD50&Zn($(U&E#(@VuzMnXPSmzS
zs7$0g*Lh;`HtY1caqwYJw{mjP8tJt`POxP8={BG>rv#RAPA{~&oV43RWUv{{M{JQ@
z|CD0wTvgr{$3Kfy|9H1!s8yNQJNabKiImxf?^2c5dn8qIZ!gabw1vOE+;nTB{42nq
z%xPe60St;sXN(%#&D>gjvffkVk1b*^uD-nSjl9rAlRr(Q0p-!O>9k_iuFky>dgagP
zk=OYMbMJhiUI#MxR&c+5VBDCNlYmY#6s1|PkssLflLk?FYeNB>K`7A4~H+xkUQ(+
z?jpdN0B9luBw@gb(Y1#mEOu1WDD80swLCGU(TLkg?eQ^LpntS?{kz9JA{SsN;z0%=
zMp^@_DsH4D8QUg_dQ{=d*n6
zewI#)80BBU{+3SPqR(lh-hxPSMC+ZF+*n~+CAqX+S|uh3bSLZ5=zb*>?`~O^%YFEU
zkoIoJ^eTdnQ_$KJ7@8Qb0*m~*SCaxZ);s-Iq1aQ&U5Y+(#7AZyyJ@s
z+SDv~o8Fq3?nhM{x!B(C5RT8wL;V9)6jJ^>sN%wUoX{R2ws)4{74Z=<)b5h%fnCRi
zfk&O(X7`FJe7Eu>nYjkui*NyQD=PI=W}yUZ69cEU`?h--h4&d&!||o%?7gxu0J^G6
z7reGWtuS&vG60fSFK=)~k}z{@GpBUSwl9s+$OAd=smDnR)NuYo5ys-b(WXC;
zi6D>C_WPET%TR4RKu`oP}3F*sqP
zl$Iz!^vcKhDd@&0?Ym5@YMby@y!_E2?g{d?~C-}eJo;v^5V%DoG{ZY7HS!#f@K0`ax}pclyG(&ytf
zAAT`mg4=_ByaC`LaYGI}j*C+Th;TVM(|zRI%`_my{97a=HYqpw&7~6^mRrQouiSR0
zlEaTM6uBL%_E-j>$~_?HVQ4Q7e&`1XoU0rAtsfeEw{=1G9WHc^H&)q4$r9JF4kExC
zG+(meV!4e!c+}Yk|AiRsXA;=8G%fv~f{h=lM5mP^!?ZXz{guc+rYYQz1mv+!NdN8U
zV;#cWD%>te{42WgSbz>}%P(r6iAmp~=YR-g>>bRL_$~G
z4N0*75TfQ9BcAVy#fiH60>|nje3-j+X@Li~iXKbO@G%W9#4J>gC_3r&CKKy_(2X7=H#hf6cKi7QZw*;
zpjrRh3GCHlv6)}q6o#FAdnzDLXg%d-e4OR5Kd+1%
zd9vp+uS;c1V+!9anB(uSnk2^*g!f^Io&gQ`Ohi=8eaZVpU*3%`rx_XF?+{$3e!lj3
za@zCmk4-BBluX{6rSv9wqx}Kv!>5T45|VvoQHgs7#b(_-5V>}FQ=L`!uwR>08I{m
z-$n~D>VkE@racSA%rP?#VfTp)2qI6S-D(A^wJM+ez`t^w7srS7tvTIol2_?SXcbfC
z0h@)%jT0qz^6xDlR?8m1UD@>&06){(_+4BigzD|_!fbM|
z4U~0CJ!MIMPhF(&y2EaX|2aP&hd`!eR}%?Nk8%*ko07fe@fCfxl4ce
zwmC+&1+QN`K}ds;7l&y==d6rDeC)}F@p*wSzXWPw;ydN16P!fZ36hNO!^WASMie=Y
za7LE!zoRb?h}#&v>{e$VhFl}WjmjY`W%T4$-Ead=M|{pWiq#&jdY6ic`3xACyqZuY
zds*?Ok+%O6CM{#{!+qKhGmCxP;m?2I8DruBp7Dq2tK$60WzG;#F$yFI!xdHEc-()i
zT9*8k(jQ08ej>u^_+fg40d7`3=hz$I+J<>dWq}giw+U=8{gJ<%=qf2m1?&@-EDSHuE9
zJ!csNAO89Lqez^ELEQRoVOamw!eGbATz-Qm%
zqv?0P)O@^)&~@lH)nt(u%7kES$zt8rr%VfH@{_8-C?zZ5GP@o~Za_@%l=nz&KWEagS-_AR)Vs&zAQ09h-
zf_JP^je?;8B_yDL!exz~s7`SwJ{>4Tu1_6u&Tk&>W*9G`Cglng)4VHx?F+>xJR4R?
zDv1GTL$}Xpw!1oe95OJ^StcA1VKUwR;fFb#|E4iCJ5#sUJ^reAqEWLSeNjg<8~zFV
zCQf?|CN2Kt_N|I8%;{|Y+f7~;T@bm|`DWC+59~2hJ?Cy5lI-5&4K^~(d)#}381~!<
zShhG-7%sMB@d3KZybdqVcs1upOWgqkTwnh^Cc?(9$2SO|+kq%)uMN1eEizITW9|Hf
zVr{QYcr~h3HJWZ_UreQ1Tm}<-J!9DF{;kF7ne|#oLzV^F?53Vjg}sM%C8{dyU}`=y
zfgiRVgq!!eaZ;dlaQy7qZ~G8z*XDoRCAv5I=Ut*w$Z)K@I<>#c;r=ps;j1F(RVaa6
z;3y+GLBuEkHwt-P241vPX}6EA$#!>Mejqe`Y5A}uTlO6o-6X~fT|SnpUBAC0S3{kE
z9TLU-p&bHr;04}fY|F^^O$ys|0x9XL3+7b3fg-aIhg;cfl*N0`
zJr_zx3!eg0{&Cl{TVx4d1}N&!8mMm6+nnroxwc^Y=m;FNyi_~>zuGa9{4`;woItsE6q%}_IeoL97^n+
z9sPJAO!oJ61g`oDT>Za+^KGZmm`;nQn|QPQIS#~(<>zfsMyDK+&oS`H*Xx48(Lm2=
zZj#T(Q1wqFt^4FpB#mP9zmv3?$#)l4dUc+!#W*6pXYZxz8o3c=&r>n6n2=)u(0~(}
z0DuO?937sR_w^@vAD)b|5w2RQb#><*3RmA5>rl&qR4XL;TtGkgdIq;sM8ShiyFZ;9
z&Ty+B3<;!~1Ie_>@Q;t*j0x)icFrKOzSJ7=_-6^5!KPw!%$53XjC}`x6#~d1F>cZe
zSNqM=i>AJ=>NUK@2k5#u0h{~tq8pNkG#r-Tlzi9ZRzMQPCDPxK@^U=v1R}+v7Qf$U
zqHNof@xNj8l#duad*`Ym{t+vU%98Or>`piI@Wfb{gg`!}TG5az{Nzf!r0X_LPvF|b
z-D@u6^hxn=5t@GLNFz$tJJM(MVRT)AG4Pdv6AS{;m+4B4T5y7tHQ?xi27ewL2Ma*=
z58A(^0OOB5sK2d6-faSYe+|Qs#=V?k
zA$OP=7b{eEul##dUWI$>Us8F<(G`)}5ECWE4Mz=?CpOf@1R`I-3W~g>PmPqQ{(^WooiV5uB<1HJ$
z%K1KA08BEOcU2R^=%^{{aPz#+zVF^KDl!BuYQPQ)#sTxZ1i(C6hn6BQyvB~ktPT3{kU6&_q>^j
zYB`+AOpOx`U)FzpJrwXq=RO~`e0blu9N`HC*B?pJlSsE!8CGAZ0&qsAC}<%Sxb>VA
zZGiLytsMj4(23QyU%mw`-hwl*6+Cp-^Rpr>*nI
zAHw13YF(N@GQju(7XHH~C#2O5&(?IDUR1vSB=i$x)pCffN9!rcYoYPFQ5QF9++HWg
zbC0TVz4w|30Hj-2q6?#ezPOr^il@WOWXtxAI@7jVRhXNT)}P~nTGzRrj^-K2Fm|O;
zbLv@mW!oj!TLqnxUvKe}FGi*WfhGp8!5C?Z0Pb8O`?O!6R#yV@*%ozy&QJS0Oi_;#
z`(N|FpL#v{9iI1~3&KokpNQbqgrROhPKULkIjUXIghddR`{u2NMwh_Otrlh56YI-t
zXAE_pSyORPO6T(XAU!|q$M_6UhADcY=}U)9V#~xS__H;{rvAYG3vy;
z>RP(GHYi3KzPU2yG6s2m>H0<|`@TWA8qz`b3=~EimCq>uZv
zQ~?h&aURtGux-w-q%Qri_e?a1<>y0Fp0gbTK7WC9|6V+vAYKT3vU-18g+AadVs>a+
z$y_m2DT?XUIi>J{rgHLevOpt}c+v$$MZ0i<7qP%bMwJ<=8YcQl5Ie3h=^{#{A5)p8
zbWdtDKNp)HZf&N*L9hU4QD;_O0}ECo0wdh4^mUG?p_&a5VeY)p(AR0el__%t;V*827teYt
zQF1yW8^->}(Et{=3Jw&jA1Ced*9zd56E0Q~8-2mF%YBl+v#Mu#?=kpjCC&|<69&ff
zBr_I+M&_yl0~22%{@ju@eLY~NPJS^JrzcaOxj^vPyNzK3?+-_te$@uIJ0QOPyKhrT
z+h-sJWvMng-biWj^~XjGttT@~PU`i!#c)na5R(|$pT_N46cdcwgknYAEhy;OVrtaf
z@(+^$wT!1ChBXTG8RIG&|FswSm!nEwu-U3^(j-P!!`JEFYj7(q>4^EatH5GudQvgp
zg@EtHu@Ln9CIp5}{~v^aYQrgVSc?-~gdgQ->Id{N)+1W^gTwJ~)b#o>HT_TP{|S6K
z=Qzr1zj0`$IjJ91a3e@+-X9-VUh2igWgoo4bAm52TFoEv(Rx0=ht2+llm7J^de&EJ
zN)9)@S7*Hgvt!B(N_+fm+)fIL^|YF|Wa*r+H{asqA~awAfUjuj>AOYty#xrad6QKTE$%R8
zx4h2k#PbJ*gfce(`}oi>4T*CF!H)k-N;6RNJUvur_)zW6rt7zT2Bs2?JEYrzdmYxR
znb%gK4UId=;fJ6(sdR*S&S6N+ZF{qknSJ(~DdfD>YH|FLuCnsgs%+DfJi?NKfky{7
z?H>5;k8a<4e)W^YNX`4u19|Q{D?|331B@lY7oq7_6f(sLI&ZhlZj!G_r71F*cpy0R
zcvkQ1^zLI$esQ~GDjk$7CiuiZ@tn!c76q#T_&;v((Y}$v#aD4p_n&Pb`F+q{r~UAk
Z7iVs2wPSi}fqg{rG*ony3lwkr{y(Ud)0qGO
diff --git a/docs/images/Open-IM-Servers-on-docker.png b/docs/images/Open-IM-Servers-on-docker.png
deleted file mode 100644
index c66f7fb095e862e64eaab2a9dbc1ac1c3c73977b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 10172
zcmcJVc{r4B-~Y!FLbl41G?rAdmJniyQmK&a%T#14ritt^!?#35D4{G9h3rZ8Wt3$^
zmTXhR2xGF0VHjqg=Tdj~dfdnJ9LMkYU4J-cxSZEq=lOY^@Av0D*8|)0R@;Pk34=hO
zZKqFJUI2l3JAv0vg#6bW97g+W
ze4-Zn9KW{x$Y~9|$nlHm@p)A(Tj0)k{W1DxJxa>F6vWgk^4mtWC;2wW*
zR>u(f5hc?Qsrf|nmg)1(=`Ip$m)v1@?Nk+hqL(x_z~|QC58ldeMZJzSVyZHs8qt3A
zl`lTP%*BK_cOC7OX=!lS36A*eqrGC65;S<$%7J_(o?&DvsEPl{)@@tNN+e*t;Kd}G
zH&_JhXfX>l6)j_ROLV$J$CaiWL^UjjIa4a0
zz2~XoUx0ftra(XT9rgxApwNUnxm2sb+)RPa%Z(onj==m4sOG8u0-Z^oz13|>Q4%X7
zi!O0T#VU3Xoi&DI&sVoxnNw->`#g2Dr#>dmiJbJ{w#H#Ylit4&+58pD*3
zth)rXHFMXrI+J*T{ow!@9`wjN=GG~-@_6q}fKGt&&4a|kt-_y$xW
zi&6C$*H)470<-$M(-o*rMC;cAPX;Y~_RaqtHsVskf>I3t*=zA
zJHh*1YTSahORxAieBMJ@eWa7^Kv;pb->6h`bmb7};lofTx*r`uQ0=bqKzU#cHu_56
zmjy2v#d@)_%57p9x8e9D+Ag*|H|rsu&dv)%#!?#K3WS4rG|Q#JwMQ5de^sMr<3aDa
zW>3fB+VmJC(YMFk+h8KYB(lZouX&pZA8j1Gd_pmAYOrg1*BH#=_(k#S`#{
zOs9S16pJ_FpWT@DgwMsEXgml-Wn8gmCIuJcmo{K-+}%njuO?Sd44jDg=H81pF`Hno
z7Cf}Ovu$yqwW*SGKcd-n-f7roceyCqMTMH!TVI6@siicu;VV&z3`W%&YGI)m%iPc+
zfJy9)TVrqaIyu&~BpL0+lqIBc<66#$&(+RM98K+V{BVOGvuj$zLfTW=GR_*p_tBch
zQ9X{4tc0{4T=$REvgNKHX+7?)BH|Cq2FxpU!iWiO7c|$kDS+^Djo^ZPKqg>
zSKbQ?n7dCl80lqb|7gV;vyT^e%DmK2>Mc(;aew_SIC@r=-QD(tOHoNh##uu>S}Iv_
z6X(7UL$c`UJ;ya<;8^ksb?$p}KF!Z>WvmyW4rL#2N>ij;H%XZqmPb=U!
z4ELR8a{%{h%Iv9Sk=8TsnYz}j;o_V`SC
zXn0RIWfaDYBfrWDjSf81@P&6S_MJsu;&s;IPiUAJjD#|obML|EOR+fBISaTSM0AXIj}wy3bS
zg*Wbzg6Vq&D7s^sL>g0oPP0l;r$#5B0&C?KtFXiC^IPJ+<#8DD1rg)y+nFrmF&u;8
zKmz0N7Fc-mI0OZ1*@&bX20oCmUR;-M2KIC|^}02l!3rwG=SA5v9S7HR1aScu{yL9Uwi2|4-%gL%b7dJmkvg>-cYw^6Q~At)Z~Z#LTJYu4+2|WZnBA8&
zWomnmhsA_eU(~H4N=&(rrxr690jh}YFPjhALZf4J8&`R_S)8^yMi&1&jXSki)x(C0
zs9I<#O3gSGnRjivXuxk}zt%Km!9EO|Fnh_>bnlhRa{SvW?nzkF#Qm=!{DDggftPw7
z`f4`&MYp5VhKI+BB73R4KR3c1oB|fKQ*_F>JQX{rZsVHmhWtfLc1KzZHrA;wkNs|o
z^qZ-tKN3yucxj=ZQsiTsyVZ9y3Z6k)HHOHq2NDMt1_L5On4{ChS*XezhFmG!^Lai6
zvUbO+_yvr}>2K#7G+VDFYrdt0J~&!7;da~|=ZSii($^0WBqDA=V{zmQnHJu|S-YmJ
z*JSyfCm=I&@ob_}Z*?D-7CHx`ltngU&`fYcqbaL4oO|=TaywxaSB1RlNxlJnO5WI<
zbkgReC;M_I#ujiBTsQ%|1Md}K3VzXjB3y91D`w5uU8y@^%pM<%F`MO|(sfVyNIF{m
zY6-Q!AN9DNQ|r&{sF_9$1y;Av>FBs=*$ijS)ie(@x!E!4XW;=DdY=`;_2@e7nrt;$
zrv#GwDwxIRZKhcsdSUy9W$RUuOdBzUdmk#WR;_O%W5WihGRpenB$b8^y0Z+E)Lw|S
z@uDqpIL);U4Xxf3Z)lapU;o
z{#uz<0v!2`qX~MQmMd%hl7LtLV(^!>MyFO>R8Zj0106WWG7nhMD?LS;gAnjH`xc(V
zn|40A<8st)(5GF_<%IAbGChIfaZ=BkZ$6Lo&6giRKeX)qIlOPmk8aUBapL%++uM%X
z@QzODW@6ke6jUitr6FXIXm%3h(HkrFkpVu^*C1a09+xw*j5!C654{V&MS=Ks7+uPB
z=FhLcYrz(s971m1#f&rhwM?mqWi;!Xi16M8-Um7bBIViHalF|Kl%g>IJj`Z?^Zvu<
z_HKF78G#HPqo*-Tp7KT$*8)>Yy&9$}pOwpTjfx&iW}gXpgYI23dnV#QSE*3Ilp_5I
zH40!$hi@HkFqXAgr<=-OrZfy<8HeC-!a(2j05aT=Ib>{b^LwrTbO-60LAPiCh~H46
zfPx8gW&52G*P5SOmF*lZACT>@1kHS2aS%I8oLyBx%#_zX=eyp_zLQ1?>VT=EAF2s1
zs|r%8SB-}f523_ECEvIN?ex_}rZEmZL;YNdTtHmRXUN?xjqDm{teb51NshA(&Y{}N
zI-u`X_20KHU+Da>WBx9T9COxYgla*N_xkEa-#=P9b2Hy8Gf@`Plf<&W6t0q{>3$*r
zpAn|Q;i2kwtuV_V+pXDOXABoNWWU2$z(fYdf99KEiGcKsaYlwlIvz{>pNUa2pQ=g*
zuU8>BTg-$r^C1+$_Uas*l=4y`F*!H)mf
zk2IRN|2Qu0=cl(C6{n(y`0mx~d=e=_pPQS5o0v!qTY4ytYQMB54mVe^?lNNRqOY~-
z+|x95qq`p+vT>@1sW0?1{EszfULSwqH(tT%xKav!6aa#HekB&7eY;h6kD+VARFsv&
z4=;vPq}vb{m%=sCQK|W3bG9MIr<4^D5$z^u-n!uZcSZcl&C3Wu4&ZA)>1kN}vHb%B_6vA
zCOv+>!KKe{I%71X485E(u2mAm4UJ{CYW4;(r%T+v{S$3P`HN=<{aDV2=1+T9QX~of#mGV-ZnYZyjdzY7WrmQnRsq2il%p%^~-`R
zw?;YV^%1;csO3*y@h@Mv6uxhx?gVqvVXs+IcR}i$4P|&0l5vv=73QrIqn^#eQXh0w
z)BFg0GhqltaBM`dz-yjcc1znq6Qy-XqgC;!PQKZL)s=>~`~ecJ+3D$1HK`Dg*3IHo
zB9G#G;rJ()+1Py!VfgnZoNqZCfy(#Vz+7bQ?gkkq-5qgG&|iJe_?EKAeQ1#AulMuZ
zH0eX}siD#;bF4&Qc8ourxQO0B|`4l~vHUJJGQ`L#6|S^HFIQVyUB#
zH|DMPhofS~k9wlV!!vIqfmOW(g!S9gRbY2msGPup!0
zEr;r*^PZJ>0aGn2N;MF+V9tli8v#}G^s>v9WZpujQZ?$X1?z@^!Lji0y+tB5ykD9H
z46~e=BNXxZ%H02?PGz{SmjE6`3A`IYpD>Kl)?Qp4>Z^Kw6-x`tF!(ht<`kk#i{)BQ
z7#AD}G*-y1ziVzPIMtY)?Hls3)@)--;Hp|wF~jV5ALbZmgerVYaC4z6&qT96xtR{zV>Ho=&FY-QA$IR}3(BrlB{krTwVtV6-bR_B!fkJs1P&e1-W*)=H-zGMx6#h>tXa7cJ
za&>Cp{~1c^d(Y>4c$DYuAPH+`#=%+FHg+u8L9$NNv?adG(;6OJ=)${9`>ufxP3>Br
zrH^&pOhAAN)>VNIWbXx5w3=V3gTW|sFmo@EgevIDGt;!hog+}
z&Dx%E7U+!L{l4SI`{xD2efevXx!Ig4JR>nj>LAK-@1dQmb
zr5!jj4R(b{(>0R>=No%?>Z~Iy77#+#5&Gxvj#{K90!6a^AtIxOB{JjGc@4}jdM?eF
z=QedXFa`8CNj!+zg?G_Pvw6QSK@yW-pus(sYP}s)m#r^lb`19z7+e2_nTA%Bc6O%f
zuvb-w!F!It;r9Q8R8UAyeQwL<^u(4=I&5M}{@*ZdUMM)$qdDpEY4zvTkcWLksFVOj
zlXWV5gr>1)>OxklJp|{Is=yRPteyl){_vvAT+eU}bfKz|Y4+k~fyFpm(N4y@J2dV1IepHbOe=H9pE;*+ZzXSxQLoF(h9F!hbK{O~ELFVk%_4Vc68y&)SL8|~xc
z3j3aZ%JB*d@7mu+3fkJHBDr<4JwVae@^2WwEBK`?Yf%78g3*~d3Xwi9fPeoT%`kesSz;XNp;K2^9Nf5
z;i9b!z%m4M0NlUN00h<0)=$p0oP-prjom5%y+TI$9dyB<{XuHk;9Y85C?WL
z$$G$9=x3bcc^Ua=WJ|6YXK~AxCqdDc>4Py&Ha3<#Hf)H*7G7%Qe&Les&-XpyJ?(7@
zX(X|_BS%h0w=8JI7DjjgtA~q6DL7z-Z1RkUY+&IpyJCu1$zLDi9U;{e`EHyFXO^CU
zZS`Hmdu{);?qAKQnKiz^e!+lhN(V(aaYwDV`om~z`Z+fVhoFhzJ!zalSDRl(H(~7Z
zAE#Tq-*VnsmSM>GO)%?N-i1&{`?5-jh}Zc1s2ZwX8wmJNa)rnS2EMc!6T%aEJ%qcf3DuzU3?*94aagKO
zdG)<+!J*G{K=nd-`U2
zL+AQn{8&=ymaoNRdCw{qP?SxqjlS!8X^`Nv{F
zEWxvCIC&yKb2iYGl!4+&;)V4*Czu9Y3Li;6a+0M#@s_nJn_lG7r1-?w?zb)WKZw@k
zm{j*2(4dnmkvw4$yFPvJpB%y}|`p
z+}}KHdxa&*0V4V?3q$PF@380|BAL&P`?AJngwUS
z`fiy^u)irrxIMm}jFNDGj{*#@4=)rV8g5N@B*+6@tJpgipCmrT&gi4hxIKgOF#GUZ
zb~b3NSsC(KM^yF}McCu=fJ>thd*LdmnFN-e!EME!8Wj0Lb1&fL><fi}72hD?d`pB_XtMi)(cc_%i_2}Fy2Rb-*+F~%=(0fmjS=0r8P^}7WeSk@NKrp}
zq8%ikl5iPM&lq*Wj`aiOl_lCO^=QW_6SFri7TRx+`gsL4)U{I=WhS=dvU%$RJxOle
zkT-p<0=bf{5}Tg(_77W#$6R)4$>vbNq_=)_ZH~S_3+3?G{%%usyC1Xf{%TW==3E-Q#hc+ra$C0dwpP;Q6IOICnm~H*XWJmr}qf
zuzzV#|5#z5K`jLu)Z#x4s$<5_cbg5W^uIQ!Uhw;_AD@MMhs{@7Kwa7b6)&+0y}s@TLan7_L-)+W{J_x#poLJk#fCtLP$g>YkxT
zD0R(p$MO)D&rZ=6awoUNDEYdwT9W1LYU@}p<~uBFhfw2EKzbK$Cy){J&~SD^@yi$M
zE!ctif<^9cy1)-eG&ps-{=w^s>N3)TE2QClxmpu~z4VIvGic*hcEIgxkU?on2lNeN
zU_+)JUK-WjOotNWYY={wpA`kolKA`&ax?y6g`?fs2NQTqM9g|MJP9rD>75fNIi2!!
z-cpC|u~5r_8CczhnR#6hx9UuOnm&ywwL
z)*=9|_$M11Q^@X^wB?#v;r9aDoc@2LMWX+i7QKtkP?PxZdNCFR5)9dV7J#VIfzaK{
z-H|@gS;4u=X3Zaw92%E@BGf4lRq87+D;wWB&8u*?;&6E}L$GesIK!O;jNi5ck)DI_j115-
zbwLt&+%I00`Ra)^evNDtp~sr9o)=*p?aGVvSb(LiSEZI)u^&&M8jJAmVXh`ccVrsg
zqmx~8m82}#u3a|3R@W4{`6cZ4@$t)tpYJwGEx>L!n^IU;=M*fumE#djo3Y)UkN=xm
z?h;Gdbj@)`{vi2xS&cdi3}E^C2k3Vs)%rI*ywB&oDZBs3uKr&K*wkyM7BGaT4||lU
zJ4wVx)%10A#&@i2}WYLNH@&qh-vALM%r|bLo<_qC5;zoOS7xwh4-l#S))nqIl4p00;*dNHdD%vXfW<
zjwVAIQhKvdF#6EIUo72a#?IwArxs?cJDU9i+9KGwW`p4^A12=+h)>ehC-LNBJv^Kc
zP>Of#i>g63QwSb6-LZf+5OgjbEnT$j15_U6@-Z0?N1@nG@
zxW(Dm_nq-8%eejLtM`R+>Suw+=#a(Lj8sHok1VjACD6FEa~)hp)2LOR+X6O;
z(~1~dX}sBiCxWPJSUB_HcOx;wy
z@%kzG6mD@*Uv)M%hZ{Vs`#S;;?#c*y(2j@lfRT2(CsCi!@VP#ygRUzIwIza9@j{Zr
zkfZgd|2PPH3}K1Typ15$tJ;z5AY-V^uOKk09K{3WI^`2JiEl>|Rk=8>OlVn8{Cv=i
zE5yT;eLOe{2Uj~Wr{Fu`Vjf#TOx%gpo2z2
z@rA0wJ~P{92O#k)&wqI=@fr@7Dl>^z$p&oJ&!iG-4J21Xd+H!27s>3%=1_0z=~9`n
zFiF?2m7!Iq;VqZ-(1i9A2s{qc%w|{aZhMBg!vP-YXyeKJmA^X!sW|(&M)CE!R$1z*
zZEEWJmSr6Y)*ZKoy4N9LuPKoX@nsg6;upTfJ*_j9~?f5F^NYU*q%y-`S_F5AT(2
zSVK+BCT#M#;Gtp47COc~ZMq_68&VNEdx?f0hzKRe#(kCa%!&iUL#j)0eMmKS~$?UuDvDOFD|2Q1?UgMsMid
sg`CV5BktBj=BfmzkinLL0~`p(0;wZp(^3aKl?OU~;=EB1F!~jy#QqoFFcMm0SeVe+wK6gw!
z6CR6^gv@h1{Fm}h-^2a!pZ$ieGYD>_Vlyo$3<;Xo-E$|KC(}otp}nZBek1bJ5$Wkk
z!oLo-oW&Q$R>t$4l{GIX@}2D-O`)5wHmMyq`p6v5cGNvy<;uyU=j>Y|Ug^v48KSQf
z1>6r(FLw${JJ2`2XcdFVE94RyRa@tEgP&qe04bfvlBVR5z9yXI2dLaXQ
zdV3!tM|r)_TjJ>Q)9|4+Bs0SI?raLlK))<*aQX|f@&~&=a#$XQvS78~jn))F{l;C=
zfg!pTWP3JG5o7)}oCdyLV^tn;WKrU#?e4Nv$jbmR+mEnq#v8aeT2HUR<&~Y=S3Qfv
z-%_v}ICv~dv(ff?tH&@3k-^v>!mNniQ&!IPCE{cr6Aw-#c2`2vXv>N`-Kzat$0>*o
zpP~^R+l2GWJ5qz10RkUKSE3#<{IOd@n&X7T%w?P*^tsNt#*KA~#4{{mIbQ7w9${wFjmyhv`&~S7N-s(`SN!WdG3!
zdZ-GRX@I{{+J_nh_v~z#l53qhl^g!2(Q<{&E_+iG5mWn~cEkXUD-U-?dcuwbw=})=f3zSk@`EMaB@);*&WyADu
z(Y|0x!yvmUbb5cLg$lr|#;3=9S82d;UYP4!qrh}pi^z~N%WO2hHcwNt)8oB6A=DN~
zdv1cZ0njkp3hMC#A_I&{4in$#{!ZOsJnR8-fa1WnNx)3u{A8f9sbCVOphAA7VhBo%
z{aX;b$2vkOlXi!hP0?QfsUKz>I#1!A_0y%vs2Pr!;U&yE#fKhzLu9yqtaltdh4Y)P
zxFm$%RRSGSt2P`K00Kn*+x%Sn)LQGmC!bc@3!qR8qz22j_F<~f4=U^^%ix7gOEZO
zY6c*nJnK|v2cW@iqXcwobJYm{zmOpTbd8O2j#jYM4EiWaoL9nyS)ErRoQ?T!!I;hk
z>Ns-Z!4$_Uc05ERjLx*zU-yA|IiW~JY@ww-ZuIEnSzj#LUF-xe-!e5ev
zx(Z@T9r|AG%Lj;zt)VHQ26Rhu;j}uEhwn$yEb~Z&c4tsAG{j;QR5kKC%f9Rek`C
z!GD(xeC5DTg&Pu6Pvrgf+#aX(emtS3BDyFs?5+TjvH$4)9meiHByIogo;jX+N)hcP
zMXqe#J1s7Uy__oMtU*A_tpmFnf|Q_z-4HCZO;Pu;DY>kg$ljp>DnY`LYZBN-L1B;fqI}p1*
z2NBBD6q=B|^y{S2&pM`0(D67f;k>O~?yUv*m$=p5J>|1$YjB`F)y(7eyo7Mrzyl0YNY1rKWIw*&CaVc#m4S
zYZtq__bS=d*WP{i;TzjND96&NrlI%q621CIFOAP;Z46x~*soqo^ovQvxrUunGI-tH
zyRPzJ?2f$XJW2Py+0QOsVpd5bw-s`$L8%Kn_4~F+N>#hmU!sD&u|!VThw1X~bhCNX
z(((gsrmLPyXpTlNB~xEJZ?dcPVy7v1o@eP^OLoN3e=;8+TG3{g+RvESJ@(o?r^TUl4l+_q-iF9P^FloHd81J@_?<
z-K96p+7Rsp7K}`Jt*($5HtbiDg3{K^C0&tGNDMq;X|d$rr}GXvhzc!@B-SQ|plvX&
zX6nM#wAi{`Hrz3LKL~{+Wv;FwrWbsYP_q7TQMYEFa`a0SC9eUdwPSrwIh)W5a4<^e
zqSkn0=eI?c?l#=8PFilVVKY$krgAvXcT>0q9YM#>&5~|Lg-b+N(Z!YFi>j}4L403s
z+>8>_6(b#V94>q4rU81urtcM5-;BDp!n5Tl(y8P#_1O))xC;BTtK!pdckK(Q*9i(F
ziOn6t>k<5jw#n-~Ol!Qbkk4pw;Fg#|rO*1#9`-KL6H{j9^mo!ViMeGD-o$MC{u(Hr
zc*|!$Lyj5#U?^%p@I=i?a_bN_^@%Ibse<;ZELD7KeO>FEr8HPr7JHfC$~3#K#lg`L
zlJ3=vN~6pwKaqmKq;T=ytp?kzJc`nZpaR){Ek=o=)MN~+EC((tK>`oR+0SGy&T@;f
zYzhEGw>L4^hqLHx;3(zgFQx91n=DeK)Wsr}%wM6x)qQ3t_SxrZtSw9RnkFe0p13}-
zKsb#=vAJBwVxJxG4^!+f-r>l9eA*30>fKFvHiHeSU$B1F)Cb2u2f
z_{lkozP@NFcIzQp2FPB=oIpe&*rsj#gFE3gtyjMaD+O_EhfBwP=5wYewQi%_4rbTF
z?CQ-8#$&2W$k+^KDfYt>IV>%sQUp3F^l?0teaj~^*z#mjBAdbKV%8;0WG?q8FWQ|$
zJzijmO3rTljp>u0i%Hm%Lk
z9Ju!g`-dtuXo*NnAz~xLdxT@K2yhtG;!TIFs~1@l<8XG1u!7-5v5!TTZ=Sfg
zi-+bp+U+R+%R&%FPUTigB+z#EL3%(PeR@W|8oTskHaBkj##$q8!zxb0=JF4@3*xc;7IVsr!d^!|6AsE$WG^#sWalDv8j$0L
zSzn61kRopL_t@c$Zr9WU6s-En3KZILFF!3(z=dn=r$*_-KY!}&EX6`2-OKEpFt+qUy#h9d5}
zD8B?dHgHhTL5t3y5Jr*t?fnuCk|(UaM!XA*%`nn$eO8hob~BD#)0w@)CBpREu4`|N
z==$XAO8pwyc@p<(tV+aw1~x;nFuK8Fff?wZ=Y5x%O}>W)?E5iUU6+}2s}XKbT`DUo
zzS1!A5M9|!Jb7U4_(vV^9w`fI{ahP5=Dc&305ig1lc6x`4c&^gZ`uz#Zx)4ARRM8Kn=%D`=IwtbaGZq%rC&$J
zvUP>iVnnq!<6JGm`{P6Zh361cd+3&XLldUZN2>5{*uic@
ziZ$Y+#?*l*=II8Hu!Qq2LTaxO!dgJij$rZ$oO2tPnm?9%v+6OL{Ypo>V{B9G@^=(x
z`jnZuwZ~$)Z3<_Dz59L%Mwfnoq_g<1hGxdDWhw=oH?J~W@=vV~)Qc`pM
zTaj-KVu5~wDSE_I+XajryxR3t)BVjPQ!hs{mG;gTr&V4*i-*vEB<=tD@_$T!2WR!+_D~zvJ(i$04Gh=ENssVZwj>
z(&!Gfeo0%!w04uhZb<%{(e=)yH-ge*tviyiq1HNBjLVT{vj52R1=YV(XSlLy1qgf@
zPEPEBeMHb1rfM{39#AZQsgM}WZp(Fg}0m)WSa
zYV~_E)lxhCa@Vo0y10jjejk~xyFlFplZ-PV_4YO${|wvM4209l9dKSn^PzhO#O
zaycS8yjw$|3=>gzhb04U_j9)0J0m_wu5?ErjXZ+di0Aj2&A;OcGD({$RZ-H@h
zAlb6%a9!VdeYg#fVXmBxcO*SyMf(!8D8Qjz)stDzVQstY(aSF~^n*`*Aeme0gQ3R)
zJf`k-kL_{CedEQ{nFJcK76$``oAvT6;}QQWLWEeE$@`ME!KnumQ3a40B^J-Gi)sVL)9cT`}HW%ndIxjvSb
zN%t1*-n2FC;K>&((|=^tg~Jh&jqM;tB`7;yH1|QRR9((%-rlGO(DoAU)%wq>MDOqc
z7>2KkYo%j?>G1L06u9OeJ%1l!K=1t$W6IRyxU*{oHcJ)SE{J)-mquKNq_3y%uN$oz
zVB+#<9!%;2`!lZce8NzK9(!H+mU-{pVI@h_Rm*Vj!I
zbJPQnPZVhLZX2xp3G8e|-C@0Mn*9^xI+Ho8z==H)Cld2UAqTh2pM$OfftWE*e@NOD
z@gQ@BF9bRKG$3HndbF;bF*@@&GaV!(dNv*_>0(OT6+ug?7HpfsA39}NTIzk?%bZar
z!5h!FCA3g$vB)L?YE@{ibi5N%ZPKZ3747ZLGV9Z7h=(U-S=L7UuT@K&@Vd+@7*{@%K1m9V^2v91d;J_5(H!&
zhtQtj>t3YnAX|C=q5Bg!5v)|>3Q)QB%?h9O^ZTfM;Mr?;vDE6i0R88?u
zy7PwKC2Nfm0+z9eh{O5j!GgT(&*GD%n*1S~DYU{u35GB*@+Smy1{cv%*l>F}QteEcB
zv;AlL&ws5d-wZUPt=)Tn`JHJuWgH~n54JdD(2CplfQH+u18+COxx^9PGup%!Q50VE
z*XlxQ2?39O$8KGp?S^t^$=!dkcn_t1c!pSD9S)jfo)Ed1EiC<3ZXz4@GypdcJQ;qu
z9^2Xomj9jKB<#9p+2vovgMsMbq8ED0qKlf$
zXDcEOU_Wz_(=`e
z>3xQIB}gS?k6V!=a`e^f1e`)gY>%J;{3>TV6QI{IG59~~^FbAw9#{mP7iqQZSA^6&
z9r#ZOKj5-MfAQof;HJx=dkCJ~iJ`QXpJt8fl<$p6EbKRQ?;_f8>8timX3R6HYf{Sx
z3v6a8fKR|HW$e4dDDTW0$O6`sLIT^Xaa$L=9m{m?{jz^I2D}=-?1i^xfK(%yK;HSR
zU?O}RE3yoT#ym#zR%_-^Y(6KuhPvof=Lm>Md*zBn669dR&eY7*3}fUHReXTxOy%Uc
zDm&V7K2rYmK#Fu?k@ocq;~~Las+;U5%W@HE74B0U*5BC?An-e}nN6nBO7C~x#HA!2
zQH*qNVdk8~aANr=#^o5VQlmD1Njh;mU}|4H3pR3e`D_aG`qx77ZlfO$5J=~9xzg%g
z^DY0jPEfNJSnmB&FO|IJQ|~p}~mmn8+ix
z{tgh{axW@UuMS8O2X~Ur*r~j6JH(&;6TG+K-FN_mj9;6GLnFV7!ASb$n&IAL^P#yV
z-xCCr&nN%!>fwY;js!HIWoeWI)d1-LvKewnhCVYyKeuZ@-vZe?XrXu0>tVo$|)V(K5T%cKl6O$J={h8MA@
z0W|9^J86u5co2_sb_KBGZ?8v8nh9Ivt$smX!D~>TJAVr-aQ=m1u{x^*{ZEBOVaQJQ
z23df4_+3V8({X*2*e%167)<=rFaPSEr;@B!G=K
zQmr?OBanp#oDphXD^t9sanQ0-0xmSO?`CbW33Rc}yMsKt=3iX|wEq5?=2fCSmJ3XV
zave9Mp??M7;vV#xhb%B&wK*%!eiza3M0U1%PgKe`+ehYlzxg*hIk0U7FRwdo##n@(
z%_of+pL7voUECPnu2OuKq^AAdE)07>Xd%-c;L&|2_vL?73A%tYeejIA3Hrh+ocfAw
zCUTvZ28ds0o}pH$F4N2ywKMqwW?ZM-Y8r2l?Tkgc+s6nfXA5Th8Sq}=tkvPc@-*lm
zl7^1JApiBNPuPU%z9<|hX-Q;{(lOx&lO-W(+G)CbWv;8+4~qxHwmnR&%Fla9~QeoK@Kq+gKpYhO^utn1?(x=
zPt~i@w7I5Qm)m6P+@{z6&U=Wj_3g}$^0m&Mk+qH@!IRGV)RWN*8Hl15$r{@0B8}{M
zl4P+rG`1ICw9YqUd!(uHrPfcV`EnQ0rUXc5c)&C%xj~qpM3zsMuM20@1cY&-qi+ji
zjqVdnGf%jcK6J_T)CXibL=YL~1T*7Zq@v{I1|jFitH9;o%lKxp50(KUWjXIJIDuT-
zCn{f9v6u?mzUFxKbah^WX8NpYTo*aA`!q6QJV$#YkH^jBsW`7zLZ;#)FLITV@1=vZ
zK3PV)>F0bF*96kI3a4GCT15>fK#iFeq@)PBl)`D4A*(`wc%2f#D3u%Ib*pu&|LpR9
zr?q~i9KQM3HhUDLILnGZc$8k-FBrVGnfypVEjH?MNx>O{eX^-jZsUVG$p}02K7>34
z3=#WYN~so@%8wM7J>a(KG5W6)CtAjcp`+Wc=4yBhEyXXyC&b4WO~c1!u?+nwU-v{)
zdZ(v3!UA5BrXg&bp=MsHPde^XDU<7Ubqu_QJ{&gXmd0j%7slR??_QOdH~>(t^AuQU
zp9>P;I1e{E4eRJqt&MLQDNqj?kd2~w82x5hP5=;WG-3s{s$qQy=?Udua1}N(UGn+j
zD>rzwQ59HVmnP&V6m4KI8j=l3{}f;->~Zy&-3ML=Fb3RvrRaMUKyTqk4NWp<5n(4EN--}^<_4QDiJ?;~zjukImj?*k
z;`I3OnSqr|k}Vs!&Xn%DhPH>dxu|SfoA-m*RjOvb^VeXBB0C}^sIIym@U}ch_=1fnF5A*!tMcOTs_Ms3O
z=6yqG*@9%yZUDzD(;0|EWp>;cAs#HEJCDOC1>%17G0(EAu|zm*bqoV9lZ7D(@#^;_
zA};wp+RGU)Uz0I!+gj5a5nE8rsnQSXo&uKg#kkJ7l`aSq_@`t|3@VcVxVEAWGyo#H@Ro
z#4&Z6T=s*l>6g;rE8AI_e@}8GX_(U&b1#6V!t1rww8Sk!#TOr_128}x1&fF1ys-*V
z&nP~6%!o(fxwxWlF)c~s^XY}z9B+i_YrhWBt`whhGyU0Ox0q
zbMI=-WK*$j&AkOF16IwVssm(63i=Lmac{(k>})J2L+8+L#)Z+fc)YV9zEE!@-t2I$
zQaD7+MeNQcNya4h%Y@5B!9@D@;bJ}OR}`iL_9xVnws^-}Klk1gPJuI9th*yZ1LN9`
zH(1%8>{e7tH3t?|Yh#|DrlU!X=h0wmlohw$pC!58oh&|)_MMv?E`BsBJ6WVn8Y293
zH)tUHV4kM-B_iT^gnEX4Wt)1TMqu`P*)6;6K65_%dCE*f%YbnZ9H7l1XQR=)yIJSx
z{X3$l*)D)Jp_D|>+#g}TP@%4vB(&g4wL4Wx+}m2|HmI}fy?45Y_#}CIa;K6aHrAjb
zc(TPw(zA@o*+|0kUC*7AjSMR2dwVNIHv0`FM50Tfb>j9uj)sf3nI_%Jk{c0pf};&^
z(R6jt+S@fh7w_3T;e=l7q!ABi+VtB%~DzwN81y>Ai>NBGz4ymsH9&nCVV`{>@
z-_N)lP7W4iyf@5QbMbj6uMkPIokGE;Wii37m$4=d_gPS;Z&esws${KFiS^D+iyS-r
zaLs?Y)HqkK;+ARN;&VCN_Ve8D+!A$beLT}RCyrj(-tBsF&72p4wYdrstF?J&mGih#@1sDc?3sj7n=3+8jk%xA3{n5`50{UENkKXCS!CQ7DO^
z+OKkHsXmQb_}SvCa`XdftQ>jtHUl*{ghpn`b=-P9C_3!tyhHGQ3Bd%gxHIMg*Az}e
z9;+GU^=YVb#$eEGFm>hbx@`-eN!I|$wH&eVn0a^mBjW3ck#16#Mc7rs?fxw!N8EXn
z%~7!zKlF}~Qy#tCyiEDqhROg24ppzwCvR9XK=8`y!7M_52)m~I1u#Y3w4jCW8LiAR=Dfe}uRAOLp0jJHaTuELNf5l#
z`as0vSK1Do2YfJ*mjOOnk?Xt*3=4zcKPK}y7G?UIwf`Y%tsKopxvidW(BCjs>TBUS
zfup3Obpf6lM4uw2{Da<8jsDOm)b94I)jVvLG&@nmq+I`6wn`e0=-00P(#dLz)9o47
zdq$QhS!$J2X2lWzqI=h3tDA2H9~r)n$;CJ>|1QW7$&<_+ZYJI+h5w-
z3q>(!eC?VmnEP2SljWVqu^L`ceDBKLCohHhIsk|8!3z4UYmn_p@thkz5GOimJS}Cd
z`wr*pu>EvZj!c$zKcBx}L=}6asQC6qC@Q$g|C6Xx0DH;NWSM+_w4c$Tm^WxCk{Z=`
zar+W8x|xPFnHIZ%7pud5Aj#W{UGaDGx@A9hgZH9`udE?)_Q8M#MQsW1?YEtR1c`7BjKV7pB22dYG9sEpJ1
zhzsRnP3zD+R*jlPS}|iaJm{w;jeUj&7WVCYGo8~DgDg&9DkfhamX}dz6YqTp`UOzl
zzm6#OR6y;${)L{p!M}Iu3)>@=bZh%rYaG8rPR}TZ4LN6!n+*(*cx+O`l;4W3xybk-bR~r_Dx_N&Y7KDzyd)R0(l~>M2oRVhacnOx`-zc
z+$LSP6ND)130sn%4@>AO*jgDD8Bvky!EXaWw@VqdP;A(8+w-yUem-iduWN>Vcx43F
zV8@3`xWlr2Tg|%-rF!`vTY2SkI4!>l^ZbG~-{PuyZ3Y%35L9_%CIP(qn#Fp^{VTdk
z5Nll%jCyh>AL}2W=-kp}y|`W3lQoLl<9mI@LLP-lArm%qJD0+A;G}59Y4vMeetU8i
zeY8)WViLJa)Rt)m=Pvz0&vdX1Q#>kRFa@+9;H@YL(Q2Bk=2j4BIHt4RsZdG89>Hbu
z-Kl?{K#;54lyF}q0iLOSrnxYd=L_J9J9IW(S?x79tlCydAs5-K*q)o^?=3ud=WCP)
z|I<$j-$oRg2+@k(RO8|&k^pL0&}`CirAPjqE#3n?8Uu+|_iEv8$vcN$#PL<+`D)iQ
zGc%dL>&^%+9{FxiXi0T~S#fU5`Jt4Fdc=r7}_XzEYn$
zeejswj6JU4wN~6K-Cvn9CX)j*ZKo>fc;Pc?V2#qTsY<-uQSXM(|`N@qeRl;ksNC{3T5k0R&mt|)Wd
zZgFhALbc*t>nm{#sswD2Jk>0E93_SCB*BPQheAW1sgz_Su~cXyOLnrdi;A(?Qil-vrBqJEsl-^M
z#ReBG%tyAzuV@{2q|40ZFc1egQ{2JfrNnrJ5^k6*257+7z)`nzfRzs)p$rumduD;pU%Yta!&SRidWAMSk>mOC@koY*Eyd7@Jzetst*i?
zYVDUetR{UHu$bL0TLZd_pitDutATvDav$?H#aTvTD*7ptiN|Op5GTZ-34byU1VAL
z&ehlu4rd55g0Y6`Du#Bay4dW%oO+qzWn;Jup1*cj6A1Q9$VE&6;DzB$suyJ$#dtU*
zeDlSRw-#Q;OrXVmq%@Oy3>=543^w(~F3OOGpL+Qr)PO2NejQd6g4V#jqx
ze~SBj*MbN$F(iYj?YS4rU;(ZmSJn*Us5ru;WqYj_0}=N$6b<#Av$-;E7tF5jr9m!C
z%N9g3S*pvNUZ^&>>UfaqA?a%JvCsG$^{mLJ)e+`<1`P#X7{9;{NWB4j{=OJW6?p}S
zUKr)PnvOLd+%dWayNTbdDv(EbIB(&Om=kDb)j+Ou=zRN*r8Pb7K|MDEtxvb$4|07m
z(AWbBw|+FESqAy=C&b#7!Af8OIT}n>cmW78@F-5VzKY|}lr){$25qZ>o4?7J_(h6u8{@8j)0c|6)qA)ur@~6A7|KQk5U78kt_5&=}QfXCB%6%rI=II4^c>DwfAb-
zAPAscHW(uNVXL5p1Cr+Y*AY0%XqvSeS)3KTnQRn(GY6S8FLjsEOej{MQZX62+fP<}
zS;W-qzCg2okUkzb6yRQKJM(CDrP8roR^>El`uFil>d@nBf@{k8{0n~j`SsA|p#>3Z
z+Zvew^|mm+Yh6Bjq;y7Ta3B2^0pD_lWYXQ7@y|WkgX1IzzPir~*Capv*xw%O^LNwE
z)dU{3_$<7kHhm7Akg4_&u01@G_HFzUM#ai|)K!q?9X44)D_mSmWCz}&su7%RJ5-vo
zb=XgSa?tCiRJld)Uj+|~dj~Xo>$2bW^Gy`r
z%F}bY_Q!z1idG)tbf-yQ<*!$+zgk>Hz4313=QRMZmh^A6HZR+b_1F)di4C%&!S?yb
z=8s+>=4!dLPD?L(o3}X)KO^|{G7giQ2c2UBStTeIqaNImvfK@G$Iw*Ptz;BCbnoA0
z2z>UaK0^Jv`*o@biAKMNw~8kA;ZvBaSLgue1m+-H`IeBmCUU{1v4gb(;8fSe)oiB@Myr
z_L-XRfq(I=OBu{ntEyqw@6Xf4E|#TD5z2wj51!Cjgwq1w|K*gGku&RUU|)QOfB~I`hwKao
z4K2|d>Hr3kC?|r!W!avd_8!Iw8|eM@q8Vp4e$(rh8mvI$%zU{FA5cfyMTL4n+4j-q
z9C^=ULfVtatH^(V!@tYiV=yFZFm(LALKT?$EQgNbgn}b7q&ijHcX9T_yl2+U!X%oj6>>UP_`j2Yc;&
zCbo=S)0xIdS=+Ah)cLRgsnEvr)hDo4QWyeCv-39Xx2_$QvX7Z04AH;r$yH3I{J!yG5ob9FHS>v?eR27rfvW^jy3lw`L&L8m8#s-q%QSwFko}@p
zC3+Of|H`tx_gu;Bv3O!8wZJ2}E!3Y*?0n-qC1T~NWYuF{+el02f3;hpYZj1n6%rt|
zxiH48Y+6J!A9;tN#ddf3yZBXpQLG(x*sT!8q>GnG-4`8$w-%vJfcA8TEeqOVIy%0NeJfm<0A+J%}q
zo4LQ_SZ=UL^JAIW#uHE8!BcK>Ne9%Zmm8Hg_P--X
zbX@?-USRH}+?c|Dd*|YdHs*6cWG4C6cRa^1hd+L>djfpHmlsK2Ich_}s-yP6A^O|R
zUw{dN@(FB2#9`D~AK#^w##Exu(e(SC(NK^pb%(BggN~(FWo5-D1Ae=`36WT1+LW-G
zog=@y1l;*v6S+0xc0gSi1sh3wFk!@lJGH7_Zjl~+hHe}tA2Ua6gy98bTCR1i*0$Uglf$ms=}`u+-A955=P#WI;z<{QpVHK
zZH_>tTKk!2eevw9V%x~(E7_6@+6@+%(f*v>bX9yS_OuskKC+lnluDH9e|?A_Qw4^|
zQAa2Bf*o4vctXx?yJ^GixhGKW<>91)(mp#l8ws9*srsB|kuU^+x$gneMV*5L+%BW7
zH?rSnVN8nJb-c6dY9z|Xv=@i!X`yM+lsT)$wAUIPwfh$lyK