From e50142a3b913fcfa08825c7693a5b2ad2f259ce8 Mon Sep 17 00:00:00 2001
From: "kim.dev.6789"
Date: Wed, 14 Jan 2026 22:16:44 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A4=8D=E5=88=B6=E9=A1=B9=E7=9B=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.dockerignore | 28 +
.gitattributes | 1 +
.gitea/SECRETS_CONFIG.md | 255 +
.gitea/workflows/build.yml | 535 ++
.gitignore | 426 ++
.golangci.yml | 912 +++
CHANGELOG.md | 1 +
CHANGELOG/CHANGELOG-3.8.md | 70 +
CHANGELOG/README.md | 4 +
CODE_OF_CONDUCT.md | 128 +
CONTRIBUTING-zh_CN.md | 96 +
CONTRIBUTING.md | 94 +
Dockerfile | 49 +
LICENSE | 201 +
README.md | 140 +-
README_zh_CN.md | 139 +
assets/README.md | 32 +
assets/colors.md | 11 +
assets/demo/README.md | 14 +
assets/demo/efficient-meetings.png | Bin 0 -> 1442977 bytes
assets/demo/group-chat.png | Bin 0 -> 428165 bytes
assets/demo/hello-openim.png | Bin 0 -> 49844 bytes
.../demo/multi-terminal-synchronization.png | Bin 0 -> 1074824 bytes
assets/demo/multiple-message.png | Bin 0 -> 953198 bytes
assets/demo/special-function.png | Bin 0 -> 325259 bytes
assets/intive-slack.png | Bin 0 -> 21044 bytes
assets/logo-gif/LICENSE | 1 +
assets/logo-gif/openim-logo.gif | Bin 0 -> 2682640 bytes
assets/logo/LICENSE | 1 +
assets/logo/openim-logo-blue.png | Bin 0 -> 32557 bytes
assets/logo/openim-logo-cyan.png | Bin 0 -> 35907 bytes
assets/logo/openim-logo-gradient.png | Bin 0 -> 38678 bytes
assets/logo/openim-logo-green.png | Bin 0 -> 32597 bytes
assets/logo/openim-logo-orange.png | Bin 0 -> 37334 bytes
assets/logo/openim-logo-purple.png | Bin 0 -> 32931 bytes
assets/logo/openim-logo-red.png | Bin 0 -> 31948 bytes
assets/logo/openim-logo-yellow.png | Bin 0 -> 36659 bytes
assets/logo/openim-logo.png | Bin 0 -> 38208 bytes
assets/openim-logo-gradient.pdf | Bin 0 -> 10462 bytes
assets/openim-logo-gradient.svg | 1 +
assets/openim-logo-green.pdf | Bin 0 -> 10749 bytes
assets/openim-logo-green.svg | 1 +
bootstrap.bat | 31 +
bootstrap.sh | 23 +
build/README.md | 65 +
build/goreleaser.yaml | 431 ++
build/images/Dockerfile | 24 +
build/images/openim-api/Dockerfile | 42 +
build/images/openim-crontask/Dockerfile | 42 +
build/images/openim-msggateway/Dockerfile | 43 +
build/images/openim-msgtransfer/Dockerfile | 43 +
build/images/openim-push/Dockerfile | 43 +
build/images/openim-rpc-auth/Dockerfile | 42 +
.../images/openim-rpc-conversation/Dockerfile | 42 +
build/images/openim-rpc-friend/Dockerfile | 42 +
build/images/openim-rpc-group/Dockerfile | 42 +
build/images/openim-rpc-msg/Dockerfile | 64 +
build/images/openim-rpc-third/Dockerfile | 42 +
build/images/openim-rpc-user/Dockerfile | 40 +
.../images/openim-tools/component/Dockerfile | 108 +
cmd/main.go | 406 ++
cmd/openim-api/main.go | 28 +
cmd/openim-cmdutils/main.go | 66 +
cmd/openim-crontask/main.go | 26 +
cmd/openim-msggateway/main.go | 26 +
cmd/openim-msgtransfer/main.go | 26 +
cmd/openim-push/main.go | 26 +
cmd/openim-rpc/openim-rpc-auth/main.go | 26 +
.../openim-rpc-conversation/main.go | 26 +
cmd/openim-rpc/openim-rpc-friend/main.go | 26 +
cmd/openim-rpc/openim-rpc-group/main.go | 26 +
cmd/openim-rpc/openim-rpc-msg/main.go | 26 +
cmd/openim-rpc/openim-rpc-third/main.go | 26 +
cmd/openim-rpc/openim-rpc-user/main.go | 26 +
config/README.md | 87 +
config/README_zh_CN.md | 86 +
config/alertmanager.yml | 34 +
config/discovery.yml | 22 +
config/email.tmpl | 36 +
config/grafana-template/Demo.json | 5576 +++++++++++++++++
config/instance-down-rules.yml | 44 +
config/kafka.yml | 40 +
config/local-cache.yml | 34 +
config/log.yml | 14 +
config/minio.yml | 16 +
config/mongodb.yml | 51 +
config/notification.yml | 326 +
config/openim-api.yml | 33 +
config/openim-crontask.yml | 4 +
config/openim-msggateway.yml | 45 +
config/openim-msgtransfer.yml | 25 +
config/openim-push.yml | 64 +
config/openim-rpc-auth.yml | 39 +
config/openim-rpc-conversation.yml | 35 +
config/openim-rpc-friend.yml | 35 +
config/openim-rpc-group.yml | 38 +
config/openim-rpc-msg.yml | 39 +
config/openim-rpc-third.yml | 69 +
config/openim-rpc-user.yml | 35 +
config/prometheus.yml | 119 +
config/redis.yml | 16 +
config/share.yml | 20 +
config/webhooks.yml | 202 +
deployments/Readme.md | 188 +
deployments/deploy/clusterRole.yml | 24 +
deployments/deploy/ingress.yml | 25 +
deployments/deploy/kafka-secret.yml | 7 +
deployments/deploy/kafka-service.yml | 20 +
deployments/deploy/kafka-statefulset.yml | 71 +
deployments/deploy/minio-secret.yml | 8 +
deployments/deploy/minio-service.yml | 18 +
deployments/deploy/minio-statefulset.yml | 79 +
deployments/deploy/mongo-secret.yml | 8 +
deployments/deploy/mongo-service.yml | 13 +
deployments/deploy/mongo-statefulset.yml | 108 +
deployments/deploy/openim-api-deployment.yml | 59 +
deployments/deploy/openim-api-service.yml | 17 +
deployments/deploy/openim-config.yml | 1060 ++++
.../deploy/openim-crontask-deployment.yml | 31 +
.../deploy/openim-msggateway-deployment.yml | 48 +
.../deploy/openim-msggateway-service.yml | 21 +
.../deploy/openim-msgtransfer-deployment.yml | 60 +
.../deploy/openim-msgtransfer-service.yml | 13 +
deployments/deploy/openim-push-deployment.yml | 51 +
deployments/deploy/openim-push-service.yml | 17 +
.../deploy/openim-rpc-auth-deployment.yml | 39 +
.../deploy/openim-rpc-auth-service.yml | 17 +
.../openim-rpc-conversation-deployment.yml | 49 +
.../openim-rpc-conversation-service.yml | 17 +
.../deploy/openim-rpc-friend-deployment.yml | 49 +
.../deploy/openim-rpc-friend-service.yml | 17 +
.../deploy/openim-rpc-group-deployment.yml | 49 +
.../deploy/openim-rpc-group-service.yml | 17 +
.../deploy/openim-rpc-msg-deployment.yml | 63 +
deployments/deploy/openim-rpc-msg-service.yml | 17 +
.../deploy/openim-rpc-third-deployment.yml | 59 +
.../deploy/openim-rpc-third-service.yml | 17 +
.../deploy/openim-rpc-user-deployment.yml | 63 +
.../deploy/openim-rpc-user-service.yml | 17 +
deployments/deploy/redis-secret.yml | 7 +
deployments/deploy/redis-service.yml | 15 +
deployments/deploy/redis-statefulset.yml | 55 +
docker-compose.yml | 342 +
docs/.generated_docs | 77 +
docs/CODEOWNERS | 4 +
docs/K8s服务发现Bug最终修复方案.md | 925 +++
docs/README.md | 66 +
docs/SuperGroup使用限制分析.md | 183 +
docs/client-api.md | 1455 +++++
docs/contrib/README.md | 42 +
docs/contrib/api.md | 5 +
docs/contrib/bash-log.md | 49 +
docs/contrib/cicd-actions.md | 129 +
docs/contrib/code-conventions.md | 88 +
docs/contrib/commit.md | 9 +
docs/contrib/development.md | 72 +
docs/contrib/directory.md | 3 +
docs/contrib/environment.md | 537 ++
docs/contrib/error-code.md | 22 +
docs/contrib/git-workflow.md | 102 +
docs/contrib/gitcherry-pick.md | 176 +
docs/contrib/github-workflow.md | 283 +
docs/contrib/go-code.md | 1478 +++++
docs/contrib/go-code1.md | 1554 +++++
docs/contrib/go-doc.md | 50 +
docs/contrib/images.md | 116 +
docs/contrib/init-config.md | 74 +
docs/contrib/install-docker.md | 53 +
docs/contrib/install-openim-linux-system.md | 353 ++
docs/contrib/kafka.md | 162 +
docs/contrib/linux-development.md | 137 +
docs/contrib/local-actions.md | 14 +
docs/contrib/logging.md | 507 ++
.../contrib/mac-developer-deployment-guide.md | 258 +
docs/contrib/offline-deployment.md | 178 +
docs/contrib/prometheus-grafana.md | 326 +
docs/contrib/protoc-tools.md | 60 +
docs/contrib/release.md | 251 +
docs/contrib/test.md | 263 +
docs/contrib/util-go.md | 8 +
docs/contrib/util-makefile.md | 90 +
docs/contrib/util-scripts.md | 248 +
docs/contrib/version.md | 238 +
docs/contributing/CONTRIBUTING-JP.md | 33 +
docs/contributing/CONTRIBUTING-PL.md | 33 +
docs/images/architecture-layers.png | Bin 0 -> 293222 bytes
docs/images/architecture.jpg | Bin 0 -> 212410 bytes
docs/images/oepnim-design.png | Bin 0 -> 66183 bytes
docs/images/open-im-logo.png | Bin 0 -> 245627 bytes
docs/images/open-im-server.png | Bin 0 -> 109213 bytes
docs/images/wechat.jpg | Bin 0 -> 121026 bytes
docs/meeting-api.md | 415 ++
docs/meeting-client-api.md | 619 ++
docs/readme/README_cs.md | 183 +
docs/readme/README_da.md | 185 +
docs/readme/README_el.md | 183 +
docs/readme/README_es.md | 185 +
docs/readme/README_fa.md | 183 +
docs/readme/README_fr.md | 172 +
docs/readme/README_hu.md | 183 +
docs/readme/README_ja.md | 183 +
docs/readme/README_ko.md | 183 +
docs/readme/README_tr.md | 183 +
docs/readme/README_uk.md | 183 +
docs/readme/README_vi.md | 183 +
docs/redpacket-api.md | 565 ++
docs/redpacket-flow.md | 390 ++
docs/redpacket-implementation-plan.md | 208 +
docs/redpacket-message-structure.md | 289 +
docs/statistics-api.md | 267 +
docs/troubleshooting.md | 92 +
docs/webhook-config.md | 587 ++
docs/使用Ex字段区分群类型方案.md | 208 +
docs/统计接口调用example.md | 34 +
go.mod | 231 +
go.sum | 683 ++
install.sh | 555 ++
internal/api/auth.go | 45 +
internal/api/config_manager.go | 413 ++
internal/api/conversation.go | 82 +
internal/api/custom_validator.go | 34 +
internal/api/friend.go | 120 +
internal/api/group.go | 171 +
internal/api/init.go | 104 +
internal/api/jssdk/jssdk.go | 287 +
internal/api/jssdk/sort.go | 33 +
internal/api/jssdk/tools.go | 77 +
internal/api/meeting.go | 1371 ++++
internal/api/msg.go | 575 ++
internal/api/prometheus_discovery.go | 99 +
internal/api/ratelimit.go | 83 +
internal/api/redpacket.go | 1022 +++
internal/api/router.go | 493 ++
internal/api/statistics.go | 555 ++
internal/api/third.go | 175 +
internal/api/user.go | 260 +
internal/api/wallet.go | 523 ++
internal/msggateway/callback.go | 76 +
internal/msggateway/client.go | 476 ++
internal/msggateway/compressor.go | 113 +
internal/msggateway/compressor_test.go | 139 +
internal/msggateway/constant.go | 72 +
internal/msggateway/context.go | 216 +
internal/msggateway/encoder.go | 74 +
internal/msggateway/http_error.go | 25 +
internal/msggateway/hub_server.go | 264 +
internal/msggateway/init.go | 117 +
internal/msggateway/long_conn.go | 179 +
internal/msggateway/message_handler.go | 282 +
internal/msggateway/online.go | 131 +
internal/msggateway/options.go | 63 +
internal/msggateway/subscription.go | 167 +
internal/msggateway/user_map.go | 185 +
internal/msggateway/ws_server.go | 568 ++
internal/msgtransfer/callback.go | 112 +
internal/msgtransfer/init.go | 188 +
.../msgtransfer/online_history_msg_handler.go | 410 ++
.../online_msg_to_mongo_handler.go | 78 +
internal/push/callback.go | 150 +
internal/push/offlinepush/dummy/push.go | 38 +
internal/push/offlinepush/fcm/push.go | 172 +
internal/push/offlinepush/getui/body.go | 219 +
internal/push/offlinepush/getui/push.go | 219 +
.../push/offlinepush/jpush/body/audience.go | 64 +
.../push/offlinepush/jpush/body/message.go | 41 +
.../offlinepush/jpush/body/notification.go | 72 +
.../push/offlinepush/jpush/body/options.go | 23 +
.../push/offlinepush/jpush/body/platform.go | 99 +
.../push/offlinepush/jpush/body/pushobj.go | 43 +
internal/push/offlinepush/jpush/push.go | 107 +
internal/push/offlinepush/offlinepusher.go | 55 +
internal/push/offlinepush/options/options.go | 14 +
internal/push/offlinepush_handler.go | 105 +
internal/push/onlinepusher.go | 214 +
internal/push/push.go | 163 +
internal/push/push_handler.go | 615 ++
internal/rpc/auth/auth.go | 311 +
internal/rpc/conversation/callback.go | 117 +
internal/rpc/conversation/conversation.go | 865 +++
internal/rpc/conversation/db_map.go | 85 +
internal/rpc/conversation/notification.go | 75 +
internal/rpc/conversation/sync.go | 63 +
internal/rpc/group/cache.go | 46 +
internal/rpc/group/callback.go | 476 ++
internal/rpc/group/convert.go | 63 +
internal/rpc/group/db_map.go | 134 +
internal/rpc/group/fill.go | 25 +
internal/rpc/group/group.go | 2096 +++++++
internal/rpc/group/notification.go | 930 +++
internal/rpc/group/statistics.go | 47 +
internal/rpc/group/sync.go | 197 +
internal/rpc/incrversion/batch_option.go | 207 +
internal/rpc/incrversion/option.go | 153 +
internal/rpc/msg/as_read.go | 231 +
internal/rpc/msg/callback.go | 236 +
internal/rpc/msg/clear.go | 61 +
internal/rpc/msg/delete.go | 251 +
internal/rpc/msg/filter.go | 106 +
internal/rpc/msg/msg_status.go | 44 +
internal/rpc/msg/notification.go | 50 +
internal/rpc/msg/qrcode_decoder.go | 971 +++
internal/rpc/msg/qrcode_detect.go | 191 +
internal/rpc/msg/revoke.go | 134 +
internal/rpc/msg/send.go | 231 +
internal/rpc/msg/seq.go | 105 +
internal/rpc/msg/server.go | 218 +
internal/rpc/msg/statistics.go | 107 +
internal/rpc/msg/sync_msg.go | 658 ++
internal/rpc/msg/utils.go | 91 +
internal/rpc/msg/verify.go | 405 ++
internal/rpc/relation/black.go | 165 +
internal/rpc/relation/callback.go | 169 +
internal/rpc/relation/friend.go | 597 ++
internal/rpc/relation/notification.go | 303 +
internal/rpc/relation/sync.go | 108 +
internal/rpc/third/log.go | 233 +
internal/rpc/third/r2.go | 446 ++
internal/rpc/third/s3.go | 352 ++
internal/rpc/third/third.go | 175 +
internal/rpc/third/tool.go | 88 +
internal/rpc/user/callback.go | 127 +
internal/rpc/user/config.go | 71 +
internal/rpc/user/notification.go | 126 +
internal/rpc/user/online.go | 104 +
internal/rpc/user/statistics.go | 43 +
internal/rpc/user/user.go | 730 +++
internal/tools/cron/clear_msg.go | 851 +++
internal/tools/cron/cron_task.go | 307 +
internal/tools/cron/cron_test.go | 64 +
internal/tools/cron/dist_look.go | 86 +
internal/tools/cron/meeting.go | 152 +
internal/tools/cron/msg.go | 37 +
internal/tools/cron/s3.go | 80 +
magefile.go | 105 +
magefile_unix.go | 21 +
magefile_windows.go | 8 +
package-lock.json | 6 +
pkg/apistruct/config_manager.go | 28 +
pkg/apistruct/doc.go | 15 +
pkg/apistruct/manage.go | 584 ++
pkg/apistruct/msg.go | 186 +
pkg/apistruct/public.go | 20 +
pkg/apistruct/statistics.go | 124 +
pkg/authverify/doc.go | 15 +
pkg/authverify/token.go | 120 +
pkg/callbackstruct/common.go | 93 +
pkg/callbackstruct/constant.go | 70 +
pkg/callbackstruct/conversation.go | 91 +
pkg/callbackstruct/doc.go | 15 +
pkg/callbackstruct/friend.go | 139 +
pkg/callbackstruct/group.go | 290 +
pkg/callbackstruct/message.go | 115 +
pkg/callbackstruct/msg_gateway.go | 46 +
pkg/callbackstruct/push.go | 53 +
pkg/callbackstruct/revoke.go | 26 +
pkg/callbackstruct/user.go | 102 +
pkg/common/cmd/api.go | 97 +
pkg/common/cmd/auth.go | 73 +
pkg/common/cmd/conversation.go | 75 +
pkg/common/cmd/cron_task.go | 75 +
pkg/common/cmd/doc.go | 15 +
pkg/common/cmd/friend.go | 75 +
pkg/common/cmd/group.go | 76 +
pkg/common/cmd/msg.go | 77 +
pkg/common/cmd/msg_gateway.go | 105 +
pkg/common/cmd/msg_gateway_test.go | 69 +
pkg/common/cmd/msg_transfer.go | 78 +
pkg/common/cmd/msg_utils.go | 171 +
pkg/common/cmd/push.go | 80 +
pkg/common/cmd/root.go | 251 +
pkg/common/cmd/third.go | 75 +
pkg/common/cmd/user.go | 77 +
pkg/common/config/config.go | 979 +++
pkg/common/config/constant.go | 47 +
pkg/common/config/doc.go | 15 +
pkg/common/config/env.go | 30 +
pkg/common/config/global.go | 11 +
pkg/common/config/load_config.go | 44 +
pkg/common/config/load_config_test.go | 93 +
pkg/common/config/parse.go | 107 +
pkg/common/convert/auth.go | 25 +
pkg/common/convert/black.go | 56 +
pkg/common/convert/conversation.go | 61 +
pkg/common/convert/doc.go | 15 +
pkg/common/convert/friend.go | 171 +
pkg/common/convert/group.go | 174 +
pkg/common/convert/msg.go | 98 +
pkg/common/convert/user.go | 109 +
pkg/common/convert/user_test.go | 87 +
.../discovery/direct/direct_resolver.go | 96 +
pkg/common/discovery/direct/directconn.go | 174 +
pkg/common/discovery/direct/doc.go | 15 +
pkg/common/discovery/discoveryregister.go | 55 +
.../discovery/discoveryregister_test.go | 60 +
pkg/common/discovery/doc.go | 15 +
pkg/common/discovery/etcd/config_manager.go | 106 +
pkg/common/discovery/etcd/const.go | 9 +
pkg/common/discovery/kubernetes/doc.go | 15 +
pkg/common/discovery/kubernetes/kubernetes.go | 640 ++
pkg/common/ginprometheus/doc.go | 15 +
pkg/common/ginprometheus/ginprometheus.go | 444 ++
pkg/common/prommetrics/api.go | 48 +
pkg/common/prommetrics/grpc_auth.go | 30 +
pkg/common/prommetrics/grpc_msg.go | 47 +
pkg/common/prommetrics/grpc_msggateway.go | 30 +
pkg/common/prommetrics/grpc_push.go | 37 +
pkg/common/prommetrics/grpc_user.go | 14 +
pkg/common/prommetrics/prommetrics.go | 117 +
pkg/common/prommetrics/prommetrics_test.go | 77 +
pkg/common/prommetrics/rpc.go | 74 +
pkg/common/prommetrics/transfer.go | 68 +
pkg/common/servererrs/code.go | 104 +
pkg/common/servererrs/doc.go | 1 +
pkg/common/servererrs/predefine.go | 77 +
pkg/common/servererrs/relation.go | 58 +
pkg/common/startrpc/circuitbreaker.go | 107 +
pkg/common/startrpc/mw.go | 15 +
pkg/common/startrpc/ratelimit.go | 70 +
pkg/common/startrpc/start.go | 321 +
pkg/common/startrpc/tools.go | 47 +
pkg/common/storage/cache/batch_handler.go | 17 +
pkg/common/storage/cache/black.go | 27 +
pkg/common/storage/cache/client_config.go | 8 +
pkg/common/storage/cache/conversation.go | 65 +
pkg/common/storage/cache/doc.go | 15 +
pkg/common/storage/cache/friend.go | 48 +
pkg/common/storage/cache/group.go | 70 +
pkg/common/storage/cache/mcache/minio.go | 50 +
pkg/common/storage/cache/mcache/msg_cache.go | 132 +
pkg/common/storage/cache/mcache/online.go | 82 +
.../storage/cache/mcache/seq_conversation.go | 79 +
pkg/common/storage/cache/mcache/third.go | 98 +
pkg/common/storage/cache/mcache/token.go | 166 +
pkg/common/storage/cache/mcache/tools.go | 63 +
pkg/common/storage/cache/msg.go | 30 +
pkg/common/storage/cache/online.go | 9 +
pkg/common/storage/cache/redis/batch.go | 135 +
.../storage/cache/redis/batch_handler.go | 149 +
pkg/common/storage/cache/redis/batch_test.go | 56 +
pkg/common/storage/cache/redis/black.go | 65 +
.../storage/cache/redis/client_config.go | 69 +
.../storage/cache/redis/conversation.go | 276 +
pkg/common/storage/cache/redis/friend.go | 167 +
pkg/common/storage/cache/redis/group.go | 385 ++
pkg/common/storage/cache/redis/lua_script.go | 127 +
.../storage/cache/redis/lua_script_test.go | 75 +
pkg/common/storage/cache/redis/minio.go | 59 +
pkg/common/storage/cache/redis/msg.go | 94 +
pkg/common/storage/cache/redis/online.go | 161 +
.../storage/cache/redis/online_count.go | 149 +
pkg/common/storage/cache/redis/online_test.go | 52 +
.../cache/redis/redis_shard_manager.go | 211 +
pkg/common/storage/cache/redis/s3.go | 95 +
.../storage/cache/redis/seq_conversation.go | 521 ++
.../cache/redis/seq_conversation_test.go | 144 +
pkg/common/storage/cache/redis/seq_user.go | 184 +
.../storage/cache/redis/seq_user_test.go | 112 +
pkg/common/storage/cache/redis/third.go | 90 +
pkg/common/storage/cache/redis/token.go | 248 +
pkg/common/storage/cache/redis/user.go | 107 +
pkg/common/storage/cache/s3.go | 52 +
pkg/common/storage/cache/seq_conversation.go | 19 +
pkg/common/storage/cache/seq_user.go | 16 +
pkg/common/storage/cache/third.go | 18 +
pkg/common/storage/cache/token.go | 19 +
pkg/common/storage/cache/user.go | 33 +
pkg/common/storage/common/types.go | 26 +
pkg/common/storage/controller/auth.go | 253 +
pkg/common/storage/controller/black.go | 101 +
.../storage/controller/client_config.go | 58 +
pkg/common/storage/controller/conversation.go | 451 ++
pkg/common/storage/controller/doc.go | 15 +
pkg/common/storage/controller/friend.go | 406 ++
pkg/common/storage/controller/group.go | 574 ++
pkg/common/storage/controller/msg.go | 865 +++
pkg/common/storage/controller/msg_transfer.go | 277 +
pkg/common/storage/controller/push.go | 58 +
pkg/common/storage/controller/s3.go | 136 +
pkg/common/storage/controller/third.go | 73 +
pkg/common/storage/controller/user.go | 263 +
pkg/common/storage/database/black.go | 114 +
pkg/common/storage/database/cache.go | 16 +
pkg/common/storage/database/client_config.go | 15 +
pkg/common/storage/database/conversation.go | 48 +
pkg/common/storage/database/doc.go | 15 +
pkg/common/storage/database/friend.go | 60 +
pkg/common/storage/database/friend_request.go | 42 +
pkg/common/storage/database/group.go | 40 +
pkg/common/storage/database/group_member.go | 48 +
pkg/common/storage/database/group_request.go | 33 +
pkg/common/storage/database/log.go | 30 +
pkg/common/storage/database/meeting.go | 52 +
.../storage/database/meeting_checkin.go | 41 +
pkg/common/storage/database/mgo/black.go | 106 +
pkg/common/storage/database/mgo/cache.go | 183 +
pkg/common/storage/database/mgo/cache_test.go | 133 +
.../storage/database/mgo/client_config.go | 99 +
.../storage/database/mgo/conversation.go | 325 +
pkg/common/storage/database/mgo/doc.go | 15 +
pkg/common/storage/database/mgo/friend.go | 271 +
.../storage/database/mgo/friend_request.go | 143 +
pkg/common/storage/database/mgo/group.go | 162 +
.../storage/database/mgo/group_member.go | 282 +
.../storage/database/mgo/group_request.go | 115 +
pkg/common/storage/database/mgo/helpers.go | 24 +
pkg/common/storage/database/mgo/log.go | 85 +
pkg/common/storage/database/mgo/meeting.go | 183 +
.../storage/database/mgo/meeting_checkin.go | 110 +
pkg/common/storage/database/mgo/msg.go | 1501 +++++
pkg/common/storage/database/mgo/msg_test.go | 178 +
pkg/common/storage/database/mgo/object.go | 126 +
pkg/common/storage/database/mgo/redpacket.go | 234 +
.../storage/database/mgo/seq_conversation.go | 104 +
.../database/mgo/seq_conversation_test.go | 43 +
pkg/common/storage/database/mgo/seq_user.go | 127 +
.../storage/database/mgo/system_config.go | 99 +
pkg/common/storage/database/mgo/user.go | 699 +++
.../storage/database/mgo/version_log.go | 304 +
.../storage/database/mgo/version_test.go | 40 +
pkg/common/storage/database/mgo/wallet.go | 231 +
pkg/common/storage/database/msg.go | 48 +
pkg/common/storage/database/name.go | 29 +
pkg/common/storage/database/object.go | 34 +
pkg/common/storage/database/redpacket.go | 62 +
pkg/common/storage/database/seq.go | 16 +
pkg/common/storage/database/seq_user.go | 13 +
pkg/common/storage/database/system_config.go | 39 +
pkg/common/storage/database/user.go | 56 +
pkg/common/storage/database/version_log.go | 21 +
pkg/common/storage/database/wallet.go | 65 +
pkg/common/storage/model/application.go | 18 +
pkg/common/storage/model/black.go | 28 +
pkg/common/storage/model/cache.go | 9 +
pkg/common/storage/model/client_config.go | 7 +
pkg/common/storage/model/conversation.go | 40 +
pkg/common/storage/model/doc.go | 15 +
pkg/common/storage/model/friend.go | 33 +
pkg/common/storage/model/friend_request.go | 31 +
pkg/common/storage/model/group.go | 37 +
pkg/common/storage/model/group_member.go | 35 +
pkg/common/storage/model/group_request.go | 33 +
pkg/common/storage/model/log.go | 32 +
pkg/common/storage/model/meeting.go | 57 +
pkg/common/storage/model/meeting_checkin.go | 38 +
pkg/common/storage/model/msg.go | 158 +
pkg/common/storage/model/object.go | 31 +
pkg/common/storage/model/redpacket.go | 75 +
pkg/common/storage/model/seq.go | 7 +
pkg/common/storage/model/seq_user.go | 9 +
pkg/common/storage/model/subscribe.go | 30 +
pkg/common/storage/model/system_config.go | 48 +
pkg/common/storage/model/user.go | 55 +
pkg/common/storage/model/version_log.go | 74 +
pkg/common/storage/model/wallet.go | 56 +
pkg/common/storage/versionctx/rpc.go | 14 +
pkg/common/storage/versionctx/version.go | 49 +
pkg/common/webhook/condition.go | 14 +
pkg/common/webhook/config_manager.go | 433 ++
pkg/common/webhook/doc.go | 15 +
pkg/common/webhook/http_client.go | 191 +
pkg/common/webhook/http_client_test.go | 15 +
pkg/dbbuild/builder.go | 29 +
pkg/dbbuild/microservices.go | 26 +
pkg/dbbuild/standalone.go | 76 +
pkg/localcache/cache.go | 131 +
pkg/localcache/cache_test.go | 93 +
pkg/localcache/doc.go | 15 +
pkg/localcache/init.go | 88 +
pkg/localcache/link/doc.go | 15 +
pkg/localcache/link/link.go | 123 +
pkg/localcache/link/link_test.go | 34 +
pkg/localcache/lru/doc.go | 15 +
pkg/localcache/lru/lru.go | 37 +
pkg/localcache/lru/lru_expiration.go | 114 +
pkg/localcache/lru/lru_lazy.go | 190 +
pkg/localcache/lru/lru_lazy_test.go | 113 +
pkg/localcache/lru/lru_slot.go | 82 +
pkg/localcache/option.go | 136 +
pkg/localcache/tool.go | 23 +
pkg/mqbuild/builder.go | 60 +
pkg/msgprocessor/conversation.go | 149 +
pkg/msgprocessor/doc.go | 15 +
pkg/msgprocessor/options.go | 173 +
pkg/notification/common_user/common.go | 31 +
pkg/notification/grouphash/grouphash.go | 102 +
pkg/notification/msg.go | 272 +
pkg/rpccache/auth.go | 69 +
pkg/rpccache/common.go | 77 +
pkg/rpccache/conversation.go | 195 +
pkg/rpccache/doc.go | 15 +
pkg/rpccache/friend.go | 102 +
pkg/rpccache/group.go | 190 +
pkg/rpccache/online.go | 346 +
pkg/rpccache/subscriber.go | 44 +
pkg/rpccache/user.go | 130 +
pkg/rpcli/auth.go | 31 +
pkg/rpcli/conversation.go | 95 +
pkg/rpcli/group.go | 73 +
pkg/rpcli/msg.go | 92 +
pkg/rpcli/msggateway.go | 14 +
pkg/rpcli/push.go | 14 +
pkg/rpcli/relation.go | 24 +
pkg/rpcli/rtc.go | 14 +
pkg/rpcli/third.go | 14 +
pkg/rpcli/tool.go | 32 +
pkg/rpcli/user.go | 96 +
pkg/statistics/doc.go | 15 +
pkg/statistics/statistics.go | 68 +
pkg/tools/batcher/batcher.go | 277 +
pkg/tools/batcher/batcher_test.go | 66 +
pkg/util/conversationutil/conversationutil.go | 61 +
pkg/util/conversationutil/doc.go | 1 +
pkg/util/hashutil/id.go | 16 +
pkg/util/useronline/split.go | 27 +
scripts/template/LICENSE | 201 +
scripts/template/LICENSE_TEMPLATES | 13 +
scripts/template/boilerplate.txt | 3 +
scripts/template/footer.md.tmpl | 19 +
scripts/template/head.md.tmpl | 31 +
scripts/template/project_README.md | 41 +
start-config.yml | 18 +
test/e2e/README.md | 136 +
test/e2e/api/token/token.go | 149 +
test/e2e/api/user/curd.go | 71 +
test/e2e/api/user/user.go | 125 +
test/e2e/conformance/.keep | 1 +
test/e2e/e2e.go | 51 +
test/e2e/e2e_test.go | 37 +
test/e2e/framework/config/config.go | 84 +
test/e2e/framework/config/config_test.go | 89 +
test/e2e/framework/ginkgowrapper/.keep | 1 +
.../framework/ginkgowrapper/ginkgowrapper.go | 15 +
.../ginkgowrapper/ginkgowrapper_test.go | 15 +
test/e2e/framework/helpers/.keep | 1 +
test/e2e/framework/helpers/chat/chat.go | 167 +
test/e2e/page/chat_page.go | 15 +
test/e2e/page/login_page.go | 15 +
test/e2e/performance/.keep | 1 +
test/e2e/rpc/auth/.keep | 1 +
test/e2e/rpc/conversation/.keep | 1 +
test/e2e/rpc/friend/.keep | 1 +
test/e2e/rpc/group/.keep | 1 +
test/e2e/rpc/message/.keep | 1 +
test/e2e/scalability/.keep | 1 +
test/e2e/upgrade/.keep | 1 +
test/e2e/web/Readme.md | 2 +
test/jwt/main.go | 48 +
test/readme | 17 +
test/stress-test-v2/README.md | 19 +
test/stress-test-v2/main.go | 759 +++
test/stress-test/README.md | 19 +
test/stress-test/main.go | 458 ++
test/testdata/README.md | 64 +
test/testdata/db/messages.json | 0
test/testdata/db/users.json | 0
test/testdata/requests/login.json | 0
test/testdata/requests/register.json | 0
test/testdata/requests/send-message.json | 0
test/testdata/responses/login.json | 0
test/testdata/responses/register.json | 0
test/testdata/responses/sendMessage.json | 0
test/webhook/msgmodify/main.go | 65 +
tools/README.md | 25 +
tools/changelog/changelog.go | 198 +
tools/check-component/main.go | 194 +
tools/check-free-memory/main.go | 26 +
tools/imctl/.gitignore | 50 +
tools/imctl/README.md | 89 +
tools/imctl/main.go | 22 +
tools/infra/main.go | 52 +
tools/ncpu/README.md | 39 +
tools/ncpu/main.go | 32 +
tools/ncpu/main_test.go | 35 +
tools/s3/README.md | 12 +
tools/s3/internal/conversion.go | 203 +
tools/s3/main.go | 24 +
tools/seq/internal/seq.go | 347 +
tools/seq/main.go | 26 +
tools/url2im/main.go | 119 +
tools/url2im/pkg/api.go | 124 +
tools/url2im/pkg/buffer.go | 110 +
tools/url2im/pkg/config.go | 30 +
tools/url2im/pkg/http.go | 21 +
tools/url2im/pkg/manage.go | 400 ++
tools/url2im/pkg/md5.go | 43 +
tools/url2im/pkg/progress.go | 55 +
tools/versionchecker/main.go | 113 +
tools/yamlfmt/main.go | 72 +
tools/yamlfmt/main_test.go | 158 +
version/version | 1 +
version/version.go | 14 +
691 files changed, 97009 insertions(+), 1 deletion(-)
create mode 100644 .dockerignore
create mode 100644 .gitattributes
create mode 100644 .gitea/SECRETS_CONFIG.md
create mode 100644 .gitea/workflows/build.yml
create mode 100644 .gitignore
create mode 100644 .golangci.yml
create mode 120000 CHANGELOG.md
create mode 100644 CHANGELOG/CHANGELOG-3.8.md
create mode 100644 CHANGELOG/README.md
create mode 100644 CODE_OF_CONDUCT.md
create mode 100644 CONTRIBUTING-zh_CN.md
create mode 100644 CONTRIBUTING.md
create mode 100644 Dockerfile
create mode 100644 LICENSE
create mode 100644 README_zh_CN.md
create mode 100644 assets/README.md
create mode 100644 assets/colors.md
create mode 100644 assets/demo/README.md
create mode 100644 assets/demo/efficient-meetings.png
create mode 100644 assets/demo/group-chat.png
create mode 100644 assets/demo/hello-openim.png
create mode 100644 assets/demo/multi-terminal-synchronization.png
create mode 100644 assets/demo/multiple-message.png
create mode 100644 assets/demo/special-function.png
create mode 100644 assets/intive-slack.png
create mode 100644 assets/logo-gif/LICENSE
create mode 100644 assets/logo-gif/openim-logo.gif
create mode 100644 assets/logo/LICENSE
create mode 100644 assets/logo/openim-logo-blue.png
create mode 100644 assets/logo/openim-logo-cyan.png
create mode 100644 assets/logo/openim-logo-gradient.png
create mode 100644 assets/logo/openim-logo-green.png
create mode 100644 assets/logo/openim-logo-orange.png
create mode 100644 assets/logo/openim-logo-purple.png
create mode 100644 assets/logo/openim-logo-red.png
create mode 100644 assets/logo/openim-logo-yellow.png
create mode 100644 assets/logo/openim-logo.png
create mode 100644 assets/openim-logo-gradient.pdf
create mode 100644 assets/openim-logo-gradient.svg
create mode 100644 assets/openim-logo-green.pdf
create mode 100644 assets/openim-logo-green.svg
create mode 100644 bootstrap.bat
create mode 100644 bootstrap.sh
create mode 100644 build/README.md
create mode 100644 build/goreleaser.yaml
create mode 100644 build/images/Dockerfile
create mode 100644 build/images/openim-api/Dockerfile
create mode 100644 build/images/openim-crontask/Dockerfile
create mode 100644 build/images/openim-msggateway/Dockerfile
create mode 100644 build/images/openim-msgtransfer/Dockerfile
create mode 100644 build/images/openim-push/Dockerfile
create mode 100644 build/images/openim-rpc-auth/Dockerfile
create mode 100644 build/images/openim-rpc-conversation/Dockerfile
create mode 100644 build/images/openim-rpc-friend/Dockerfile
create mode 100644 build/images/openim-rpc-group/Dockerfile
create mode 100644 build/images/openim-rpc-msg/Dockerfile
create mode 100644 build/images/openim-rpc-third/Dockerfile
create mode 100644 build/images/openim-rpc-user/Dockerfile
create mode 100644 build/images/openim-tools/component/Dockerfile
create mode 100644 cmd/main.go
create mode 100644 cmd/openim-api/main.go
create mode 100644 cmd/openim-cmdutils/main.go
create mode 100644 cmd/openim-crontask/main.go
create mode 100644 cmd/openim-msggateway/main.go
create mode 100644 cmd/openim-msgtransfer/main.go
create mode 100644 cmd/openim-push/main.go
create mode 100644 cmd/openim-rpc/openim-rpc-auth/main.go
create mode 100644 cmd/openim-rpc/openim-rpc-conversation/main.go
create mode 100644 cmd/openim-rpc/openim-rpc-friend/main.go
create mode 100644 cmd/openim-rpc/openim-rpc-group/main.go
create mode 100644 cmd/openim-rpc/openim-rpc-msg/main.go
create mode 100644 cmd/openim-rpc/openim-rpc-third/main.go
create mode 100644 cmd/openim-rpc/openim-rpc-user/main.go
create mode 100644 config/README.md
create mode 100644 config/README_zh_CN.md
create mode 100644 config/alertmanager.yml
create mode 100644 config/discovery.yml
create mode 100644 config/email.tmpl
create mode 100644 config/grafana-template/Demo.json
create mode 100644 config/instance-down-rules.yml
create mode 100644 config/kafka.yml
create mode 100644 config/local-cache.yml
create mode 100644 config/log.yml
create mode 100644 config/minio.yml
create mode 100644 config/mongodb.yml
create mode 100644 config/notification.yml
create mode 100644 config/openim-api.yml
create mode 100644 config/openim-crontask.yml
create mode 100644 config/openim-msggateway.yml
create mode 100644 config/openim-msgtransfer.yml
create mode 100644 config/openim-push.yml
create mode 100644 config/openim-rpc-auth.yml
create mode 100644 config/openim-rpc-conversation.yml
create mode 100644 config/openim-rpc-friend.yml
create mode 100644 config/openim-rpc-group.yml
create mode 100644 config/openim-rpc-msg.yml
create mode 100644 config/openim-rpc-third.yml
create mode 100644 config/openim-rpc-user.yml
create mode 100644 config/prometheus.yml
create mode 100644 config/redis.yml
create mode 100644 config/share.yml
create mode 100644 config/webhooks.yml
create mode 100644 deployments/Readme.md
create mode 100644 deployments/deploy/clusterRole.yml
create mode 100644 deployments/deploy/ingress.yml
create mode 100644 deployments/deploy/kafka-secret.yml
create mode 100644 deployments/deploy/kafka-service.yml
create mode 100644 deployments/deploy/kafka-statefulset.yml
create mode 100644 deployments/deploy/minio-secret.yml
create mode 100644 deployments/deploy/minio-service.yml
create mode 100644 deployments/deploy/minio-statefulset.yml
create mode 100644 deployments/deploy/mongo-secret.yml
create mode 100644 deployments/deploy/mongo-service.yml
create mode 100644 deployments/deploy/mongo-statefulset.yml
create mode 100644 deployments/deploy/openim-api-deployment.yml
create mode 100644 deployments/deploy/openim-api-service.yml
create mode 100644 deployments/deploy/openim-config.yml
create mode 100644 deployments/deploy/openim-crontask-deployment.yml
create mode 100644 deployments/deploy/openim-msggateway-deployment.yml
create mode 100644 deployments/deploy/openim-msggateway-service.yml
create mode 100644 deployments/deploy/openim-msgtransfer-deployment.yml
create mode 100644 deployments/deploy/openim-msgtransfer-service.yml
create mode 100644 deployments/deploy/openim-push-deployment.yml
create mode 100644 deployments/deploy/openim-push-service.yml
create mode 100644 deployments/deploy/openim-rpc-auth-deployment.yml
create mode 100644 deployments/deploy/openim-rpc-auth-service.yml
create mode 100644 deployments/deploy/openim-rpc-conversation-deployment.yml
create mode 100644 deployments/deploy/openim-rpc-conversation-service.yml
create mode 100644 deployments/deploy/openim-rpc-friend-deployment.yml
create mode 100644 deployments/deploy/openim-rpc-friend-service.yml
create mode 100644 deployments/deploy/openim-rpc-group-deployment.yml
create mode 100644 deployments/deploy/openim-rpc-group-service.yml
create mode 100644 deployments/deploy/openim-rpc-msg-deployment.yml
create mode 100644 deployments/deploy/openim-rpc-msg-service.yml
create mode 100644 deployments/deploy/openim-rpc-third-deployment.yml
create mode 100644 deployments/deploy/openim-rpc-third-service.yml
create mode 100644 deployments/deploy/openim-rpc-user-deployment.yml
create mode 100644 deployments/deploy/openim-rpc-user-service.yml
create mode 100644 deployments/deploy/redis-secret.yml
create mode 100644 deployments/deploy/redis-service.yml
create mode 100644 deployments/deploy/redis-statefulset.yml
create mode 100644 docker-compose.yml
create mode 100644 docs/.generated_docs
create mode 100644 docs/CODEOWNERS
create mode 100644 docs/K8s服务发现Bug最终修复方案.md
create mode 100644 docs/README.md
create mode 100644 docs/SuperGroup使用限制分析.md
create mode 100644 docs/client-api.md
create mode 100644 docs/contrib/README.md
create mode 100644 docs/contrib/api.md
create mode 100644 docs/contrib/bash-log.md
create mode 100644 docs/contrib/cicd-actions.md
create mode 100644 docs/contrib/code-conventions.md
create mode 100644 docs/contrib/commit.md
create mode 100644 docs/contrib/development.md
create mode 100644 docs/contrib/directory.md
create mode 100644 docs/contrib/environment.md
create mode 100644 docs/contrib/error-code.md
create mode 100644 docs/contrib/git-workflow.md
create mode 100644 docs/contrib/gitcherry-pick.md
create mode 100644 docs/contrib/github-workflow.md
create mode 100644 docs/contrib/go-code.md
create mode 100644 docs/contrib/go-code1.md
create mode 100644 docs/contrib/go-doc.md
create mode 100644 docs/contrib/images.md
create mode 100644 docs/contrib/init-config.md
create mode 100644 docs/contrib/install-docker.md
create mode 100644 docs/contrib/install-openim-linux-system.md
create mode 100644 docs/contrib/kafka.md
create mode 100644 docs/contrib/linux-development.md
create mode 100644 docs/contrib/local-actions.md
create mode 100644 docs/contrib/logging.md
create mode 100644 docs/contrib/mac-developer-deployment-guide.md
create mode 100644 docs/contrib/offline-deployment.md
create mode 100644 docs/contrib/prometheus-grafana.md
create mode 100644 docs/contrib/protoc-tools.md
create mode 100644 docs/contrib/release.md
create mode 100644 docs/contrib/test.md
create mode 100644 docs/contrib/util-go.md
create mode 100644 docs/contrib/util-makefile.md
create mode 100644 docs/contrib/util-scripts.md
create mode 100644 docs/contrib/version.md
create mode 100644 docs/contributing/CONTRIBUTING-JP.md
create mode 100644 docs/contributing/CONTRIBUTING-PL.md
create mode 100644 docs/images/architecture-layers.png
create mode 100644 docs/images/architecture.jpg
create mode 100644 docs/images/oepnim-design.png
create mode 100644 docs/images/open-im-logo.png
create mode 100644 docs/images/open-im-server.png
create mode 100644 docs/images/wechat.jpg
create mode 100644 docs/meeting-api.md
create mode 100644 docs/meeting-client-api.md
create mode 100644 docs/readme/README_cs.md
create mode 100644 docs/readme/README_da.md
create mode 100644 docs/readme/README_el.md
create mode 100644 docs/readme/README_es.md
create mode 100644 docs/readme/README_fa.md
create mode 100644 docs/readme/README_fr.md
create mode 100644 docs/readme/README_hu.md
create mode 100644 docs/readme/README_ja.md
create mode 100644 docs/readme/README_ko.md
create mode 100644 docs/readme/README_tr.md
create mode 100644 docs/readme/README_uk.md
create mode 100644 docs/readme/README_vi.md
create mode 100644 docs/redpacket-api.md
create mode 100644 docs/redpacket-flow.md
create mode 100644 docs/redpacket-implementation-plan.md
create mode 100644 docs/redpacket-message-structure.md
create mode 100644 docs/statistics-api.md
create mode 100644 docs/troubleshooting.md
create mode 100644 docs/webhook-config.md
create mode 100644 docs/使用Ex字段区分群类型方案.md
create mode 100644 docs/统计接口调用example.md
create mode 100644 go.mod
create mode 100644 go.sum
create mode 100755 install.sh
create mode 100644 internal/api/auth.go
create mode 100644 internal/api/config_manager.go
create mode 100644 internal/api/conversation.go
create mode 100644 internal/api/custom_validator.go
create mode 100644 internal/api/friend.go
create mode 100644 internal/api/group.go
create mode 100644 internal/api/init.go
create mode 100644 internal/api/jssdk/jssdk.go
create mode 100644 internal/api/jssdk/sort.go
create mode 100644 internal/api/jssdk/tools.go
create mode 100644 internal/api/meeting.go
create mode 100644 internal/api/msg.go
create mode 100644 internal/api/prometheus_discovery.go
create mode 100644 internal/api/ratelimit.go
create mode 100644 internal/api/redpacket.go
create mode 100644 internal/api/router.go
create mode 100644 internal/api/statistics.go
create mode 100644 internal/api/third.go
create mode 100644 internal/api/user.go
create mode 100644 internal/api/wallet.go
create mode 100644 internal/msggateway/callback.go
create mode 100644 internal/msggateway/client.go
create mode 100644 internal/msggateway/compressor.go
create mode 100644 internal/msggateway/compressor_test.go
create mode 100644 internal/msggateway/constant.go
create mode 100644 internal/msggateway/context.go
create mode 100644 internal/msggateway/encoder.go
create mode 100644 internal/msggateway/http_error.go
create mode 100644 internal/msggateway/hub_server.go
create mode 100644 internal/msggateway/init.go
create mode 100644 internal/msggateway/long_conn.go
create mode 100644 internal/msggateway/message_handler.go
create mode 100644 internal/msggateway/online.go
create mode 100644 internal/msggateway/options.go
create mode 100644 internal/msggateway/subscription.go
create mode 100644 internal/msggateway/user_map.go
create mode 100644 internal/msggateway/ws_server.go
create mode 100644 internal/msgtransfer/callback.go
create mode 100644 internal/msgtransfer/init.go
create mode 100644 internal/msgtransfer/online_history_msg_handler.go
create mode 100644 internal/msgtransfer/online_msg_to_mongo_handler.go
create mode 100644 internal/push/callback.go
create mode 100644 internal/push/offlinepush/dummy/push.go
create mode 100644 internal/push/offlinepush/fcm/push.go
create mode 100644 internal/push/offlinepush/getui/body.go
create mode 100644 internal/push/offlinepush/getui/push.go
create mode 100644 internal/push/offlinepush/jpush/body/audience.go
create mode 100644 internal/push/offlinepush/jpush/body/message.go
create mode 100644 internal/push/offlinepush/jpush/body/notification.go
create mode 100644 internal/push/offlinepush/jpush/body/options.go
create mode 100644 internal/push/offlinepush/jpush/body/platform.go
create mode 100644 internal/push/offlinepush/jpush/body/pushobj.go
create mode 100644 internal/push/offlinepush/jpush/push.go
create mode 100644 internal/push/offlinepush/offlinepusher.go
create mode 100644 internal/push/offlinepush/options/options.go
create mode 100644 internal/push/offlinepush_handler.go
create mode 100644 internal/push/onlinepusher.go
create mode 100644 internal/push/push.go
create mode 100644 internal/push/push_handler.go
create mode 100644 internal/rpc/auth/auth.go
create mode 100644 internal/rpc/conversation/callback.go
create mode 100644 internal/rpc/conversation/conversation.go
create mode 100644 internal/rpc/conversation/db_map.go
create mode 100644 internal/rpc/conversation/notification.go
create mode 100644 internal/rpc/conversation/sync.go
create mode 100644 internal/rpc/group/cache.go
create mode 100644 internal/rpc/group/callback.go
create mode 100644 internal/rpc/group/convert.go
create mode 100644 internal/rpc/group/db_map.go
create mode 100644 internal/rpc/group/fill.go
create mode 100644 internal/rpc/group/group.go
create mode 100644 internal/rpc/group/notification.go
create mode 100644 internal/rpc/group/statistics.go
create mode 100644 internal/rpc/group/sync.go
create mode 100644 internal/rpc/incrversion/batch_option.go
create mode 100644 internal/rpc/incrversion/option.go
create mode 100644 internal/rpc/msg/as_read.go
create mode 100644 internal/rpc/msg/callback.go
create mode 100644 internal/rpc/msg/clear.go
create mode 100644 internal/rpc/msg/delete.go
create mode 100644 internal/rpc/msg/filter.go
create mode 100644 internal/rpc/msg/msg_status.go
create mode 100644 internal/rpc/msg/notification.go
create mode 100644 internal/rpc/msg/qrcode_decoder.go
create mode 100644 internal/rpc/msg/qrcode_detect.go
create mode 100644 internal/rpc/msg/revoke.go
create mode 100644 internal/rpc/msg/send.go
create mode 100644 internal/rpc/msg/seq.go
create mode 100644 internal/rpc/msg/server.go
create mode 100644 internal/rpc/msg/statistics.go
create mode 100644 internal/rpc/msg/sync_msg.go
create mode 100644 internal/rpc/msg/utils.go
create mode 100644 internal/rpc/msg/verify.go
create mode 100644 internal/rpc/relation/black.go
create mode 100644 internal/rpc/relation/callback.go
create mode 100644 internal/rpc/relation/friend.go
create mode 100644 internal/rpc/relation/notification.go
create mode 100644 internal/rpc/relation/sync.go
create mode 100644 internal/rpc/third/log.go
create mode 100644 internal/rpc/third/r2.go
create mode 100644 internal/rpc/third/s3.go
create mode 100644 internal/rpc/third/third.go
create mode 100644 internal/rpc/third/tool.go
create mode 100644 internal/rpc/user/callback.go
create mode 100644 internal/rpc/user/config.go
create mode 100644 internal/rpc/user/notification.go
create mode 100644 internal/rpc/user/online.go
create mode 100644 internal/rpc/user/statistics.go
create mode 100644 internal/rpc/user/user.go
create mode 100644 internal/tools/cron/clear_msg.go
create mode 100644 internal/tools/cron/cron_task.go
create mode 100644 internal/tools/cron/cron_test.go
create mode 100644 internal/tools/cron/dist_look.go
create mode 100644 internal/tools/cron/meeting.go
create mode 100644 internal/tools/cron/msg.go
create mode 100644 internal/tools/cron/s3.go
create mode 100644 magefile.go
create mode 100644 magefile_unix.go
create mode 100644 magefile_windows.go
create mode 100644 package-lock.json
create mode 100644 pkg/apistruct/config_manager.go
create mode 100644 pkg/apistruct/doc.go
create mode 100644 pkg/apistruct/manage.go
create mode 100644 pkg/apistruct/msg.go
create mode 100644 pkg/apistruct/public.go
create mode 100644 pkg/apistruct/statistics.go
create mode 100644 pkg/authverify/doc.go
create mode 100644 pkg/authverify/token.go
create mode 100644 pkg/callbackstruct/common.go
create mode 100644 pkg/callbackstruct/constant.go
create mode 100644 pkg/callbackstruct/conversation.go
create mode 100644 pkg/callbackstruct/doc.go
create mode 100644 pkg/callbackstruct/friend.go
create mode 100644 pkg/callbackstruct/group.go
create mode 100644 pkg/callbackstruct/message.go
create mode 100644 pkg/callbackstruct/msg_gateway.go
create mode 100644 pkg/callbackstruct/push.go
create mode 100644 pkg/callbackstruct/revoke.go
create mode 100644 pkg/callbackstruct/user.go
create mode 100644 pkg/common/cmd/api.go
create mode 100644 pkg/common/cmd/auth.go
create mode 100644 pkg/common/cmd/conversation.go
create mode 100644 pkg/common/cmd/cron_task.go
create mode 100644 pkg/common/cmd/doc.go
create mode 100644 pkg/common/cmd/friend.go
create mode 100644 pkg/common/cmd/group.go
create mode 100644 pkg/common/cmd/msg.go
create mode 100644 pkg/common/cmd/msg_gateway.go
create mode 100644 pkg/common/cmd/msg_gateway_test.go
create mode 100644 pkg/common/cmd/msg_transfer.go
create mode 100644 pkg/common/cmd/msg_utils.go
create mode 100644 pkg/common/cmd/push.go
create mode 100644 pkg/common/cmd/root.go
create mode 100644 pkg/common/cmd/third.go
create mode 100644 pkg/common/cmd/user.go
create mode 100644 pkg/common/config/config.go
create mode 100644 pkg/common/config/constant.go
create mode 100644 pkg/common/config/doc.go
create mode 100644 pkg/common/config/env.go
create mode 100644 pkg/common/config/global.go
create mode 100644 pkg/common/config/load_config.go
create mode 100644 pkg/common/config/load_config_test.go
create mode 100644 pkg/common/config/parse.go
create mode 100644 pkg/common/convert/auth.go
create mode 100644 pkg/common/convert/black.go
create mode 100644 pkg/common/convert/conversation.go
create mode 100644 pkg/common/convert/doc.go
create mode 100644 pkg/common/convert/friend.go
create mode 100644 pkg/common/convert/group.go
create mode 100644 pkg/common/convert/msg.go
create mode 100644 pkg/common/convert/user.go
create mode 100644 pkg/common/convert/user_test.go
create mode 100644 pkg/common/discovery/direct/direct_resolver.go
create mode 100644 pkg/common/discovery/direct/directconn.go
create mode 100644 pkg/common/discovery/direct/doc.go
create mode 100644 pkg/common/discovery/discoveryregister.go
create mode 100644 pkg/common/discovery/discoveryregister_test.go
create mode 100644 pkg/common/discovery/doc.go
create mode 100644 pkg/common/discovery/etcd/config_manager.go
create mode 100644 pkg/common/discovery/etcd/const.go
create mode 100644 pkg/common/discovery/kubernetes/doc.go
create mode 100644 pkg/common/discovery/kubernetes/kubernetes.go
create mode 100644 pkg/common/ginprometheus/doc.go
create mode 100644 pkg/common/ginprometheus/ginprometheus.go
create mode 100644 pkg/common/prommetrics/api.go
create mode 100644 pkg/common/prommetrics/grpc_auth.go
create mode 100644 pkg/common/prommetrics/grpc_msg.go
create mode 100644 pkg/common/prommetrics/grpc_msggateway.go
create mode 100644 pkg/common/prommetrics/grpc_push.go
create mode 100644 pkg/common/prommetrics/grpc_user.go
create mode 100644 pkg/common/prommetrics/prommetrics.go
create mode 100644 pkg/common/prommetrics/prommetrics_test.go
create mode 100644 pkg/common/prommetrics/rpc.go
create mode 100644 pkg/common/prommetrics/transfer.go
create mode 100644 pkg/common/servererrs/code.go
create mode 100644 pkg/common/servererrs/doc.go
create mode 100644 pkg/common/servererrs/predefine.go
create mode 100644 pkg/common/servererrs/relation.go
create mode 100644 pkg/common/startrpc/circuitbreaker.go
create mode 100644 pkg/common/startrpc/mw.go
create mode 100644 pkg/common/startrpc/ratelimit.go
create mode 100644 pkg/common/startrpc/start.go
create mode 100644 pkg/common/startrpc/tools.go
create mode 100644 pkg/common/storage/cache/batch_handler.go
create mode 100644 pkg/common/storage/cache/black.go
create mode 100644 pkg/common/storage/cache/client_config.go
create mode 100644 pkg/common/storage/cache/conversation.go
create mode 100644 pkg/common/storage/cache/doc.go
create mode 100644 pkg/common/storage/cache/friend.go
create mode 100644 pkg/common/storage/cache/group.go
create mode 100644 pkg/common/storage/cache/mcache/minio.go
create mode 100644 pkg/common/storage/cache/mcache/msg_cache.go
create mode 100644 pkg/common/storage/cache/mcache/online.go
create mode 100644 pkg/common/storage/cache/mcache/seq_conversation.go
create mode 100644 pkg/common/storage/cache/mcache/third.go
create mode 100644 pkg/common/storage/cache/mcache/token.go
create mode 100644 pkg/common/storage/cache/mcache/tools.go
create mode 100644 pkg/common/storage/cache/msg.go
create mode 100644 pkg/common/storage/cache/online.go
create mode 100644 pkg/common/storage/cache/redis/batch.go
create mode 100644 pkg/common/storage/cache/redis/batch_handler.go
create mode 100644 pkg/common/storage/cache/redis/batch_test.go
create mode 100644 pkg/common/storage/cache/redis/black.go
create mode 100644 pkg/common/storage/cache/redis/client_config.go
create mode 100644 pkg/common/storage/cache/redis/conversation.go
create mode 100644 pkg/common/storage/cache/redis/friend.go
create mode 100644 pkg/common/storage/cache/redis/group.go
create mode 100644 pkg/common/storage/cache/redis/lua_script.go
create mode 100644 pkg/common/storage/cache/redis/lua_script_test.go
create mode 100644 pkg/common/storage/cache/redis/minio.go
create mode 100644 pkg/common/storage/cache/redis/msg.go
create mode 100644 pkg/common/storage/cache/redis/online.go
create mode 100644 pkg/common/storage/cache/redis/online_count.go
create mode 100644 pkg/common/storage/cache/redis/online_test.go
create mode 100644 pkg/common/storage/cache/redis/redis_shard_manager.go
create mode 100644 pkg/common/storage/cache/redis/s3.go
create mode 100644 pkg/common/storage/cache/redis/seq_conversation.go
create mode 100644 pkg/common/storage/cache/redis/seq_conversation_test.go
create mode 100644 pkg/common/storage/cache/redis/seq_user.go
create mode 100644 pkg/common/storage/cache/redis/seq_user_test.go
create mode 100644 pkg/common/storage/cache/redis/third.go
create mode 100644 pkg/common/storage/cache/redis/token.go
create mode 100644 pkg/common/storage/cache/redis/user.go
create mode 100644 pkg/common/storage/cache/s3.go
create mode 100644 pkg/common/storage/cache/seq_conversation.go
create mode 100644 pkg/common/storage/cache/seq_user.go
create mode 100644 pkg/common/storage/cache/third.go
create mode 100644 pkg/common/storage/cache/token.go
create mode 100644 pkg/common/storage/cache/user.go
create mode 100644 pkg/common/storage/common/types.go
create mode 100644 pkg/common/storage/controller/auth.go
create mode 100644 pkg/common/storage/controller/black.go
create mode 100644 pkg/common/storage/controller/client_config.go
create mode 100644 pkg/common/storage/controller/conversation.go
create mode 100644 pkg/common/storage/controller/doc.go
create mode 100644 pkg/common/storage/controller/friend.go
create mode 100644 pkg/common/storage/controller/group.go
create mode 100644 pkg/common/storage/controller/msg.go
create mode 100644 pkg/common/storage/controller/msg_transfer.go
create mode 100644 pkg/common/storage/controller/push.go
create mode 100644 pkg/common/storage/controller/s3.go
create mode 100644 pkg/common/storage/controller/third.go
create mode 100644 pkg/common/storage/controller/user.go
create mode 100644 pkg/common/storage/database/black.go
create mode 100644 pkg/common/storage/database/cache.go
create mode 100644 pkg/common/storage/database/client_config.go
create mode 100644 pkg/common/storage/database/conversation.go
create mode 100644 pkg/common/storage/database/doc.go
create mode 100644 pkg/common/storage/database/friend.go
create mode 100644 pkg/common/storage/database/friend_request.go
create mode 100644 pkg/common/storage/database/group.go
create mode 100644 pkg/common/storage/database/group_member.go
create mode 100644 pkg/common/storage/database/group_request.go
create mode 100644 pkg/common/storage/database/log.go
create mode 100644 pkg/common/storage/database/meeting.go
create mode 100644 pkg/common/storage/database/meeting_checkin.go
create mode 100644 pkg/common/storage/database/mgo/black.go
create mode 100644 pkg/common/storage/database/mgo/cache.go
create mode 100644 pkg/common/storage/database/mgo/cache_test.go
create mode 100644 pkg/common/storage/database/mgo/client_config.go
create mode 100644 pkg/common/storage/database/mgo/conversation.go
create mode 100644 pkg/common/storage/database/mgo/doc.go
create mode 100644 pkg/common/storage/database/mgo/friend.go
create mode 100644 pkg/common/storage/database/mgo/friend_request.go
create mode 100644 pkg/common/storage/database/mgo/group.go
create mode 100644 pkg/common/storage/database/mgo/group_member.go
create mode 100644 pkg/common/storage/database/mgo/group_request.go
create mode 100644 pkg/common/storage/database/mgo/helpers.go
create mode 100644 pkg/common/storage/database/mgo/log.go
create mode 100644 pkg/common/storage/database/mgo/meeting.go
create mode 100644 pkg/common/storage/database/mgo/meeting_checkin.go
create mode 100644 pkg/common/storage/database/mgo/msg.go
create mode 100644 pkg/common/storage/database/mgo/msg_test.go
create mode 100644 pkg/common/storage/database/mgo/object.go
create mode 100644 pkg/common/storage/database/mgo/redpacket.go
create mode 100644 pkg/common/storage/database/mgo/seq_conversation.go
create mode 100644 pkg/common/storage/database/mgo/seq_conversation_test.go
create mode 100644 pkg/common/storage/database/mgo/seq_user.go
create mode 100644 pkg/common/storage/database/mgo/system_config.go
create mode 100644 pkg/common/storage/database/mgo/user.go
create mode 100644 pkg/common/storage/database/mgo/version_log.go
create mode 100644 pkg/common/storage/database/mgo/version_test.go
create mode 100644 pkg/common/storage/database/mgo/wallet.go
create mode 100644 pkg/common/storage/database/msg.go
create mode 100644 pkg/common/storage/database/name.go
create mode 100644 pkg/common/storage/database/object.go
create mode 100644 pkg/common/storage/database/redpacket.go
create mode 100644 pkg/common/storage/database/seq.go
create mode 100644 pkg/common/storage/database/seq_user.go
create mode 100644 pkg/common/storage/database/system_config.go
create mode 100644 pkg/common/storage/database/user.go
create mode 100644 pkg/common/storage/database/version_log.go
create mode 100644 pkg/common/storage/database/wallet.go
create mode 100644 pkg/common/storage/model/application.go
create mode 100644 pkg/common/storage/model/black.go
create mode 100644 pkg/common/storage/model/cache.go
create mode 100644 pkg/common/storage/model/client_config.go
create mode 100644 pkg/common/storage/model/conversation.go
create mode 100644 pkg/common/storage/model/doc.go
create mode 100644 pkg/common/storage/model/friend.go
create mode 100644 pkg/common/storage/model/friend_request.go
create mode 100644 pkg/common/storage/model/group.go
create mode 100644 pkg/common/storage/model/group_member.go
create mode 100644 pkg/common/storage/model/group_request.go
create mode 100644 pkg/common/storage/model/log.go
create mode 100644 pkg/common/storage/model/meeting.go
create mode 100644 pkg/common/storage/model/meeting_checkin.go
create mode 100644 pkg/common/storage/model/msg.go
create mode 100644 pkg/common/storage/model/object.go
create mode 100644 pkg/common/storage/model/redpacket.go
create mode 100644 pkg/common/storage/model/seq.go
create mode 100644 pkg/common/storage/model/seq_user.go
create mode 100644 pkg/common/storage/model/subscribe.go
create mode 100644 pkg/common/storage/model/system_config.go
create mode 100644 pkg/common/storage/model/user.go
create mode 100644 pkg/common/storage/model/version_log.go
create mode 100644 pkg/common/storage/model/wallet.go
create mode 100644 pkg/common/storage/versionctx/rpc.go
create mode 100644 pkg/common/storage/versionctx/version.go
create mode 100644 pkg/common/webhook/condition.go
create mode 100644 pkg/common/webhook/config_manager.go
create mode 100644 pkg/common/webhook/doc.go
create mode 100644 pkg/common/webhook/http_client.go
create mode 100644 pkg/common/webhook/http_client_test.go
create mode 100644 pkg/dbbuild/builder.go
create mode 100644 pkg/dbbuild/microservices.go
create mode 100644 pkg/dbbuild/standalone.go
create mode 100644 pkg/localcache/cache.go
create mode 100644 pkg/localcache/cache_test.go
create mode 100644 pkg/localcache/doc.go
create mode 100644 pkg/localcache/init.go
create mode 100644 pkg/localcache/link/doc.go
create mode 100644 pkg/localcache/link/link.go
create mode 100644 pkg/localcache/link/link_test.go
create mode 100644 pkg/localcache/lru/doc.go
create mode 100644 pkg/localcache/lru/lru.go
create mode 100644 pkg/localcache/lru/lru_expiration.go
create mode 100644 pkg/localcache/lru/lru_lazy.go
create mode 100644 pkg/localcache/lru/lru_lazy_test.go
create mode 100644 pkg/localcache/lru/lru_slot.go
create mode 100644 pkg/localcache/option.go
create mode 100644 pkg/localcache/tool.go
create mode 100644 pkg/mqbuild/builder.go
create mode 100644 pkg/msgprocessor/conversation.go
create mode 100644 pkg/msgprocessor/doc.go
create mode 100644 pkg/msgprocessor/options.go
create mode 100644 pkg/notification/common_user/common.go
create mode 100644 pkg/notification/grouphash/grouphash.go
create mode 100644 pkg/notification/msg.go
create mode 100644 pkg/rpccache/auth.go
create mode 100644 pkg/rpccache/common.go
create mode 100644 pkg/rpccache/conversation.go
create mode 100644 pkg/rpccache/doc.go
create mode 100644 pkg/rpccache/friend.go
create mode 100644 pkg/rpccache/group.go
create mode 100644 pkg/rpccache/online.go
create mode 100644 pkg/rpccache/subscriber.go
create mode 100644 pkg/rpccache/user.go
create mode 100644 pkg/rpcli/auth.go
create mode 100644 pkg/rpcli/conversation.go
create mode 100644 pkg/rpcli/group.go
create mode 100644 pkg/rpcli/msg.go
create mode 100644 pkg/rpcli/msggateway.go
create mode 100644 pkg/rpcli/push.go
create mode 100644 pkg/rpcli/relation.go
create mode 100644 pkg/rpcli/rtc.go
create mode 100644 pkg/rpcli/third.go
create mode 100644 pkg/rpcli/tool.go
create mode 100644 pkg/rpcli/user.go
create mode 100644 pkg/statistics/doc.go
create mode 100644 pkg/statistics/statistics.go
create mode 100644 pkg/tools/batcher/batcher.go
create mode 100644 pkg/tools/batcher/batcher_test.go
create mode 100644 pkg/util/conversationutil/conversationutil.go
create mode 100644 pkg/util/conversationutil/doc.go
create mode 100644 pkg/util/hashutil/id.go
create mode 100644 pkg/util/useronline/split.go
create mode 100644 scripts/template/LICENSE
create mode 100644 scripts/template/LICENSE_TEMPLATES
create mode 100644 scripts/template/boilerplate.txt
create mode 100644 scripts/template/footer.md.tmpl
create mode 100644 scripts/template/head.md.tmpl
create mode 100644 scripts/template/project_README.md
create mode 100644 start-config.yml
create mode 100644 test/e2e/README.md
create mode 100644 test/e2e/api/token/token.go
create mode 100644 test/e2e/api/user/curd.go
create mode 100644 test/e2e/api/user/user.go
create mode 100644 test/e2e/conformance/.keep
create mode 100644 test/e2e/e2e.go
create mode 100644 test/e2e/e2e_test.go
create mode 100644 test/e2e/framework/config/config.go
create mode 100644 test/e2e/framework/config/config_test.go
create mode 100644 test/e2e/framework/ginkgowrapper/.keep
create mode 100644 test/e2e/framework/ginkgowrapper/ginkgowrapper.go
create mode 100644 test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go
create mode 100644 test/e2e/framework/helpers/.keep
create mode 100644 test/e2e/framework/helpers/chat/chat.go
create mode 100644 test/e2e/page/chat_page.go
create mode 100644 test/e2e/page/login_page.go
create mode 100644 test/e2e/performance/.keep
create mode 100644 test/e2e/rpc/auth/.keep
create mode 100644 test/e2e/rpc/conversation/.keep
create mode 100644 test/e2e/rpc/friend/.keep
create mode 100644 test/e2e/rpc/group/.keep
create mode 100644 test/e2e/rpc/message/.keep
create mode 100644 test/e2e/scalability/.keep
create mode 100644 test/e2e/upgrade/.keep
create mode 100644 test/e2e/web/Readme.md
create mode 100644 test/jwt/main.go
create mode 100644 test/readme
create mode 100644 test/stress-test-v2/README.md
create mode 100644 test/stress-test-v2/main.go
create mode 100644 test/stress-test/README.md
create mode 100755 test/stress-test/main.go
create mode 100644 test/testdata/README.md
create mode 100644 test/testdata/db/messages.json
create mode 100644 test/testdata/db/users.json
create mode 100644 test/testdata/requests/login.json
create mode 100644 test/testdata/requests/register.json
create mode 100644 test/testdata/requests/send-message.json
create mode 100644 test/testdata/responses/login.json
create mode 100644 test/testdata/responses/register.json
create mode 100644 test/testdata/responses/sendMessage.json
create mode 100644 test/webhook/msgmodify/main.go
create mode 100644 tools/README.md
create mode 100644 tools/changelog/changelog.go
create mode 100644 tools/check-component/main.go
create mode 100644 tools/check-free-memory/main.go
create mode 100644 tools/imctl/.gitignore
create mode 100644 tools/imctl/README.md
create mode 100644 tools/imctl/main.go
create mode 100644 tools/infra/main.go
create mode 100644 tools/ncpu/README.md
create mode 100644 tools/ncpu/main.go
create mode 100644 tools/ncpu/main_test.go
create mode 100644 tools/s3/README.md
create mode 100644 tools/s3/internal/conversion.go
create mode 100644 tools/s3/main.go
create mode 100644 tools/seq/internal/seq.go
create mode 100644 tools/seq/main.go
create mode 100644 tools/url2im/main.go
create mode 100644 tools/url2im/pkg/api.go
create mode 100644 tools/url2im/pkg/buffer.go
create mode 100644 tools/url2im/pkg/config.go
create mode 100644 tools/url2im/pkg/http.go
create mode 100644 tools/url2im/pkg/manage.go
create mode 100644 tools/url2im/pkg/md5.go
create mode 100644 tools/url2im/pkg/progress.go
create mode 100644 tools/versionchecker/main.go
create mode 100644 tools/yamlfmt/main.go
create mode 100644 tools/yamlfmt/main_test.go
create mode 100644 version/version
create mode 100644 version/version.go
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..cf6c3cd
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,28 @@
+# Ignore files and directories starting with a dot
+
+# Ignore specific files
+.dockerignore
+.git
+
+# Ignore build artifacts
+logs/
+_output/
+# Ignore non-essential documentation
+README.md
+README-zh_CN.md
+CONTRIBUTING.md
+CHANGELOG/
+# LICENSE
+
+# Ignore testing and linting configuration
+.golangci.yml
+
+
+# Ignore assets
+assets/
+
+# Ignore components
+components/
+
+# Ignore tools and scripts
+.github/
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfdb8b7
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.sh text eol=lf
diff --git a/.gitea/SECRETS_CONFIG.md b/.gitea/SECRETS_CONFIG.md
new file mode 100644
index 0000000..da67ee7
--- /dev/null
+++ b/.gitea/SECRETS_CONFIG.md
@@ -0,0 +1,255 @@
+# OpenIM Server 项目 Gitea Actions 秘钥配置指南
+
+## 📋 概述
+
+本指南说明如何在 Gitea 中配置必要的秘钥,以支持 OpenIM Server 项目的自动构建和部署到阿里云 ACK。
+
+## 🔑 必需秘钥配置
+
+### 1. Docker Hub 相关秘钥
+
+#### DOCKER_USERNAME
+- **描述**: Docker Hub 用户名
+- **示例**: `openim`
+- **获取方式**: 在 Docker Hub 注册账号
+
+#### DOCKER_PASSWORD
+- **描述**: Docker Hub 密码或访问令牌
+- **示例**: `your-docker-password` 或 `dckr_pat_xxxxxxxxxxxx`
+- **推荐**: 使用访问令牌(Access Token)而不是密码
+- **获取方式**:
+ 1. 登录 Docker Hub
+ 2. 进入 Account Settings → Security
+ 3. 创建 New Access Token
+
+### 2. 阿里云 ACK 相关秘钥
+
+#### KUBECONFIG
+- **描述**: 阿里云 ACK 集群的 kubeconfig 内容(base64编码)
+- **格式**: base64编码的YAML格式kubeconfig文件内容
+- **获取方式**: 见下方详细说明
+
+#### ALIBABA_CLOUD_ACCESS_KEY_ID (可选)
+- **描述**: 阿里云AccessKey ID
+- **用途**: 用于通过aliyun CLI获取kubeconfig
+- **获取方式**: 阿里云控制台 → 访问控制 → AccessKey管理
+
+#### ALIBABA_CLOUD_ACCESS_KEY_SECRET (可选)
+- **描述**: 阿里云AccessKey Secret
+- **用途**: 用于通过aliyun CLI获取kubeconfig
+- **获取方式**: 阿里云控制台 → 访问控制 → AccessKey管理
+
+#### ACK_CLUSTER_ID (可选)
+- **描述**: 阿里云ACK集群ID
+- **用途**: 用于通过aliyun CLI获取kubeconfig
+- **获取方式**: ACK控制台集群详情页
+
+#### ACK_REGION (可选)
+- **描述**: 阿里云ACK集群区域
+- **默认值**: `cn-hangzhou`
+- **示例**: `cn-beijing`, `cn-shanghai`, `cn-shenzhen`
+
+#### NAMESPACE (可选)
+- **描述**: Kubernetes命名空间
+- **默认值**: `openim`
+- **示例**: `openim`, `default`, `production`
+
+## 🚀 获取阿里云 ACK KUBECONFIG
+
+### 方法1: 通过阿里云控制台(推荐)
+
+1. **登录阿里云控制台**
+ - 访问 [阿里云容器服务控制台](https://cs.console.aliyun.com/)
+
+2. **选择集群**
+ - 进入目标 ACK 集群详情页
+
+3. **获取连接信息**
+ - 点击 "连接信息" 标签
+ - 复制 "公网访问" 或 "内网访问" 的 kubeconfig 内容
+
+4. **编码kubeconfig**
+ ```bash
+ # 将获取的kubeconfig内容保存到文件
+ cat > kubeconfig.yaml << 'EOF'
+ apiVersion: v1
+ clusters:
+ - cluster:
+ certificate-authority-data: LS0tLS1CRUdJTi...
+ server: https://your-cluster-id.cn-hangzhou.cs.aliyuncs.com:6443
+ name: kubernetes
+ contexts:
+ - context:
+ cluster: kubernetes
+ user: your-user
+ name: kubernetes
+ current-context: kubernetes
+ kind: Config
+ preferences: {}
+ users:
+ - name: your-user
+ user:
+ client-certificate-data: LS0tLS1CRUdJTi...
+ client-key-data: LS0tLS1CRUdJTi...
+ EOF
+
+ # 编码为base64
+ base64 -w 0 kubeconfig.yaml
+ ```
+
+### 方法2: 通过阿里云 CLI
+
+1. **安装阿里云 CLI**
+ ```bash
+ # macOS
+ brew install aliyun-cli
+
+ # Linux
+ curl -sSL https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz | tar -xzC /usr/local/bin
+ ```
+
+2. **配置认证**
+ ```bash
+ aliyun configure
+ # 输入 AccessKey ID 和 AccessKey Secret
+ ```
+
+3. **获取kubeconfig并编码**
+ ```bash
+ # 获取指定集群的kubeconfig
+ aliyun cs GET /k8s/clusters/{cluster_id}/user_config > kubeconfig.yaml
+
+ # 编码为base64
+ base64 -w 0 kubeconfig.yaml
+ ```
+
+## 🔧 在 Gitea 中配置秘钥
+
+### 1. 进入仓库设置
+
+1. 打开 OpenIM Server 项目仓库
+2. 点击 "Settings" 标签
+3. 在左侧菜单中点击 "Secrets"
+
+### 2. 添加秘钥
+
+点击 "New Secret" 按钮,依次添加以下秘钥:
+
+#### 必需秘钥
+
+##### DOCKER_USERNAME
+- **Name**: `DOCKER_USERNAME`
+- **Value**: 你的 Docker Hub 用户名
+
+##### DOCKER_PASSWORD
+- **Name**: `DOCKER_PASSWORD`
+- **Value**: 你的 Docker Hub 密码或访问令牌
+
+##### KUBECONFIG
+- **Name**: `KUBECONFIG`
+- **Value**: base64编码的kubeconfig文件内容
+
+#### 可选秘钥
+
+##### ALIBABA_CLOUD_ACCESS_KEY_ID
+- **Name**: `ALIBABA_CLOUD_ACCESS_KEY_ID`
+- **Value**: 阿里云AccessKey ID
+
+##### ALIBABA_CLOUD_ACCESS_KEY_SECRET
+- **Name**: `ALIBABA_CLOUD_ACCESS_KEY_SECRET`
+- **Value**: 阿里云AccessKey Secret
+
+##### ACK_CLUSTER_ID
+- **Name**: `ACK_CLUSTER_ID`
+- **Value**: ACK集群ID
+
+##### ACK_REGION
+- **Name**: `ACK_REGION`
+- **Value**: ACK集群区域(默认:cn-hangzhou)
+
+##### NAMESPACE
+- **Name**: `NAMESPACE`
+- **Value**: Kubernetes命名空间(默认:openim)
+
+## 🚨 安全注意事项
+
+### 1. 秘钥安全
+- **不要** 将秘钥提交到代码仓库
+- **定期轮换** 访问令牌和密码
+- **使用最小权限** 原则配置访问权限
+
+### 2. KUBECONFIG 安全
+- **限制权限**: 确保kubeconfig只有必要的权限
+- **定期更新**: 定期更新证书和密钥
+- **监控访问**: 监控集群访问日志
+
+### 3. Docker Hub 安全
+- **使用访问令牌**: 优先使用访问令牌而不是密码
+- **限制权限**: 只授予必要的仓库推送权限
+- **定期轮换**: 定期更新访问令牌
+
+## 🔍 故障排除
+
+### 常见问题
+
+#### 1. Docker 登录失败
+```
+Error: Cannot perform an interactive login from a non TTY device
+```
+**解决方案**: 检查 `DOCKER_USERNAME` 和 `DOCKER_PASSWORD` 是否正确配置
+
+#### 2. kubectl 连接失败
+```
+Unable to connect to the server: x509: certificate signed by unknown authority
+```
+**解决方案**: 检查 `KUBECONFIG` 中的证书数据是否正确
+
+#### 3. 镜像拉取失败
+```
+Error: pull access denied for openim/openim-api
+```
+**解决方案**: 检查 Docker Hub 权限和镜像名称是否正确
+
+#### 4. 部署超时
+```
+deployment "openim-api" exceeded its progress deadline
+```
+**解决方案**: 检查集群资源是否充足,Pod 是否正常启动
+
+### 调试命令
+
+```bash
+# 检查秘钥是否正确设置
+echo "Docker username: $DOCKER_USERNAME"
+echo "Kubeconfig length: ${#KUBECONFIG}"
+
+# 测试 Docker 登录
+echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
+
+# 测试 kubectl 连接
+echo "$KUBECONFIG" | base64 -d > ~/.kube/config
+kubectl cluster-info
+kubectl get nodes
+```
+
+## 📚 参考文档
+
+- [Gitea Actions 文档](https://docs.gitea.io/en-us/actions/)
+- [阿里云 ACK 文档](https://help.aliyun.com/product/85222.html)
+- [Docker Hub 访问令牌](https://docs.docker.com/docker-hub/access-tokens/)
+- [Kubernetes kubeconfig](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/)
+- [OpenIM 官方文档](https://docs.openim.io/)
+
+## 🆘 支持
+
+如遇到问题,请检查:
+1. 秘钥是否正确配置
+2. 网络连接是否正常
+3. 权限是否充足
+4. 集群状态是否正常
+
+更多帮助请参考:
+- Gitea Actions 日志
+- 阿里云 ACK 控制台
+- Docker Hub 状态页面
+- OpenIM 官方文档
diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml
new file mode 100644
index 0000000..bfb90ea
--- /dev/null
+++ b/.gitea/workflows/build.yml
@@ -0,0 +1,535 @@
+name: OpenIM Server 构建和发布
+
+on:
+ push:
+ branches: [ main, master, wallet, develop, release-* ]
+ paths:
+ - '**'
+ pull_request:
+ branches: [ main, master, wallet ]
+ paths:
+ - '**'
+ release:
+ types: [published]
+ workflow_dispatch:
+ inputs:
+ tag:
+ description: "Tag version to be used for Docker image"
+ required: true
+ default: "latest"
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ REGISTRY: docker.io
+ DOCKER_USER: ${{ secrets.DOCKER_USERNAME || 'mag1666888' }}
+ GO_VERSION: "1.24"
+
+jobs:
+ build-and-push:
+ runs-on: openim
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: 检出代码
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+
+ - name: 配置 SSH 密钥
+ run: |
+ echo "🔑 配置 SSH 密钥..."
+ # 创建 .ssh 目录
+ mkdir -p ~/.ssh
+ chmod 700 ~/.ssh
+
+ # 从 secrets 中获取 SSH 私钥并 base64 解码
+ echo "${{ secrets.SSH_PRIVATE_KEY }}" | base64 -d > ~/.ssh/id_rsa
+ chmod 600 ~/.ssh/id_rsa
+
+ # 配置 SSH 主机密钥验证(可选,避免首次连接时的确认提示)
+ ssh-keyscan -H git.imall.cloud >> ~/.ssh/known_hosts 2>/dev/null || true
+ chmod 644 ~/.ssh/known_hosts
+
+ # 验证 SSH 密钥
+ if [ -f ~/.ssh/id_rsa ]; then
+ echo "✅ SSH 密钥配置成功"
+ else
+ echo "❌ SSH 密钥配置失败"
+ exit 1
+ fi
+
+ - name: 检出 protocol 仓库
+ run: |
+ echo "📦 克隆 protocol 仓库..."
+ # 使用 SSH 方式克隆 protocol 仓库
+ git clone git@git.imall.cloud:openim/protocol.git ./protocol || true
+ cd ./protocol
+ git fetch --all
+ git checkout v1.0.4
+ cd ..
+ # 创建父目录的protocol符号链接,使replace ../protocol 能正确找到
+ ln -sf $PWD/protocol ../protocol || true
+ echo "✅ protocol 仓库检出完成"
+
+ - name: 设置 Go 缓存
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cache/go-build
+ ~/go/pkg/mod
+ key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+ restore-keys: |
+ ${{ runner.os }}-go-
+
+ - name: 设置 Go 环境
+ uses: actions/setup-go@v5
+ with:
+ go-version: ${{ env.GO_VERSION }}
+ cache: true
+
+ - name: 检查 Go 环境
+ run: |
+ if command -v go &> /dev/null; then
+ echo "Go: $(go version)"
+ go mod verify >/dev/null 2>&1
+ go mod tidy >/dev/null 2>&1
+ go mod download >/dev/null 2>&1
+ echo "Go modules verified"
+ else
+ echo "Go not found, skipping Go steps"
+ fi
+
+ - name: 检查系统资源
+ run: |
+ echo "系统资源信息:"
+ echo "CPU核心数: $(nproc)"
+ echo "内存总量: $(free -h | awk '/^Mem:/ {print $2}')"
+ echo "可用内存: $(free -h | awk '/^Mem:/ {print $7}')"
+ echo "磁盘空间: $(df -h / | awk 'NR==2 {print $4}')"
+ echo ""
+
+ - name: 清理 Docker 环境
+ run: |
+ echo "清理Docker环境..."
+ docker image prune -f >/dev/null 2>&1 || true
+
+ - name: 登录到 Docker Hub
+ uses: docker/login-action@v3.3.0
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ - name: 设置 Docker Buildx
+ uses: docker/setup-buildx-action@v3.8.0
+ with:
+ driver-opts: |
+ image=moby/buildkit:buildx-stable-1
+ network=host
+
+ - name: 构建和推送所有服务镜像
+ working-directory: ${{ github.workspace }}
+ run: |
+ # 设置错误处理
+ trap 'echo "脚本在行 $LINENO 处失败,退出状态: $?"' ERR
+ set -e
+
+ # 获取版本标签(使用分支名)
+ if [ "${{ github.event_name }}" = "release" ]; then
+ VERSION_TAG="${{ github.event.release.tag_name }}"
+ elif [ -n "${{ github.event.inputs.tag }}" ]; then
+ VERSION_TAG="${{ github.event.inputs.tag }}"
+ else
+ # 使用分支名作为标签
+ VERSION_TAG="${{ github.ref_name }}"
+ fi
+
+ echo "构建OpenIM Server镜像 (标签: $VERSION_TAG)"
+ echo "Docker用户: $DOCKER_USER"
+
+ # 定义构建顺序(openim-msggateway 和 openim-push 优先构建)
+ CORE_SERVICES=(
+ "openim-msggateway"
+ "openim-push"
+ "openim-rpc-msg"
+ "openim-api"
+ "openim-msgtransfer"
+ "openim-crontask"
+ )
+
+ RPC_SERVICES=(
+ "openim-rpc-auth"
+ "openim-rpc-user"
+ "openim-rpc-friend"
+ "openim-rpc-group"
+ "openim-rpc-conversation"
+ "openim-rpc-third"
+ )
+
+ # 构建函数
+ build_service() {
+ local service=$1
+ local dockerfile="build/images/$service/Dockerfile"
+ local start_time=$(date +%s)
+
+ if [ -f "$dockerfile" ]; then
+ echo "📦 构建 $service..."
+
+ if docker buildx build \
+ --platform linux/amd64 \
+ --file "$dockerfile" \
+ --tag "$DOCKER_USER/$service:$VERSION_TAG" \
+ --tag "$DOCKER_USER/$service:prod" \
+ --push \
+ --progress=plain \
+ --cache-from type=gha,scope=openim-build-${{ github.ref_name }}-$service \
+ --cache-to type=gha,mode=max,scope=openim-build-${{ github.ref_name }}-$service \
+ --build-arg BUILDKIT_INLINE_CACHE=1 \
+ --build-arg GOCACHE=/go-cache \
+ --build-arg GOMAXPROCS=$(nproc) \
+ --provenance=false \
+ --sbom=false \
+ . > "/tmp/build_${service}.log" 2>&1; then
+
+ local end_time=$(date +%s)
+ local duration=$((end_time - start_time))
+ echo "✅ $service 构建成功 (${duration}秒)"
+ else
+ echo "❌ $service 构建失败,查看详细错误日志:"
+ echo "=========================================="
+ cat "/tmp/build_${service}.log"
+ echo "=========================================="
+ echo "最后 50 行错误日志:"
+ tail -50 "/tmp/build_${service}.log"
+ return 1
+ fi
+ else
+ echo "❌ $service - 未找到 Dockerfile: $dockerfile"
+ return 1
+ fi
+ }
+
+ # 初始化构建统计
+ failed_services=()
+ successful_services=()
+
+ # 计算总服务数
+ total_services=$((${#CORE_SERVICES[@]} + ${#RPC_SERVICES[@]}))
+ echo "开始构建 $total_services 个服务..."
+
+ # 先构建核心服务
+ for service in "${CORE_SERVICES[@]}"; do
+ if build_service "$service"; then
+ successful_services+=("$service")
+ else
+ failed_services+=("$service")
+ fi
+ done
+
+ # 构建RPC服务
+ for service in "${RPC_SERVICES[@]}"; do
+ if build_service "$service"; then
+ successful_services+=("$service")
+ else
+ failed_services+=("$service")
+ fi
+ done
+
+ # 输出构建结果统计
+ echo ""
+ echo "🎉 构建完成总结"
+ echo "✅ 成功构建: ${#successful_services[@]} 个服务"
+ echo "❌ 构建失败: ${#failed_services[@]} 个服务"
+ echo "📊 成功率: $(( ${#successful_services[@]} * 100 / total_services ))%"
+
+ if [ ${#failed_services[@]} -gt 0 ]; then
+ echo ""
+ echo "失败服务错误日志:"
+ for service in "${failed_services[@]}"; do
+ echo "=== $service ==="
+ cat "/tmp/build_${service}.log" 2>/dev/null || echo "无法读取日志文件"
+ echo ""
+ done
+ exit 1
+ fi
+
+ - name: 配置 kubectl
+ if: success()
+ run: |
+ echo "🔧 配置 kubectl 连接到阿里云 ACK..."
+ # 创建 kubeconfig 目录
+ mkdir -p ~/.kube
+
+ # 从 secrets 中获取 kubeconfig 内容并处理
+ echo "📝 处理 kubeconfig 文件..."
+
+ # 直接解码 base64 内容
+ echo "🔍 解码 base64 编码的 kubeconfig..."
+ echo "${{ secrets.KUBECONFIG }}" | base64 -d > ~/.kube/config
+
+ # 验证解码是否成功
+ if [ ! -s ~/.kube/config ]; then
+ echo "❌ kubeconfig 解码失败或文件为空"
+ exit 1
+ fi
+
+ # 显示 kubeconfig 内容供手动检查
+ echo "🔍 解码后的 kubeconfig 内容:"
+ cat ~/.kube/config
+
+ chmod 600 ~/.kube/config
+ echo "✅ kubeconfig 配置完成"
+
+ # 详细验证 kubectl 配置
+ echo "🔍 验证 kubectl 配置..."
+ echo "当前上下文:"
+ kubectl config current-context 2>&1 || echo "无法获取当前上下文"
+
+ echo "可用上下文:"
+ kubectl config get-contexts 2>&1 || echo "无法获取上下文列表"
+
+ echo "集群信息:"
+ kubectl cluster-info 2>&1 || echo "无法获取集群信息"
+
+ echo "API 版本:"
+ kubectl version --short 2>&1 || echo "无法获取版本信息"
+
+ - name: 部署到阿里云 ACK
+ if: success()
+ run: |
+ echo "🚀 开始部署到阿里云 ACK..."
+
+ # 简单验证 kubectl
+ if ! kubectl version --client >/dev/null 2>&1; then
+ echo "❌ kubectl 不可用,跳过部署步骤"
+ exit 0
+ fi
+
+ echo "✅ kubectl 可用,尝试部署..."
+
+ # 获取版本标签(使用分支名)
+ if [ "${{ github.event_name }}" = "release" ]; then
+ VERSION_TAG="${{ github.event.release.tag_name }}"
+ elif [ -n "${{ github.event.inputs.tag }}" ]; then
+ VERSION_TAG="${{ github.event.inputs.tag }}"
+ else
+ # 使用分支名作为标签
+ VERSION_TAG="${{ github.ref_name }}"
+ fi
+
+ echo "版本标签: $VERSION_TAG"
+ echo "Docker用户: $DOCKER_USER"
+
+ # 检查部署文件是否存在
+ DEPLOY_DIR="deployments/deploy"
+ if [ ! -d "$DEPLOY_DIR" ]; then
+ echo "❌ 部署目录不存在: $DEPLOY_DIR"
+ echo "📁 当前目录内容:"
+ ls -la
+ echo "⚠️ 部署失败,但构建流程继续"
+ exit 0
+ fi
+
+ echo "📁 进入部署目录: $DEPLOY_DIR"
+ cd "$DEPLOY_DIR"
+
+ # 设置命名空间
+ NS=${NS:-default}
+ echo "使用命名空间: $NS"
+
+ # 创建命名空间(如果不存在)
+ kubectl get ns "$NS" >/dev/null 2>&1 || kubectl create ns "$NS"
+ kubectl config set-context --current --namespace="$NS"
+
+ # 尝试部署,如果失败则继续
+ echo "🚀 开始部署OpenIM Server服务..."
+
+ # 定义所有部署文件
+ DEPLOYMENT_FILES=(
+ "openim-api-deployment.yml"
+ "openim-crontask-deployment.yml"
+ "openim-rpc-user-deployment.yml"
+ "openim-msggateway-deployment.yml"
+ "openim-push-deployment.yml"
+ "openim-msgtransfer-deployment.yml"
+ "openim-rpc-conversation-deployment.yml"
+ "openim-rpc-auth-deployment.yml"
+ "openim-rpc-group-deployment.yml"
+ "openim-rpc-friend-deployment.yml"
+ "openim-rpc-msg-deployment.yml"
+ "openim-rpc-third-deployment.yml"
+ )
+
+ # 更新镜像标签并部署
+ DEPLOYMENT_ERRORS=()
+ for file in "${DEPLOYMENT_FILES[@]}"; do
+ if [ -f "$file" ]; then
+ echo "📦 处理 $file..."
+ # 备份原文件(保留 imagePullSecrets 等配置)
+ cp "$file" "$file.bak"
+ # 更新镜像标签(替换用户名和标签,但保留 imagePullSecrets)
+ sed -i "s|image: .*/openim-|image: $DOCKER_USER/openim-|g" "$file"
+ sed -i "s|:prod|:prod|g" "$file"
+ # 验证 imagePullSecrets 是否保留
+ if ! grep -q "imagePullSecrets:" "$file"; then
+ echo "⚠️ 警告: $file 中缺少 imagePullSecrets,从备份恢复..."
+ cp "$file.bak" "$file"
+ # 只更新镜像,不修改其他内容
+ sed -i "s|image: .*/openim-|image: $DOCKER_USER/openim-|g" "$file"
+ sed -i "s|:prod|:prod|g" "$file"
+ fi
+ # 应用文件并捕获详细错误
+ echo "🔍 执行: kubectl apply -f $file"
+ if kubectl apply -f "$file" 2>&1; then
+ echo "✅ $file 部署成功"
+ else
+ ERROR_OUTPUT=$(kubectl apply -f "$file" 2>&1)
+ echo "❌ $file 部署失败:"
+ echo "$ERROR_OUTPUT"
+ DEPLOYMENT_ERRORS+=("$file: $ERROR_OUTPUT")
+ echo "⚠️ 继续处理下一个文件..."
+ fi
+ # 清理备份文件
+ rm -f "$file.bak"
+ else
+ echo "⚠️ $file 不存在,跳过"
+ fi
+ done
+
+ # 显示部署错误总结
+ if [ ${#DEPLOYMENT_ERRORS[@]} -gt 0 ]; then
+ echo ""
+ echo "🚨 部署错误总结:"
+ echo "=========================================="
+ for error in "${DEPLOYMENT_ERRORS[@]}"; do
+ echo "❌ $error"
+ done
+ echo "=========================================="
+ fi
+
+ echo "✅ 部署步骤完成"
+
+ # 强制重启所有部署以使用新镜像
+ echo "🔄 强制重启所有部署以使用新镜像..."
+ DEPLOYMENTS=(
+ "openim-api"
+ "openim-crontask"
+ "messagegateway-rpc-server"
+ "openim-msgtransfer-server"
+ "push-rpc-server"
+ "auth-rpc-server"
+ "user-rpc-server"
+ "friend-rpc-server"
+ "group-rpc-server"
+ "conversation-rpc-server"
+ "third-rpc-server"
+ "msg-rpc-server"
+ )
+
+ for deployment in "${DEPLOYMENTS[@]}"; do
+ echo "🔄 重启部署: $deployment"
+ # 先删除 pod 以强制拉取新镜像(即使 imagePullPolicy 是 Always,有时也需要删除 pod)
+ if kubectl delete pods -l app="$deployment" --grace-period=0 --force 2>&1; then
+ echo "✅ $deployment Pod 已删除,将重新创建并拉取新镜像"
+ fi
+ # 然后重启 deployment
+ if kubectl rollout restart deployment "$deployment" 2>&1; then
+ echo "✅ $deployment 重启成功"
+ else
+ echo "⚠️ $deployment 重启失败,可能不存在"
+ fi
+ done
+
+ echo "⏳ 等待部署完成..."
+ for deployment in "${DEPLOYMENTS[@]}"; do
+ echo "⏳ 等待 $deployment 就绪..."
+ if kubectl rollout status deployment "$deployment" --timeout=300s; then
+ echo "✅ $deployment 部署完成"
+ else
+ echo "⚠️ $deployment 超时,检查Pod状态..."
+ echo "Pod状态:"
+ kubectl get pods -l app="$deployment" 2>&1 || echo "无法获取Pod状态"
+ echo "Pod事件:"
+ kubectl get events --field-selector involvedObject.name="$deployment" --sort-by='.lastTimestamp' 2>&1 | tail -10 || echo "无法获取事件"
+ echo "部署详情:"
+ kubectl describe deployment "$deployment" 2>&1 | tail -20 || echo "无法获取部署详情"
+ fi
+ done
+
+ - name: 验证部署状态
+ if: success()
+ run: |
+ echo "🔍 验证部署状态..."
+
+ # 详细检查集群连接和权限
+ echo "🔍 检查集群连接..."
+ if kubectl cluster-info 2>&1; then
+ echo "✅ 集群连接正常"
+ else
+ CLUSTER_ERROR=$(kubectl cluster-info 2>&1)
+ echo "❌ 集群连接失败: $CLUSTER_ERROR"
+ fi
+
+ echo "🔍 检查命名空间权限..."
+ if kubectl get namespaces 2>&1; then
+ echo "✅ 命名空间权限正常"
+ else
+ NS_ERROR=$(kubectl get namespaces 2>&1)
+ echo "❌ 命名空间权限不足: $NS_ERROR"
+ fi
+
+ echo "🔍 检查 Pod 状态..."
+ if kubectl get pods -l app=openim 2>&1; then
+ echo "✅ Pod 状态检查完成"
+ else
+ POD_ERROR=$(kubectl get pods -l app=openim 2>&1)
+ echo "❌ Pod 状态检查失败: $POD_ERROR"
+ fi
+
+ echo "🔍 检查部署状态..."
+ if kubectl get deployments -l app=openim 2>&1; then
+ echo "✅ 部署状态检查完成"
+ else
+ DEPLOY_ERROR=$(kubectl get deployments -l app=openim 2>&1)
+ echo "❌ 部署状态检查失败: $DEPLOY_ERROR"
+ fi
+
+ echo "✅ 验证完成"
+
+ - name: 生成构建报告
+ run: |
+ # 获取版本标签(使用分支名)
+ if [ "${{ github.event_name }}" = "release" ]; then
+ VERSION_TAG="${{ github.event.release.tag_name }}"
+ elif [ -n "${{ github.event.inputs.tag }}" ]; then
+ VERSION_TAG="${{ github.event.inputs.tag }}"
+ else
+ # 使用分支名作为标签
+ VERSION_TAG="${{ github.ref_name }}"
+ fi
+
+ echo "## OpenIM Server Build Complete" >> $GITHUB_STEP_SUMMARY
+ echo "**Tag:** $VERSION_TAG" >> $GITHUB_STEP_SUMMARY
+ echo "**Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
+ echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
+ echo "**Platform:** linux/amd64" >> $GITHUB_STEP_SUMMARY
+ echo "**Mode:** 完整构建和部署" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "**Images:**" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-api:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-msggateway:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-msgtransfer:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-push:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-crontask:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-rpc-auth:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-rpc-user:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-rpc-friend:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-rpc-group:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-rpc-conversation:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-rpc-third:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
+ echo "- \`$DOCKER_USER/openim-rpc-msg:$VERSION_TAG\`" >> $GITHUB_STEP_SUMMARY
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3d7401b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,426 @@
+# Copyright © 2023 OpenIMSDK.
+#
+# 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.
+
+# ==============================================================================
+# For the entire design of.gitignore, ignore git commits and ignore files
+#===============================================================================
+#
+
+### OpenIM developer supplement ###
+logs
+.devcontainer
+components
+out-test
+Dockerfile.cross
+
+### Makefile ###
+tmp/
+bin/
+output/
+_output/
+deployments/charts/generated-configs/
+
+### OpenIM Config ###
+.env
+config/config.yaml
+config/notification.yaml
+
+### OpenIM deploy ###
+deployments/openim-server/charts
+
+# files used by the developer
+.idea.md
+.todo.md
+.note.md
+scripts/chat_register_login.sh
+scripts/check_online_vs_register.sh
+scripts/cleanup_online_keys.sh
+scripts/cleanup_online_keys_cluster.sh
+scripts/start_all_local.sh
+scripts/switch_online_prefix_roll_restart_verify.sh
+scripts/verify_online_prefix.sh
+
+# ==============================================================================
+# Created by https://www.toptal.com/developers/gitignore/api/go,git,vim,tags,test,emacs,backup,jetbrains
+# Edit at https://www.toptal.com/developers/gitignore?templates=go,git,vim,tags,test,emacs,backup,jetbrains
+
+### Backup ###
+*.bak
+*.gho
+*.ori
+*.orig
+*.tmp
+
+### Emacs ###
+# -*- mode: gitignore; -*-
+*~
+\#*\#
+/.emacs.desktop
+/.emacs.desktop.lock
+*.elc
+auto-save-list
+tramp
+.\#*
+
+# Org-mode
+.org-id-locations
+*_archive
+
+# flymake-mode
+*_flymake.*
+
+# eshell files
+/eshell/history
+/eshell/lastdir
+
+# elpa packages
+/elpa/
+
+# reftex files
+*.rel
+
+# AUCTeX auto folder
+/auto/
+
+# cask packages
+.cask/
+dist/
+
+# Flycheck
+flycheck_*.el
+
+# server auth directory
+/server/
+
+# projectiles files
+.projectile
+
+# directory configuration
+.dir-locals.el
+
+# network security
+/network-security.data
+
+### vscode ###
+.vscode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# End of https://www.toptal.com/developers/gitignore/api/vim,jetbrains,vscode,git,go,tags,backup,test
+
+### Git ###
+# Created by git for backups. To disable backups in Git:
+# $ git config --global mergetool.keepBackup false
+
+# Created by git when using merge tools for conflicts
+*.BACKUP.*
+*.BASE.*
+*.LOCAL.*
+*.REMOTE.*
+*_BACKUP_*.txt
+*_BASE_*.txt
+*_LOCAL_*.txt
+*_REMOTE_*.txt
+
+### Go ###
+# If you prefer the allow list template instead of the deny list, see community template:
+# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
+#
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+vendor/
+
+# Go workspace file
+# go.work
+go.work.sum
+
+### JetBrains ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### JetBrains Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+# https://plugins.jetbrains.com/plugin/7973-sonarlint
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator-enh.xml
+.idea/**/markdown-navigator/
+
+# Cache file creation bug
+# See https://youtrack.jetbrains.com/issue/JBR-2257
+.idea/$CACHE_FILE$
+
+# CodeStream plugin
+# https://plugins.jetbrains.com/plugin/12206-codestream
+.idea/codestream.xml
+
+# Azure Toolkit for IntelliJ plugin
+# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
+.idea/**/azureSettings.xml
+
+### Tags ###
+# Ignore tags created by etags, ctags, gtags (GNU global) and cscope
+TAGS
+.TAGS
+!TAGS/
+tags
+.tags
+!tags/
+gtags.files
+GTAGS
+GRTAGS
+GPATH
+GSYMS
+cscope.files
+cscope.out
+cscope.in.out
+cscope.po.out
+
+
+### Test ###
+### Ignore all files that could be used to test your code and
+### you wouldn't want to push
+
+# Reference https://en.wikipedia.org/wiki/Metasyntactic_variable
+
+# Most common
+*foo
+*bar
+*fubar
+*foobar
+*baz
+
+# Less common
+*qux
+*quux
+*bongo
+*bazola
+*ztesch
+
+# UK, Australia
+*wibble
+*wobble
+*wubble
+*flob
+*blep
+*blah
+*boop
+*beep
+
+# Japanese
+*hoge
+*piyo
+*fuga
+*hogera
+*hogehoge
+
+# Portugal, Spain
+*fulano
+*sicrano
+*beltrano
+*mengano
+*perengano
+*zutano
+
+# France, Italy, the Netherlands
+*toto
+*titi
+*tata
+*tutu
+*pipppo
+*pluto
+*paperino
+*aap
+*noot
+*mies
+
+# Other names that would make sense
+*tests
+*testsdir
+*testsfile
+*testsfiles
+*testdir
+*testfile
+*testfiles
+*testing
+*testingdir
+*testingfile
+*testingfiles
+*temp
+*tempdir
+*tempfile
+*tempfiles
+*tmp
+*tmpdir
+*tmpfile
+*tmpfiles
+*lol
+
+### Vim ###
+# Swap
+[._]*.s[a-v][a-z]
+!*.svg # comment out if you don't need vector files
+[._]*.sw[a-p]
+[._]s[a-rt-v][a-z]
+[._]ss[a-gi-z]
+[._]sw[a-p]
+
+# Session
+Session.vim
+Sessionx.vim
+
+# Temporary
+.netrwhist
+# Auto-generated tag files
+# Persistent undo
+[._]*.un~
+
+# End of https://www.toptal.com/developers/gitignore/api/go,git,vim,tags,test,emacs,backup,jetbrains
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+.idea
+dist/
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 0000000..c1a5bfd
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,912 @@
+# options for analysis running
+run:
+ # default concurrency is a available CPU number
+ concurrency: 4
+
+ # timeout for analysis, e.g. 30s, 5m, default is 1m
+ timeout: 5m
+
+ # exit code when at least one issue was found, default is 1
+ issues-exit-code: 1
+
+ # include test files or not, default is true
+ tests: true
+
+ # list of build tags, all linters use it. Default is empty list.
+ build-tags:
+ - mytag
+
+ # which dirs to skip: issues from them won't be reported;
+ # can use regexp here: generated.*, regexp is applied on full path;
+ # default value is empty list, but default dirs are skipped independently
+ # from this option's value (see skip-dirs-use-default).
+ # "/" will be replaced by current OS file path separator to properly work
+ # on Windows.
+ # skip-dirs:
+ # - components
+ # - docs
+ # - util
+ # - .*~
+ # - api/swagger/docs
+
+
+ # - server/docs
+ # - components/mnt/config/certs
+ # - logs
+
+ # default is true. Enables skipping of directories:
+ # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
+ # skip-dirs-use-default: true
+
+ # which files to skip: they will be analyzed, but issues from them
+ # won't be reported. Default value is empty list, but there is
+ # no need to include all autogenerated files, we confidently recognize
+ # autogenerated files. If it's not please let us know.
+ # "/" will be replaced by current OS file path separator to properly work
+ # on Windows.
+ # skip-files:
+ # - ".*\\.my\\.go$"
+ # - _test.go
+ # - ".*_test.go"
+ # - "mocks/"
+ # - ".github/"
+ # - "logs/"
+ # - "_output/"
+ # - "components/"
+
+ # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
+ # If invoked with -mod=readonly, the go command is disallowed from the implicit
+ # automatic updating of go.mod described above. Instead, it fails when any changes
+ # to go.mod are needed. This setting is most useful to check that go.mod does
+ # not need updates, such as in a continuous integration and testing system.
+ # If invoked with -mod=vendor, the go command assumes that the vendor
+ # directory holds the correct copies of dependencies and ignores
+ # the dependency descriptions in go.mod.
+ #modules-download-mode: release|readonly|vendor
+
+ # Allow multiple parallel golangci-lint instances running.
+ # If false (default) - golangci-lint acquires file lock on start.
+ allow-parallel-runners: true
+
+
+# output configuration options
+output:
+ # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
+ # format: colored-line-number
+
+ # print lines of code with issue, default is true
+ print-issued-lines: true
+
+ # print linter name in the end of issue text, default is true
+ print-linter-name: true
+
+ # make issues output unique by line, default is true
+ uniq-by-line: true
+
+ # add a prefix to the output file references; default is no prefix
+ path-prefix: ""
+
+ # sorts results by: filepath, line and column
+ sort-results: true
+
+# all available settings of specific linters
+linters-settings:
+ bidichk:
+ # The following configurations check for all mentioned invisible unicode
+ # runes. It can be omitted because all runes are enabled by default.
+ left-to-right-embedding: true
+ right-to-left-embedding: true
+ pop-directional-formatting: true
+ left-to-right-override: true
+ right-to-left-override: true
+ left-to-right-isolate: true
+ right-to-left-isolate: true
+ first-strong-isolate: true
+ pop-directional-isolate: true
+
+ dupl:
+ # tokens count to trigger issue, 150 by default
+ threshold: 200
+ errcheck:
+ # report about not checking of errors in type assertions: `a := b.(MyStruct)`;
+ # default is false: such cases aren't reported by default.
+ check-type-assertions: false
+
+ # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
+ # default is false: such cases aren't reported by default.
+ check-blank: false
+
+ # [deprecated] comma-separated list of pairs of the form pkg:regex
+ # the regex is used to ignore names within pkg. (default "fmt:.*").
+ # see https://github.com/kisielk/errcheck#the-deprecated-method for details
+ #ignore: GenMarkdownTree,os:.*,BindPFlags,WriteTo,Help
+ #ignore: (os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*print(f|ln)?|os\.(Un)?Setenv
+
+ # path to a file containing a list of functions to exclude from checking
+ # see https://github.com/kisielk/errcheck#excluding-functions for details
+ # exclude: errcheck.txt
+
+ errorlint:
+ # Check whether fmt.Errorf uses the %w verb for formatting errors. See the readme for caveats
+ errorf: true
+ # Check for plain type assertions and type switches
+ asserts: true
+ # Check for plain error comparisons
+ comparison: true
+
+ exhaustive:
+ # Program elements to check for exhaustiveness.
+ # Default: [ switch ]
+ check:
+ - switch
+ - map
+ # check switch statements in generated files also
+ check-generated: false
+ # indicates that switch statements are to be considered exhaustive if a
+ # 'default' case is present, even if all enum members aren't listed in the
+ # switch
+ default-signifies-exhaustive: false
+ # enum members matching the supplied regex do not have to be listed in
+ # switch statements to satisfy exhaustiveness
+ ignore-enum-members: ""
+ # consider enums only in package scopes, not in inner scopes
+ package-scope-only: false
+
+
+ forbidigo:
+ # # Forbid the following identifiers (identifiers are written using regexp):
+ forbid:
+ # - ^print.*$
+ - 'fmt\.Print.*'
+ - fmt.Println.* # too much log noise
+ - ^unsafe\..*$
+ - ^init$
+ - ^os.Exit$
+ - ^fmt.Print.*$
+ - errors.New.*$
+ - ^fmt.Println.*$
+ - ^panic$
+ - painc
+ # - ginkgo\\.F.* # these are used just for local development
+ # # Exclude godoc examples from forbidigo checks. Default is true.
+ # exclude_godoc_examples: false
+
+ funlen:
+ lines: 220
+ statements: 80
+
+ gocognit:
+ # minimal code complexity to report, 30 by default (but we recommend 10-20)
+ min-complexity: 30
+
+ goconst:
+ # minimal length of string constant, 3 by default
+ min-len: 3
+ # minimal occurrences count to trigger, 3 by default
+ min-occurrences: 3
+ # ignore test files, false by default
+ ignore-tests: false
+ # look for existing constants matching the values, true by default
+ match-constant: true
+ # search also for duplicated numbers, false by default
+ numbers: false
+ # minimum value, only works with goconst.numbers, 3 by default
+ min: 3
+ # maximum value, only works with goconst.numbers, 3 by default
+ max: 3
+ # ignore when constant is not used as function argument, true by default
+ ignore-calls: true
+
+ gocritic:
+ # Which checks should be enabled; can't be combined with 'disabled-checks';
+ # See https://go-critic.github.io/overview#checks-overview
+ # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`
+ # By default list of stable checks is used.
+ enabled-checks:
+ #- rangeValCopy
+ - ruleguard
+
+ # Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
+ disabled-checks:
+ - regexpMust
+ - ifElseChain
+ #- exitAfterDefer
+
+ # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
+ # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
+ enabled-tags:
+ - performance
+ disabled-tags:
+ - experimental
+
+ # Settings passed to gocritic.
+ # The settings key is the name of a supported gocritic checker.
+ # The list of supported checkers can be find in https://go-critic.github.io/overview.
+ settings:
+ captLocal: # must be valid enabled check name
+ # whether to restrict checker to params only (default true)
+ paramsOnly: true
+ elseif:
+ # whether to skip balanced if-else pairs (default true)
+ skipBalanced: true
+ hugeParam:
+ # size in bytes that makes the warning trigger (default 80)
+ sizeThreshold: 80
+ rangeExprCopy:
+ # size in bytes that makes the warning trigger (default 512)
+ sizeThreshold: 512
+ # whether to check test functions (default true)
+ skipTestFuncs: true
+ rangeValCopy:
+ # size in bytes that makes the warning trigger (default 128)
+ sizeThreshold: 32
+ # whether to check test functions (default true)
+ skipTestFuncs: true
+ ruleguard:
+ # path to a gorules file for the ruleguard checker
+ rules: ''
+ underef:
+ # whether to skip (*x).method() calls where x is a pointer receiver (default true)
+ skipRecvDeref: true
+
+ gocyclo:
+ # minimal code complexity to report, 30 by default (but we recommend 10-20)
+ min-complexity: 30
+ cyclop:
+ # the maximal code complexity to report
+ max-complexity: 50
+ # the maximal average package complexity. If it's higher than 0.0 (float) the check is enabled (default 0.0)
+ package-average: 0.0
+ # should ignore tests (default false)
+ skip-tests: false
+ godot:
+ # comments to be checked: `declarations`, `toplevel`, or `all`
+ scope: declarations
+ # list of regexps for excluding particular comment lines from check
+ exclude:
+ # example: exclude comments which contain numbers
+ - '[0-9]+'
+ - 'func\s+\w+'
+ - 'FIXME:'
+ - '.*func.*'
+ # check that each sentence starts with a capital letter
+ capital: true
+ godox:
+ # report any comments starting with keywords, this is useful for TODO or FIXME comments that
+ # might be left in the code accidentally and should be resolved before merging
+ keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting
+ #- TODO
+ - BUG
+ - FIXME
+ #- NOTE
+ - OPTIMIZE # marks code that should be optimized before merging
+ - HACK # marks hack-arounds that should be removed before merging
+ gofmt:
+ # simplify code: gofmt with `-s` option, true by default
+ simplify: true
+
+ gofumpt:
+ # Select the Go version to target. The default is `1.18`.
+ go-version: "1.21"
+
+ # Choose whether or not to use the extra rules that are disabled
+ # by default
+ extra-rules: false
+
+ # goheader:
+ # values:
+ # const:
+ # define here const type values in format k:v, for example:
+ # COMPANY: MY COMPANY
+ # regexp:
+ # define here regexp type values, for example
+ # AUTHOR: .*@mycompany\.com
+ # template: # |-
+ # put here copyright header template for source code files, for example:
+ # Note: {{ YEAR }} is a builtin value that returns the year relative to the current machine time.
+ #
+ # {{ AUTHOR }} {{ COMPANY }} {{ YEAR }}
+ # SPDX-License-Identifier: Apache-2.0
+
+ # 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.
+ # template-path:
+ # also as alternative of directive 'template' you may put the path to file with the template source
+
+ goimports:
+ # put imports beginning with prefix after 3rd-party packages;
+ # it's a comma-separated list of prefixes
+ local-prefixes: github.com/openimsdk/open-im-server-deploy
+
+ gomnd:
+ # List of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.
+ # Default: ["argument", "case", "condition", "operation", "return", "assign"]
+ checks:
+ - argument
+ - case
+ - condition
+ - operation
+ - return
+ - assign
+ # List of numbers to exclude from analysis.
+ # The numbers should be written as string.
+ # Values always ignored: "1", "1.0", "0" and "0.0"
+ # Default: []
+ ignored-numbers:
+ - '0666'
+ - '0755'
+ - '42'
+ # List of file patterns to exclude from analysis.
+ # Values always ignored: `.+_test.go`
+ # Default: []
+ ignored-files:
+ - 'magic1_.+\.go$'
+ # List of function patterns to exclude from analysis.
+ # Following functions are always ignored: `time.Date`,
+ # `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`,
+ # `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`.
+ # Default: []
+ ignored-functions:
+ - '^math\.'
+ - '^webhook\.StatusText$'
+ gomoddirectives:
+ # Allow local `replace` directives. Default is false.
+ replace-local: true
+ # List of allowed `replace` directives. Default is empty.
+ replace-allow-list:
+ - google.golang.org/grpc
+
+ # Allow to not explain why the version has been retracted in the `retract` directives. Default is false.
+ retract-allow-no-explanation: false
+ # Forbid the use of the `exclude` directives. Default is false.
+ exclude-forbidden: false
+
+ gomodguard:
+ allowed:
+ modules:
+ - gorm.io/gen # List of allowed modules
+ - gorm.io/gorm
+ - gorm.io/driver/mysql
+ - k8s.io/klog
+ - github.com/allowed/module
+ - go.mongodb.org/mongo-driver/mongo
+ # - gopkg.in/yaml.v2
+ domains: # List of allowed module domains
+ - google.golang.org
+ - gopkg.in
+ - golang.org
+ - github.com
+ - go.mongodb.org
+ - go.uber.org
+ - openim.io
+ - go.etcd.io
+ blocked:
+ versions:
+ - github.com/MakeNowJust/heredoc:
+ version: "> 2.0.9"
+ reason: "use the latest version"
+ local_replace_directives: false # Set to true to raise lint issues for packages that are loaded from a local path via replace directive
+
+ gosec:
+ # To select a subset of rules to run.
+ # Available rules: https://github.com/securego/gosec#available-rules
+ includes:
+ - G401
+ - G306
+ - G101
+ # To specify a set of rules to explicitly exclude.
+ # Available rules: https://github.com/securego/gosec#available-rules
+ excludes:
+ - G204
+ # Exclude generated files
+ exclude-generated: true
+ # Filter out the issues with a lower severity than the given value. Valid options are: low, medium, high.
+ severity: "low"
+ # Filter out the issues with a lower confidence than the given value. Valid options are: low, medium, high.
+ confidence: "low"
+ # To specify the configuration of rules.
+ # The configuration of rules is not fully documented by gosec:
+ # https://github.com/securego/gosec#configuration
+ # https://github.com/securego/gosec/blob/569328eade2ccbad4ce2d0f21ee158ab5356a5cf/rules/rulelist.go#L60-L102
+ config:
+ G306: "0600"
+ G101:
+ pattern: "(?i)example"
+ ignore_entropy: false
+ entropy_threshold: "80.0"
+ per_char_threshold: "3.0"
+ truncate: "32"
+
+ gosimple:
+ # Select the Go version to target. The default is '1.13'.
+ go: "1.20"
+ # https://staticcheck.io/docs/options#checks
+ checks: [ "all" ]
+
+ govet:
+ # settings per analyzer
+ settings:
+ printf: # analyzer name, run `go tool vet help` to see all analyzers
+ funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer
+ - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
+ - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
+ - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
+ - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
+
+ # enable or disable analyzers by name
+ enable:
+ - atomicalign
+ enable-all: false
+ disable:
+ - shadow
+ disable-all: false
+
+ depguard:
+ rules:
+ prevent_unmaintained_packages:
+ list-mode: lax # allow unless explicitely denied
+ files:
+ - $all
+ - "!$test"
+ allow:
+ - $gostd
+ deny:
+ - pkg: io/ioutil
+ desc: "replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil"
+ - pkg: github.com/OpenIMSDK
+ desc: "The OpenIM organization has been replaced with lowercase, please do not use uppercase organization name, you will use openimsdk"
+ - pkg: log
+ desc: "We have a wrapped log package at openim, we recommend you to use our wrapped log package, https://github.com/openimsdk/open-im-server-deploy/blob/main/docs/contrib/logging.md"
+ - pkg: errors
+ desc: "We have a wrapped errors package at openim, we recommend you to use our wrapped errors package, https://github.com/openimsdk/open-im-server-deploy/blob/main/docs/contrib/error-code.md"
+
+ importas:
+ # if set to `true`, force to use alias.
+ no-unaliased: true
+ # List of aliases
+ alias:
+ # using `servingv1` alias for `knative.dev/serving/pkg/apis/serving/v1` package
+ - pkg: knative.dev/serving/pkg/apis/serving/v1
+ alias: servingv1
+ - pkg: gopkg.in/yaml.v2
+ alias: yaml
+ # using `autoscalingv1alpha1` alias for `knative.dev/serving/pkg/apis/autoscaling/v1alpha1` package
+ - pkg: knative.dev/serving/pkg/apis/autoscaling/v1alpha1
+ alias: autoscalingv1alpha1
+ # You can specify the package path by regular expression,
+ # and alias by regular expression expansion syntax like below.
+ # see https://github.com/julz/importas#use-regular-expression for details
+ - pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+)
+ alias: $1$2
+
+ ireturn:
+ # ireturn allows using `allow` and `reject` settings at the same time.
+ # Both settings are lists of the keywords and regular expressions matched to interface or package names.
+ # keywords:
+ # - `empty` for `interface{}`
+ # - `error` for errors
+ # - `stdlib` for standard library
+ # - `anon` for anonymous interfaces
+
+ # By default, it allows using errors, empty interfaces, anonymous interfaces,
+ # and interfaces provided by the standard library.
+ allow:
+ - anon
+ - error
+ - empty
+ - stdlib
+ # You can specify idiomatic endings for interface
+ - (or|er)$
+
+ # Reject patterns
+ reject:
+ - github.com\/user\/package\/v4\.Type
+
+ lll:
+ # max line length, lines longer will be reported. Default is 250.
+ # '\t' is counted as 1 character by default, and can be changed with the tab-width option
+ line-length: 250
+ # tab width in spaces. Default to 1.
+ tab-width: 4
+ misspell:
+ # Correct spellings using locale preferences for US or UK.
+ # Default is to use a neutral variety of English.
+ # Setting locale to US will correct the British spelling of 'colour' to 'color'.
+ locale: US
+ ignore-words:
+ - someword
+ nakedret:
+ # make an issue if func has more lines of code than this setting and it has naked returns; default is 30
+ max-func-lines: 30
+
+ nestif:
+ # minimal complexity of if statements to report, 5 by default
+ min-complexity: 4
+
+ nilnil:
+ # By default, nilnil checks all returned types below.
+ checked-types:
+ - ptr
+ - func
+ - iface
+ - map
+ - chan
+
+ nlreturn:
+ # size of the block (including return statement that is still "OK")
+ # so no return split required.
+ block-size: 1
+
+ nolintlint:
+ # Disable to ensure that all nolint directives actually have an effect. Default is true.
+ allow-unused: false
+ # Exclude following linters from requiring an explanation. Default is [].
+ allow-no-explanation: [ ]
+ # Enable to require an explanation of nonzero length after each nolint directive. Default is false.
+ require-explanation: false
+ # Enable to require nolint directives to mention the specific linter being suppressed. Default is false.
+ require-specific: true
+
+ prealloc:
+ # XXX: we don't recommend using this linter before doing performance profiling.
+ # For most programs usage of prealloc will be a premature optimization.
+
+ # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
+ # True by default.
+ simple: true
+ range-loops: true # Report preallocation suggestions on range loops, true by default
+ for-loops: false # Report preallocation suggestions on for loops, false by default
+
+ promlinter:
+ # Promlinter cannot infer all metrics name in static analysis.
+ # Enable strict mode will also include the errors caused by failing to parse the args.
+ strict: false
+ # Please refer to https://github.com/yeya24/promlinter#usage for detailed usage.
+ disabled-linters:
+ - "Help"
+ - "MetricUnits"
+ - "Counter"
+ - "HistogramSummaryReserved"
+ - "MetricTypeInName"
+ - "ReservedChars"
+ - "CamelCase"
+
+ predeclared:
+ # comma-separated list of predeclared identifiers to not report on
+ ignore: ""
+ # include method names and field names (i.e., qualified names) in checks
+ q: false
+ rowserrcheck:
+ packages:
+ - github.com/jmoiron/sqlx
+
+ revive:
+ # see https://github.com/mgechev/revive#available-rules for details.
+ ignore-generated-header: true
+ severity: warning
+ rules:
+ - name: indent-error-flow
+ severity: warning
+ - name: exported
+ severity: warning
+ - name: var-naming
+ arguments: [ [ "OpenIM"] ]
+ # arguments: [ ["ID", "HTTP", "URL", "URI", "API", "APIKey", "Token", "TokenID", "TokenSecret", "TokenKey", "TokenSecret", "JWT", "JWTToken", "JWTTokenID", "JWTTokenSecret", "JWTTokenKey", "JWTTokenSecret", "OAuth", "OAuthToken", "RPC" ] ]
+ - name: atomic
+ - name: line-length-limit
+ severity: error
+ arguments: [200]
+ - name: unhandled-error
+ arguments : ["fmt.Printf", "myFunction"]
+
+ staticcheck:
+ # Select the Go version to target. The default is '1.13'.
+ go: "1.20"
+ # https://staticcheck.io/docs/options#checks
+ checks: [ "all" ]
+
+ stylecheck:
+ # Select the Go version to target. The default is '1.13'.
+ go: "1.20"
+
+ # https://staticcheck.io/docs/options#checks
+ checks: [ "all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022" ]
+ # https://staticcheck.io/docs/options#dot_import_whitelist
+ dot-import-whitelist:
+ - fmt
+ # https://staticcheck.io/docs/options#initialisms
+ initialisms: [ "ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS" ]
+ # https://staticcheck.io/docs/options#http_status_code_whitelist
+ http-status-code-whitelist: [ "200", "400", "404", "500" ]
+
+ tagliatelle:
+ # check the struck tag name case
+ case:
+ # use the struct field name to check the name of the struct tag
+ use-field-name: true
+ rules:
+ # any struct tag type can be used.
+ # support string case: `camel`, `pascal`, `kebab`, `snake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`
+ json: camel
+ yaml: camel
+ xml: camel
+ bson: camel
+ avro: snake
+ mapstructure: kebab
+
+ testpackage:
+ # regexp pattern to skip files
+ skip-regexp: (id|export|internal)_test\.go
+ thelper:
+ # The following configurations enable all checks. It can be omitted because all checks are enabled by default.
+ # You can enable only required checks deleting unnecessary checks.
+ test:
+ first: true
+ name: true
+ begin: true
+ benchmark:
+ first: true
+ name: true
+ begin: true
+ tb:
+ first: true
+ name: true
+ begin: true
+
+ tenv:
+ # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.
+ # By default, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked.
+ all: false
+
+ unparam:
+ # Inspect exported functions, default is false. Set to true if no external program/library imports your code.
+ # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
+ # if it's called for subdir of a project it can't find external interfaces. All text editor integrations
+ # with golangci-lint call it on a directory with the changed file.
+ check-exported: false
+ # unused:
+ # treat code as a program (not a library) and report unused exported identifiers; default is false.
+ # XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
+ # if it's called for subdir of a project it can't find funcs usages. All text editor integrations
+ # with golangci-lint call it on a directory with the changed file.
+ whitespace:
+ multi-if: false # Enforces newlines (or comments) after every multi-line if statement
+ multi-func: false # Enforces newlines (or comments) after every multi-line function signature
+
+ wrapcheck:
+ # An array of strings that specify substrings of signatures to ignore.
+ # If this set, it will override the default set of ignored signatures.
+ # See https://github.com/tomarrell/wrapcheck#configuration for more information.
+ ignoreSigs:
+ - .Errorf(
+ - errors.New(
+ - errors.Unwrap(
+ - .Wrap(
+ - .WrapMsg(
+ - .Wrapf(
+ - .WithMessage(
+ - .WithMessagef(
+ - .WithStack(
+ ignorePackageGlobs:
+ - encoding/*
+ - github.com/pkg/*
+ - github.com/openimsdk/*
+ - github.com/OpenIMSDK/*
+
+ wsl:
+ # If true append is only allowed to be cuddled if appending value is
+ # matching variables, fields or types on line above. Default is true.
+ strict-append: true
+ # Allow calls and assignments to be cuddled as long as the lines have any
+ # matching variables, fields or types. Default is true.
+ allow-assign-and-call: true
+ # Allow assignments to be cuddled with anything. Default is false.
+ allow-assign-and-anything: false
+ # Allow multiline assignments to be cuddled. Default is true.
+ allow-multiline-assign: true
+ # Allow declarations (var) to be cuddled.
+ allow-cuddle-declarations: false
+ # Allow trailing comments in ending of blocks
+ allow-trailing-comment: false
+ # Force newlines in end of case at this limit (0 = never).
+ force-case-trailing-whitespace: 0
+ # Force cuddling of err checks with err var assignment
+ force-err-cuddling: false
+ # Allow leading comments to be separated with empty liens
+ allow-separated-leading-comment: false
+ makezero:
+ # Allow only slices initialized with a length of zero. Default is false.
+ always: false
+
+ # The custom section can be used to define linter plugins to be loaded at runtime. See README doc
+ # for more info.
+ #custom:
+ # Each custom linter should have a unique name.
+ #example:
+ # The path to the plugin *.so. Can be absolute or local. Required for each custom linter
+ #path: /path/to/example.so
+ # The description of the linter. Optional, just for documentation purposes.
+ #description: This is an example usage of a plugin linter.
+ # Intended to point to the repo location of the linter. Optional, just for documentation purposes.
+ #original-url: github.com/golangci/example-linter
+
+linters:
+ # please, do not use `enable-all`: it's deprecated and will be removed soon.
+ # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
+ # enable-all: true
+ disable-all: true
+ enable:
+ - typecheck # Basic type checking
+ - gofmt # Format check
+ - govet # Go's standard linting tool
+ - gosimple # Suggestions for simplifying code
+ - errcheck
+ - decorder
+ - ineffassign
+ - forbidigo
+ - revive
+ - reassign
+ - tparallel
+ - unconvert
+ - fieldalignment
+ - dupl
+ - dupword
+ - errname
+ - gci
+ - exhaustive
+ - gocritic
+ - goprintffuncname
+ - gomnd
+ - goconst
+ - gosec
+ - misspell # Spelling mistakes
+ - staticcheck # Static analysis
+ - unused # Checks for unused code
+ # - goimports # Checks if imports are correctly sorted and formatted
+ - godot # Checks for comment punctuation
+ - bodyclose # Ensures HTTP response body is closed
+ - stylecheck # Style checker for Go code
+ - unused # Checks for unused code
+ - errcheck # Checks for missed error returns
+ fast: true
+
+issues:
+ # List of regexps of issue texts to exclude, empty list by default.
+ # But independently from this option we use default exclude patterns,
+ # it can be disabled by `exclude-use-default: false`. To list all
+ # excluded by default patterns execute `golangci-lint run --help`
+ exclude:
+ - tools/.*
+ - test/.*
+ - components/*
+ - third_party/.*
+
+ # Excluding configuration per-path, per-linter, per-text and per-source
+ exclude-rules:
+ - linters:
+ - revive
+ path: (log/.*)\.go
+
+ - linters:
+ - wrapcheck
+ path: (cmd/.*|pkg/.*)\.go
+
+ - linters:
+ - typecheck
+ #path: (pkg/storage/.*)\.go
+ path: (internal/.*|pkg/.*)\.go
+
+ - path: (cmd/.*|test/.*|tools/.*|internal/pump/pumps/.*)\.go
+ linters:
+ - forbidigo
+
+ - path: (cmd/[a-z]*/.*|store/.*)\.go
+ linters:
+ - dupl
+
+ - linters:
+ - gocritic
+ text: (hugeParam:|rangeValCopy:)
+
+ - path: (cmd/[a-z]*/.*)\.go
+ linters:
+ - lll
+
+ - path: (validator/.*|code/.*|validator/.*|watcher/watcher/.*)
+ linters:
+ - gochecknoinits
+
+ - path: (internal/.*/options|internal/pump|pkg/log/options.go|internal/authzserver|tools/)
+ linters:
+ - tagliatelle
+
+ - path: (pkg/app/.*)\.go
+ linters:
+ - unused
+ - forbidigo
+
+ # Exclude some staticcheck messages
+ - linters:
+ - staticcheck
+ text: "SA9003:"
+
+ # Exclude lll issues for long lines with go:generate
+ - linters:
+ - lll
+ source: "^//go:generate "
+
+ - text: ".*[\u4e00-\u9fa5]+.*"
+ linters:
+ - golint
+ source: "^//.*$"
+
+ # Independently from option `exclude` we use default exclude patterns,
+ # it can be disabled by this option. To list all
+ # excluded by default patterns execute `golangci-lint run --help`.
+ # Default value for this option is true.
+ exclude-use-default: true
+
+ # The default value is false. If set to true exclude and exclude-rules
+ # regular expressions become case sensitive.
+ exclude-case-sensitive: false
+
+ # The list of ids of default excludes to include or disable. By default it's empty.
+ include:
+ - EXC0002 # disable excluding of issues about comments from golint
+
+ # Maximum issues count per one linter. Set to 0 to disable. Default is 50.
+ max-issues-per-linter: 0
+
+ # Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
+ max-same-issues: 0
+
+ # Show only new issues: if there are unstaged changes or untracked files,
+ # only those changes are analyzed, else only changes in HEAD~ are analyzed.
+ # It's a super-useful option for integration of golangci-lint into existing
+ # large codebase. It's not practical to fix all existing issues at the moment
+ # of integration: much better don't allow issues in new code.
+ # Default is false.
+ new: false
+
+ # Show only new issues created after git revision `REV`
+ # new-from-rev: REV
+
+ # Show only new issues created in git patch with set file path.
+ #new-from-patch: path/to/patch/file
+
+ # Fix found issues (if it's supported by the linter)
+ fix: true
+
+severity:
+ # Default value is empty string.
+ # Set the default severity for issues. If severity rules are defined and the issues
+ # do not match or no severity is provided to the rule this will be the default
+ # severity applied. Severities should match the supported severity names of the
+ # selected out format.
+ # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity
+ # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity
+ # - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
+ default-severity: error
+
+ # The default value is false.
+ # If set to true severity-rules regular expressions become case sensitive.
+ case-sensitive: false
+
+ # Default value is empty list.
+ # When a list of severity rules are provided, severity information will be added to lint
+ # issues. Severity rules have the same filtering capability as exclude rules except you
+ # are allowed to specify one matcher per severity rule.
+ # Only affects out formats that support setting severity information.
+ rules:
+ - linters:
+ - dupl
+ severity: info
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 120000
index 0000000..c72a9ce
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1 @@
+CHANGELOG/CHANGELOG.md
\ No newline at end of file
diff --git a/CHANGELOG/CHANGELOG-3.8.md b/CHANGELOG/CHANGELOG-3.8.md
new file mode 100644
index 0000000..e348e56
--- /dev/null
+++ b/CHANGELOG/CHANGELOG-3.8.md
@@ -0,0 +1,70 @@
+## [v3.8.3-patch.6](https://github.com/openimsdk/open-im-server-deploy/releases/tag/v3.8.3-patch.6) (2025-07-23)
+
+### Bug Fixes
+* fix: Add friend DB in notification sender [#3438](https://github.com/openimsdk/open-im-server-deploy/pull/3438)
+* fix: remove update version file workflows have new line in 3.8.3-patch branch. [#3452](https://github.com/openimsdk/open-im-server-deploy/pull/3452)
+* fix: s3 aws init [#3454](https://github.com/openimsdk/open-im-server-deploy/pull/3454)
+* fix: use safe submodule init in workflows in v3.8.3-patch. [#3469](https://github.com/openimsdk/open-im-server-deploy/pull/3469)
+
+**Full Changelog**: [v3.8.3-patch.5...v3.8.3-patch.6](https://github.com/openimsdk/open-im-server-deploy/compare/v3.8.3-patch.5...v3.8.3-patch.6)
+
+## [v3.8.3-patch.5](https://github.com/openimsdk/open-im-server-deploy/releases/tag/v3.8.3-patch.5) (2025-06-10)
+
+### New Features
+* feat: optimize friend and group applications [#3396](https://github.com/openimsdk/open-im-server-deploy/pull/3396)
+
+### Bug Fixes
+* fix: solve unocrrect invite notification [Created [#3219](https://github.com/openimsdk/open-im-server-deploy/pull/3219)
+
+### Builds
+* build: update gomake version in dockerfile.[Patch branch] [#3416](https://github.com/openimsdk/open-im-server-deploy/pull/3416)
+
+**Full Changelog**: [v3.8.3...v3.8.3-patch.5](https://github.com/openimsdk/open-im-server-deploy/compare/v3.8.3...v3.8.3-patch.5)
+
+## [v3.8.3-patch.4](https://github.com/openimsdk/open-im-server-deploy/releases/tag/v3.8.3-patch.4) (2025-03-13)
+
+### Bug Fixes
+* fix: solve unocrrect invite notificationfrom #3213
+
+**Full Changelog**: [v3.8.3-patch.3...v3.8.3-patch.4](https://github.com/openimsdk/open-im-server-deploy/compare/v3.8.3-patch.3...v3.8.3-patch.4)
+
+## [v3.8.3-patch.3](https://github.com/openimsdk/open-im-server-deploy/releases/tag/v3.8.3-patch.3) (2025-03-07)
+
+### New Features
+* feat: optimizing BatchGetIncrementalGroupMember #3180
+
+### Bug Fixes
+* fix: solve uncorrect notification when set group info #3172
+* fix: the sorting is wrong after canceling the administrator in group settings #3185
+* fix: solve uncorrect GroupMember enter group notification type. #3188
+
+### Refactors
+* refactor: change sendNotification to sendMessage to avoid ambiguity regarding message sending behavior. #3173
+
+**Full Changelog**: [v3.8.3-patch.2...v3.8.3-patch.3](https://github.com/openimsdk/open-im-server-deploy/compare/v3.8.3-patch.2...v3.8.3-patch.3)
+
+## [v3.8.3-patch.2](https://github.com/openimsdk/open-im-server-deploy/releases/tag/v3.8.3-patch.2) (2025-02-28)
+
+### Bug Fixes
+* fix: Offline push does not have a badge && Android offline push (#3146) [#3174](https://github.com/openimsdk/open-im-server-deploy/pull/3174)
+
+**Full Changelog**: [v3.8.3-patch.1...v3.8.3-patch.2](https://github.com/openimsdk/open-im-server-deploy/compare/v3.8.3-patch.1...v3.8.3-patch.2)
+
+## [v3.8.3-patch.1](https://github.com/openimsdk/open-im-server-deploy/releases/tag/v3.8.3-patch.1) (2025-02-25)
+
+### New Features
+* feat: add backup volume && optimize log print [Created [#3121](https://github.com/openimsdk/open-im-server-deploy/pull/3121)
+
+### Bug Fixes
+* fix: seq conversion failed without exiting [Created [#3120](https://github.com/openimsdk/open-im-server-deploy/pull/3120)
+* fix: check error in BatchSetTokenMapByUidPid [Created [#3123](https://github.com/openimsdk/open-im-server-deploy/pull/3123)
+* fix: DeleteDoc crash [Created [#3124](https://github.com/openimsdk/open-im-server-deploy/pull/3124)
+* fix: the abnormal message has no sending time, causing the SDK to be abnormal [Created [#3126](https://github.com/openimsdk/open-im-server-deploy/pull/3126)
+* fix: crash caused [#3127](https://github.com/openimsdk/open-im-server-deploy/pull/3127)
+* fix: the user sets the conversation timer cleanup timestamp unit incorrectly [Created [#3128](https://github.com/openimsdk/open-im-server-deploy/pull/3128)
+* fix: seq conversion not reading env in docker environment [Created [#3131](https://github.com/openimsdk/open-im-server-deploy/pull/3131)
+
+### Builds
+* build: improve workflows contents. [Created [#3125](https://github.com/openimsdk/open-im-server-deploy/pull/3125)
+
+**Full Changelog**: [v3.8.3-e-v1.1.5...v3.8.3-patch.1-e-v1.1.5](https://github.com/openimsdk/open-im-server-deploy-enterprise/compare/v3.8.3-e-v1.1.5...v3.8.3-patch.1-e-v1.1.5)
\ No newline at end of file
diff --git a/CHANGELOG/README.md b/CHANGELOG/README.md
new file mode 100644
index 0000000..204194d
--- /dev/null
+++ b/CHANGELOG/README.md
@@ -0,0 +1,4 @@
+# CHANGELOGs
+
+- [CHANGELOG-3.8.md](./CHANGELOG-3.8.md)
+
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..66b1ee7
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,128 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+ overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+ advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+ address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+`security@openim.io`.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.0, available at
+https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct
+enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.
diff --git a/CONTRIBUTING-zh_CN.md b/CONTRIBUTING-zh_CN.md
new file mode 100644
index 0000000..ecb88cb
--- /dev/null
+++ b/CONTRIBUTING-zh_CN.md
@@ -0,0 +1,96 @@
+
+
+# 如何给 OpenIM 贡献代码(提交 Pull Request)
+
+
+ English ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
+本指南将以 [openimsdk/open-im-server-deploy](https://github.com/openimsdk/open-im-server-deploy) 为例,详细说明如何为 OpenIM 项目贡献代码。我们采用“一问题一分支”的策略,确保每个 Issue 都对应一个专门的分支,以便有效管理代码变更。
+
+### 1. Fork 仓库
+前往 [openimsdk/open-im-server-deploy](https://github.com/openimsdk/open-im-server-deploy) GitHub 页面,点击右上角的 "Fork" 按钮,将仓库 Fork 到你的 GitHub 账户下。
+
+### 2. 克隆仓库
+将你 Fork 的仓库克隆到本地:
+```bash
+git clone https://github.com/your-username/open-im-server-deploy.git
+```
+
+### 3. 设置远程上游
+添加原始仓库为远程上游以便跟踪其更新:
+```bash
+git remote add upstream https://github.com/openimsdk/open-im-server-deploy.git
+```
+
+### 4. 创建 Issue
+在原始仓库中创建一个新的 Issue,详细描述你遇到的问题或希望添加
+
+的新功能。
+
+### 5. 创建新分支
+基于主分支创建一个新分支,并使用描述性的名称与 Issue ID,例如:
+```bash
+git checkout -b fix-bug-123
+```
+
+### 6. 提交更改
+在你的本地分支上进行更改后,提交这些更改:
+```bash
+git add .
+git commit -m "Describe your changes in detail"
+```
+
+### 7. 推送分支
+将你的分支推送回你的 GitHub Fork:
+```bash
+git push origin fix-bug-123
+```
+
+### 8. 创建 Pull Request
+在 GitHub 上转到你的 Fork 仓库,点击 "Pull Request" 按钮。确保 PR 描述清楚,并链接到相关的 Issue。
+
+### 9. 签署 CLA
+如果这是你第一次提交 PR,你需要在 PR 的评论中回复:
+```
+I have read the CLA Document and I hereby sign the CLA
+```
+
+### 编程规范
+请参考以下文档以了解关于 Go 语言编程规范的详细信息:
+- [Go 编码规范](https://github.com/openimsdk/open-im-server-deploy/blob/main/docs/contrib/go-code.md)
+- [代码约定](https://github.com/openimsdk/open-im-server-deploy/blob/main/docs/contrib/code-conventions.md)
+
+### 日志规范
+- **禁止使用标准的 `log` 包**。
+- 应使用 `"github.com/openimsdk/tools/log"` 包来打印日志,该包支持多种日志级别:`debug`、`info`、`warn`、`error`。
+- **错误日志应仅在首次调用的函数中打印**,以防止日志重复,并确保错误的上下文清晰。
+
+### 异常及错误处理
+- **禁止使用 `panic`**:程序中不应使用 `panic`,以避免在遇到不可恢复的错误时突然终止。
+- **错误包裹**:使用 `"github.com/openimsdk/tools/errs"` 来包裹错误,保持错误信息的完整性并增加调试便利。
+- **错误传递**:如果函数本身不能处理错误,应将错误返回给调用者,而不是隐藏或忽略这些错误。
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..c7ded50
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,94 @@
+# How to Contribute to OpenIM (Submitting Pull Requests)
+
+
+ English ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
+This guide will use [openimsdk/open-im-server-deploy](https://github.com/openimsdk/open-im-server-deploy) as an example to explain in detail how to contribute code to the OpenIM project. We adopt a "one issue, one branch" strategy to ensure each issue corresponds to a dedicated branch for effective code change management.
+
+### 1. Fork the Repository
+Go to the [openimsdk/open-im-server-deploy](https://github.com/openimsdk/open-im-server-deploy) GitHub page, click the "Fork" button in the upper right corner to fork the repository to your GitHub account.
+
+### 2. Clone the Repository
+Clone the repository you forked to your local machine:
+```bash
+git clone https://github.com/your-username/open-im-server-deploy.git
+```
+
+### 3. Set Upstream Remote
+Add the original repository as a remote upstream to track updates:
+```bash
+git remote add upstream https://github.com/openimsdk/open-im-server-deploy.git
+```
+
+### 4. Create an Issue
+Create a new issue in the original repository detailing the problem you encountered or the new feature you wish to add.
+
+### 5. Create a New Branch
+Create a new branch off the main branch with a descriptive name and Issue ID, for example:
+```bash
+git checkout -b fix-bug-123
+```
+
+### 6. Commit Changes
+After making changes on your local branch, commit these changes:
+```bash
+git add .
+git commit -m "Describe your changes
+
+ in detail"
+```
+
+### 7. Push the Branch
+Push your branch back to your GitHub fork:
+```bash
+git push origin fix-bug-123
+```
+
+### 8. Create a Pull Request
+Go to your fork on GitHub and click the "Pull Request" button. Ensure the PR description is clear and links to the related issue.
+
+### 9. Sign the CLA
+If this is your first time submitting a PR, you will need to reply in the comments of the PR:
+```
+I have read the CLA Document and I hereby sign the CLA
+```
+
+### Programming Standards
+Please refer to the following documents for detailed information on Go language programming standards:
+- [Go Coding Standards](https://github.com/openimsdk/open-im-server-deploy/blob/main/docs/contrib/go-code.md)
+- [Code Conventions](https://github.com/openimsdk/open-im-server-deploy/blob/main/docs/contrib/code-conventions.md)
+
+### Logging Standards
+- **Do not use the standard `log` package**.
+- Use the `"github.com/openimsdk/tools/log"` package for logging, which supports multiple log levels: `debug`, `info`, `warn`, `error`.
+- **Error logs should only be printed in the function where they are first actively called** to prevent log duplication and ensure clear error context.
+
+### Exception and Error Handling
+- **Prohibit the use of `panic`**: The code should not use `panic` to avoid abrupt termination when encountering unrecoverable errors.
+- **Error Wrapping**: Use `"github.com/openimsdk/tools/errs"` to wrap errors, maintaining the integrity of error information and facilitating debugging.
+- **Error Propagation**: If a function cannot handle an error itself, it should return the error to the caller, rather than hiding or ignoring it.
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..8a95b68
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,49 @@
+# Use Go 1.22 Alpine as the base image for building the application
+FROM golang:1.22-alpine AS builder
+
+# Define the base directory for the application as an environment variable
+ENV SERVER_DIR=/openim-server
+
+# Set the working directory inside the container based on the environment variable
+WORKDIR $SERVER_DIR
+
+# Set the Go proxy to improve dependency resolution speed
+# ENV GOPROXY=https://goproxy.io,direct
+
+# Copy all files from the current directory into the container
+COPY . .
+
+RUN go mod download
+
+# Install Mage to use for building the application
+RUN go install github.com/magefile/mage@v1.15.0
+
+# Optionally build your application if needed
+RUN mage build
+
+# Using Alpine Linux with Go environment for the final image
+FROM golang:1.22-alpine
+
+# Install necessary packages, such as bash
+RUN apk add --no-cache bash
+
+# Set the environment and work directory
+ENV SERVER_DIR=/openim-server
+WORKDIR $SERVER_DIR
+
+
+# Copy the compiled binaries and mage from the builder image to the final image
+COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output
+COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config
+COPY --from=builder /go/bin/mage /usr/local/bin/mage
+COPY --from=builder $SERVER_DIR/magefile_windows.go $SERVER_DIR/
+COPY --from=builder $SERVER_DIR/magefile_unix.go $SERVER_DIR/
+COPY --from=builder $SERVER_DIR/magefile.go $SERVER_DIR/
+COPY --from=builder $SERVER_DIR/start-config.yml $SERVER_DIR/
+COPY --from=builder $SERVER_DIR/go.mod $SERVER_DIR/
+COPY --from=builder $SERVER_DIR/go.sum $SERVER_DIR/
+
+RUN go get github.com/openimsdk/gomake@v0.0.15-alpha.1
+
+# Set the command to run when the container starts
+ENTRYPOINT ["sh", "-c", "mage start && tail -f /dev/null"]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/README.md b/README.md
index d2beaf1..3810b7d 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,140 @@
-# open-im-server-deploy
+
+
+
+
+
+
+
+[](https://github.com/openimsdk/open-im-server-deploy/stargazers)
+[](https://github.com/openimsdk/open-im-server-deploy/network/members)
+[](https://app.codecov.io/gh/openimsdk/open-im-server-deploy)
+[](https://goreportcard.com/report/github.com/openimsdk/open-im-server-deploy)
+[](https://pkg.go.dev/git.imall.cloud/openim/open-im-server-deploy)
+[](https://github.com/openimsdk/open-im-server-deploy/blob/main/LICENSE)
+[](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A)
+[](https://www.bestpractices.dev/projects/8045)
+[](https://github.com/openimsdk/open-im-server-deploy/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22)
+[](https://golang.org/)
+[](https://gurubase.io/g/openim)
+
+
+ English ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
+
+
+
+
+## :busts_in_silhouette: Join Our Community
+
+- 💬 [Follow us on Twitter](https://twitter.com/founder_im63606)
+- 🚀 [Join our Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A)
+- :eyes: [Join our WeChat Group](https://openim-1253691595.cos.ap-nanjing.myqcloud.com/WechatIMG20.jpeg)
+
+## Ⓜ️ About OpenIM
+
+Unlike standalone chat applications such as Telegram, Signal, and Rocket.Chat, OpenIM offers an open-source instant messaging solution designed specifically for developers rather than as a directly installable standalone chat app. Comprising OpenIM SDK and OpenIM Server, it provides developers with a complete set of tools and services to integrate instant messaging functions into their applications, including message sending and receiving, user management, and group management. Overall, OpenIM aims to provide developers with the necessary tools and framework to implement efficient instant messaging solutions in their applications.
+
+
+
+## 🚀 Introduction to OpenIMSDK
+
+**OpenIMSDK**, designed for **OpenIMServer**, is an IM SDK created specifically for integration into client applications. It supports various functionalities and modules:
+
+- 🌟 Main Features:
+
+ - 📦 Local Storage
+ - 🔔 Listener Callbacks
+ - 🛡️ API Wrapping
+ - 🌐 Connection Management
+
+- 📚 Main Modules:
+ 1. 🚀 Initialization and Login
+ 2. 👤 User Management
+ 3. 👫 Friends Management
+ 4. 🤖 Group Functions
+ 5. 💬 Session Handling
+
+Built with Golang and supports cross-platform deployment to ensure a consistent integration experience across all platforms.
+
+👉 **[Explore the GO SDK](https://github.com/openimsdk/openim-sdk-core)**
+
+## 🌐 Introduction to OpenIMServer
+
+- **OpenIMServer** features include:
+ - 🌐 Microservices Architecture: Supports cluster mode, including a gateway and multiple rpc services.
+ - 🚀 Diverse Deployment Options: Supports source code, Kubernetes, or Docker deployment.
+ - Massive User Support: Supports large-scale groups with hundreds of thousands, millions of users, and billions of messages.
+
+### Enhanced Business Functions:
+
+- **REST API**: Provides a REST API for business systems to enhance functionality, such as group creation and message pushing through backend interfaces.
+
+- **Webhooks**: Expands business forms through callbacks, sending requests to business servers before or after certain events.
+
+ 
+
+## :rocket: Quick Start
+
+Experience online for iOS/Android/H5/PC/Web:
+
+👉 **[OpenIM Online Demo](https://www.openim.io/en/commercial)**
+
+To facilitate user experience, we offer various deployment solutions. You can choose your preferred 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)**
+
+## System Support
+
+Supports Linux, Windows, Mac systems, and ARM and AMD CPU architectures.
+
+## :link: Links
+
+- **[Developer Manual](https://docs.openim.io/)**
+- **[Changelog](https://github.com/openimsdk/open-im-server-deploy/blob/main/CHANGELOG.md)**
+
+## :writing_hand: How to Contribute
+
+We welcome contributions of any kind! Please make sure to read our [Contributor Documentation](https://github.com/openimsdk/open-im-server-deploy/blob/main/CONTRIBUTING.md) before submitting a Pull Request.
+
+- **[Report a Bug](https://github.com/openimsdk/open-im-server-deploy/issues/new?assignees=&labels=bug&template=bug_report.md&title=)**
+- **[Suggest a Feature](https://github.com/openimsdk/open-im-server-deploy/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)**
+- **[Submit a Pull Request](https://github.com/openimsdk/open-im-server-deploy/pulls)**
+
+Thank you for contributing to building a powerful instant messaging solution!
+
+## :closed_book: License
+
+This software is licensed under the Apache License 2.0
+
+## 🔮 Thanks to our contributors!
+
+
+
+
diff --git a/README_zh_CN.md b/README_zh_CN.md
new file mode 100644
index 0000000..066666f
--- /dev/null
+++ b/README_zh_CN.md
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+[](https://github.com/openimsdk/open-im-server-deploy/stargazers)
+[](https://github.com/openimsdk/open-im-server-deploy/network/members)
+[](https://app.codecov.io/gh/openimsdk/open-im-server-deploy)
+[](https://goreportcard.com/report/github.com/openimsdk/open-im-server-deploy)
+[](https://pkg.go.dev/git.imall.cloud/openim/open-im-server-deploy)
+[](https://github.com/openimsdk/open-im-server-deploy/blob/main/LICENSE)
+[](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A)
+[](https://www.bestpractices.dev/projects/8045)
+[](https://github.com/openimsdk/open-im-server-deploy/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22)
+[](https://golang.org/)
+
+
+ English ·
+ 中文 ·
+ Українська ·
+ Česky ·
+ Magyar ·
+ Español ·
+ فارسی ·
+ Français ·
+ Deutsch ·
+ Polski ·
+ Indonesian ·
+ Suomi ·
+ മലയാളം ·
+ 日本語 ·
+ Nederlands ·
+ Italiano ·
+ Русский ·
+ Português (Brasil) ·
+ Esperanto ·
+ 한국어 ·
+ العربي ·
+ Tiếng Việt ·
+ Dansk ·
+ Ελληνικά ·
+ Türkçe
+
+
+
+
+
+
+## :busts_in_silhouette: 加入我们的社区
+
+- 💬 [关注我们的 Twitter](https://twitter.com/founder_im63606)
+- 🚀 [加入我们的 Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2hljfom5u-9ZuzP3NfEKW~BJKbpLm0Hw)
+- :eyes: [加入我们的微信群](https://openim-1253691595.cos.ap-nanjing.myqcloud.com/WechatIMG20.jpeg)
+
+## Ⓜ️ 关于 OpenIM
+
+与 Telegram、Signal、Rocket.Chat 等独立聊天应用不同,OpenIM 提供了专为开发者设计的开源即时通讯解决方案,而不是直接安装使用的独立聊天应用。OpenIM 由 OpenIM SDK 和 OpenIM Server 两大部分组成,为开发者提供了一整套集成即时通讯功能的工具和服务,包括消息发送接收、用户管理和群组管理等。总体来说,OpenIM 旨在为开发者提供必要的工具和框架,帮助他们在自己的应用中实现高效的即时通讯解决方案。
+
+
+
+## 🚀 OpenIMSDK 介绍
+
+**OpenIMSDK** 是为 **OpenIMServer** 设计的 IM SDK,专为集成到客户端应用而生。它支持多种功能和模块:
+
+- 🌟 主要功能:
+
+ - 📦 本地存储
+ - 🔔 监听器回调
+ - 🛡️ API 封装
+ - 🌐 连接管理
+
+- 📚 主要模块:
+ 1. 🚀 初始化及登录
+ 2. 👤 用户管理
+ 3. 👫 好友管理
+ 4. 🤖 群组功能
+ 5. 💬 会话处理
+
+它使用 Golang 构建,并支持跨平台部署,确保在所有平台上提供一致的接入体验。
+
+👉 **[探索 GO SDK](https://github.com/openimsdk/openim-sdk-core)**
+
+## 🌐 OpenIMServer 介绍
+
+- **OpenIMServer** 的特点包括:
+ - 🌐 微服务架构:支持集群模式,包括网关(gateway)和多个 rpc 服务。
+ - 🚀 多样的部署方式:支持源代码、Kubernetes 或 Docker 部署。
+ - 海量用户支持:支持十万级超大群组,千万级用户和百亿级消息。
+
+### 增强的业务功能:
+
+- **REST API**:为业务系统提供 REST API,增加群组创建、消息推送等后台接口功能。
+
+- **Webhooks**:通过事件前后的回调,向业务服务器发送请求,扩展更多的业务形态。
+
+ 
+
+## :rocket: 快速入门
+
+在线体验 iOS/Android/H5/PC/Web:
+
+👉 **[OpenIM 在线演示](https://www.openim.io/en/commercial)**
+
+为了便于用户体验,我们提供了多种部署解决方案,您可以根据以下列表选择适合您的部署方式:
+
+- **[源代码部署指南](https://docs.openim.io/guides/gettingStarted/imSourceCodeDeployment)**
+- **[Docker 部署指南](https://docs.openim.io/guides/gettingStarted/dockerCompose)**
+
+## 系统支持
+
+支持 Linux、Windows、Mac 系统以及 ARM 和 AMD CPU 架构。
+
+## :link: 相关链接
+
+- **[开发手册](https://docs.openim.io/)**
+- **[更新日志](https://github.com/openimsdk/open-im-server-deploy/blob/main/CHANGELOG.md)**
+
+## :writing_hand: 如何贡献
+
+我们欢迎任何形式的贡献!在提交 Pull Request 之前,请确保阅读我们的[贡献者文档](https://github.com/openimsdk/open-im-server-deploy/blob/main/CONTRIBUTING.md)
+
+- **[报告 Bug](https://github.com/openimsdk/open-im-server-deploy/issues/new?assignees=&labels=bug&template=bug_report.md&title=)**
+- **[提出新特性](https://github.com/openimsdk/open-im-server-deploy/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)**
+- **[提交 Pull Request](https://github.com/openimsdk/open-im-server-deploy/pulls)**
+
+感谢您的贡献,一起来打造强大的即时通讯解决方案!
+
+## :closed_book: 开源许可证 License
+
+This software is licensed under the Apache License 2.0
+
+## 🔮 Thanks to our contributors!
+
+
+
+
diff --git a/assets/README.md b/assets/README.md
new file mode 100644
index 0000000..96e9a78
--- /dev/null
+++ b/assets/README.md
@@ -0,0 +1,32 @@
+# `/assets`
+
+The `/assets` directory in the OpenIM repository contains various assets such as images, logos, and animated GIFs. These assets serve different purposes and contribute to the functionality and aesthetics of the OpenIM project.
+
+## Directory Structure:
+
+```bash
+assets/
+├── README.md # Documentation for the assets directory
+├── images # Directory holding images related to OpenIM
+│ ├── architecture.png # Image depicting the architecture of OpenIM
+│ └── mvc.png # Image illustrating the Model-View-Controller (MVC) pattern
+├── intive-slack.png # Image displaying the Intive Slack logo
+├── logo # Directory containing various logo variations for OpenIM
+│ ├── openim-logo-black.png # OpenIM logo with a black background
+│ ├── openim-logo-blue.png # OpenIM logo with a blue background
+│ ├── openim-logo-green.png # OpenIM logo with a green background
+│ ├── openim-logo-purple.png # OpenIM logo with a purple background
+│ ├── openim-logo-white.png # OpenIM logo with a white background
+│ ├── openim-logo-yellow.png # OpenIM logo with a yellow background
+│ └── openim-logo.png # OpenIM logo with a transparent background
+└── logo-gif # Directory containing animated GIF versions of the OpenIM logo
+ └── openim-log.gif # Animated OpenIM logo with a transparent background
+```
+
+## Copyright Notice:
+
+The OpenIM logo, including its variations and animated versions, displayed in this repository [OpenIM](https://github.com/openimsdk/open-im-server-deploy) under the `/assets/logo` and `/assets/logo-gif` directories, are protected by copyright laws.
+
+The logo design is credited to @Xx(席欣).
+
+Please respect the intellectual property rights and refrain from unauthorized use and distribution of these assets.
\ No newline at end of file
diff --git a/assets/colors.md b/assets/colors.md
new file mode 100644
index 0000000..cf87777
--- /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/assets/demo/README.md b/assets/demo/README.md
new file mode 100644
index 0000000..ce4cc0f
--- /dev/null
+++ b/assets/demo/README.md
@@ -0,0 +1,14 @@
+## :star2: Why OpenIM
+
+**🔍 Function screenshot display**
+
+
+
+
+| multiple message | Efficient meetings |
+| :---------------------------------------: | :---------------------------------------------: |
+|  |  |
+| **One-to-one and group chats** | **Special features - Custom messages** |
+|  |  |
+
+
diff --git a/assets/demo/efficient-meetings.png b/assets/demo/efficient-meetings.png
new file mode 100644
index 0000000000000000000000000000000000000000..46b009dc375119d57e7a55f3bab921b0b572ba47
GIT binary patch
literal 1442977
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