Full Code of openimsdk/open-im-server for AI

main d16a617ba8ff cached
667 files
2.7 MB
739.3k tokens
3403 symbols
1 requests
Download .txt
Showing preview only (2,942K chars total). Download the full file or copy to clipboard to get everything.
Repository: openimsdk/open-im-server
Branch: main
Commit: d16a617ba8ff
Files: 667
Total size: 2.7 MB

Directory structure:
gitextract_q8p9a5l9/

├── .dockerignore
├── .gitattributes
├── .github/
│   ├── .codecov.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   ├── config.yml
│   │   ├── deployment.yml
│   │   ├── documentation.md
│   │   ├── feature-request.yml
│   │   ├── other.yml
│   │   └── rfc.md
│   ├── sync-release.yml
│   └── workflows/
│       ├── auto-assign-issue.yml
│       ├── auto-invite-comment.yml
│       ├── changelog.yml
│       ├── cla-assistant.yml
│       ├── cleanup-after-milestone-prs-merged.yml
│       ├── codeql-analysis.yml
│       ├── comment-check.yml
│       ├── docker-build-and-release-services-images.yml
│       ├── go-build-test.yml
│       ├── help-comment-issue.yml
│       ├── issue-translator.yml
│       ├── merge-from-milestone.yml
│       ├── publish-docker-image.yml
│       ├── remove-unused-labels.yml
│       ├── reopen-issue.yml
│       ├── update-version-file-on-release.yml
│       └── user-first-interaction.yml
├── .gitignore
├── .golangci.yml
├── CHANGELOG/
│   ├── CHANGELOG-3.8.md
│   └── README.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING-zh_CN.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── README_zh_CN.md
├── assets/
│   ├── README.md
│   ├── colors.md
│   ├── demo/
│   │   └── README.md
│   ├── logo/
│   │   └── LICENSE
│   └── logo-gif/
│       └── LICENSE
├── bootstrap.bat
├── bootstrap.sh
├── build/
│   ├── README.md
│   ├── goreleaser.yaml
│   └── images/
│       ├── Dockerfile
│       ├── openim-api/
│       │   └── Dockerfile
│       ├── openim-crontask/
│       │   └── Dockerfile
│       ├── openim-msggateway/
│       │   └── Dockerfile
│       ├── openim-msgtransfer/
│       │   └── Dockerfile
│       ├── openim-push/
│       │   └── Dockerfile
│       ├── openim-rpc-auth/
│       │   └── Dockerfile
│       ├── openim-rpc-conversation/
│       │   └── Dockerfile
│       ├── openim-rpc-friend/
│       │   └── Dockerfile
│       ├── openim-rpc-group/
│       │   └── Dockerfile
│       ├── openim-rpc-msg/
│       │   └── Dockerfile
│       ├── openim-rpc-third/
│       │   └── Dockerfile
│       ├── openim-rpc-user/
│       │   └── Dockerfile
│       └── openim-tools/
│           └── component/
│               └── Dockerfile
├── cmd/
│   ├── main.go
│   ├── openim-api/
│   │   └── main.go
│   ├── openim-cmdutils/
│   │   └── main.go
│   ├── openim-crontask/
│   │   └── main.go
│   ├── openim-msggateway/
│   │   └── main.go
│   ├── openim-msgtransfer/
│   │   └── main.go
│   ├── openim-push/
│   │   └── main.go
│   └── openim-rpc/
│       ├── openim-rpc-auth/
│       │   └── main.go
│       ├── openim-rpc-conversation/
│       │   └── main.go
│       ├── openim-rpc-friend/
│       │   └── main.go
│       ├── openim-rpc-group/
│       │   └── main.go
│       ├── openim-rpc-msg/
│       │   └── main.go
│       ├── openim-rpc-third/
│       │   └── main.go
│       └── openim-rpc-user/
│           └── main.go
├── config/
│   ├── README.md
│   ├── README_zh_CN.md
│   ├── alertmanager.yml
│   ├── discovery.yml
│   ├── email.tmpl
│   ├── grafana-template/
│   │   └── Demo.json
│   ├── instance-down-rules.yml
│   ├── kafka.yml
│   ├── local-cache.yml
│   ├── log.yml
│   ├── minio.yml
│   ├── mongodb.yml
│   ├── notification.yml
│   ├── openim-api.yml
│   ├── openim-crontask.yml
│   ├── openim-msggateway.yml
│   ├── openim-msgtransfer.yml
│   ├── openim-push.yml
│   ├── openim-rpc-auth.yml
│   ├── openim-rpc-conversation.yml
│   ├── openim-rpc-friend.yml
│   ├── openim-rpc-group.yml
│   ├── openim-rpc-msg.yml
│   ├── openim-rpc-third.yml
│   ├── openim-rpc-user.yml
│   ├── prometheus.yml
│   ├── redis.yml
│   ├── share.yml
│   └── webhooks.yml
├── deployments/
│   ├── Readme.md
│   └── deploy/
│       ├── clusterRole.yml
│       ├── ingress.yml
│       ├── kafka-secret.yml
│       ├── kafka-service.yml
│       ├── kafka-statefulset.yml
│       ├── minio-secret.yml
│       ├── minio-service.yml
│       ├── minio-statefulset.yml
│       ├── mongo-secret.yml
│       ├── mongo-service.yml
│       ├── mongo-statefulset.yml
│       ├── openim-api-deployment.yml
│       ├── openim-api-service.yml
│       ├── openim-config.yml
│       ├── openim-crontask-deployment.yml
│       ├── openim-msggateway-deployment.yml
│       ├── openim-msggateway-service.yml
│       ├── openim-msgtransfer-deployment.yml
│       ├── openim-msgtransfer-service.yml
│       ├── openim-push-deployment.yml
│       ├── openim-push-service.yml
│       ├── openim-rpc-auth-deployment.yml
│       ├── openim-rpc-auth-service.yml
│       ├── openim-rpc-conversation-deployment.yml
│       ├── openim-rpc-conversation-service.yml
│       ├── openim-rpc-friend-deployment.yml
│       ├── openim-rpc-friend-service.yml
│       ├── openim-rpc-group-deployment.yml
│       ├── openim-rpc-group-service.yml
│       ├── openim-rpc-msg-deployment.yml
│       ├── openim-rpc-msg-service.yml
│       ├── openim-rpc-third-deployment.yml
│       ├── openim-rpc-third-service.yml
│       ├── openim-rpc-user-deployment.yml
│       ├── openim-rpc-user-service.yml
│       ├── redis-secret.yml
│       ├── redis-service.yml
│       └── redis-statefulset.yml
├── docker-compose.yml
├── docs/
│   ├── .generated_docs
│   ├── CODEOWNERS
│   ├── README.md
│   ├── contrib/
│   │   ├── README.md
│   │   ├── api.md
│   │   ├── bash-log.md
│   │   ├── cicd-actions.md
│   │   ├── code-conventions.md
│   │   ├── commit.md
│   │   ├── development.md
│   │   ├── directory.md
│   │   ├── environment.md
│   │   ├── error-code.md
│   │   ├── git-workflow.md
│   │   ├── gitcherry-pick.md
│   │   ├── github-workflow.md
│   │   ├── go-code.md
│   │   ├── go-code1.md
│   │   ├── go-doc.md
│   │   ├── images.md
│   │   ├── init-config.md
│   │   ├── install-docker.md
│   │   ├── install-openim-linux-system.md
│   │   ├── kafka.md
│   │   ├── linux-development.md
│   │   ├── local-actions.md
│   │   ├── logging.md
│   │   ├── mac-developer-deployment-guide.md
│   │   ├── offline-deployment.md
│   │   ├── prometheus-grafana.md
│   │   ├── protoc-tools.md
│   │   ├── release.md
│   │   ├── test.md
│   │   ├── util-go.md
│   │   ├── util-makefile.md
│   │   ├── util-scripts.md
│   │   └── version.md
│   ├── contributing/
│   │   ├── CONTRIBUTING-JP.md
│   │   └── CONTRIBUTING-PL.md
│   └── readme/
│       ├── README_cs.md
│       ├── README_da.md
│       ├── README_el.md
│       ├── README_es.md
│       ├── README_fa.md
│       ├── README_fr.md
│       ├── README_hu.md
│       ├── README_ja.md
│       ├── README_ko.md
│       ├── README_tr.md
│       ├── README_uk.md
│       └── README_vi.md
├── go.mod
├── go.sum
├── install.sh
├── internal/
│   ├── api/
│   │   ├── auth.go
│   │   ├── config_manager.go
│   │   ├── conversation.go
│   │   ├── custom_validator.go
│   │   ├── friend.go
│   │   ├── group.go
│   │   ├── init.go
│   │   ├── jssdk/
│   │   │   ├── jssdk.go
│   │   │   ├── sort.go
│   │   │   └── tools.go
│   │   ├── msg.go
│   │   ├── prometheus_discovery.go
│   │   ├── ratelimit.go
│   │   ├── router.go
│   │   ├── third.go
│   │   └── user.go
│   ├── msggateway/
│   │   ├── callback.go
│   │   ├── client.go
│   │   ├── client_conn.go
│   │   ├── compressor.go
│   │   ├── compressor_test.go
│   │   ├── constant.go
│   │   ├── context.go
│   │   ├── encoder.go
│   │   ├── http_error.go
│   │   ├── hub_server.go
│   │   ├── init.go
│   │   ├── message_handler.go
│   │   ├── online.go
│   │   ├── options.go
│   │   ├── subscription.go
│   │   ├── user_map.go
│   │   └── ws_server.go
│   ├── msgtransfer/
│   │   ├── callback.go
│   │   ├── init.go
│   │   ├── online_history_msg_handler.go
│   │   └── online_msg_to_mongo_handler.go
│   ├── push/
│   │   ├── callback.go
│   │   ├── offlinepush/
│   │   │   ├── dummy/
│   │   │   │   └── push.go
│   │   │   ├── fcm/
│   │   │   │   └── push.go
│   │   │   ├── getui/
│   │   │   │   ├── body.go
│   │   │   │   └── push.go
│   │   │   ├── jpush/
│   │   │   │   ├── body/
│   │   │   │   │   ├── audience.go
│   │   │   │   │   ├── message.go
│   │   │   │   │   ├── notification.go
│   │   │   │   │   ├── options.go
│   │   │   │   │   ├── platform.go
│   │   │   │   │   └── pushobj.go
│   │   │   │   └── push.go
│   │   │   ├── offlinepusher.go
│   │   │   └── options/
│   │   │       └── options.go
│   │   ├── offlinepush_handler.go
│   │   ├── onlinepusher.go
│   │   ├── push.go
│   │   └── push_handler.go
│   ├── rpc/
│   │   ├── auth/
│   │   │   └── auth.go
│   │   ├── conversation/
│   │   │   ├── callback.go
│   │   │   ├── conversation.go
│   │   │   ├── db_map.go
│   │   │   ├── notification.go
│   │   │   └── sync.go
│   │   ├── group/
│   │   │   ├── cache.go
│   │   │   ├── callback.go
│   │   │   ├── convert.go
│   │   │   ├── db_map.go
│   │   │   ├── fill.go
│   │   │   ├── group.go
│   │   │   ├── notification.go
│   │   │   ├── statistics.go
│   │   │   └── sync.go
│   │   ├── incrversion/
│   │   │   ├── batch_option.go
│   │   │   └── option.go
│   │   ├── msg/
│   │   │   ├── as_read.go
│   │   │   ├── callback.go
│   │   │   ├── clear.go
│   │   │   ├── delete.go
│   │   │   ├── filter.go
│   │   │   ├── msg_status.go
│   │   │   ├── notification.go
│   │   │   ├── revoke.go
│   │   │   ├── send.go
│   │   │   ├── seq.go
│   │   │   ├── server.go
│   │   │   ├── statistics.go
│   │   │   ├── sync_msg.go
│   │   │   ├── utils.go
│   │   │   └── verify.go
│   │   ├── relation/
│   │   │   ├── black.go
│   │   │   ├── callback.go
│   │   │   ├── friend.go
│   │   │   ├── notification.go
│   │   │   └── sync.go
│   │   ├── third/
│   │   │   ├── log.go
│   │   │   ├── s3.go
│   │   │   ├── third.go
│   │   │   └── tool.go
│   │   └── user/
│   │       ├── callback.go
│   │       ├── config.go
│   │       ├── notification.go
│   │       ├── online.go
│   │       ├── statistics.go
│   │       └── user.go
│   └── tools/
│       └── cron/
│           ├── cron_task.go
│           ├── cron_test.go
│           ├── dist_look.go
│           ├── msg.go
│           ├── s3.go
│           └── user_msg.go
├── magefile.go
├── magefile_unix.go
├── magefile_windows.go
├── pkg/
│   ├── apistruct/
│   │   ├── config_manager.go
│   │   ├── doc.go
│   │   ├── manage.go
│   │   ├── msg.go
│   │   └── public.go
│   ├── authverify/
│   │   ├── doc.go
│   │   └── token.go
│   ├── callbackstruct/
│   │   ├── common.go
│   │   ├── constant.go
│   │   ├── conversation.go
│   │   ├── doc.go
│   │   ├── friend.go
│   │   ├── group.go
│   │   ├── message.go
│   │   ├── msg_gateway.go
│   │   ├── push.go
│   │   ├── revoke.go
│   │   └── user.go
│   ├── common/
│   │   ├── cmd/
│   │   │   ├── api.go
│   │   │   ├── auth.go
│   │   │   ├── conversation.go
│   │   │   ├── cron_task.go
│   │   │   ├── doc.go
│   │   │   ├── friend.go
│   │   │   ├── group.go
│   │   │   ├── msg.go
│   │   │   ├── msg_gateway.go
│   │   │   ├── msg_gateway_test.go
│   │   │   ├── msg_transfer.go
│   │   │   ├── msg_utils.go
│   │   │   ├── push.go
│   │   │   ├── root.go
│   │   │   ├── third.go
│   │   │   └── user.go
│   │   ├── config/
│   │   │   ├── config.go
│   │   │   ├── constant.go
│   │   │   ├── doc.go
│   │   │   ├── env.go
│   │   │   ├── global.go
│   │   │   ├── load_config.go
│   │   │   ├── load_config_test.go
│   │   │   └── parse.go
│   │   ├── convert/
│   │   │   ├── auth.go
│   │   │   ├── black.go
│   │   │   ├── conversation.go
│   │   │   ├── doc.go
│   │   │   ├── friend.go
│   │   │   ├── group.go
│   │   │   ├── msg.go
│   │   │   ├── user.go
│   │   │   └── user_test.go
│   │   ├── discovery/
│   │   │   ├── direct/
│   │   │   │   ├── direct_resolver.go
│   │   │   │   ├── directconn.go
│   │   │   │   └── doc.go
│   │   │   ├── discoveryregister.go
│   │   │   ├── discoveryregister_test.go
│   │   │   ├── doc.go
│   │   │   ├── etcd/
│   │   │   │   ├── config_manager.go
│   │   │   │   └── const.go
│   │   │   └── kubernetes/
│   │   │       ├── doc.go
│   │   │       └── kubernetes.go
│   │   ├── ginprometheus/
│   │   │   ├── doc.go
│   │   │   └── ginprometheus.go
│   │   ├── prommetrics/
│   │   │   ├── api.go
│   │   │   ├── grpc_auth.go
│   │   │   ├── grpc_msg.go
│   │   │   ├── grpc_msggateway.go
│   │   │   ├── grpc_push.go
│   │   │   ├── grpc_user.go
│   │   │   ├── prommetrics.go
│   │   │   ├── prommetrics_test.go
│   │   │   ├── rpc.go
│   │   │   └── transfer.go
│   │   ├── servererrs/
│   │   │   ├── code.go
│   │   │   ├── doc.go
│   │   │   ├── predefine.go
│   │   │   └── relation.go
│   │   ├── startrpc/
│   │   │   ├── circuitbreaker.go
│   │   │   ├── mw.go
│   │   │   ├── ratelimit.go
│   │   │   ├── start.go
│   │   │   └── tools.go
│   │   ├── storage/
│   │   │   ├── cache/
│   │   │   │   ├── batch_handler.go
│   │   │   │   ├── black.go
│   │   │   │   ├── cachekey/
│   │   │   │   │   ├── black.go
│   │   │   │   │   ├── client_config.go
│   │   │   │   │   ├── conversation.go
│   │   │   │   │   ├── doc.go
│   │   │   │   │   ├── friend.go
│   │   │   │   │   ├── group.go
│   │   │   │   │   ├── msg.go
│   │   │   │   │   ├── online.go
│   │   │   │   │   ├── s3.go
│   │   │   │   │   ├── seq.go
│   │   │   │   │   ├── third.go
│   │   │   │   │   ├── token.go
│   │   │   │   │   └── user.go
│   │   │   │   ├── client_config.go
│   │   │   │   ├── conversation.go
│   │   │   │   ├── doc.go
│   │   │   │   ├── friend.go
│   │   │   │   ├── group.go
│   │   │   │   ├── mcache/
│   │   │   │   │   ├── minio.go
│   │   │   │   │   ├── msg_cache.go
│   │   │   │   │   ├── online.go
│   │   │   │   │   ├── seq_conversation.go
│   │   │   │   │   ├── third.go
│   │   │   │   │   ├── token.go
│   │   │   │   │   └── tools.go
│   │   │   │   ├── msg.go
│   │   │   │   ├── online.go
│   │   │   │   ├── redis/
│   │   │   │   │   ├── batch.go
│   │   │   │   │   ├── batch_handler.go
│   │   │   │   │   ├── batch_test.go
│   │   │   │   │   ├── black.go
│   │   │   │   │   ├── client_config.go
│   │   │   │   │   ├── conversation.go
│   │   │   │   │   ├── friend.go
│   │   │   │   │   ├── group.go
│   │   │   │   │   ├── lua_script.go
│   │   │   │   │   ├── lua_script_test.go
│   │   │   │   │   ├── minio.go
│   │   │   │   │   ├── msg.go
│   │   │   │   │   ├── online.go
│   │   │   │   │   ├── online_test.go
│   │   │   │   │   ├── redis_shard_manager.go
│   │   │   │   │   ├── s3.go
│   │   │   │   │   ├── seq_conversation.go
│   │   │   │   │   ├── seq_conversation_test.go
│   │   │   │   │   ├── seq_user.go
│   │   │   │   │   ├── seq_user_test.go
│   │   │   │   │   ├── third.go
│   │   │   │   │   ├── token.go
│   │   │   │   │   └── user.go
│   │   │   │   ├── s3.go
│   │   │   │   ├── seq_conversation.go
│   │   │   │   ├── seq_user.go
│   │   │   │   ├── third.go
│   │   │   │   ├── token.go
│   │   │   │   └── user.go
│   │   │   ├── common/
│   │   │   │   └── types.go
│   │   │   ├── controller/
│   │   │   │   ├── auth.go
│   │   │   │   ├── black.go
│   │   │   │   ├── client_config.go
│   │   │   │   ├── conversation.go
│   │   │   │   ├── doc.go
│   │   │   │   ├── friend.go
│   │   │   │   ├── group.go
│   │   │   │   ├── msg.go
│   │   │   │   ├── msg_transfer.go
│   │   │   │   ├── push.go
│   │   │   │   ├── s3.go
│   │   │   │   ├── third.go
│   │   │   │   └── user.go
│   │   │   ├── database/
│   │   │   │   ├── black.go
│   │   │   │   ├── cache.go
│   │   │   │   ├── client_config.go
│   │   │   │   ├── conversation.go
│   │   │   │   ├── doc.go
│   │   │   │   ├── friend.go
│   │   │   │   ├── friend_request.go
│   │   │   │   ├── group.go
│   │   │   │   ├── group_member.go
│   │   │   │   ├── group_request.go
│   │   │   │   ├── log.go
│   │   │   │   ├── mgo/
│   │   │   │   │   ├── black.go
│   │   │   │   │   ├── cache.go
│   │   │   │   │   ├── cache_test.go
│   │   │   │   │   ├── client_config.go
│   │   │   │   │   ├── conversation.go
│   │   │   │   │   ├── doc.go
│   │   │   │   │   ├── friend.go
│   │   │   │   │   ├── friend_request.go
│   │   │   │   │   ├── group.go
│   │   │   │   │   ├── group_member.go
│   │   │   │   │   ├── group_request.go
│   │   │   │   │   ├── helpers.go
│   │   │   │   │   ├── log.go
│   │   │   │   │   ├── msg.go
│   │   │   │   │   ├── msg_test.go
│   │   │   │   │   ├── object.go
│   │   │   │   │   ├── seq_conversation.go
│   │   │   │   │   ├── seq_conversation_test.go
│   │   │   │   │   ├── seq_user.go
│   │   │   │   │   ├── user.go
│   │   │   │   │   ├── version_log.go
│   │   │   │   │   └── version_test.go
│   │   │   │   ├── msg.go
│   │   │   │   ├── name.go
│   │   │   │   ├── object.go
│   │   │   │   ├── seq.go
│   │   │   │   ├── seq_user.go
│   │   │   │   ├── user.go
│   │   │   │   └── version_log.go
│   │   │   ├── kafka/
│   │   │   │   ├── config.go
│   │   │   │   ├── consumer_group.go
│   │   │   │   ├── producer.go
│   │   │   │   ├── sarama.go
│   │   │   │   ├── tls.go
│   │   │   │   ├── util.go
│   │   │   │   └── verify.go
│   │   │   ├── model/
│   │   │   │   ├── application.go
│   │   │   │   ├── black.go
│   │   │   │   ├── cache.go
│   │   │   │   ├── client_config.go
│   │   │   │   ├── conversation.go
│   │   │   │   ├── doc.go
│   │   │   │   ├── friend.go
│   │   │   │   ├── friend_request.go
│   │   │   │   ├── group.go
│   │   │   │   ├── group_member.go
│   │   │   │   ├── group_request.go
│   │   │   │   ├── log.go
│   │   │   │   ├── msg.go
│   │   │   │   ├── object.go
│   │   │   │   ├── seq.go
│   │   │   │   ├── seq_user.go
│   │   │   │   ├── subscribe.go
│   │   │   │   ├── user.go
│   │   │   │   └── version_log.go
│   │   │   └── versionctx/
│   │   │       ├── rpc.go
│   │   │       └── version.go
│   │   └── webhook/
│   │       ├── condition.go
│   │       ├── doc.go
│   │       ├── http_client.go
│   │       └── http_client_test.go
│   ├── dbbuild/
│   │   ├── builder.go
│   │   ├── microservices.go
│   │   └── standalone.go
│   ├── localcache/
│   │   ├── cache.go
│   │   ├── cache_test.go
│   │   ├── doc.go
│   │   ├── init.go
│   │   ├── link/
│   │   │   ├── doc.go
│   │   │   ├── link.go
│   │   │   └── link_test.go
│   │   ├── lru/
│   │   │   ├── doc.go
│   │   │   ├── lru.go
│   │   │   ├── lru_expiration.go
│   │   │   ├── lru_lazy.go
│   │   │   ├── lru_lazy_test.go
│   │   │   └── lru_slot.go
│   │   ├── option.go
│   │   └── tool.go
│   ├── mqbuild/
│   │   └── builder.go
│   ├── msgprocessor/
│   │   ├── conversation.go
│   │   ├── doc.go
│   │   └── options.go
│   ├── notification/
│   │   ├── common_user/
│   │   │   └── common.go
│   │   ├── grouphash/
│   │   │   └── grouphash.go
│   │   └── msg.go
│   ├── rpccache/
│   │   ├── auth.go
│   │   ├── common.go
│   │   ├── conversation.go
│   │   ├── doc.go
│   │   ├── friend.go
│   │   ├── group.go
│   │   ├── online.go
│   │   ├── subscriber.go
│   │   └── user.go
│   ├── rpcli/
│   │   ├── auth.go
│   │   ├── conversation.go
│   │   ├── group.go
│   │   ├── msg.go
│   │   ├── msggateway.go
│   │   ├── push.go
│   │   ├── relation.go
│   │   ├── rtc.go
│   │   ├── third.go
│   │   ├── tool.go
│   │   └── user.go
│   ├── statistics/
│   │   ├── doc.go
│   │   └── statistics.go
│   ├── tools/
│   │   └── batcher/
│   │       ├── batcher.go
│   │       └── batcher_test.go
│   └── util/
│       ├── conversationutil/
│       │   ├── conversationutil.go
│       │   └── doc.go
│       ├── hashutil/
│       │   └── id.go
│       └── useronline/
│           └── split.go
├── scripts/
│   └── template/
│       ├── LICENSE
│       ├── LICENSE_TEMPLATES
│       ├── boilerplate.txt
│       ├── footer.md.tmpl
│       ├── head.md.tmpl
│       └── project_README.md
├── start-config.yml
├── test/
│   ├── e2e/
│   │   ├── README.md
│   │   ├── api/
│   │   │   ├── token/
│   │   │   │   └── token.go
│   │   │   └── user/
│   │   │       ├── curd.go
│   │   │       └── user.go
│   │   ├── conformance/
│   │   │   └── .keep
│   │   ├── e2e.go
│   │   ├── e2e_test.go
│   │   ├── framework/
│   │   │   ├── config/
│   │   │   │   ├── config.go
│   │   │   │   └── config_test.go
│   │   │   ├── ginkgowrapper/
│   │   │   │   ├── .keep
│   │   │   │   ├── ginkgowrapper.go
│   │   │   │   └── ginkgowrapper_test.go
│   │   │   └── helpers/
│   │   │       ├── .keep
│   │   │       └── chat/
│   │   │           └── chat.go
│   │   ├── page/
│   │   │   ├── chat_page.go
│   │   │   └── login_page.go
│   │   ├── performance/
│   │   │   └── .keep
│   │   ├── rpc/
│   │   │   ├── auth/
│   │   │   │   └── .keep
│   │   │   ├── conversation/
│   │   │   │   └── .keep
│   │   │   ├── friend/
│   │   │   │   └── .keep
│   │   │   ├── group/
│   │   │   │   └── .keep
│   │   │   └── message/
│   │   │       └── .keep
│   │   ├── scalability/
│   │   │   └── .keep
│   │   ├── upgrade/
│   │   │   └── .keep
│   │   └── web/
│   │       └── Readme.md
│   ├── jwt/
│   │   └── main.go
│   ├── readme
│   ├── stress-test/
│   │   ├── README.md
│   │   └── main.go
│   ├── stress-test-v2/
│   │   ├── README.md
│   │   └── main.go
│   ├── testdata/
│   │   ├── README.md
│   │   ├── db/
│   │   │   ├── messages.json
│   │   │   └── users.json
│   │   ├── requests/
│   │   │   ├── login.json
│   │   │   ├── register.json
│   │   │   └── send-message.json
│   │   └── responses/
│   │       ├── login.json
│   │       ├── register.json
│   │       └── sendMessage.json
│   └── webhook/
│       └── msgmodify/
│           └── main.go
├── tools/
│   ├── README.md
│   ├── changelog/
│   │   └── changelog.go
│   ├── check-component/
│   │   └── main.go
│   ├── check-free-memory/
│   │   └── main.go
│   ├── imctl/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   └── main.go
│   ├── infra/
│   │   └── main.go
│   ├── ncpu/
│   │   ├── README.md
│   │   ├── main.go
│   │   └── main_test.go
│   ├── s3/
│   │   ├── README.md
│   │   ├── internal/
│   │   │   └── conversion.go
│   │   └── main.go
│   ├── seq/
│   │   ├── internal/
│   │   │   └── seq.go
│   │   └── main.go
│   ├── stress-test-v2/
│   │   └── main.go
│   ├── url2im/
│   │   ├── main.go
│   │   └── pkg/
│   │       ├── api.go
│   │       ├── buffer.go
│   │       ├── config.go
│   │       ├── http.go
│   │       ├── manage.go
│   │       ├── md5.go
│   │       └── progress.go
│   ├── versionchecker/
│   │   └── main.go
│   └── yamlfmt/
│       ├── main.go
│       └── main_test.go
└── version/
    ├── version
    └── version.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
# 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/


================================================
FILE: .gitattributes
================================================
*.sh text eol=lf


================================================
FILE: .github/.codecov.yml
================================================
coverage:
  status:
    project:
      default: false # disable the default status that measures entire project
      pkg: # declare a new status context "pkg"
        paths:
          - pkg/* # only include coverage in "pkg/" folder
        informational: true # Always pass check
      tools: # declare a new status context "tools"
        paths:
          - tools/* # only include coverage in "tools/" folder
        informational: true # Always pass check
      test: # declare a new status context "test"
        paths:
          - test/* # only include coverage in "test/" folder
        informational: true # Always pass check
      
      # internal: # declare a new status context "internal"
      #   paths:
      #     - internal/* # only include coverage in "internal/" folder
      #   informational: true # Always pass check
      # cmd: # declare a new status context "cmd"
      #   paths:
      #     - cmd/* # only include coverage in "cmd/" folder
      #   informational: true # Always pass check
    patch: off # disable the commit only checks


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.yml
================================================
name: Bug Report
title: "[BUG] "
labels: ["bug"]
description: "Create a detailed report to help us identify and resolve issues."
# assignees: []

body:
  - type: markdown
    attributes:
      value: "Thank you for taking the time to fill out the bug report. Please provide as much information as possible to help us understand and replicate the bug."

  - type: input
    id: openim-server-version
    attributes:
      label: OpenIM Server Version
      description: "Please provide the version number of OpenIM Server you are using."
      placeholder: "e.g., 3.8.0"
    validations:
      required: true

  - type: dropdown
    id: operating-system
    attributes:
      label: Operating System and CPU Architecture
      description: "Please select the operating system and describe the CPU architecture."
      options:
        - Linux (AMD)
        - Linux (ARM)
        - Windows (AMD)
        - Windows (ARM)
        - macOS (AMD)
        - macOS (ARM)
    validations:
      required: true

  - type: dropdown
    id: deployment-method
    attributes:
      label: Deployment Method
      description: "Please specify how OpenIM Server was deployed."
      options:
        - Source Code Deployment
        - Docker Deployment
    validations:
      required: true
      
  - type: textarea
    id: bug-description-reproduction
    attributes:
      label: Bug Description and Steps to Reproduce
      description: "Provide a detailed description of the bug and a step-by-step guide on how to reproduce it."
      placeholder: "Describe the bug in detail here...\n\nSteps to reproduce the bug on the server:\n1. Start the server with specific configurations (mention any relevant config details).\n2. Make an API call to '...' endpoint with the following payload '...'.\n3. Observe the behavior and note any error messages or logs.\n4. Mention any additional setup relevant to the bug (e.g., database version, external service dependencies)."
    validations:
      required: true

  - type: markdown
    attributes:
      value: "If possible, please add screenshots to help explain your problem."

  - type: textarea
    id: screenshots-link
    attributes:
      label: Screenshots Link
      description: "If applicable, please provide any links to screenshots here."
      placeholder: "Paste your screenshot URL here, e.g., http://imgur.com/example"

================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  # - name: "Bug Report"
  #   description: "Report a bug in the project"
  #   file: "bug-report.yml"
  - name: 📢 Connect on slack
    url: https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A
    about: Support OpenIM-related requests or issues, get in touch with developers and help on slack
  - name: 🌐 OpenIM Blog
    url: https://www.openim.io/
    about: Open the OpenIM community blog


================================================
FILE: .github/ISSUE_TEMPLATE/deployment.yml
================================================
name: Deployment issue
title: "[Deployment] "
labels: ["deployment"]
description: "Create a detailed report to help us identify and resolve deployment issues."
# assignees: []

body:
  - type: markdown
    attributes:
      value: "Thank you for taking the time to fill out the deployment issue report. Please provide as much information as possible to help us understand and resolve the issue."

  - type: input
    id: openim-server-version
    attributes:
      label: OpenIM Server Version
      description: "Please provide the version number of OpenIM Server you are using."
      placeholder: "e.g., 3.8.0"
    validations:
      required: true

  - type: dropdown
    id: operating-system
    attributes:
      label: Operating System and CPU Architecture
      description: "Please select the operating system and describe the CPU architecture."
      options:
        - Linux (AMD)
        - Linux (ARM)
        - Windows (AMD)
        - Windows (ARM)
        - macOS (AMD)
        - macOS (ARM)
    validations:
      required: true

  - type: dropdown
    id: deployment-method
    attributes:
      label: Deployment Method
      description: "Please specify how OpenIM Server was deployed."
      options:
        - Source Code Deployment
        - Docker Deployment
    validations:
      required: true
      
  - type: textarea
    id: issue-description-reproduction
    attributes:
      label: Issue Description and Steps to Reproduce
      description: "Provide a detailed description of the issue and a step-by-step guide on how to reproduce it."
      placeholder: "Describe the issue in detail here...\n\nSteps to reproduce the issue on the server:\n1. Start the server with specific configurations (mention any relevant config details).\n2. Make an API call to '...' endpoint with the following payload '...'.\n3. Observe the behavior and note any error messages or logs.\n4. Mention any additional setup relevant to the bug (e.g., database version, external service dependencies)."
    validations:
      required: true

  - type: markdown
    attributes:
      value: "If possible, please add screenshots to help explain your problem."

  - type: textarea
    id: screenshots-link
    attributes:
      label: Screenshots Link
      description: "If applicable, please provide any links to screenshots here."
      placeholder: "Paste your screenshot URL here, e.g., http://imgur.com/example"

================================================
FILE: .github/ISSUE_TEMPLATE/documentation.md
================================================
---
name: Documentation Update
about: Propose updates to documentation, including README files and other docs.
title: "[DOC]: "  # Prefix for the title to help identify documentation issues
labels: documentation  # Labels to be automatically added
assignees: ''  # Optionally, specify maintainers or teams to be auto-assigned

---

## Documentation Updates
Describe the documentation that needs to be updated or corrected. Please specify the files and sections if possible.

## Motivation
Explain why these updates are necessary. What is missing, misleading, or outdated?

## Suggested Changes
Detail the changes that you propose. If you are suggesting large changes, include examples or mockups of what the updated documentation should look like.

## Additional Information
Include any other information that might be relevant, such as links to discussions or related issues in the repository.


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.yml
================================================
name: Feature Request
title: "[FEATURE REQUEST] "
labels: ["feature request","enhancement"]
description: "Propose a new feature or improvement that you believe will help enhance the project."
# assignees: []

body:
  - type: markdown
    attributes:
      value: "Thank you for taking the time to propose a feature request. Please fill in as much detail as possible to help us understand why this feature is necessary and how it should work."

  - type: textarea
    id: feature-reason
    attributes:
      label: Why this feature?
      description: "Explain why this feature is needed. What problem does it solve? How does it benefit the project and its users?"
      placeholder: "Describe the need for this feature..."
    validations:
      required: true

  - type: textarea
    id: solution-proposal
    attributes:
      label: Suggested Solution
      description: "Describe your proposed solution for this feature. How do you envision it working?"
      placeholder: "Detail your solution here..."
    validations:
      required: true

  - type: markdown
    attributes:
      value: "Please provide any other relevant information or screenshots that could help illustrate your idea."

  - type: textarea
    id: additional-info
    attributes:
      label: Additional Information
      description: "Include any additional information, links, or screenshots that might be relevant to your feature request."
      placeholder: "Add more context or links to relevant resources..."

  - type: markdown
    attributes:
      value: "Thank you for contributing to the project! We appreciate your input and will review your suggestion as soon as possible."


================================================
FILE: .github/ISSUE_TEMPLATE/other.yml
================================================
name: 🐧 Other
description: Use this for any other issues. Please do NOT create blank issues
title: "[Other]: <give this problem a name>"
labels: ["other"]
# assignees: []

body:
  - type: markdown
    attributes:
      value: "# Other issue"
  - type: textarea
    id: issuedescription
    attributes:
      label: What would you like to share?
      description: Provide a clear and concise explanation of your issue.
    validations:
      required: true
  - type: textarea
    id: extrainfo
    attributes:
      label: Additional information
      description: Is there anything else we should know about this issue?
    validations:
      required: false
  - type: markdown
    attributes:
      value: |
        You can also join our Discord community [here](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A)
        Feel free to check out other cool repositories of the openim Community [here](https://github.com/openimsdk)


================================================
FILE: .github/ISSUE_TEMPLATE/rfc.md
================================================
---
name: RFC - Feature Proposal
about: Submit a proposal for a significant feature to invite community discussion.
title: "[RFC]: "  # Prefix for the title to help identify RFC proposals
labels: rfc, proposal  # Labels to be automatically added
assignees: ''  # Optionally, specify maintainers or teams to be auto-assigned

---

## Proposal Overview
Briefly describe the content and objectives of your proposal.

## Motivation
Why is this new feature necessary? What is the background of this problem?

## Detailed Design
Describe the technical details of the proposal, including implementation steps, code snippets, or architecture diagrams.

## Alternatives Considered
Have other alternatives been considered? Why is this approach preferred over others?

## Impact
How will this proposal affect existing practices and community users?

## Additional Information
Include any other relevant information such as related discussions, prior related work, etc.


================================================
FILE: .github/sync-release.yml
================================================
openimsdk/openim-docker:
  - source: ./config
    dest: ./openim-server/release/config
    replace: true
  - source: ./docs
    dest: ./openim-server/release/docs
    replace: true
  - source: ./scripts
    dest: ./openim-server/release/scripts
    replace: true
  - source: ./scripts
    dest: ./scripts
    replace: false
  - source: ./Makefile
    dest: ./Makefile
    replace: false


================================================
FILE: .github/workflows/auto-assign-issue.yml
================================================
name: Assign issue to comment author
on:
  issue_comment:
    types: [created]
jobs:
  assign-issue:
    if: |
      contains(github.event.comment.body, '/assign') || contains(github.event.comment.body, '/accept') &&
      !contains(github.event.comment.user.login, 'openim-robot')
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Assign the issue
        run: |
          export LETASE_MILESTONES=$(curl 'https://api.github.com/repos/$OWNER/$PEPO/milestones' | jq -r 'last(.[]).title')
          gh issue edit ${{ github.event.issue.number }} --add-assignee "${{ github.event.comment.user.login }}"
          gh issue edit ${{ github.event.issue.number }} --add-label "accepted"
          gh issue comment $ISSUE --body "@${{ github.event.comment.user.login }} Glad to see you accepted this issue🤲, this issue has been assigned to you. I set the milestones for this issue to [$LETASE_MILESTONES](https://github.com/$OWNER/$PEPO/milestones), We are looking forward to your PR!"

        # gh issue edit ${{ github.event.issue.number }} --milestone "$LETASE_MILESTONES"
        env:
          GH_TOKEN: ${{ secrets.BOT_TOKEN }}
          ISSUE: ${{ github.event.issue.html_url }}
          OWNER: ${{ github.repository_owner }}
          REPO: ${{ github.event.repository.name }}


================================================
FILE: .github/workflows/auto-invite-comment.yml
================================================
name: Invite users to join OpenIM Community.
on:
  issue_comment:
    types:
      - created
jobs:
  issue_comment:
    name: Invite users to join OpenIM Community
    if: ${{ github.event.comment.body == '/invite' || github.event.comment.body == '/close' || github.event.comment.body == '/comment' }}
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - name: Invite user to join OpenIM Community
        uses: peter-evans/create-or-update-comment@v4
        with:
          token: ${{ secrets.BOT_GITHUB_TOKEN }}
          issue-number: ${{ github.event.issue.number }}
          body: |
            We value close connections with our users, developers, and contributors here at Open-IM-Server. With a large community and maintainer team, we're always here to help and support you. Whether you're looking to join our community or have any questions or suggestions, we welcome you to get in touch with us.

            Our most recommended way to get in touch is through [Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A). Even if you're in China, Slack is usually not blocked by firewalls, making it an easy way to connect with us. Our Slack community is the ideal place to discuss and share ideas and suggestions with other users and developers of Open-IM-Server. You can ask technical questions, seek help, or share your experiences with other users of Open-IM-Server.

            In addition to Slack, we also offer the following ways to get in touch:

            + <a href="https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A" target="_blank"><img src="https://img.shields.io/badge/Slack-OpenIM%2B-blueviolet?logo=slack&amp;logoColor=white"></a> We also have Slack channels for you to communicate and discuss. To join, visit https://slack.com/ and join our [👀 Open-IM-Server slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) team channel.
            + <a href="https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=info@openim.io" target="_blank"><img src="https://img.shields.io/badge/gmail-%40OOpenIMSDKCore?style=social&logo=gmail"></a> Get in touch with us on [Gmail](https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=winxu81@gmail.com). If you have any questions or issues that need resolving, or any suggestions and feedback for our open source projects, please feel free to contact us via email.
            + <a href="https://doc.rentsoft.cn/" target="_blank"><img src="https://img.shields.io/badge/%E5%8D%9A%E5%AE%A2-%40OpenIMSDKCore-blue?style=social&logo=Octopus%20Deploy"></a> Read our [blog](https://doc.rentsoft.cn/). Our blog is a great place to stay up-to-date with Open-IM-Server projects and trends. On the blog, we share our latest developments, tech trends, and other interesting information.
            + <a href="https://github.com/OpenIMSDK/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg" target="_blank"><img src="https://img.shields.io/badge/%E5%BE%AE%E4%BF%A1-OpenIMSDKCore-brightgreen?logo=wechat&style=flat-square"></a> Add [Wechat](https://github.com/OpenIMSDK/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of Open-IM-Server. We will process your request as soon as possible.

      # - name: Close Issue
      #   uses: peter-evans/close-issue@v3
      #   with:
      #     token: ${{ secrets.BOT_GITHUB_TOKEN }}
      #     issue-number: ${{ github.event.issue.number }}
      #     comment: 🤖 Auto-closing issue, if you still need help please reopen the issue or ask for help in the community above
      #     labels: |
      #       accepted


================================================
FILE: .github/workflows/changelog.yml
================================================
name: Release Changelog

on:
  release:
    types: [released]

permissions:
  contents: write
  pull-requests: write

jobs:
  update-changelog:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Run Go Changelog Generator
      run: |
        # Run the Go changelog generator, passing the release tag if available
        if [ "${{ github.event.release.tag_name }}" = "latest" ]; then
          go run tools/changelog/changelog.go > "${{ github.event.release.tag_name }}-changelog.md"
        else
          go run tools/changelog/changelog.go "${{ github.event.release.tag_name }}" > "${{ github.event.release.tag_name }}-changelog.md"
        fi

    - name: Handle changelog files
      run: |
        # Ensure that the CHANGELOG directory exists
        mkdir -p CHANGELOG

        # Extract Major.Minor version by removing the 'v' prefix from the tag name
        TAG_NAME=${{ github.event.release.tag_name }}
        CHANGELOG_VERSION_NUMBER=$(echo "$TAG_NAME" | sed 's/^v//' | grep -oP '^\d+\.\d+')

        # Define the new changelog file path
        CHANGELOG_FILENAME="CHANGELOG-$CHANGELOG_VERSION_NUMBER.md"
        CHANGELOG_PATH="CHANGELOG/$CHANGELOG_FILENAME"

        # Check if the changelog file for the current release already exists
        if [ -f "$CHANGELOG_PATH" ]; then
          # If the file exists, append the new changelog to the existing one
          cat "$CHANGELOG_PATH" >> "${TAG_NAME}-changelog.md"
          # Overwrite the existing changelog with the updated content
          mv "${TAG_NAME}-changelog.md" "$CHANGELOG_PATH"
        else
          # If the changelog file doesn't exist, rename the temp changelog file to the new changelog file
          mv "${TAG_NAME}-changelog.md" "$CHANGELOG_PATH"

          # Ensure that README.md exists
          if [ ! -f "CHANGELOG/README.md" ]; then
            echo -e "# CHANGELOGs\n\n" > CHANGELOG/README.md
          fi
          
            # Add the new changelog entry at the top of the README.md
            if ! grep -q "\[$CHANGELOG_FILENAME\]" CHANGELOG/README.md; then
            sed -i "3i- [$CHANGELOG_FILENAME](./$CHANGELOG_FILENAME)" CHANGELOG/README.md
            # Remove the extra newline character added by sed
            # sed -i '4d' CHANGELOG/README.md
            fi
          fi

    - name: Clean up
      run: |
        # Remove any temporary files that were created during the process
        rm -f "${{ github.event.release.tag_name }}-changelog.md"

    - name: Create Pull Request
      uses: peter-evans/create-pull-request@v7.0.5
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        commit-message: "Update CHANGELOG for release ${{ github.event.release.tag_name }}"
        title: "Update CHANGELOG for release ${{ github.event.release.tag_name }}"
        body: "This PR updates the CHANGELOG files for release ${{ github.event.release.tag_name }}"
        branch: changelog-${{ github.event.release.tag_name }} 
        base: main 
        delete-branch: true
        labels: changelog


================================================
FILE: .github/workflows/cla-assistant.yml
================================================
name: CLA Assistant
on:
  issue_comment:
    types: [created]
  pull_request_target:
    types: [opened,closed,synchronize]

# explicitly configure permissions, in case your GITHUB_TOKEN workflow permissions are set to read-only in repository settings
permissions:
  actions: write
  contents: write # this can be 'read' if the signatures are in remote repository
  pull-requests: write
  statuses: write

jobs:
  CLA-Assistant:
    runs-on: ubuntu-latest
    steps:
      - name: "CLA Assistant"
        if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
        uses: contributor-assistant/github-action@v2.4.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PERSONAL_ACCESS_TOKEN: ${{ secrets.BOT_TOKEN }}
        with:
          path-to-signatures: 'signatures/cla.json'
          path-to-document: 'https://github.com/OpenIM-Robot/cla/blob/main/README.md' # e.g. a CLA or a DCO document
          branch: 'main'
          allowlist: 'bot*,*bot,OpenIM-Robot'

         # the followings are the optional inputs - If the optional inputs are not given, then default values will be taken
          remote-organization-name: OpenIM-Robot
          remote-repository-name: cla
          create-file-commit-message: 'Creating file for storing CLA Signatures'
          # signed-commit-message: '$contributorName has signed the CLA in $owner/$repo#$pullRequestNo'
          custom-notsigned-prcomment: '💕 Thank you for your contribution and please kindly read and sign our CLA. [CLA Docs](https://github.com/OpenIM-Robot/cla/blob/main/README.md)'
          custom-pr-sign-comment: 'I have read the CLA Document and I hereby sign the CLA'
          custom-allsigned-prcomment: '🤖 All Contributors have signed the [CLA](https://github.com/OpenIM-Robot/cla/blob/main/README.md).<br> The signed information is recorded [**here**](https://github.com/OpenIM-Robot/cla/blob/main/signatures/cla.json)'
          #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true)
          #use-dco-flag: true - If you are using DCO instead of CLA


================================================
FILE: .github/workflows/cleanup-after-milestone-prs-merged.yml
================================================
name: Cleanup After Milestone PRs Merged

on:
  pull_request:
    types:
      - closed

jobs:
  handle_pr:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v4.2.0

    - name: Get the PR title and extract PR numbers
      id: extract_pr_numbers
      run: |
        # Get the PR title
        PR_TITLE="${{ github.event.pull_request.title }}"

        echo "PR Title: $PR_TITLE"

        # Extract PR numbers from the title
        PR_NUMBERS=$(echo "$PR_TITLE" | grep -oE "#[0-9]+" | tr -d '#' | tr '\n' ' ')
        echo "Extracted PR Numbers: $PR_NUMBERS"

        # Save PR numbers to a file
        echo "$PR_NUMBERS" > pr_numbers.txt
        echo "Saved PR Numbers to pr_numbers.txt"

        # Check if the title matches a specific pattern
        if echo "$PR_TITLE" | grep -qE "^deps: Merge( #[0-9]+)+ PRs into .+"; then
          echo "proceed=true" >> $GITHUB_OUTPUT
        else
          echo "proceed=false" >> $GITHUB_OUTPUT
        fi

    - name: Use extracted PR numbers and label PRs
      if: (steps.extract_pr_numbers.outputs.proceed == 'true' || contains(github.event.pull_request.labels.*.name, 'milestone-merge')) && github.event.pull_request.merged == true
      run: |
        # Read the previously saved PR numbers
        PR_NUMBERS=$(cat pr_numbers.txt)
        echo "Using extracted PR Numbers: $PR_NUMBERS"

        # Loop through each PR number and add label
        for PR_NUMBER in $PR_NUMBERS; do
          echo "Adding 'cherry-picked' label to PR #$PR_NUMBER"
          curl -X POST \
            -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
            -H "Accept: application/vnd.github+json" \
            https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels \
            -d '{"labels":["cherry-picked"]}'
        done
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

    - name: Delete branch after PR close
      if: steps.extract_pr_numbers.outputs.proceed == 'true' || contains(github.event.pull_request.labels.*.name, 'milestone-merge')
      run: |
        BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
        echo "Branch to delete: $BRANCH_NAME"
        git push origin --delete "$BRANCH_NAME"
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.

name: "CodeQL"

on:
  push:
    branches: [ main ]
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [ main ]
  schedule:
    - cron: '18 19 * * 6'

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        language: [ 'go' ]
        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
        # Learn more:
        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed

    steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v3
      with:
        languages: ${{ matrix.language }}
        # If you wish to specify custom queries, you can do so here or in a config file.
        # By default, queries listed here will override any specified in a config file.
        # Prefix the list here with "+" to use these queries and those in the config file.
        # queries: ./path/to/local/query, your-org/your-repo/queries@main

    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
    # If this step fails, then you should remove it and run the build manually (see below)
    - name: Autobuild
      uses: github/codeql-action/autobuild@v3

    # ℹ️ Command-line programs to run using the OS shell.
    # 📚 https://git.io/JvXDl

    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
    #    and modify them (or add more) to build your code if your project
    #    uses a compiled language

    #- run: |
    #   make bootstrap
    #   make release

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v3

================================================
FILE: .github/workflows/comment-check.yml
================================================
name: Non-English Comments Check

on:
  pull_request:
    branches:
      - main
  workflow_dispatch:

jobs:
  non-english-comments-check:
    runs-on: ubuntu-latest

    env:
      # need ignore Dirs
      EXCLUDE_DIRS: ".git docs tests scripts assets node_modules build"
      # need ignore Files
      EXCLUDE_FILES: "*.md *.txt *.html *.css *.min.js *.mdx"

    steps:
      - uses: actions/checkout@v4

      - name: Search for Non-English comments
        run: |
          set -e
          # Define the regex pattern to match Chinese characters
          pattern='[\p{Han}]'

          # Process the directories to be excluded
          exclude_dirs=""
          for dir in $EXCLUDE_DIRS; do
            exclude_dirs="$exclude_dirs --exclude-dir=$dir"
          done

          # Process the file types to be excluded
          exclude_files=""
          for file in $EXCLUDE_FILES; do
            exclude_files="$exclude_files --exclude=$file"
          done

          # Use grep to find all comments containing Non-English characters and save to file
          grep -Pnr "$pattern" . $exclude_dirs $exclude_files > non_english_comments.txt || true

      - name: Output non-English comments are found
        run: |
          if [ -s non_english_comments.txt ]; then
            echo "Non-English comments found in the following locations:"
            cat non_english_comments.txt
            exit 1  # terminate the workflow
          else
            echo "No Non_English comments found."
          fi


================================================
FILE: .github/workflows/docker-build-and-release-services-images.yml
================================================
name: Build and release services Docker Images

on:
  push:
    branches:
      - release-*
  release:
    types: [published]
  workflow_dispatch:
    inputs:
      tag:
        description: "Tag version to be used for Docker image"
        required: true
        default: "v3.8.3"

jobs:
  build-and-push:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3.8.0

      - name: Log in to Docker Hub
        uses: docker/login-action@v3.3.0
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3.3.0
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Log in to Aliyun Container Registry
        uses: docker/login-action@v3.3.0
        with:
          registry: registry.cn-hangzhou.aliyuncs.com
          username: ${{ secrets.ALIREGISTRY_USERNAME }}
          password: ${{ secrets.ALIREGISTRY_TOKEN }}

      - name: Extract metadata for Docker (tags, labels)
        id: meta
        uses: docker/metadata-action@v5.6.0
        with:
          tags: |
            type=ref,event=tag
            type=schedule
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=semver,pattern=v{{version}}
            type=semver,pattern=release-{{raw}}
            type=sha
            type=raw,value=${{ github.event.inputs.tag }}

      - name: Build and push Docker images
        run: |
          IMG_DIR="build/images"
          for dir in "$IMG_DIR"/*/; do
              # Find Dockerfile or *.dockerfile in a case-insensitive manner
              dockerfile=$(find "$dir" -maxdepth 1 -type f \( -iname 'dockerfile' -o -iname '*.dockerfile' \) | head -n 1)
              
              if [ -n "$dockerfile" ] && [ -f "$dockerfile" ]; then
                  IMAGE_NAME=$(basename "$dir")
                  echo "Building Docker image for $IMAGE_NAME with tags:"
                  
                  # Initialize tag arguments
                  tag_args=()

                  # Read each tag and append --tag arguments
                  while IFS= read -r tag; do
                      tag_args+=(--tag "${{ secrets.DOCKER_USERNAME }}/$IMAGE_NAME:$tag")
                      tag_args+=(--tag "ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME:$tag")
                      tag_args+=(--tag "registry.cn-hangzhou.aliyuncs.com/openimsdk/$IMAGE_NAME:$tag")
                  done <<< "${{ steps.meta.outputs.tags }}"

                  # Build and push the Docker image with all tags
                  docker buildx build --platform linux/amd64,linux/arm64 \
                    --file "$dockerfile" \
                    "${tag_args[@]}" \
                    --push \
                    "."
              else
                  echo "No valid Dockerfile found in $dir"
              fi
          done


================================================
FILE: .github/workflows/go-build-test.yml
================================================
name: Go Build Test

on:
  push:
  pull_request:
    paths-ignore:
      - "**/*.md"

  workflow_dispatch:

jobs:
  go-build:
    name: Test with go ${{ matrix.go_version }} on ${{ matrix.os }}
    runs-on: ${{ matrix.os }}

    env:
      SHARE_CONFIG_PATH: config/share.yml

    permissions:
      contents: write
      pull-requests: write
    strategy:
      matrix:
        os: [ubuntu-latest]
        go_version: ["1.22.x"]

    steps:
      - name: Checkout Server repository
        uses: actions/checkout@v4

      - name: Set up Go ${{ matrix.go_version }}
        uses: actions/setup-go@v5
        with:
          go-version: ${{ matrix.go_version }}

      - name: Get Server dependencies
        run: |
          go install github.com/magefile/mage@latest
          go mod tidy
          go mod download

      - name: Set up infra services
        uses: hoverkraft-tech/compose-action@v2.0.1
        with:
          compose-file: "./docker-compose.yml"

      - name: Modify Server Configuration
        run: |
          yq e '.secret = 123456' -i ${{ env.SHARE_CONFIG_PATH }}

      # - name: Get Internal IP Address
      #   id: get-ip
      #   run: |
      #     IP=$(hostname -I | awk '{print $1}')
      #     echo "The IP Address is: $IP"
      #     echo "::set-output name=ip::$IP"

      # - name: Update .env
      #   run: |
      #     sed -i 's|externalAddress:.*|externalAddress: "http://${{ steps.get-ip.outputs.ip }}:10005"|' config/minio.yml
      #     cat config/minio.yml

      - name: Build and test Server Services
        run: |
          mage build
          mage start
          mage check

      - name: Checkout Chat repository
        uses: actions/checkout@v4
        with:
          repository: "openimsdk/chat"
          path: "chat-repo"

      - name: Get Chat dependencies
        run: |
          cd ${{ github.workspace }}/chat-repo
          go mod tidy
          go mod download
          go install github.com/magefile/mage@latest

      - name: Modify Chat Configuration
        run: |
          cd ${{ github.workspace }}/chat-repo
          yq e '.openIM.secret = 123456' -i ${{ env.SHARE_CONFIG_PATH }}

      - name: Build and test Chat Services
        run: |
          cd ${{ github.workspace }}/chat-repo
          mage build
          mage start
          mage check

      - name: Test Server and Chat
        run: |
          check_error() {
            echo "Response: $1"
            errCode=$(echo $1 | jq -r '.errCode')
            if [ "$errCode" != "0" ]; then
              errMsg=$(echo $1 | jq -r '.errMsg')
              echo "Error: $errMsg"
              exit 1
            fi
          }

          # Test register
          response1=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
            "verifyCode": "666666",
            "platform": 3,
            "autoLogin": true,
            "user":{
            "nickname": "test12312",
            "areaCode":"+86",
            "phoneNumber": "12345678190",
            "password":"test123456"
            }
          }' http://127.0.0.1:10008/account/register)
          check_error "$response1"
          userID1=$(echo $response1 | jq -r '.data.userID')
          echo "userID1: $userID1"

          response2=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
            "verifyCode": "666666",
            "platform": 3,
            "autoLogin": true,
            "user":{
            "nickname": "test22312",
            "areaCode":"+86",
            "phoneNumber": "12345678290",
            "password":"test123456"
            }
          }' http://127.0.0.1:10008/account/register)
          check_error "$response2"
          userID2=$(echo $response2 | jq -r '.data.userID')
          echo "userID2: $userID2"

          # Test login
          login_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin"  -d '{
            "platform": 3,
            "areaCode":"+86",
            "phoneNumber": "12345678190",
            "password":"test123456"
          }' http://localhost:10008/account/login)
          check_error "$login_response"

          # Test get admin token
          get_admin_token_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
            "secret": "123456",
            "platformID": 2,
            "userID": "imAdmin"
          }' http://127.0.0.1:10002/auth/get_admin_token)
          check_error "$get_admin_token_response"
          adminToken=$(echo $get_admin_token_response | jq -r '.data.token')
          echo "adminToken: $adminToken"

          # Test send message
          send_msg_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -H "token: $adminToken" -d '{
            "sendID": "'$userID1'",
            "recvID": "'$userID2'",
            "senderPlatformID": 3,
            "content": {
              "content": "hello!!"
            },
            "contentType": 101,
            "sessionType": 1
           }' http://127.0.0.1:10002/msg/send_msg)
           check_error "$send_msg_response"

          # Test get users
          get_users_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -H "token: $adminToken" -d '{
            "pagination": {
               "pageNumber": 1,
               "showNumber": 100
             }
            }' http://127.0.0.1:10002/user/get_users)
          check_error "$get_users_response"

  go-test:
    name: Benchmark Test with go ${{ matrix.go_version }} on ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    permissions:
      contents: write
    env:
      SDK_DIR: openim-sdk-core
      NOTIFICATION_CONFIG_PATH: config/notification.yml
      SHARE_CONFIG_PATH: config/share.yml

    strategy:
      matrix:
        os: [ubuntu-latest]
        go_version: ["1.22.x"]

    steps:
      - name: Checkout Server repository
        uses: actions/checkout@v4

      - name: Checkout SDK repository
        uses: actions/checkout@v4
        with:
          repository: "openimsdk/openim-sdk-core"
          ref: "main"
          path: ${{ env.SDK_DIR }}

      - name: Set up Go ${{ matrix.go_version }}
        uses: actions/setup-go@v5
        with:
          go-version: ${{ matrix.go_version }}

      - name: Get Server dependencies
        run: |
          go install github.com/magefile/mage@latest
          go mod download

      - name: Modify Server Configuration
        run: |
          yq e '.groupCreated.isSendMsg = true' -i ${{ env.NOTIFICATION_CONFIG_PATH }}
          yq e '.friendApplicationApproved.isSendMsg = true' -i ${{ env.NOTIFICATION_CONFIG_PATH }}
          yq e '.secret = 123456' -i ${{ env.SHARE_CONFIG_PATH }}

      - name: Start Server Services
        run: |
          docker compose up -d
          mage build
          mage start
          mage check

      - name: Build test SDK core
        run: |
          cd ${{ env.SDK_DIR }}
          go mod tidy
          cd integration_test
          mkdir data
          go run main.go -lgr 0.8 -imf -crg -ckgn -ckcon -sem -ckmsn -u 20 -su 5 -lg 2 -cg 2 -cgm 3 -sm 10 -gm 10 -reg

  dockerfile-test:
    name: Build and Test Dockerfile
    runs-on: ubuntu-latest
    strategy:
      matrix:
        go_version: ["1.22"]

    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Set up Go ${{ matrix.go_version }}
        uses: actions/setup-go@v5
        with:
          go-version: ${{ matrix.go_version }}

      - name: Get dependencies
        run: |
          go mod tidy
          go mod download
          go install github.com/magefile/mage@latest

      - name: Build Docker Image
        run: |
          IMAGE_NAME="${{ github.event.repository.name }}-test"
          CONTAINER_NAME="${{ github.event.repository.name }}-container"
          docker build -t $IMAGE_NAME .

      - name: Run Docker Container
        run: |
          IMAGE_NAME="${{ github.event.repository.name }}-test"
          CONTAINER_NAME="${{ github.event.repository.name }}-container"
          docker run --name $CONTAINER_NAME -d $IMAGE_NAME
          docker ps -a

      - name: Test Docker Container Logs
        run: |
          CONTAINER_NAME="${{ github.event.repository.name }}-container"
          docker logs $CONTAINER_NAME


================================================
FILE: .github/workflows/help-comment-issue.yml
================================================
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Good frist issue add comment
on:
  issues:
    types:
      - labeled

jobs:
  add-comment:
    if: github.event.label.name == 'help wanted' || github.event.label.name == 'good first issue'
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - name: Add comment
        uses: peter-evans/create-or-update-comment@v4
        with:
          issue-number: ${{ github.event.issue.number }}
          token: ${{ secrets.BOT_TOKEN }}
          body: |
            This issue is available for anyone to work on. **Make sure to reference this issue in your pull request.** :sparkles: Thank you for your contribution! :sparkles:
            [Join slack 🤖](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) to connect and communicate with our developers.
            If you wish to accept this assignment, please leave a comment in the comments section: `/accept`.🎯


================================================
FILE: .github/workflows/issue-translator.yml
================================================
name: 'issue-translator'
on: 
  issue_comment: 
    types: [created]
  issues: 
    types: [opened]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: usthe/issues-translate-action@v2.7
        with:
          BOT_GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} 
          IS_MODIFY_TITLE: true
          # not require, default false, . Decide whether to modify the issue title
          # if true, the robot account @Issues-translate-bot must have modification permissions, invite @Issues-translate-bot to your project or use your custom bot.
          CUSTOM_BOT_NOTE: Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿
          # not require. Customize the translation robot prefix message.

================================================
FILE: .github/workflows/merge-from-milestone.yml
================================================
name: Create Individual PRs from Milestone

permissions:
  contents: write
  pull-requests: write
  issues: write

on:
  workflow_dispatch:
    inputs:
      milestone_name:
        description: "Milestone name to collect closed PRs from"
        required: true
        default: "v3.8.4"
      target_branch:
        description: "Target branch to merge the consolidated PR"
        required: true
        default: "pre-release-v3.8.4"

env:
  MILESTONE_NAME: ${{ github.event.inputs.milestone_name || 'v3.8.4' }}
  TARGET_BRANCH: ${{ github.event.inputs.target_branch || 'pre-release-v3.8.4' }}
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
  LABEL_NAME: cherry-picked
  TEMP_DIR: /tmp

jobs:
  merge_milestone_prs:
    runs-on: ubuntu-latest
    steps:
      - name: Setup temp directory
        run: |
          # Create the temporary directory and initialize necessary files
          mkdir -p ${{ env.TEMP_DIR }}
          touch ${{ env.TEMP_DIR }}/pr_numbers.txt
          touch ${{ env.TEMP_DIR }}/commit_hashes.txt
          touch ${{ env.TEMP_DIR }}/pr_title.txt
          touch ${{ env.TEMP_DIR }}/pr_body.txt
          touch ${{ env.TEMP_DIR }}/created_pr_number.txt

      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.BOT_TOKEN }}

      - name: Setup Git User for OpenIM-Robot
        run: |
          git config --global user.email "OpenIM-Robot@users.noreply.github.com"
          git config --global user.name "OpenIM-Robot"

      - name: Fetch Milestone ID and Filter PR Numbers
        env:
          MILESTONE_NAME: ${{ env.MILESTONE_NAME }}
        run: |
          # Fetch milestone details and extract milestone ID
          milestones=$(curl -s -H "Authorization: token $BOT_TOKEN" \
            -H "Accept: application/vnd.github+json" \
            "https://api.github.com/repos/${{ github.repository }}/milestones")
          milestone_id=$(echo "$milestones" | grep -B3 "\"title\": \"$MILESTONE_NAME\"" | grep '"number":' | head -n1 | grep -o '[0-9]\+')
          if [ -z "$milestone_id" ]; then
            echo "Milestone '$MILESTONE_NAME' not found. Exiting."
            exit 1
          fi
          echo "Milestone ID: $milestone_id"
          echo "MILESTONE_ID=$milestone_id" >> $GITHUB_ENV

          # Fetch issues for the milestone
          issues=$(curl -s -H "Authorization: token $BOT_TOKEN" \
                -H "Accept: application/vnd.github+json" \
                "https://api.github.com/repos/${{ github.repository }}/issues?milestone=$milestone_id&state=closed&per_page=100")

          > ${{ env.TEMP_DIR }}/pr_numbers.txt

          # Filter PRs that do not have the 'cherry-picked' label
          for pr_number in $(echo "$issues" | jq -r '.[] | select(.pull_request != null) | .number'); do
            labels=$(curl -s -H "Authorization: token $BOT_TOKEN" \
              -H "Accept: application/vnd.github+json" \
              "https://api.github.com/repos/${{ github.repository }}/issues/$pr_number/labels" | jq -r '.[].name')

            if ! echo "$labels" | grep -q "${LABEL_NAME}"; then
              echo "PR #$pr_number does not have the 'cherry-picked' label. Adding to the list."
              echo "$pr_number" >> ${{ env.TEMP_DIR }}/pr_numbers.txt
            fi
          done

          sort -n ${{ env.TEMP_DIR }}/pr_numbers.txt -o ${{ env.TEMP_DIR }}/pr_numbers.txt

      - name: Create Individual PRs
        run: |
          for pr_number in $(cat ${{ env.TEMP_DIR }}/pr_numbers.txt); do
            pr_details=$(curl -s -H "Authorization: token $BOT_TOKEN" \
              -H "Accept: application/vnd.github+json" \
              "https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
            pr_title=$(echo "$pr_details" | jq -r '.title')
            pr_body=$(echo "$pr_details" | jq -r '.body')
            pr_creator=$(echo "$pr_details" | jq -r '.user.login')
            merge_commit=$(echo "$pr_details" | jq -r '.merge_commit_sha')
            short_commit_hash=$(echo "$merge_commit" | cut -c 1-7)

            if [ "$merge_commit" != "null" ]; then
              git fetch origin
              
              echo "Checking out target branch: $TARGET_BRANCH"
              git checkout $TARGET_BRANCH

              echo "Pulling latest changes from target branch: $TARGET_BRANCH"
              git pull origin $TARGET_BRANCH
              
              cherry_pick_branch="cherry-pick-${short_commit_hash}"
              git checkout -b $cherry_pick_branch

              echo "Cherry-picking commit: $merge_commit"
              if ! git cherry-pick "$merge_commit" --strategy=recursive -X theirs; then
                echo "Conflict detected for $merge_commit. Resolving with incoming changes."
                conflict_files=$(git diff --name-only --diff-filter=U)
                echo "Conflicting files:"
                echo "$conflict_files"

                for file in $conflict_files; do
                  if [ -f "$file" ]; then
                    echo "Resolving conflict for $file"
                    git add "$file"
                  else
                    echo "File $file has been deleted. Skipping."
                    git rm "$file"
                  fi
                done

                echo "Conflicts resolved. Continuing cherry-pick."
                git cherry-pick --continue || { echo "Cherry-pick failed, but continuing to create PR."; }
              else
                echo "Cherry-pick successful for commit $merge_commit."
              fi

              git remote set-url origin "https://${BOT_TOKEN}@github.com/${{ github.repository }}.git"
              
              echo "Pushing branch: $cherry_pick_branch"
              if ! git push origin $cherry_pick_branch --force; then
                echo "Push failed, but continuing to create PR..."
              fi

              new_pr_title="$pr_title [Created by @$pr_creator from #$pr_number]"
              new_pr_body="$pr_body
              > This PR is created from original PR #$pr_number."

              response=$(curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
                -H "Accept: application/vnd.github+json" \
                https://api.github.com/repos/${{ github.repository }}/pulls \
                -d "$(jq -n --arg title "$new_pr_title" \
                  --arg head "$cherry_pick_branch" \
                  --arg base "$TARGET_BRANCH" \
                  --arg body "$new_pr_body" \
                  '{title: $title, head: $head, base: $base, body: $body}')")

              new_pr_number=$(echo "$response" | jq -r '.number')

              if [[ "$new_pr_number" == "null" || -z "$new_pr_number" ]]; then
                echo "Failed to create PR. Response: $response"
              
                git checkout $TARGET_BRANCH

                git branch -D $cherry_pick_branch
                
                echo "Deleted branch: $cherry_pick_branch"
                git push origin --delete $cherry_pick_branch
              else
                echo "Created PR #$new_pr_number"

                curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
                -H "Accept: application/vnd.github+json" \
                -d '{"labels": ["milestone-merge"]}' \
                "https://api.github.com/repos/${{ github.repository }}/issues/$new_pr_number/labels"
              fi

              echo ""
              echo "----------------------------------------"
              echo ""
            fi
          done


================================================
FILE: .github/workflows/publish-docker-image.yml
================================================
name: Publish Docker image to registries

on:
  push:
    branches:
      - release-*
  release:
    types: [published]
  workflow_dispatch:
    inputs:
      tag:
        description: "Tag version to be used for Docker image"
        required: true
        default: "v3.8.3"

env:
  GO_VERSION: "1.22"
  IMAGE_NAME: "openim-server"
  # IMAGE_NAME: ${{ github.event.repository.name }}
  DOCKER_BUILDKIT: 1

jobs:
  publish-docker-images:
    runs-on: ubuntu-latest
    if: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.merged == false) }}
    steps:
      - name: Checkout main repository
        uses: actions/checkout@v4
        with:
          path: main-repo

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3.3.0

      - name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v3
        with:
          driver-opts: network=host

      - name: Extract metadata for Docker
        id: meta
        uses: docker/metadata-action@v5.6.0
        with:
          images: |
            ${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}
            ghcr.io/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
            registry.cn-hangzhou.aliyuncs.com/openimsdk/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=tag
            type=schedule
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern=v{{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=semver,pattern={{major}}
            type=sha

      - name: Install skopeo
        run: |
          sudo apt-get update && sudo apt-get install -y skopeo

      - name: Build multi-arch images as OCI
        run: |
          mkdir -p /tmp/oci-image /tmp/docker-cache

          # Build multi-architecture image and save in OCI format        
          docker buildx build \
            --platform linux/amd64,linux/arm64 \
            --output type=oci,dest=/tmp/oci-image/multi-arch.tar \
            --cache-to type=local,dest=/tmp/docker-cache \
            --cache-from type=gha \
            ./main-repo

            # Use skopeo to convert the amd64 image from OCI format to Docker format and load it
          skopeo copy --override-arch amd64 oci-archive:/tmp/oci-image/multi-arch.tar docker-daemon:${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:local

          # check image
          docker image ls | grep openim

      - name: Checkout compose repository
        uses: actions/checkout@v4
        with:
          repository: "openimsdk/openim-docker"
          path: "compose-repo"

      - name: Get Internal IP Address
        id: get-ip
        run: |
          IP=$(hostname -I | awk '{print $1}')
          echo "The IP Address is: $IP"
          echo "ip=$IP" >> $GITHUB_OUTPUT

      - name: Update .env to use the local image
        run: |
          sed -i 's|OPENIM_SERVER_IMAGE=.*|OPENIM_SERVER_IMAGE=${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:local|' ${{ github.workspace }}/compose-repo/.env
          sed -i 's|MINIO_EXTERNAL_ADDRESS=.*|MINIO_EXTERNAL_ADDRESS=http://${{ steps.get-ip.outputs.ip }}:10005|' ${{ github.workspace }}/compose-repo/.env

      - name: Start services using Docker Compose
        run: |
          cd ${{ github.workspace }}/compose-repo
          docker compose up -d

          docker compose ps

      # - name: Check openim-server health
      #   run: |
      #     timeout=300
      #     interval=30
      #     elapsed=0
      #     while [[ $elapsed -le $timeout ]]; do
      #       if ! docker exec openim-server mage check; then
      #         echo "openim-server is not ready, waiting..."
      #         sleep $interval
      #         elapsed=$(($elapsed + $interval))
      #       else
      #         echo "Health check successful"
      #         exit 0
      #       fi
      #     done
      #     echo "Health check failed after 5 minutes"
      #     exit 1

      # - name: Check openim-chat health
      #   if: success()
      #   run: |
      #     if ! docker exec openim-chat mage check; then
      #         echo "openim-chat check failed"
      #         exit 1
      #       else
      #         echo "Health check successful"
      #         exit 0
      #       fi

      - name: Log in to Docker Hub
        uses: docker/login-action@v3.3.0
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3.3.0
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Log in to Aliyun Container Registry
        uses: docker/login-action@v3.3.0
        with:
          registry: registry.cn-hangzhou.aliyuncs.com
          username: ${{ secrets.ALIREGISTRY_USERNAME }}
          password: ${{ secrets.ALIREGISTRY_TOKEN }}

      - name: Push multi-architecture images
        if: success()
        run: |
          docker buildx build \
            --platform linux/amd64,linux/arm64 \
            $(echo "${{ steps.meta.outputs.tags }}" | sed 's/,/ --tag /g' | sed 's/^/--tag /') \
            --cache-from type=local,src=/tmp/docker-cache \
            --push \
            ./main-repo

      - name: Verify multi-platform support
        run: |
          images=(
            "${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}"
            "ghcr.io/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}"
            "registry.cn-hangzhou.aliyuncs.com/openimsdk/${{ env.IMAGE_NAME }}"
          )

          for image in "${images[@]}"; do
              for tag in $(echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' | cut -d':' -f2); do
                  echo "Verifying multi-arch support for $image:$tag"
                  manifest=$(docker manifest inspect "$image:$tag" || echo "error")
                  if [[ "$manifest" == "error" ]]; then
                      echo "Manifest not found for $image:$tag"
                      exit 1
                  fi
                  amd64_found=$(echo "$manifest" | jq '.manifests[] | select(.platform.architecture == "amd64")')
                  arm64_found=$(echo "$manifest" | jq '.manifests[] | select(.platform.architecture == "arm64")')
                  if [[ -z "$amd64_found" ]]; then
                      echo "Multi-platform support check failed for $image:$tag - missing amd64"
                      exit 1
                  fi
                  if [[ -z "$arm64_found" ]]; then
                      echo "Multi-platform support check failed for $image:$tag - missing arm64"
                      exit 1
                  fi
                  echo "✅ $image:$tag supports both amd64 and arm64 architectures"
              done
          done


================================================
FILE: .github/workflows/remove-unused-labels.yml
================================================
name: Remove Unused Labels
on:
  workflow_dispatch:

jobs:
  cleanup:
    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write
      contents: read
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Fetch All Issues and PRs
        id: fetch_issues_prs
        uses: actions/github-script@v7.0.1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issues = await github.paginate(github.rest.issues.listForRepo, {
              owner: context.repo.owner,
              repo: context.repo.repo,
              state: 'all',
              per_page: 100
            });

            const labelsInUse = new Set();
            issues.forEach(issue => {
              issue.labels.forEach(label => {
                labelsInUse.add(label.name);
              });
            });

            return JSON.stringify(Array.from(labelsInUse));
          result-encoding: string

      - name: Fetch All Labels
        id: fetch_labels
        uses: actions/github-script@v7.0.1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const labels = await github.paginate(github.rest.issues.listLabelsForRepo, {
              owner: context.repo.owner,
              repo: context.repo.repo,
              per_page: 100
            });

            return JSON.stringify(labels.map(label => label.name));
          result-encoding: string

      - name: Remove Unused Labels
        uses: actions/github-script@v7.0.1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const labelsInUse = new Set(JSON.parse(process.env.LABELS_IN_USE));
            const allLabels = JSON.parse(process.env.ALL_LABELS);

            const unusedLabels = allLabels.filter(label => !labelsInUse.has(label));

            for (const label of unusedLabels) {
              await github.rest.issues.deleteLabel({
                owner: context.repo.owner,
                repo: context.repo.repo,
                name: label
              });
              console.log(`Deleted label: ${label}`);
            }
        env:
          LABELS_IN_USE: ${{ steps.fetch_issues_prs.outputs.result }}
          ALL_LABELS: ${{ steps.fetch_labels.outputs.result }}


================================================
FILE: .github/workflows/reopen-issue.yml
================================================
name: Reopen and Update Stale Issues

on:
  workflow_dispatch:

jobs:
  reopen_stale_issues:
    runs-on: ubuntu-latest
    permissions:
      issues: write
      contents: read

    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Fetch Closed Issues with lifecycle/stale Label
        id: fetch_issues
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issues = await github.paginate(github.rest.issues.listForRepo, {
              owner: context.repo.owner,
              repo: context.repo.repo,
              state: 'closed',
              labels: 'lifecycle/stale',
              per_page: 100
            });
            const issueNumbers = issues
              .filter(issue => !issue.pull_request) // exclude PR
              .map(issue => issue.number);
            console.log(`Fetched issues: ${issueNumbers}`);
            return issueNumbers;

      - name: Set issue numbers
        id: set_issue_numbers
        run: |
          echo "ISSUE_NUMBERS=${{ steps.fetch_issues.outputs.result }}" >> $GITHUB_ENV
          echo "Issue numbers: ${{ steps.fetch_issues.outputs.result }}"

      - name: Reopen Issues
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issueNumbers = JSON.parse(process.env.ISSUE_NUMBERS);
            console.log(`Reopening issues: ${issueNumbers}`);

            for (const issue_number of issueNumbers) {
              // Reopen the issue
              await github.rest.issues.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue_number,
                state: 'open'
              });
              console.log(`Reopened issue #${issue_number}`);
            }

      - name: Remove lifecycle/stale Label
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issueNumbers = JSON.parse(process.env.ISSUE_NUMBERS);
            console.log(`Removing 'lifecycle/stale' label from issues: ${issueNumbers}`);

            for (const issue_number of issueNumbers) {
              // Remove the lifecycle/stale label
              await github.rest.issues.removeLabel({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue_number,
                name: 'lifecycle/stale'
              });
              console.log(`Removed label 'lifecycle/stale' from issue #${issue_number}`);
            }


================================================
FILE: .github/workflows/update-version-file-on-release.yml
================================================
name: Update Version File on Release

on:
  release:
    types: [created]

jobs:
  update-version:
    runs-on: ubuntu-latest
    env:
      TAG_VERSION: ${{ github.event.release.tag_name }}
    steps:
      # Step 1: Checkout the original repository's code
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          # submodules: "recursive"

      - name: Safe submodule initialization
        run: |
          echo "Checking for submodules..."
          if [ -f .gitmodules ]; then
            if [ -s .gitmodules ]; then
              echo "Initializing submodules..."
              if git submodule sync --recursive 2>/dev/null; then
                git submodule update --init --force --recursive || {
                  echo "Warning: Some submodules failed to initialize, continuing anyway..."
                }
              else
                echo "Warning: Submodule sync failed, continuing without submodules..."
              fi
            else
              echo ".gitmodules exists but is empty, skipping submodule initialization"
            fi
          else
            echo "No .gitmodules file found, no submodules to initialize"
          fi

      # Step 2: Set up Git with official account
      - name: Set up Git
        run: |
          git config --global user.name "github-actions[bot]"
          git config --global user.email "github-actions[bot]@users.noreply.github.com"

      # Step 3: Check and delete existing tag
      - name: Check and delete existing tag
        run: |
          if git rev-parse ${{ env.TAG_VERSION }} >/dev/null 2>&1; then
            git tag -d ${{ env.TAG_VERSION }}
            git push --delete origin ${{ env.TAG_VERSION }}
          fi

      # Step 4: Update version file
      - name: Update version file
        run: |
          mkdir -p version
          echo -n "${{ env.TAG_VERSION }}" > version/version

      # Step 5: Commit and push changes
      - name: Commit and push changes
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          git add version/version
          git commit -m "Update version to ${{ env.TAG_VERSION }}"

      # Step 6: Update tag
      - name: Update tag
        run: |
          git tag -fa ${{ env.TAG_VERSION }} -m "Update version to ${{ env.TAG_VERSION }}"
          git push origin ${{ env.TAG_VERSION }} --force

      # Step 7: Find and Publish Draft Release
      - name: Find and Publish Draft Release
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const { owner, repo } = context.repo;
            const tagName = process.env.TAG_VERSION;

            try {
              let release;
              try {
                const response = await github.rest.repos.getReleaseByTag({
                  owner,
                  repo,
                  tag: tagName
                });
                release = response.data;
              } catch (tagError) {
                core.info(`Release not found by tag, searching all releases...`);
                const releases = await github.rest.repos.listReleases({
                  owner,
                  repo,
                  per_page: 100
                });
            
                release = releases.data.find(r => r.draft && r.tag_name === tagName);            
                if (!release) {
                  throw new Error(`No release found with tag ${tagName}`);
                }
              }
            
              await github.rest.repos.updateRelease({
                owner,
                repo,
                release_id: release.id,
                draft: false,
                prerelease: release.prerelease
              });
            
              const status = release.draft ? "was draft" : "was already published";
              core.info(`Release ${tagName} ensured to be published (${status}).`);
            
            } catch (error) {
              core.warning(`Could not find or update release for tag ${tagName}: ${error.message}`);
            }


================================================
FILE: .github/workflows/user-first-interaction.yml
================================================
name: User First Interaction

on:
  issues:
    types: [opened]
  pull_request:
    branches: [main]
    types: [opened]

jobs:
  check_for_first_interaction:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/first-interaction@v1.3.0
        with:
          repo-token: ${{ secrets.BOT_TOKEN }}
          pr-message: |
            Hello! Thank you for your contribution.

            If you are fixing a bug, please reference the issue number in the description.

            If you are implementing a feature request, please check with the maintainers that the feature will be accepted first.

            [Join slack 🤖](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) to connect and communicate with our developers.

            Please leave your information in the [✨ discussions](https://github.com/orgs/OpenIMSDK/discussions/426), we expect anyone to join OpenIM developer community.

          issue-message: |
            Hello! Thank you for filing an issue.

            If this is a bug report, please include relevant logs to help us debug the problem.

            [Join slack 🤖](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) to connect and communicate with our developers.
        continue-on-error: true


================================================
FILE: .gitignore
================================================
# 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

# ==============================================================================
# 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
.idea
dist/

================================================
FILE: .golangci.yml
================================================
# 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

  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/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/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


================================================
FILE: CHANGELOG/CHANGELOG-3.8.md
================================================
## [v3.8.3-patch.6](https://github.com/openimsdk/open-im-server/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/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/pull/3452)
* fix: s3 aws init [#3454](https://github.com/openimsdk/open-im-server/pull/3454)
* fix: use safe submodule init in workflows in v3.8.3-patch. [#3469](https://github.com/openimsdk/open-im-server/pull/3469)

**Full Changelog**: [v3.8.3-patch.5...v3.8.3-patch.6](https://github.com/openimsdk/open-im-server/compare/v3.8.3-patch.5...v3.8.3-patch.6)

## [v3.8.3-patch.5](https://github.com/openimsdk/open-im-server/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/pull/3396)

### Bug Fixes
* fix: solve unocrrect invite notification [Created [#3219](https://github.com/openimsdk/open-im-server/pull/3219)

### Builds
* build: update gomake version in dockerfile.[Patch branch] [#3416](https://github.com/openimsdk/open-im-server/pull/3416)

**Full Changelog**: [v3.8.3...v3.8.3-patch.5](https://github.com/openimsdk/open-im-server/compare/v3.8.3...v3.8.3-patch.5)

## [v3.8.3-patch.4](https://github.com/openimsdk/open-im-server/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/compare/v3.8.3-patch.3...v3.8.3-patch.4)

## [v3.8.3-patch.3](https://github.com/openimsdk/open-im-server/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/compare/v3.8.3-patch.2...v3.8.3-patch.3)

## [v3.8.3-patch.2](https://github.com/openimsdk/open-im-server/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/pull/3174)

**Full Changelog**: [v3.8.3-patch.1...v3.8.3-patch.2](https://github.com/openimsdk/open-im-server/compare/v3.8.3-patch.1...v3.8.3-patch.2)

## [v3.8.3-patch.1](https://github.com/openimsdk/open-im-server/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/pull/3121)

### Bug Fixes
* fix: seq conversion failed without exiting [Created [#3120](https://github.com/openimsdk/open-im-server/pull/3120)
* fix: check error in BatchSetTokenMapByUidPid [Created [#3123](https://github.com/openimsdk/open-im-server/pull/3123)
* fix: DeleteDoc crash [Created [#3124](https://github.com/openimsdk/open-im-server/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/pull/3126)
* fix: crash caused [#3127](https://github.com/openimsdk/open-im-server/pull/3127)
* fix: the user sets the conversation timer cleanup timestamp unit incorrectly [Created [#3128](https://github.com/openimsdk/open-im-server/pull/3128)
* fix: seq conversion not reading env in docker environment [Created [#3131](https://github.com/openimsdk/open-im-server/pull/3131)

### Builds
* build: improve workflows contents. [Created [#3125](https://github.com/openimsdk/open-im-server/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-enterprise/compare/v3.8.3-e-v1.1.5...v3.8.3-patch.1-e-v1.1.5)

================================================
FILE: CHANGELOG/README.md
================================================
# CHANGELOGs

- [CHANGELOG-3.8.md](./CHANGELOG-3.8.md)



================================================
FILE: CODE_OF_CONDUCT.md
================================================
# 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.


================================================
FILE: CONTRIBUTING-zh_CN.md
================================================


# 如何给 OpenIM 贡献代码(提交 Pull Request)

<p align="center">
  <a href="./CONTRIBUTING.md">English</a> · 
  <a href="./CONTRIBUTING-zh_CN.md">中文</a> · 
  <a href="docs/contributing/CONTRIBUTING-UA.md">Українська</a> · 
  <a href="docs/contributing/CONTRIBUTING-CS.md">Česky</a> · 
  <a href="docs/contributing/CONTRIBUTING-HU.md">Magyar</a> · 
  <a href="docs/contributing/CONTRIBUTING-ES.md">Español</a> · 
  <a href="docs/contributing/CONTRIBUTING-FA.md">فارسی</a> · 
  <a href="docs/contributing/CONTRIBUTING-FR.md">Français</a> · 
  <a href="docs/contributing/CONTRIBUTING-DE.md">Deutsch</a> · 
  <a href="docs/contributing/CONTRIBUTING-PL.md">Polski</a> · 
  <a href="docs/contributing/CONTRIBUTING-ID.md">Indonesian</a> · 
  <a href="docs/contributing/CONTRIBUTING-FI.md">Suomi</a> · 
  <a href="docs/contributing/CONTRIBUTING-ML.md">മലയാളം</a> · 
  <a href="docs/contributing/CONTRIBUTING-JP.md">日本語</a> · 
  <a href="docs/contributing/CONTRIBUTING-NL.md">Nederlands</a> · 
  <a href="docs/contributing/CONTRIBUTING-IT.md">Italiano</a> · 
  <a href="docs/contributing/CONTRIBUTING-RU.md">Русский</a> · 
  <a href="docs/contributing/CONTRIBUTING-PTBR.md">Português (Brasil)</a> · 
  <a href="docs/contributing/CONTRIBUTING-EO.md">Esperanto</a> · 
  <a href="docs/contributing/CONTRIBUTING-KR.md">한국어</a> · 
  <a href="docs/contributing/CONTRIBUTING-AR.md">العربي</a> · 
  <a href="docs/contributing/CONTRIBUTING-VN.md">Tiếng Việt</a> · 
  <a href="docs/contributing/CONTRIBUTING-DA.md">Dansk</a> · 
  <a href="docs/contributing/CONTRIBUTING-GR.md">Ελληνικά</a> · 
  <a href="docs/contributing/CONTRIBUTING-TR.md">Türkçe</a>
</p>

本指南将以 [openimsdk/open-im-server](https://github.com/openimsdk/open-im-server) 为例,详细说明如何为 OpenIM 项目贡献代码。我们采用“一问题一分支”的策略,确保每个 Issue 都对应一个专门的分支,以便有效管理代码变更。

### 1. Fork 仓库
前往 [openimsdk/open-im-server](https://github.com/openimsdk/open-im-server) GitHub 页面,点击右上角的 "Fork" 按钮,将仓库 Fork 到你的 GitHub 账户下。

### 2. 克隆仓库
将你 Fork 的仓库克隆到本地:
```bash
git clone https://github.com/your-username/open-im-server.git
```

### 3. 设置远程上游
添加原始仓库为远程上游以便跟踪其更新:
```bash
git remote add upstream https://github.com/openimsdk/open-im-server.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/blob/main/docs/contrib/go-code.md)
- [代码约定](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md)

### 日志规范
- **禁止使用标准的 `log` 包**。
- 应使用 `"github.com/openimsdk/tools/log"` 包来打印日志,该包支持多种日志级别:`debug`、`info`、`warn`、`error`。
- **错误日志应仅在首次调用的函数中打印**,以防止日志重复,并确保错误的上下文清晰。

### 异常及错误处理
- **禁止使用 `panic`**:程序中不应使用 `panic`,以避免在遇到不可恢复的错误时突然终止。
- **错误包裹**:使用 `"github.com/openimsdk/tools/errs"` 来包裹错误,保持错误信息的完整性并增加调试便利。
- **错误传递**:如果函数本身不能处理错误,应将错误返回给调用者,而不是隐藏或忽略这些错误。


================================================
FILE: CONTRIBUTING.md
================================================
# How to Contribute to OpenIM (Submitting Pull Requests)

<p align="center">
  <a href="./CONTRIBUTING.md">English</a> · 
  <a href="./CONTRIBUTING-zh_CN.md">中文</a> · 
  <a href="docs/contributing/CONTRIBUTING-UA.md">Українська</a> · 
  <a href="docs/contributing/CONTRIBUTING-CS.md">Česky</a> · 
  <a href="docs/contributing/CONTRIBUTING-HU.md">Magyar</a> · 
  <a href="docs/contributing/CONTRIBUTING-ES.md">Español</a> · 
  <a href="docs/contributing/CONTRIBUTING-FA.md">فارسی</a> · 
  <a href="docs/contributing/CONTRIBUTING-FR.md">Français</a> · 
  <a href="docs/contributing/CONTRIBUTING-DE.md">Deutsch</a> · 
  <a href="docs/contributing/CONTRIBUTING-PL.md">Polski</a> · 
  <a href="docs/contributing/CONTRIBUTING-ID.md">Indonesian</a> · 
  <a href="docs/contributing/CONTRIBUTING-FI.md">Suomi</a> · 
  <a href="docs/contributing/CONTRIBUTING-ML.md">മലയാളം</a> · 
  <a href="docs/contributing/CONTRIBUTING-JP.md">日本語</a> · 
  <a href="docs/contributing/CONTRIBUTING-NL.md">Nederlands</a> · 
  <a href="docs/contributing/CONTRIBUTING-IT.md">Italiano</a> · 
  <a href="docs/contributing/CONTRIBUTING-RU.md">Русский</a> · 
  <a href="docs/contributing/CONTRIBUTING-PTBR.md">Português (Brasil)</a> · 
  <a href="docs/contributing/CONTRIBUTING-EO.md">Esperanto</a> · 
  <a href="docs/contributing/CONTRIBUTING-KR.md">한국어</a> · 
  <a href="docs/contributing/CONTRIBUTING-AR.md">العربي</a> · 
  <a href="docs/contributing/CONTRIBUTING-VN.md">Tiếng Việt</a> · 
  <a href="docs/contributing/CONTRIBUTING-DA.md">Dansk</a> · 
  <a href="docs/contributing/CONTRIBUTING-GR.md">Ελληνικά</a> · 
  <a href="docs/contributing/CONTRIBUTING-TR.md">Türkçe</a>
</p>

This guide will use [openimsdk/open-im-server](https://github.com/openimsdk/open-im-server) 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](https://github.com/openimsdk/open-im-server) 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.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.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/blob/main/docs/contrib/go-code.md)
- [Code Conventions](https://github.com/openimsdk/open-im-server/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.


================================================
FILE: Dockerfile
================================================
# 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"]


================================================
FILE: LICENSE
================================================
                                 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.


================================================
FILE: README.md
================================================
<p align="center">
    <a href="https://openim.io">
        <img src="./assets/logo-gif/openim-logo.gif" width="60%" height="30%"/>
    </a>
</p>

<div align="center">

[![Stars](https://img.shields.io/github/stars/openimsdk/open-im-server?style=for-the-badge&logo=github&colorB=ff69b4)](https://github.com/openimsdk/open-im-server/stargazers)
[![Forks](https://img.shields.io/github/forks/openimsdk/open-im-server?style=for-the-badge&logo=github&colorB=blue)](https://github.com/openimsdk/open-im-server/network/members)
[![Codecov](https://img.shields.io/codecov/c/github/openimsdk/open-im-server?style=for-the-badge&logo=codecov&colorB=orange)](https://app.codecov.io/gh/openimsdk/open-im-server)
[![Go Report Card](https://goreportcard.com/badge/github.com/openimsdk/open-im-server?style=for-the-badge)](https://goreportcard.com/report/github.com/openimsdk/open-im-server)
[![Go Reference](https://img.shields.io/badge/Go%20Reference-blue.svg?style=for-the-badge&logo=go&logoColor=white)](https://pkg.go.dev/github.com/openimsdk/open-im-server/v3)
[![License](https://img.shields.io/badge/license-Apache--2.0-green?style=for-the-badge)](https://github.com/openimsdk/open-im-server/blob/main/LICENSE)
[![Slack](https://img.shields.io/badge/Slack-500%2B-blueviolet?style=for-the-badge&logo=slack&logoColor=white)](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A)
[![Best Practices](https://img.shields.io/badge/Best%20Practices-purple?style=for-the-badge)](https://www.bestpractices.dev/projects/8045)
[![Good First Issues](https://img.shields.io/github/issues/openimsdk/open-im-server/good%20first%20issue?style=for-the-badge&logo=github)](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22)
[![Language](https://img.shields.io/badge/Language-Go-blue.svg?style=for-the-badge&logo=go&logoColor=white)](https://golang.org/)
[![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20OpenIM%20Guru-006BFF?style=for-the-badge)](https://gurubase.io/g/openim)

<p align="center">
  <a href="./README.md">English</a> · 
  <a href="./README_zh_CN.md">中文</a> · 
  <a href="./docs/readme/README_uk.md">Українська</a> · 
  <a href="./docs/readme/README_cs.md">Česky</a> · 
  <a href="./docs/readme/README_hu.md">Magyar</a> · 
  <a href="./docs/readme/README_es.md">Español</a> · 
  <a href="./docs/readme/README_fa.md">فارسی</a> · 
  <a href="./docs/readme/README_fr.md">Français</a> · 
  <a href="./docs/readme/README_de.md">Deutsch</a> · 
  <a href="./docs/readme/README_pl.md">Polski</a> · 
  <a href="./docs/readme/README_id.md">Indonesian</a> · 
  <a href="./docs/readme/README_fi.md">Suomi</a> · 
  <a href="./docs/readme/README_ml.md">മലയാളം</a> · 
  <a href="./docs/readme/README_ja.md">日本語</a> · 
  <a href="./docs/readme/README_nl.md">Nederlands</a> · 
  <a href="./docs/readme/README_it.md">Italiano</a> · 
  <a href="./docs/readme/README_ru.md">Русский</a> · 
  <a href="./docs/readme/README_pt_BR.md">Português (Brasil)</a> · 
  <a href="./docs/readme/README_eo.md">Esperanto</a> · 
  <a href="./docs/readme/README_ko.md">한국어</a> · 
  <a href="./docs/readme/README_ar.md">العربي</a> · 
  <a href="./docs/readme/README_vi.md">Tiếng Việt</a> · 
  <a href="./docs/readme/README_da.md">Dansk</a> · 
  <a href="./docs/readme/README_el.md">Ελληνικά</a> · 
  <a href="./docs/readme/README_tr.md">Türkçe</a>
</p>

</div>

</p>

## :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.

![App-OpenIM Relationship](./docs/images/oepnim-design.png)

## 🚀 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.

  ![Overall Architecture](./docs/images/architecture-layers.png)

## :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/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/blob/main/CONTRIBUTING.md) before submitting a Pull Request.

- **[Report a Bug](https://github.com/openimsdk/open-im-server/issues/new?assignees=&labels=bug&template=bug_report.md&title=)**
- **[Suggest a Feature](https://github.com/openimsdk/open-im-server/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)**
- **[Submit a Pull Request](https://github.com/openimsdk/open-im-server/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!

<a href="https://github.com/openimsdk/open-im-server/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=openimsdk/open-im-server" />
</a>


================================================
FILE: README_zh_CN.md
================================================
<p align="center">
    <a href="https://openim.io">
        <img src="./assets/logo-gif/openim-logo.gif" width="60%" height="30%"/>
    </a>
</p>

<div align="center">

[![Stars](https://img.shields.io/github/stars/openimsdk/open-im-server?style=for-the-badge&logo=github&colorB=ff69b4)](https://github.com/openimsdk/open-im-server/stargazers)
[![Forks](https://img.shields.io/github/forks/openimsdk/open-im-server?style=for-the-badge&logo=github&colorB=blue)](https://github.com/openimsdk/open-im-server/network/members)
[![Codecov](https://img.shields.io/codecov/c/github/openimsdk/open-im-server?style=for-the-badge&logo=codecov&colorB=orange)](https://app.codecov.io/gh/openimsdk/open-im-server)
[![Go Report Card](https://goreportcard.com/badge/github.com/openimsdk/open-im-server?style=for-the-badge)](https://goreportcard.com/report/github.com/openimsdk/open-im-server)
[![Go Reference](https://img.shields.io/badge/Go%20Reference-blue.svg?style=for-the-badge&logo=go&logoColor=white)](https://pkg.go.dev/github.com/openimsdk/open-im-server/v3)
[![License](https://img.shields.io/badge/license-Apache--2.0-green?style=for-the-badge)](https://github.com/openimsdk/open-im-server/blob/main/LICENSE)
[![Slack](https://img.shields.io/badge/Slack-500%2B-blueviolet?style=for-the-badge&logo=slack&logoColor=white)](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A)
[![Best Practices](https://img.shields.io/badge/Best%20Practices-purple?style=for-the-badge)](https://www.bestpractices.dev/projects/8045)
[![Good First Issues](https://img.shields.io/github/issues/openimsdk/open-im-server/good%20first%20issue?style=for-the-badge&logo=github)](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22)
[![Language](https://img.shields.io/badge/Language-Go-blue.svg?style=for-the-badge&logo=go&logoColor=white)](https://golang.org/)

<p align="center">
  <a href="./README.md">English</a> · 
  <a href="./README_zh_CN.md">中文</a> · 
  <a href="./docs/readme/README_uk.md">Українська</a> · 
  <a href="./docs/readme/README_cs.md">Česky</a> · 
  <a href="./docs/readme/README_hu.md">Magyar</a> · 
  <a href="./docs/readme/README_es.md">Español</a> · 
  <a href="./docs/readme/README_fa.md">فارسی</a> · 
  <a href="./docs/readme/README_fr.md">Français</a> · 
  <a href="./docs/readme/README_de.md">Deutsch</a> · 
  <a href="./docs/readme/README_pl.md">Polski</a> · 
  <a href="./docs/readme/README_id.md">Indonesian</a> · 
  <a href="./docs/readme/README_fi.md">Suomi</a> · 
  <a href="./docs/readme/README_ml.md">മലയാളം</a> · 
  <a href="./docs/readme/README_ja.md">日本語</a> · 
  <a href="./docs/readme/README_nl.md">Nederlands</a> · 
  <a href="./docs/readme/README_it.md">Italiano</a> · 
  <a href="./docs/readme/README_ru.md">Русский</a> · 
  <a href="./docs/readme/README_pt_BR.md">Português (Brasil)</a> · 
  <a href="./docs/readme/README_eo.md">Esperanto</a> · 
  <a href="./docs/readme/README_ko.md">한국어</a> · 
  <a href="./docs/readme/README_ar.md">العربي</a> · 
  <a href="./docs/readme/README_vi.md">Tiếng Việt</a> · 
  <a href="./docs/readme/README_da.md">Dansk</a> · 
  <a href="./docs/readme/README_el.md">Ελληνικά</a> · 
  <a href="./docs/readme/README_tr.md">Türkçe</a>
</p>

</div>

</p>

## :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 旨在为开发者提供必要的工具和框架,帮助他们在自己的应用中实现高效的即时通讯解决方案。

![App-OpenIM 关系](./docs/images/oepnim-design.png)

## 🚀 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**:通过事件前后的回调,向业务服务器发送请求,扩展更多的业务形态。

  ![整体架构](./docs/images/architecture-layers.png)

## :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/blob/main/CHANGELOG.md)**

## :writing_hand: 如何贡献

我们欢迎任何形式的贡献!在提交 Pull Request 之前,请确保阅读我们的[贡献者文档](https://github.com/openimsdk/open-im-server/blob/main/CONTRIBUTING.md)

- **[报告 Bug](https://github.com/openimsdk/open-im-server/issues/new?assignees=&labels=bug&template=bug_report.md&title=)**
- **[提出新特性](https://github.com/openimsdk/open-im-server/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)**
- **[提交 Pull Request](https://github.com/openimsdk/open-im-server/pulls)**

感谢您的贡献,一起来打造强大的即时通讯解决方案!

## :closed_book: 开源许可证 License

This software is licensed under the Apache License 2.0

## 🔮 Thanks to our contributors!

<a href="https://github.com/openimsdk/open-im-server/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=openimsdk/open-im-server" />
</a>


================================================
FILE: assets/README.md
================================================
# `/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) 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.

================================================
FILE: assets/colors.md
================================================
# 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*.


================================================
FILE: assets/demo/README.md
================================================
## :star2: Why OpenIM

**🔍 Function screenshot display**

<div align="center">


|             multiple message              |               Efficient meetings                |
| :---------------------------------------: | :---------------------------------------------: |
| ![multiple-message](./multiple-message.png) | ![efficient-meetings](./efficient-meetings.png) |
|      **One-to-one and group chats**       |     **Special features - Custom messages**      |
|      ![group-chat](./group-chat.png)      |   ![special-function](./special-function.png)    |

</div>


================================================
FILE: assets/logo/LICENSE
================================================
# The OpenIM logo files are licensed under a choice of either Apache-2.0 or CC-BY-4.0 (Creative Commons Attribution 4.0 International).

================================================
FILE: assets/logo-gif/LICENSE
================================================
# The OpenIM logo files are licensed under a choice of either Apache-2.0 or CC-BY-4.0 (Creative Commons Attribution 4.0 International).

================================================
FILE: bootstrap.bat
================================================
@echo off
SETLOCAL

mage -version >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
    echo Mage is already installed.
    GOTO DOWNLOAD
)

go version >nul 2>&1
IF NOT %ERRORLEVEL% EQU 0 (
    echo Go is not installed. Please install Go and try again.
    exit /b 1
)

echo Installing Mage...
go install github.com/magefile/mage@latest

mage -version >nul 2>&1
IF NOT %ERRORLEVEL% EQU 0 (
    echo Mage installation failed.
    echo Please ensure that %GOPATH%/bin is in your PATH.
    exit /b 1
)

echo Mage installed successfully.

:DOWNLOAD
go mod download

ENDLOCAL


================================================
FILE: bootstrap.sh
================================================
#!/bin/bash

if [[ ":$PATH:" == *":$HOME/.local/bin:"* ]]; then
    TARGET_DIR="$HOME/.local/bin"
else
    TARGET_DIR="/usr/local/bin"
    echo "Using /usr/local/bin as the installation directory. Might require sudo permissions."
fi

if ! command -v mage &> /dev/null; then
    echo "Installing Mage to $TARGET_DIR ..."
    GOBIN=$TARGET_DIR go install github.com/magefile/mage@latest
fi

if ! command -v mage &> /dev/null; then
    echo "Mage installation failed."
    echo "Please ensure that $TARGET_DIR is in your \$PATH."
    exit 1
fi

echo "Mage installed successfully."

go mod download


================================================
FILE: build/README.md
================================================
# Building OpenIM

Building OpenIM is easy if you take advantage of the containerized build environment. This document will help guide you through understanding this build process.

## Requirements

1. Docker, using one of the following configurations:
  * **macOS** Install Docker for Mac. See installation instructions [here](https://docs.docker.com/docker-for-mac/).
     **Note**: You will want to set the Docker VM to have at least 4GB of initial memory or building will likely fail.
  * **Linux with local Docker**  Install Docker according to the [instructions](https://docs.docker.com/installation/#installation) for your OS.
  * **Windows with Docker Desktop WSL2 backend**  Install Docker according to the [instructions](https://docs.docker.com/docker-for-windows/wsl-tech-preview/). Be sure to store your sources in the local Linux file system, not the Windows remote mount at `/mnt/c`.
  
  **Note**: You will need to check if Docker CLI plugin buildx is properly installed (`docker-buildx` file should be present in `~/.docker/cli-plugins`). You can install buildx according to the [instructions](https://github.com/docker/buildx/blob/master/README.md#installing).

2. **Optional** [Google Cloud SDK](https://developers.google.com/cloud/sdk/)

You must install and configure Google Cloud SDK if you want to upload your release to Google Cloud Storage and may safely omit this otherwise.

## Actions

About [Images packages](https://github.com/orgs/OpenIMSDK/packages?repo_name=Open-IM-Server)

All files in the `build/images` directory are not templated and are instead rendered by Github Actions, which is an automated process.

Trigger condition:
1. create a new tag with the format `vX.Y.Z` (e.g. `v1.0.0`)
2. push the tag to the remote repository
3. wait for the build to finish
4. download the artifacts from the release page

## Make images

**help info:**

```bash
$ make image.help
```

**build images:**

```bash
$ make image
```

## Overview

While it is possible to build OpenIM using a local golang installation, we have a build process that runs in a Docker container.  This simplifies initial set up and provides for a very consistent build and test environment.


## Basic Flow

The scripts directly under [`build/`](.) are used to build and test.  They will ensure that the `openim-build` Docker image is built (based on [`build/build-image/Dockerfile`](../Dockerfile) and after base image's `OPENIM_BUILD_IMAGE_CROSS_TAG` from Dockerfile is replaced with one of those actual tags of the base image, like `v1.13.9-2`) and then execute the appropriate command in that container.  These scripts will both ensure that the right data is cached from run to run for incremental builds and will copy the results back out of the container. You can specify a different registry/name and version for `openim-cross` by setting `OPENIM_CROSS_IMAGE` and `OPENIM_CROSS_VERSION`, see [`common.sh`](common.sh) for more details.

The `openim-build` container image is built by first creating a "context" directory in `_output/images/build-image`.  It is done there instead of at the root of the OpenIM repo to minimize the amount of data we need to package up when building the image.

There are 3 different containers instances that are run from this image.  The first is a "data" container to store all data that needs to persist across to support incremental builds. Next there is an "rsync" container that is used to transfer data in and out to the data container.  Lastly there is a "build" container that is used for actually doing build actions.  The data container persists across runs while the rsync and build containers are deleted after each use.

`rsync` is used transparently behind the scenes to efficiently move data in and out of the container.  This will use an ephemeral port picked by Docker.  You can modify this by setting the `OPENIM_RSYNC_PORT` env variable.

All Docker names are suffixed with a hash derived from the file path (to allow concurrent usage on things like CI machines) and a version number.  When the version number changes all state is cleared and clean build is started.  This allows the build infrastructure to be changed and signal to CI systems that old artifacts need to be deleted.

## Build artifacts
The build system output all its products to a top level directory in the source repository named `_output`.
These include the binary compiled packages (e.g. imctl, openim-api etc.) and archived Docker images.
If you intend to run a component with a docker image you will need to import it from this directory with


================================================
FILE: build/goreleaser.yaml
================================================
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com

before:
  hooks:
    - make clean
    # You may remove this if you don't use go modules.
    - make tidy
    - make copyright.add
    # you may remove this if you don't need go generate
    - go generate ./...

git:
  # What should be used to sort tags when gathering the current and previous
  # tags if there are more than one tag in the same commit.
  #
  # Default: '-version:refname'
  tag_sort: -version:creatordate

  # What should be used to specify prerelease suffix while sorting tags when gathering
  # the current and previous tags if there are more than one tag in the same commit.
  #
  # Since: v1.17
  prerelease_suffix: "-"

  # Tags to be ignored by GoReleaser.
  # This means that GoReleaser will not pick up tags that match any of the
  # provided values as either previous or current tags.
  #
  # Templates: allowed.
  # Since: v1.21.
  ignore_tags:
    - nightly
    # - "{{.Env.IGNORE_TAG}}"
  
snapshot:
  name_template: "{{ incpatch .Version }}-next"

# gomod:
#   proxy: true

report_sizes: true

# metadata:
#   mod_timestamp: "{{ .CommitTimestamp }}"

builds:
  - binary: openim-api
    id: openim-api
    main: ./cmd/openim-api/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-cmdutils
    id: openim-cmdutils
    main: ./cmd/openim-cmdutils/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-crontask
    id: openim-crontask
    main: ./cmd/openim-crontask/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-msggateway
    id: openim-msggateway
    main: ./cmd/openim-msggateway/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-msgtransfer
    id: openim-msgtransfer
    main: ./cmd/openim-msgtransfer/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-push
    id: openim-push
    main: ./cmd/openim-push/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-rpc-auth
    id: openim-rpc-auth
    main: ./cmd/openim-rpc/openim-rpc-auth/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-rpc-conversation
    id: openim-rpc-conversation
    main: ./cmd/openim-rpc/openim-rpc-conversation/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-rpc-friend
    id: openim-rpc-friend
    main: ./cmd/openim-rpc/openim-rpc-friend/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-rpc-group
    id: openim-rpc-group
    main: ./cmd/openim-rpc/openim-rpc-group/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-rpc-msg
    id: openim-rpc-msg
    main: ./cmd/openim-rpc/openim-rpc-msg/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-rpc-third
    id: openim-rpc-third
    main: ./cmd/openim-rpc/openim-rpc-third/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64

  - binary: openim-rpc-user
    id: openim-rpc-user
    main: ./cmd/openim-rpc/openim-rpc-user/main.go
    goos:
      - darwin
      - windows
      - linux
    goarch:
      - amd64
      - arm64


# TODO:Need a script, such as the init - release to help binary to find the right directory
# ,which can be compiled binary
archives:
  - format: tar.gz
    # this name template makes the OS and Arch compatible with the results of uname.
    name_template: >-
      {{ .ProjectName }}_
      {{- title .Os }}_
      {{- if eq .Arch "amd64" }}x86_64
      {{- else if eq .Arch "386" }}i386
      {{- else }}{{ .Arch }}{{ end }}
      {{- if .Arm }}v{{ .Arm }}{{ end }}

    # Set this to true if you want all files in the archive to be in a single directory.
    # If set to true and you extract the archive 'goreleaser_Linux_arm64.tar.gz',
    # you'll get a folder 'goreleaser_Linux_arm64'.
    # If set to false, all files are extracted separately.
    # You can also set it to a custom folder name (templating is supported).
    wrap_in_directory: true

    # use zip for windows archives
    files:
      - CHANGELOG/*
      - deployment/*
      - config/*
      - build/*
      - scripts/*
      - Makefile
      - install.sh
      - docs/*
      - src: "*.md"
        dst: docs

        # Strip parent folders when adding files to the archive.
        strip_parent: true

        # File info.
        # Not all fields are supported by all formats available formats.
        #
        # Default: copied from the source file
        info:
          # Templates: allowed (since v1.14)
          owner: root

          # Templates: allowed (since v1.14)
          group: root

          # Must be in time.RFC3339Nano format.
          #
          # Templates: allowed (since v1.14)
          mtime: "{{ .CommitDate }}"

          # File mode.
          mode: 0644

    format_overrides:
    - goos: windows
      format: zip

changelog:
  sort: asc
  use: github
  filters:
    exclude:
      - "^test:"
      - "^chore"
      - "merge conflict"
      - Merge pull request
      - Merge remote-tracking branch
      - Merge branch
      - go mod tidy
  groups:
    - title: Dependency updates
      regexp: '^.*?(feat|fix)\(deps\)!?:.+$'
      order: 300
    - title: "New Features"
      regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
      order: 100
    - title: "Security updates"
      regexp: '^.*?sec(\([[:word:]]+\))??!?:.+$'
      order: 150
    - title: "Bug fixes"
      regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$'
      order: 200
    - title: "Documentation updates"
      regexp: ^.*?doc(\([[:word:]]+\))??!?:.+$
      order: 400
    - title: "Build process updates"
      regexp: ^.*?build(\([[:word:]]+\))??!?:.+$
      order: 400
    - title: Other work
      order: 9999

# dockers:
#   - image_templates:
#       - "openimsdk/open-im-server:{{ .Tag }}-amd64"
#       - "ghcr.io/goreleaser/goreleaser:{{ .Tag }}-amd64"
#     dockerfile: build/images/openim-api/Dockerfile.release
#     ids: 
#       - openim-api
#     use: buildx
#     build_flag_templates:
#       - "--pull"
#       - "--label=io.artifacthub.package.readme-url=https://raw.githubusercontent.com/openimsdk/open-im-server/main/README.md"
#       - "--label=io.artifacthub.package.logo-url=hhttps://github.com/openimsdk/open-im-server/blob/main/assets/logo/openim-logo-green.png"
#       - '--label=io.artifacthub.package.maintainers=[{"name":"Xinwei Xiong","email":"3293172751nss@gmail.com"}]'
#       - "--label=io.artifacthub.package.license=Apace-2.0"
#       - "--label=org.opencontainers.image.description=OpenIM Open source top instant messaging system"
#       - "--label=org.opencontainers.image.created={{.Date}}"
#       - "--label=org.opencontainers.image.name={{.ProjectName}}"
#       - "--label=org.opencontainers.image.revision={{.FullCommit}}"
#       - "--label=org.opencontainers.image.version={{.Version}}"
#       - "--label=org.opencontainers.image.source={{.GitURL}}"
#       - "--platform=linux/amd64"
#     extra_files:
#       - scripts/entrypoint.sh
#   - image_templates:
#       - "goreleaser/goreleaser:{{ .Tag }}-arm64"
#       - "ghcr.io/goreleaser/goreleaser:{{ .Tag }}-arm64"
#     dockerfile: build/images/openim-api/Dockerfile.release
#     use: buildx
#     build_flag_templates:
#       - "--pull"
#       - "--label=io.artifacthub.package.readme-url=https://raw.githubusercontent.com/openimsdk/open-im-server/main/README.md"
#       - "--label=io.artifacthub.package.logo-url=hhttps://github.com/openimsdk/open-im-server/blob/main/assets/logo/openim-logo-green.png"
#       - '--label=io.artifacthub.package.maintainers=[{"name":"Xinwei Xiong","email":"3293172751nss@gmail.com"}]'
#       - "--label=io.artifacthub.package.license=Apace-2.0"
#       - "--label=org.opencontainers.image.description=OpenIM Open source top instant messaging system"
#       - "--label=org.opencontainers.image.created={{.Date}}"
#       - "--label=org.opencontainers.image.name={{.ProjectName}}"
#       - "--label=org.opencontainers.image.revision={{.FullCommit}}"
#       - "--label=org.opencontainers.image.version={{.Version}}"
#       - "--label=org.opencontainers.image.source={{.GitURL}}"
#       - "--platform=linux/arm64"
#     goarch: arm64
#     extra_files:
#       - scripts/entrypoint.sh

# docker_manifests:
#   - name_template: "goreleaser/goreleaser:{{ .Tag }}"
#     image_templates:
#       - "goreleaser/goreleaser:{{ .Tag }}-amd64"
#       - "goreleaser/goreleaser:{{ .Tag }}-arm64"
#   - name_template: "ghcr.io/goreleaser/goreleaser:{{ .Tag }}"
#     image_templates:
#       - "ghcr.io/goreleaser/goreleaser:{{ .Tag }}-amd64"
#       - "ghcr.io/goreleaser/goreleaser:{{ .Tag }}-arm64"
#   - name_template: "goreleaser/goreleaser:latest"
#     image_templates:
#       - "goreleaser/goreleaser:{{ .Tag }}-amd64"
#       - "goreleaser/goreleaser:{{ .Tag }}-arm64"
#   - name_template: "ghcr.io/goreleaser/goreleaser:latest"
#     image_templates:
#       - "ghcr.io/goreleaser/goreleaser:{{ .Tag }}-amd64"
#       - "ghcr.io/goreleaser/goreleaser:{{ .Tag }}-arm64"

nfpms:
  - id: packages
    builds:
      - openim-api
      - openim-cmdutils
      - openim-crontask
      - openim-msggateway
      - openim-msgtransfer
      - openim-push
      - openim-rpc-auth
      - openim-rpc-conversation
      - openim-rpc-friend
      - openim-rpc-group
      - openim-rpc-msg
      - openim-rpc-third
      - openim-rpc-user
    # Your app's vendor.
    vendor: OpenIMSDK
    homepage: https://github.com/openimsdk/open-im-server
    maintainer: kubbot <https://github.com/kubbot>
    description: |-
      Auto sync github labels
      kubbot && openimbot
    license: MIT
    formats:
      - apk
      - deb
      - rpm
      - termux.deb # Since: v1.11
      - archlinux # Since: v1.13
    dependencies:
      - git
    recommends:
      - golang


# The lines beneath this are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj

# Default: './dist'
dist: ./_output/dist

# .goreleaser.yaml
milestones:
  # You can have multiple milestone configs
  -
    # Repository for the milestone
    # Default is extracted from the origin remote URL
    repo:
      owner: OpenIMSDK
      name: Open-IM-Server

    # Whether to close the milestone
    close: true

    # Fail release on errors, such as missing milestone.
    fail_on_error: false

    # Name of the milestone
    #
    # Default: '{{ .Tag }}'
    name_template: "Current Release"

# publishers:
#   - name: "fury.io"
#     ids:
#       - packages
#     dir: "{{ dir .ArtifactPath }}"
#     cmd: |
#       bash -c '
#       if [[ "{{ .Tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
#         curl -F package=@{{ .ArtifactName }} https://{{ .Env.FURY_TOKEN }}@push.fury.io/{{ .Env.USERNAME }}/
#       else
#         echo "Skipping deployment: Non-production release detected"
#       fi'

checksum:
  name_template: "{{ .ProjectName }}_checksums.txt"
  algorithm: sha256

release:
  prerelease: auto


================================================
FILE: build/images/Dockerfile
================================================
# # Copyright © 2023 OpenIM. All rights reserved.
# #
# # Licensed under the Apache License, Version 2.0 (the "License");
# # you may not use this file except in compliance with the License.
# # You may obtain a copy of the License at
# #
# #     http://www.apache.org/licenses/LICENSE-2.0
# #
# # Unless required by applicable law or agreed to in writing, software
# # distributed under the License is distributed on an "AS IS" BASIS,
# # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# # See the License for the specific language governing permissions and
# # limitations under the License.

# FROM BASE_IMAGE

# WORKDIR ${SERVER_WORKDIR}

# # Set HTTP proxy
# ARG BINARY_NAME

# COPY BINARY_NAME ./bin/BINARY_NAME

# ENTRYPOINT ["./bin/BINARY_NAME"]

================================================
FILE: build/images/openim-api/Dockerfile
================================================
# 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 tidy

RUN go build -o _output/openim-api ./cmd/openim-api

# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-api"]


================================================
FILE: build/images/openim-crontask/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-crontask ./cmd/openim-crontask


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-crontask"]


================================================
FILE: build/images/openim-msggateway/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-msggateway ./cmd/openim-msggateway


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-msggateway"]


================================================
FILE: build/images/openim-msgtransfer/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-msgtransfer ./cmd/openim-msgtransfer


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-msgtransfer"]


================================================
FILE: build/images/openim-push/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-push ./cmd/openim-push


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-push"]


================================================
FILE: build/images/openim-rpc-auth/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-rpc-auth ./cmd/openim-rpc/openim-rpc-auth


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-rpc-auth"]


================================================
FILE: build/images/openim-rpc-conversation/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-rpc-conversation ./cmd/openim-rpc/openim-rpc-conversation


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-rpc-conversation"]


================================================
FILE: build/images/openim-rpc-friend/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-rpc-friend ./cmd/openim-rpc/openim-rpc-friend


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-rpc-friend"]


================================================
FILE: build/images/openim-rpc-group/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-rpc-group ./cmd/openim-rpc/openim-rpc-group


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-rpc-group"]


================================================
FILE: build/images/openim-rpc-msg/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-rpc-msg ./cmd/openim-rpc/openim-rpc-msg


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-rpc-msg"]


================================================
FILE: build/images/openim-rpc-third/Dockerfile
================================================
# 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 tidy



RUN go build -o _output/openim-rpc-third ./cmd/openim-rpc/openim-rpc-third


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-rpc-third"]


================================================
FILE: build/images/openim-rpc-user/Dockerfile
================================================
# 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 tidy

RUN go build -o _output/openim-rpc-user ./cmd/openim-rpc/openim-rpc-user


# Using Alpine Linux for the final image
FROM alpine:latest

# 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

# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/openim-rpc-user"]


================================================
FILE: build/images/openim-tools/component/Dockerfile
================================================
# # Copyright © 2023 OpenIM. All rights reserved.
# #
# # Licensed under the Apache License, Version 2.0 (the "License");
# # you may not use this file except in compliance with the License.
# # You may obtain a copy of the License at
# #
# #     http://www.apache.org/licenses/LICENSE-2.0
# #
# # Unless required by applicable law or agreed to in writing, software
# # distributed under the License is distributed on an "AS IS" BASIS,
# # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# # See the License for the specific language governing permissions and
# # limitations under the License.

# # OpenIM base image: https://github.com/openim-sigs/openim-base-image

# # Set go mod installation source and proxy

# FROM golang:1.20 AS builder

# 

# WORKDIR /openim/openim-server

# 
# ENV GOPROXY=$GOPROXY

# COPY go.mod go.sum ./
# RUN go mod download

# COPY . .

# RUN make clean
# RUN make build BINS=component

# # FROM ghcr.io/openim-sigs/openim-bash-image:latest
# FROM ghcr.io/openim-sigs/openim-bash-image:latest

# WORKDIR /openim/openim-server

# COPY --from=builder /openim/openim-server/_output/bin/tools /openim/openim-server/_output/bin/tools/
# COPY --from=builder /openim/openim-server/config /openim/openim-server/config

# ENV OPENIM_SERVER_CONFIG_NAME=/openim/openim-server/config

# RUN mv ${OPENIM_SERVER_BINDIR}/platforms/$(get_os)/$(get_arch)/component /usr/bin/component

# ENTRYPOINT ["bash", "-c", "component -c $OPENIM_SERVER_CONFIG_NAME"]


# 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

# ENV BINS=openim-rpc-user

# Optionally build your application if needed
# RUN mage build ${BINS} check-free-memory seq || true
RUN mage build check-free-memory seq || true

# Using Alpine Linux with Go environment for the final image
FROM golang:1.22-alpine

# Install necessary packages, such as bash
RUN apk add 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 echo -e "serviceBinaries:\n  \n" \
    > $SERVER_DIR/start-config.yml && \
    echo -e "toolBinaries:\n  - check-free-memory\n  - seq\n" >> $SERVER_DIR/start-config.yml && \
    echo "maxFileDescriptors: 10000" >> $SERVER_DIR/start-config.yml

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"]


================================================
FILE: cmd/main.go
================================================
package main

import (
	"bytes"
	"context"
	"flag"
	"fmt"
	"net"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/mitchellh/mapstructure"
	"github.com/openimsdk/open-im-server/v3/internal/api"
	"github.com/openimsdk/open-im-server/v3/internal/msggateway"
	"github.com/openimsdk/open-im-server/v3/internal/msgtransfer"
	"github.com/openimsdk/open-im-server/v3/internal/push"
	"github.com/openimsdk/open-im-server/v3/internal/rpc/auth"
	"github.com/openimsdk/open-im-server/v3/internal/rpc/conversation"
	"github.com/openimsdk/open-im-server/v3/internal/rpc/group"
	"github.com/openimsdk/open-im-server/v3/internal/rpc/msg"
	"github.com/openimsdk/open-im-server/v3/internal/rpc/relation"
	"github.com/openimsdk/open-im-server/v3/internal/rpc/third"
	"github.com/openimsdk/open-im-server/v3/internal/rpc/user"
	"github.com/openimsdk/open-im-server/v3/internal/tools/cron"
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
	"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
	"github.com/openimsdk/open-im-server/v3/version"
	"github.com/openimsdk/tools/discovery"
	"github.com/openimsdk/tools/discovery/standalone"
	"github.com/openimsdk/tools/log"
	"github.com/openimsdk/tools/system/program"
	"github.com/openimsdk/tools/utils/datautil"
	"github.com/spf13/viper"
	"google.golang.org/grpc"
)

func init() {
	config.SetStandalone()
	prommetrics.RegistryAll()
}

func main() {
	var configPath string
	flag.StringVar(&configPath, "c", "", "config path")
	flag.Parse()
	if configPath == "" {
		_, _ = fmt.Fprintln(os.Stderr, "config path is empty")
		os.Exit(1)
		return
	}
	cmd := newCmds(configPath)
	putCmd(cmd, false, auth.Start)
	putCmd(cmd, false, conversation.Start)
	putCmd(cmd, false, relation.Start)
	putCmd(cmd, false, group.Start)
	putCmd(cmd, false, msg.Start)
	putCmd(cmd, false, third.Start)
	putCmd(cmd, false, user.Start)
	putCmd(cmd, false, push.Start)
	putCmd(cmd, true, msggateway.Start)
	putCmd(cmd, true, msgtransfer.Start)
	putCmd(cmd, true, api.Start)
	putCmd(cmd, true, cron.Start)
	ctx := context.Background()
	if err := cmd.run(ctx); err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "server exit %s", err)
		os.Exit(1)
		return
	}
}

func newCmds(confPath string) *cmds {
	return &cmds{confPath: confPath}
}

type cmdName struct {
	Name  string
	Func  func(ctx context.Context) error
	B
Download .txt
gitextract_q8p9a5l9/

├── .dockerignore
├── .gitattributes
├── .github/
│   ├── .codecov.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   ├── config.yml
│   │   ├── deployment.yml
│   │   ├── documentation.md
│   │   ├── feature-request.yml
│   │   ├── other.yml
│   │   └── rfc.md
│   ├── sync-release.yml
│   └── workflows/
│       ├── auto-assign-issue.yml
│       ├── auto-invite-comment.yml
│       ├── changelog.yml
│       ├── cla-assistant.yml
│       ├── cleanup-after-milestone-prs-merged.yml
│       ├── codeql-analysis.yml
│       ├── comment-check.yml
│       ├── docker-build-and-release-services-images.yml
│       ├── go-build-test.yml
│       ├── help-comment-issue.yml
│       ├── issue-translator.yml
│       ├── merge-from-milestone.yml
│       ├── publish-docker-image.yml
│       ├── remove-unused-labels.yml
│       ├── reopen-issue.yml
│       ├── update-version-file-on-release.yml
│       └── user-first-interaction.yml
├── .gitignore
├── .golangci.yml
├── CHANGELOG/
│   ├── CHANGELOG-3.8.md
│   └── README.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING-zh_CN.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── README_zh_CN.md
├── assets/
│   ├── README.md
│   ├── colors.md
│   ├── demo/
│   │   └── README.md
│   ├── logo/
│   │   └── LICENSE
│   └── logo-gif/
│       └── LICENSE
├── bootstrap.bat
├── bootstrap.sh
├── build/
│   ├── README.md
│   ├── goreleaser.yaml
│   └── images/
│       ├── Dockerfile
│       ├── openim-api/
│       │   └── Dockerfile
│       ├── openim-crontask/
│       │   └── Dockerfile
│       ├── openim-msggateway/
│       │   └── Dockerfile
│       ├── openim-msgtransfer/
│       │   └── Dockerfile
│       ├── openim-push/
│       │   └── Dockerfile
│       ├── openim-rpc-auth/
│       │   └── Dockerfile
│       ├── openim-rpc-conversation/
│       │   └── Dockerfile
│       ├── openim-rpc-friend/
│       │   └── Dockerfile
│       ├── openim-rpc-group/
│       │   └── Dockerfile
│       ├── openim-rpc-msg/
│       │   └── Dockerfile
│       ├── openim-rpc-third/
│       │   └── Dockerfile
│       ├── openim-rpc-user/
│       │   └── Dockerfile
│       └── openim-tools/
│           └── component/
│               └── Dockerfile
├── cmd/
│   ├── main.go
│   ├── openim-api/
│   │   └── main.go
│   ├── openim-cmdutils/
│   │   └── main.go
│   ├── openim-crontask/
│   │   └── main.go
│   ├── openim-msggateway/
│   │   └── main.go
│   ├── openim-msgtransfer/
│   │   └── main.go
│   ├── openim-push/
│   │   └── main.go
│   └── openim-rpc/
│       ├── openim-rpc-auth/
│       │   └── main.go
│       ├── openim-rpc-conversation/
│       │   └── main.go
│       ├── openim-rpc-friend/
│       │   └── main.go
│       ├── openim-rpc-group/
│       │   └── main.go
│       ├── openim-rpc-msg/
│       │   └── main.go
│       ├── openim-rpc-third/
│       │   └── main.go
│       └── openim-rpc-user/
│           └── main.go
├── config/
│   ├── README.md
│   ├── README_zh_CN.md
│   ├── alertmanager.yml
│   ├── discovery.yml
│   ├── email.tmpl
│   ├── grafana-template/
│   │   └── Demo.json
│   ├── instance-down-rules.yml
│   ├── kafka.yml
│   ├── local-cache.yml
│   ├── log.yml
│   ├── minio.yml
│   ├── mongodb.yml
│   ├── notification.yml
│   ├── openim-api.yml
│   ├── openim-crontask.yml
│   ├── openim-msggateway.yml
│   ├── openim-msgtransfer.yml
│   ├── openim-push.yml
│   ├── openim-rpc-auth.yml
│   ├── openim-rpc-conversation.yml
│   ├── openim-rpc-friend.yml
│   ├── openim-rpc-group.yml
│   ├── openim-rpc-msg.yml
│   ├── openim-rpc-third.yml
│   ├── openim-rpc-user.yml
│   ├── prometheus.yml
│   ├── redis.yml
│   ├── share.yml
│   └── webhooks.yml
├── deployments/
│   ├── Readme.md
│   └── deploy/
│       ├── clusterRole.yml
│       ├── ingress.yml
│       ├── kafka-secret.yml
│       ├── kafka-service.yml
│       ├── kafka-statefulset.yml
│       ├── minio-secret.yml
│       ├── minio-service.yml
│       ├── minio-statefulset.yml
│       ├── mongo-secret.yml
│       ├── mongo-service.yml
│       ├── mongo-statefulset.yml
│       ├── openim-api-deployment.yml
│       ├── openim-api-service.yml
│       ├── openim-config.yml
│       ├── openim-crontask-deployment.yml
│       ├── openim-msggateway-deployment.yml
│       ├── openim-msggateway-service.yml
│       ├── openim-msgtransfer-deployment.yml
│       ├── openim-msgtransfer-service.yml
│       ├── openim-push-deployment.yml
│       ├── openim-push-service.yml
│       ├── openim-rpc-auth-deployment.yml
│       ├── openim-rpc-auth-service.yml
│       ├── openim-rpc-conversation-deployment.yml
│       ├── openim-rpc-conversation-service.yml
│       ├── openim-rpc-friend-deployment.yml
│       ├── openim-rpc-friend-service.yml
│       ├── openim-rpc-group-deployment.yml
│       ├── openim-rpc-group-service.yml
│       ├── openim-rpc-msg-deployment.yml
│       ├── openim-rpc-msg-service.yml
│       ├── openim-rpc-third-deployment.yml
│       ├── openim-rpc-third-service.yml
│       ├── openim-rpc-user-deployment.yml
│       ├── openim-rpc-user-service.yml
│       ├── redis-secret.yml
│       ├── redis-service.yml
│       └── redis-statefulset.yml
├── docker-compose.yml
├── docs/
│   ├── .generated_docs
│   ├── CODEOWNERS
│   ├── README.md
│   ├── contrib/
│   │   ├── README.md
│   │   ├── api.md
│   │   ├── bash-log.md
│   │   ├── cicd-actions.md
│   │   ├── code-conventions.md
│   │   ├── commit.md
│   │   ├── development.md
│   │   ├── directory.md
│   │   ├── environment.md
│   │   ├── error-code.md
│   │   ├── git-workflow.md
│   │   ├── gitcherry-pick.md
│   │   ├── github-workflow.md
│   │   ├── go-code.md
│   │   ├── go-code1.md
│   │   ├── go-doc.md
│   │   ├── images.md
│   │   ├── init-config.md
│   │   ├── install-docker.md
│   │   ├── install-openim-linux-system.md
│   │   ├── kafka.md
│   │   ├── linux-development.md
│   │   ├── local-actions.md
│   │   ├── logging.md
│   │   ├── mac-developer-deployment-guide.md
│   │   ├── offline-deployment.md
│   │   ├── prometheus-grafana.md
│   │   ├── protoc-tools.md
│   │   ├── release.md
│   │   ├── test.md
│   │   ├── util-go.md
│   │   ├── util-makefile.md
│   │   ├── util-scripts.md
│   │   └── version.md
│   ├── contributing/
│   │   ├── CONTRIBUTING-JP.md
│   │   └── CONTRIBUTING-PL.md
│   └── readme/
│       ├── README_cs.md
│       ├── README_da.md
│       ├── README_el.md
│       ├── README_es.md
│       ├── README_fa.md
│       ├── README_fr.md
│       ├── README_hu.md
│       ├── README_ja.md
│       ├── README_ko.md
│       ├── README_tr.md
│       ├── README_uk.md
│       └── README_vi.md
├── go.mod
├── go.sum
├── install.sh
├── internal/
│   ├── api/
│   │   ├── auth.go
│   │   ├── config_manager.go
│   │   ├── conversation.go
│   │   ├── custom_validator.go
│   │   ├── friend.go
│   │   ├── group.go
│   │   ├── init.go
│   │   ├── jssdk/
│   │   │   ├── jssdk.go
│   │   │   ├── sort.go
│   │   │   └── tools.go
│   │   ├── msg.go
│   │   ├── prometheus_discovery.go
│   │   ├── ratelimit.go
│   │   ├── router.go
│   │   ├── third.go
│   │   └── user.go
│   ├── msggateway/
│   │   ├── callback.go
│   │   ├── client.go
│   │   ├── client_conn.go
│   │   ├── compressor.go
│   │   ├── compressor_test.go
│   │   ├── constant.go
│   │   ├── context.go
│   │   ├── encoder.go
│   │   ├── http_error.go
│   │   ├── hub_server.go
│   │   ├── init.go
│   │   ├── message_handler.go
│   │   ├── online.go
│   │   ├── options.go
│   │   ├── subscription.go
│   │   ├── user_map.go
│   │   └── ws_server.go
│   ├── msgtransfer/
│   │   ├── callback.go
│   │   ├── init.go
│   │   ├── online_history_msg_handler.go
│   │   └── online_msg_to_mongo_handler.go
│   ├── push/
│   │   ├── callback.go
│   │   ├── offlinepush/
│   │   │   ├── dummy/
│   │   │   │   └── push.go
│   │   │   ├── fcm/
│   │   │   │   └── push.go
│   │   │   ├── getui/
│   │   │   │   ├── body.go
│   │   │   │   └── push.go
│   │   │   ├── jpush/
│   │   │   │   ├── body/
│   │   │   │   │   ├── audience.go
│   │   │   │   │   ├── message.go
│   │   │   │   │   ├── notification.go
│   │   │   │   │   ├── options.go
│   │   │   │   │   ├── platform.go
│   │   │   │   │   └── pushobj.go
│   │   │   │   └── push.go
│   │   │   ├── offlinepusher.go
│   │   │   └── options/
│   │   │       └── options.go
│   │   ├── offlinepush_handler.go
│   │   ├── onlinepusher.go
│   │   ├── push.go
│   │   └── push_handler.go
│   ├── rpc/
│   │   ├── auth/
│   │   │   └── auth.go
│   │   ├── conversation/
│   │   │   ├── callback.go
│   │   │   ├── conversation.go
│   │   │   ├── db_map.go
│   │   │   ├── notification.go
│   │   │   └── sync.go
│   │   ├── group/
│   │   │   ├── cache.go
│   │   │   ├── callback.go
│   │   │   ├── convert.go
│   │   │   ├── db_map.go
│   │   │   ├── fill.go
│   │   │   ├── group.go
│   │   │   ├── notification.go
│   │   │   ├── statistics.go
│   │   │   └── sync.go
│   │   ├── incrversion/
│   │   │   ├── batch_option.go
│   │   │   └── option.go
│   │   ├── msg/
│   │   │   ├── as_read.go
│   │   │   ├── callback.go
│   │   │   ├── clear.go
│   │   │   ├── delete.go
│   │   │   ├── filter.go
│   │   │   ├── msg_status.go
│   │   │   ├── notification.go
│   │   │   ├── revoke.go
│   │   │   ├── send.go
│   │   │   ├── seq.go
│   │   │   ├── server.go
│   │   │   ├── statistics.go
│   │   │   ├── sync_msg.go
│   │   │   ├── utils.go
│   │   │   └── verify.go
│   │   ├── relation/
│   │   │   ├── black.go
│   │   │   ├── callback.go
│   │   │   ├── friend.go
│   │   │   ├── notification.go
│   │   │   └── sync.go
│   │   ├── third/
│   │   │   ├── log.go
│   │   │   ├── s3.go
│   │   │   ├── third.go
│   │   │   └── tool.go
│   │   └── user/
│   │       ├── callback.go
│   │       ├── config.go
│   │       ├── notification.go
│   │       ├── online.go
│   │       ├── statistics.go
│   │       └── user.go
│   └── tools/
│       └── cron/
│           ├── cron_task.go
│           ├── cron_test.go
│           ├── dist_look.go
│           ├── msg.go
│           ├── s3.go
│           └── user_msg.go
├── magefile.go
├── magefile_unix.go
├── magefile_windows.go
├── pkg/
│   ├── apistruct/
│   │   ├── config_manager.go
│   │   ├── doc.go
│   │   ├── manage.go
│   │   ├── msg.go
│   │   └── public.go
│   ├── authverify/
│   │   ├── doc.go
│   │   └── token.go
│   ├── callbackstruct/
│   │   ├── common.go
│   │   ├── constant.go
│   │   ├── conversation.go
│   │   ├── doc.go
│   │   ├── friend.go
│   │   ├── group.go
│   │   ├── message.go
│   │   ├── msg_gateway.go
│   │   ├── push.go
│   │   ├── revoke.go
│   │   └── user.go
│   ├── common/
│   │   ├── cmd/
│   │   │   ├── api.go
│   │   │   ├── auth.go
│   │   │   ├── conversation.go
│   │   │   ├── cron_task.go
│   │   │   ├── doc.go
│   │   │   ├── friend.go
│   │   │   ├── group.go
│   │   │   ├── msg.go
│   │   │   ├── msg_gateway.go
│   │   │   ├── msg_gateway_test.go
│   │   │   ├── msg_transfer.go
│   │   │   ├── msg_utils.go
│   │   │   ├── push.go
│   │   │   ├── root.go
│   │   │   ├── third.go
│   │   │   └── user.go
│   │   ├── config/
│   │   │   ├── config.go
│   │   │   ├── constant.go
│   │   │   ├── doc.go
│   │   │   ├── env.go
│   │   │   ├── global.go
│   │   │   ├── load_config.go
│   │   │   ├── load_config_test.go
│   │   │   └── parse.go
│   │   ├── convert/
│   │   │   ├── auth.go
│   │   │   ├── black.go
│   │   │   ├── conversation.go
│   │   │   ├── doc.go
│   │   │   ├── friend.go
│   │   │   ├── group.go
│   │   │   ├── msg.go
│   │   │   ├── user.go
│   │   │   └── user_test.go
│   │   ├── discovery/
│   │   │   ├── direct/
│   │   │   │   ├── direct_resolver.go
│   │   │   │   ├── directconn.go
│   │   │   │   └── doc.go
│   │   │   ├── discoveryregister.go
│   │   │   ├── discoveryregister_test.go
│   │   │   ├── doc.go
│   │   │   ├── etcd/
│   │   │   │   ├── config_manager.go
│   │   │   │   └── const.go
│   │   │   └── kubernetes/
│   │   │       ├── doc.go
│   │   │       └── kubernetes.go
│   │   ├── ginprometheus/
│   │   │   ├── doc.go
│   │   │   └── ginprometheus.go
│   │   ├── prommetrics/
│   │   │   ├── api.go
│   │   │   ├── grpc_auth.go
│   │   │   ├── grpc_msg.go
│   │   │   ├── grpc_msggateway.go
│   │   │   ├── grpc_push.go
│   │   │   ├── grpc_user.go
│   │   │   ├── prommetrics.go
│   │   │   ├── prommetrics_test.go
│   │   │   ├── rpc.go
│   │   │   └── transfer.go
│   │   ├── servererrs/
│   │   │   ├── code.go
│   │   │   ├── doc.go
│   │   │   ├── predefine.go
│   │   │   └── relation.go
│   │   ├── startrpc/
│   │   │   ├── circuitbreaker.go
│   │   │   ├── mw.go
│   │   │   ├── ratelimit.go
│   │   │   ├── start.go
│   │   │   └── tools.go
│   │   ├── storage/
│   │   │   ├── cache/
│   │   │   │   ├── batch_handler.go
│   │   │   │   ├── black.go
│   │   │   │   ├── cachekey/
│   │   │   │   │   ├── black.go
│   │   │   │   │   ├── client_config.go
│   │   │   │   │   ├── conversation.go
│   │   │   │   │   ├── doc.go
│   │   │   │   │   ├── friend.go
│   │   │   │   │   ├── group.go
│   │   │   │   │   ├── msg.go
│   │   │   │   │   ├── online.go
│   │   │   │   │   ├── s3.go
│   │   │   │   │   ├── seq.go
│   │   │   │   │   ├── third.go
│   │   │   │   │   ├── token.go
│   │   │   │   │   └── user.go
│   │   │   │   ├── client_config.go
│   │   │   │   ├── conversation.go
│   │   │   │   ├── doc.go
│   │   │   │   ├── friend.go
│   │   │   │   ├── group.go
│   │   │   │   ├── mcache/
│   │   │   │   │   ├── minio.go
│   │   │   │   │   ├── msg_cache.go
│   │   │   │   │   ├── online.go
│   │   │   │   │   ├── seq_conversation.go
│   │   │   │   │   ├── third.go
│   │   │   │   │   ├── token.go
│   │   │   │   │   └── tools.go
│   │   │   │   ├── msg.go
│   │   │   │   ├── online.go
│   │   │   │   ├── redis/
│   │   │   │   │   ├── batch.go
│   │   │   │   │   ├── batch_handler.go
│   │   │   │   │   ├── batch_test.go
│   │   │   │   │   ├── black.go
│   │   │   │   │   ├── client_config.go
│   │   │   │   │   ├── conversation.go
│   │   │   │   │   ├── friend.go
│   │   │   │   │   ├── group.go
│   │   │   │   │   ├── lua_script.go
│   │   │   │   │   ├── lua_script_test.go
│   │   │   │   │   ├── minio.go
│   │   │   │   │   ├── msg.go
│   │   │   │   │   ├── online.go
│   │   │   │   │   ├── online_test.go
│   │   │   │   │   ├── redis_shard_manager.go
│   │   │   │   │   ├── s3.go
│   │   │   │   │   ├── seq_conversation.go
│   │   │   │   │   ├── seq_conversation_test.go
│   │   │   │   │   ├── seq_user.go
│   │   │   │   │   ├── seq_user_test.go
│   │   │   │   │   ├── third.go
│   │   │   │   │   ├── token.go
│   │   │   │   │   └── user.go
│   │   │   │   ├── s3.go
│   │   │   │   ├── seq_conversation.go
│   │   │   │   ├── seq_user.go
│   │   │   │   ├── third.go
│   │   │   │   ├── token.go
│   │   │   │   └── user.go
│   │   │   ├── common/
│   │   │   │   └── types.go
│   │   │   ├── controller/
│   │   │   │   ├── auth.go
│   │   │   │   ├── black.go
│   │   │   │   ├── client_config.go
│   │   │   │   ├── conversation.go
│   │   │   │   ├── doc.go
│   │   │   │   ├── friend.go
│   │   │   │   ├── group.go
│   │   │   │   ├── msg.go
│   │   │   │   ├── msg_transfer.go
│   │   │   │   ├── push.go
│   │   │   │   ├── s3.go
│   │   │   │   ├── third.go
│   │   │   │   └── user.go
│   │   │   ├── database/
│   │   │   │   ├── black.go
│   │   │   │   ├── cache.go
│   │   │   │   ├── client_config.go
│   │   │   │   ├── conversation.go
│   │   │   │   ├── doc.go
│   │   │   │   ├── friend.go
│   │   │   │   ├── friend_request.go
│   │   │   │   ├── group.go
│   │   │   │   ├── group_member.go
│   │   │   │   ├── group_request.go
│   │   │   │   ├── log.go
│   │   │   │   ├── mgo/
│   │   │   │   │   ├── black.go
│   │   │   │   │   ├── cache.go
│   │   │   │   │   ├── cache_test.go
│   │   │   │   │   ├── client_config.go
│   │   │   │   │   ├── conversation.go
│   │   │   │   │   ├── doc.go
│   │   │   │   │   ├── friend.go
│   │   │   │   │   ├── friend_request.go
│   │   │   │   │   ├── group.go
│   │   │   │   │   ├── group_member.go
│   │   │   │   │   ├── group_request.go
│   │   │   │   │   ├── helpers.go
│   │   │   │   │   ├── log.go
│   │   │   │   │   ├── msg.go
│   │   │   │   │   ├── msg_test.go
│   │   │   │   │   ├── object.go
│   │   │   │   │   ├── seq_conversation.go
│   │   │   │   │   ├── seq_conversation_test.go
│   │   │   │   │   ├── seq_user.go
│   │   │   │   │   ├── user.go
│   │   │   │   │   ├── version_log.go
│   │   │   │   │   └── version_test.go
│   │   │   │   ├── msg.go
│   │   │   │   ├── name.go
│   │   │   │   ├── object.go
│   │   │   │   ├── seq.go
│   │   │   │   ├── seq_user.go
│   │   │   │   ├── user.go
│   │   │   │   └── version_log.go
│   │   │   ├── kafka/
│   │   │   │   ├── config.go
│   │   │   │   ├── consumer_group.go
│   │   │   │   ├── producer.go
│   │   │   │   ├── sarama.go
│   │   │   │   ├── tls.go
│   │   │   │   ├── util.go
│   │   │   │   └── verify.go
│   │   │   ├── model/
│   │   │   │   ├── application.go
│   │   │   │   ├── black.go
│   │   │   │   ├── cache.go
│   │   │   │   ├── client_config.go
│   │   │   │   ├── conversation.go
│   │   │   │   ├── doc.go
│   │   │   │   ├── friend.go
│   │   │   │   ├── friend_request.go
│   │   │   │   ├── group.go
│   │   │   │   ├── group_member.go
│   │   │   │   ├── group_request.go
│   │   │   │   ├── log.go
│   │   │   │   ├── msg.go
│   │   │   │   ├── object.go
│   │   │   │   ├── seq.go
│   │   │   │   ├── seq_user.go
│   │   │   │   ├── subscribe.go
│   │   │   │   ├── user.go
│   │   │   │   └── version_log.go
│   │   │   └── versionctx/
│   │   │       ├── rpc.go
│   │   │       └── version.go
│   │   └── webhook/
│   │       ├── condition.go
│   │       ├── doc.go
│   │       ├── http_client.go
│   │       └── http_client_test.go
│   ├── dbbuild/
│   │   ├── builder.go
│   │   ├── microservices.go
│   │   └── standalone.go
│   ├── localcache/
│   │   ├── cache.go
│   │   ├── cache_test.go
│   │   ├── doc.go
│   │   ├── init.go
│   │   ├── link/
│   │   │   ├── doc.go
│   │   │   ├── link.go
│   │   │   └── link_test.go
│   │   ├── lru/
│   │   │   ├── doc.go
│   │   │   ├── lru.go
│   │   │   ├── lru_expiration.go
│   │   │   ├── lru_lazy.go
│   │   │   ├── lru_lazy_test.go
│   │   │   └── lru_slot.go
│   │   ├── option.go
│   │   └── tool.go
│   ├── mqbuild/
│   │   └── builder.go
│   ├── msgprocessor/
│   │   ├── conversation.go
│   │   ├── doc.go
│   │   └── options.go
│   ├── notification/
│   │   ├── common_user/
│   │   │   └── common.go
│   │   ├── grouphash/
│   │   │   └── grouphash.go
│   │   └── msg.go
│   ├── rpccache/
│   │   ├── auth.go
│   │   ├── common.go
│   │   ├── conversation.go
│   │   ├── doc.go
│   │   ├── friend.go
│   │   ├── group.go
│   │   ├── online.go
│   │   ├── subscriber.go
│   │   └── user.go
│   ├── rpcli/
│   │   ├── auth.go
│   │   ├── conversation.go
│   │   ├── group.go
│   │   ├── msg.go
│   │   ├── msggateway.go
│   │   ├── push.go
│   │   ├── relation.go
│   │   ├── rtc.go
│   │   ├── third.go
│   │   ├── tool.go
│   │   └── user.go
│   ├── statistics/
│   │   ├── doc.go
│   │   └── statistics.go
│   ├── tools/
│   │   └── batcher/
│   │       ├── batcher.go
│   │       └── batcher_test.go
│   └── util/
│       ├── conversationutil/
│       │   ├── conversationutil.go
│       │   └── doc.go
│       ├── hashutil/
│       │   └── id.go
│       └── useronline/
│           └── split.go
├── scripts/
│   └── template/
│       ├── LICENSE
│       ├── LICENSE_TEMPLATES
│       ├── boilerplate.txt
│       ├── footer.md.tmpl
│       ├── head.md.tmpl
│       └── project_README.md
├── start-config.yml
├── test/
│   ├── e2e/
│   │   ├── README.md
│   │   ├── api/
│   │   │   ├── token/
│   │   │   │   └── token.go
│   │   │   └── user/
│   │   │       ├── curd.go
│   │   │       └── user.go
│   │   ├── conformance/
│   │   │   └── .keep
│   │   ├── e2e.go
│   │   ├── e2e_test.go
│   │   ├── framework/
│   │   │   ├── config/
│   │   │   │   ├── config.go
│   │   │   │   └── config_test.go
│   │   │   ├── ginkgowrapper/
│   │   │   │   ├── .keep
│   │   │   │   ├── ginkgowrapper.go
│   │   │   │   └── ginkgowrapper_test.go
│   │   │   └── helpers/
│   │   │       ├── .keep
│   │   │       └── chat/
│   │   │           └── chat.go
│   │   ├── page/
│   │   │   ├── chat_page.go
│   │   │   └── login_page.go
│   │   ├── performance/
│   │   │   └── .keep
│   │   ├── rpc/
│   │   │   ├── auth/
│   │   │   │   └── .keep
│   │   │   ├── conversation/
│   │   │   │   └── .keep
│   │   │   ├── friend/
│   │   │   │   └── .keep
│   │   │   ├── group/
│   │   │   │   └── .keep
│   │   │   └── message/
│   │   │       └── .keep
│   │   ├── scalability/
│   │   │   └── .keep
│   │   ├── upgrade/
│   │   │   └── .keep
│   │   └── web/
│   │       └── Readme.md
│   ├── jwt/
│   │   └── main.go
│   ├── readme
│   ├── stress-test/
│   │   ├── README.md
│   │   └── main.go
│   ├── stress-test-v2/
│   │   ├── README.md
│   │   └── main.go
│   ├── testdata/
│   │   ├── README.md
│   │   ├── db/
│   │   │   ├── messages.json
│   │   │   └── users.json
│   │   ├── requests/
│   │   │   ├── login.json
│   │   │   ├── register.json
│   │   │   └── send-message.json
│   │   └── responses/
│   │       ├── login.json
│   │       ├── register.json
│   │       └── sendMessage.json
│   └── webhook/
│       └── msgmodify/
│           └── main.go
├── tools/
│   ├── README.md
│   ├── changelog/
│   │   └── changelog.go
│   ├── check-component/
│   │   └── main.go
│   ├── check-free-memory/
│   │   └── main.go
│   ├── imctl/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   └── main.go
│   ├── infra/
│   │   └── main.go
│   ├── ncpu/
│   │   ├── README.md
│   │   ├── main.go
│   │   └── main_test.go
│   ├── s3/
│   │   ├── README.md
│   │   ├── internal/
│   │   │   └── conversion.go
│   │   └── main.go
│   ├── seq/
│   │   ├── internal/
│   │   │   └── seq.go
│   │   └── main.go
│   ├── stress-test-v2/
│   │   └── main.go
│   ├── url2im/
│   │   ├── main.go
│   │   └── pkg/
│   │       ├── api.go
│   │       ├── buffer.go
│   │       ├── config.go
│   │       ├── http.go
│   │       ├── manage.go
│   │       ├── md5.go
│   │       └── progress.go
│   ├── versionchecker/
│   │   └── main.go
│   └── yamlfmt/
│       ├── main.go
│       └── main_test.go
└── version/
    ├── version
    └── version.go
Download .txt
Showing preview only (334K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3403 symbols across 411 files)

FILE: cmd/main.go
  function init (line 45) | func init() {
  function main (line 50) | func main() {
  function newCmds (line 80) | func newCmds(confPath string) *cmds {
  type cmdName (line 84) | type cmdName struct
  type cmds (line 89) | type cmds struct
    method getTypePath (line 96) | func (x *cmds) getTypePath(typ reflect.Type) string {
    method initDiscovery (line 100) | func (x *cmds) initDiscovery() {
    method initAllConfig (line 117) | func (x *cmds) initAllConfig() error {
    method parseConf (line 159) | func (x *cmds) parseConf(conf any) error {
    method add (line 197) | func (x *cmds) add(name string, block bool, fn func(ctx context.Contex...
    method initLog (line 201) | func (x *cmds) initLog() error {
    method run (line 222) | func (x *cmds) run(ctx context.Context) error {
  function putCmd (line 332) | func putCmd[C any](cmd *cmds, block bool, fn func(ctx context.Context, c...
  type cmdManger (line 346) | type cmdManger struct
    method Start (line 353) | func (x *cmdManger) Start(name string) {
    method Shutdown (line 369) | func (x *cmdManger) Shutdown(name string) {
    method Wait (line 387) | func (x *cmdManger) Wait() <-chan struct{} {
    method Running (line 398) | func (x *cmdManger) Running() []string {

FILE: cmd/openim-api/main.go
  function main (line 23) | func main() {

FILE: cmd/openim-cmdutils/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-crontask/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-msggateway/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-msgtransfer/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-push/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-rpc/openim-rpc-auth/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-rpc/openim-rpc-conversation/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-rpc/openim-rpc-friend/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-rpc/openim-rpc-group/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-rpc/openim-rpc-msg/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-rpc/openim-rpc-third/main.go
  function main (line 22) | func main() {

FILE: cmd/openim-rpc/openim-rpc-user/main.go
  function main (line 22) | func main() {

FILE: internal/api/auth.go
  type AuthApi (line 23) | type AuthApi struct
    method GetAdminToken (line 31) | func (o *AuthApi) GetAdminToken(c *gin.Context) {
    method GetUserToken (line 35) | func (o *AuthApi) GetUserToken(c *gin.Context) {
    method ParseToken (line 39) | func (o *AuthApi) ParseToken(c *gin.Context) {
    method ForceLogout (line 43) | func (o *AuthApi) ForceLogout(c *gin.Context) {
  function NewAuthApi (line 27) | func NewAuthApi(client auth.AuthClient) AuthApi {

FILE: internal/api/config_manager.go
  constant waitHttp (line 25) | waitHttp = time.Millisecond * 200
  type ConfigManager (line 28) | type ConfigManager struct
    method CheckAdmin (line 46) | func (cm *ConfigManager) CheckAdmin(c *gin.Context) {
    method GetConfig (line 53) | func (cm *ConfigManager) GetConfig(c *gin.Context) {
    method GetConfigList (line 72) | func (cm *ConfigManager) GetConfigList(c *gin.Context) {
    method SetConfig (line 81) | func (cm *ConfigManager) SetConfig(c *gin.Context) {
    method SetConfigs (line 148) | func (cm *ConfigManager) SetConfigs(c *gin.Context) {
    method ResetConfig (line 273) | func (cm *ConfigManager) ResetConfig(c *gin.Context) {
    method resetConfig (line 282) | func (cm *ConfigManager) resetConfig(c *gin.Context, checkChange bool,...
    method Restart (line 344) | func (cm *ConfigManager) Restart(c *gin.Context) {
    method restart (line 349) | func (cm *ConfigManager) restart(c *gin.Context) {
    method SetEnableConfigManager (line 358) | func (cm *ConfigManager) SetEnableConfigManager(c *gin.Context) {
    method GetEnableConfigManager (line 398) | func (cm *ConfigManager) GetEnableConfigManager(c *gin.Context) {
  function NewConfigManager (line 36) | func NewConfigManager(IMAdminUserID []string, cfg *config.AllConfig, cli...
  function compareAndOp (line 234) | func compareAndOp[T any](c *gin.Context, old any, req *apistruct.SetConf...
  function compareAndSave (line 252) | func compareAndSave[T any](c *gin.Context, old any, req *apistruct.SetCo...

FILE: internal/api/conversation.go
  type ConversationApi (line 24) | type ConversationApi struct
    method GetAllConversations (line 32) | func (o *ConversationApi) GetAllConversations(c *gin.Context) {
    method GetSortedConversationList (line 36) | func (o *ConversationApi) GetSortedConversationList(c *gin.Context) {
    method GetConversation (line 40) | func (o *ConversationApi) GetConversation(c *gin.Context) {
    method GetConversations (line 44) | func (o *ConversationApi) GetConversations(c *gin.Context) {
    method SetConversations (line 48) | func (o *ConversationApi) SetConversations(c *gin.Context) {
    method GetFullOwnerConversationIDs (line 56) | func (o *ConversationApi) GetFullOwnerConversationIDs(c *gin.Context) {
    method GetIncrementalConversation (line 60) | func (o *ConversationApi) GetIncrementalConversation(c *gin.Context) {
    method GetOwnerConversation (line 64) | func (o *ConversationApi) GetOwnerConversation(c *gin.Context) {
    method GetNotNotifyConversationIDs (line 68) | func (o *ConversationApi) GetNotNotifyConversationIDs(c *gin.Context) {
    method GetPinnedConversationIDs (line 72) | func (o *ConversationApi) GetPinnedConversationIDs(c *gin.Context) {
    method UpdateConversationsByUser (line 76) | func (o *ConversationApi) UpdateConversationsByUser(c *gin.Context) {
    method DeleteConversations (line 80) | func (o *ConversationApi) DeleteConversations(c *gin.Context) {
  function NewConversationApi (line 28) | func NewConversationApi(client conversation.ConversationClient) Conversa...

FILE: internal/api/custom_validator.go
  function RequiredIf (line 23) | func RequiredIf(fl validator.FieldLevel) bool {

FILE: internal/api/friend.go
  type FriendApi (line 24) | type FriendApi struct
    method ApplyToAddFriend (line 32) | func (o *FriendApi) ApplyToAddFriend(c *gin.Context) {
    method RespondFriendApply (line 36) | func (o *FriendApi) RespondFriendApply(c *gin.Context) {
    method DeleteFriend (line 40) | func (o *FriendApi) DeleteFriend(c *gin.Context) {
    method GetFriendApplyList (line 44) | func (o *FriendApi) GetFriendApplyList(c *gin.Context) {
    method GetDesignatedFriendsApply (line 48) | func (o *FriendApi) GetDesignatedFriendsApply(c *gin.Context) {
    method GetSelfApplyList (line 52) | func (o *FriendApi) GetSelfApplyList(c *gin.Context) {
    method GetFriendList (line 56) | func (o *FriendApi) GetFriendList(c *gin.Context) {
    method GetDesignatedFriends (line 60) | func (o *FriendApi) GetDesignatedFriends(c *gin.Context) {
    method SetFriendRemark (line 64) | func (o *FriendApi) SetFriendRemark(c *gin.Context) {
    method AddBlack (line 68) | func (o *FriendApi) AddBlack(c *gin.Context) {
    method GetPaginationBlacks (line 72) | func (o *FriendApi) GetPaginationBlacks(c *gin.Context) {
    method GetSpecifiedBlacks (line 76) | func (o *FriendApi) GetSpecifiedBlacks(c *gin.Context) {
    method RemoveBlack (line 80) | func (o *FriendApi) RemoveBlack(c *gin.Context) {
    method ImportFriends (line 84) | func (o *FriendApi) ImportFriends(c *gin.Context) {
    method IsFriend (line 88) | func (o *FriendApi) IsFriend(c *gin.Context) {
    method GetFriendIDs (line 92) | func (o *FriendApi) GetFriendIDs(c *gin.Context) {
    method GetSpecifiedFriendsInfo (line 96) | func (o *FriendApi) GetSpecifiedFriendsInfo(c *gin.Context) {
    method UpdateFriends (line 100) | func (o *FriendApi) UpdateFriends(c *gin.Context) {
    method GetIncrementalFriends (line 104) | func (o *FriendApi) GetIncrementalFriends(c *gin.Context) {
    method GetIncrementalBlacks (line 110) | func (o *FriendApi) GetIncrementalBlacks(c *gin.Context) {
    method GetFullFriendUserIDs (line 114) | func (o *FriendApi) GetFullFriendUserIDs(c *gin.Context) {
    method GetSelfUnhandledApplyCount (line 118) | func (o *FriendApi) GetSelfUnhandledApplyCount(c *gin.Context) {
  function NewFriendApi (line 28) | func NewFriendApi(client relation.FriendClient) FriendApi {

FILE: internal/api/group.go
  type GroupApi (line 23) | type GroupApi struct
    method CreateGroup (line 31) | func (o *GroupApi) CreateGroup(c *gin.Context) {
    method SetGroupInfo (line 35) | func (o *GroupApi) SetGroupInfo(c *gin.Context) {
    method SetGroupInfoEx (line 39) | func (o *GroupApi) SetGroupInfoEx(c *gin.Context) {
    method JoinGroup (line 43) | func (o *GroupApi) JoinGroup(c *gin.Context) {
    method QuitGroup (line 47) | func (o *GroupApi) QuitGroup(c *gin.Context) {
    method ApplicationGroupResponse (line 51) | func (o *GroupApi) ApplicationGroupResponse(c *gin.Context) {
    method TransferGroupOwner (line 55) | func (o *GroupApi) TransferGroupOwner(c *gin.Context) {
    method GetRecvGroupApplicationList (line 59) | func (o *GroupApi) GetRecvGroupApplicationList(c *gin.Context) {
    method GetUserReqGroupApplicationList (line 63) | func (o *GroupApi) GetUserReqGroupApplicationList(c *gin.Context) {
    method GetGroupUsersReqApplicationList (line 67) | func (o *GroupApi) GetGroupUsersReqApplicationList(c *gin.Context) {
    method GetSpecifiedUserGroupRequestInfo (line 71) | func (o *GroupApi) GetSpecifiedUserGroupRequestInfo(c *gin.Context) {
    method GetGroupsInfo (line 75) | func (o *GroupApi) GetGroupsInfo(c *gin.Context) {
    method KickGroupMember (line 80) | func (o *GroupApi) KickGroupMember(c *gin.Context) {
    method GetGroupMembersInfo (line 84) | func (o *GroupApi) GetGroupMembersInfo(c *gin.Context) {
    method GetGroupMemberList (line 89) | func (o *GroupApi) GetGroupMemberList(c *gin.Context) {
    method InviteUserToGroup (line 93) | func (o *GroupApi) InviteUserToGroup(c *gin.Context) {
    method GetJoinedGroupList (line 97) | func (o *GroupApi) GetJoinedGroupList(c *gin.Context) {
    method DismissGroup (line 101) | func (o *GroupApi) DismissGroup(c *gin.Context) {
    method MuteGroupMember (line 105) | func (o *GroupApi) MuteGroupMember(c *gin.Context) {
    method CancelMuteGroupMember (line 109) | func (o *GroupApi) CancelMuteGroupMember(c *gin.Context) {
    method MuteGroup (line 113) | func (o *GroupApi) MuteGroup(c *gin.Context) {
    method CancelMuteGroup (line 117) | func (o *GroupApi) CancelMuteGroup(c *gin.Context) {
    method SetGroupMemberInfo (line 121) | func (o *GroupApi) SetGroupMemberInfo(c *gin.Context) {
    method GetGroupAbstractInfo (line 125) | func (o *GroupApi) GetGroupAbstractInfo(c *gin.Context) {
    method GroupCreateCount (line 137) | func (o *GroupApi) GroupCreateCount(c *gin.Context) {
    method GetGroups (line 141) | func (o *GroupApi) GetGroups(c *gin.Context) {
    method GetGroupMemberUserIDs (line 145) | func (o *GroupApi) GetGroupMemberUserIDs(c *gin.Context) {
    method GetIncrementalJoinGroup (line 149) | func (o *GroupApi) GetIncrementalJoinGroup(c *gin.Context) {
    method GetIncrementalGroupMember (line 153) | func (o *GroupApi) GetIncrementalGroupMember(c *gin.Context) {
    method GetIncrementalGroupMemberBatch (line 157) | func (o *GroupApi) GetIncrementalGroupMemberBatch(c *gin.Context) {
    method GetFullGroupMemberUserIDs (line 161) | func (o *GroupApi) GetFullGroupMemberUserIDs(c *gin.Context) {
    method GetFullJoinGroupIDs (line 165) | func (o *GroupApi) GetFullJoinGroupIDs(c *gin.Context) {
    method GetGroupApplicationUnhandledCount (line 169) | func (o *GroupApi) GetGroupApplicationUnhandledCount(c *gin.Context) {
  function NewGroupApi (line 27) | func NewGroupApi(client group.GroupClient) GroupApi {

FILE: internal/api/init.go
  type Config (line 35) | type Config struct
  function Start (line 42) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/api/jssdk/jssdk.go
  constant maxGetActiveConversation (line 23) | maxGetActiveConversation     = 500
  constant defaultGetActiveConversation (line 24) | defaultGetActiveConversation = 100
  function NewJSSdkApi (line 27) | func NewJSSdkApi(userClient *rpcli.UserClient, relationClient *rpcli.Rel...
  type JSSdk (line 38) | type JSSdk struct
    method GetActiveConversations (line 46) | func (x *JSSdk) GetActiveConversations(c *gin.Context) {
    method GetConversations (line 50) | func (x *JSSdk) GetConversations(c *gin.Context) {
    method fillConversations (line 54) | func (x *JSSdk) fillConversations(ctx context.Context, conversations [...
    method getActiveConversations (line 104) | func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk...
    method getConversations (line 191) | func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetCo...
    method checkMessagesAndGetLastMessage (line 258) | func (x *JSSdk) checkMessagesAndGetLastMessage(ctx context.Context, us...

FILE: internal/api/jssdk/sort.go
  type sortActiveConversations (line 5) | type sortActiveConversations struct
    method Top (line 10) | func (s sortActiveConversations) Top(limit int) []*msg.ActiveConversat...
    method Len (line 17) | func (s sortActiveConversations) Len() int {
    method Less (line 21) | func (s sortActiveConversations) Less(i, j int) bool {
    method Swap (line 31) | func (s sortActiveConversations) Swap(i, j int) {

FILE: internal/api/jssdk/tools.go
  function field (line 16) | func field[A, B, C any](ctx context.Context, fn func(ctx context.Context...
  function call (line 25) | func call[A, B any](c *gin.Context, fn func(ctx context.Context, req *A)...

FILE: internal/api/msg.go
  function getMsgDataDescriptor (line 51) | func getMsgDataDescriptor() []protoreflect.FieldDescriptor {
  type MessageApi (line 79) | type MessageApi struct
    method SetOptions (line 90) | func (*MessageApi) SetOptions(options map[string]bool, value bool) {
    method newUserSendMsgReq (line 97) | func (m *MessageApi) newUserSendMsgReq(_ *gin.Context, params *apistru...
    method GetSeq (line 154) | func (m *MessageApi) GetSeq(c *gin.Context) {
    method PullMsgBySeqs (line 158) | func (m *MessageApi) PullMsgBySeqs(c *gin.Context) {
    method RevokeMsg (line 162) | func (m *MessageApi) RevokeMsg(c *gin.Context) {
    method MarkMsgsAsRead (line 166) | func (m *MessageApi) MarkMsgsAsRead(c *gin.Context) {
    method MarkConversationAsRead (line 170) | func (m *MessageApi) MarkConversationAsRead(c *gin.Context) {
    method GetConversationsHasReadAndMaxSeq (line 174) | func (m *MessageApi) GetConversationsHasReadAndMaxSeq(c *gin.Context) {
    method SetConversationHasReadSeq (line 178) | func (m *MessageApi) SetConversationHasReadSeq(c *gin.Context) {
    method ClearConversationsMsg (line 182) | func (m *MessageApi) ClearConversationsMsg(c *gin.Context) {
    method UserClearAllMsg (line 186) | func (m *MessageApi) UserClearAllMsg(c *gin.Context) {
    method DeleteMsgs (line 190) | func (m *MessageApi) DeleteMsgs(c *gin.Context) {
    method DeleteMsgPhysicalBySeq (line 194) | func (m *MessageApi) DeleteMsgPhysicalBySeq(c *gin.Context) {
    method DeleteMsgPhysical (line 198) | func (m *MessageApi) DeleteMsgPhysical(c *gin.Context) {
    method getSendMsgReq (line 202) | func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendM...
    method getModifyFields (line 243) | func (m *MessageApi) getModifyFields(req, respModify *sdkws.MsgData) m...
    method ginRespSendMsg (line 270) | func (m *MessageApi) ginRespSendMsg(c *gin.Context, req *msg.SendMsgRe...
    method SendMessage (line 280) | func (m *MessageApi) SendMessage(c *gin.Context) {
    method SendBusinessNotification (line 335) | func (m *MessageApi) SendBusinessNotification(c *gin.Context) {
    method BatchSendMsg (line 401) | func (m *MessageApi) BatchSendMsg(c *gin.Context) {
    method SendSimpleMessage (line 458) | func (m *MessageApi) SendSimpleMessage(c *gin.Context) {
    method CheckMsgIsSendSuccess (line 553) | func (m *MessageApi) CheckMsgIsSendSuccess(c *gin.Context) {
    method GetUsersOnlineStatus (line 557) | func (m *MessageApi) GetUsersOnlineStatus(c *gin.Context) {
    method GetActiveUser (line 561) | func (m *MessageApi) GetActiveUser(c *gin.Context) {
    method GetActiveGroup (line 565) | func (m *MessageApi) GetActiveGroup(c *gin.Context) {
    method SearchMsg (line 569) | func (m *MessageApi) SearchMsg(c *gin.Context) {
    method GetServerTime (line 573) | func (m *MessageApi) GetServerTime(c *gin.Context) {
  function NewMessageApi (line 86) | func NewMessageApi(client msg.MsgClient, userClient *rpcli.UserClient, i...

FILE: internal/api/prometheus_discovery.go
  type PrometheusDiscoveryApi (line 15) | type PrometheusDiscoveryApi struct
    method discovery (line 28) | func (p *PrometheusDiscoveryApi) discovery(c *gin.Context, key string) {
    method Api (line 57) | func (p *PrometheusDiscoveryApi) Api(c *gin.Context) {
    method User (line 61) | func (p *PrometheusDiscoveryApi) User(c *gin.Context) {
    method Group (line 65) | func (p *PrometheusDiscoveryApi) Group(c *gin.Context) {
    method Msg (line 69) | func (p *PrometheusDiscoveryApi) Msg(c *gin.Context) {
    method Friend (line 73) | func (p *PrometheusDiscoveryApi) Friend(c *gin.Context) {
    method Conversation (line 77) | func (p *PrometheusDiscoveryApi) Conversation(c *gin.Context) {
    method Third (line 81) | func (p *PrometheusDiscoveryApi) Third(c *gin.Context) {
    method Auth (line 85) | func (p *PrometheusDiscoveryApi) Auth(c *gin.Context) {
    method Push (line 89) | func (p *PrometheusDiscoveryApi) Push(c *gin.Context) {
    method MessageGateway (line 93) | func (p *PrometheusDiscoveryApi) MessageGateway(c *gin.Context) {
    method MessageTransfer (line 97) | func (p *PrometheusDiscoveryApi) MessageTransfer(c *gin.Context) {
  function NewPrometheusDiscoveryApi (line 20) | func NewPrometheusDiscoveryApi(config *Config, client discovery.SvcDisco...

FILE: internal/api/ratelimit.go
  type RateLimiter (line 19) | type RateLimiter struct
  function RateLimitMiddleware (line 26) | func RateLimitMiddleware(config *RateLimiter) gin.HandlerFunc {
  function calculateBBRRetryAfter (line 68) | func calculateBBRRetryAfter(status bbr.Stat) string {

FILE: internal/api/router.go
  constant NoCompression (line 36) | NoCompression      = -1
  constant DefaultCompression (line 37) | DefaultCompression = 0
  constant BestCompression (line 38) | BestCompression    = 1
  constant BestSpeed (line 39) | BestSpeed          = 2
  function prommetricsGin (line 42) | func prommetricsGin() gin.HandlerFunc {
  function newGinRouter (line 57) | func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegi...
  function GinParseToken (line 347) | func GinParseToken(authClient *rpcli.AuthClient) gin.HandlerFunc {
  function setGinIsAdmin (line 378) | func setGinIsAdmin(imAdminUserID []string) gin.HandlerFunc {

FILE: internal/api/third.go
  type ThirdApi (line 33) | type ThirdApi struct
    method FcmUpdateToken (line 42) | func (o *ThirdApi) FcmUpdateToken(c *gin.Context) {
    method SetAppBadge (line 46) | func (o *ThirdApi) SetAppBadge(c *gin.Context) {
    method PartLimit (line 81) | func (o *ThirdApi) PartLimit(c *gin.Context) {
    method PartSize (line 85) | func (o *ThirdApi) PartSize(c *gin.Context) {
    method InitiateMultipartUpload (line 89) | func (o *ThirdApi) InitiateMultipartUpload(c *gin.Context) {
    method AuthSign (line 96) | func (o *ThirdApi) AuthSign(c *gin.Context) {
    method CompleteMultipartUpload (line 100) | func (o *ThirdApi) CompleteMultipartUpload(c *gin.Context) {
    method AccessURL (line 107) | func (o *ThirdApi) AccessURL(c *gin.Context) {
    method InitiateFormData (line 111) | func (o *ThirdApi) InitiateFormData(c *gin.Context) {
    method CompleteFormData (line 115) | func (o *ThirdApi) CompleteFormData(c *gin.Context) {
    method ObjectRedirect (line 122) | func (o *ThirdApi) ObjectRedirect(c *gin.Context) {
    method UploadLogs (line 160) | func (o *ThirdApi) UploadLogs(c *gin.Context) {
    method DeleteLogs (line 164) | func (o *ThirdApi) DeleteLogs(c *gin.Context) {
    method SearchLogs (line 168) | func (o *ThirdApi) SearchLogs(c *gin.Context) {
    method GetPrometheus (line 172) | func (o *ThirdApi) GetPrometheus(c *gin.Context) {
  function NewThirdApi (line 38) | func NewThirdApi(client third.ThirdClient, grafanaUrl string) ThirdApi {
  function setURLPrefixOption (line 52) | func setURLPrefixOption[A, B, C any](_ func(client C, ctx context.Contex...
  function setURLPrefix (line 58) | func setURLPrefix(c *gin.Context, urlPrefix *string) error {

FILE: internal/api/user.go
  type UserApi (line 30) | type UserApi struct
    method UserRegister (line 40) | func (u *UserApi) UserRegister(c *gin.Context) {
    method UpdateUserInfo (line 45) | func (u *UserApi) UpdateUserInfo(c *gin.Context) {
    method UpdateUserInfoEx (line 49) | func (u *UserApi) UpdateUserInfoEx(c *gin.Context) {
    method SetGlobalRecvMessageOpt (line 52) | func (u *UserApi) SetGlobalRecvMessageOpt(c *gin.Context) {
    method GetUsersPublicInfo (line 56) | func (u *UserApi) GetUsersPublicInfo(c *gin.Context) {
    method GetAllUsersID (line 60) | func (u *UserApi) GetAllUsersID(c *gin.Context) {
    method AccountCheck (line 64) | func (u *UserApi) AccountCheck(c *gin.Context) {
    method GetUsers (line 68) | func (u *UserApi) GetUsers(c *gin.Context) {
    method GetUsersOnlineStatus (line 73) | func (u *UserApi) GetUsersOnlineStatus(c *gin.Context) {
    method UserRegisterCount (line 129) | func (u *UserApi) UserRegisterCount(c *gin.Context) {
    method GetUsersOnlineTokenDetail (line 134) | func (u *UserApi) GetUsersOnlineTokenDetail(c *gin.Context) {
    method SubscriberStatus (line 195) | func (u *UserApi) SubscriberStatus(c *gin.Context) {
    method GetUserStatus (line 200) | func (u *UserApi) GetUserStatus(c *gin.Context) {
    method GetSubscribeUsersStatus (line 205) | func (u *UserApi) GetSubscribeUsersStatus(c *gin.Context) {
    method ProcessUserCommandAdd (line 210) | func (u *UserApi) ProcessUserCommandAdd(c *gin.Context) {
    method ProcessUserCommandDelete (line 215) | func (u *UserApi) ProcessUserCommandDelete(c *gin.Context) {
    method ProcessUserCommandUpdate (line 220) | func (u *UserApi) ProcessUserCommandUpdate(c *gin.Context) {
    method ProcessUserCommandGet (line 225) | func (u *UserApi) ProcessUserCommandGet(c *gin.Context) {
    method ProcessUserCommandGetAll (line 230) | func (u *UserApi) ProcessUserCommandGetAll(c *gin.Context) {
    method AddNotificationAccount (line 234) | func (u *UserApi) AddNotificationAccount(c *gin.Context) {
    method UpdateNotificationAccountInfo (line 238) | func (u *UserApi) UpdateNotificationAccountInfo(c *gin.Context) {
    method SearchNotificationAccount (line 242) | func (u *UserApi) SearchNotificationAccount(c *gin.Context) {
    method GetUserClientConfig (line 246) | func (u *UserApi) GetUserClientConfig(c *gin.Context) {
    method SetUserClientConfig (line 250) | func (u *UserApi) SetUserClientConfig(c *gin.Context) {
    method DelUserClientConfig (line 254) | func (u *UserApi) DelUserClientConfig(c *gin.Context) {
    method PageUserClientConfig (line 258) | func (u *UserApi) PageUserClientConfig(c *gin.Context) {
  function NewUserApi (line 36) | func NewUserApi(client user.UserClient, discov discovery.Conn, config co...

FILE: internal/msggateway/callback.go
  method webhookAfterUserOnline (line 27) | func (ws *WsServer) webhookAfterUserOnline(ctx context.Context, after *c...
  method webhookAfterUserOffline (line 45) | func (ws *WsServer) webhookAfterUserOffline(ctx context.Context, after *...
  method webhookAfterUserKickOff (line 62) | func (ws *WsServer) webhookAfterUserKickOff(ctx context.Context, after *...

FILE: internal/msggateway/client.go
  constant MessageText (line 44) | MessageText = iota + 1
  constant MessageBinary (line 46) | MessageBinary
  constant CloseMessage (line 50) | CloseMessage = 8
  constant PingMessage (line 54) | PingMessage = 9
  constant PongMessage (line 58) | PongMessage = 10
  type PingPongHandler (line 61) | type PingPongHandler
  type Client (line 63) | type Client struct
    method ResetClient (line 85) | func (c *Client) ResetClient(ctx *UserConnContext, conn ClientConn, lo...
    method readMessage (line 114) | func (c *Client) readMessage() {
    method handleMessage (line 147) | func (c *Client) handleMessage(message []byte) error {
    method setAppBackgroundStatus (line 216) | func (c *Client) setAppBackgroundStatus(ctx context.Context, req *Req)...
    method close (line 227) | func (c *Client) close() {
    method replyMessage (line 239) | func (c *Client) replyMessage(ctx context.Context, binaryReq *Req, err...
    method PushMessage (line 263) | func (c *Client) PushMessage(ctx context.Context, msgData *sdkws.MsgDa...
    method KickOnlineMessage (line 285) | func (c *Client) KickOnlineMessage() error {
    method PushUserOnlineStatus (line 295) | func (c *Client) PushUserOnlineStatus(data []byte) error {
    method writeBinaryMsg (line 303) | func (c *Client) writeBinaryMsg(resp Resp) error {

FILE: internal/msggateway/client_conn.go
  type ClientConn (line 18) | type ClientConn interface
  type websocketMessage (line 24) | type websocketMessage struct
  function NewWebSocketClientConn (line 29) | func NewWebSocketClientConn(conn *websocket.Conn, readLimit int64, readT...
  type websocketClientConn (line 49) | type websocketClientConn struct
    method ReadMessage (line 57) | func (c *websocketClientConn) ReadMessage() ([]byte, error) {
    method WriteMessage (line 65) | func (c *websocketClientConn) WriteMessage(message []byte) error {
    method Close (line 69) | func (c *websocketClientConn) Close() error {
    method closeBy (line 73) | func (c *websocketClientConn) closeBy(err error) error {
    method writeMessage (line 83) | func (c *websocketClientConn) writeMessage(messageType int, data []byt...
    method loopSend (line 95) | func (c *websocketClientConn) loopSend() {
    method setReadDeadline (line 135) | func (c *websocketClientConn) setReadDeadline() error {
    method readMessage (line 140) | func (c *websocketClientConn) readMessage() ([]byte, error) {
    method onReadTextMessage (line 175) | func (c *websocketClientConn) onReadTextMessage(buf []byte) error {
    method pingHandler (line 198) | func (c *websocketClientConn) pingHandler(appData string) error {
    method pongHandler (line 211) | func (c *websocketClientConn) pongHandler(string) error {
    method doPing (line 215) | func (c *websocketClientConn) doPing(d time.Duration) {

FILE: internal/msggateway/compressor.go
  type Compressor (line 31) | type Compressor interface
  type GzipCompressor (line 38) | type GzipCompressor struct
    method Compress (line 46) | func (g *GzipCompressor) Compress(rawData []byte) ([]byte, error) {
    method CompressWithPool (line 61) | func (g *GzipCompressor) CompressWithPool(rawData []byte) ([]byte, err...
    method DeCompress (line 77) | func (g *GzipCompressor) DeCompress(compressedData []byte) ([]byte, er...
    method DecompressWithPool (line 95) | func (g *GzipCompressor) DecompressWithPool(compressedData []byte) ([]...
  function NewGzipCompressor (line 42) | func NewGzipCompressor() *GzipCompressor {

FILE: internal/msggateway/compressor_test.go
  function mockRandom (line 25) | func mockRandom() []byte {
  function TestCompressDecompress (line 31) | func TestCompressDecompress(t *testing.T) {
  function TestCompressDecompressWithConcurrency (line 57) | func TestCompressDecompressWithConcurrency(t *testing.T) {
  function BenchmarkCompress (line 89) | func BenchmarkCompress(b *testing.B) {
  function BenchmarkCompressWithSyncPool (line 99) | func BenchmarkCompressWithSyncPool(b *testing.B) {
  function BenchmarkDecompress (line 109) | func BenchmarkDecompress(b *testing.B) {
  function BenchmarkDecompressWithSyncPool (line 123) | func BenchmarkDecompressWithSyncPool(b *testing.B) {
  function TestName (line 136) | func TestName(t *testing.T) {

FILE: internal/msggateway/constant.go
  constant WsUserID (line 20) | WsUserID                = "sendID"
  constant CommonUserID (line 21) | CommonUserID            = "userID"
  constant PlatformID (line 22) | PlatformID              = "platformID"
  constant ConnID (line 23) | ConnID                  = "connID"
  constant Token (line 24) | Token                   = "token"
  constant OperationID (line 25) | OperationID             = "operationID"
  constant Compression (line 26) | Compression             = "compression"
  constant GzipCompressionProtocol (line 27) | GzipCompressionProtocol = "gzip"
  constant BackgroundStatus (line 28) | BackgroundStatus        = "isBackground"
  constant SendResponse (line 29) | SendResponse            = "isMsgResp"
  constant SDKType (line 30) | SDKType                 = "sdkType"
  constant SDKVersion (line 31) | SDKVersion              = "sdkVersion"
  constant GoSDK (line 35) | GoSDK = "go"
  constant JsSDK (line 36) | JsSDK = "js"
  constant WebSocket (line 40) | WebSocket = iota + 1
  constant WSGetNewestSeq (line 45) | WSGetNewestSeq        = 1001
  constant WSPullMsgBySeqList (line 46) | WSPullMsgBySeqList    = 1002
  constant WSSendMsg (line 47) | WSSendMsg             = 1003
  constant WSSendSignalMsg (line 48) | WSSendSignalMsg       = 1004
  constant WSPullMsg (line 49) | WSPullMsg             = 1005
  constant WSGetConvMaxReadSeq (line 50) | WSGetConvMaxReadSeq   = 1006
  constant WsPullConvLastMessage (line 51) | WsPullConvLastMessage = 1007
  constant WSPushMsg (line 52) | WSPushMsg             = 2001
  constant WSKickOnlineMsg (line 53) | WSKickOnlineMsg       = 2002
  constant WsLogoutMsg (line 54) | WsLogoutMsg           = 2003
  constant WsSetBackgroundStatus (line 55) | WsSetBackgroundStatus = 2004
  constant WsSubUserOnlineStatus (line 56) | WsSubUserOnlineStatus = 2005
  constant WSDataError (line 57) | WSDataError           = 3001
  constant writeWait (line 62) | writeWait = 10 * time.Second
  constant pongWait (line 65) | pongWait = 30 * time.Second
  constant pingPeriod (line 68) | pingPeriod = (pongWait * 9) / 10
  constant maxMessageSize (line 71) | maxMessageSize = 51200

FILE: internal/msggateway/context.go
  type UserConnContextInfo (line 32) | type UserConnContextInfo struct
  type UserConnContext (line 44) | type UserConnContext struct
    method Deadline (line 54) | func (c *UserConnContext) Deadline() (deadline time.Time, ok bool) {
    method Done (line 58) | func (c *UserConnContext) Done() <-chan struct{} {
    method Err (line 62) | func (c *UserConnContext) Err() error {
    method Value (line 66) | func (c *UserConnContext) Value(key any) any {
    method ParseEssentialArgs (line 107) | func (c *UserConnContext) ParseEssentialArgs() error {
    method parseByQuery (line 116) | func (c *UserConnContext) parseByQuery(query url.Values, header http.H...
    method parseByJson (line 148) | func (c *UserConnContext) parseByJson(data string) error {
    method checkInfo (line 160) | func (c *UserConnContext) checkInfo(info *UserConnContextInfo) error {
    method GetRemoteAddr (line 184) | func (c *UserConnContext) GetRemoteAddr() string {
    method SetHeader (line 188) | func (c *UserConnContext) SetHeader(key, value string) {
    method ErrReturn (line 192) | func (c *UserConnContext) ErrReturn(error string, code int) {
    method GetConnID (line 196) | func (c *UserConnContext) GetConnID() string {
    method GetUserID (line 200) | func (c *UserConnContext) GetUserID() string {
    method GetPlatformID (line 207) | func (c *UserConnContext) GetPlatformID() int {
    method GetOperationID (line 214) | func (c *UserConnContext) GetOperationID() string {
    method SetOperationID (line 221) | func (c *UserConnContext) SetOperationID(operationID string) {
    method GetToken (line 228) | func (c *UserConnContext) GetToken() string {
    method GetCompression (line 235) | func (c *UserConnContext) GetCompression() bool {
    method GetSDKType (line 239) | func (c *UserConnContext) GetSDKType() string {
    method GetSDKVersion (line 253) | func (c *UserConnContext) GetSDKVersion() string {
    method ShouldSendResp (line 260) | func (c *UserConnContext) ShouldSendResp() bool {
    method SetToken (line 264) | func (c *UserConnContext) SetToken(token string) {
    method GetBackground (line 271) | func (c *UserConnContext) GetBackground() bool {
  function newContext (line 85) | func newContext(respWriter http.ResponseWriter, req *http.Request) *User...
  function newTempContext (line 100) | func newTempContext() *UserConnContext {

FILE: internal/msggateway/encoder.go
  type Encoder (line 25) | type Encoder interface
  type GobEncoder (line 30) | type GobEncoder struct
    method Encode (line 36) | func (g GobEncoder) Encode(data any) ([]byte, error) {
    method Decode (line 45) | func (g GobEncoder) Decode(encodeData []byte, decodeData any) error {
  function NewGobEncoder (line 32) | func NewGobEncoder() Encoder {
  type JsonEncoder (line 54) | type JsonEncoder struct
    method Encode (line 60) | func (g JsonEncoder) Encode(data any) ([]byte, error) {
    method Decode (line 68) | func (g JsonEncoder) Decode(encodeData []byte, decodeData any) error {
  function NewJsonEncoder (line 56) | func NewJsonEncoder() Encoder {

FILE: internal/msggateway/http_error.go
  function httpError (line 22) | func httpError(ctx *UserConnContext, err error) {

FILE: internal/msggateway/hub_server.go
  type Server (line 74) | type Server struct
    method InitServer (line 37) | func (s *Server) InitServer(ctx context.Context, config *Config, disCo...
    method SetLongConnServer (line 85) | func (s *Server) SetLongConnServer(LongConnServer LongConnServer) {
    method GetUsersOnlineStatus (line 102) | func (s *Server) GetUsersOnlineStatus(ctx context.Context, req *msggat...
    method pushToUser (line 135) | func (s *Server) pushToUser(ctx context.Context, userID string, msgDat...
    method SuperGroupOnlineBatchPushOneMsg (line 171) | func (s *Server) SuperGroupOnlineBatchPushOneMsg(ctx context.Context, ...
    method KickUserOffline (line 222) | func (s *Server) KickUserOffline(ctx context.Context, req *msggateway....
    method MultiTerminalLoginCheck (line 242) | func (s *Server) MultiTerminalLoginCheck(ctx context.Context, req *msg...
  function NewServer (line 89) | func NewServer(longConnServer LongConnServer, conf *Config, ready func(s...

FILE: internal/msggateway/init.go
  type Config (line 32) | type Config struct
  function Start (line 42) | func Start(ctx context.Context, conf *Config, client discovery.SvcDiscov...

FILE: internal/msggateway/message_handler.go
  constant TextPing (line 34) | TextPing = "ping"
  constant TextPong (line 35) | TextPong = "pong"
  type TextMessage (line 38) | type TextMessage struct
  type Req (line 43) | type Req struct
    method String (line 52) | func (r *Req) String() string {
  function getReq (line 68) | func getReq() *Req {
  function freeReq (line 79) | func freeReq(req *Req) {
  type Resp (line 83) | type Resp struct
    method String (line 92) | func (r *Resp) String() string {
  type MessageHandler (line 102) | type MessageHandler interface
  type GrpcHandler (line 116) | type GrpcHandler struct
    method GetSeq (line 130) | func (g *GrpcHandler) GetSeq(ctx context.Context, data *Req) ([]byte, ...
    method SendMessage (line 151) | func (g *GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]b...
    method SendSignalMessage (line 175) | func (g *GrpcHandler) SendSignalMessage(ctx context.Context, data *Req...
    method PullMessageBySeqList (line 187) | func (g *GrpcHandler) PullMessageBySeqList(ctx context.Context, data *...
    method GetConversationsHasReadAndMaxSeq (line 206) | func (g *GrpcHandler) GetConversationsHasReadAndMaxSeq(ctx context.Con...
    method GetSeqMessage (line 225) | func (g *GrpcHandler) GetSeqMessage(ctx context.Context, data *Req) ([...
    method UserLogout (line 244) | func (g *GrpcHandler) UserLogout(ctx context.Context, data *Req) ([]by...
    method SetUserDeviceBackground (line 260) | func (g *GrpcHandler) SetUserDeviceBackground(ctx context.Context, dat...
    method GetLastMessage (line 271) | func (g *GrpcHandler) GetLastMessage(ctx context.Context, data *Req) (...
  function NewGrpcHandler (line 122) | func NewGrpcHandler(validate *validator.Validate, msgClient *rpcli.MsgCl...

FILE: internal/msggateway/online.go
  method ChangeOnlineStatus (line 21) | func (ws *WsServer) ChangeOnlineStatus(concurrent int) {

FILE: internal/msggateway/options.go
  type Option (line 20) | type Option
  type configs (line 21) | type configs struct
  function WithPort (line 35) | func WithPort(port int) Option {
  function WithMaxConnNum (line 41) | func WithMaxConnNum(num int64) Option {
  function WithHandshakeTimeout (line 47) | func WithHandshakeTimeout(t time.Duration) Option {
  function WithMessageMaxMsgLength (line 53) | func WithMessageMaxMsgLength(length int) Option {
  function WithWriteBufferSize (line 59) | func WithWriteBufferSize(size int) Option {

FILE: internal/msggateway/subscription.go
  method subscriberUserOnlineStatusChanges (line 12) | func (ws *WsServer) subscriberUserOnlineStatusChanges(ctx context.Contex...
  method SubUserOnlineStatus (line 21) | func (ws *WsServer) SubUserOnlineStatus(ctx context.Context, client *Cli...
  function newSubscription (line 44) | func newSubscription() *Subscription {
  type subClient (line 50) | type subClient struct
  type Subscription (line 54) | type Subscription struct
    method DelClient (line 59) | func (s *Subscription) DelClient(client *Client) {
    method GetClient (line 84) | func (s *Subscription) GetClient(userID string) []*Client {
    method Sub (line 98) | func (s *Subscription) Sub(client *Client, addUserIDs, delUserIDs []st...
  method pushUserIDOnlineStatus (line 149) | func (ws *WsServer) pushUserIDOnlineStatus(ctx context.Context, userID s...

FILE: internal/msggateway/user_map.go
  type UserMap (line 9) | type UserMap interface
  type UserState (line 19) | type UserState struct
  type UserPlatform (line 25) | type UserPlatform struct
    method PlatformIDs (line 30) | func (u *UserPlatform) PlatformIDs() []int32 {
    method PlatformIDSet (line 41) | func (u *UserPlatform) PlatformIDSet() map[int32]struct{} {
  function newUserMap (line 52) | func newUserMap() UserMap {
  type userMap (line 59) | type userMap struct
    method RecvSubChange (line 65) | func (u *userMap) RecvSubChange(userID string, platformIDs []int32) bo...
    method push (line 83) | func (u *userMap) push(userID string, userPlatform *UserPlatform, offl...
    method GetAll (line 93) | func (u *userMap) GetAll(userID string) ([]*Client, bool) {
    method Get (line 103) | func (u *userMap) Get(userID string, platformID int) ([]*Client, bool,...
    method Set (line 119) | func (u *userMap) Set(userID string, client *Client) {
    method DeleteClients (line 134) | func (u *userMap) DeleteClients(userID string, clients []*Client) (isD...
    method GetAllUserStatus (line 165) | func (u *userMap) GetAllUserStatus(deadline time.Time, nowtime time.Ti...
    method UserState (line 183) | func (u *userMap) UserState() <-chan UserState {

FILE: internal/msggateway/ws_server.go
  type LongConnServer (line 33) | type LongConnServer interface
  type WsServer (line 48) | type WsServer struct
    method SetDiscoveryRegistry (line 82) | func (ws *WsServer) SetDiscoveryRegistry(ctx context.Context, disCov d...
    method UnRegister (line 121) | func (ws *WsServer) UnRegister(c *Client) {
    method Validate (line 125) | func (ws *WsServer) Validate(_ any) error {
    method GetUserAllCons (line 129) | func (ws *WsServer) GetUserAllCons(userID string) ([]*Client, bool) {
    method GetUserPlatformCons (line 133) | func (ws *WsServer) GetUserPlatformCons(userID string, platform int) (...
    method Run (line 171) | func (ws *WsServer) Run(ctx context.Context) error {
    method sendUserOnlineInfoToOtherNode (line 221) | func (ws *WsServer) sendUserOnlineInfoToOtherNode(ctx context.Context,...
    method SetKickHandlerInfo (line 259) | func (ws *WsServer) SetKickHandlerInfo(i *kickHandler) {
    method registerClient (line 263) | func (ws *WsServer) registerClient(client *Client) {
    method KickUserConn (line 328) | func (ws *WsServer) KickUserConn(client *Client) error {
    method multiTerminalLoginChecker (line 333) | func (ws *WsServer) multiTerminalLoginChecker(clientOK bool, oldClient...
    method unregisterClient (line 439) | func (ws *WsServer) unregisterClient(client *Client) {
    method validateRespWithRequest (line 456) | func (ws *WsServer) validateRespWithRequest(ctx *UserConnContext, resp...
    method handlerError (line 468) | func (ws *WsServer) handlerError(ctx *UserConnContext, w http.Response...
    method wsHandler (line 491) | func (ws *WsServer) wsHandler(w http.ResponseWriter, r *http.Request) {
  type kickHandler (line 76) | type kickHandler struct
  function NewWsServer (line 137) | func NewWsServer(msgGatewayConfig *Config, opts ...Option) *WsServer {
  constant concurrentRequest (line 219) | concurrentRequest = 3
  function getRemoteAdders (line 316) | func getRemoteAdders(client []*Client) string {

FILE: internal/msgtransfer/callback.go
  function toCommonCallback (line 20) | func toCommonCallback(ctx context.Context, msg *sdkws.MsgData, command s...
  function GetContent (line 43) | func GetContent(msg *sdkws.MsgData) string {
  method webhookAfterMsgSaveDB (line 54) | func (mc *OnlineHistoryMongoConsumerHandler) webhookAfterMsgSaveDB(ctx c...
  function buildKeyMsgDataQuery (line 74) | func buildKeyMsgDataQuery(msg *sdkws.MsgData) map[string]string {
  function filterAfterMsg (line 86) | func filterAfterMsg(msg *sdkws.MsgData, after *config.AfterConfig) bool {
  function filterMsg (line 90) | func filterMsg(msg *sdkws.MsgData, attentionIds []string, deniedTypes []...
  function defaultDeniedTypes (line 111) | func defaultDeniedTypes(contentType int32) bool {

FILE: internal/msgtransfer/init.go
  type MsgTransfer (line 37) | type MsgTransfer struct
    method Start (line 149) | func (m *MsgTransfer) Start(ctx context.Context) error {
  type Config (line 50) | type Config struct
  function Start (line 61) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/msgtransfer/online_history_msg_handler.go
  constant size (line 47) | size              = 500
  constant mainDataBuffer (line 48) | mainDataBuffer    = 500
  constant subChanBuffer (line 49) | subChanBuffer     = 50
  constant worker (line 50) | worker            = 50
  constant interval (line 51) | interval          = 100 * time.Millisecond
  constant hasReadChanBuffer (line 52) | hasReadChanBuffer = 1000
  type ContextMsg (line 55) | type ContextMsg struct
  type userHasReadSeq (line 62) | type userHasReadSeq struct
  type OnlineHistoryRedisConsumerHandler (line 67) | type OnlineHistoryRedisConsumerHandler struct
    method do (line 126) | func (och *OnlineHistoryRedisConsumerHandler) do(ctx context.Context, ...
    method doSetReadSeq (line 144) | func (och *OnlineHistoryRedisConsumerHandler) doSetReadSeq(ctx context...
    method parseConsumerMessages (line 192) | func (och *OnlineHistoryRedisConsumerHandler) parseConsumerMessages(ct...
    method categorizeMessageLists (line 211) | func (och *OnlineHistoryRedisConsumerHandler) categorizeMessageLists(t...
    method handleMsg (line 254) | func (och *OnlineHistoryRedisConsumerHandler) handleMsg(ctx context.Co...
    method handleNotification (line 331) | func (och *OnlineHistoryRedisConsumerHandler) handleNotification(ctx c...
    method HandleUserHasReadSeqMessages (line 354) | func (och *OnlineHistoryRedisConsumerHandler) HandleUserHasReadSeqMess...
    method Close (line 371) | func (och *OnlineHistoryRedisConsumerHandler) Close() {
    method toPushTopic (line 376) | func (och *OnlineHistoryRedisConsumerHandler) toPushTopic(ctx context....
    method HandlerRedisMessage (line 399) | func (och *OnlineHistoryRedisConsumerHandler) HandlerRedisMessage(msg ...
  type ConsumerMessage (line 78) | type ConsumerMessage struct
  function NewOnlineHistoryRedisConsumerHandler (line 85) | func NewOnlineHistoryRedisConsumerHandler(ctx context.Context, client di...
  function withAggregationCtx (line 385) | func withAggregationCtx(ctx context.Context, values []*ContextMsg) conte...

FILE: internal/msgtransfer/online_msg_to_mongo_handler.go
  type OnlineHistoryMongoConsumerHandler (line 28) | type OnlineHistoryMongoConsumerHandler struct
    method HandleChatWs2Mongo (line 42) | func (mc *OnlineHistoryMongoConsumerHandler) HandleChatWs2Mongo(val mq...
  function NewOnlineHistoryMongoConsumerHandler (line 34) | func NewOnlineHistoryMongoConsumerHandler(database controller.MsgTransfe...

FILE: internal/push/callback.go
  method webhookBeforeOfflinePush (line 30) | func (c *ConsumerHandler) webhookBeforeOfflinePush(ctx context.Context, ...
  method webhookBeforeOnlinePush (line 71) | func (c *ConsumerHandler) webhookBeforeOnlinePush(ctx context.Context, b...
  method webhookBeforeGroupOnlinePush (line 102) | func (c *ConsumerHandler) webhookBeforeGroupOnlinePush(
  function GetContent (line 140) | func GetContent(msg *sdkws.MsgData) string {

FILE: internal/push/offlinepush/dummy/push.go
  function NewClient (line 24) | func NewClient() *Dummy {
  type Dummy (line 28) | type Dummy struct
    method Push (line 32) | func (d *Dummy) Push(ctx context.Context, userIDs []string, title, con...

FILE: internal/push/offlinepush/fcm/push.go
  constant SinglePushCountLimit (line 37) | SinglePushCountLimit = 400
  type Fcm (line 41) | type Fcm struct
    method Push (line 79) | func (f *Fcm) Push(ctx context.Context, userIDs []string, title, conte...
  function NewClient (line 48) | func NewClient(pushConf *config.Push, cache cache.ThirdCache, fcmConfigP...

FILE: internal/push/offlinepush/getui/body.go
  type Resp (line 33) | type Resp struct
    method parseError (line 39) | func (r *Resp) parseError() (err error) {
  type RespI (line 51) | type RespI interface
  type AuthReq (line 55) | type AuthReq struct
  type AuthResp (line 61) | type AuthResp struct
  type TaskResp (line 66) | type TaskResp struct
  type Settings (line 70) | type Settings struct
  type strategy (line 75) | type strategy struct
  type Audience (line 91) | type Audience struct
  type PushMessage (line 95) | type PushMessage struct
  type PushChannel (line 100) | type PushChannel struct
  type PushReq (line 105) | type PushReq struct
    method setPushChannel (line 184) | func (pushReq *PushReq) setPushChannel(title string, body string) {
  type Ios (line 115) | type Ios struct
  type Alert (line 124) | type Alert struct
  type Android (line 129) | type Android struct
  type Notification (line 136) | type Notification struct
  type Options (line 146) | type Options struct
  type Payload (line 162) | type Payload struct
  function newPushReq (line 166) | func newPushReq(pushConf *config.Push, title, content string) PushReq {
  function newBatchPushReq (line 179) | func newBatchPushReq(userIDs []string, taskID string) PushReq {

FILE: internal/push/offlinepush/getui/push.go
  constant pushURL (line 43) | pushURL      = "/push/single/alias"
  constant authURL (line 44) | authURL      = "/auth"
  constant taskURL (line 45) | taskURL      = "/push/list/message"
  constant batchPushURL (line 46) | batchPushURL = "/push/list/alias"
  constant tokenExpireCode (line 49) | tokenExpireCode = 10001
  constant tokenExpireTime (line 50) | tokenExpireTime = 60 * 60 * 23
  constant taskIDTTL (line 51) | taskIDTTL       = 1000 * 60 * 60 * 24
  type Client (line 54) | type Client struct
    method Push (line 71) | func (g *Client) Push(ctx context.Context, userIDs []string, title, co...
    method Auth (line 125) | func (g *Client) Auth(ctx context.Context, timeStamp int64) (token str...
    method GetTaskID (line 145) | func (g *Client) GetTaskID(ctx context.Context, token string, pushReq ...
    method batchPush (line 157) | func (g *Client) batchPush(ctx context.Context, token string, userIDs ...
    method singlePush (line 166) | func (g *Client) singlePush(ctx context.Context, token, userID string,...
    method request (line 173) | func (g *Client) request(ctx context.Context, url string, input any, t...
    method postReturn (line 180) | func (g *Client) postReturn(
    method getTokenAndSave2Redis (line 196) | func (g *Client) getTokenAndSave2Redis(ctx context.Context) (token str...
    method GetTaskIDAndSave2Redis (line 208) | func (g *Client) GetTaskIDAndSave2Redis(ctx context.Context, token str...
  function NewClient (line 62) | func NewClient(pushConf *config.Push, cache cache.ThirdCache) *Client {

FILE: internal/push/offlinepush/jpush/body/audience.go
  constant TAG (line 18) | TAG            = "tag"
  constant TAGAND (line 19) | TAGAND         = "tag_and"
  constant TAGNOT (line 20) | TAGNOT         = "tag_not"
  constant ALIAS (line 21) | ALIAS          = "alias"
  constant REGISTRATIONID (line 22) | REGISTRATIONID = "registration_id"
  type Audience (line 25) | type Audience struct
    method set (line 30) | func (a *Audience) set(key string, v []string) {
    method SetTag (line 42) | func (a *Audience) SetTag(tags []string) {
    method SetTagAnd (line 46) | func (a *Audience) SetTagAnd(tags []string) {
    method SetTagNot (line 50) | func (a *Audience) SetTagNot(tags []string) {
    method SetAlias (line 54) | func (a *Audience) SetAlias(alias []string) {
    method SetRegistrationId (line 58) | func (a *Audience) SetRegistrationId(ids []string) {
    method SetAll (line 62) | func (a *Audience) SetAll() {

FILE: internal/push/offlinepush/jpush/body/message.go
  type Message (line 17) | type Message struct
    method SetMsgContent (line 24) | func (m *Message) SetMsgContent(c string) {
    method SetTitle (line 28) | func (m *Message) SetTitle(t string) {
    method SetContentType (line 32) | func (m *Message) SetContentType(c string) {
    method SetExtras (line 36) | func (m *Message) SetExtras(key string, value any) {

FILE: internal/push/offlinepush/jpush/body/notification.go
  type Notification (line 22) | type Notification struct
    method SetAlert (line 49) | func (n *Notification) SetAlert(alert string, title string, opts *opti...
    method SetExtras (line 61) | func (n *Notification) SetExtras(extras map[string]string) {
    method SetAndroidIntent (line 66) | func (n *Notification) SetAndroidIntent(pushConf *config.Push) {
    method IOSEnableMutableContent (line 70) | func (n *Notification) IOSEnableMutableContent() {
  type Android (line 28) | type Android struct
  type Ios (line 36) | type Ios struct
  type IosAlert (line 44) | type IosAlert struct

FILE: internal/push/offlinepush/jpush/body/options.go
  type Options (line 17) | type Options struct
    method SetApnsProduction (line 21) | func (o *Options) SetApnsProduction(c bool) {

FILE: internal/push/offlinepush/jpush/body/platform.go
  constant ANDROID (line 24) | ANDROID      = "android"
  constant IOS (line 25) | IOS          = "ios"
  constant QUICKAPP (line 26) | QUICKAPP     = "quickapp"
  constant WINDOWSPHONE (line 27) | WINDOWSPHONE = "winphone"
  constant ALL (line 28) | ALL          = "all"
  type Platform (line 31) | type Platform struct
    method Set (line 36) | func (p *Platform) Set(os string) error {
    method SetPlatform (line 70) | func (p *Platform) SetPlatform(platform string) error {
    method SetIOS (line 81) | func (p *Platform) SetIOS() error {
    method SetAndroid (line 85) | func (p *Platform) SetAndroid() error {
    method SetQuickApp (line 89) | func (p *Platform) SetQuickApp() error {
    method SetWindowsPhone (line 93) | func (p *Platform) SetWindowsPhone() error {
    method SetAll (line 97) | func (p *Platform) SetAll() {

FILE: internal/push/offlinepush/jpush/body/pushobj.go
  type PushObj (line 17) | type PushObj struct
    method SetPlatform (line 25) | func (p *PushObj) SetPlatform(pf *Platform) {
    method SetAudience (line 29) | func (p *PushObj) SetAudience(ad *Audience) {
    method SetNotification (line 33) | func (p *PushObj) SetNotification(no *Notification) {
    method SetMessage (line 37) | func (p *PushObj) SetMessage(m *Message) {
    method SetOptions (line 41) | func (p *PushObj) SetOptions(o *Options) {

FILE: internal/push/offlinepush/jpush/push.go
  type JPush (line 28) | type JPush struct
    method Auth (line 39) | func (j *JPush) Auth(apiKey, secretKey string, timeStamp int64) (token...
    method SetAlias (line 43) | func (j *JPush) SetAlias(cid, alias string) (resp string, err error) {
    method getAuthorization (line 47) | func (j *JPush) getAuthorization(appKey string, masterSecret string) s...
    method Push (line 54) | func (j *JPush) Push(ctx context.Context, userIDs []string, title, con...
    method request (line 89) | func (j *JPush) request(ctx context.Context, po body.PushObj, resp *ma...
  function NewClient (line 33) | func NewClient(pushConf *config.Push) *JPush {

FILE: internal/push/offlinepush/offlinepusher.go
  constant geTUI (line 30) | geTUI    = "getui"
  constant firebase (line 31) | firebase = "fcm"
  constant jPush (line 32) | jPush    = "jpush"
  type OfflinePusher (line 36) | type OfflinePusher interface
  function NewOfflinePusher (line 40) | func NewOfflinePusher(pushConf *config.Push, cache cache.ThirdCache, fcm...

FILE: internal/push/offlinepush/options/options.go
  type Opts (line 4) | type Opts struct
  type Signal (line 12) | type Signal struct

FILE: internal/push/offlinepush_handler.go
  type OfflinePushConsumerHandler (line 18) | type OfflinePushConsumerHandler struct
    method HandleMsg2OfflinePush (line 28) | func (o *OfflinePushConsumerHandler) HandleMsg2OfflinePush(ctx context...
    method getOfflinePushInfos (line 49) | func (o *OfflinePushConsumerHandler) getOfflinePushInfos(msg *sdkws.Ms...
    method offlinePushMsg (line 94) | func (o *OfflinePushConsumerHandler) offlinePushMsg(ctx context.Contex...
  function NewOfflinePushConsumerHandler (line 22) | func NewOfflinePushConsumerHandler(offlinePusher offlinepush.OfflinePush...

FILE: internal/push/onlinepusher.go
  type OnlinePusher (line 21) | type OnlinePusher interface
  type emptyOnlinePusher (line 28) | type emptyOnlinePusher struct
    method GetConnsAndOnlinePush (line 34) | func (emptyOnlinePusher) GetConnsAndOnlinePush(ctx context.Context, ms...
    method GetOnlinePushFailedUserIDs (line 38) | func (u emptyOnlinePusher) GetOnlinePushFailedUserIDs(ctx context.Cont...
  function newEmptyOnlinePusher (line 30) | func newEmptyOnlinePusher() *emptyOnlinePusher {
  function NewOnlinePusher (line 43) | func NewOnlinePusher(disCov discovery.Conn, config *Config) (OnlinePushe...
  type DefaultAllNode (line 58) | type DefaultAllNode struct
    method GetConnsAndOnlinePush (line 67) | func (d *DefaultAllNode) GetConnsAndOnlinePush(ctx context.Context, ms...
    method GetOnlinePushFailedUserIDs (line 122) | func (d *DefaultAllNode) GetOnlinePushFailedUserIDs(_ context.Context,...
  function NewDefaultAllNode (line 63) | func NewDefaultAllNode(disCov discovery.Conn, config *Config) *DefaultAl...
  type K8sStaticConsistentHash (line 141) | type K8sStaticConsistentHash struct
    method GetConnsAndOnlinePush (line 150) | func (k *K8sStaticConsistentHash) GetConnsAndOnlinePush(ctx context.Co...
    method GetOnlinePushFailedUserIDs (line 205) | func (k *K8sStaticConsistentHash) GetOnlinePushFailedUserIDs(_ context...
  function NewK8sStaticConsistentHash (line 146) | func NewK8sStaticConsistentHash(disCov discovery.SvcDiscoveryRegistry, c...

FILE: internal/push/push.go
  type pushServer (line 26) | type pushServer struct
    method DelUserPushToken (line 46) | func (p pushServer) DelUserPushToken(ctx context.Context,
  type Config (line 33) | type Config struct
  function Start (line 54) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/push/push_handler.go
  type ConsumerHandler (line 31) | type ConsumerHandler struct
    method HandleMs2PsChat (line 88) | func (c *ConsumerHandler) HandleMs2PsChat(ctx context.Context, msg []b...
    method WaitCache (line 122) | func (c *ConsumerHandler) WaitCache() {
    method Push2User (line 127) | func (c *ConsumerHandler) Push2User(ctx context.Context, userIDs []str...
    method shouldPushOffline (line 181) | func (c *ConsumerHandler) shouldPushOffline(_ context.Context, msg *sd...
    method GetConnsAndOnlinePush (line 195) | func (c *ConsumerHandler) GetConnsAndOnlinePush(ctx context.Context, m...
    method Push2Group (line 221) | func (c *ConsumerHandler) Push2Group(ctx context.Context, groupID stri...
    method asyncOfflinePush (line 265) | func (c *ConsumerHandler) asyncOfflinePush(ctx context.Context, needOf...
    method groupMessagesHandler (line 286) | func (c *ConsumerHandler) groupMessagesHandler(ctx context.Context, gr...
    method offlinePushMsg (line 334) | func (c *ConsumerHandler) offlinePushMsg(ctx context.Context, msg *sdk...
    method filterGroupMessageOfflinePush (line 348) | func (c *ConsumerHandler) filterGroupMessageOfflinePush(ctx context.Co...
    method getOfflinePushInfos (line 357) | func (c *ConsumerHandler) getOfflinePushInfos(msg *sdkws.MsgData) (tit...
    method DeleteMemberAndSetConversationSeq (line 402) | func (c *ConsumerHandler) DeleteMemberAndSetConversationSeq(ctx contex...
  function NewConsumerHandler (line 47) | func NewConsumerHandler(ctx context.Context, config *Config, database co...
  function unmarshalNotificationElem (line 411) | func unmarshalNotificationElem(bytes []byte, t any) error {

FILE: internal/rpc/auth/auth.go
  type authServer (line 49) | type authServer struct
    method GetAdminToken (line 116) | func (s *authServer) GetAdminToken(ctx context.Context, req *pbauth.Ge...
    method GetUserToken (line 143) | func (s *authServer) GetUserToken(ctx context.Context, req *pbauth.Get...
    method GetExistingToken (line 174) | func (s *authServer) GetExistingToken(ctx context.Context, req *pbauth...
    method parseToken (line 185) | func (s *authServer) parseToken(ctx context.Context, tokensString stri...
    method ParseToken (line 225) | func (s *authServer) ParseToken(ctx context.Context, req *pbauth.Parse...
    method ForceLogout (line 237) | func (s *authServer) ForceLogout(ctx context.Context, req *pbauth.Forc...
    method forceKickOff (line 247) | func (s *authServer) forceKickOff(ctx context.Context, userID string, ...
    method InvalidateToken (line 279) | func (s *authServer) InvalidateToken(ctx context.Context, req *pbauth....
    method KickTokens (line 304) | func (s *authServer) KickTokens(ctx context.Context, req *pbauth.KickT...
  type Config (line 59) | type Config struct
  function Start (line 68) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/rpc/conversation/callback.go
  method webhookBeforeCreateSingleChatConversations (line 13) | func (c *conversationServer) webhookBeforeCreateSingleChatConversations(...
  method webhookAfterCreateSingleChatConversations (line 47) | func (c *conversationServer) webhookAfterCreateSingleChatConversations(c...
  method webhookBeforeCreateGroupChatConversations (line 67) | func (c *conversationServer) webhookBeforeCreateGroupChatConversations(c...
  method webhookAfterCreateGroupChatConversations (line 100) | func (c *conversationServer) webhookAfterCreateGroupChatConversations(ct...

FILE: internal/rpc/conversation/conversation.go
  type conversationServer (line 48) | type conversationServer struct
    method GetConversation (line 120) | func (c *conversationServer) GetConversation(ctx context.Context, req ...
    method GetSortedConversationList (line 137) | func (c *conversationServer) GetSortedConversationList(ctx context.Con...
    method GetAllConversations (line 224) | func (c *conversationServer) GetAllConversations(ctx context.Context, ...
    method GetConversations (line 237) | func (c *conversationServer) GetConversations(ctx context.Context, req...
    method getConversations (line 250) | func (c *conversationServer) getConversations(ctx context.Context, own...
    method SetConversation (line 261) | func (c *conversationServer) SetConversation(ctx context.Context, req ...
    method SetConversations (line 280) | func (c *conversationServer) SetConversations(ctx context.Context, req...
    method UpdateConversationsByUser (line 366) | func (c *conversationServer) UpdateConversationsByUser(ctx context.Con...
    method CreateSingleChatConversations (line 383) | func (c *conversationServer) CreateSingleChatConversations(ctx context...
    method CreateGroupChatConversations (line 442) | func (c *conversationServer) CreateGroupChatConversations(ctx context....
    method SetConversationMaxSeq (line 466) | func (c *conversationServer) SetConversationMaxSeq(ctx context.Context...
    method SetConversationMinSeq (line 480) | func (c *conversationServer) SetConversationMinSeq(ctx context.Context...
    method GetConversationIDs (line 494) | func (c *conversationServer) GetConversationIDs(ctx context.Context, r...
    method GetUserConversationIDsHash (line 505) | func (c *conversationServer) GetUserConversationIDsHash(ctx context.Co...
    method GetConversationOfflinePushUserIDs (line 516) | func (c *conversationServer) GetConversationOfflinePushUserIDs(ctx con...
    method conversationSort (line 540) | func (c *conversationServer) conversationSort(conversations map[int64]...
    method getConversationInfo (line 562) | func (c *conversationServer) getConversationInfo(ctx context.Context, ...
    method GetConversationNotReceiveMessageUserIDs (line 639) | func (c *conversationServer) GetConversationNotReceiveMessageUserIDs(c...
    method UpdateConversation (line 647) | func (c *conversationServer) UpdateConversation(ctx context.Context, r...
    method GetOwnerConversation (line 698) | func (c *conversationServer) GetOwnerConversation(ctx context.Context,...
    method GetNotNotifyConversationIDs (line 712) | func (c *conversationServer) GetNotNotifyConversationIDs(ctx context.C...
    method GetPinnedConversationIDs (line 723) | func (c *conversationServer) GetPinnedConversationIDs(ctx context.Cont...
    method ClearUserConversationMsg (line 734) | func (c *conversationServer) ClearUserConversationMsg(ctx context.Cont...
    method setConversationMinSeqAndLatestMsgDestructTime (line 764) | func (c *conversationServer) setConversationMinSeqAndLatestMsgDestruct...
    method DeleteConversations (line 782) | func (c *conversationServer) DeleteConversations(ctx context.Context, ...
  type Config (line 61) | type Config struct
  function Start (line 72) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/rpc/conversation/db_map.go
  function UpdateConversationsMap (line 10) | func UpdateConversationsMap(ctx context.Context, req *conversation.SetCo...
  function UserUpdateCheckMap (line 56) | func UserUpdateCheckMap(ctx context.Context, userID string, req *convers...

FILE: internal/rpc/conversation/notification.go
  type ConversationNotificationSender (line 29) | type ConversationNotificationSender struct
    method ConversationSetPrivateNotification (line 40) | func (c *ConversationNotificationSender) ConversationSetPrivateNotific...
    method ConversationChangeNotification (line 53) | func (c *ConversationNotificationSender) ConversationChangeNotificatio...
    method ConversationUnreadChangeNotification (line 62) | func (c *ConversationNotificationSender) ConversationUnreadChangeNotif...
    method ConversationDeleteNotification (line 77) | func (c *ConversationNotificationSender) ConversationDeleteNotificatio...
  function NewConversationNotificationSender (line 33) | func NewConversationNotificationSender(conf *config.Notification, msgCli...

FILE: internal/rpc/conversation/sync.go
  method GetFullOwnerConversationIDs (line 13) | func (c *conversationServer) GetFullOwnerConversationIDs(ctx context.Con...
  method GetIncrementalConversation (line 37) | func (c *conversationServer) GetIncrementalConversation(ctx context.Cont...

FILE: internal/rpc/group/cache.go
  method GetGroupInfoCache (line 25) | func (g *groupServer) GetGroupInfoCache(ctx context.Context, req *pbgrou...
  method GetGroupMemberCache (line 35) | func (g *groupServer) GetGroupMemberCache(ctx context.Context, req *pbgr...

FILE: internal/rpc/group/callback.go
  method webhookBeforeCreateGroup (line 35) | func (g *groupServer) webhookBeforeCreateGroup(ctx context.Context, befo...
  method webhookAfterCreateGroup (line 80) | func (g *groupServer) webhookAfterCreateGroup(ctx context.Context, after...
  method webhookBeforeMembersJoinGroup (line 104) | func (g *groupServer) webhookBeforeMembersJoinGroup(ctx context.Context,...
  method webhookBeforeSetGroupMemberInfo (line 147) | func (g *groupServer) webhookBeforeSetGroupMemberInfo(ctx context.Contex...
  method webhookAfterSetGroupMemberInfo (line 186) | func (g *groupServer) webhookAfterSetGroupMemberInfo(ctx context.Context...
  method webhookAfterQuitGroup (line 207) | func (g *groupServer) webhookAfterQuitGroup(ctx context.Context, after *...
  method webhookAfterKickGroupMember (line 216) | func (g *groupServer) webhookAfterKickGroupMember(ctx context.Context, a...
  method webhookAfterDismissGroup (line 226) | func (g *groupServer) webhookAfterDismissGroup(ctx context.Context, afte...
  method webhookBeforeApplyJoinGroup (line 231) | func (g *groupServer) webhookBeforeApplyJoinGroup(ctx context.Context, b...
  method webhookAfterTransferGroupOwner (line 242) | func (g *groupServer) webhookAfterTransferGroupOwner(ctx context.Context...
  method webhookBeforeInviteUserToGroup (line 252) | func (g *groupServer) webhookBeforeInviteUserToGroup(ctx context.Context...
  method webhookAfterJoinGroup (line 278) | func (g *groupServer) webhookAfterJoinGroup(ctx context.Context, after *...
  method webhookBeforeSetGroupInfo (line 290) | func (g *groupServer) webhookBeforeSetGroupInfo(ctx context.Context, bef...
  method webhookAfterSetGroupInfo (line 339) | func (g *groupServer) webhookAfterSetGroupInfo(ctx context.Context, afte...
  method webhookBeforeSetGroupInfoEx (line 363) | func (g *groupServer) webhookBeforeSetGroupInfoEx(ctx context.Context, b...
  method webhookAfterSetGroupInfoEx (line 408) | func (g *groupServer) webhookAfterSetGroupInfoEx(ctx context.Context, af...

FILE: internal/rpc/group/convert.go
  method groupDB2PB (line 22) | func (g *groupServer) groupDB2PB(group *model.Group, ownerUserID string,...
  method groupMemberDB2PB (line 44) | func (g *groupServer) groupMemberDB2PB(member *model.GroupMember, appMan...
  method groupMemberDB2PB2 (line 61) | func (g *groupServer) groupMemberDB2PB2(member *model.GroupMember) *sdkw...

FILE: internal/rpc/group/db_map.go
  function UpdateGroupInfoMap (line 28) | func UpdateGroupInfoMap(ctx context.Context, group *sdkws.GroupInfoForSe...
  function UpdateGroupInfoExMap (line 59) | func UpdateGroupInfoExMap(ctx context.Context, group *pbgroup.SetGroupIn...
  function UpdateGroupStatusMap (line 107) | func UpdateGroupStatusMap(status int) map[string]any {
  function UpdateGroupMemberMutedTimeMap (line 113) | func UpdateGroupMemberMutedTimeMap(t time.Time) map[string]any {
  function UpdateGroupMemberMap (line 119) | func UpdateGroupMemberMap(req *pbgroup.SetGroupMemberInfo) map[string]any {

FILE: internal/rpc/group/fill.go
  method PopulateGroupMember (line 23) | func (g *groupServer) PopulateGroupMember(ctx context.Context, members ....

FILE: internal/rpc/group/group.go
  type groupServer (line 57) | type groupServer struct
    method NotificationUserInfoUpdate (line 129) | func (g *groupServer) NotificationUserInfoUpdate(ctx context.Context, ...
    method CheckGroupAdmin (line 155) | func (g *groupServer) CheckGroupAdmin(ctx context.Context, groupID str...
    method IsNotFound (line 172) | func (g *groupServer) IsNotFound(err error) bool {
    method GenGroupID (line 176) | func (g *groupServer) GenGroupID(ctx context.Context, groupID *string)...
    method CreateGroup (line 205) | func (g *groupServer) CreateGroup(ctx context.Context, req *pbgroup.Cr...
    method GetJoinedGroupList (line 315) | func (g *groupServer) GetJoinedGroupList(ctx context.Context, req *pbg...
    method InviteUserToGroup (line 361) | func (g *groupServer) InviteUserToGroup(ctx context.Context, req *pbgr...
    method GetGroupAllMember (line 481) | func (g *groupServer) GetGroupAllMember(ctx context.Context, req *pbgr...
    method checkAdminOrInGroup (line 509) | func (g *groupServer) checkAdminOrInGroup(ctx context.Context, groupID...
    method GetGroupMemberList (line 524) | func (g *groupServer) GetGroupMemberList(ctx context.Context, req *pbg...
    method KickGroupMember (line 550) | func (g *groupServer) KickGroupMember(ctx context.Context, req *pbgrou...
    method GetGroupMembersInfo (line 660) | func (g *groupServer) GetGroupMembersInfo(ctx context.Context, req *pb...
    method getGroupMembersInfo (line 679) | func (g *groupServer) getGroupMembersInfo(ctx context.Context, groupID...
    method GetGroupApplicationList (line 696) | func (g *groupServer) GetGroupApplicationList(ctx context.Context, req...
    method GetGroupsInfo (line 779) | func (g *groupServer) GetGroupsInfo(ctx context.Context, req *pbgroup....
    method GetGroupApplicationUnhandledCount (line 792) | func (g *groupServer) GetGroupApplicationUnhandledCount(ctx context.Co...
    method getGroupsInfo (line 809) | func (g *groupServer) getGroupsInfo(ctx context.Context, groupIDs []st...
    method GroupApplicationResponse (line 840) | func (g *groupServer) GroupApplicationResponse(ctx context.Context, re...
    method JoinGroup (line 922) | func (g *groupServer) JoinGroup(ctx context.Context, req *pbgroup.Join...
    method QuitGroup (line 1000) | func (g *groupServer) QuitGroup(ctx context.Context, req *pbgroup.Quit...
    method deleteMemberAndSetConversationSeq (line 1031) | func (g *groupServer) deleteMemberAndSetConversationSeq(ctx context.Co...
    method setMemberJoinSeq (line 1040) | func (g *groupServer) setMemberJoinSeq(ctx context.Context, groupID st...
    method SetGroupInfo (line 1045) | func (g *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.S...
    method SetGroupInfoEx (line 1138) | func (g *groupServer) SetGroupInfoEx(ctx context.Context, req *pbgroup...
    method TransferGroupOwner (line 1252) | func (g *groupServer) TransferGroupOwner(ctx context.Context, req *pbg...
    method GetGroups (line 1315) | func (g *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetG...
    method GetGroupMembersCMS (line 1364) | func (g *groupServer) GetGroupMembersCMS(ctx context.Context, req *pbg...
    method GetUserReqApplicationList (line 1383) | func (g *groupServer) GetUserReqApplicationList(ctx context.Context, r...
    method DismissGroup (line 1437) | func (g *groupServer) DismissGroup(ctx context.Context, req *pbgroup.D...
    method MuteGroupMember (line 1491) | func (g *groupServer) MuteGroupMember(ctx context.Context, req *pbgrou...
    method CancelMuteGroupMember (line 1525) | func (g *groupServer) CancelMuteGroupMember(ctx context.Context, req *...
    method MuteGroup (line 1565) | func (g *groupServer) MuteGroup(ctx context.Context, req *pbgroup.Mute...
    method CancelMuteGroup (line 1576) | func (g *groupServer) CancelMuteGroup(ctx context.Context, req *pbgrou...
    method SetGroupMemberInfo (line 1587) | func (g *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbg...
    method GetGroupAbstractInfo (line 1743) | func (g *groupServer) GetGroupAbstractInfo(ctx context.Context, req *p...
    method GetUserInGroupMembers (line 1779) | func (g *groupServer) GetUserInGroupMembers(ctx context.Context, req *...
    method GetGroupMemberUserIDs (line 1800) | func (g *groupServer) GetGroupMemberUserIDs(ctx context.Context, req *...
    method GetGroupMemberRoleLevel (line 1813) | func (g *groupServer) GetGroupMemberRoleLevel(ctx context.Context, req...
    method GetGroupUsersReqApplicationList (line 1834) | func (g *groupServer) GetGroupUsersReqApplicationList(ctx context.Cont...
    method GetSpecifiedUserGroupRequestInfo (line 1905) | func (g *groupServer) GetSpecifiedUserGroupRequestInfo(ctx context.Con...
  type Config (line 69) | type Config struct
  function Start (line 80) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/rpc/group/notification.go
  constant applicantReceiver (line 51) | applicantReceiver = iota
  constant adminReceiver (line 52) | adminReceiver
  function NewNotificationSender (line 55) | func NewNotificationSender(db controller.GroupDatabase, config *Config, ...
  type NotificationSender (line 77) | type NotificationSender struct
    method PopulateGroupMember (line 86) | func (g *NotificationSender) PopulateGroupMember(ctx context.Context, ...
    method getUser (line 121) | func (g *NotificationSender) getUser(ctx context.Context, userID strin...
    method getGroupInfo (line 137) | func (g *NotificationSender) getGroupInfo(ctx context.Context, groupID...
    method getGroupMembers (line 158) | func (g *NotificationSender) getGroupMembers(ctx context.Context, grou...
    method getGroupMemberMap (line 174) | func (g *NotificationSender) getGroupMemberMap(ctx context.Context, gr...
    method getGroupMember (line 186) | func (g *NotificationSender) getGroupMember(ctx context.Context, group...
    method getGroupOwnerAndAdminUserID (line 197) | func (g *NotificationSender) getGroupOwnerAndAdminUserID(ctx context.C...
    method groupMemberDB2PB (line 209) | func (g *NotificationSender) groupMemberDB2PB(member *model.GroupMembe...
    method fillOpUser (line 238) | func (g *NotificationSender) fillOpUser(ctx context.Context, targetUse...
    method fillUserByUserID (line 242) | func (g *NotificationSender) fillUserByUserID(ctx context.Context, use...
    method setVersion (line 286) | func (g *NotificationSender) setVersion(ctx context.Context, version *...
    method setSortVersion (line 298) | func (g *NotificationSender) setSortVersion(ctx context.Context, versi...
    method GroupCreatedNotification (line 313) | func (g *NotificationSender) GroupCreatedNotification(ctx context.Cont...
    method GroupInfoSetNotification (line 327) | func (g *NotificationSender) GroupInfoSetNotification(ctx context.Cont...
    method GroupInfoSetNameNotification (line 341) | func (g *NotificationSender) GroupInfoSetNameNotification(ctx context....
    method GroupInfoSetAnnouncementNotification (line 355) | func (g *NotificationSender) GroupInfoSetAnnouncementNotification(ctx ...
    method uuid (line 369) | func (g *NotificationSender) uuid() string {
    method getGroupRequest (line 373) | func (g *NotificationSender) getGroupRequest(ctx context.Context, grou...
    method JoinGroupApplicationNotification (line 397) | func (g *NotificationSender) JoinGroupApplicationNotification(ctx cont...
    method MemberQuitNotification (line 436) | func (g *NotificationSender) MemberQuitNotification(ctx context.Contex...
    method GroupApplicationAcceptedNotification (line 453) | func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx ...
    method GroupApplicationRejectedNotification (line 497) | func (g *NotificationSender) GroupApplicationRejectedNotification(ctx ...
    method GroupOwnerTransferredNotification (line 541) | func (g *NotificationSender) GroupOwnerTransferredNotification(ctx con...
    method MemberKickedNotification (line 572) | func (g *NotificationSender) MemberKickedNotification(ctx context.Cont...
    method GroupApplicationAgreeMemberEnterNotification (line 586) | func (g *NotificationSender) GroupApplicationAgreeMemberEnterNotificat...
    method groupApplicationAgreeMemberEnterNotification (line 590) | func (g *NotificationSender) groupApplicationAgreeMemberEnterNotificat...
    method MemberEnterNotification (line 642) | func (g *NotificationSender) MemberEnterNotification(ctx context.Conte...
    method GroupDismissedNotification (line 683) | func (g *NotificationSender) GroupDismissedNotification(ctx context.Co...
    method GroupMemberMutedNotification (line 696) | func (g *NotificationSender) GroupMemberMutedNotification(ctx context....
    method GroupMemberCancelMutedNotification (line 724) | func (g *NotificationSender) GroupMemberCancelMutedNotification(ctx co...
    method GroupMutedNotification (line 749) | func (g *NotificationSender) GroupMutedNotification(ctx context.Contex...
    method GroupCancelMutedNotification (line 777) | func (g *NotificationSender) GroupCancelMutedNotification(ctx context....
    method GroupMemberInfoSetNotification (line 805) | func (g *NotificationSender) GroupMemberInfoSetNotification(ctx contex...
    method GroupMemberSetToAdminNotification (line 830) | func (g *NotificationSender) GroupMemberSetToAdminNotification(ctx con...
    method GroupMemberSetToOrdinaryUserNotification (line 854) | func (g *NotificationSender) GroupMemberSetToOrdinaryUserNotification(...

FILE: internal/rpc/group/statistics.go
  method GroupCreateCount (line 26) | func (g *groupServer) GroupCreateCount(ctx context.Context, req *group.G...

FILE: internal/rpc/group/sync.go
  constant versionSyncLimit (line 18) | versionSyncLimit = 500
  method GetFullGroupMemberUserIDs (line 20) | func (g *groupServer) GetFullGroupMemberUserIDs(ctx context.Context, req...
  method GetFullJoinGroupIDs (line 44) | func (g *groupServer) GetFullJoinGroupIDs(ctx context.Context, req *pbgr...
  method GetIncrementalGroupMember (line 68) | func (g *groupServer) GetIncrementalGroupMember(ctx context.Context, req...
  method GetIncrementalJoinGroup (line 146) | func (g *groupServer) GetIncrementalJoinGroup(ctx context.Context, req *...
  method BatchGetIncrementalGroupMember (line 172) | func (g *groupServer) BatchGetIncrementalGroupMember(ctx context.Context...

FILE: internal/rpc/incrversion/batch_option.go
  type BatchOption (line 12) | type BatchOption struct
  method newError (line 24) | func (o *BatchOption[A, B]) newError(msg string) error {
  method check (line 28) | func (o *BatchOption[A, B]) check() error {
  method validVersions (line 47) | func (o *BatchOption[A, B]) validVersions() []bool {
  method equalIDs (line 56) | func (o *BatchOption[A, B]) equalIDs(objIDs []primitive.ObjectID) []bool {
  method getVersions (line 64) | func (o *BatchOption[A, B]) getVersions(tags *[]int) (versions map[strin...
  method Build (line 139) | func (o *BatchOption[A, B]) Build() (*B, error) {

FILE: internal/rpc/incrversion/option.go
  constant syncLimit (line 19) | syncLimit = 200
  constant tagQuery (line 22) | tagQuery = iota + 1
  constant tagFull (line 23) | tagFull
  constant tagEqual (line 24) | tagEqual
  type Option (line 27) | type Option struct
  method newError (line 40) | func (o *Option[A, B]) newError(msg string) error {
  method check (line 44) | func (o *Option[A, B]) check() error {
  method validVersion (line 69) | func (o *Option[A, B]) validVersion() bool {
  method equalID (line 74) | func (o *Option[A, B]) equalID(objID primitive.ObjectID) bool {
  method getVersion (line 78) | func (o *Option[A, B]) getVersion(tag *int) (*model.VersionLog, error) {
  method Build (line 108) | func (o *Option[A, B]) Build() (*B, error) {

FILE: internal/rpc/msg/as_read.go
  method GetConversationsHasReadAndMaxSeq (line 32) | func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context...
  method SetConversationHasReadSeq (line 88) | func (m *msgServer) SetConversationHasReadSeq(ctx context.Context, req *...
  method MarkMsgsAsRead (line 106) | func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsg...
  method MarkConversationAsRead (line 148) | func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg...
  method sendMarkAsReadNotification (line 221) | func (m *msgServer) sendMarkAsReadNotification(ctx context.Context, conv...

FILE: internal/rpc/msg/callback.go
  function toCommonCallback (line 37) | func toCommonCallback(ctx context.Context, msg *pbchat.SendMsgReq, comma...
  function GetContent (line 60) | func GetContent(msg *sdkws.MsgData) string {
  method webhookBeforeSendSingleMsg (line 71) | func (m *msgServer) webhookBeforeSendSingleMsg(ctx context.Context, befo...
  method webhookAfterSendSingleMsg (line 93) | func (m *msgServer) webhookAfterSendSingleMsg(ctx context.Context, after...
  method webhookBeforeSendGroupMsg (line 107) | func (m *msgServer) webhookBeforeSendGroupMsg(ctx context.Context, befor...
  method webhookAfterSendGroupMsg (line 127) | func (m *msgServer) webhookAfterSendGroupMsg(ctx context.Context, after ...
  method webhookBeforeMsgModify (line 142) | func (m *msgServer) webhookBeforeMsgModify(ctx context.Context, before *...
  method webhookAfterGroupMsgRead (line 186) | func (m *msgServer) webhookAfterGroupMsgRead(ctx context.Context, after ...
  method webhookAfterSingleMsgRead (line 191) | func (m *msgServer) webhookAfterSingleMsgRead(ctx context.Context, after...
  method webhookAfterRevokeMsg (line 199) | func (m *msgServer) webhookAfterRevokeMsg(ctx context.Context, after *co...
  function buildKeyMsgDataQuery (line 209) | func buildKeyMsgDataQuery(msg *sdkws.MsgData) map[string]string {

FILE: internal/rpc/msg/clear.go
  method DestructMsgs (line 13) | func (m *msgServer) DestructMsgs(ctx context.Context, req *msg.DestructM...
  method GetLastMessageSeqByTime (line 55) | func (m *msgServer) GetLastMessageSeqByTime(ctx context.Context, req *ms...

FILE: internal/rpc/msg/delete.go
  method getMinSeqs (line 28) | func (m *msgServer) getMinSeqs(maxSeqs map[string]int64) map[string]int64 {
  method validateDeleteSyncOpt (line 36) | func (m *msgServer) validateDeleteSyncOpt(opt *msg.DeleteSyncOpt) (isSyn...
  method ClearConversationsMsg (line 43) | func (m *msgServer) ClearConversationsMsg(ctx context.Context, req *msg....
  method UserClearAllMsg (line 53) | func (m *msgServer) UserClearAllMsg(ctx context.Context, req *msg.UserCl...
  method DeleteMsgs (line 67) | func (m *msgServer) DeleteMsgs(ctx context.Context, req *msg.DeleteMsgsR...
  method DeleteMsgPhysicalBySeq (line 95) | func (m *msgServer) DeleteMsgPhysicalBySeq(ctx context.Context, req *msg...
  method DeleteMsgPhysical (line 106) | func (m *msgServer) DeleteMsgPhysical(ctx context.Context, req *msg.Dele...
  method clearConversation (line 117) | func (m *msgServer) clearConversation(ctx context.Context, conversationI...

FILE: internal/rpc/msg/filter.go
  constant separator (line 14) | separator = "-"
  function filterAfterMsg (line 17) | func filterAfterMsg(msg *pbchat.SendMsgReq, after *config.AfterConfig) b...
  function filterBeforeMsg (line 21) | func filterBeforeMsg(msg *pbchat.SendMsgReq, before *config.BeforeConfig...
  function filterMsg (line 25) | func filterMsg(msg *pbchat.SendMsgReq, attentionIds []string, deniedType...
  function defaultDeniedTypes (line 47) | func defaultDeniedTypes(contentType int32) bool {
  function isInInterval (line 61) | func isInInterval(data int32, interval []string) bool {

FILE: internal/rpc/msg/msg_status.go
  method SetSendMsgStatus (line 25) | func (m *msgServer) SetSendMsgStatus(ctx context.Context, req *pbmsg.Set...
  method GetSendMsgStatus (line 33) | func (m *msgServer) GetSendMsgStatus(ctx context.Context, req *pbmsg.Get...

FILE: internal/rpc/msg/notification.go
  type MsgNotificationSender (line 25) | type MsgNotificationSender struct
    method UserDeleteMsgsNotification (line 33) | func (m *MsgNotificationSender) UserDeleteMsgsNotification(ctx context...
    method MarkAsReadNotification (line 42) | func (m *MsgNotificationSender) MarkAsReadNotification(ctx context.Con...
  function NewMsgNotificationSender (line 29) | func NewMsgNotificationSender(config *Config, opts ...notification.Notif...

FILE: internal/rpc/msg/revoke.go
  method RevokeMsg (line 35) | func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq...

FILE: internal/rpc/msg/send.go
  method SendMsg (line 37) | func (m *msgServer) SendMsg(ctx context.Context, req *pbmsg.SendMsgReq) ...
  method sendMsg (line 55) | func (m *msgServer) sendMsg(ctx context.Context, req *pbmsg.SendMsgReq, ...
  method sendMsgGroupChat (line 69) | func (m *msgServer) sendMsgGroupChat(ctx context.Context, req *pbmsg.Sen...
  method setConversationAtInfo (line 99) | func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdk...
  method sendMsgNotification (line 161) | func (m *msgServer) sendMsgNotification(ctx context.Context, req *pbmsg....
  method sendMsgSingleChat (line 173) | func (m *msgServer) sendMsgSingleChat(ctx context.Context, req *pbmsg.Se...
  method SendSimpleMsg (line 207) | func (m *msgServer) SendSimpleMsg(ctx context.Context, req *pbmsg.SendSi...

FILE: internal/rpc/msg/seq.go
  method GetConversationMaxSeq (line 26) | func (m *msgServer) GetConversationMaxSeq(ctx context.Context, req *pbms...
  method GetMaxSeqs (line 34) | func (m *msgServer) GetMaxSeqs(ctx context.Context, req *pbmsg.GetMaxSeq...
  method GetHasReadSeqs (line 42) | func (m *msgServer) GetHasReadSeqs(ctx context.Context, req *pbmsg.GetHa...
  method GetMsgByConversationIDs (line 50) | func (m *msgServer) GetMsgByConversationIDs(ctx context.Context, req *pb...
  method SetUserConversationsMinSeq (line 58) | func (m *msgServer) SetUserConversationsMinSeq(ctx context.Context, req ...
  method GetActiveConversation (line 67) | func (m *msgServer) GetActiveConversation(ctx context.Context, req *pbms...
  method SetUserConversationMaxSeq (line 89) | func (m *msgServer) SetUserConversationMaxSeq(ctx context.Context, req *...
  method SetUserConversationMinSeq (line 98) | func (m *msgServer) SetUserConversationMinSeq(ctx context.Context, req *...

FILE: internal/rpc/msg/server.go
  type MessageInterceptorFunc (line 41) | type MessageInterceptorFunc
  type MessageInterceptorChain (line 44) | type MessageInterceptorChain
  type Config (line 46) | type Config struct
  type msgServer (line 59) | type msgServer struct
    method addInterceptorHandler (line 77) | func (m *msgServer) addInterceptorHandler(interceptorFunc ...MessageIn...
    method conversationAndGetRecvID (line 160) | func (m *msgServer) conversationAndGetRecvID(conversation *conversatio...
  function Start (line 82) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/rpc/msg/statistics.go
  method GetActiveUser (line 29) | func (m *msgServer) GetActiveUser(ctx context.Context, req *msg.GetActiv...
  method GetActiveGroup (line 67) | func (m *msgServer) GetActiveGroup(ctx context.Context, req *msg.GetActi...

FILE: internal/rpc/msg/sync_msg.go
  method PullMessageBySeqs (line 31) | func (m *msgServer) PullMessageBySeqs(ctx context.Context, req *sdkws.Pu...
  method GetSeqMessage (line 92) | func (m *msgServer) GetSeqMessage(ctx context.Context, req *msg.GetSeqMe...
  method GetMaxSeq (line 123) | func (m *msgServer) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqR...
  method SearchMessage (line 152) | func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMe...
  method GetServerTime (line 248) | func (m *msgServer) GetServerTime(ctx context.Context, _ *msg.GetServerT...
  method GetLastMessage (line 252) | func (m *msgServer) GetLastMessage(ctx context.Context, req *msg.GetLast...

FILE: internal/rpc/msg/utils.go
  function IsNotFound (line 24) | func IsNotFound(err error) bool {
  type activeConversations (line 33) | type activeConversations
    method Len (line 35) | func (s activeConversations) Len() int {
    method Less (line 39) | func (s activeConversations) Less(i, j int) bool {
    method Swap (line 43) | func (s activeConversations) Swap(i, j int) {

FILE: internal/rpc/msg/verify.go
  type Validator (line 37) | type Validator interface
  type MessageRevoked (line 41) | type MessageRevoked struct
  method messageVerification (line 54) | func (m *msgServer) messageVerification(ctx context.Context, data *msg.S...
  method encapsulateMsgData (line 143) | func (m *msgServer) encapsulateMsgData(msg *sdkws.MsgData) {
  function GetMsgID (line 171) | func GetMsgID(sendID string) string {
  method modifyMessageByUserMessageReceiveOpt (line 176) | func (m *msgServer) modifyMessageByUserMessageReceiveOpt(ctx context.Con...

FILE: internal/rpc/relation/black.go
  method GetPaginationBlacks (line 31) | func (s *friendServer) GetPaginationBlacks(ctx context.Context, req *rel...
  method IsBlack (line 48) | func (s *friendServer) IsBlack(ctx context.Context, req *relation.IsBlac...
  method RemoveBlack (line 62) | func (s *friendServer) RemoveBlack(ctx context.Context, req *relation.Re...
  method AddBlack (line 77) | func (s *friendServer) AddBlack(ctx context.Context, req *relation.AddBl...
  method GetSpecifiedBlacks (line 103) | func (s *friendServer) GetSpecifiedBlacks(ctx context.Context, req *rela...

FILE: internal/rpc/relation/callback.go
  method webhookAfterDeleteFriend (line 27) | func (s *friendServer) webhookAfterDeleteFriend(ctx context.Context, aft...
  method webhookBeforeAddFriend (line 36) | func (s *friendServer) webhookBeforeAddFriend(ctx context.Context, befor...
  method webhookAfterAddFriend (line 54) | func (s *friendServer) webhookAfterAddFriend(ctx context.Context, after ...
  method webhookAfterSetFriendRemark (line 65) | func (s *friendServer) webhookAfterSetFriendRemark(ctx context.Context, ...
  method webhookAfterImportFriends (line 76) | func (s *friendServer) webhookAfterImportFriends(ctx context.Context, af...
  method webhookAfterRemoveBlack (line 86) | func (s *friendServer) webhookAfterRemoveBlack(ctx context.Context, afte...
  method webhookBeforeSetFriendRemark (line 96) | func (s *friendServer) webhookBeforeSetFriendRemark(ctx context.Context,...
  method webhookBeforeAddBlack (line 115) | func (s *friendServer) webhookBeforeAddBlack(ctx context.Context, before...
  method webhookBeforeAddFriendAgree (line 127) | func (s *friendServer) webhookBeforeAddFriendAgree(ctx context.Context, ...
  method webhookAfterAddFriendAgree (line 141) | func (s *friendServer) webhookAfterAddFriendAgree(ctx context.Context, a...
  method webhookBeforeImportFriends (line 153) | func (s *friendServer) webhookBeforeImportFriends(ctx context.Context, b...

FILE: internal/rpc/relation/friend.go
  type friendServer (line 45) | type friendServer struct
    method ApplyToAddFriend (line 137) | func (s *friendServer) ApplyToAddFriend(ctx context.Context, req *rela...
    method ImportFriends (line 168) | func (s *friendServer) ImportFriends(ctx context.Context, req *relatio...
    method RespondFriendApply (line 203) | func (s *friendServer) RespondFriendApply(ctx context.Context, req *re...
    method DeleteFriend (line 239) | func (s *friendServer) DeleteFriend(ctx context.Context, req *relation...
    method SetFriendRemark (line 260) | func (s *friendServer) SetFriendRemark(ctx context.Context, req *relat...
    method GetFriendInfo (line 284) | func (s *friendServer) GetFriendInfo(ctx context.Context, req *relatio...
    method GetDesignatedFriends (line 295) | func (s *friendServer) GetDesignatedFriends(ctx context.Context, req *...
    method getFriend (line 312) | func (s *friendServer) getFriend(ctx context.Context, ownerUserID stri...
    method GetDesignatedFriendsApply (line 324) | func (s *friendServer) GetDesignatedFriendsApply(ctx context.Context, ...
    method GetPaginationFriendsApplyTo (line 341) | func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context...
    method GetPaginationFriendsApplyFrom (line 365) | func (s *friendServer) GetPaginationFriendsApplyFrom(ctx context.Conte...
    method IsFriend (line 390) | func (s *friendServer) IsFriend(ctx context.Context, req *relation.IsF...
    method GetPaginationFriends (line 402) | func (s *friendServer) GetPaginationFriends(ctx context.Context, req *...
    method GetFriendIDs (line 423) | func (s *friendServer) GetFriendIDs(ctx context.Context, req *relation...
    method GetSpecifiedFriendsInfo (line 437) | func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, re...
    method UpdateFriends (line 517) | func (s *friendServer) UpdateFriends(ctx context.Context, req *relatio...
    method GetSelfUnhandledApplyCount (line 555) | func (s *friendServer) GetSelfUnhandledApplyCount(ctx context.Context,...
    method getCommonUserMap (line 570) | func (s *friendServer) getCommonUserMap(ctx context.Context, userIDs [...
  type Config (line 57) | type Config struct
  function Start (line 69) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/rpc/relation/notification.go
  type FriendNotificationSender (line 42) | type FriendNotificationSender struct
    method getUsersInfoMap (line 102) | func (f *FriendNotificationSender) getUsersInfoMap(ctx context.Context...
    method getFromToUserNickname (line 115) | func (f *FriendNotificationSender) getFromToUserNickname(ctx context.C...
    method UserInfoUpdatedNotification (line 123) | func (f *FriendNotificationSender) UserInfoUpdatedNotification(ctx con...
    method getCommonUserMap (line 128) | func (f *FriendNotificationSender) getCommonUserMap(ctx context.Contex...
    method getFriendRequests (line 138) | func (f *FriendNotificationSender) getFriendRequests(ctx context.Conte...
    method FriendApplicationAddNotification (line 158) | func (f *FriendNotificationSender) FriendApplicationAddNotification(ct...
    method FriendApplicationAgreedNotification (line 174) | func (f *FriendNotificationSender) FriendApplicationAgreedNotification...
    method FriendApplicationRefusedNotification (line 197) | func (f *FriendNotificationSender) FriendApplicationRefusedNotificatio...
    method FriendDeletedNotification (line 236) | func (f *FriendNotificationSender) FriendDeletedNotification(ctx conte...
    method setVersion (line 244) | func (f *FriendNotificationSender) setVersion(ctx context.Context, ver...
    method setSortVersion (line 255) | func (f *FriendNotificationSender) setSortVersion(ctx context.Context,...
    method FriendRemarkSetNotification (line 270) | func (f *FriendNotificationSender) FriendRemarkSetNotification(ctx con...
    method FriendsInfoUpdateNotification (line 278) | func (f *FriendNotificationSender) FriendsInfoUpdateNotification(ctx c...
    method BlackAddedNotification (line 285) | func (f *FriendNotificationSender) BlackAddedNotification(ctx context....
    method BlackDeletedNotification (line 292) | func (f *FriendNotificationSender) BlackDeletedNotification(ctx contex...
    method FriendInfoUpdatedNotification (line 300) | func (f *FriendNotificationSender) FriendInfoUpdatedNotification(ctx c...
  type friendNotificationSenderOptions (line 50) | type friendNotificationSenderOptions
  function WithFriendDB (line 52) | func WithFriendDB(db controller.FriendDatabase) friendNotificationSender...
  function WithDBFunc (line 58) | func WithDBFunc(fn func(ctx context.Context, userIDs []string) (users []...
  function WithRpcFunc (line 74) | func WithRpcFunc(fn func(ctx context.Context, userIDs []string) ([]*sdkw...
  function NewFriendNotificationSender (line 90) | func NewFriendNotificationSender(conf *config.Notification, msgClient *r...

FILE: internal/rpc/relation/sync.go
  method NotificationUserInfoUpdate (line 17) | func (s *friendServer) NotificationUserInfoUpdate(ctx context.Context, r...
  method GetFullFriendUserIDs (line 42) | func (s *friendServer) GetFullFriendUserIDs(ctx context.Context, req *re...
  method GetIncrementalFriends (line 66) | func (s *friendServer) GetIncrementalFriends(ctx context.Context, req *r...

FILE: internal/rpc/third/log.go
  function genLogID (line 32) | func genLogID() string {
  method UploadLogs (line 47) | func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadL...
  method DeleteLogs (line 85) | func (t *thirdServer) DeleteLogs(ctx context.Context, req *third.DeleteL...
  function dbToPbLogInfos (line 109) | func dbToPbLogInfos(logs []*relationtb.Log) []*third.LogInfo {
  method SearchLogs (line 126) | func (t *thirdServer) SearchLogs(ctx context.Context, req *third.SearchL...

FILE: internal/rpc/third/s3.go
  method PartLimit (line 40) | func (t *thirdServer) PartLimit(ctx context.Context, req *third.PartLimi...
  method PartSize (line 52) | func (t *thirdServer) PartSize(ctx context.Context, req *third.PartSizeR...
  method InitiateMultipartUpload (line 60) | func (t *thirdServer) InitiateMultipartUpload(ctx context.Context, req *...
  method AuthSign (line 114) | func (t *thirdServer) AuthSign(ctx context.Context, req *third.AuthSignR...
  method CompleteMultipartUpload (line 137) | func (t *thirdServer) CompleteMultipartUpload(ctx context.Context, req *...
  method AccessURL (line 163) | func (t *thirdServer) AccessURL(ctx context.Context, req *third.AccessUR...
  method InitiateFormData (line 188) | func (t *thirdServer) InitiateFormData(ctx context.Context, req *third.I...
  method CompleteFormData (line 249) | func (t *thirdServer) CompleteFormData(ctx context.Context, req *third.C...
  method apiAddress (line 287) | func (t *thirdServer) apiAddress(prefix, name string) string {
  method DeleteOutdatedData (line 291) | func (t *thirdServer) DeleteOutdatedData(ctx context.Context, req *third...
  type FormDataMate (line 323) | type FormDataMate struct

FILE: internal/rpc/third/third.go
  type thirdServer (line 46) | type thirdServer struct
    method FcmUpdateToken (line 143) | func (t *thirdServer) FcmUpdateToken(ctx context.Context, req *third.F...
    method SetAppBadge (line 151) | func (t *thirdServer) SetAppBadge(ctx context.Context, req *third.SetA...
  type Config (line 56) | type Config struct
  function Start (line 67) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/rpc/third/tool.go
  function toPbMapArray (line 29) | func toPbMapArray(m map[string][]string) []*third.KeyValues {
  method checkUploadName (line 43) | func (t *thirdServer) checkUploadName(ctx context.Context, name string) ...
  function checkValidObjectNamePrefix (line 65) | func checkValidObjectNamePrefix(objectName string) error {
  function checkValidObjectName (line 75) | func checkValidObjectName(objectName string) error {
  function putUpdate (line 82) | func putUpdate[T any](update map[string]any, name string, val interface{...

FILE: internal/rpc/user/callback.go
  method webhookBeforeUpdateUserInfo (line 28) | func (s *userServer) webhookBeforeUpdateUserInfo(ctx context.Context, be...
  method webhookAfterUpdateUserInfo (line 48) | func (s *userServer) webhookAfterUpdateUserInfo(ctx context.Context, aft...
  method webhookBeforeUpdateUserInfoEx (line 58) | func (s *userServer) webhookBeforeUpdateUserInfoEx(ctx context.Context, ...
  method webhookAfterUpdateUserInfoEx (line 78) | func (s *userServer) webhookAfterUpdateUserInfoEx(ctx context.Context, a...
  method webhookBeforeUserRegister (line 88) | func (s *userServer) webhookBeforeUserRegister(ctx context.Context, befo...
  method webhookAfterUserRegister (line 108) | func (s *userServer) webhookAfterUserRegister(ctx context.Context, after...

FILE: internal/rpc/user/config.go
  method GetUserClientConfig (line 12) | func (s *userServer) GetUserClientConfig(ctx context.Context, req *pbuse...
  method SetUserClientConfig (line 28) | func (s *userServer) SetUserClientConfig(ctx context.Context, req *pbuse...
  method DelUserClientConfig (line 43) | func (s *userServer) DelUserClientConfig(ctx context.Context, req *pbuse...
  method PageUserClientConfig (line 53) | func (s *userServer) PageUserClientConfig(ctx context.Context, req *pbus...

FILE: internal/rpc/user/notification.go
  type UserNotificationSender (line 32) | type UserNotificationSender struct
    method UserStatusChangeNotification (line 103) | func (u *UserNotificationSender) UserStatusChangeNotification(
    method UserCommandUpdateNotification (line 109) | func (u *UserNotificationSender) UserCommandUpdateNotification(
    method UserCommandAddNotification (line 115) | func (u *UserNotificationSender) UserCommandAddNotification(
    method UserCommandDeleteNotification (line 121) | func (u *UserNotificationSender) UserCommandDeleteNotification(
  type userNotificationSenderOptions (line 39) | type userNotificationSenderOptions
  function WithUserDB (line 41) | func WithUserDB(db controller.UserDatabase) userNotificationSenderOptions {
  function WithUserFunc (line 47) | func WithUserFunc(
  function NewUserNotificationSender (line 65) | func NewUserNotificationSender(config *Config, msgClient *rpcli.MsgClien...

FILE: internal/rpc/user/online.go
  method getUserOnlineStatus (line 12) | func (s *userServer) getUserOnlineStatus(ctx context.Context, userID str...
  method getUsersOnlineStatus (line 29) | func (s *userServer) getUsersOnlineStatus(ctx context.Context, userIDs [...
  method SubscribeOrCancelUsersStatus (line 42) | func (s *userServer) SubscribeOrCancelUsersStatus(ctx context.Context, r...
  method GetUserStatus (line 47) | func (s *userServer) GetUserStatus(ctx context.Context, req *pbuser.GetU...
  method SetUserStatus (line 56) | func (s *userServer) SetUserStatus(ctx context.Context, req *pbuser.SetU...
  method GetSubscribeUsersStatus (line 74) | func (s *userServer) GetSubscribeUsersStatus(ctx context.Context, req *p...
  method SetUserOnlineStatus (line 78) | func (s *userServer) SetUserOnlineStatus(ctx context.Context, req *pbuse...
  method GetAllOnlineUsers (line 87) | func (s *userServer) GetAllOnlineUsers(ctx context.Context, req *pbuser....

FILE: internal/rpc/user/statistics.go
  method UserRegisterCount (line 25) | func (s *userServer) UserRegisterCount(ctx context.Context, req *pbuser....

FILE: internal/rpc/user/user.go
  constant defaultSecret (line 53) | defaultSecret = "openIM123"
  type userServer (line 56) | type userServer struct
    method GetDesignateUsers (line 145) | func (s *userServer) GetDesignateUsers(ctx context.Context, req *pbuse...
    method UpdateUserInfo (line 158) | func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbuser.U...
    method UpdateUserInfoEx (line 185) | func (s *userServer) UpdateUserInfoEx(ctx context.Context, req *pbuser...
    method SetGlobalRecvMessageOpt (line 228) | func (s *userServer) SetGlobalRecvMessageOpt(ctx context.Context, req ...
    method AccountCheck (line 242) | func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.Acc...
    method GetPaginationUsers (line 270) | func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbus...
    method UserRegister (line 288) | func (s *userServer) UserRegister(ctx context.Context, req *pbuser.Use...
    method GetGlobalRecvMessageOpt (line 346) | func (s *userServer) GetGlobalRecvMessageOpt(ctx context.Context, req ...
    method GetAllUserID (line 355) | func (s *userServer) GetAllUserID(ctx context.Context, req *pbuser.Get...
    method ProcessUserCommandAdd (line 364) | func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *p...
    method ProcessUserCommandDelete (line 392) | func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req...
    method ProcessUserCommandUpdate (line 411) | func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req...
    method ProcessUserCommandGet (line 439) | func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *p...
    method ProcessUserCommandGetAll (line 469) | func (s *userServer) ProcessUserCommandGetAll(ctx context.Context, req...
    method AddNotificationAccount (line 498) | func (s *userServer) AddNotificationAccount(ctx context.Context, req *...
    method UpdateNotificationAccountInfo (line 544) | func (s *userServer) UpdateNotificationAccountInfo(ctx context.Context...
    method SearchNotificationAccount (line 570) | func (s *userServer) SearchNotificationAccount(ctx context.Context, re...
    method GetNotificationAccount (line 619) | func (s *userServer) GetNotificationAccount(ctx context.Context, req *...
    method genUserID (line 639) | func (s *userServer) genUserID() string {
    method userModelToResp (line 654) | func (s *userServer) userModelToResp(users []*tablerelation.User, pagi...
    method NotificationUserInfoUpdate (line 680) | func (s *userServer) NotificationUserInfoUpdate(ctx context.Context, u...
    method SortQuery (line 714) | func (s *userServer) SortQuery(ctx context.Context, req *pbuser.SortQu...
  type Config (line 72) | type Config struct
  function Start (line 84) | func Start(ctx context.Context, config *Config, client discovery.SvcDisc...

FILE: internal/tools/cron/cron_task.go
  type Config (line 21) | type Config struct
  function Start (line 27) | func Start(ctx context.Context, conf *Config, client discovery.SvcDiscov...
  type Locker (line 98) | type Locker interface
  type emptyLocker (line 102) | type emptyLocker struct
    method ExecuteWithLock (line 104) | func (emptyLocker) ExecuteWithLock(ctx context.Context, taskName strin...
  type cronServer (line 108) | type cronServer struct
    method registerClearS3 (line 118) | func (c *cronServer) registerClearS3() error {
    method registerDeleteMsg (line 129) | func (c *cronServer) registerDeleteMsg() error {
    method registerClearUserMsg (line 140) | func (c *cronServer) registerClearUserMsg() error {

FILE: internal/tools/cron/cron_test.go
  function TestName (line 19) | func TestName(t *testing.T) {

FILE: internal/tools/cron/dist_look.go
  constant lockLeaseTTL (line 15) | lockLeaseTTL = 300
  type EtcdLocker (line 18) | type EtcdLocker struct
    method ExecuteWithLock (line 37) | func (e *EtcdLocker) ExecuteWithLock(ctx context.Context, taskName str...
  function NewEtcdLocker (line 24) | func NewEtcdLocker(client *clientv3.Client) (*EtcdLocker, error) {

FILE: internal/tools/cron/msg.go
  method deleteMsg (line 13) | func (c *cronServer) deleteMsg() {

FILE: internal/tools/cron/s3.go
  method clearS3 (line 13) | func (c *cronServer) clearS3() {

FILE: internal/tools/cron/user_msg.go
  method clearUserMsg (line 13) | func (c *cronServer) clearUserMsg() {

FILE: magefile.go
  function Build (line 34) | func Build() {
  function BuildWithCustomConfig (line 43) | func BuildWithCustomConfig() {
  function Start (line 62) | func Start() {
  function StartWithCustomConfig (line 81) | func StartWithCustomConfig() {
  function Stop (line 106) | func Stop() {
  function Check (line 110) | func Check() {
  function Export (line 114) | func Export() {

FILE: magefile_unix.go
  function setMaxOpenFiles (line 12) | func setMaxOpenFiles() error {

FILE: magefile_windows.go
  function setMaxOpenFiles (line 6) | func setMaxOpenFiles() error {

FILE: pkg/apistruct/config_manager.go
  type GetConfigReq (line 3) | type GetConfigReq struct
  type GetConfigListResp (line 7) | type GetConfigListResp struct
  type SetConfigReq (line 13) | type SetConfigReq struct
  type SetConfigsReq (line 18) | type SetConfigsReq struct
  type SetEnableConfigManagerReq (line 22) | type SetEnableConfigManagerReq struct
  type GetEnableConfigManagerResp (line 26) | type GetEnableConfigManagerResp struct

FILE: pkg/apistruct/manage.go
  type SendMsg (line 23) | type SendMsg struct
  type SendMsgReq (line 65) | type SendMsgReq struct
  type GetConversationListReq (line 71) | type GetConversationListReq struct
  type GetConversationListResp (line 79) | type GetConversationListResp struct
  type ConversationElem (line 84) | type ConversationElem struct
  type BatchSendMsgReq (line 96) | type BatchSendMsgReq struct
  type BatchSendMsgResp (line 107) | type BatchSendMsgResp struct
  type SendSingleMsgReq (line 116) | type SendSingleMsgReq struct
  type KeyMsgData (line 124) | type KeyMsgData struct
  type SingleReturnResult (line 131) | type SingleReturnResult struct
  type SendMsgResp (line 148) | type SendMsgResp struct

FILE: pkg/apistruct/msg.go
  type PictureBaseInfo (line 19) | type PictureBaseInfo struct
  type PictureElem (line 28) | type PictureElem struct
  type SoundElem (line 35) | type SoundElem struct
  type VideoElem (line 43) | type VideoElem struct
  type FileElem (line 58) | type FileElem struct
  type AtElem (line 65) | type AtElem struct
  type LocationElem (line 72) | type LocationElem struct
  type CustomElem (line 78) | type CustomElem struct
  type TextElem (line 84) | type TextElem struct
  type MarkdownTextElem (line 88) | type MarkdownTextElem struct
  type StreamMsgElem (line 92) | type StreamMsgElem struct
  type RevokeElem (line 97) | type RevokeElem struct
  type QuoteElem (line 101) | type QuoteElem struct
  type OANotificationElem (line 106) | type OANotificationElem struct
  type MessageRevoked (line 120) | type MessageRevoked struct
  type MsgStruct (line 129) | type MsgStruct struct
  type AtInfo (line 164) | type AtInfo struct

FILE: pkg/apistruct/public.go
  type GroupAddMemberInfo (line 17) | type GroupAddMemberInfo struct

FILE: pkg/authverify/token.go
  function Secret (line 28) | func Secret(secret string) jwt.Keyfunc {
  function CheckAdmin (line 34) | func CheckAdmin(ctx context.Context) error {
  function CheckUserIsAdmin (line 45) | func CheckUserIsAdmin(ctx context.Context, userID string) bool {
  function CheckSystemAccount (line 49) | func CheckSystemAccount(ctx context.Context, level int32) bool {
  constant CtxAdminUserIDsKey (line 54) | CtxAdminUserIDsKey = "CtxAdminUserIDsKey"
  function WithIMAdminUserIDs (line 57) | func WithIMAdminUserIDs(ctx context.Context, imAdminUserID []string) con...
  function GetIMAdminUserIDs (line 61) | func GetIMAdminUserIDs(ctx context.Context) []string {
  function IsAdmin (line 66) | func IsAdmin(ctx context.Context) bool {
  function CheckAccess (line 70) | func CheckAccess(ctx context.Context, ownerUserID string) error {
  function CheckAccessIn (line 80) | func CheckAccessIn(ctx context.Context, ownerUserIDs ...string) error {
  constant ctxTempAdminKey (line 95) | ctxTempAdminKey = "ctxImTempAdminKey"
  function WithTempAdmin (line 97) | func WithTempAdmin(ctx context.Context) context.Context {
  function IsTempAdmin (line 113) | func IsTempAdmin(ctx context.Context) bool {
  function IsSystemAdmin (line 118) | func IsSystemAdmin(ctx context.Context) bool {

FILE: pkg/callbackstruct/common.go
  constant Next (line 23) | Next = 1
  type CommonCallbackReq (line 26) | type CommonCallbackReq struct
    method GetCallbackCommand (line 47) | func (c *CommonCallbackReq) GetCallbackCommand() string {
  type CallbackReq (line 51) | type CallbackReq interface
  type CallbackResp (line 55) | type CallbackResp interface
  type CommonCallbackResp (line 59) | type CommonCallbackResp struct
    method Parse (line 67) | func (c CommonCallbackResp) Parse() error {
  type UserStatusBaseCallback (line 74) | type UserStatusBaseCallback struct
    method GetCallbackCommand (line 81) | func (c UserStatusBaseCallback) GetCallbackCommand() string {
  type UserStatusCallbackReq (line 85) | type UserStatusCallbackReq struct
  type UserStatusBatchCallbackReq (line 90) | type UserStatusBatchCallbackReq struct

FILE: pkg/callbackstruct/constant.go
  constant CallbackBeforeInviteJoinGroupCommand (line 18) | CallbackBeforeInviteJoinGroupCommand               = "callbackBeforeInvi...
  constant CallbackAfterJoinGroupCommand (line 19) | CallbackAfterJoinGroupCommand                      = "callbackAfterJoinG...
  constant CallbackAfterSetGroupInfoCommand (line 20) | CallbackAfterSetGroupInfoCommand                   = "callbackAfterSetGr...
  constant CallbackAfterSetGroupInfoExCommand (line 21) | CallbackAfterSetGroupInfoExCommand                 = "callbackAfterSetGr...
  constant CallbackBeforeSetGroupInfoCommand (line 22) | CallbackBeforeSetGroupInfoCommand                  = "callbackBeforeSetG...
  constant CallbackBeforeSetGroupInfoExCommand (line 23) | CallbackBeforeSetGroupInfoExCommand                = "callbackBeforeSetG...
  constant CallbackAfterRevokeMsgCommand (line 24) | CallbackAfterRevokeMsgCommand                      = "callbackBeforeAfte...
  constant CallbackBeforeAddBlackCommand (line 25) | CallbackBeforeAddBlackCommand                      = "callbackBeforeAddB...
  constant CallbackAfterAddFriendCommand (line 26) | CallbackAfterAddFriendCommand                      = "callbackAfterAddFr...
  constant CallbackBeforeAddFriendAgreeCommand (line 27) | CallbackBeforeAddFriendAgreeCommand                = "callbackBeforeAddF...
  constant CallbackAfterAddFriendAgreeCommand (line 28) | CallbackAfterAddFriendAgreeCommand                 = "callbackAfterAddFr...
  constant CallbackAfterDeleteFriendCommand (line 29) | CallbackAfterDeleteFriendCommand                   = "callbackAfterDelet...
  constant CallbackBeforeImportFriendsCommand (line 30) | CallbackBeforeImportFriendsCommand                 = "callbackBeforeImpo...
  constant CallbackAfterImportFriendsCommand (line 31) | CallbackAfterImportFriendsCommand                  = "callbackAfterImpor...
  constant CallbackAfterRemoveBlackCommand (line 32) | CallbackAfterRemoveBlackCommand                    = "callbackAfterRemov...
  constant CallbackAfterQuitGroupCommand (line 33) | CallbackAfterQuitGroupCommand                      = "callbackAfterQuitG...
  constant CallbackAfterKickGroupCommand (line 34) | CallbackAfterKickGroupCommand                      = "callbackAfterKickG...
  constant CallbackAfterDisMissGroupCommand (line 35) | CallbackAfterDisMissGroupCommand                   = "callbackAfterDisMi...
  constant CallbackBeforeJoinGroupCommand (line 36) | CallbackBeforeJoinGroupCommand                     = "callbackBeforeJoin...
  constant CallbackAfterGroupMsgReadCommand (line 37) | CallbackAfterGroupMsgReadCommand                   = "callbackAfterGroup...
  constant CallbackBeforeMsgModifyCommand (line 38) | CallbackBeforeMsgModifyCommand                     = "callbackBeforeMsgM...
  constant CallbackAfterUpdateUserInfoCommand (line 39) | CallbackAfterUpdateUserInfoCommand                 = "callbackAfterUpdat...
  constant CallbackAfterUpdateUserInfoExCommand (line 40) | CallbackAfterUpdateUserInfoExCommand               = "callbackAfterUpdat...
  constant CallbackBeforeUpdateUserInfoExCommand (line 41) | CallbackBeforeUpdateUserInfoExCommand              = "callbackBeforeUpda...
  constant CallbackBeforeUserRegisterCommand (line 42) | CallbackBeforeUserRegisterCommand                  = "callbackBeforeUser...
  constant CallbackAfterUserRegisterCommand (line 43) | CallbackAfterUserRegisterCommand                   = "callbackAfterUserR...
  constant CallbackAfterTransferGroupOwnerCommand (line 44) | CallbackAfterTransferGroupOwnerCommand             = "callbackAfterTrans...
  constant CallbackBeforeSetFriendRemarkCommand (line 45) | CallbackBeforeSetFriendRemarkCommand               = "callbackBeforeSetF...
  constant CallbackAfterSetFriendRemarkCommand (line 46) | CallbackAfterSetFriendRemarkCommand                = "callbackAfterSetFr...
  constant CallbackAfterSingleMsgReadCommand (line 47) | CallbackAfterSingleMsgReadCommand                  = "callbackAfterSingl...
  constant CallbackBeforeSendSingleMsgCommand (line 48) | CallbackBeforeSendSingleMsgCommand                 = "callbackBeforeSend...
  constant CallbackAfterSendSingleMsgCommand (line 49) | CallbackAfterSendSingleMsgCommand                  = "callbackAfterSendS...
  constant CallbackBeforeSendGroupMsgCommand (line 50) | CallbackBeforeSendGroupMsgCommand                  = "callbackBeforeSend...
  constant CallbackAfterSendGroupMsgCommand (line 51) | CallbackAfterSendGroupMsgCommand                   = "callbackAfterSendG...
  constant CallbackAfterUserOnlineCommand (line 52) | CallbackAfterUserOnlineCommand                     = "callbackAfterUserO...
  constant CallbackAfterUserOfflineCommand (line 53) | CallbackAfterUserOfflineCommand                    = "callbackAfterUserO...
  constant CallbackAfterUserKickOffCommand (line 54) | CallbackAfterUserKickOffCommand                    = "callbackAfterUserK...
  constant CallbackBeforeOfflinePushCommand (line 55) | CallbackBeforeOfflinePushCommand                   = "callbackBeforeOffl...
  constant CallbackBeforeOnlinePushCommand (line 56) | CallbackBeforeOnlinePushCommand                    = "callbackBeforeOnli...
  constant CallbackBeforeGroupOnlinePushCommand (line 57) | CallbackBeforeGroupOnlinePushCommand               = "callbackBeforeGrou...
  constant CallbackBeforeAddFriendCommand (line 58) | CallbackBeforeAddFriendCommand                     = "callbackBeforeAddF...
  constant CallbackBeforeUpdateUserInfoCommand (line 59) | CallbackBeforeUpdateUserInfoCommand                = "callbackBeforeUpda...
  constant CallbackBeforeCreateGroupCommand (line 60) | CallbackBeforeCreateGroupCommand                   = "callbackBeforeCrea...
  constant CallbackAfterCreateGroupCommand (line 61) | CallbackAfterCreateGroupCommand                    = "callbackAfterCreat...
  constant CallbackBeforeMembersJoinGroupCommand (line 62) | CallbackBeforeMembersJoinGroupCommand              = "callbackBeforeMemb...
  constant CallbackBeforeSetGroupMemberInfoCommand (line 63) | CallbackBeforeSetGroupMemberInfoCommand            = "callbackBeforeSetG...
  constant CallbackAfterSetGroupMemberInfoCommand (line 64) | CallbackAfterSetGroupMemberInfoCommand             = "callbackAfterSetGr...
  constant CallbackBeforeCreateSingleChatConversationsCommand (line 65) | CallbackBeforeCreateSingleChatConversationsCommand = "callbackBeforeCrea...
  constant CallbackAfterCreateSingleChatConversationsCommand (line 66) | CallbackAfterCreateSingleChatConversationsCommand  = "callbackAfterCreat...
  constant CallbackBeforeCreateGroupChatConversationsCommand (line 67) | CallbackBeforeCreateGroupChatConversationsCommand  = "callbackBeforeCrea...
  constant CallbackAfterCreateGroupChatConversationsCommand (line 68) | CallbackAfterCreateGroupChatConversationsCommand   = "callbackAfterCreat...
  constant CallbackAfterMsgSaveDBCommand (line 69) | CallbackAfterMsgSaveDBCommand                      = "callbackAfterMsgSa...

FILE: pkg/callbackstruct/conversation.go
  type CallbackBeforeCreateSingleChatConversationsReq (line 3) | type CallbackBeforeCreateSingleChatConversationsReq struct
  type CallbackBeforeCreateSingleChatConversationsResp (line 18) | type CallbackBeforeCreateSingleChatConversationsResp struct
  type CallbackAfterCreateSingleChatConversationsReq (line 29) | type CallbackAfterCreateSingleChatConversationsReq struct
  type CallbackAfterCreateSingleChatConversationsResp (line 44) | type CallbackAfterCreateSingleChatConversationsResp struct
  type CallbackBeforeCreateGroupChatConversationsReq (line 48) | type CallbackBeforeCreateGroupChatConversationsReq struct
  type CallbackBeforeCreateGroupChatConversationsResp (line 63) | type CallbackBeforeCreateGroupChatConversationsResp struct
  type CallbackAfterCreateGroupChatConversationsReq (line 74) | type CallbackAfterCreateGroupChatConversationsReq struct
  type CallbackAfterCreateGroupChatConversationsResp (line 89) | type CallbackAfterCreateGroupChatConversationsResp struct

FILE: pkg/callbackstruct/friend.go
  type CallbackBeforeAddFriendReq (line 17) | type CallbackBeforeAddFriendReq struct
  type CallbackBeforeAddFriendResp (line 25) | type CallbackBeforeAddFriendResp struct
  type CallBackAddFriendReplyBeforeReq (line 29) | type CallBackAddFriendReplyBeforeReq struct
  type CallBackAddFriendReplyBeforeResp (line 35) | type CallBackAddFriendReplyBeforeResp struct
  type CallbackBeforeSetFriendRemarkReq (line 39) | type CallbackBeforeSetFriendRemarkReq struct
  type CallbackBeforeSetFriendRemarkResp (line 46) | type CallbackBeforeSetFriendRemarkResp struct
  type CallbackAfterSetFriendRemarkReq (line 51) | type CallbackAfterSetFriendRemarkReq struct
  type CallbackAfterSetFriendRemarkResp (line 58) | type CallbackAfterSetFriendRemarkResp struct
  type CallbackAfterAddFriendReq (line 61) | type CallbackAfterAddFriendReq struct
  type CallbackAfterAddFriendResp (line 68) | type CallbackAfterAddFriendResp struct
  type CallbackBeforeAddBlackReq (line 71) | type CallbackBeforeAddBlackReq struct
  type CallbackBeforeAddBlackResp (line 77) | type CallbackBeforeAddBlackResp struct
  type CallbackBeforeAddFriendAgreeReq (line 81) | type CallbackBeforeAddFriendAgreeReq struct
  type CallbackBeforeAddFriendAgreeResp (line 89) | type CallbackBeforeAddFriendAgreeResp struct
  type CallbackAfterAddFriendAgreeReq (line 93) | type CallbackAfterAddFriendAgreeReq struct
  type CallbackAfterAddFriendAgreeResp (line 101) | type CallbackAfterAddFriendAgreeResp struct
  type CallbackAfterDeleteFriendReq (line 105) | type CallbackAfterDeleteFriendReq struct
  type CallbackAfterDeleteFriendResp (line 110) | type CallbackAfterDeleteFriendResp struct
  type CallbackBeforeImportFriendsReq (line 114) | type CallbackBeforeImportFriendsReq struct
  type CallbackBeforeImportFriendsResp (line 119) | type CallbackBeforeImportFriendsResp struct
  type CallbackAfterImportFriendsReq (line 123) | type CallbackAfterImportFriendsReq struct
  type CallbackAfterImportFriendsResp (line 128) | type CallbackAfterImportFriendsResp struct
  type CallbackAfterRemoveBlackReq (line 132) | type CallbackAfterRemoveBlackReq struct
  type CallbackAfterRemoveBlackResp (line 137) | type CallbackAfterRemoveBlackResp struct

FILE: pkg/callbackstruct/group.go
  type CallbackCommand (line 23) | type CallbackCommand
    method GetCallbackCommand (line 25) | func (c CallbackCommand) GetCallbackCommand() string {
  type CallbackBeforeCreateGroupReq (line 29) | type CallbackBeforeCreateGroupReq struct
  type CallbackBeforeCreateGroupResp (line 36) | type CallbackBeforeCreateGroupResp struct
  type CallbackAfterCreateGroupReq (line 53) | type CallbackAfterCreateGroupReq struct
  type CallbackAfterCreateGroupResp (line 59) | type CallbackAfterCreateGroupResp struct
  type CallbackGroupMember (line 63) | type CallbackGroupMember struct
  type CallbackBeforeMembersJoinGroupReq (line 68) | type CallbackBeforeMembersJoinGroupReq struct
  type MemberJoinGroupCallBack (line 75) | type MemberJoinGroupCallBack struct
  type CallbackBeforeMembersJoinGroupResp (line 84) | type CallbackBeforeMembersJoinGroupResp struct
  type CallbackBeforeSetGroupMemberInfoReq (line 89) | type CallbackBeforeSetGroupMemberInfoReq struct
  type CallbackBeforeSetGroupMemberInfoResp (line 99) | type CallbackBeforeSetGroupMemberInfoResp struct
  type CallbackAfterSetGroupMemberInfoReq (line 107) | type CallbackAfterSetGroupMemberInfoReq struct
  type CallbackAfterSetGroupMemberInfoResp (line 117) | type CallbackAfterSetGroupMemberInfoResp struct
  type CallbackQuitGroupReq (line 121) | type CallbackQuitGroupReq struct
  type CallbackQuitGroupResp (line 127) | type CallbackQuitGroupResp struct
  type CallbackKillGroupMemberReq (line 131) | type CallbackKillGroupMemberReq struct
  type CallbackKillGroupMemberResp (line 138) | type CallbackKillGroupMemberResp struct
  type CallbackDisMissGroupReq (line 142) | type CallbackDisMissGroupReq struct
  type CallbackDisMissGroupResp (line 150) | type CallbackDisMissGroupResp struct
  type CallbackJoinGroupReq (line 154) | type CallbackJoinGroupReq struct
  type CallbackJoinGroupResp (line 163) | type CallbackJoinGroupResp struct
  type CallbackTransferGroupOwnerReq (line 167) | type CallbackTransferGroupOwnerReq struct
  type CallbackTransferGroupOwnerResp (line 174) | type CallbackTransferGroupOwnerResp struct
  type CallbackBeforeInviteUserToGroupReq (line 178) | type CallbackBeforeInviteUserToGroupReq struct
  type CallbackBeforeInviteUserToGroupResp (line 185) | type CallbackBeforeInviteUserToGroupResp struct
  type CallbackAfterJoinGroupReq (line 190) | type CallbackAfterJoinGroupReq struct
  type CallbackAfterJoinGroupResp (line 198) | type CallbackAfterJoinGroupResp struct
  type CallbackBeforeSetGroupInfoReq (line 202) | type CallbackBeforeSetGroupInfoReq struct
  type CallbackBeforeSetGroupInfoResp (line 216) | type CallbackBeforeSetGroupInfoResp struct
  type CallbackAfterSetGroupInfoReq (line 229) | type CallbackAfterSetGroupInfoReq struct
  type CallbackAfterSetGroupInfoResp (line 243) | type CallbackAfterSetGroupInfoResp struct
  type CallbackBeforeSetGroupInfoExReq (line 247) | type CallbackBeforeSetGroupInfoExReq struct
  type CallbackBeforeSetGroupInfoExResp (line 261) | type CallbackBeforeSetGroupInfoExResp struct
  type CallbackAfterSetGroupInfoExReq (line 274) | type CallbackAfterSetGroupInfoExReq struct
  type CallbackAfterSetGroupInfoExResp (line 288) | type CallbackAfterSetGroupInfoExResp struct

FILE: pkg/callbackstruct/message.go
  type CallbackBeforeSendSingleMsgReq (line 21) | type CallbackBeforeSendSingleMsgReq struct
  type CallbackBeforeSendSingleMsgResp (line 26) | type CallbackBeforeSendSingleMsgResp struct
  type CallbackAfterSendSingleMsgReq (line 30) | type CallbackAfterSendSingleMsgReq struct
  type CallbackAfterSendSingleMsgResp (line 35) | type CallbackAfterSendSingleMsgResp struct
  type CallbackBeforeSendGroupMsgReq (line 39) | type CallbackBeforeSendGroupMsgReq struct
  type CallbackBeforeSendGroupMsgResp (line 44) | type CallbackBeforeSendGroupMsgResp struct
  type CallbackAfterSendGroupMsgReq (line 48) | type CallbackAfterSendGroupMsgReq struct
  type CallbackAfterSendGroupMsgResp (line 53) | type CallbackAfterSendGroupMsgResp struct
  type CallbackMsgModifyCommandReq (line 57) | type CallbackMsgModifyCommandReq struct
  type CallbackMsgModifyCommandResp (line 61) | type CallbackMsgModifyCommandResp struct
  type CallbackGroupMsgReadReq (line 83) | type CallbackGroupMsgReadReq struct
  type CallbackGroupMsgReadResp (line 91) | type CallbackGroupMsgReadResp struct
  type CallbackSingleMsgReadReq (line 95) | type CallbackSingleMsgReadReq struct
  type CallbackSingleMsgReadResp (line 103) | type CallbackSingleMsgReadResp struct
  type CallbackAfterMsgSaveDBReq (line 107) | type CallbackAfterMsgSaveDBReq struct
  type CallbackAfterMsgSaveDBResp (line 113) | type CallbackAfterMsgSaveDBResp struct

FILE: pkg/callbackstruct/msg_gateway.go
  type CallbackUserOnlineReq (line 17) | type CallbackUserOnlineReq struct
  type CallbackUserOnlineResp (line 25) | type CallbackUserOnlineResp struct
  type CallbackUserOfflineReq (line 29) | type CallbackUserOfflineReq struct
  type CallbackUserOfflineResp (line 35) | type CallbackUserOfflineResp struct
  type CallbackUserKickOffReq (line 39) | type CallbackUserKickOffReq struct
  type CallbackUserKickOffResp (line 44) | type CallbackUserKickOffResp struct

FILE: pkg/callbackstruct/push.go
  type CallbackBeforePushReq (line 19) | type CallbackBeforePushReq struct
  type CallbackBeforePushResp (line 31) | type CallbackBeforePushResp struct
  type CallbackBeforeSuperGroupOnlinePushReq (line 37) | type CallbackBeforeSuperGroupOnlinePushReq struct
  type CallbackBeforeSuperGroupOnlinePushResp (line 49) | type CallbackBeforeSuperGroupOnlinePushResp struct

FILE: pkg/callbackstruct/revoke.go
  type CallbackAfterRevokeMsgReq (line 17) | type CallbackAfterRevokeMsgReq struct
  type CallbackAfterRevokeMsgResp (line 24) | type CallbackAfterRevokeMsgResp struct

FILE: pkg/callbackstruct/user.go
  type CallbackBeforeUpdateUserInfoReq (line 22) | type CallbackBeforeUpdateUserInfoReq struct
  type CallbackBeforeUpdateUserInfoResp (line 30) | type CallbackBeforeUpdateUserInfoResp struct
  type CallbackAfterUpdateUserInfoReq (line 37) | type CallbackAfterUpdateUserInfoReq struct
  type CallbackAfterUpdateUserInfoResp (line 44) | type CallbackAfterUpdateUserInfoResp struct
  type CallbackBeforeUpdateUserInfoExReq (line 48) | type CallbackBeforeUpdateUserInfoExReq struct
  type CallbackBeforeUpdateUserInfoExResp (line 55) | type CallbackBeforeUpdateUserInfoExResp struct
  type CallbackAfterUpdateUserInfoExReq (line 62) | type CallbackAfterUpdateUserInfoExReq struct
  type CallbackAfterUpdateUserInfoExResp (line 69) | type CallbackAfterUpdateUserInfoExResp struct
  type CallbackBeforeUserRegisterReq (line 73) | type CallbackBeforeUserRegisterReq struct
  type CallbackBeforeUserRegisterResp (line 78) | type CallbackBeforeUserRegisterResp struct
  type CallbackAfterUserRegisterReq (line 83) | type CallbackAfterUserRegisterReq struct
  type CallbackAfterUserRegisterResp (line 88) | type CallbackAfterUserRegisterResp struct

FILE: pkg/common/cmd/api.go
  type ApiCmd (line 29) | type ApiCmd struct
    method Exec (line 72) | func (a *ApiCmd) Exec() error {
    method runE (line 76) | func (a *ApiCmd) runE() error {
  function NewApiCmd (line 36) | func NewApiCmd() *ApiCmd {

FILE: pkg/common/cmd/auth.go
  type AuthRpcCmd (line 28) | type AuthRpcCmd struct
    method Exec (line 55) | func (a *AuthRpcCmd) Exec() error {
    method runE (line 59) | func (a *AuthRpcCmd) runE() error {
  function NewAuthRpcCmd (line 35) | func NewAuthRpcCmd() *AuthRpcCmd {

FILE: pkg/common/cmd/conversation.go
  type ConversationRpcCmd (line 28) | type ConversationRpcCmd struct
    method Exec (line 56) | func (a *ConversationRpcCmd) Exec() error {
    method runE (line 60) | func (a *ConversationRpcCmd) runE() error {
  function NewConversationRpcCmd (line 35) | func NewConversationRpcCmd() *ConversationRpcCmd {

FILE: pkg/common/cmd/cron_task.go
  type CronTaskCmd (line 28) | type CronTaskCmd struct
    method Exec (line 51) | func (a *CronTaskCmd) Exec() error {
    method runE (line 55) | func (a *CronTaskCmd) runE() error {
  function NewCronTaskCmd (line 35) | func NewCronTaskCmd() *CronTaskCmd {

FILE: pkg/common/cmd/friend.go
  type FriendRpcCmd (line 28) | type FriendRpcCmd struct
    method Exec (line 56) | func (a *FriendRpcCmd) Exec() error {
    method runE (line 60) | func (a *FriendRpcCmd) runE() error {
  function NewFriendRpcCmd (line 35) | func NewFriendRpcCmd() *FriendRpcCmd {

FILE: pkg/common/cmd/group.go
  type GroupRpcCmd (line 29) | type GroupRpcCmd struct
    method Exec (line 57) | func (a *GroupRpcCmd) Exec() error {
    method runE (line 61) | func (a *GroupRpcCmd) runE() error {
  function NewGroupRpcCmd (line 36) | func NewGroupRpcCmd() *GroupRpcCmd {

FILE: pkg/common/cmd/msg.go
  type MsgRpcCmd (line 28) | type MsgRpcCmd struct
    method Exec (line 57) | func (a *MsgRpcCmd) Exec() error {
    method runE (line 61) | func (a *MsgRpcCmd) runE() error {
  function NewMsgRpcCmd (line 35) | func NewMsgRpcCmd() *MsgRpcCmd {

FILE: pkg/common/cmd/msg_gateway.go
  type MsgGatewayCmd (line 29) | type MsgGatewayCmd struct
    method Exec (line 54) | func (m *MsgGatewayCmd) Exec() error {
    method runE (line 58) | func (m *MsgGatewayCmd) runE() error {
  function NewMsgGatewayCmd (line 36) | func NewMsgGatewayCmd() *MsgGatewayCmd {

FILE: pkg/common/cmd/msg_gateway_test.go
  type MockRootCmd (line 29) | type MockRootCmd struct
    method Execute (line 33) | func (m *MockRootCmd) Execute() error {
  function TestName (line 38) | func TestName(t *testing.T) {
  function TestName1 (line 65) | func TestName1(t *testing.T) {

FILE: pkg/common/cmd/msg_transfer.go
  type MsgTransferCmd (line 29) | type MsgTransferCmd struct
    method Exec (line 56) | func (m *MsgTransferCmd) Exec() error {
    method runE (line 60) | func (m *MsgTransferCmd) runE() error {
  function NewMsgTransferCmd (line 36) | func NewMsgTransferCmd() *MsgTransferCmd {

FILE: pkg/common/cmd/msg_utils.go
  type MsgUtilsCmd (line 22) | type MsgUtilsCmd struct
    method AddUserIDFlag (line 26) | func (m *MsgUtilsCmd) AddUserIDFlag() {
    method AddIndexFlag (line 29) | func (m *MsgUtilsCmd) AddIndexFlag() {
    method AddConfigDirFlag (line 33) | func (m *MsgUtilsCmd) AddConfigDirFlag() {
    method getUserIDFlag (line 38) | func (m *MsgUtilsCmd) getUserIDFlag(cmdLines *cobra.Command) string {
    method AddFixAllFlag (line 43) | func (m *MsgUtilsCmd) AddFixAllFlag() {
    method AddClearAllFlag (line 52) | func (m *MsgUtilsCmd) AddClearAllFlag() {
    method AddSuperGroupIDFlag (line 61) | func (m *MsgUtilsCmd) AddSuperGroupIDFlag() {
    method getSuperGroupIDFlag (line 65) | func (m *MsgUtilsCmd) getSuperGroupIDFlag(cmdLines *cobra.Command) str...
    method AddBeginSeqFlag (line 70) | func (m *MsgUtilsCmd) AddBeginSeqFlag() {
    method AddLimitFlag (line 79) | func (m *MsgUtilsCmd) AddLimitFlag() {
    method Execute (line 88) | func (m *MsgUtilsCmd) Execute() error {
  function NewMsgUtilsCmd (line 92) | func NewMsgUtilsCmd(use, short string, args cobra.PositionalArgs) *MsgUt...
  type GetCmd (line 102) | type GetCmd struct
  function NewGetCmd (line 106) | func NewGetCmd() *GetCmd {
  type FixCmd (line 112) | type FixCmd struct
  function NewFixCmd (line 116) | func NewFixCmd() *FixCmd {
  type ClearCmd (line 122) | type ClearCmd struct
  function NewClearCmd (line 126) | func NewClearCmd() *ClearCmd {
  type SeqCmd (line 132) | type SeqCmd struct
    method GetSeqCmd (line 143) | func (s *SeqCmd) GetSeqCmd() *cobra.Command {
    method FixSeqCmd (line 150) | func (s *SeqCmd) FixSeqCmd() *cobra.Command {
  function NewSeqCmd (line 136) | func NewSeqCmd() *SeqCmd {
  type MsgCmd (line 154) | type MsgCmd struct
    method GetMsgCmd (line 165) | func (m *MsgCmd) GetMsgCmd() *cobra.Command {
    method ClearMsgCmd (line 169) | func (m *MsgCmd) ClearMsgCmd() *cobra.Command {
  function NewMsgCmd (line 158) | func NewMsgCmd() *MsgCmd {

FILE: pkg/common/cmd/push.go
  type PushRpcCmd (line 28) | type PushRpcCmd struct
    method Exec (line 58) | func (a *PushRpcCmd) Exec() error {
    method runE (line 62) | func (a *PushRpcCmd) runE() error {
  function NewPushRpcCmd (line 35) | func NewPushRpcCmd() *PushRpcCmd {

FILE: pkg/common/cmd/root.go
  type RootCmd (line 19) | type RootCmd struct
    method ConfigPath (line 30) | func (r *RootCmd) ConfigPath() string {
    method Index (line 34) | func (r *RootCmd) Index() int {
    method Port (line 38) | func (r *RootCmd) Port() int {
    method initEtcd (line 82) | func (r *RootCmd) initEtcd() error {
    method persistentPreRun (line 99) | func (r *RootCmd) persistentPreRun(cmd *cobra.Command, opts ...func(*C...
    method initializeConfiguration (line 119) | func (r *RootCmd) initializeConfiguration(cmd *cobra.Command, opts *Cm...
    method updateConfigFromEtcd (line 137) | func (r *RootCmd) updateConfigFromEtcd(opts *CmdOpts) error {
    method applyOptions (line 195) | func (r *RootCmd) applyOptions(opts ...func(*CmdOpts)) *CmdOpts {
    method initializeLogger (line 204) | func (r *RootCmd) initializeLogger(cmdOpts *CmdOpts) error {
    method getFlag (line 231) | func (r *RootCmd) getFlag(cmd *cobra.Command) (string, int, error) {
    method Execute (line 245) | func (r *RootCmd) Execute() error {
  type CmdOpts (line 42) | type CmdOpts struct
  function WithCronTaskLogName (line 47) | func WithCronTaskLogName() func(*CmdOpts) {
  function WithLogName (line 53) | func WithLogName(logName string) func(*CmdOpts) {
  function WithConfigMap (line 58) | func WithConfigMap(configMap map[string]any) func(*CmdOpts) {
  function NewRootCmd (line 64) | func NewRootCmd(processName string, opts ...func(*CmdOpts)) *RootCmd {
  function defaultCmdOpts (line 225) | func defaultCmdOpts() *CmdOpts {

FILE: pkg/common/cmd/third.go
  type ThirdRpcCmd (line 28) | type ThirdRpcCmd struct
    method Exec (line 56) | func (a *ThirdRpcCmd) Exec() error {
    method runE (line 60) | func (a *ThirdRpcCmd) runE() error {
  function NewThirdRpcCmd (line 35) | func NewThirdRpcCmd() *ThirdRpcCmd {

FILE: pkg/common/cmd/user.go
  type UserRpcCmd (line 28) | type UserRpcCmd struct
    method Exec (line 57) | func (a *UserRpcCmd) Exec() error {
    method runE (line 61) | func (a *UserRpcCmd) runE() error {
  function NewUserRpcCmd (line 35) | func NewUserRpcCmd() *UserRpcCmd {

FILE: pkg/common/config/config.go
  constant StructTagName (line 31) | StructTagName = "yaml"
  type Path (line 33) | type Path
  type Index (line 35) | type Index
  type CacheConfig (line 37) | type CacheConfig struct
    method Failed (line 677) | func (l *CacheConfig) Failed() time.Duration {
    method Success (line 681) | func (l *CacheConfig) Success() time.Duration {
    method Enable (line 685) | func (l *CacheConfig) Enable() bool {
  type LocalCache (line 45) | type LocalCache struct
    method GetConfigFileName (line 895) | func (lc *LocalCache) GetConfigFileName() string {
  type Log (line 53) | type Log struct
    method GetConfigFileName (line 899) | func (l *Log) GetConfigFileName() string {
  type Minio (line 64) | type Minio struct
    method Build (line 615) | func (m *Minio) Build() *minio.Config {
    method GetConfigFileName (line 903) | func (m *Minio) GetConfigFileName() string {
  type Mongo (line 74) | type Mongo struct
    method Build (line 549) | func (m *Mongo) Build() *mongoutil.Config {
    method GetConfigFileName (line 907) | func (m *Mongo) GetConfigFileName() string {
  type ReplicaSetConfig (line 89) | type ReplicaSetConfig struct
  type ReadPrefConfig (line 96) | type ReadPrefConfig struct
  type WriteConcernConfig (line 102) | type WriteConcernConfig struct
  type Kafka (line 108) | type Kafka struct
    method Build (line 597) | func (k *Kafka) Build() *kafka.Config {
    method GetConfigFileName (line 891) | func (k *Kafka) GetConfigFileName() string {
  type TLSConfig (line 125) | type TLSConfig struct
  type API (line 134) | type API struct
    method GetConfigFileName (line 915) | func (a *API) GetConfigFileName() string {
  type RateLimiter (line 150) | type RateLimiter struct
  type CircuitBreaker (line 157) | type CircuitBreaker struct
  type CronTask (line 165) | type CronTask struct
    method GetConfigFileName (line 919) | func (ct *CronTask) GetConfigFileName() string {
  type OfflinePushConfig (line 172) | type OfflinePushConfig struct
  type NotificationConfig (line 179) | type NotificationConfig struct
  type Notification (line 186) | type Notification struct
    method GetConfigFileName (line 911) | func (n *Notification) GetConfigFileName() string {
  type Prometheus (line 222) | type Prometheus struct
  type MsgGateway (line 227) | type MsgGateway struct
    method GetConfigFileName (line 923) | func (mg *MsgGateway) GetConfigFileName() string {
  type MsgTransfer (line 241) | type MsgTransfer struct
    method GetConfigFileName (line 927) | func (mt *MsgTransfer) GetConfigFileName() string {
  type Push (line 251) | type Push struct
    method GetConfigFileName (line 931) | func (p *Push) GetConfigFileName() string {
  type Auth (line 284) | type Auth struct
    method GetConfigFileName (line 935) | func (a *Auth) GetConfigFileName() string {
  type Conversation (line 294) | type Conversation struct
    method GetConfigFileName (line 939) | func (c *Conversation) GetConfigFileName() string {
  type Friend (line 301) | type Friend struct
    method GetConfigFileName (line 943) | func (f *Friend) GetConfigFileName() string {
  type Group (line 308) | type Group struct
    method GetConfigFileName (line 947) | func (g *Group) GetConfigFileName() string {
  type Msg (line 316) | type Msg struct
    method GetConfigFileName (line 951) | func (m *Msg) GetConfigFileName() string {
  type Third (line 324) | type Third struct
    method GetConfigFileName (line 955) | func (t *Third) GetConfigFileName() string {
  type Cos (line 337) | type Cos struct
    method Build (line 633) | func (c *Cos) Build() *cos.Config {
  type Oss (line 344) | type Oss struct
    method Build (line 643) | func (o *Oss) Build() *oss.Config {
  type Kodo (line 354) | type Kodo struct
    method Build (line 655) | func (o *Kodo) Build() *kodo.Config {
  type Aws (line 364) | type Aws struct
    method Build (line 667) | func (o *Aws) Build() *aws.Config {
  type User (line 373) | type User struct
    method GetConfigFileName (line 959) | func (u *User) GetConfigFileName() string {
  type RPC (line 380) | type RPC struct
  type Redis (line 387) | type Redis struct
    method Build (line 579) | func (r *Redis) Build() *redisutil.Config {
    method GetConfigFileName (line 963) | func (r *Redis) GetConfigFileName() string {
  type Sentinel (line 399) | type Sentinel struct
  type BeforeConfig (line 406) | type BeforeConfig struct
  type AfterConfig (line 413) | type AfterConfig struct
  type Share (line 420) | type Share struct
    method GetConfigFileName (line 967) | func (s *Share) GetConfigFileName() string {
  type MaxRequestBody (line 430) | type MaxRequestBody struct
  type MultiLogin (line 435) | type MultiLogin struct
  type RpcService (line 440) | type RpcService struct
    method GetServiceNames (line 452) | func (r *RpcService) GetServiceNames() []string {
  type Webhooks (line 467) | type Webhooks struct
    method GetConfigFileName (line 971) | func (w *Webhooks) GetConfigFileName() string {
  type ZooKeeper (line 524) | type ZooKeeper struct
  type Discovery (line 531) | type Discovery struct
    method GetConfigFileName (line 887) | func (d *Discovery) GetConfigFileName() string {
  type Kubernetes (line 538) | type Kubernetes struct
  type Etcd (line 542) | type Etcd struct
  function InitNotification (line 689) | func InitNotification(notification *Notification) {
  type AllConfig (line 758) | type AllConfig struct
    method Name2Config (line 783) | func (a *AllConfig) Name2Config(name string) any {
    method GetConfigNames (line 834) | func (a *AllConfig) GetConfigNames() []string {
  constant FileName (line 862) | FileName                         = "config.yaml"
  constant DiscoveryConfigFilename (line 863) | DiscoveryConfigFilename          = "discovery.yml"
  constant KafkaConfigFileName (line 864) | KafkaConfigFileName              = "kafka.yml"
  constant LocalCacheConfigFileName (line 865) | LocalCacheConfigFileName         = "local-cache.yml"
  constant LogConfigFileName (line 866) | LogConfigFileName                = "log.yml"
  constant MinioConfigFileName (line 867) | MinioConfigFileName              = "minio.yml"
  constant MongodbConfigFileName (line 868) | MongodbConfigFileName            = "mongodb.yml"
  constant NotificationFileName (line 869) | NotificationFileName             = "notification.yml"
  constant OpenIMAPICfgFileName (line 870) | OpenIMAPICfgFileName             = "openim-api.yml"
  constant OpenIMCronTaskCfgFileName (line 871) | OpenIMCronTaskCfgFileName        = "openim-crontask.yml"
  constant OpenIMMsgGatewayCfgFileName (line 872) | OpenIMMsgGatewayCfgFileName      = "openim-msggateway.yml"
  constant OpenIMMsgTransferCfgFileName (line 873) | OpenIMMsgTransferCfgFileName     = "openim-msgtransfer.yml"
  constant OpenIMPushCfgFileName (line 874) | OpenIMPushCfgFileName            = "openim-push.yml"
  constant OpenIMRPCAuthCfgFileName (line 875) | OpenIMRPCAuthCfgFileName         = "openim-rpc-auth.yml"
  constant OpenIMRPCConversationCfgFileName (line 876) | OpenIMRPCConversationCfgFileName = "openim-rpc-conversation.yml"
  constant OpenIMRPCFriendCfgFileName (line 877) | OpenIMRPCFriendCfgFileName       = "openim-rpc-friend.yml"
  constant OpenIMRPCGroupCfgFileName (line 878) | OpenIMRPCGroupCfgFileName        = "openim-rpc-group.yml"
  constant OpenIMRPCMsgCfgFileName (line 879) | OpenIMRPCMsgCfgFileName          = "openim-rpc-msg.yml"
  constant OpenIMRPCThirdCfgFileName (line 880) | OpenIMRPCThirdCfgFileName        = "openim-rpc-third.yml"
  constant OpenIMRPCUserCfgFileName (line 881) | OpenIMRPCUserCfgFileName         = "openim-rpc-user.yml"
  constant RedisConfigFileName (line 882) | RedisConfigFileName              = "redis.yml"
  constant ShareFileName (line 883) | ShareFileName                    = "share.yml"
  constant WebhooksConfigFileName (line 884) | WebhooksConfigFileName           = "webhooks.yml"

FILE: pkg/common/config/constant.go
  constant ConfKey (line 19) | ConfKey = "conf"
  constant MountConfigFilePath (line 22) | MountConfigFilePath = "CONFIG_PATH"
  constant DeploymentType (line 23) | DeploymentType      = "DEPLOYMENT_TYPE"
  constant KUBERNETES (line 24) | KUBERNETES          = runtimeenv.Kubernetes
  constant ETCD (line 25) | ETCD                = "etcd"
  constant DefaultDirPerm (line 32) | DefaultDirPerm = 0755
  constant PrivateFilePerm (line 35) | PrivateFilePerm = 0600
  constant ExecFilePerm (line 39) | ExecFilePerm = 0754
  constant SharedDirPerm (line 43) | SharedDirPerm = 0770
  constant ReadOnlyDirPerm (line 46) | ReadOnlyDirPerm = 0555

FILE: pkg/common/config/env.go
  function init (line 7) | func init() {
  constant FlagConf (line 28) | FlagConf          = "config_folder_path"
  constant FlagTransferIndex (line 29) | FlagTransferIndex = "index"

FILE: pkg/common/config/global.go
  function SetStandalone (line 5) | func SetStandalone() {
  function Standalone (line 9) | func Standalone() bool {

FILE: pkg/common/config/load_config.go
  function Load (line 14) | func Load(configDirectory string, configFileName string, envPrefix strin...
  function loadConfig (line 27) | func loadConfig(path string, envPrefix string, config any) error {

FILE: pkg/common/config/load_config_test.go
  function TestLoadLogConfig (line 10) | func TestLoadLogConfig(t *testing.T) {
  function TestLoadMongoConfig (line 19) | func TestLoadMongoConfig(t *testing.T) {
  function TestLoadMinioConfig (line 39) | func TestLoadMinioConfig(t *testing.T) {
  function TestLoadWebhooksConfig (line 46) | func TestLoadWebhooksConfig(t *testing.T) {
  function TestLoadOpenIMRpcUserConfig (line 54) | func TestLoadOpenIMRpcUserConfig(t *testing.T) {
  function TestLoadNotificationConfig (line 64) | func TestLoadNotificationConfig(t *testing.T) {
  function TestLoadOpenIMThirdConfig (line 71) | func TestLoadOpenIMThirdConfig(t *testing.T) {
  function TestTransferConfig (line 87) | func TestTransferConfig(t *testing.T) {

FILE: pkg/common/config/parse.go
  constant DefaultFolderPath (line 30) | DefaultFolderPath = "../config/"
  function GetDefaultConfigPath (line 34) | func GetDefaultConfigPath() (string, error) {
  function GetProjectRoot (line 48) | func GetProjectRoot() (string, error) {
  function GetOptionsByNotification (line 60) | func GetOptionsByNotification(cfg NotificationConfig, sendMessage *bool)...
  function initConfig (line 85) | func initConfig(config any, configName, configFolderPath string) error {

FILE: pkg/common/convert/auth.go
  function TokenMapDB2Pb (line 3) | func TokenMapDB2Pb(tokenMapDB map[string]int) map[string]int32 {
  function TokenMapPb2DB (line 15) | func TokenMapPb2DB(tokenMapPB map[string]int32) map[string]int {

FILE: pkg/common/convert/black.go
  function BlackDB2Pb (line 25) | func BlackDB2Pb(ctx context.Context, blackDBs []*model.Black, f func(ctx...

FILE: pkg/common/convert/conversation.go
  function ConversationDB2Pb (line 23) | func ConversationDB2Pb(conversationDB *model.Conversation) *conversation...
  function ConversationsDB2Pb (line 32) | func ConversationsDB2Pb(conversationsDB []*model.Conversation) (conversa...
  function ConversationPb2DB (line 44) | func ConversationPb2DB(conversationPB *conversation.Conversation) *model...
  function ConversationsPb2DB (line 52) | func ConversationsPb2DB(conversationsPB []*conversation.Conversation) (c...

FILE: pkg/common/convert/friend.go
  function FriendPb2DB (line 30) | func FriendPb2DB(friend *sdkws.FriendInfo) *model.Friend {
  function FriendDB2Pb (line 41) | func FriendDB2Pb(ctx context.Context, friendDB *model.Friend, getUsers f...
  function FriendsDB2Pb (line 57) | func FriendsDB2Pb(ctx context.Context, friendsDB []*model.Friend, getUse...
  function FriendOnlyDB2PbOnly (line 88) | func FriendOnlyDB2PbOnly(friendsDB []*model.Friend) []*relation.FriendIn...
  function FriendRequestDB2Pb (line 103) | func FriendRequestDB2Pb(ctx context.Context, friendRequests []*model.Fri...
  function FriendPb2DBMap (line 141) | func FriendPb2DBMap(friend *sdkws.FriendInfo) map[string]any {

FILE: pkg/common/convert/group.go
  function Db2PbGroupInfo (line 25) | func Db2PbGroupInfo(m *model.Group, ownerUserID string, memberCount uint...
  function Pb2DbGroupRequest (line 47) | func Pb2DbGroupRequest(req *pbgroup.GroupApplicationResponseReq, handleU...
  function Db2PbCMSGroup (line 58) | func Db2PbCMSGroup(m *model.Group, ownerUserID string, ownerUserName str...
  function Db2PbGroupMember (line 66) | func Db2PbGroupMember(m *model.GroupMember) *sdkws.GroupMemberFullInfo {
  function Db2PbGroupRequest (line 83) | func Db2PbGroupRequest(m *model.GroupRequest, user *sdkws.UserInfo, grou...
  function Db2PbGroupAbstractInfo (line 108) | func Db2PbGroupAbstractInfo(
  function Pb2DBGroupInfo (line 120) | func Pb2DBGroupInfo(m *sdkws.GroupInfo) *model.Group {

FILE: pkg/common/convert/msg.go
  function MsgPb2DB (line 23) | func MsgPb2DB(msg *sdkws.MsgData) *model.MsgDataModel {
  function MsgDB2Pb (line 60) | func MsgDB2Pb(msgModel *model.MsgDataModel) *sdkws.MsgData {

FILE: pkg/common/convert/user.go
  function UserDB2Pb (line 25) | func UserDB2Pb(user *relationtb.User) *sdkws.UserInfo {
  function UsersDB2Pb (line 37) | func UsersDB2Pb(users []*relationtb.User) []*sdkws.UserInfo {
  function UserPb2DB (line 41) | func UserPb2DB(user *sdkws.UserInfo) *relationtb.User {
  function UserPb2DBMap (line 53) | func UserPb2DBMap(user *sdkws.UserInfo) map[string]any {
  function UserPb2DBMapEx (line 74) | func UserPb2DBMapEx(user *sdkws.UserInfoWithEx) map[string]any {

FILE: pkg/common/convert/user_test.go
  function TestUsersDB2Pb (line 25) | func TestUsersDB2Pb(t *testing.T) {
  function TestUserPb2DB (line 45) | func TestUserPb2DB(t *testing.T) {
  function TestUserPb2DBMap (line 65) | func TestUserPb2DBMap(t *testing.T) {

FILE: pkg/common/discovery/direct/direct_resolver.go
  constant slashSeparator (line 27) | slashSeparator = "/"
  constant EndpointSepChar (line 29) | EndpointSepChar = ','
  constant subsetSize (line 31) | subsetSize = 32
  constant scheme (line 32) | scheme     = "direct"
  type ResolverDirect (line 35) | type ResolverDirect struct
    method Build (line 42) | func (rd *ResolverDirect) Build(target resolver.Target, cc resolver.Cl...
    method Scheme (line 67) | func (rd *ResolverDirect) Scheme() string {
  function NewResolverDirect (line 38) | func NewResolverDirect() *ResolverDirect {
  function init (line 64) | func init() {
  function GetEndpoints (line 72) | func GetEndpoints(target resolver.Target) string {
  function subset (line 75) | func subset(set []string, sub int) []string {
  type nopResolver (line 86) | type nopResolver struct
    method ResolveNow (line 90) | func (n nopResolver) ResolveNow(options resolver.ResolveNowOptions) {
    method Close (line 94) | func (n nopResolver) Close() {

FILE: pkg/common/discovery/discoveryregister.go
  function NewDiscoveryRegister (line 33) | func NewDiscoveryRegister(discovery *config.Discovery, watchNames []stri...

FILE: pkg/common/discovery/discoveryregister_test.go
  function setupTestEnvironment (line 21) | func setupTestEnvironment() {

FILE: pkg/common/discovery/etcd/config_manager.go
  function RegisterShutDown (line 21) | func RegisterShutDown(shutDown ...func() error) {
  type ConfigManager (line 25) | type ConfigManager struct
    method Watch (line 41) | func (c *ConfigManager) Watch(ctx context.Context) {
  function BuildKey (line 31) | func BuildKey(s string) string {
  function NewConfigManager (line 35) | func NewConfigManager(client *clientv3.Client, configNames []string) *Co...
  function restartServer (line 72) | func restartServer(ctx context.Context) error {

FILE: pkg/common/discovery/etcd/const.go
  constant ConfigKeyPrefix (line 4) | ConfigKeyPrefix       = "/open-im/config/"
  constant RestartKey (line 5) | RestartKey            = "restart"
  constant EnableConfigCenterKey (line 6) | EnableConfigCenterKey = "enable-config-center"
  constant Enable (line 7) | Enable                = "enable"
  constant Disable (line 8) | Disable               = "disable"

FILE: pkg/common/discovery/kubernetes/kubernetes.go
  type KubernetesConnManager (line 21) | type KubernetesConnManager struct
    method initializeConns (line 57) | func (k *KubernetesConnManager) initializeConns(serviceName string) er...
    method GetConns (line 91) | func (k *KubernetesConnManager) GetConns(ctx context.Context, serviceN...
    method GetConn (line 117) | func (k *KubernetesConnManager) GetConn(ctx context.Context, serviceNa...
    method GetSelfConnTarget (line 146) | func (k *KubernetesConnManager) GetSelfConnTarget() string {
    method AddOption (line 180) | func (k *KubernetesConnManager) AddOption(opts ...grpc.DialOption) {
    method CloseConn (line 187) | func (k *KubernetesConnManager) CloseConn(conn *grpc.ClientConn) {
    method Close (line 192) | func (k *KubernetesConnManager) Close() {
    method Register (line 203) | func (k *KubernetesConnManager) Register(serviceName, host string, por...
    method UnRegister (line 207) | func (k *KubernetesConnManager) UnRegister() error {
    method GetUserIdHashGatewayHost (line 211) | func (k *KubernetesConnManager) GetUserIdHashGatewayHost(ctx context.C...
    method getServicePort (line 215) | func (k *KubernetesConnManager) getServicePort(serviceName string) (in...
    method watchEndpoints (line 240) | func (k *KubernetesConnManager) watchEndpoints() {
    method handleEndpointChange (line 261) | func (k *KubernetesConnManager) handleEndpointChange(obj interface{}) {
  function NewKubernetesConnManager (line 34) | func NewKubernetesConnManager(namespace string, options ...grpc.DialOpti...

FILE: pkg/common/prommetrics/api.go
  function RegistryApi (line 28) | func RegistryApi() {
  function ApiInit (line 32) | func ApiInit(listener net.Listener) error {
  function APICall (line 42) | func APICall(path string, method string, apiCode int) {
  function HttpCall (line 46) | func HttpCall(path string, method string, status int) {

FILE: pkg/common/prommetrics/grpc_auth.go
  function RegistryAuth (line 28) | func RegistryAuth() {

FILE: pkg/common/prommetrics/grpc_msg.go
  function RegistryMsg (line 40) | func RegistryMsg() {

FILE: pkg/common/prommetrics/grpc_msggateway.go
  function RegistryMsgGateway (line 28) | func RegistryMsgGateway() {

FILE: pkg/common/prommetrics/grpc_push.go
  function RegistryPush (line 32) | func RegistryPush() {

FILE: pkg/common/prommetrics/grpc_user.go
  function RegistryUser (line 12) | func RegistryUser() {

FILE: pkg/common/prommetrics/prommetrics.go
  constant commonPath (line 28) | commonPath = "/metrics"
  type prometheusRegistry (line 32) | type prometheusRegistry struct
    method MustRegister (line 36) | func (x *prometheusRegistry) MustRegister(cs ...prometheus.Collector) {
  function init (line 47) | func init() {
  function Init (line 61) | func Init(registry *prometheus.Registry, listener net.Listener, path str...
  function RegistryAll (line 68) | func RegistryAll() {
  function Start (line 79) | func Start(listener net.Listener) error {
  constant APIKeyName (line 86) | APIKeyName             = "api"
  constant MessageTransferKeyName (line 87) | MessageTransferKeyName = "message-transfer"
  constant TTL (line 89) | TTL = 300
  type Target (line 92) | type Target struct
  type RespTarget (line 97) | type RespTarget struct
  function BuildDiscoveryKeyPrefix (line 102) | func BuildDiscoveryKeyPrefix(name string) string {
  function BuildDiscoveryKey (line 106) | func BuildDiscoveryKey(name string, index int) string {
  function BuildDefaultTarget (line 110) | func BuildDefaultTarget(host string, ip int) Target {

FILE: pkg/common/prommetrics/prommetrics_test.go
  function TestName (line 73) | func TestName(t *testing.T) {

FILE: pkg/common/prommetrics/rpc.go
  constant rpcPath (line 13) | rpcPath = commonPath
  function RegistryRpc (line 26) | func RegistryRpc() {
  function RpcInit (line 30) | func RpcInit(cs []prometheus.Collector, listener net.Listener) error {
  function RPCCall (line 39) | func RPCCall(name string, path string, code int) {
  function GetGrpcServerMetrics (line 43) | func GetGrpcServerMetrics() *gp.ServerMetrics {
  function GetGrpcCusMetrics (line 51) | func GetGrpcCusMetrics(registerName string, discovery *config.Discovery)...

FILE: pkg/common/prommetrics/transfer.go
  function RegistryTransfer (line 47) | func RegistryTransfer() {
  function TransferInit (line 57) | func TransferInit(listener net.Listener) error {

FILE: pkg/common/servererrs/code.go
  constant UnknownCode (line 18) | UnknownCode = 1000
  constant FormattingError (line 22) | FormattingError      = 10001
  constant HasRegistered (line 23) | HasRegistered        = 10002
  constant NotRegistered (line 24) | NotRegistered        = 10003
  constant PasswordErr (line 25) | PasswordErr          = 10004
  constant GetIMTokenErr (line 26) | GetIMTokenErr        = 10005
  constant RepeatSendCode (line 27) | RepeatSendCode       = 10006
  constant MailSendCodeErr (line 28) | MailSendCodeErr      = 10007
  constant SmsSendCodeErr (line 29) | SmsSendCodeErr       = 10008
  constant CodeInvalidOrExpired (line 30) | CodeInvalidOrExpired = 10009
  constant RegisterFailed (line 31) | RegisterFailed       = 10010
  constant ResetPasswordFailed (line 32) | ResetPasswordFailed  = 10011
  constant RegisterLimit (line 33) | RegisterLimit        = 10012
  constant LoginLimit (line 34) | LoginLimit           = 10013
  constant InvitationError (line 35) | InvitationError      = 10014
  constant NoError (line 40) | NoError = 0
  constant DatabaseError (line 42) | DatabaseError = 90002
  constant NetworkError (line 43) | NetworkError  = 90004
  constant DataError (line 44) | DataError     = 90007
  constant CallbackError (line 46) | CallbackError = 80000
  constant ServerInternalError (line 49) | ServerInternalError   = 500
  constant ArgsError (line 50) | ArgsError             = 1001
  constant NoPermissionError (line 51) | NoPermissionError     = 1002
  constant DuplicateKeyError (line 52) | DuplicateKeyError     = 1003
  constant RecordNotFoundError (line 53) | RecordNotFoundError   = 1004
  constant SecretNotChangedError (line 54) | SecretNotChangedError = 1050
  constant UserIDNotFoundError (line 57) | UserIDNotFoundError    = 1101
  constant RegisteredAlreadyError (line 58) | RegisteredAlreadyError = 1102
  constant GroupIDNotFoundError (line 61) | GroupIDNotFoundError  = 1201
  constant GroupIDExisted (line 62) | GroupIDExisted        = 1202
  constant NotInGroupYetError (line 63) | NotInGroupYetError    = 1203
  constant DismissedAlreadyError (line 64) | DismissedAlreadyError = 1204
  constant GroupTypeNotSupport (line 65) | GroupTypeNotSupport   = 1205
  constant GroupRequestHandled (line 66) | GroupRequestHandled   = 1206
  constant CanNotAddYourselfError (line 69) | CanNotAddYourselfError   = 1301
  constant BlockedByPeer (line 70) | BlockedByPeer            = 1302
  constant NotPeersFriend (line 71) | NotPeersFriend           = 1303
  constant RelationshipAlreadyError (line 72) | RelationshipAlreadyError = 1304
  constant FriendRequestHandled (line 73) | FriendRequestHandled     = 1305
  constant MessageHasReadDisable (line 76) | MessageHasReadDisable = 1401
  constant MutedInGroup (line 77) | MutedInGroup          = 1402
  constant MutedGroup (line 78) | MutedGroup            = 1403
  constant MsgAlreadyRevoke (line 79) | MsgAlreadyRevoke      = 1404
  constant TokenExpiredError (line 82) | TokenExpiredError     = 1501
  constant TokenInvalidError (line 83) | TokenInvalidError     = 1502
  constant TokenMalformedError (line 84) | TokenMalformedError   = 1503
  constant TokenNotValidYetError (line 85) | TokenNotValidYetError = 1504
  constant TokenUnknownError (line 86) | TokenUnknownError     = 1505
  constant TokenKickedError (line 87) | TokenKickedError      = 1506
  constant TokenNotExistError (line 88) | TokenNotExistError    = 1507
  constant ConnOverMaxNumLimit (line 91) | ConnOverMaxNumLimit  = 1601
  constant ConnArgsErr (line 92) | ConnArgsErr          = 1602
  constant PushMsgErr (line 93) | PushMsgErr           = 1603
  constant IOSBackgroundPushErr (line 94) | IOSBackgroundPushErr = 1604
  constant FileUploadedExpiredError (line 97) | FileUploadedExpiredError = 1701

FILE: pkg/common/servererrs/relation.go
  function init (line 21) | func init() {
  type relation (line 27) | type relation struct
    method Add (line 31) | func (r *relation) Add(codes ...int) {
    method Is (line 48) | func (r *relation) Is(parent, child int) bool {

FILE: pkg/common/startrpc/circuitbreaker.go
  type CircuitBreaker (line 15) | type CircuitBreaker struct
  function NewCircuitBreaker (line 23) | func NewCircuitBreaker(config *CircuitBreaker) circuitbreaker.CircuitBre...
  function UnaryCircuitBreakerInterceptor (line 36) | func UnaryCircuitBreakerInterceptor(breaker circuitbreaker.CircuitBreake...
  function StreamCircuitBreakerInterceptor (line 73) | func StreamCircuitBreakerInterceptor(breaker circuitbreaker.CircuitBreak...

FILE: pkg/common/startrpc/mw.go
  function grpcServerIMAdminUserID (line 10) | func grpcServerIMAdminUserID(imAdminUserID []string) grpc.ServerOption {

FILE: pkg/common/startrpc/ratelimit.go
  type RateLimiter (line 15) | type RateLimiter struct
  function NewRateLimiter (line 22) | func NewRateLimiter(config *RateLimiter) ratelimit.Limiter {
  function UnaryRateLimitInterceptor (line 34) | func UnaryRateLimitInterceptor(limiter ratelimit.Limiter) grpc.ServerOpt...
  function StreamRateLimitInterceptor (line 53) | func StreamRateLimitInterceptor(limiter ratelimit.Limiter) grpc.ServerOp...

FILE: pkg/common/startrpc/start.go
  function init (line 46) | func init() {
  function Start (line 50) | func Start[T any](ctx context.Context, disc *conf.Discovery, circuitBrea...
  function listenTCP (line 278) | func listenTCP(addr string) (net.Listener, int, error) {
  function prommetricsUnaryInterceptor (line 286) | func prommetricsUnaryInterceptor(rpcRegisterName string) grpc.ServerOpti...
  function prommetricsStreamInterceptor (line 304) | func prommetricsStreamInterceptor(rpcRegisterName string) grpc.ServerOpt...
  type grpcServiceRegistrar (line 308) | type grpcServiceRegistrar struct
    method RegisterService (line 312) | func (x *grpcServiceRegistrar) RegisterService(desc *grpc.ServiceDesc,...

FILE: pkg/common/startrpc/tools.go
  function getConfig (line 9) | func getConfig[T any](value reflect.Value) *T {
  function getConfigRpcMaxRequestBody (line 33) | func getConfigRpcMaxRequestBody(value reflect.Value) *conf.MaxRequestBody {
  function getConfigShare (line 37) | func getConfigShare(value reflect.Value) *conf.Share {

FILE: pkg/common/storage/cache/batch_handler.go
  type BatchDeleter (line 8) | type BatchDeleter interface

FILE: pkg/common/storage/cache/black.go
  type BlackCache (line 21) | type BlackCache interface

FILE: pkg/common/storage/cache/cachekey/black.go
  constant BlackIDsKey (line 18) | BlackIDsKey = "BLACK_IDS:"
  constant IsBlackKey (line 19) | IsBlackKey  = "IS_BLACK:"
  function GetBlackIDsKey (line 22) | func GetBlackIDsKey(ownerUserID string) string {
  function GetIsBlackIDsKey (line 27) | func GetIsBlackIDsKey(possibleBlackUserID, userID string) string {

FILE: pkg/common/storage/cache/cachekey/client_config.go
  constant ClientConfig (line 3) | ClientConfig = "CLIENT_CONFIG"
  function GetClientConfigKey (line 5) | func GetClientConfigKey(userID string) string {

FILE: pkg/common/storage/cache/cachekey/conversation.go
  constant ConversationKey (line 18) | ConversationKey                          = "CONVERSATION:"
  constant ConversationIDsKey (line 19) | ConversationIDsKey                       = "CONVERSATION_IDS:"
  constant NotNotifyConversationIDsKey (line 20) | NotNotifyConversationIDsKey              = "NOT_NOTIFY_CONVERSATION_IDS:"
  constant PinnedConversationIDsKey (line 21) | PinnedConversationIDsKey                 = "PINNED_CONVERSATION_IDS:"
  constant ConversationIDsHashKey (line 22) | ConversationIDsHashKey                   = "CONVERSATION_IDS_HASH:"
  constant ConversationHasReadSeqKey (line 23) | ConversationHasReadSeqKey                = "CONVERSATION_HAS_READ_SEQ:"
  constant RecvMsgOptKey (line 24) | RecvMsgOptKey                            = "RECV_MSG_OPT:"
  constant SuperGroupRecvMsgNotNotifyUserIDsKey (line 25) | SuperGroupRecvMsgNotNotifyUserIDsKey     = "SUPER_GROUP_RECV_MSG_NOT_NOT...
  constant SuperGroupRecvMsgNotNotifyUserIDsHashKey (line 26) | SuperGroupRecvMsgNotNotifyUserIDsHashKey = "SUPER_GROUP_RECV_MSG_NOT_NOT...
  constant ConversationNotReceiveMessageUserIDsKey (line 27) | ConversationNotReceiveMessageUserIDsKey  = "CONVERSATION_NOT_RECEIVE_MES...
  constant ConversationUserMaxKey (line 28) | ConversationUserMaxKey                   = "CONVERSATION_USER_MAX:"
  function GetConversationKey (line 31) | func GetConversationKey(ownerUserID, conversationID string) string {
  function GetConversationIDsKey (line 35) | func GetConversationIDsKey(ownerUserID string) string {
  function GetNotNotifyConversationIDsKey (line 39) | func GetNotNotifyConversationIDsKey(ownerUserID string) string {
  function GetPinnedConversationIDs (line 43) | func GetPinnedConversationIDs(ownerUserID string) string {
  function GetSuperGroupRecvNotNotifyUserIDsKey (line 47) | func GetSuperGroupRecvNotNotifyUserIDsKey(groupID string) string {
  function GetRecvMsgOptKey (line 51) | func GetRecvMsgOptKey(ownerUserID, conversationID string) string {
  function GetSuperGroupRecvNotNotifyUserIDsHashKey (line 55) | func GetSuperGroupRecvNotNotifyUserIDsHashKey(groupID string) string {
  function GetConversationHasReadSeqKey (line 59) | func GetConversationHasReadSeqKey(ownerUserID, conversationID string) st...
  function GetConversationNotReceiveMessageUserIDsKey (line 63) | func GetConversationNotReceiveMessageUserIDsKey(conversationID string) s...
  function GetUserConversationIDsHashKey (line 67) | func GetUserConversationIDsHashKey(ownerUserID string) string {
  function GetConversationUserMaxVersionKey (line 71) | func GetConversationUserMaxVersionKey(userID string) string {

FILE: pkg/common/storage/cache/cachekey/friend.go
  constant FriendIDsKey (line 18) | FriendIDsKey        = "FRIEND_IDS:"
  constant TwoWayFriendsIDsKey (line 19) | TwoWayFriendsIDsKey = "COMMON_FRIENDS_IDS:"
  constant FriendKey (line 20) | FriendKey           = "FRIEND_INFO:"
  constant IsFriendKey (line 21) | IsFriendKey         = "IS_FRIEND:"
  constant FriendMaxVersionKey (line 23) | FriendMaxVersionKey = "FRIEND_MAX_VERSION:"
  function GetFriendIDsKey (line 26) | func GetFriendIDsKey(ownerUserID string) string {
  function GetTwoWayFriendsIDsKey (line 30) | func GetTwoWayFriendsIDsKey(ownerUserID string) string {
  function GetFriendKey (line 34) | func GetFriendKey(ownerUserID, friendUserID string) string {
  function GetFriendMaxVersionKey (line 38) | func GetFriendMaxVersionKey(ownerUserID string) string {
  function GetIsFriendKey (line 42) | func GetIsFriendKey(possibleFriendUserID, userID string) string {

FILE: pkg/common/storage/cache/cachekey/group.go
  constant groupExpireTime (line 23) | groupExpireTime             = time.Second * 60 * 60 * 12
  constant GroupInfoKey (line 24) | GroupInfoKey                = "GROUP_INFO:"
  constant GroupMemberIDsKey (line 25) | GroupMemberIDsKey           = "GROUP_MEMBER_IDS:"
  constant GroupMembersHashKey (line 26) | GroupMembersHashKey         = "GROUP_MEMBERS_HASH2:"
  constant GroupMemberInfoKey (line 27) | GroupMemberInfoKey          = "GROUP_MEMBER_INFO:"
  constant JoinedGroupsKey (line 28) | JoinedGroupsKey             = "JOIN_GROUPS_KEY:"
  constant GroupMemberNumKey (line 29) | GroupMemberNumKey           = "GROUP_MEMBER_NUM_CACHE:"
  constant GroupRoleLevelMemberIDsKey (line 30) | GroupRoleLevelMemberIDsKey  = "GROUP_ROLE_LEVEL_MEMBER_IDS:"
  constant GroupAdminLevelMemberIDsKey (line 31) | GroupAdminLevelMemberIDsKey = "GROUP_ADMIN_LEVEL_MEMBER_IDS:"
  constant GroupMemberMaxVersionKey (line 32) | GroupMemberMaxVersionKey    = "GROUP_MEMBER_MAX_VERSION:"
  constant GroupJoinMaxVersionKey (line 33) | GroupJoinMaxVersionKey      = "GROUP_JOIN_MAX_VERSION:"
  function GetGroupInfoKey (line 36) | func GetGroupInfoKey(groupID string) string {
  function GetJoinedGroupsKey (line 40) | func GetJoinedGroupsKey(userID string) string {
  function GetGroupMembersHashKey (line 44) | func GetGroupMembersHashKey(groupID string) string {
  function GetGroupMemberIDsKey (line 48) | func GetGroupMemberIDsKey(groupID string) string {
  function GetGroupMemberInfoKey (line 52) | func GetGroupMemberInfoKey(groupID, userID string) string {
  function GetGroupMemberNumKey (line 56) | func GetGroupMemberNumKey(groupID string) string {
  function GetGroupRoleLevelMemberIDsKey (line 60) | func GetGroupRoleLevelMemberIDsKey(groupID string, roleLevel int32) stri...
  function GetGroupMemberMaxVersionKey (line 64) | func GetGroupMemberMaxVersionKey(groupID string) string {
  function GetJoinGroupMaxVersionKey (line 68) | func GetJoinGroupMaxVersionKey(userID string) string {

FILE: pkg/common/storage/cache/cachekey/msg.go
  constant sendMsgFailedFlag (line 22) | sendMsgFailedFlag = "SEND_MSG_FAILED_FLAG:"
  constant messageCache (line 23) | messageCache      = "MSG_CACHE:"
  function GetMsgCacheKey (line 26) | func GetMsgCacheKey(conversationID string, seq int64) string {
  function GetSendMsgKey (line 30) | func GetSendMsgKey(id string) string {

FILE: pkg/common/storage/cache/cachekey/online.go
  constant OnlineKey (line 9) | OnlineKey     = "ONLINE:"
  constant OnlineChannel (line 10) | OnlineChannel = "online_change"
  constant OnlineExpire (line 11) | OnlineExpire  = time.Hour / 2
  function GetOnlineKey (line 14) | func GetOnlineKey(userID string) string {
  function GetOnlineKeyUserID (line 18) | func GetOnlineKeyUserID(key string) string {

FILE: pkg/common/storage/cache/cachekey/s3.go
  constant object (line 20) | object         = "OBJECT:"
  constant s3 (line 21) | s3             = "S3:"
  constant minioImageInfo (line 22) | minioImageInfo = "MINIO:IMAGE:"
  constant minioThumbnail (line 23) | minioThumbnail = "MINIO:THUMBNAIL:"
  function GetObjectKey (line 26) | func GetObjectKey(engine string, name string) string {
  function GetS3Key (line 30) | func GetS3Key(engine string, name string) string {
  function GetObjectImageInfoKey (line 34) | func GetObjectImageInfoKey(key string) string {
  function GetMinioImageThumbnailKey (line 38) | func GetMinioImageThumbnailKey(key string, format string, width int, hei...

FILE: pkg/common/storage/cache/cachekey/seq.go
  constant MallocSeq (line 4) | MallocSeq        = "MALLOC_SEQ:"
  constant MallocMinSeqLock (line 5) | MallocMinSeqLock = "MALLOC_MIN_SEQ:"
  constant SeqUserMaxSeq (line 7) | SeqUserMaxSeq  = "SEQ_USER_MAX:"
  constant SeqUserMinSeq (line 8) | SeqUserMinSeq  = "SEQ_USER_MIN:"
  constant SeqUserReadSeq (line 9) | SeqUserReadSeq = "SEQ_USER_READ:"
  function GetMallocSeqKey (line 12) | func GetMallocSeqKey(conversationID string) string {
  function GetMallocMinSeqKey (line 16) | func GetMallocMinSeqKey(conversationID string) string {
  function GetSeqUserMaxSeqKey (line 20) | func GetSeqUserMaxSeqKey(conversationID string, userID string) string {
  function GetSeqUserMinSeqKey (line 24) | func GetSeqUserMinSeqKey(conversationID string, userID string) string {
  function GetSeqUserReadSeqKey (line 28) | func GetSeqUserReadSeqKey(conversationID string, userID string) string {

FILE: pkg/common/storage/cache/cachekey/third.go
  constant getuiToken (line 22) | getuiToken              = "GETUI_TOKEN"
  constant getuiTaskID (line 23) | getuiTaskID             = "GETUI_TASK_ID"
  constant fmcToken (line 24) | fmcToken                = "FCM_TOKEN:"
  constant userBadgeUnreadCountSum (line 25) | userBadgeUnreadCountSum = "USER_BADGE_UNREAD_COUNT_SUM:"
  function GetFcmAccountTokenKey (line 28) | func GetFcmAccountTokenKey(account string, platformID int) string {
  function GetUserBadgeUnreadCountSumKey (line 32) | func GetUserBadgeUnreadCountSumKey(userID string) string {
  function GetGetuiTokenKey (line 36) | func GetGetuiTokenKey() string {
  function GetGetuiTaskIDKey (line 39) | func GetGetuiTaskIDKey() string {

FILE: pkg/common/storage/cache/cachekey/token.go
  constant UidPidToken (line 10) | UidPidToken = "UID_PID_TOKEN_STATUS:"
  function GetTokenKey (line 13) | func GetTokenKey(userID string, platformID int) string {
  function GetTemporaryTokenKey (line 17) | func GetTemporaryTokenKey(userID string, platformID int, token string) s...
  function GetAllPlatformTokenKey (line 21) | func GetAllPlatformTokenKey(userID string) []string {
  function GetPlatformIDByTokenKey (line 29) | func GetPlatformIDByTokenKey(key string) int {

FILE: pkg/common/storage/cache/cachekey/user.go
  constant UserInfoKey (line 18) | UserInfoKey             = "USER_INFO:"
  constant UserGlobalRecvMsgOptKey (line 19) | UserGlobalRecvMsgOptKey = "USER_GLOBAL_RECV_MSG_OPT_KEY:"
  function GetUserInfoKey (line 22) | func GetUserInfoKey(userID string) string {
  function GetUserGlobalRecvMsgOptKey (line 26) | func GetUserGlobalRecvMsgOptKey(userID string) string {

FILE: pkg/common/storage/cache/client_config.go
  type ClientConfigCache (line 5) | type ClientConfigCache interface

FILE: pkg/common/storage/cache/conversation.go
  type ConversationCache (line 24) | type ConversationCache interface

FILE: pkg/common/storage/cache/friend.go
  type FriendCache (line 23) | type FriendCache interface

FILE: pkg/common/storage/cache/group.go
  type GroupHash (line 24) | type GroupHash interface
  type GroupCache (line 28) | type GroupCache interface

FILE: pkg/common/storage/cache/mcache/minio.go
  function NewMinioCache (line 12) | func NewMinioCache(cache database.Cache) minio.Cache {
  type minioCache (line 19) | type minioCache struct
    method getObjectImageInfoKey (line 24) | func (g *minioCache) getObjectImageInfoKey(key string) string {
    method getMinioImageThumbnailKey (line 28) | func (g *minioCache) getMinioImageThumbnailKey(key string, format stri...
    method DelObjectImageInfoKey (line 32) | func (g *minioCache) DelObjectImageInfoKey(ctx context.Context, keys ....
    method DelImageThumbnailKey (line 40) | func (g *minioCache) DelImageThumbnailKey(ctx context.Context, key str...
    method GetImageObjectKeyInfo (line 44) | func (g *minioCache) GetImageObjectKeyInfo(ctx context.Context, key st...
    method GetThumbnailKey (line 48) | func (g *minioCache) GetThumbnailKey(ctx context.Context, key string, ...

FILE: pkg/common/storage/cache/mcache/msg_cache.go
  function NewMsgCache (line 25) | func NewMsgCache(cache database.Cache, msgDocDatabase database.Msg) cach...
  type msgCache (line 36) | type msgCache struct
    method getSendMsgKey (line 42) | func (x *msgCache) getSendMsgKey(id string) string {
    method SetSendMsgStatus (line 46) | func (x *msgCache) SetSendMsgStatus(ctx context.Context, id string, st...
    method GetSendMsgStatus (line 50) | func (x *msgCache) GetSendMsgStatus(ctx context.Context, id string) (i...
    method getMsgCacheKey (line 67) | func (x *msgCache) getMsgCacheKey(conversationID string, seq int64) st...
    method GetMessageBySeqs (line 72) | func (x *msgCache) GetMessageBySeqs(ctx context.Context, conversationI...
    method DelMessageBySeqs (line 113) | func (x msgCache) DelMessageBySeqs(ctx context.Context, conversationID...
    method SetMessageBySeqs (line 123) | func (x *msgCache) SetMessageBySeqs(ctx context.Context, conversationI...

FILE: pkg/common/storage/cache/mcache/online.go
  function NewOnlineCache (line 15) | func NewOnlineCache() cache.OnlineCache {
  type onlineCache (line 24) | type onlineCache struct
    method GetOnline (line 29) | func (x *onlineCache) GetOnline(ctx context.Context, userID string) ([...
    method SetUserOnline (line 43) | func (x *onlineCache) SetUserOnline(ctx context.Context, userID string...
    method GetAllOnlineUsers (line 67) | func (x *onlineCache) GetAllOnlineUsers(ctx context.Context, cursor ui...

FILE: pkg/common/storage/cache/mcache/seq_conversation.go
  function NewSeqConversationCache (line 10) | func NewSeqConversationCache(sc database.SeqConversation) cache.SeqConve...
  type seqConversationCache (line 16) | type seqConversationCache struct
    method Malloc (line 20) | func (x *seqConversationCache) Malloc(ctx context.Context, conversatio...
    method SetMinSeq (line 24) | func (x *seqConversationCache) SetMinSeq(ctx context.Context, conversa...
    method GetMinSeq (line 28) | func (x *seqConversationCache) GetMinSeq(ctx context.Context, conversa...
    method GetMaxSeqs (line 32) | func (x *seqConversationCache) GetMaxSeqs(ctx context.Context, convers...
    method GetMaxSeqsWithTime (line 44) | func (x *seqConversationCache) GetMaxSeqsWithTime(ctx context.Context,...
    method GetMaxSeq (line 56) | func (x *seqConversationCache) GetMaxSeq(ctx context.Context, conversa...
    method GetMaxSeqWithTime (line 60) | func (x *seqConversationCache) GetMaxSeqWithTime(ctx context.Context, ...
    method SetMinSeqs (line 68) | func (x *seqConversationCache) SetMinSeqs(ctx context.Context, seqs ma...
    method GetCacheMaxSeqWithTime (line 77) | func (x *seqConversationCache) GetCacheMaxSeqWithTime(ctx context.Cont...

FILE: pkg/common/storage/cache/mcache/third.go
  function NewThirdCache (line 15) | func NewThirdCache(cache database.Cache) cache.ThirdCache {
  type thirdCache (line 21) | type thirdCache struct
    method getGetuiTokenKey (line 25) | func (c *thirdCache) getGetuiTokenKey() string {
    method getGetuiTaskIDKey (line 29) | func (c *thirdCache) getGetuiTaskIDKey() string {
    method getUserBadgeUnreadCountSumKey (line 33) | func (c *thirdCache) getUserBadgeUnreadCountSumKey(userID string) stri...
    method getFcmAccountTokenKey (line 37) | func (c *thirdCache) getFcmAccountTokenKey(account string, platformID ...
    method get (line 41) | func (c *thirdCache) get(ctx context.Context, key string) (string, err...
    method SetFcmToken (line 52) | func (c *thirdCache) SetFcmToken(ctx context.Context, account string, ...
    method GetFcmToken (line 56) | func (c *thirdCache) GetFcmToken(ctx context.Context, account string, ...
    method DelFcmToken (line 60) | func (c *thirdCache) DelFcmToken(ctx context.Context, account string, ...
    method IncrUserBadgeUnreadCountSum (line 64) | func (c *thirdCache) IncrUserBadgeUnreadCountSum(ctx context.Context, ...
    method SetUserBadgeUnreadCountSum (line 68) | func (c *thirdCache) SetUserBadgeUnreadCountSum(ctx context.Context, u...
    method GetUserBadgeUnreadCountSum (line 72) | func (c *thirdCache) GetUserBadgeUnreadCountSum(ctx context.Context, u...
    method SetGetuiToken (line 84) | func (c *thirdCache) SetGetuiToken(ctx context.Context, token string, ...
    method GetGetuiToken (line 88) | func (c *thirdCache) GetGetuiToken(ctx context.Context) (string, error) {
    method SetGetuiTaskID (line 92) | func (c *thirdCache) SetGetuiTaskID(ctx context.Context, taskID string...
    method GetGetuiTaskID (line 96) | func (c *thirdCache) GetGetuiTaskID(ctx context.Context) (string, erro...

FILE: pkg/common/storage/cache/mcache/token.go
  function NewTokenCacheModel (line 17) | func NewTokenCacheModel(cache database.Cache, accessExpire int64) cache....
  type tokenCache (line 23) | type tokenCache struct
    method getTokenKey (line 28) | func (x *tokenCache) getTokenKey(userID string, platformID int, token ...
    method SetTokenFlag (line 32) | func (x *tokenCache) SetTokenFlag(ctx context.Context, userID string, ...
    method SetTokenFlagEx (line 37) | func (x *tokenCache) SetTokenFlagEx(ctx context.Context, userID string...
    method GetTokensWithoutError (line 41) | func (x *tokenCache) GetTokensWithoutError(ctx context.Context, userID...
    method HasTemporaryToken (line 59) | func (x *tokenCache) HasTemporaryToken(ctx context.Context, userID str...
    method GetAllTokensWithoutError (line 67) | func (x *tokenCache) GetAllTokensWithoutError(ctx context.Context, use...
    method SetTokenMapByUidPid (line 105) | func (x *tokenCache) SetTokenMapByUidPid(ctx context.Context, userID s...
    method BatchSetTokenMapByUidPid (line 115) | func (x *tokenCache) BatchSetTokenMapByUidPid(ctx context.Context, tok...
    method DeleteTokenByUidPid (line 127) | func (x *tokenCache) DeleteTokenByUidPid(ctx context.Context, userID s...
    method getExpireTime (line 135) | func (x *tokenCache) getExpireTime(t int64) time.Duration {
    method DeleteTokenByTokenMap (line 139) | func (x *tokenCache) DeleteTokenByTokenMap(ctx context.Context, userID...
    method DeleteAndSetTemporary (line 149) | func (x *tokenCache) DeleteAndSetTemporary(ctx context.Context, userID...

FILE: pkg/common/storage/cache/mcache/tools.go
  function getCache (line 12) | func getCache[V any](ctx context.Context, cache database.Cache, key stri...

FILE: pkg/common/storage/cache/msg.go
  type MsgCache (line 22) | type MsgCache interface

FILE: pkg/common/storage/cache/online.go
  type OnlineCache (line 5) | type OnlineCache interface

FILE: pkg/common/storage/cache/redis/batch.go
  function GetRocksCacheOptions (line 16) | func GetRocksCacheOptions() *rockscache.Options {
  function newRocksCacheClient (line 26) | func newRocksCacheClient(rdb redis.UniversalClient) *rocksCacheClient {
  type rocksCacheClient (line 37) | type rocksCacheClient struct
    method GetClient (line 42) | func (x *rocksCacheClient) GetClient() *rockscache.Client {
    method Disable (line 46) | func (x *rocksCacheClient) Disable() bool {
    method GetRedis (line 50) | func (x *rocksCacheClient) GetRedis() redis.UniversalClient {
    method GetBatchDeleter (line 54) | func (x *rocksCacheClient) GetBatchDeleter(topics ...string) cache.Bat...
  function batchGetCache2 (line 58) | func batchGetCache2[K comparable, V any](ctx context.Context, rcClient *...
  type BatchCacheCallback (line 133) | type BatchCacheCallback interface

FILE: pkg/common/storage/cache/redis/batch_handler.go
  constant rocksCacheTimeout (line 19) | rocksCacheTimeout = 11 * time.Second
  type BatchDeleterRedis (line 23) | type BatchDeleterRedis struct
    method ExecDelWithKeys (line 40) | func (c *BatchDeleterRedis) ExecDelWithKeys(ctx context.Context, keys ...
    method ChainExecDel (line 46) | func (c *BatchDeleterRedis) ChainExecDel(ctx context.Context) error {
    method execDel (line 52) | func (c *BatchDeleterRedis) execDel(ctx context.Context, keys []string...
    method Clone (line 83) | func (c *BatchDeleterRedis) Clone() cache.BatchDeleter {
    method AddKeys (line 93) | func (c *BatchDeleterRedis) AddKeys(keys ...string) {
  function NewBatchDeleterRedis (line 31) | func NewBatchDeleterRedis(rcClient *rocksCacheClient, redisPubTopics []s...
  type disableBatchDeleter (line 97) | type disableBatchDeleter struct
    method ChainExecDel (line 99) | func (x disableBatchDeleter) ChainExecDel(ctx context.Context) error {
    method ExecDelWithKeys (line 103) | func (x disableBatchDeleter) ExecDelWithKeys(ctx context.Context, keys...
    method Clone (line 107) | func (x disableBatchDeleter) Clone() cache.BatchDeleter {
    method AddKeys (line 111) | func (x disableBatchDeleter) AddKeys(keys ...string) {}
  function getCache (line 113) | func getCache[T any](ctx context.Context, rcClient *rocksCacheClient, ke...

FILE: pkg/common/storage/cache/redis/batch_test.go
  function TestName (line 12) | func TestName(t *testing.T) {

FILE: pkg/common/storage/cache/redis/black.go
  constant blackExpireTime (line 15) | blackExpireTime = time.Second * 60 * 60 * 12
  type BlackCacheRedis (line 18) | type BlackCacheRedis struct
    method CloneBlackCache (line 35) | func (b *BlackCacheRedis) CloneBlackCache() cache.BlackCache {
    method getBlackIDsKey (line 44) | func (b *BlackCacheRedis) getBlackIDsKey(ownerUserID string) string {
    method GetBlackIDs (line 48) | func (b *BlackCacheRedis) GetBlackIDs(ctx context.Context, userID stri...
    method DelBlackIDs (line 60) | func (b *BlackCacheRedis) DelBlackIDs(_ context.Context, userID string...
  function NewBlackCacheRedis (line 25) | func NewBlackCacheRedis(rdb redis.UniversalClient, localCache *config.Lo...

FILE: pkg/common/storage/cache/redis/client_config.go
  function NewClientConfigCache (line 13) | func NewClientConfigCache(rdb redis.UniversalClient, mgo database.Client...
  type ClientConfigCache (line 22) | type ClientConfigCache struct
    method getExpireTime (line 28) | func (x *ClientConfigCache) getExpireTime(userID string) time.Duration {
    method getClientConfigKey (line 36) | func (x *ClientConfigCache) getClientConfigKey(userID string) string {
    method GetConfig (line 40) | func (x *ClientConfigCache) GetConfig(ctx context.Context, userID stri...
    method DeleteUserCache (line 46) | func (x *ClientConfigCache) DeleteUserCache(ctx context.Context, userI...
    method GetUserConfig (line 54) | func (x *ClientConfigCache) GetUserConfig(ctx context.Context, userID ...

FILE: pkg/common/storage/cache/redis/conversation.go
  constant conversationExpireTime (line 20) | conversationExpireTime = time.Second * 60 * 60 * 12
  function NewConversationRedis (line 23) | func NewConversationRedis(rdb redis.UniversalClient, localCache *config....
  type ConversationRedisCache (line 33) | type ConversationRedisCache struct
    method CloneConversationCache (line 40) | func (c *ConversationRedisCache) CloneConversationCache() cache.Conver...
    method getConversationKey (line 49) | func (c *ConversationRedisCache) getConversationKey(ownerUserID, conve...
    method getConversationIDsKey (line 53) | func (c *ConversationRedisCache) getConversationIDsKey(ownerUserID str...
    method getNotNotifyConversationIDsKey (line 57) | func (c *ConversationRedisCache) getNotNotifyConversationIDsKey(ownerU...
    method getPinnedConversationIDsKey (line 61) | func (c *ConversationRedisCache) getPinnedConversationIDsKey(ownerUser...
    method getSuperGroupRecvNotNotifyUserIDsKey (line 65) | func (c *ConversationRedisCache) getSuperGroupRecvNotNotifyUserIDsKey(...
    method getRecvMsgOptKey (line 69) | func (c *ConversationRedisCache) getRecvMsgOptKey(ownerUserID, convers...
    method getSuperGroupRecvNotNotifyUserIDsHashKey (line 73) | func (c *ConversationRedisCache) getSuperGroupRecvNotNotifyUserIDsHash...
    method getConversationHasReadSeqKey (line 77) | func (c *ConversationRedisCache) getConversationHasReadSeqKey(ownerUse...
    method getConversationNotReceiveMessageUserIDsKey (line 81) | func (c *ConversationRedisCache) getConversationNotReceiveMessageUserI...
    method getUserConversationIDsHashKey (line 85) | func (c *ConversationRedisCache) getUserConversationIDsHashKey(ownerUs...
    method getConversationUserMaxVersionKey (line 89) | func (c *ConversationRedisCache) getConversationUserMaxVersionKey(owne...
    method GetUserConversationIDs (line 93) | func (c *ConversationRedisCache) GetUserConversationIDs(ctx context.Co...
    method GetUserNotNotifyConversationIDs (line 99) | func (c *ConversationRedisCache) GetUserNotNotifyConversationIDs(ctx c...
    method GetPinnedConversationIDs (line 105) | func (c *ConversationRedisCache) GetPinnedConversationIDs(ctx context....
    method DelConversationIDs (line 111) | func (c *ConversationRedisCache) DelConversationIDs(userIDs ...string)...
    method GetUserConversationIDsHash (line 122) | func (c *ConversationRedisCache) GetUserConversationIDsHash(ctx contex...
    method DelUserConversationIDsHash (line 141) | func (c *ConversationRedisCache) DelUserConversationIDsHash(ownerUserI...
    method GetConversation (line 152) | func (c *ConversationRedisCache) GetConversation(ctx context.Context, ...
    method DelConversations (line 158) | func (c *ConversationRedisCache) DelConversations(ownerUserID string, ...
    method GetConversations (line 169) | func (c *ConversationRedisCache) GetConversations(ctx context.Context,...
    method GetUserAllConversations (line 179) | func (c *ConversationRedisCache) GetUserAllConversations(ctx context.C...
    method GetUserRecvMsgOpt (line 187) | func (c *ConversationRedisCache) GetUserRecvMsgOpt(ctx context.Context...
    method DelUsersConversation (line 193) | func (c *ConversationRedisCache) DelUsersConversation(conversationID s...
    method DelUserRecvMsgOpt (line 204) | func (c *ConversationRedisCache) DelUserRecvMsgOpt(ownerUserID, conver...
    method DelSuperGroupRecvMsgNotNotifyUserIDs (line 211) | func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDs(...
    method DelSuperGroupRecvMsgNotNotifyUserIDsHash (line 218) | func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDsH...
    method DelUserAllHasReadSeqs (line 225) | func (c *ConversationRedisCache) DelUserAllHasReadSeqs(ownerUserID str...
    method GetConversationNotReceiveMessageUserIDs (line 234) | func (c *ConversationRedisCache) GetConversationNotReceiveMessageUserI...
    method DelConversationNotReceiveMessageUserIDs (line 240) | func (c *ConversationRedisCache) DelConversationNotReceiveMessageUserI...
    method DelConversationNotNotifyMessageUserIDs (line 248) | func (c *ConversationRedisCache) DelConversationNotNotifyMessageUserID...
    method DelUserPinnedConversations (line 256) | func (c *ConversationRedisCache) DelUserPinnedConversations(userIDs .....
    method DelConversationVersionUserIDs (line 264) | func (c *ConversationRedisCache) DelConversationVersionUserIDs(userIDs...
    method FindMaxConversationUserVersion (line 272) | func (c *ConversationRedisCache) FindMaxConversationUserVersion(ctx co...

FILE: pkg/common/storage/cache/redis/friend.go
  constant friendExpireTime (line 17) | friendExpireTime = time.Second * 60 * 60 * 12
  type FriendCacheRedis (line 21) | type FriendCacheRedis struct
    method CloneFriendCache (line 40) | func (f *FriendCacheRedis) CloneFriendCache() cache.FriendCache {
    method getFriendIDsKey (line 50) | func (f *FriendCacheRedis) getFriendIDsKey(ownerUserID string) string {
    method getFriendMaxVersionKey (line 54) | func (f *FriendCacheRedis) getFriendMaxVersionKey(ownerUserID string) ...
    method getTwoWayFriendsIDsKey (line 59) | func (f *FriendCacheRedis) getTwoWayFriendsIDsKey(ownerUserID string) ...
    method getFriendKey (line 64) | func (f *FriendCacheRedis) getFriendKey(ownerUserID, friendUserID stri...
    method GetFriendIDs (line 69) | func (f *FriendCacheRedis) GetFriendIDs(ctx context.Context, ownerUser...
    method DelFriendIDs (line 76) | func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) cache....
    method GetTwoWayFriendIDs (line 88) | func (f *FriendCacheRedis) GetTwoWayFriendIDs(ctx context.Context, own...
    method DelTwoWayFriendIDs (line 107) | func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, own...
    method GetFriend (line 115) | func (f *FriendCacheRedis) GetFriend(ctx context.Context, ownerUserID,...
    method DelFriend (line 123) | func (f *FriendCacheRedis) DelFriend(ownerUserID, friendUserID string)...
    method DelFriends (line 131) | func (f *FriendCacheRedis) DelFriends(ownerUserID string, friendUserID...
    method DelOwner (line 142) | func (f *FriendCacheRedis) DelOwner(friendUserID string, ownerUserIDs ...
    method DelMaxFriendVersion (line 153) | func (f *FriendCacheRedis) DelMaxFriendVersion(ownerUserIDs ...string)...
    method FindMaxFriendVersion (line 163) | func (f *FriendCacheRedis) FindMaxFriendVersion(ctx context.Context, o...
  function NewFriendCacheRedis (line 30) | func NewFriendCacheRedis(rdb redis.UniversalClient, localCache *config.L...

FILE: pkg/common/storage/cache/redis/group.go
  constant groupExpireTime (line 21) | groupExpireTime = time.Second * 60 * 60 * 12
  type GroupCacheRedis (line 24) | type GroupCacheRedis struct
    method CloneGroupCache (line 47) | func (g *GroupCacheRedis) CloneGroupCache() cache.GroupCache {
    method getGroupInfoKey (line 58) | func (g *GroupCacheRedis) getGroupInfoKey(groupID string) string {
    method getJoinedGroupsKey (line 62) | func (g *GroupCacheRedis) getJoinedGroupsKey(userID string) string {
    method getGroupMembersHashKey (line 66) | func (g *GroupCacheRedis) getGroupMembersHashKey(groupID string) string {
    method getGroupMemberIDsKey (line 70) | func (g *GroupCacheRedis) getGroupMemberIDsKey(groupID string) string {
    method getGroupMemberInfoKey (line 74) | func (g *GroupCacheRedis) getGroupMemberInfoKey(groupID, userID string...
    method getGroupMemberNumKey (line 78) | func (g *GroupCacheRedis) getGroupMemberNumKey(groupID string) string {
    method getGroupRoleLevelMemberIDsKey (line 82) | func (g *GroupCacheRedis) getGroupRoleLevelMemberIDsKey(groupID string...
    method getGroupMemberMaxVersionKey (line 86) | func (g *GroupCacheRedis) getGroupMemberMaxVersionKey(groupID string) ...
    method getJoinGroupMaxVersionKey (line 90) | func (g *GroupCacheRedis) getJoinGroupMaxVersionKey(userID string) str...
    method getGroupID (line 94) | func (g *GroupCacheRedis) getGroupID(group *model.Group) string {
    method GetGroupsInfo (line 98) | func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs ...
    method GetGroupInfo (line 102) | func (g *GroupCacheRedis) GetGroupInfo(ctx context.Context, groupID st...
    method DelGroupsInfo (line 108) | func (g *GroupCacheRedis) DelGroupsInfo(groupIDs ...string) cache.Grou...
    method DelGroupsOwner (line 119) | func (g *GroupCacheRedis) DelGroupsOwner(groupIDs ...string) cache.Gro...
    method DelGroupRoleLevel (line 130) | func (g *GroupCacheRedis) DelGroupRoleLevel(groupID string, roleLevels...
    method DelGroupAllRoleLevel (line 140) | func (g *GroupCacheRedis) DelGroupAllRoleLevel(groupID string) cache.G...
    method GetGroupMembersHash (line 144) | func (g *GroupCacheRedis) GetGroupMembersHash(ctx context.Context, gro...
    method GetGroupMemberHashMap (line 153) | func (g *GroupCacheRedis) GetGroupMemberHashMap(ctx context.Context, g...
    method DelGroupMembersHash (line 174) | func (g *GroupCacheRedis) DelGroupMembersHash(groupID string) cache.Gr...
    method GetGroupMemberIDs (line 181) | func (g *GroupCacheRedis) GetGroupMemberIDs(ctx context.Context, group...
    method DelGroupMemberIDs (line 187) | func (g *GroupCacheRedis) DelGroupMemberIDs(groupID string) cache.Grou...
    method findUserJoinedGroupID (line 194) | func (g *GroupCacheRedis) findUserJoinedGroupID(ctx context.Context, u...
    method GetJoinedGroupIDs (line 202) | func (g *GroupCacheRedis) GetJoinedGroupIDs(ctx context.Context, userI...
    method DelJoinedGroupID (line 208) | func (g *GroupCacheRedis) DelJoinedGroupID(userIDs ...string) cache.Gr...
    method GetGroupMemberInfo (line 219) | func (g *GroupCacheRedis) GetGroupMemberInfo(ctx context.Context, grou...
    method GetGroupMembersInfo (line 225) | func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, gro...
    method GetAllGroupMembersInfo (line 235) | func (g *GroupCacheRedis) GetAllGroupMembersInfo(ctx context.Context, ...
    method DelGroupMembersInfo (line 244) | func (g *GroupCacheRedis) DelGroupMembersInfo(groupID string, userIDs ...
    method GetGroupMemberNum (line 255) | func (g *GroupCacheRedis) GetGroupMemberNum(ctx context.Context, group...
    method DelGroupsMemberNum (line 261) | func (g *GroupCacheRedis) DelGroupsMemberNum(groupID ...string) cache....
    method GetGroupOwner (line 272) | func (g *GroupCacheRedis) GetGroupOwner(ctx context.Context, groupID s...
    method GetGroupsOwner (line 283) | func (g *GroupCacheRedis) GetGroupsOwner(ctx context.Context, groupIDs...
    method GetGroupRoleLevelMemberIDs (line 297) | func (g *GroupCacheRedis) GetGroupRoleLevelMemberIDs(ctx context.Conte...
    method GetGroupRoleLevelMemberInfo (line 303) | func (g *GroupCacheRedis) GetGroupRoleLevelMemberInfo(ctx context.Cont...
    method GetGroupRolesLevelMemberInfo (line 311) | func (g *GroupCacheRedis) GetGroupRolesLevelMemberInfo(ctx context.Con...
    method FindGroupMemberUser (line 323) | func (g *GroupCacheRedis) FindGroupMemberUser(ctx context.Context, gro...
    method DelMaxGroupMemberVersion (line 340) | func (g *GroupCacheRedis) DelMaxGroupMemberVersion(groupIDs ...string)...
    method DelMaxJoinGroupVersion (line 350) | func (g *GroupCacheRedis) DelMaxJoinGroupVersion(userIDs ...string) ca...
    method FindMaxGroupMemberVersion (line 360) | func (g *GroupCacheRedis) FindMaxGroupMemberVersion(ctx context.Contex...
    method BatchFindMaxGroupMemberVersion (line 366) | func (g *GroupCacheRedis) BatchFindMaxGroupMemberVersion(ctx context.C...
    method FindMaxJoinGroupVersion (line 381) | func (g *GroupCacheRedis) FindMaxJoinGroupVersion(ctx context.Context,...
  function NewGroupCacheRedis (line 34) | func NewGroupCacheRedis(rdb redis.UniversalClient, localCache *config.Lo...

FILE: pkg/common/storage/cache/redis/lua_script.go
  function callLua (line 50) | func callLua(ctx context.Context, rdb redis.Scripter, script *redis.Scri...
  function LuaSetBatchWithCommonExpire (line 67) | func LuaSetBatchWithCommonExpire(ctx context.Context, rdb redis.Scripter...
  function LuaSetBatchWithIndividualExpire (line 88) | func LuaSetBatchWithIndividualExpire(ctx context.Context, rdb redis.Scri...
  function LuaDeleteBatch (line 111) | func LuaDeleteBatch(ctx context.Context, rdb redis.Scripter, keys []stri...
  function LuaGetBatch (line 116) | func LuaGetBatch(ctx context.Context, rdb redis.Scripter, keys []string)...

FILE: pkg/common/storage/cache/redis/lua_script_test.go
  function TestLuaSetBatchWithCommonExpire (line 11) | func TestLuaSetBatchWithCommonExpire(t *testing.T) {
  function TestLuaSetBatchWithIndividualExpire (line 26) | func TestLuaSetBatchWithIndividualExpire(t *testing.T) {
  function TestLuaDeleteBatch (line 49) | func TestLuaDeleteBatch(t *testing.T) {
  function TestLuaGetBatch (line 62) | func TestLuaGetBatch(t *testing.T) {

FILE: pkg/common/storage/cache/redis/minio.go
  function NewMinioCache (line 13) | func NewMinioCache(rdb redis.UniversalClient) minio.Cache {
  type minioCacheRedis (line 22) | type minioCacheRedis struct
    method getObjectImageInfoKey (line 28) | func (g *minioCacheRedis) getObjectImageInfoKey(key string) string {
    method getMinioImageThumbnailKey (line 32) | func (g *minioCacheRedis) getMinioImageThumbnailKey(key string, format...
    method DelObjectImageInfoKey (line 36) | func (g *minioCacheRedis) DelObjectImageInfoKey(ctx context.Context, k...
    method DelImageThumbnailKey (line 44) | func (g *minioCacheRedis) DelImageThumbnailKey(ctx context.Context, ke...
    method GetImageObjectKeyInfo (line 49) | func (g *minioCacheRedis) GetImageObjectKeyInfo(ctx context.Context, k...
    method GetThumbnailKey (line 57) | func (g *minioCacheRedis) GetThumbnailKey(ctx context.Context, key str...

FILE: pkg/common/storage/cache/redis/msg.go
  constant msgCacheTimeout (line 18) | msgCacheTimeout = time.Hour * 24
  function NewMsgCache (line 20) | func NewMsgCache(client redis.UniversalClient, db database.Msg) cache.Ms...
  type msgCache (line 27) | type msgCache struct
    method getSendMsgKey (line 32) | func (c *msgCache) getSendMsgKey(id string) string {
    method SetSendMsgStatus (line 36) | func (c *msgCache) SetSendMsgStatus(ctx context.Context, id string, st...
    method GetSendMsgStatus (line 40) | func (c *msgCache) GetSendMsgStatus(ctx context.Context, id string) (i...
    method GetMessageBySeqs (line 45) | func (c *msgCache) GetMess
Condensed preview — 667 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,048K chars).
[
  {
    "path": ".dockerignore",
    "chars": 390,
    "preview": "# Ignore files and directories starting with a dot\n\n# Ignore specific files\n.dockerignore\n.git\n\n# Ignore build artifacts"
  },
  {
    "path": ".gitattributes",
    "chars": 17,
    "preview": "*.sh text eol=lf\n"
  },
  {
    "path": ".github/.codecov.yml",
    "chars": 1065,
    "preview": "coverage:\n  status:\n    project:\n      default: false # disable the default status that measures entire project\n      pk"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "chars": 2364,
    "preview": "name: Bug Report\ntitle: \"[BUG] \"\nlabels: [\"bug\"]\ndescription: \"Create a detailed report to help us identify and resolve "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 468,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  # - name: \"Bug Report\"\n  #   description: \"Report a bug in the project\"\n  #"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/deployment.yml",
    "chars": 2418,
    "preview": "name: Deployment issue\ntitle: \"[Deployment] \"\nlabels: [\"deployment\"]\ndescription: \"Create a detailed report to help us i"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/documentation.md",
    "chars": 895,
    "preview": "---\nname: Documentation Update\nabout: Propose updates to documentation, including README files and other docs.\ntitle: \"["
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "chars": 1664,
    "preview": "name: Feature Request\ntitle: \"[FEATURE REQUEST] \"\nlabels: [\"feature request\",\"enhancement\"]\ndescription: \"Propose a new "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/other.yml",
    "chars": 967,
    "preview": "name: 🐧 Other\ndescription: Use this for any other issues. Please do NOT create blank issues\ntitle: \"[Other]: <give this "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/rfc.md",
    "chars": 958,
    "preview": "---\nname: RFC - Feature Proposal\nabout: Submit a proposal for a significant feature to invite community discussion.\ntitl"
  },
  {
    "path": ".github/sync-release.yml",
    "chars": 387,
    "preview": "openimsdk/openim-docker:\n  - source: ./config\n    dest: ./openim-server/release/config\n    replace: true\n  - source: ./d"
  },
  {
    "path": ".github/workflows/auto-assign-issue.yml",
    "chars": 1382,
    "preview": "name: Assign issue to comment author\non:\n  issue_comment:\n    types: [created]\njobs:\n  assign-issue:\n    if: |\n      con"
  },
  {
    "path": ".github/workflows/auto-invite-comment.yml",
    "chars": 3685,
    "preview": "name: Invite users to join OpenIM Community.\non:\n  issue_comment:\n    types:\n      - created\njobs:\n  issue_comment:\n    "
  },
  {
    "path": ".github/workflows/changelog.yml",
    "chars": 3075,
    "preview": "name: Release Changelog\n\non:\n  release:\n    types: [released]\n\npermissions:\n  contents: write\n  pull-requests: write\n\njo"
  },
  {
    "path": ".github/workflows/cla-assistant.yml",
    "chars": 2259,
    "preview": "name: CLA Assistant\non:\n  issue_comment:\n    types: [created]\n  pull_request_target:\n    types: [opened,closed,synchroni"
  },
  {
    "path": ".github/workflows/cleanup-after-milestone-prs-merged.yml",
    "chars": 2315,
    "preview": "name: Cleanup After Milestone PRs Merged\n\non:\n  pull_request:\n    types:\n      - closed\n\njobs:\n  handle_pr:\n    runs-on:"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 2340,
    "preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
  },
  {
    "path": ".github/workflows/comment-check.yml",
    "chars": 1514,
    "preview": "name: Non-English Comments Check\n\non:\n  pull_request:\n    branches:\n      - main\n  workflow_dispatch:\n\njobs:\n  non-engli"
  },
  {
    "path": ".github/workflows/docker-build-and-release-services-images.yml",
    "chars": 3126,
    "preview": "name: Build and release services Docker Images\n\non:\n  push:\n    branches:\n      - release-*\n  release:\n    types: [publi"
  },
  {
    "path": ".github/workflows/go-build-test.yml",
    "chars": 8374,
    "preview": "name: Go Build Test\n\non:\n  push:\n  pull_request:\n    paths-ignore:\n      - \"**/*.md\"\n\n  workflow_dispatch:\n\njobs:\n  go-b"
  },
  {
    "path": ".github/workflows/help-comment-issue.yml",
    "chars": 1523,
    "preview": "# Copyright © 2023 OpenIM. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# yo"
  },
  {
    "path": ".github/workflows/issue-translator.yml",
    "chars": 760,
    "preview": "name: 'issue-translator'\non: \n  issue_comment: \n    types: [created]\n  issues: \n    types: [opened]\n\njobs:\n  build:\n    "
  },
  {
    "path": ".github/workflows/merge-from-milestone.yml",
    "chars": 7602,
    "preview": "name: Create Individual PRs from Milestone\n\npermissions:\n  contents: write\n  pull-requests: write\n  issues: write\n\non:\n "
  },
  {
    "path": ".github/workflows/publish-docker-image.yml",
    "chars": 6913,
    "preview": "name: Publish Docker image to registries\n\non:\n  push:\n    branches:\n      - release-*\n  release:\n    types: [published]\n"
  },
  {
    "path": ".github/workflows/remove-unused-labels.yml",
    "chars": 2341,
    "preview": "name: Remove Unused Labels\non:\n  workflow_dispatch:\n\njobs:\n  cleanup:\n    runs-on: ubuntu-latest\n    permissions:\n      "
  },
  {
    "path": ".github/workflows/reopen-issue.yml",
    "chars": 2687,
    "preview": "name: Reopen and Update Stale Issues\n\non:\n  workflow_dispatch:\n\njobs:\n  reopen_stale_issues:\n    runs-on: ubuntu-latest\n"
  },
  {
    "path": ".github/workflows/update-version-file-on-release.yml",
    "chars": 4135,
    "preview": "name: Update Version File on Release\n\non:\n  release:\n    types: [created]\n\njobs:\n  update-version:\n    runs-on: ubuntu-l"
  },
  {
    "path": ".github/workflows/user-first-interaction.yml",
    "chars": 1340,
    "preview": "name: User First Interaction\n\non:\n  issues:\n    types: [opened]\n  pull_request:\n    branches: [main]\n    types: [opened]"
  },
  {
    "path": ".gitignore",
    "chars": 6954,
    "preview": "# Copyright © 2023 OpenIMSDK.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this"
  },
  {
    "path": ".golangci.yml",
    "chars": 33217,
    "preview": "# options for analysis running\nrun:\n  # default concurrency is a available CPU number\n  concurrency: 4\n\n  # timeout for "
  },
  {
    "path": "CHANGELOG/CHANGELOG-3.8.md",
    "chars": 4145,
    "preview": "## [v3.8.3-patch.6](https://github.com/openimsdk/open-im-server/releases/tag/v3.8.3-patch.6) \t(2025-07-23)\n\n### Bug Fixe"
  },
  {
    "path": "CHANGELOG/README.md",
    "chars": 56,
    "preview": "# CHANGELOGs\n\n- [CHANGELOG-3.8.md](./CHANGELOG-3.8.md)\n\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5222,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING-zh_CN.md",
    "chars": 3273,
    "preview": "\n\n# 如何给 OpenIM 贡献代码(提交 Pull Request)\n\n<p align=\"center\">\n  <a href=\"./CONTRIBUTING.md\">English</a> · \n  <a href=\"./CONTR"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 4594,
    "preview": "# How to Contribute to OpenIM (Submitting Pull Requests)\n\n<p align=\"center\">\n  <a href=\"./CONTRIBUTING.md\">English</a> ·"
  },
  {
    "path": "Dockerfile",
    "chars": 1688,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n\n# Define the bas"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 7586,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"./assets/logo-gif/openim-logo.gif\" width=\"60%\" hei"
  },
  {
    "path": "README_zh_CN.md",
    "chars": 5843,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"./assets/logo-gif/openim-logo.gif\" width=\"60%\" hei"
  },
  {
    "path": "assets/README.md",
    "chars": 1899,
    "preview": "# `/assets`\n\nThe `/assets` directory in the OpenIM repository contains various assets such as images, logos, and animate"
  },
  {
    "path": "assets/colors.md",
    "chars": 327,
    "preview": "# Official Colors\n\nThe openim logo has an official blue color.  When reproducing the logo, please use the official color"
  },
  {
    "path": "assets/demo/README.md",
    "chars": 572,
    "preview": "## :star2: Why OpenIM\n\n**🔍 Function screenshot display**\n\n<div align=\"center\">\n\n\n|             multiple message         "
  },
  {
    "path": "assets/logo/LICENSE",
    "chars": 135,
    "preview": "# The OpenIM logo files are licensed under a choice of either Apache-2.0 or CC-BY-4.0 (Creative Commons Attribution 4.0 "
  },
  {
    "path": "assets/logo-gif/LICENSE",
    "chars": 135,
    "preview": "# The OpenIM logo files are licensed under a choice of either Apache-2.0 or CC-BY-4.0 (Creative Commons Attribution 4.0 "
  },
  {
    "path": "bootstrap.bat",
    "chars": 555,
    "preview": "@echo off\nSETLOCAL\n\nmage -version >nul 2>&1\nIF %ERRORLEVEL% EQU 0 (\n    echo Mage is already installed.\n    GOTO DOWNLOA"
  },
  {
    "path": "bootstrap.sh",
    "chars": 595,
    "preview": "#!/bin/bash\n\nif [[ \":$PATH:\" == *\":$HOME/.local/bin:\"* ]]; then\n    TARGET_DIR=\"$HOME/.local/bin\"\nelse\n    TARGET_DIR=\"/"
  },
  {
    "path": "build/README.md",
    "chars": 4574,
    "preview": "# Building OpenIM\n\nBuilding OpenIM is easy if you take advantage of the containerized build environment. This document w"
  },
  {
    "path": "build/goreleaser.yaml",
    "chars": 11704,
    "preview": "# This is an example .goreleaser.yml file with some sensible defaults.\n# Make sure to check the documentation at https:/"
  },
  {
    "path": "build/images/Dockerfile",
    "chars": 779,
    "preview": "# # Copyright © 2023 OpenIM. All rights reserved.\n# #\n# # Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "build/images/openim-api/Dockerfile",
    "chars": 1077,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n\n# Define the bas"
  },
  {
    "path": "build/images/openim-crontask/Dockerfile",
    "chars": 1097,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-msggateway/Dockerfile",
    "chars": 1103,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-msgtransfer/Dockerfile",
    "chars": 1106,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-push/Dockerfile",
    "chars": 1085,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-rpc-auth/Dockerfile",
    "chars": 1108,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-rpc-conversation/Dockerfile",
    "chars": 1132,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-rpc-friend/Dockerfile",
    "chars": 1114,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-rpc-group/Dockerfile",
    "chars": 1111,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-rpc-msg/Dockerfile",
    "chars": 1105,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-rpc-third/Dockerfile",
    "chars": 1111,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-rpc-user/Dockerfile",
    "chars": 1106,
    "preview": "# Use Go 1.22 Alpine as the base image for building the application\nFROM golang:1.22-alpine AS builder\n# Define the base"
  },
  {
    "path": "build/images/openim-tools/component/Dockerfile",
    "chars": 3538,
    "preview": "# # Copyright © 2023 OpenIM. All rights reserved.\n# #\n# # Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "cmd/main.go",
    "chars": 9643,
    "preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"os/signal\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"reflect\"\n"
  },
  {
    "path": "cmd/openim-api/main.go",
    "chars": 852,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-cmdutils/main.go",
    "chars": 2190,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-crontask/main.go",
    "chars": 837,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-msggateway/main.go",
    "chars": 839,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-msgtransfer/main.go",
    "chars": 840,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-push/main.go",
    "chars": 836,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-rpc/openim-rpc-auth/main.go",
    "chars": 836,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-rpc/openim-rpc-conversation/main.go",
    "chars": 844,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-rpc/openim-rpc-friend/main.go",
    "chars": 838,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-rpc/openim-rpc-group/main.go",
    "chars": 837,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-rpc/openim-rpc-msg/main.go",
    "chars": 835,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-rpc/openim-rpc-third/main.go",
    "chars": 837,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "cmd/openim-rpc/openim-rpc-user/main.go",
    "chars": 836,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  },
  {
    "path": "config/README.md",
    "chars": 5120,
    "preview": "# \t\t\t\t\t\tOpenIM Configuration File Descriptions and Common Configuration Modifications\n\n## External Component Configurati"
  },
  {
    "path": "config/README_zh_CN.md",
    "chars": 3643,
    "preview": "# \t\t\t\t\t\tOpenIM配置文件说明以及常用配置修改说明\n\n## 外部组件相关配置\n\n| Configuration File | Description                        |\n| -------------"
  },
  {
    "path": "config/alertmanager.yml",
    "chars": 762,
    "preview": "global:\n  resolve_timeout: 5m\n  smtp_from: alert@openim.io\n  smtp_smarthost: smtp.163.com:465\n  smtp_auth_username: aler"
  },
  {
    "path": "config/discovery.yml",
    "chars": 519,
    "preview": "enable: etcd\netcd:\n  rootDirectory: openim\n  address: [localhost:12379]\n  ## Attention: If you set auth in etcd\n  ## you"
  },
  {
    "path": "config/email.tmpl",
    "chars": 1643,
    "preview": "{{ define \"email.to.html\" }}\n{{ if eq .Status \"firing\" }}\n    {{ range .Alerts }}\n    <!-- Begin of OpenIM Alert -->\n   "
  },
  {
    "path": "config/grafana-template/Demo.json",
    "chars": 158152,
    "preview": "{\n  \"__inputs\": [\n    {\n      \"name\": \"DS_PROMETHEUS\",\n      \"label\": \"prometheus\",\n      \"description\": \"\",\n      \"type"
  },
  {
    "path": "config/instance-down-rules.yml",
    "chars": 1765,
    "preview": "groups:\n  - name: instance_down\n    rules:\n      - alert: InstanceDown\n        expr: up == 0\n        for: 1m\n        lab"
  },
  {
    "path": "config/kafka.yml",
    "chars": 1114,
    "preview": "## Kafka authentication\nusername:\npassword:\n\n# Producer acknowledgment settings\nproducerAck:\n# Compression type to use ("
  },
  {
    "path": "config/local-cache.yml",
    "chars": 546,
    "preview": "auth:\n  topic: DELETE_CACHE_AUTH\n  slotNum: 100\n  slotSize: 2000\n  successExpire: 300\n  failedExpire: 5\n\nuser:\n  topic: "
  },
  {
    "path": "config/log.yml",
    "chars": 651,
    "preview": "# Log storage path, default is acceptable, change to a full path if modification is needed\nstorageLocation: ../../../../"
  },
  {
    "path": "config/minio.yml",
    "chars": 552,
    "preview": "# Name of the bucket in MinIO\nbucket: openim\n# Access key ID for MinIO authentication\naccessKeyID: root\n# Secret access "
  },
  {
    "path": "config/mongodb.yml",
    "chars": 1828,
    "preview": "# URI for database connection, leave empty if using address and credential settings directly\nuri:\n# List of MongoDB serv"
  },
  {
    "path": "config/notification.yml",
    "chars": 7231,
    "preview": "groupCreated:\n  isSendMsg: true\n# Deprecated. Fixed as 1.\n  reliabilityLevel: 1\n# Deprecated. Fixed as false.\n  unreadCo"
  },
  {
    "path": "config/openim-api.yml",
    "chars": 1032,
    "preview": "api:\n  # Listening IP; 0.0.0.0 means both internal and external IPs are listened to, default is recommended\n  listenIP: "
  },
  {
    "path": "config/openim-crontask.yml",
    "chars": 169,
    "preview": "cronExecuteTime: 0 2 * * *\nretainChatRecords: 365\nfileExpireTime: 180\ndeleteObjectType: [\"msg-picture\",\"msg-file\", \"msg-"
  },
  {
    "path": "config/openim-msggateway.yml",
    "chars": 1851,
    "preview": "rpc:\n  # The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP\n "
  },
  {
    "path": "config/openim-msgtransfer.yml",
    "chars": 910,
    "preview": "prometheus:\n  # Enable or disable Prometheus monitoring\n  enable: true\n  # autoSetPorts indicates whether to automatical"
  },
  {
    "path": "config/openim-push.yml",
    "chars": 2222,
    "preview": "rpc:\n  # The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP\n "
  },
  {
    "path": "config/openim-rpc-auth.yml",
    "chars": 1573,
    "preview": "rpc:\n  # The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP\n "
  },
  {
    "path": "config/openim-rpc-conversation.yml",
    "chars": 1511,
    "preview": "rpc:\n  # The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP\n "
  },
  {
    "path": "config/openim-rpc-friend.yml",
    "chars": 1511,
    "preview": "rpc:\n  # The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP\n "
  },
  {
    "path": "config/openim-rpc-group.yml",
    "chars": 1545,
    "preview": "rpc:\n  # The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP\n "
  },
  {
    "path": "config/openim-rpc-msg.yml",
    "chars": 1584,
    "preview": "rpc:\n  # The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP\n "
  },
  {
    "path": "config/openim-rpc-third.yml",
    "chars": 2382,
    "preview": "rpc:\n  # The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP\n "
  },
  {
    "path": "config/openim-rpc-user.yml",
    "chars": 1445,
    "preview": "rpc:\n  # API or other RPCs can access this RPC through this IP; if left blank, the internal network IP is obtained by de"
  },
  {
    "path": "config/prometheus.yml",
    "chars": 4713,
    "preview": "# my global config\nglobal:\n  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 "
  },
  {
    "path": "config/redis.yml",
    "chars": 402,
    "preview": "address: [localhost:16379]\nusername:\npassword: openIM123\n# redis Mode, including \"standalone\",\"cluster\",\"sentinel\"\nredis"
  },
  {
    "path": "config/share.yml",
    "chars": 685,
    "preview": "secret: openIM123\n\n# imAdminUser: Configuration for instant messaging system administrators\nimAdminUser:\n  # userIDs: Li"
  },
  {
    "path": "config/webhooks.yml",
    "chars": 3937,
    "preview": "url: http://127.0.0.1:10006/callbackExample\nbeforeSendSingleMsg:\n  enable: false\n  timeout: 5\n  failedContinue: true\n  #"
  },
  {
    "path": "deployments/Readme.md",
    "chars": 5259,
    "preview": "# Kubernetes Deployment\n\n## Resource Requests\n\n- CPU: 2 cores\n- Memory: 4 GiB\n- Disk usage: 20 GiB (on Node)\n\n## Precond"
  },
  {
    "path": "deployments/deploy/clusterRole.yml",
    "chars": 527,
    "preview": "# ClusterRole.yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: service-reader\nrules:\n  "
  },
  {
    "path": "deployments/deploy/ingress.yml",
    "chars": 630,
    "preview": "apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  name: openim-ingress\n  annotations:\n    nginx.ingress.kuberne"
  },
  {
    "path": "deployments/deploy/kafka-secret.yml",
    "chars": 106,
    "preview": "apiVersion: v1\nkind: Secret\nmetadata:\n  name: openim-kafka-secret\ntype: Opaque\ndata:\n  kafka-password: \"\"\n"
  },
  {
    "path": "deployments/deploy/kafka-service.yml",
    "chars": 333,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: kafka-service\n  labels:\n    app: kafka\nspec:\n  ports:\n    - name: plainte"
  },
  {
    "path": "deployments/deploy/kafka-statefulset.yml",
    "chars": 1970,
    "preview": "apiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  name: kafka-statefulset\n  labels:\n    app: kafka\nspec:\n  replicas: 2\n "
  },
  {
    "path": "deployments/deploy/minio-secret.yml",
    "chars": 202,
    "preview": "apiVersion: v1\nkind: Secret\nmetadata:\n  name: openim-minio-secret\ntype: Opaque\ndata:\n  minio-root-user: cm9vdA== # Base6"
  },
  {
    "path": "deployments/deploy/minio-service.yml",
    "chars": 448,
    "preview": "---\napiVersion: v1\nkind: Service\nmetadata:\n  name: minio-service\nspec:\n  selector:\n    app: minio\n  ports:\n    - name: m"
  },
  {
    "path": "deployments/deploy/minio-statefulset.yml",
    "chars": 1751,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: minio\n  labels:\n    app: minio\nspec:\n  replicas: 2\n  selector:\n  "
  },
  {
    "path": "deployments/deploy/mongo-secret.yml",
    "chars": 256,
    "preview": "apiVersion: v1\nkind: Secret\nmetadata:\n  name: openim-mongo-secret\ntype: Opaque\ndata:\n  mongo_openim_username: b3BlbklN #"
  },
  {
    "path": "deployments/deploy/mongo-service.yml",
    "chars": 207,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: mongo-service\nspec:\n  selector:\n    app: mongo\n  ports:\n    - name: mongo"
  },
  {
    "path": "deployments/deploy/mongo-statefulset.yml",
    "chars": 3646,
    "preview": "apiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  name: mongo-statefulset\nspec:\n  serviceName: \"mongo\"\n  replicas: 2\n  s"
  },
  {
    "path": "deployments/deploy/openim-api-deployment.yml",
    "chars": 1246,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: openim-api\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n     "
  },
  {
    "path": "deployments/deploy/openim-api-service.yml",
    "chars": 306,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: openim-api-service\nspec:\n  selector:\n    app: openim-api\n  ports:\n    - n"
  },
  {
    "path": "deployments/deploy/openim-config.yml",
    "chars": 35188,
    "preview": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: openim-config\ndata:\n  discovery.yml: |\n    enable: \"kubernetes\" # \"kube"
  },
  {
    "path": "deployments/deploy/openim-crontask-deployment.yml",
    "chars": 610,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: openim-crontask\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n"
  },
  {
    "path": "deployments/deploy/openim-msggateway-deployment.yml",
    "chars": 930,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: messagegateway-rpc-server\nspec:\n  replicas: 2\n  selector:\n    mat"
  },
  {
    "path": "deployments/deploy/openim-msggateway-service.yml",
    "chars": 424,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: messagegateway-rpc-service\nspec:\n  selector:\n    app: messagegateway-rpc-"
  },
  {
    "path": "deployments/deploy/openim-msgtransfer-deployment.yml",
    "chars": 1449,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: openim-msgtransfer-server\nspec:\n  replicas: 2\n  selector:\n    mat"
  },
  {
    "path": "deployments/deploy/openim-msgtransfer-service.yml",
    "chars": 245,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: openim-msgtransfer-service\nspec:\n  selector:\n    app: openim-msgtransfer-"
  },
  {
    "path": "deployments/deploy/openim-push-deployment.yml",
    "chars": 1070,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: push-rpc-server\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n"
  },
  {
    "path": "deployments/deploy/openim-push-service.yml",
    "chars": 310,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: push-rpc-service\nspec:\n  selector:\n    app: push-rpc-server\n  ports:\n    "
  },
  {
    "path": "deployments/deploy/openim-rpc-auth-deployment.yml",
    "chars": 929,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: auth-rpc-server\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n"
  },
  {
    "path": "deployments/deploy/openim-rpc-auth-service.yml",
    "chars": 310,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: auth-rpc-service\nspec:\n  selector:\n    app: auth-rpc-server\n  ports:\n    "
  },
  {
    "path": "deployments/deploy/openim-rpc-conversation-deployment.yml",
    "chars": 1310,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: conversation-rpc-server\nspec:\n  replicas: 2\n  selector:\n    match"
  },
  {
    "path": "deployments/deploy/openim-rpc-conversation-service.yml",
    "chars": 326,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: conversation-rpc-service\nspec:\n  selector:\n    app: conversation-rpc-serv"
  },
  {
    "path": "deployments/deploy/openim-rpc-friend-deployment.yml",
    "chars": 1280,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: friend-rpc-server\nspec:\n  replicas: 2\n  selector:\n    matchLabels"
  },
  {
    "path": "deployments/deploy/openim-rpc-friend-service.yml",
    "chars": 314,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: friend-rpc-service\nspec:\n  selector:\n    app: friend-rpc-server\n  ports:\n"
  },
  {
    "path": "deployments/deploy/openim-rpc-group-deployment.yml",
    "chars": 1275,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: group-rpc-server\nspec:\n  replicas: 2\n  selector:\n    matchLabels:"
  },
  {
    "path": "deployments/deploy/openim-rpc-group-service.yml",
    "chars": 312,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: group-rpc-service\nspec:\n  selector:\n    app: group-rpc-server\n  ports:\n  "
  },
  {
    "path": "deployments/deploy/openim-rpc-msg-deployment.yml",
    "chars": 1443,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: msg-rpc-server\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n "
  },
  {
    "path": "deployments/deploy/openim-rpc-msg-service.yml",
    "chars": 308,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: msg-rpc-service\nspec:\n  selector:\n    app: msg-rpc-server\n  ports:\n    - "
  },
  {
    "path": "deployments/deploy/openim-rpc-third-deployment.yml",
    "chars": 1647,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: third-rpc-server\nspec:\n  replicas: 2\n  selector:\n    matchLabels:"
  },
  {
    "path": "deployments/deploy/openim-rpc-third-service.yml",
    "chars": 312,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: third-rpc-service\nspec:\n  selector:\n    app: third-rpc-server\n  ports:\n  "
  },
  {
    "path": "deployments/deploy/openim-rpc-user-deployment.yml",
    "chars": 1448,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: user-rpc-server\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n"
  },
  {
    "path": "deployments/deploy/openim-rpc-user-service.yml",
    "chars": 310,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: user-rpc-service\nspec:\n  selector:\n    app: user-rpc-server\n  ports:\n    "
  },
  {
    "path": "deployments/deploy/redis-secret.yml",
    "chars": 140,
    "preview": "apiVersion: v1\nkind: Secret\nmetadata:\n  name: openim-redis-secret\ntype: Opaque\ndata:\n  redis-password: b3BlbklNMTIz # \"o"
  },
  {
    "path": "deployments/deploy/redis-service.yml",
    "chars": 230,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: redis-service\n  labels:\n    app: redis\nspec:\n  type: ClusterIP\n  selector"
  },
  {
    "path": "deployments/deploy/redis-statefulset.yml",
    "chars": 1209,
    "preview": "apiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  name: redis-statefulset\nspec:\n  serviceName: \"redis\"\n  replicas: 2\n  s"
  },
  {
    "path": "docker-compose.yml",
    "chars": 14144,
    "preview": "networks:\n  openim:\n    driver: bridge\n\nservices:\n  mongodb:\n    image: \"${MONGO_IMAGE}\"\n    ports:\n      - \"37017:27017"
  },
  {
    "path": "docs/.generated_docs",
    "chars": 3136,
    "preview": "docs/.generated_docs\n\ndocs/guide/en-US/cmd/openim/openim.md\ndocs/guide/en-US/cmd/openim/openim_color.md\ndocs/guide/en-US"
  },
  {
    "path": "docs/CODEOWNERS",
    "chars": 168,
    "preview": "# CODEOWNERS file\n# This file is used to specify the individuals who are required to review changes in this repository.\n"
  },
  {
    "path": "docs/README.md",
    "chars": 5711,
    "preview": "# OpenIM Server Docs\n\nWelcome to the OpenIM Documentation hub! This center provides a comprehensive range of guides and "
  },
  {
    "path": "docs/contrib/README.md",
    "chars": 4016,
    "preview": "# Contrib Documentation Index\n\n## 📚 General Information\n- [📄 README](https://github.com/openimsdk/open-im-server/tree/ma"
  },
  {
    "path": "docs/contrib/api.md",
    "chars": 283,
    "preview": "## Interface Standards\n\nOur project, OpenIM, adheres to the [OpenAPI 3.0](https://spec.openapis.org/oas/latest.html) int"
  },
  {
    "path": "docs/contrib/bash-log.md",
    "chars": 4118,
    "preview": "## OpenIM Logging System: Design and Usage\n\n**PATH:** `scripts/lib/logging.sh`\n\n\n\n### Introduction\n\nOpenIM, an intricate"
  },
  {
    "path": "docs/contrib/cicd-actions.md",
    "chars": 8094,
    "preview": "# Continuous Integration and Automation\n\nEvery change on the OpenIM repository, either made through a pull request or di"
  },
  {
    "path": "docs/contrib/code-conventions.md",
    "chars": 4874,
    "preview": "# Code conventions\n\n- [Code conventions](#code-conventions)\n  - [POSIX shell](#posix-shell)\n  - [Go](#go)\n  - [OpenIM Na"
  },
  {
    "path": "docs/contrib/commit.md",
    "chars": 1004,
    "preview": "## Commit Standards\n\nOur project, OpenIM, follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0"
  },
  {
    "path": "docs/contrib/development.md",
    "chars": 3428,
    "preview": "# Development Guide\n\nSince OpenIM is written in Go, it is fair to assume that the Go tools are all one needs to contribu"
  },
  {
    "path": "docs/contrib/directory.md",
    "chars": 138,
    "preview": "## Catalog Service Interface Specification\n\n+ [https://github.com/kubecub/go-project-layout](https://github.com/kubecub/"
  },
  {
    "path": "docs/contrib/environment.md",
    "chars": 33458,
    "preview": "# OpenIM ENVIRONMENT CONFIGURATION\n\n<!-- vscode-markdown-toc -->\n* 1. [OpenIM Deployment Guide](#OpenIMDeploymentGuide)\n"
  },
  {
    "path": "docs/contrib/error-code.md",
    "chars": 1781,
    "preview": "## Error Code Standards\n\nError codes are one of the important means for users to locate and solve problems. When an appl"
  },
  {
    "path": "docs/contrib/git-workflow.md",
    "chars": 4381,
    "preview": "# Git workflows\n\nThis document is an overview of OpenIM git workflow. It includes conventions, tips, and how to maintain"
  },
  {
    "path": "docs/contrib/gitcherry-pick.md",
    "chars": 8867,
    "preview": "# Git Cherry-Pick Guide\n\n- Git Cherry-Pick Guide\n  - [Introduction](#introduction)\n  - [What is git cherry-pick?](#what-"
  },
  {
    "path": "docs/contrib/github-workflow.md",
    "chars": 9627,
    "preview": "---\ntitle: \"GitHub Workflow\"\nweight: 6\ndescription: |\n  This document is an overview of the GitHub workflow used by the\n"
  },
  {
    "path": "docs/contrib/go-code.md",
    "chars": 47841,
    "preview": "## OpenIM development specification\nWe have very high standards for code style and specification, and we want our produc"
  },
  {
    "path": "docs/contrib/go-code1.md",
    "chars": 48203,
    "preview": "## OpenIM development specification\nWe have very high standards for code style and specification, and we want our produc"
  },
  {
    "path": "docs/contrib/go-doc.md",
    "chars": 3957,
    "preview": "# Go Language Documentation for OpenIM\n\nIn the realm of software development, especially within Go language projects, do"
  },
  {
    "path": "docs/contrib/images.md",
    "chars": 7501,
    "preview": "# OpenIM Image Management Strategy and Pulling Guide\n\nOpenIM is an efficient, stable, and scalable instant messaging fra"
  },
  {
    "path": "docs/contrib/init-config.md",
    "chars": 3965,
    "preview": "# Init OpenIM Config\n\n- [Init OpenIM Config](#init-openim-config)\n  - [Start](#start)\n  - [Define Automated Configuratio"
  },
  {
    "path": "docs/contrib/install-docker.md",
    "chars": 950,
    "preview": "<!-- vscode-markdown-toc -->\n\n<!-- vscode-markdown-toc-config\n\tnumbering=true\n\tautoSave=true\n\t/vscode-markdown-toc-confi"
  },
  {
    "path": "docs/contrib/install-openim-linux-system.md",
    "chars": 10371,
    "preview": "# OpenIM System: Setup and Usage Guide\n\n<!-- vscode-markdown-toc -->\n* 1. [1. Introduction](#Introduction)\n* 2. [2. Prer"
  },
  {
    "path": "docs/contrib/kafka.md",
    "chars": 5448,
    "preview": "# OpenIM Kafka Guide\n\nThis document aims to provide a set of concise guidelines to help you quickly install and use Kafk"
  },
  {
    "path": "docs/contrib/linux-development.md",
    "chars": 4497,
    "preview": "# Ubuntu 22.04 OpenIM Project Development Guide\n\n## TOC\n- [Ubuntu 22.04 OpenIM Project Development Guide](#ubuntu-2204-o"
  },
  {
    "path": "docs/contrib/local-actions.md",
    "chars": 1137,
    "preview": "# act\n\nRun your [GitHub Actions](https://developer.github.com/actions/) locally! Why would you want to do this? Two reas"
  },
  {
    "path": "docs/contrib/logging.md",
    "chars": 17421,
    "preview": "# OpenIM Logging and Error Handling Documentation\n\n## Script Logging Documentation Link\n\nIf you wish to view the script'"
  },
  {
    "path": "docs/contrib/mac-developer-deployment-guide.md",
    "chars": 6912,
    "preview": "# Mac Developer Deployment Guide for OpenIM\n\n## Introduction\n\nThis guide aims to assist Mac-based developers in contribu"
  },
  {
    "path": "docs/contrib/offline-deployment.md",
    "chars": 4629,
    "preview": "# OpenIM Offline Deployment Design\n\n## 1. Base Images\n\nBelow are the base images and their versions you'll need:\n\n- [ ] "
  },
  {
    "path": "docs/contrib/prometheus-grafana.md",
    "chars": 18609,
    "preview": "# Deployment and Design of OpenIM's Management Backend and Monitoring\n\n<!-- vscode-markdown-toc -->\n* 1. [Source Code & "
  },
  {
    "path": "docs/contrib/protoc-tools.md",
    "chars": 3050,
    "preview": "# OpenIM Protoc Tool\n\n## Introduction\n\nOpenIM is passionate about ensuring that its suite of tools is custom-tailored to"
  },
  {
    "path": "docs/contrib/release.md",
    "chars": 11848,
    "preview": "# OpenIM Release Automation Design Document\n\nThis document outlines the automation process for releasing OpenIM. You can"
  },
  {
    "path": "docs/contrib/test.md",
    "chars": 15583,
    "preview": "# OpenIM RPC Service Test Control Script Documentation\n\nThis document serves as a comprehensive guide to understanding a"
  },
  {
    "path": "docs/contrib/util-go.md",
    "chars": 177,
    "preview": "# utils go \n\n+ [toold readme](https://github.com/openimsdk/open-im-server/tree/main/tools)\n\nabout scripts fix:\n```\n\"${OP"
  },
  {
    "path": "docs/contrib/util-makefile.md",
    "chars": 4191,
    "preview": "# Open-IM-Server Development Tools Guide\n\n- [Open-IM-Server Development Tools Guide](#open-im-server-development-tools-g"
  },
  {
    "path": "docs/contrib/util-scripts.md",
    "chars": 8524,
    "preview": "# OpenIM Bash Utility Script\n\nThis script offers a variety of utilities and helpers to enhance and simplify operations r"
  },
  {
    "path": "docs/contrib/version.md",
    "chars": 13906,
    "preview": "# OpenIM Branch Management and Versioning: A Blueprint for High-Grade Software Development\n\n[📚 **OpenIM TOC**](#openim-b"
  },
  {
    "path": "docs/contributing/CONTRIBUTING-JP.md",
    "chars": 1644,
    "preview": "# How do I contribute code to OpenIM\n\n<p align=\"center\">\n  <a href=\"./CONTRIBUTING.md\">English</a> · \n  <a href=\"./CONTR"
  },
  {
    "path": "docs/contributing/CONTRIBUTING-PL.md",
    "chars": 1644,
    "preview": "# How do I contribute code to OpenIM\n\n<p align=\"center\">\n  <a href=\"./CONTRIBUTING.md\">English</a> · \n  <a href=\"./CONTR"
  },
  {
    "path": "docs/readme/README_cs.md",
    "chars": 12629,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_da.md",
    "chars": 12912,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_el.md",
    "chars": 13608,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_es.md",
    "chars": 13547,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_fa.md",
    "chars": 12386,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_fr.md",
    "chars": 12908,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_hu.md",
    "chars": 13083,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_ja.md",
    "chars": 10746,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_ko.md",
    "chars": 10707,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_tr.md",
    "chars": 12761,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_uk.md",
    "chars": 12876,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "docs/readme/README_vi.md",
    "chars": 12910,
    "preview": "<p align=\"center\">\n    <a href=\"https://openim.io\">\n        <img src=\"../../assets/logo-gif/openim-logo.gif\" width=\"60%\""
  },
  {
    "path": "go.mod",
    "chars": 10953,
    "preview": "module github.com/openimsdk/open-im-server/v3\n\ngo 1.25.0\n\nrequire (\n\tfirebase.google.com/go/v4 v4.14.1\n\tgithub.com/dtm-l"
  },
  {
    "path": "go.sum",
    "chars": 64172,
    "preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.112.1 h1:uJSei"
  },
  {
    "path": "install.sh",
    "chars": 21392,
    "preview": "#!/usr/bin/env bash\n\n# Copyright © 2023 OpenIM. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 "
  },
  {
    "path": "internal/api/auth.go",
    "chars": 1274,
    "preview": "// Copyright © 2023 OpenIM. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
  }
]

// ... and 467 more files (download for full content)

About this extraction

This page contains the full source code of the openimsdk/open-im-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 667 files (2.7 MB), approximately 739.3k tokens, and a symbol index with 3403 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!