diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml
index 540c8a48b..ae27c8a0a 100644
--- a/.github/workflows/cla.yml
+++ b/.github/workflows/cla.yml
@@ -33,7 +33,7 @@ env:
OPEN_IM_SERVER_CLA_DOCUMENT: https://github.com/openim-sigs/cla/blob/main/README.md
OPEN_IM_SERVER_SIGNATURES_PATH: signatures/${{ github.event.repository.name }}/cla.json
- OPEN_IM_SERVER_ALLOWLIST: kubbot,bot*,bot-*,bot/*,bot-/*,bot,*[bot]
+ OPEN_IM_SERVER_ALLOWLIST: kubbot,openimbot,bot*,dependabot,sweep-ai,*bot,bot-*,bot/*,bot-/*,bot,*[bot]
jobs:
CLAAssistant:
diff --git a/.github/workflows/docker-buildx.yml b/.github/workflows/docker-buildx.yml
index 6113cfae5..b3b0b5683 100644
--- a/.github/workflows/docker-buildx.yml
+++ b/.github/workflows/docker-buildx.yml
@@ -106,6 +106,16 @@ jobs:
ghcr.io/openimsdk/openim-api
openim/openim-api
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-api
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-api
uses: docker/build-push-action@v5
@@ -127,6 +137,16 @@ jobs:
ghcr.io/openimsdk/openim-cmdutils
openim/openim-cmdutils
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-cmdutils
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-cmdutils
uses: docker/build-push-action@v5
@@ -148,6 +168,16 @@ jobs:
ghcr.io/openimsdk/openim-crontask
openim/openim-crontask
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-crontask
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-crontask
uses: docker/build-push-action@v5
@@ -169,6 +199,16 @@ jobs:
ghcr.io/openimsdk/openim-msggateway
openim/openim-msggateway
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-msggateway
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-msggateway
uses: docker/build-push-action@v5
@@ -190,6 +230,16 @@ jobs:
ghcr.io/openimsdk/openim-msgtransfer
openim/openim-msgtransfer
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-msgtransfer
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-msgtransfer
uses: docker/build-push-action@v5
@@ -211,6 +261,16 @@ jobs:
ghcr.io/openimsdk/openim-push
openim/openim-push
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-push
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-push
uses: docker/build-push-action@v5
@@ -232,6 +292,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-auth
openim/openim-rpc-auth
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-auth
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-auth
uses: docker/build-push-action@v5
@@ -253,6 +323,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-conversation
openim/openim-rpc-conversation
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-conversation
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-conversation
uses: docker/build-push-action@v5
@@ -274,6 +354,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-friend
openim/openim-rpc-friend
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-friend
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-friend
uses: docker/build-push-action@v5
@@ -295,6 +385,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-group
openim/openim-rpc-group
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-group
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-group
uses: docker/build-push-action@v5
@@ -316,6 +416,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-msg
openim/openim-rpc-msg
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-msg
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-msg
uses: docker/build-push-action@v5
@@ -337,6 +447,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-third
openim/openim-rpc-third
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-third
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-third
uses: docker/build-push-action@v5
@@ -358,6 +478,16 @@ jobs:
ghcr.io/openimsdk/openim-rpc-user
openim/openim-rpc-user
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-rpc-user
+ tags: |
+ type=ref,event=tag
+ type=schedule
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern=v{{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=semver,pattern={{major}}
+ type=sha
- name: Build and push Docker image for openim-rpc-user
uses: docker/build-push-action@v5
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index 2f6d7fe05..6d8112eb4 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -92,11 +92,40 @@ jobs:
- name: Exec OpenIM API test
run: |
- sudo make test-api
-
- - name: Exec OpenIM E2E test
+ touch /tmp/test.md
+ echo "# OpenIM Test" >> /tmp/test.md
+ echo "## OpenIM API Test" >> /tmp/test.md
+ echo "Command Output for OpenIM API Test
" >> /tmp/test.md
+ echo "" >> /tmp/test.md
+ sudo make test-api | tee -a /tmp/test.md
+ echo "
" >> /tmp/test.md
+ echo " " >> /tmp/test.md
+
+ - name: Exec OpenIM E2E Test
run: |
- sudo make test-e2e
+ echo "" >> /tmp/test.md
+ echo "## OpenIM E2E Test" >> /tmp/test.md
+ echo "Command Output for OpenIM E2E Test
" >> /tmp/test.md
+ echo "" >> /tmp/test.md
+ sudo make test-e2e | tee -a /tmp/test.md
+ echo "
" >> /tmp/test.md
+ echo " " >> /tmp/test.md
+
+ - name: Comment PR with file
+ uses: thollander/actions-comment-pull-request@v2
+ with:
+ filePath: /tmp/test.md
+ comment_tag: nrt_file
+ reactions: eyes, rocket
+ mode: recreate
+ GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
+ continue-on-error: true
+
+ - name: Check outputs
+ run: |
+ echo "id : ${{ steps.nrt_message.outputs.id }}"
+ echo "body : ${{ steps.nrt_message.outputs.body }}"
+ echo "html_url : ${{ steps.nrt_message.outputs.html_url }}"
- name: Exec OpenIM System uninstall
run: |
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index d16e91ba4..00339110c 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -36,21 +36,19 @@ env:
GO_VERSION: "1.19"
GOLANGCI_VERSION: "v1.50.1"
-
jobs:
openim:
name: Test with go ${{ matrix.go_version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
permissions:
contents: write
+ pull-requests: write
environment:
name: openim
-
strategy:
matrix:
go_version: ["1.19","1.20","1.21"]
os: [ubuntu-latest]
-
steps:
- name: Setup
uses: actions/checkout@v4
@@ -111,6 +109,9 @@ jobs:
openim-start:
name: Test OpenIM install/start on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
+ permissions:
+ contents: write
+ pull-requests: write
environment:
name: openim
strategy:
@@ -129,9 +130,46 @@ jobs:
run: |
sudo make install
+ # - name: Check the OpenIM environment and status
+ # run: |
+ # sudo docker images
+ # sudo docker ps
+
+ - name: Check the OpenIM environment and status
+ id: docker_info
+ run: |
+ sleep 30
+ echo "images<> $GITHUB_ENV
+ sudo docker images >> $GITHUB_ENV
+ echo "EOF" >> $GITHUB_ENV
+ echo "containers<> $GITHUB_ENV
+ sudo docker ps >> $GITHUB_ENV
+ echo "EOF" >> $GITHUB_ENV
+
+ - name: Comment PR
+ uses: thollander/actions-comment-pull-request@v2
+ with:
+ message: |
+ > [!TIP]
+ > Run make install to check the status
+
+ ### Docker Images:
+ ```
+ ${{ env.images }}
+ ```
+ ### Docker Processes:
+ ```
+ ${{ env.containers }}
+ ```
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ continue-on-error: true
+
execute-scripts:
name: Execute OpenIM Script On ${{ matrix.os }}
runs-on: ${{ matrix.os }}
+ permissions:
+ contents: write
+ pull-requests: write
environment:
name: openim
strategy:
@@ -201,10 +239,9 @@ jobs:
- name: Build, Start, Check Services and Print Logs for Ubuntu
if: runner.os == 'Linux'
run: |
- sudo make build && \
- sudo make start && \
- sudo make check || \
- (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
+ sudo make build
+ sudo make start
+ sudo make check
- name: Restart Services and Print Logs for Ubuntu
if: runner.os == 'Linux'
@@ -212,18 +249,17 @@ jobs:
sudo make restart
sudo make check
- # - name: Build, Start, Check Services and Print Logs for macOS
- # if: runner.os == 'macOS'
- # run: |
- # make init && \
- # make build && \
- # make start && \
- # make check || \
- # (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
+ - name: Build, Start, Check Services and Print Logs for macOS
+ if: runner.os == 'macOS'
+ run: |
+ make build
openim-test-build-image:
name: Build OpenIM Docker Image
runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
environment:
name: openim
steps:
@@ -245,3 +281,9 @@ jobs:
run: |
sudo make init
sudo make image
+
+ - name: Get OpenIM Docker Images Status
+ id: docker_processes
+ run: |
+ sudo docker images
+ sudo docker ps
diff --git a/README-zh_CN.md b/README-zh_CN.md
index e2df68a56..12a56d4f6 100644
--- a/README-zh_CN.md
+++ b/README-zh_CN.md
@@ -35,52 +35,62 @@
## Ⓜ️ 关于 OpenIM
-OpenIM 不仅仅是一个开源的即时消息组件,它是你的应用程序生态系统的一个不可或缺的部分。查看下面的图表,了解 AppServer、AppClient、OpenIMServer 和 OpenIMSDK 是如何交互的。
+OpenIM 是一个专门设计用于在应用程序中集成聊天、音视频通话、通知以及AI聊天机器人等通信功能的服务平台。它通过提供一系列强大的API和Webhooks,使开发者可以轻松地在他们的应用中加入这些交互特性。OpenIM 本身并不是一个独立运行的聊天应用,而是作为一个平台,为其他应用提供支持,实现丰富的通信功能。下图展示 AppServer、AppClient、OpenIMServer 和 OpenIMSDK 之间的交互关系来具体说明。
+
+
+
+

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

## 🚀 About OpenIMSDK
-**OpenIMSDK** seamlessly integrates into your application, delivering a rich, real-time messaging experience without requiring intricate UI integration. It provides:
-
-+ **Local Storage**: For quick data retrieval and message synchronization.
-+ **Listener Callbacks**: Ensuring real-time message interactivity.
-+ **API Encapsulation**: Streamlining development processes.
-+ **Connection Management**: Guaranteeing reliable message delivery.
-
-It's crafted in Golang and supports cross-platform deployment, ensuring a coherent messaging experience across all platforms.
-
-👉 **[Explore GO SDK](https://github.com/openimsdk/openim-sdk-core)**
-
-## 🌐 About OpenIMServer
-
-**OpenIMServer**, meticulously developed in Golang, ensures a stellar instant messaging server capability with a multifold approach:
-
-+ **Modular Composition**: It's comprised of several modules, such as the gateway and multiple RPC services, offering a versatile messaging environment.
-+ **Microservices Architecture**: Supporting cluster modes, it assures outstanding performance and scalability to manage communication effectively across various instances.
-+ **Diverse Deployment Options**: Adapts to your operational preferences, offering deployment via source code, Kubernetes, or Docker.
-
-### Enhanced Business Functionalities:
-
-+ **REST API**: OpenIMServer provides REST API for business systems, aiming to empower your operations with additional functionalities like group creation and message push via backend interfaces.
-+ **Callbacks**: To expand its utility across varied business forms, OpenIMServer offers callback capabilities. That is, it sends a request to the business server before or after an event occurs, such as sending a message, enriching the interaction and data exchange flow in the communication processes.
-
-👉 **[Learn More](https://docs.openim.io/guides/introduction/product)**
-
-
++ **REST API**: OpenIMServer offers REST APIs for business systems, aimed at empowering businesses with more functionalities, such as creating groups and sending push messages through backend interfaces.
++ **Webhooks**: OpenIMServer provides callback capabilities to extend more business forms. A callback means that OpenIMServer sends a request to the business server before or after a certain event, like callbacks before or after sending a message.
+👉 **[Learn more](https://docs.openim.io/guides/introduction/product)**
## :rocket: Quick Start
-We support many platforms. Here are the addresses for quick experience on the web side:
-
-👉 **[OpenIM online web demo](https://web-enterprise.rentsoft.cn/)**
-
-You can quickly learn OpenIM engineering solutions, all it takes is one simple command:
-
-```bash
-$ make demo
-```
-
-🤲 In order to facilitate the user experience, we have provided a variety of deployment solutions, you can choose your own deployment method according to the list below:
-
-
+🤲 To facilitate user experience, we offer various deployment solutions. You can choose your deployment method from the list below:
+ **[Source Code Deployment Guide](https://docs.openim.io/guides/gettingStarted/imSourceCodeDeployment)**
-+ **[Production deployment of Linux systems](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/install-openim-linux-system.md)**
+ **[Docker Deployment Guide](https://docs.openim.io/guides/gettingStarted/dockerCompose)**
-+ **[Kubernetes Deployment Guide](https://github.com/openimsdk/open-im-server/tree/main/deployments)**
-
-
++ **[Kubernetes Deployment Guide](https://docs.openim.io/guides/gettingStarted/k8s-deployment)**
## :hammer_and_wrench: To start developing OpenIM
diff --git a/build/goreleaser.yaml b/build/goreleaser.yaml
index ed7f7cd1b..93fe9f4c8 100644
--- a/build/goreleaser.yaml
+++ b/build/goreleaser.yaml
@@ -3,12 +3,36 @@
before:
hooks:
+ - make clean
# You may remove this if you don't use go modules.
- make tidy
- make copyright.add
# you may remove this if you don't need go generate
- go generate ./...
+git:
+ # What should be used to sort tags when gathering the current and previous
+ # tags if there are more than one tag in the same commit.
+ #
+ # Default: '-version:refname'
+ tag_sort: -version:creatordate
+
+ # What should be used to specify prerelease suffix while sorting tags when gathering
+ # the current and previous tags if there are more than one tag in the same commit.
+ #
+ # Since: v1.17
+ prerelease_suffix: "-"
+
+ # Tags to be ignored by GoReleaser.
+ # This means that GoReleaser will not pick up tags that match any of the
+ # provided values as either previous or current tags.
+ #
+ # Templates: allowed.
+ # Since: v1.21.
+ ignore_tags:
+ - nightly
+ # - "{{.Env.IGNORE_TAG}}"
+
snapshot:
name_template: "{{ incpatch .Version }}-next"
@@ -495,4 +519,4 @@ checksum:
algorithm: sha256
release:
- prerelease: auto
\ No newline at end of file
+ prerelease: auto
diff --git a/deployments/templates/env-template.yaml b/deployments/templates/env-template.yaml
index e0fd7bc9f..e7166ff2d 100644
--- a/deployments/templates/env-template.yaml
+++ b/deployments/templates/env-template.yaml
@@ -1,3 +1,17 @@
+# Copyright © 2024 OpenIM. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
# -----------------------------------------------------------------------------
# General Configuration
# This section contains general configuration options for the entire environment.
@@ -84,19 +98,23 @@ OPENIM_IP=${OPENIM_IP}
# Default: ZOOKEEPER_PORT=12181
ZOOKEEPER_PORT=${ZOOKEEPER_PORT}
-# Port on which MongoDB service is running.
+# MongoDB service port configuration.
# Default: MONGO_PORT=37017
# MONGO_PORT=${MONGO_PORT}
-# Username to authenticate with the MongoDB service.
-# Default: MONGO_USERNAME=root
-# MONGO_USERNAME=${MONGO_USERNAME}
-
-# Password to authenticate with the MongoDB service.
+# Password for MongoDB admin user. Used for service authentication.
# Default: MONGO_PASSWORD=openIM123
MONGO_PASSWORD=${MONGO_PASSWORD}
-# Name of the database in MongoDB to be used.
+# Username for a regular OpenIM user in MongoDB.
+# Default: MONGO_OPENIM_USERNAME=openIM
+MONGO_OPENIM_USERNAME=${MONGO_OPENIM_USERNAME}
+
+# Password for a regular OpenIM user in MongoDB.
+# Default: MONGO_OPENIM_PASSWORD=openIM123456
+MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD}
+
+# Specifies the database name to be used within MongoDB.
# Default: MONGO_DATABASE=openIM_v3
MONGO_DATABASE=${MONGO_DATABASE}
@@ -177,7 +195,6 @@ OPENIM_WS_PORT=${OPENIM_WS_PORT}
# Default: API_OPENIM_PORT=10002
API_OPENIM_PORT=${API_OPENIM_PORT}
-
# ======================================
# ========== OpenIM Chat ===============
# ======================================
@@ -190,9 +207,9 @@ CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION}
# Default: OPENIM_CHAT_API_PORT=10008
OPENIM_CHAT_API_PORT=${OPENIM_CHAT_API_PORT}
-# Directory path for storing data files or related information for OpenIM chat.
-# Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main
-OPENIM_CHAT_DATA_DIR=${OPENIM_CHAT_DATA_DIR}
+# Port for the OpenIM admin API.
+# Default: OPENIM_ADMIN_API_PORT=10009
+OPENIM_ADMIN_API_PORT=${OPENIM_ADMIN_API_PORT}
# ======================================
# ========== OpenIM Admin ==============
@@ -201,10 +218,6 @@ OPENIM_CHAT_DATA_DIR=${OPENIM_CHAT_DATA_DIR}
# Branch name for OpenIM server.
# Default: SERVER_IMAGE_VERSION=main
SERVER_IMAGE_VERSION=${SERVER_IMAGE_VERSION}
-
-# Port for the OpenIM admin API.
-# Default: OPENIM_ADMIN_API_PORT=10009
-OPENIM_ADMIN_API_PORT=${OPENIM_ADMIN_API_PORT}
# Port for the node exporter.
# Default: NODE_EXPORTER_PORT=19100
@@ -224,4 +237,4 @@ OPENIM_ADMIN_FRONT_PORT=${OPENIM_ADMIN_FRONT_PORT}
# Port for the alertmanager.
# Default: ALERT_MANAGER_PORT=19093
-ALERT_MANAGER_PORT=${ALERT_MANAGER_PORT}
\ No newline at end of file
+ALERT_MANAGER_PORT=${ALERT_MANAGER_PORT}
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index 110c5c646..d5b066504 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -53,8 +53,8 @@ mongo:
# Maximum connection pool size
address: [ ${MONGO_ADDRESS}:${MONGO_PORT} ]
database: ${MONGO_DATABASE}
- username: ${MONGO_USERNAME}
- password: ${MONGO_PASSWORD}
+ username: ${MONGO_OPENIM_USERNAME}
+ password: ${MONGO_OPENIM_PASSWORD}
maxPoolSize: ${MONGO_MAX_POOL_SIZE}
###################### Redis configuration information ######################
diff --git a/docker-compose.yml b/docker-compose.yml
index fd71896a7..defc910c4 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -16,18 +16,20 @@ services:
ports:
- "${MONGO_PORT:-37017}:27017"
container_name: mongo
- command: --wiredTigerCacheSizeGB 1 --auth
+ command: ["/bin/bash", "-c", "/docker-entrypoint-initdb.d/mongo-init.sh || true; docker-entrypoint.sh mongod --wiredTigerCacheSizeGB 1 --auth"]
volumes:
- "${DATA_DIR:-./}/components/mongodb/data/db:/data/db"
- "${DATA_DIR:-./}/components/mongodb/data/logs:/data/logs"
- "${DATA_DIR:-./}/components/mongodb/data/conf:/etc/mongo"
- - ./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro
+ - "./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro"
environment:
- TZ=Asia/Shanghai
- wiredTigerCacheSizeGB=1
- MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME:-root}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD:-openIM123}
- MONGO_INITDB_DATABASE=${MONGO_DATABASE:-openIM_v3}
+ - MONGO_OPENIM_USERNAME=${MONGO_OPENIM_USERNAME:-openIM} # Non-root username
+ - MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD:-openIM123456} # Non-root password
restart: always
networks:
server:
@@ -122,9 +124,9 @@ services:
server:
ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7}
- ## Uncomment and configure the following services as needed
+ # Uncomment and configure the following services as needed
# openim-admin:
- # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin:toc-base-open-docker.35
+ # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0
# container_name: openim-admin
# restart: always
# ports:
@@ -167,12 +169,6 @@ services:
# hostname: grafana
# user: root
# restart: always
- # environment:
- # - GF_SECURITY_ALLOW_EMBEDDING=true
- # - GF_SESSION_COOKIE_SAMESITE=none
- # - GF_SESSION_COOKIE_SECURE=true
- # - GF_AUTH_ANONYMOUS_ENABLED=true
- # - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
# ports:
# - "${GRAFANA_PORT:-13000}:3000"
# volumes:
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index e52d57235..7425c8022 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -104,8 +104,8 @@ Docker deployment offers a slightly more intricate template. Within the [openim-
Configuration file modifications can be made by specifying corresponding environment variables, for instance:
```bash
-export CHAT_IMAGE_VERSION="main"
-export SERVER_IMAGE_VERSION="main"
+export CHAT_IMAGE_VERSION="main"
+export SERVER_IMAGE_VERSION="main"
```
These variables are stored within the [`environment.sh`](https://github.com/OpenIMSDK/openim-docker/blob/main/scripts/install/environment.sh) configuration:
@@ -114,6 +114,9 @@ These variables are stored within the [`environment.sh`](https://github.com/Open
readonly CHAT_IMAGE_VERSION=${CHAT_IMAGE_VERSION:-'main'}
readonly SERVER_IMAGE_VERSION=${SERVER_IMAGE_VERSION:-'main'}
```
+> [!IMPORTANT]
+> Can learn to read our mirror version strategy: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md
+
Setting a variable, e.g., `export CHAT_IMAGE_VERSION="release-v1.3"`, will prioritize `CHAT_IMAGE_VERSION="release-v1.3"` as the variable value. Ultimately, the chosen image version is determined, and rendering is achieved through `make init` (or `./scripts/init-config.sh`).
@@ -127,7 +130,7 @@ For convenience, configuration through modifying environment variables is recomm
+ PASSWORD
- + **Description**: Password for mysql, mongodb, redis, and minio.
+ + **Description**: Password for mongodb, redis, and minio.
+ **Default**: `openIM123`
+ Notes:
+ Minimum password length: 8 characters.
@@ -139,20 +142,22 @@ For convenience, configuration through modifying environment variables is recomm
+ OPENIM_USER
- + **Description**: Username for mysql, mongodb, redis, and minio.
+ + **Description**: Username for redis, and minio.
+ **Default**: `root`
```bash
export OPENIM_USER="root"
```
-+ API_URL
+> mongo is `openIM`, use `export MONGO_OPENIM_USERNAME="openIM"` to modify
+
++ OPENIM_IP
+ **Description**: API address.
+ **Note**: If the server has an external IP, it will be automatically obtained. For internal networks, set this variable to the IP serving internally.
```bash
- export API_URL="http://ip:10002"
+ export OPENIM_IP="ip"
```
+ DATA_DIR
@@ -304,8 +309,10 @@ This section involves setting up MongoDB, including its port, address, and crede
| -------------- | -------------- | ----------------------- |
| MONGO_PORT | "27017" | Port used by MongoDB. |
| MONGO_ADDRESS | [Generated IP] | IP address for MongoDB. |
-| MONGO_USERNAME | [User Defined] | Username for MongoDB. |
-| MONGO_PASSWORD | [User Defined] | Password for MongoDB. |
+| MONGO_USERNAME | [User Defined] | Admin Username for MongoDB. |
+| MONGO_PASSWORD | [User Defined] | Admin Password for MongoDB. |
+| MONGO_OPENIM_PASSWORD | [User Defined] | OpenIM Username for MongoDB. |
+| MONGO_OPENIM_PASSWORD | [User Defined] | OpenIM Password for MongoDB. |
### 2.8. Tencent Cloud COS Configuration
diff --git a/docs/contrib/images.md b/docs/contrib/images.md
index 44bd7b5bf..d1a83d639 100644
--- a/docs/contrib/images.md
+++ b/docs/contrib/images.md
@@ -26,6 +26,7 @@ We provide multiple versions of our images to meet different project requirement
1. `main`: This image corresponds to the latest version of the main branch in OpenIM. It is updated frequently, making it perfect for users who want to stay at the cutting edge of our features.
2. `release-v3.*`: This is the image that corresponds to the latest version of OpenIM's stable release branch. It's ideal for users who prefer a balance between new features and stability.
3. `v3.*.*`: These images are specific to each tag in OpenIM. They are preserved in their original state and are never overwritten. These are the go-to images for users who need a specific, unchanging version of OpenIM.
+4. The image versions adhere to Semantic Versioning 2.0.0 strategy. Taking the `openim-server` image as an example, available at [openim-server container package](https://github.com/openimsdk/open-im-server/pkgs/container/openim-server): upon tagging with v3.5.0, the CI automatically releases the following tags - `openim-server:3`, `openim-server:3.5`, `openim-server:3.5.0`, `openim-server:v3.5.0`, `openim-server:latest`, and `sha-e0244d9`. It's important to note that only `sha-e0244d9` is absolutely unique, whereas `openim-server:v3.5.0` and `openim-server:3.5.0` maintain a degree of uniqueness.
### Multi-Architecture Images
diff --git a/docs/contrib/version.md b/docs/contrib/version.md
index 0e03b8d8b..574badf59 100644
--- a/docs/contrib/version.md
+++ b/docs/contrib/version.md
@@ -1,6 +1,7 @@
# OpenIM Branch Management and Versioning: A Blueprint for High-Grade Software Development
[📚 **OpenIM TOC**](#openim-branch-management-and-versioning-a-blueprint-for-high-grade-software-development)
+- [OpenIM Branch Management and Versioning: A Blueprint for High-Grade Software Development](#openim-branch-management-and-versioning-a-blueprint-for-high-grade-software-development)
- [Unfolding the Mechanism of OpenIM Version Maintenance](#unfolding-the-mechanism-of-openim-version-maintenance)
- [Main Branch: The Heart of OpenIM Development](#main-branch-the-heart-of-openim-development)
- [Release Branch: The Beacon of Stability](#release-branch-the-beacon-of-stability)
@@ -8,8 +9,21 @@
- [Release Management: A Guided Tour](#release-management-a-guided-tour)
- [Milestones, Branching, and Addressing Major Bugs](#milestones-branching-and-addressing-major-bugs)
- [Version Skew Policy](#version-skew-policy)
+ - [Supported version skew](#supported-version-skew)
+ - [OpenIM Versioning, Branching, and Tag Strategy](#openim-versioning-branching-and-tag-strategy)
+ - [Supported Version Skew](#supported-version-skew-1)
+ - [openim-api](#openim-api)
+ - [openim-rpc-\* Components](#openim-rpc--components)
+ - [Other OpenIM Services](#other-openim-services)
+ - [Supported Component Upgrade Order](#supported-component-upgrade-order)
+ - [openim-api](#openim-api-1)
+ - [openim-rpc-\* Components](#openim-rpc--components-1)
+ - [Other OpenIM Services](#other-openim-services-1)
+ - [Conclusion](#conclusion)
- [Applying Principles: A Git Workflow Example](#applying-principles-a-git-workflow-example)
+ - [Release Process](#release-process)
- [Docker Images Version Management](#docker-images-version-management)
+ - [More](#more)
At OpenIM, we acknowledge the profound impact of implementing a robust and efficient version management system, hence we abide by the established standards of [Semantic Versioning 2.0.0](https://semver.org/lang/zh-CN/).
@@ -213,3 +227,10 @@ Throughout this process, active communication within the team is pivotal to main
## Docker Images Version Management
For more details on managing Docker image versions, visit [OpenIM Docker Images Administration](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md).
+
+## More
+
+More on multi-branch version management design and version management design at helm charts:
+
++ https://github.com/openimsdk/open-im-server/issues/1695
++ https://github.com/openimsdk/open-im-server/issues/1662
\ No newline at end of file
diff --git a/go.mod b/go.mod
index bff8174f7..345cf044d 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,8 @@ go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
- github.com/OpenIMSDK/protocol v0.0.45
- github.com/OpenIMSDK/tools v0.0.21
+ github.com/OpenIMSDK/protocol v0.0.46
+ github.com/OpenIMSDK/tools v0.0.23
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
diff --git a/go.sum b/go.sum
index a1963a29e..8a102d347 100644
--- a/go.sum
+++ b/go.sum
@@ -18,10 +18,10 @@ firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIw
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c=
github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ=
-github.com/OpenIMSDK/protocol v0.0.45 h1:0MxdGddw09k17xgR6Kn6ZLtcTrEosTCWXA/rhgSmbQQ=
-github.com/OpenIMSDK/protocol v0.0.45/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
-github.com/OpenIMSDK/tools v0.0.21 h1:iTapc2mIEVH/xl5Nd6jfwPub11Pgp44tVcE1rjB3a48=
-github.com/OpenIMSDK/tools v0.0.21/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/OpenIMSDK/protocol v0.0.46 h1:LKfwcC3pUcJKSxiIyj82fc479BuDbDtsCrPxa7bHxmo=
+github.com/OpenIMSDK/protocol v0.0.46/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/tools v0.0.23 h1:xozfrGzhbpNPlDTap5DLVPk+JfgZ/ZyIj4Cuu3/bm9w=
+github.com/OpenIMSDK/tools v0.0.23/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
diff --git a/internal/api/msg.go b/internal/api/msg.go
index 548450534..9348596ac 100644
--- a/internal/api/msg.go
+++ b/internal/api/msg.go
@@ -164,6 +164,8 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM
data = apistruct.VideoElem{}
case constant.File:
data = apistruct.FileElem{}
+ case constant.AtText:
+ data = apistruct.AtElem{}
case constant.Custom:
data = apistruct.CustomElem{}
case constant.OANotification:
@@ -172,7 +174,6 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM
if err = m.userRpcClient.GetNotificationByID(c, req.SendID); err != nil {
return nil, err
}
-
default:
return nil, errs.ErrArgs.WithDetail("not support err contentType")
}
diff --git a/internal/msggateway/constant.go b/internal/msggateway/constant.go
index fe5f09bdc..045629b4e 100644
--- a/internal/msggateway/constant.go
+++ b/internal/msggateway/constant.go
@@ -26,6 +26,7 @@ const (
Compression = "compression"
GzipCompressionProtocol = "gzip"
BackgroundStatus = "isBackground"
+ MsgResp = "isMsgResp"
)
const (
diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go
index 70c2f8fe0..7e8129105 100644
--- a/internal/msggateway/n_ws_server.go
+++ b/internal/msggateway/n_ws_server.go
@@ -16,7 +16,10 @@ package msggateway
import (
"context"
+ "encoding/json"
"errors"
+ "fmt"
+ "github.com/OpenIMSDK/tools/apiresp"
"net/http"
"os"
"os/signal"
@@ -342,11 +345,7 @@ func (ws *WsServer) multiTerminalLoginChecker(clientOK bool, oldClients []*Clien
if !clientOK {
return
}
-
- isDeleteUser := ws.clients.deleteClients(newClient.UserID, oldClients)
- if isDeleteUser {
- ws.onlineUserNum.Add(-1)
- }
+ ws.clients.deleteClients(newClient.UserID, oldClients)
for _, c := range oldClients {
err := c.KickOnlineMessage()
if err != nil {
@@ -422,84 +421,102 @@ func (ws *WsServer) unregisterClient(client *Client) {
)
}
-func (ws *WsServer) wsHandler(w http.ResponseWriter, r *http.Request) {
- connContext := newContext(w, r)
+func (ws *WsServer) ParseWSArgs(r *http.Request) (args *WSArgs, err error) {
+ var v WSArgs
+ defer func() {
+ args = &v
+ }()
+ query := r.URL.Query()
+ v.MsgResp, _ = strconv.ParseBool(query.Get(MsgResp))
if ws.onlineUserConnNum.Load() >= ws.wsMaxConnNum {
- httpError(connContext, errs.ErrConnOverMaxNumLimit)
- return
+ return nil, errs.ErrConnOverMaxNumLimit.Wrap("over max conn num limit")
}
- var (
- token string
- userID string
- platformIDStr string
- exists bool
- compression bool
- )
-
- token, exists = connContext.Query(Token)
- if !exists {
- httpError(connContext, errs.ErrConnArgsErr)
- return
+ if v.Token = query.Get(Token); v.Token == "" {
+ return nil, errs.ErrConnArgsErr.Wrap("token is empty")
}
- userID, exists = connContext.Query(WsUserID)
- if !exists {
- httpError(connContext, errs.ErrConnArgsErr)
- return
+ if v.UserID = query.Get(WsUserID); v.UserID == "" {
+ return nil, errs.ErrConnArgsErr.Wrap("sendID is empty")
}
- platformIDStr, exists = connContext.Query(PlatformID)
- if !exists {
- httpError(connContext, errs.ErrConnArgsErr)
- return
+ platformIDStr := query.Get(PlatformID)
+ if platformIDStr == "" {
+ return nil, errs.ErrConnArgsErr.Wrap("platformID is empty")
}
platformID, err := strconv.Atoi(platformIDStr)
if err != nil {
- httpError(connContext, errs.ErrConnArgsErr)
- return
+ return nil, errs.ErrConnArgsErr.Wrap("platformID is not int")
}
- if err = authverify.WsVerifyToken(token, userID, platformID); err != nil {
- httpError(connContext, err)
- return
+ v.PlatformID = platformID
+ if err = authverify.WsVerifyToken(v.Token, v.UserID, platformID); err != nil {
+ return nil, err
}
- m, err := ws.cache.GetTokensWithoutError(context.Background(), userID, platformID)
+ if query.Get(Compression) == GzipCompressionProtocol {
+ v.Compression = true
+ }
+ if r.Header.Get(Compression) == GzipCompressionProtocol {
+ v.Compression = true
+ }
+ m, err := ws.cache.GetTokensWithoutError(context.Background(), v.UserID, platformID)
if err != nil {
- httpError(connContext, err)
- return
+ return nil, err
}
- if v, ok := m[token]; ok {
+ if v, ok := m[v.Token]; ok {
switch v {
case constant.NormalToken:
case constant.KickedToken:
- httpError(connContext, errs.ErrTokenKicked.Wrap())
- return
+ return nil, errs.ErrTokenKicked.Wrap()
default:
- httpError(connContext, errs.ErrTokenUnknown.Wrap())
- return
+ return nil, errs.ErrTokenUnknown.Wrap(fmt.Sprintf("token status is %d", v))
}
} else {
- httpError(connContext, errs.ErrTokenNotExist.Wrap())
- return
+ return nil, errs.ErrTokenNotExist.Wrap()
}
+ return &v, nil
+}
- wsLongConn := newGWebSocket(WebSocket, ws.handshakeTimeout, ws.writeBufferSize)
- err = wsLongConn.GenerateLongConn(w, r)
- if err != nil {
- httpError(connContext, err)
- return
- }
- compressProtoc, exists := connContext.Query(Compression)
- if exists {
- if compressProtoc == GzipCompressionProtocol {
- compression = true
+type WSArgs struct {
+ Token string
+ UserID string
+ PlatformID int
+ Compression bool
+ MsgResp bool
+}
+
+func (ws *WsServer) wsHandler(w http.ResponseWriter, r *http.Request) {
+ connContext := newContext(w, r)
+ args, pErr := ws.ParseWSArgs(r)
+ var wsLongConn *GWebSocket
+ if args.MsgResp {
+ wsLongConn = newGWebSocket(WebSocket, ws.handshakeTimeout, ws.writeBufferSize)
+ if err := wsLongConn.GenerateLongConn(w, r); err != nil {
+ httpError(connContext, err)
+ return
}
- }
- compressProtoc, exists = connContext.GetHeader(Compression)
- if exists {
- if compressProtoc == GzipCompressionProtocol {
- compression = true
+ data, err := json.Marshal(apiresp.ParseError(pErr))
+ if err != nil {
+ _ = wsLongConn.Close()
+ return
+ }
+ if err := wsLongConn.WriteMessage(MessageText, data); err != nil {
+ _ = wsLongConn.Close()
+ return
+ }
+ if pErr != nil {
+ _ = wsLongConn.Close()
+ return
+ }
+ } else {
+ if pErr != nil {
+ httpError(connContext, pErr)
+ return
+ }
+ wsLongConn = newGWebSocket(WebSocket, ws.handshakeTimeout, ws.writeBufferSize)
+ if err := wsLongConn.GenerateLongConn(w, r); err != nil {
+ httpError(connContext, err)
+ return
}
}
client := ws.clientPool.Get().(*Client)
- client.ResetClient(connContext, wsLongConn, connContext.GetBackground(), compression, ws, token)
+ client.ResetClient(connContext, wsLongConn, connContext.GetBackground(), args.Compression, ws, args.Token)
ws.registerChan <- client
go client.readMessage()
}
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index a89800153..f9b73ad2b 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -476,13 +476,42 @@ func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGro
func (s *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGroupMemberListReq) (*pbgroup.GetGroupMemberListResp, error) {
resp := &pbgroup.GetGroupMemberListResp{}
- total, members, err := s.db.PageGetGroupMember(ctx, req.GroupID, req.Pagination)
+ var (
+ total int64
+ members []*relationtb.GroupMemberModel
+ err error
+ )
+ if req.Keyword == "" {
+ total, members, err = s.db.PageGetGroupMember(ctx, req.GroupID, req.Pagination)
+ } else {
+ members, err = s.db.FindGroupMemberAll(ctx, req.GroupID)
+ }
if err != nil {
return nil, err
}
if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
+ if req.Keyword != "" {
+ groupMembers := make([]*relationtb.GroupMemberModel, 0)
+ for _, member := range members {
+ if member.UserID == req.Keyword {
+ groupMembers = append(groupMembers, member)
+ total++
+ continue
+ }
+ if member.Nickname == req.Keyword {
+ groupMembers = append(groupMembers, member)
+ total++
+ continue
+ }
+ }
+
+ GMembers := utils.Paginate(groupMembers, int(req.Pagination.GetPageNumber()), int(req.Pagination.GetShowNumber()))
+ resp.Members = utils.Batch(convert.Db2PbGroupMember, GMembers)
+ resp.Total = uint32(total)
+ return resp, nil
+ }
resp.Total = uint32(total)
resp.Members = utils.Batch(convert.Db2PbGroupMember, members)
return resp, nil
@@ -1042,20 +1071,29 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq) (*pbgroup.GetGroupsResp, error) {
resp := &pbgroup.GetGroupsResp{}
var (
- groups []*relationtb.GroupModel
- err error
+ group []*relationtb.GroupModel
+ err error
)
if req.GroupID != "" {
- groups, err = s.db.FindGroup(ctx, []string{req.GroupID})
- resp.Total = uint32(len(groups))
+ group, err = s.db.FindGroup(ctx, []string{req.GroupID})
+ resp.Total = uint32(len(group))
} else {
var total int64
- total, groups, err = s.db.SearchGroup(ctx, req.GroupName, req.Pagination)
+ total, group, err = s.db.SearchGroup(ctx, req.GroupName, req.Pagination)
resp.Total = uint32(total)
}
if err != nil {
return nil, err
}
+
+ var groups []*relationtb.GroupModel
+ for _, v := range group {
+ if v.Status == constant.GroupStatusDismissed {
+ resp.Total--
+ continue
+ }
+ groups = append(groups, v)
+ }
groupIDs := utils.Slice(groups, func(e *relationtb.GroupModel) string {
return e.GroupID
})
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index 3295f18f6..4b11d625d 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -17,6 +17,7 @@ package user
import (
"context"
"errors"
+ "github.com/OpenIMSDK/tools/pagination"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"math/rand"
"strings"
@@ -58,6 +59,11 @@ type userServer struct {
RegisterCenter registry.SvcDiscoveryRegistry
}
+func (s *userServer) ProcessUserCommandGetAll(ctx context.Context, req *pbuser.ProcessUserCommandGetAllReq) (*pbuser.ProcessUserCommandGetAllResp, error) {
+ //TODO implement me
+ panic("implement me")
+}
+
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
rdb, err := cache.NewRedis()
if err != nil {
@@ -228,7 +234,7 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
}
func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPaginationUsersReq) (resp *pbuser.GetPaginationUsersResp, err error) {
- total, users, err := s.Page(ctx, req.Pagination)
+ total, users, err := s.PageFindUser(ctx, constant.IMOrdinaryUser, req.Pagination)
if err != nil {
return nil, err
}
@@ -384,6 +390,7 @@ func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.Proc
return nil, err
}
+
var value string
if req.Value != nil {
value = req.Value.Value
@@ -516,22 +523,23 @@ func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.Add
return nil, err
}
- var userID string
- for i := 0; i < 20; i++ {
- userId := s.genUserID()
- _, err := s.UserDatabase.FindWithError(ctx, []string{userId})
- if err == nil {
- continue
+ if req.UserID == "" {
+ for i := 0; i < 20; i++ {
+ userId := s.genUserID()
+ _, err := s.UserDatabase.FindWithError(ctx, []string{userId})
+ if err == nil {
+ continue
+ }
+ req.UserID = userId
+ break
+ }
+ if req.UserID == "" {
+ return nil, errs.ErrInternalServer.Wrap("gen user id failed")
}
- userID = userId
- break
- }
- if userID == "" {
- return nil, errs.ErrInternalServer.Wrap("gen user id failed")
}
user := &tablerelation.UserModel{
- UserID: userID,
+ UserID: req.UserID,
Nickname: req.NickName,
FaceURL: req.FaceURL,
CreateTime: time.Now(),
@@ -541,7 +549,11 @@ func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.Add
return nil, err
}
- return &pbuser.AddNotificationAccountResp{}, nil
+ return &pbuser.AddNotificationAccountResp{
+ UserID: req.UserID,
+ NickName: req.NickName,
+ FaceURL: req.FaceURL,
+ }, nil
}
func (s *userServer) UpdateNotificationAccountInfo(ctx context.Context, req *pbuser.UpdateNotificationAccountInfoReq) (*pbuser.UpdateNotificationAccountInfoResp, error) {
@@ -575,30 +587,33 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.
return nil, err
}
- if req.NickName != "" {
- users, err := s.UserDatabase.FindByNickname(ctx, req.NickName)
+ var users []*relation.UserModel
+ var err error
+ if req.Keyword != "" {
+ users, err = s.UserDatabase.Find(ctx, []string{req.Keyword})
if err != nil {
return nil, err
}
- resp := s.userModelToResp(users)
- return resp, nil
- }
-
- if req.UserID != "" {
- users, err := s.UserDatabase.Find(ctx, []string{req.UserID})
+ resp := s.userModelToResp(users, req.Pagination)
+ if resp.Total != 0 {
+ return resp, nil
+ }
+ users, err = s.UserDatabase.FindByNickname(ctx, req.Keyword)
if err != nil {
return nil, err
}
- resp := s.userModelToResp(users)
+ resp = s.userModelToResp(users, req.Pagination)
+ return resp, nil
+
return resp, nil
}
- _, users, err := s.UserDatabase.Page(ctx, req.Pagination)
+ users, err = s.UserDatabase.FindNotification(ctx, constant.AppNotificationAdmin)
if err != nil {
return nil, err
}
- resp := s.userModelToResp(users)
+ resp := s.userModelToResp(users, req.Pagination)
return resp, nil
}
@@ -632,11 +647,11 @@ func (s *userServer) genUserID() string {
return string(data)
}
-func (s *userServer) userModelToResp(users []*relation.UserModel) *pbuser.SearchNotificationAccountResp {
+func (s *userServer) userModelToResp(users []*relation.UserModel, pagination pagination.Pagination) *pbuser.SearchNotificationAccountResp {
accounts := make([]*pbuser.NotificationAccountInfo, 0)
var total int64
for _, v := range users {
- if v.AppMangerLevel == constant.AppNotificationAdmin || v.AppMangerLevel == constant.AppAdmin {
+ if v.AppMangerLevel == constant.AppNotificationAdmin && !utils.IsContain(v.UserID, config.Config.IMAdmin.UserID) {
temp := &pbuser.NotificationAccountInfo{
UserID: v.UserID,
FaceURL: v.FaceURL,
@@ -646,5 +661,8 @@ func (s *userServer) userModelToResp(users []*relation.UserModel) *pbuser.Search
total += 1
}
}
- return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: accounts}
+
+ notificationAccounts := utils.Paginate(accounts, int(pagination.GetPageNumber()), int(pagination.GetShowNumber()))
+
+ return &pbuser.SearchNotificationAccountResp{Total: total, NotificationAccounts: notificationAccounts}
}
diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go
index d9aa0dbb1..4c71224ee 100644
--- a/pkg/authverify/token.go
+++ b/pkg/authverify/token.go
@@ -38,6 +38,9 @@ func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
if utils.IsContain(opUserID, config.Config.Manager.UserID) {
return nil
}
+ if utils.IsContain(opUserID, config.Config.IMAdmin.UserID) {
+ return nil
+ }
if opUserID == ownerUserID {
return nil
}
@@ -45,13 +48,16 @@ func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
}
func IsAppManagerUid(ctx context.Context) bool {
- return utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID)
+ return utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) || utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID)
}
func CheckAdmin(ctx context.Context) error {
if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) {
return nil
}
+ if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.IMAdmin.UserID) {
+ return nil
+ }
return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx)))
}
func CheckIMAdmin(ctx context.Context) error {
@@ -69,7 +75,7 @@ func ParseRedisInterfaceToken(redisToken any) (*tokenverify.Claims, error) {
}
func IsManagerUserID(opUserID string) bool {
- return utils.IsContain(opUserID, config.Config.Manager.UserID)
+ return utils.IsContain(opUserID, config.Config.Manager.UserID) || utils.IsContain(opUserID, config.Config.IMAdmin.UserID)
}
func WsVerifyToken(token, userID string, platformID int) error {
diff --git a/pkg/common/config/version b/pkg/common/config/version
index e682ea429..4d0729e54 100644
--- a/pkg/common/config/version
+++ b/pkg/common/config/version
@@ -1 +1 @@
-v3.3.0
\ No newline at end of file
+v3.5.0
\ No newline at end of file
diff --git a/pkg/common/db/controller/conversation.go b/pkg/common/db/controller/conversation.go
index 2a0cb63e4..c6629e9c8 100644
--- a/pkg/common/db/controller/conversation.go
+++ b/pkg/common/db/controller/conversation.go
@@ -279,7 +279,7 @@ func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context,
for _, v := range existConversationUserIDs {
cache = cache.DelConversations(v, conversationID)
}
- return c.cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
})
}
diff --git a/pkg/common/db/controller/group.go b/pkg/common/db/controller/group.go
index 4147d59c0..decd868d6 100644
--- a/pkg/common/db/controller/group.go
+++ b/pkg/common/db/controller/group.go
@@ -197,7 +197,7 @@ func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data ma
func (g *groupDatabase) DismissGroup(ctx context.Context, groupID string, deleteMember bool) error {
return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
c := g.cache.NewCache()
- if err := g.groupDB.UpdateState(ctx, groupID, constant.GroupStatusDismissed); err != nil {
+ if err := g.groupDB.UpdateStatus(ctx, groupID, constant.GroupStatusDismissed); err != nil {
return err
}
if deleteMember {
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index d6fc91935..cedae5c97 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -40,6 +40,8 @@ type UserDatabase interface {
Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error)
// Find userInfo By Nickname
FindByNickname(ctx context.Context, nickname string) (users []*relation.UserModel, err error)
+ // Find notificationAccounts
+ FindNotification(ctx context.Context, level int64) (users []*relation.UserModel, err error)
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db
Create(ctx context.Context, users []*relation.UserModel) (err error)
// Update update (non-zero value) external guarantee userID exists
@@ -48,6 +50,8 @@ type UserDatabase interface {
UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
// Page If not found, no error is returned
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
+ // FindUser
+ PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
// IsExist true as long as one exists
IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
// GetAllUserID Get all user IDs
@@ -141,6 +145,11 @@ func (u *userDatabase) FindByNickname(ctx context.Context, nickname string) (use
return u.userDB.TakeByNickname(ctx, nickname)
}
+// Find notificationAccouts
+func (u *userDatabase) FindNotification(ctx context.Context, level int64) (users []*relation.UserModel, err error) {
+ return u.userDB.TakeNotification(ctx, level)
+}
+
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db.
func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) {
return u.tx.Transaction(ctx, func(ctx context.Context) error {
@@ -176,6 +185,10 @@ func (u *userDatabase) Page(ctx context.Context, pagination pagination.Paginatio
return u.userDB.Page(ctx, pagination)
}
+func (u *userDatabase) PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return u.userDB.PageFindUser(ctx, level, pagination)
+}
+
// IsExist Does userIDs exist? As long as there is one, it will be true.
func (u *userDatabase) IsExist(ctx context.Context, userIDs []string) (exist bool, err error) {
users, err := u.userDB.Find(ctx, userIDs)
diff --git a/pkg/common/db/mgo/group.go b/pkg/common/db/mgo/group.go
index 65dbbca59..a9c6d1eb8 100644
--- a/pkg/common/db/mgo/group.go
+++ b/pkg/common/db/mgo/group.go
@@ -49,8 +49,8 @@ func (g *GroupMgo) Create(ctx context.Context, groups []*relation.GroupModel) (e
return mgoutil.InsertMany(ctx, g.coll, groups)
}
-func (g *GroupMgo) UpdateState(ctx context.Context, groupID string, state int32) (err error) {
- return g.UpdateMap(ctx, groupID, map[string]any{"state": state})
+func (g *GroupMgo) UpdateStatus(ctx context.Context, groupID string, status int32) (err error) {
+ return g.UpdateMap(ctx, groupID, map[string]any{"status": status})
}
func (g *GroupMgo) UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error) {
diff --git a/pkg/common/db/mgo/group_member.go b/pkg/common/db/mgo/group_member.go
index 8c3041901..8e3dd1efa 100644
--- a/pkg/common/db/mgo/group_member.go
+++ b/pkg/common/db/mgo/group_member.go
@@ -51,7 +51,11 @@ func (g *GroupMemberMgo) Create(ctx context.Context, groupMembers []*relation.Gr
}
func (g *GroupMemberMgo) Delete(ctx context.Context, groupID string, userIDs []string) (err error) {
- return mgoutil.DeleteMany(ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
+ filter := bson.M{"group_id": groupID}
+ if len(userIDs) > 0 {
+ filter["user_id"] = bson.M{"$in": userIDs}
+ }
+ return mgoutil.DeleteMany(ctx, g.coll, filter)
}
func (g *GroupMemberMgo) UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error {
@@ -84,8 +88,8 @@ func (g *GroupMemberMgo) FindRoleLevelUserIDs(ctx context.Context, groupID strin
}
func (g *GroupMemberMgo) SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*relation.GroupMemberModel, err error) {
- //TODO implement me
- panic("implement me")
+ filter := bson.M{"group_id": groupID, "nickname": bson.M{"$regex": keyword}}
+ return mgoutil.FindPage[*relation.GroupMemberModel](ctx, g.coll, filter, pagination)
}
func (g *GroupMemberMgo) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
index 1e17bda30..b82966371 100644
--- a/pkg/common/db/mgo/user.go
+++ b/pkg/common/db/mgo/user.go
@@ -66,6 +66,10 @@ func (u *UserMgo) Take(ctx context.Context, userID string) (user *relation.UserM
return mgoutil.FindOne[*relation.UserModel](ctx, u.coll, bson.M{"user_id": userID})
}
+func (u *UserMgo) TakeNotification(ctx context.Context, level int64) (user []*relation.UserModel, err error) {
+ return mgoutil.Find[*relation.UserModel](ctx, u.coll, bson.M{"app_manger_level": level})
+}
+
func (u *UserMgo) TakeByNickname(ctx context.Context, nickname string) (user []*relation.UserModel, err error) {
return mgoutil.Find[*relation.UserModel](ctx, u.coll, bson.M{"nickname": nickname})
}
@@ -74,6 +78,10 @@ func (u *UserMgo) Page(ctx context.Context, pagination pagination.Pagination) (c
return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{}, pagination)
}
+func (u *UserMgo) PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{"app_manger_level": level}, pagination)
+}
+
func (u *UserMgo) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error) {
return mgoutil.FindPage[string](ctx, u.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"user_id": 1}))
}
diff --git a/pkg/common/db/table/relation/group.go b/pkg/common/db/table/relation/group.go
index bb1ddd878..57d6b1d62 100644
--- a/pkg/common/db/table/relation/group.go
+++ b/pkg/common/db/table/relation/group.go
@@ -42,7 +42,7 @@ type GroupModel struct {
type GroupModelInterface interface {
Create(ctx context.Context, groups []*GroupModel) (err error)
UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error)
- UpdateState(ctx context.Context, groupID string, state int32) (err error)
+ UpdateStatus(ctx context.Context, groupID string, status int32) (err error)
Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
Take(ctx context.Context, groupID string) (group *GroupModel, err error)
Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*GroupModel, err error)
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index d35d399a6..a1b4269d1 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -53,8 +53,10 @@ type UserModelInterface interface {
UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
Find(ctx context.Context, userIDs []string) (users []*UserModel, err error)
Take(ctx context.Context, userID string) (user *UserModel, err error)
+ TakeNotification(ctx context.Context, level int64) (user []*UserModel, err error)
TakeByNickname(ctx context.Context, nickname string) (user []*UserModel, err error)
Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
+ PageFindUser(ctx context.Context, level int64, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
Exist(ctx context.Context, userID string) (exist bool, err error)
GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error)
GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go
index 8cfb97a98..b8184d767 100644
--- a/pkg/common/db/unrelation/mongo.go
+++ b/pkg/common/db/unrelation/mongo.go
@@ -78,8 +78,8 @@ func buildMongoURI() string {
return config.Config.Mongo.Uri
}
- username := os.Getenv("MONGO_USERNAME")
- password := os.Getenv("MONGO_PASSWORD")
+ username := os.Getenv("MONGO_OPENIM_USERNAME")
+ password := os.Getenv("MONGO_OPENIM_PASSWORD")
address := os.Getenv("MONGO_ADDRESS")
port := os.Getenv("MONGO_PORT")
database := os.Getenv("MONGO_DATABASE")
@@ -103,9 +103,9 @@ func buildMongoURI() string {
maxPoolSize = fmt.Sprint(config.Config.Mongo.MaxPoolSize)
}
- uriFormat := "mongodb://%s/%s?maxPoolSize=%s&authSource=admin"
+ uriFormat := "mongodb://%s/%s?maxPoolSize=%s"
if username != "" && password != "" {
- uriFormat = "mongodb://%s:%s@%s/%s?maxPoolSize=%s&authSource=admin"
+ uriFormat = "mongodb://%s:%s@%s/%s?maxPoolSize=%s"
return fmt.Sprintf(uriFormat, username, password, address, database, maxPoolSize)
}
return fmt.Sprintf(uriFormat, address, database, maxPoolSize)
diff --git a/pkg/msgprocessor/conversation.go b/pkg/msgprocessor/conversation.go
index 56255f37c..7477bea7a 100644
--- a/pkg/msgprocessor/conversation.go
+++ b/pkg/msgprocessor/conversation.go
@@ -52,6 +52,7 @@ func GetChatConversationIDByMsg(msg *sdkws.MsgData) string {
case constant.NotificationChatType:
return "sn_" + msg.SendID + "_" + msg.RecvID
}
+
return ""
}
diff --git a/pkg/msgprocessor/options.go b/pkg/msgprocessor/options.go
index ea383a1af..c6e209b98 100644
--- a/pkg/msgprocessor/options.go
+++ b/pkg/msgprocessor/options.go
@@ -37,6 +37,7 @@ func NewOptions(opts ...OptionsOpt) Options {
for _, opt := range opts {
opt(options)
}
+
return options
}
diff --git a/pkg/rpcclient/user.go b/pkg/rpcclient/user.go
index de633ee30..451914cd3 100644
--- a/pkg/rpcclient/user.go
+++ b/pkg/rpcclient/user.go
@@ -64,6 +64,9 @@ func NewUserRpcClient(client discoveryregistry.SvcDiscoveryRegistry) UserRpcClie
// GetUsersInfo retrieves information for multiple users based on their user IDs.
func (u *UserRpcClient) GetUsersInfo(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error) {
+ if len(userIDs) == 0 {
+ return []*sdkws.UserInfo{}, nil
+ }
resp, err := u.Client.GetDesignateUsers(ctx, &user.GetDesignateUsersReq{
UserIDs: userIDs,
})
diff --git a/scripts/docker-start-all.sh b/scripts/docker-start-all.sh
index 3c83b02bb..2616b7bd1 100755
--- a/scripts/docker-start-all.sh
+++ b/scripts/docker-start-all.sh
@@ -36,4 +36,4 @@ sleep 5
"${OPENIM_ROOT}"/scripts/check-all.sh
-tail -f ${LOG_FILE}
\ No newline at end of file
+tail -f ${LOG_FILE}
diff --git a/scripts/genconfig.sh b/scripts/genconfig.sh
index 2371edc9d..8ded38b22 100755
--- a/scripts/genconfig.sh
+++ b/scripts/genconfig.sh
@@ -29,16 +29,8 @@ if [ $# -ne 2 ];then
exit 1
fi
-openim::util::require-dig
-result=$?
-if [ $result -ne 0 ]; then
- openim::log::info "Please install 'dig' to use this feature."
- openim::log::info "Installation instructions:"
- openim::log::info " For Ubuntu/Debian: sudo apt-get install dnsutils"
- openim::log::info " For CentOS/RedHat: sudo yum install bind-utils"
- openim::log::info " For macOS: 'dig' should be preinstalled. If missing, try: brew install bind"
- openim::log::info " For Windows: Install BIND9 tools from https://www.isc.org/download/"
- openim::log::error_exit "Error: 'dig' command is required but not installed."
+if [ -z "${OPENIM_IP}" ]; then
+ openim::util::require-dig
fi
source "${env_file}"
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index 47db34433..9afbb97c9 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright © 2023 OpenIM. All rights reserved.
+# Copyright © 2024 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,8 +13,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+#
+# OpenIM Docker Deployment Script
+#
+# This script automates the process of building the OpenIM server image
+# and deploying it using Docker Compose.
+#
+# Variables:
+# - SERVER_IMAGE_VERSION: Version of the server image (default: test)
+# - IMAGE_REGISTRY: Docker image registry (default: openim)
+# - DOCKER_COMPOSE_FILE_URL: URL to the docker-compose.yml file
+#
+# Usage:
+# SERVER_IMAGE_VERSION=latest IMAGE_REGISTRY=myregistry ./this_script.sh
-# Common utilities, variables and checks for all build scripts.
set -o errexit
set -o nounset
set -o pipefail
@@ -28,24 +40,45 @@ chmod +x "${OPENIM_ROOT}"/scripts/*.sh
openim::util::ensure_docker_daemon_connectivity
+# Default values for variables
+: ${SERVER_IMAGE_VERSION:=test}
+: ${IMAGE_REGISTRY:=openim}
+: ${DOCKER_COMPOSE_FILE_URL:="https://raw.githubusercontent.com/openimsdk/openim-docker/main/docker-compose.yaml"}
+
DOCKER_COMPOSE_COMMAND=
# Check if docker-compose command is available
openim::util::check_docker_and_compose_versions
-
-if command -v docker compose &> /dev/null
-then
+if command -v docker compose &> /dev/null; then
openim::log::info "docker compose command is available"
DOCKER_COMPOSE_COMMAND="docker compose"
else
DOCKER_COMPOSE_COMMAND="docker-compose"
fi
+export SERVER_IMAGE_VERSION
+export IMAGE_REGISTRY
"${OPENIM_ROOT}"/scripts/init-config.sh
+
pushd "${OPENIM_ROOT}"
+docker build -t "${IMAGE_REGISTRY}/openim-server:${SERVER_IMAGE_VERSION}" .
${DOCKER_COMPOSE_COMMAND} stop
-curl https://gitee.com/openimsdk/openim-docker/raw/main/example/full-openim-server-and-chat.yml -o docker-compose.yml
+curl "${DOCKER_COMPOSE_FILE_URL}" -o docker-compose.yml
${DOCKER_COMPOSE_COMMAND} up -d
-sleep 60
+
+# Function to check container status
+check_containers() {
+ if ! ${DOCKER_COMPOSE_COMMAND} ps | grep -q 'Up'; then
+ echo "Error: One or more docker containers failed to start."
+ ${DOCKER_COMPOSE_COMMAND} logs
+ return 1
+ fi
+ return 0
+}
+
+# Wait for a short period to allow containers to initialize
+sleep 30
+check_containers
+
${DOCKER_COMPOSE_COMMAND} logs openim-server
${DOCKER_COMPOSE_COMMAND} ps
diff --git a/scripts/install/dependency.sh b/scripts/install/dependency.sh
index bfa0909e2..78995bcf9 100755
--- a/scripts/install/dependency.sh
+++ b/scripts/install/dependency.sh
@@ -35,8 +35,8 @@ docker run -d \
-e MONGO_INITDB_ROOT_USERNAME=${OPENIM_USER} \
-e MONGO_INITDB_ROOT_PASSWORD=${PASSWORD} \
-e MONGO_INITDB_DATABASE=openIM \
- -e MONGO_USERNAME=${OPENIM_USER} \
- -e MONGO_PASSWORD=${PASSWORD} \
+ -e MONGO_OPENIM_USERNAME=${OPENIM_USER} \
+ -e MONGO_OPENIM_PASSWORD=${PASSWORD} \
--restart always \
mongo:6.0.2 --wiredTigerCacheSizeGB 1 --auth
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index 6021b7d48..3200d1cce 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -171,9 +171,14 @@ def "MONGO_URI" # MongoDB的URI
def "MONGO_PORT" "37017" # MongoDB的端口
def "MONGO_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # MongoDB的地址
def "MONGO_DATABASE" "${DATABASE_NAME}" # MongoDB的数据库名
-def "MONGO_USERNAME" "${OPENIM_USER}" # MongoDB的用户名
-# MongoDB的密码
+def "MONGO_USERNAME" "root" # MongoDB的管理员身份用户名
+# MongoDB的管理员身份密码
readonly MONGO_PASSWORD=${MONGO_PASSWORD:-"${PASSWORD}"}
+# Mongo OpenIM 身份用户名
+def "MONGO_OPENIM_USERNAME" "openIM"
+# Mongo OpenIM 身份密码
+readonly MONGO_OPENIM_PASSWORD=${MONGO_OPENIM_PASSWORD:-"${PASSWORD}"}
+
def "MONGO_MAX_POOL_SIZE" "100" # 最大连接池大小
###################### Object 配置信息 ######################
diff --git a/scripts/lib/util.sh b/scripts/lib/util.sh
index b8d76edeb..4de240972 100755
--- a/scripts/lib/util.sh
+++ b/scripts/lib/util.sh
@@ -1146,8 +1146,13 @@ function openim::util::require-jq {
# Checks whether dig is installed and provides installation instructions if it is not.
function openim::util::require-dig {
if ! command -v dig &>/dev/null; then
- openim::log::error "dig command not found."
- return 1
+ openim::log::error "Please install 'dig' to use this feature."
+ openim::log::error "Installation instructions:"
+ openim::log::error " For Ubuntu/Debian: sudo apt-get install dnsutils"
+ openim::log::error " For CentOS/RedHat: sudo yum install bind-utils"
+ openim::log::error " For macOS: 'dig' should be preinstalled. If missing, try: brew install bind"
+ openim::log::error " For Windows: Install BIND9 tools from https://www.isc.org/download/"
+ openim::log::error_exit "dig command not found."
fi
return 0
}
diff --git a/scripts/make-rules/common.mk b/scripts/make-rules/common.mk
index 81b44826b..c56f9f071 100644
--- a/scripts/make-rules/common.mk
+++ b/scripts/make-rules/common.mk
@@ -129,7 +129,7 @@ FIND := find . ! -path './utils/*' ! -path './vendor/*' ! -path './third_party/*
XARGS := xargs -r --no-run-if-empty
# Linux command settings-CODE DIRS Copyright
-CODE_DIRS := $(ROOT_DIR)/pkg $(ROOT_DIR)/cmd $(ROOT_DIR)/config $(ROOT_DIR)/.docker-compose_cfg $(ROOT_DIR)/internal $(ROOT_DIR)/scripts $(ROOT_DIR)/test $(ROOT_DIR)/.github $(ROOT_DIR)/build $(ROOT_DIR)/tools $(ROOT_DIR)/deployments
+CODE_DIRS := $(ROOT_DIR)/pkg $(ROOT_DIR)/cmd $(ROOT_DIR)/config $(ROOT_DIR)/internal $(ROOT_DIR)/scripts $(ROOT_DIR)/test $(ROOT_DIR)/.github $(ROOT_DIR)/build $(ROOT_DIR)/tools $(ROOT_DIR)/deployments
FINDS := find $(CODE_DIRS)
# Makefile settings: Select different behaviors by determining whether V option is set
diff --git a/scripts/mongo-init.sh b/scripts/mongo-init.sh
index 07d0e3d03..41d9ca0aa 100755
--- a/scripts/mongo-init.sh
+++ b/scripts/mongo-init.sh
@@ -12,15 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-mongo -- "$MONGO_INITDB_DATABASE" <