diff --git a/.dockerignore b/.dockerignore
index 705512401..263798e07 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -20,7 +20,6 @@ CHANGELOG/
# Ignore deployment-related files
docker-compose.yaml
-deployments/
# Ignore assets
assets/
diff --git a/.env b/.env
deleted file mode 100644
index 8213b9e3c..000000000
--- a/.env
+++ /dev/null
@@ -1,315 +0,0 @@
-# Copyright © 2023 OpenIM. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# ======================================
-# ========= Basic Configuration ========
-# ======================================
-
-# The user for authentication or system operations.
-# Default: USER=root
-USER=root
-
-# Password associated with the specified user for authentication.
-# Default: PASSWORD=openIM123
-PASSWORD=openIM123
-
-# Endpoint for the MinIO object storage service.
-# Default: MINIO_ENDPOINT=http://172.28.0.1:10005
-MINIO_ENDPOINT=http://172.28.0.1:10005
-
-# Base URL for the application programming interface (API).
-# Default: API_URL=http://172.28.0.1:10002
-API_URL=http://172.28.0.1:10002
-
-# Directory path for storing data files or related information.
-# Default: DATA_DIR=./
-DATA_DIR=./
-
-# Choose the appropriate image address, the default is GITHUB image,
-# you can choose docker hub, for Chinese users can choose Ali Cloud
-# export IMAGE_REGISTRY="ghcr.io/openimsdk"
-# export IMAGE_REGISTRY="openim"
-# export IMAGE_REGISTRY="registry.cn-hangzhou.aliyuncs.com/openimsdk"
-IMAGE_REGISTRY=ghcr.io/openimsdk
-
-# ======================================
-# ========= Network Configuration ======
-# ======================================
-
-# Subnet for the Docker network.
-# Default: DOCKER_BRIDGE_SUBNET=172.28.0.0/16
-DOCKER_BRIDGE_SUBNET=172.28.0.0/16
-
-# Gateway for the Docker network.
-# Default: DOCKER_BRIDGE_GATEWAY=172.28.0.1
-DOCKER_BRIDGE_GATEWAY=172.28.0.1
-
-# Address or hostname for the MySQL network.
-# Default: MYSQL_NETWORK_ADDRESS=172.28.0.2
-MYSQL_NETWORK_ADDRESS=172.28.0.2
-
-# Address or hostname for the MongoDB network.
-# Default: MONGO_NETWORK_ADDRESS=172.28.0.3
-MONGO_NETWORK_ADDRESS=172.28.0.3
-
-# Address or hostname for the Redis network.
-# Default: REDIS_NETWORK_ADDRESS=172.28.0.4
-REDIS_NETWORK_ADDRESS=172.28.0.4
-
-# Address or hostname for the Kafka network.
-# Default: KAFKA_NETWORK_ADDRESS=172.28.0.5
-KAFKA_NETWORK_ADDRESS=172.28.0.5
-
-# Address or hostname for the ZooKeeper network.
-# Default: ZOOKEEPER_NETWORK_ADDRESS=172.28.0.6
-ZOOKEEPER_NETWORK_ADDRESS=172.28.0.6
-
-# Address or hostname for the MinIO network.
-# Default: MINIO_NETWORK_ADDRESS=172.28.0.7
-MINIO_NETWORK_ADDRESS=172.28.0.7
-
-# Address or hostname for the OpenIM web network.
-# Default: OPENIM_WEB_NETWORK_ADDRESS=172.28.0.8
-OPENIM_WEB_NETWORK_ADDRESS=172.28.0.8
-
-# Address or hostname for the OpenIM server network.
-# Default: OPENIM_SERVER_NETWORK_ADDRESS=172.28.0.9
-OPENIM_SERVER_NETWORK_ADDRESS=172.28.0.9
-
-# Address or hostname for the OpenIM chat network.
-# Default: OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.10
-OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.10
-
-# Address or hostname for the Prometheus network.
-# Default: PROMETHEUS_NETWORK_ADDRESS=172.28.0.11
-PROMETHEUS_NETWORK_ADDRESS=172.28.0.11
-
-# Address or hostname for the Grafana network.
-# Default: GRAFANA_NETWORK_ADDRESS=172.28.0.12
-GRAFANA_NETWORK_ADDRESS=172.28.0.12
-
-# Address or hostname for the node_exporter network.
-# Default: NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.13
-NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.13
-
-# Address or hostname for the OpenIM admin network.
-# Default: OPENIM_ADMIN_NETWORK_ADDRESS=172.28.0.14
-OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=172.28.0.14
-
-# Address or hostname for the alertmanager network.
-# Default: ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.14
-ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.14
-# ===============================================
-# = Component Extension Configuration =
-# ===============================================
-
-# ============ Component Extension Configuration ==========
-# ----- ZooKeeper Configuration -----
-# Address or hostname for the ZooKeeper service.
-# Default: ZOOKEEPER_ADDRESS=172.28.0.1
-ZOOKEEPER_ADDRESS=172.28.0.6
-
-# Port for ZooKeeper service.
-# Default: ZOOKEEPER_PORT=12181
-ZOOKEEPER_PORT=12181
-
-# ----- MySQL Configuration -----
-
-# Address or hostname for the MySQL service.
-# Default: MYSQL_ADDRESS=172.28.0.1
-MYSQL_ADDRESS=172.28.0.2
-
-# Port on which MySQL database service is running.
-# Default: MYSQL_PORT=13306
-MYSQL_PORT=13306
-
-# Password to authenticate with the MySQL database service.
-# Default: MYSQL_PASSWORD=openIM123
-MYSQL_PASSWORD=openIM123
-
-# ----- MongoDB Configuration -----
-# Address or hostname for the MongoDB service.
-# Default: MONGO_ADDRESS=172.28.0.1
-MONGO_ADDRESS=172.28.0.3
-
-# Port on which MongoDB service is running.
-# Default: MONGO_PORT=37017
-MONGO_PORT=37017
-
-# Username to authenticate with the MongoDB service.
-# Default: MONGO_USERNAME=root
-MONGO_USERNAME=root
-
-# Password to authenticate with the MongoDB service.
-# Default: MONGO_PASSWORD=openIM123
-MONGO_PASSWORD=openIM123
-
-# Name of the database in MongoDB to be used.
-# Default: MONGO_DATABASE=openIM_v3
-MONGO_DATABASE=openIM_v3
-
-# ----- Redis Configuration -----
-# Address or hostname for the Redis service.
-# Default: REDIS_ADDRESS=172.28.0.1
-REDIS_ADDRESS=172.28.0.4
-
-# Port on which Redis in-memory data structure store is running.
-# Default: REDIS_PORT=16379
-REDIS_PORT=16379
-
-# Password to authenticate with the Redis service.
-# Default: REDIS_PASSWORD=openIM123
-REDIS_PASSWORD=openIM123
-
-# ----- Kafka Configuration -----
-# Address or hostname for the Kafka service.
-# Default: KAFKA_ADDRESS=172.28.0.1
-KAFKA_ADDRESS=172.28.0.5
-
-# Port on which Kafka distributed streaming platform is running.
-# Default: KAFKA_PORT=19092
-KAFKA_PORT=19094
-
-# Topic in Kafka for storing the latest messages in Redis.
-# Default: KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis
-KAFKA_LATESTMSG_REDIS_TOPIC=latestMsgToRedis
-
-# Topic in Kafka for pushing messages (e.g. notifications or updates).
-# Default: KAFKA_MSG_PUSH_TOPIC=msgToPush
-KAFKA_MSG_PUSH_TOPIC=msgToPush
-
-# Topic in Kafka for storing offline messages in MongoDB.
-# Default: KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql
-KAFKA_OFFLINEMSG_MONGO_TOPIC=offlineMsgToMongoMysql
-
-# ----- MinIO Configuration ----
-# Address or hostname for the MinIO object storage service.
-# Default: MINIO_ADDRESS=172.28.0.1
-MINIO_ADDRESS=172.28.0.7
-
-# Port on which MinIO object storage service is running.
-# Default: MINIO_PORT=10005
-MINIO_PORT=10005
-
-# Access key to authenticate with the MinIO service.
-# Default: MINIO_ACCESS_KEY=root
-MINIO_ACCESS_KEY=root
-
-# Secret key corresponding to the access key for MinIO authentication.
-# Default: MINIO_SECRET_KEY=openIM123
-MINIO_SECRET_KEY=openIM123
-
-# ----- Prometheus Configuration -----
-# Address or hostname for the Prometheus service.
-# Default: PROMETHEUS_ADDRESS=172.28.0.1
-PROMETHEUS_ADDRESS=172.28.0.11
-
-# Port on which Prometheus service is running.
-# Default: PROMETHEUS_PORT=19090
-PROMETHEUS_PORT=19090
-
-# ----- Grafana Configuration -----
-# Address or hostname for the Grafana service.
-# Default: GRAFANA_ADDRESS=172.28.0.1
-GRAFANA_ADDRESS=172.28.0.12
-
-# Port on which Grafana service is running.
-# Default: GRAFANA_PORT=3000
-GRAFANA_PORT=3000
-
-# ======================================
-# ============ OpenIM Web ===============
-# ======================================
-
-# Path to the OpenIM web distribution.
-# Default: OPENIM_WEB_DIST_PATH=/app/dist
-OPENIM_WEB_DIST_PATH=/app/dist
-
-# Port on which OpenIM web service is running.
-# Default: OPENIM_WEB_PORT=11001
-OPENIM_WEB_PORT=11001
-
-# Address or hostname for the OpenIM web service.
-# Default: OPENIM_WEB_ADDRESS=172.28.0.1
-OPENIM_WEB_ADDRESS=172.28.0.8
-
-# ======================================
-# ========= OpenIM Server ==============
-# ======================================
-
-# Address or hostname for the OpenIM server.
-# Default: OPENIM_SERVER_ADDRESS=172.28.0.1
-OPENIM_SERVER_ADDRESS=172.28.0.9
-
-# Port for the OpenIM WebSockets.
-# Default: OPENIM_WS_PORT=10001
-OPENIM_WS_PORT=10001
-
-# Port for the OpenIM API.
-# Default: API_OPENIM_PORT=10002
-API_OPENIM_PORT=10002
-
-
-# ======================================
-# ========== OpenIM Chat ===============
-# ======================================
-
-# Branch name for OpenIM chat.
-# Default: CHAT_BRANCH=main
-CHAT_BRANCH=main
-
-# Address or hostname for the OpenIM chat service.
-# Default: OPENIM_CHAT_ADDRESS=172.28.0.1
-OPENIM_CHAT_ADDRESS=172.28.0.10
-
-# Port for the OpenIM chat API.
-# Default: OPENIM_CHAT_API_PORT=10008
-OPENIM_CHAT_API_PORT=10008
-
-# Directory path for storing data files or related information for OpenIM chat.
-# Default: OPENIM_CHAT_DATA_DIR=./openim-chat/main
-OPENIM_CHAT_DATA_DIR=./openim-chat/main
-
-
-# ======================================
-# ========== OpenIM Admin ==============
-# ======================================
-
-# Branch name for OpenIM server.
-# Default: SERVER_BRANCH=main
-SERVER_BRANCH=main
-
-# Port for the OpenIM admin API.
-# Default: OPENIM_ADMIN_API_PORT=10009
-OPENIM_ADMIN_API_PORT=10009
-
-# Port for the node exporter.
-# Default: NODE_EXPORTER_PORT=19100
-NODE_EXPORTER_PORT=19100
-
-# Port for the prometheus.
-# Default: PROMETHEUS_PORT=19090
-PROMETHEUS_PORT=19090
-
-# Port for the grafana.
-# Default: GRAFANA_PORT=3000
-GRAFANA_PORT=3000
-
-# Port for the admin front.
-# Default: OPENIM_ADMIN_FRONT_PORT=11002
-OPENIM_ADMIN_FRONT_PORT=11002
-
-# Port for the alertmanager.
-# Default: ALERT_MANAGER_PORT=19093
-ALERT_MANAGER_PORT=19093
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index b16d614f6..2f6d7fe05 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -22,6 +22,9 @@ on:
# run e2e test every 4 hours
- cron: 0 */4 * * *
+env:
+ CALLBACK_ENABLE: true
+
jobs:
build:
name: Test
@@ -70,9 +73,9 @@ jobs:
- name: Docker Operations
run: |
- curl -o docker-compose.yml https://raw.githubusercontent.com/OpenIMSDK/openim-docker/main/example/basic-openim-server-dependency.yml
+ sudo make init
sudo docker compose up -d
- sudo sleep 60
+ sudo sleep 20
- name: Module Operations
run: |
diff --git a/.github/workflows/opencommit.yml b/.github/workflows/opencommit.yml
index 11bc00524..629a67aae 100644
--- a/.github/workflows/opencommit.yml
+++ b/.github/workflows/opencommit.yml
@@ -51,4 +51,5 @@ jobs:
OCO_EMOJI: false
OCO_MODEL: gpt-3.5-turbo-16k
OCO_LANGUAGE: en
- OCO_PROMPT_MODULE: conventional-commit
\ No newline at end of file
+ OCO_PROMPT_MODULE: conventional-commit
+ continue-on-error: true
\ No newline at end of file
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index 2e4cc9e24..5f010db8a 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -156,9 +156,9 @@ jobs:
- name: Docker Operations
run: |
- curl -o docker-compose.yml https://raw.githubusercontent.com/OpenIMSDK/openim-docker/main/example/basic-openim-server-dependency.yml
+ sudo make init
sudo docker compose up -d
- sudo sleep 60
+ sudo sleep 20
- name: Module Operations
run: |
@@ -195,4 +195,5 @@ jobs:
- name: Test Docker Build
run: |
+ sudo make init
sudo make image
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index fa1818e2b..675ce10c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -391,3 +391,5 @@ Sessionx.vim
dist/
.env
config/config.yaml
+config/alertmanager.yml
+config/prometheus.yml
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index f738d4457..32639af7a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -25,7 +25,8 @@ WORKDIR ${SERVER_WORKDIR}
# Copy scripts and binary files to the production image
COPY --from=builder ${OPENIM_SERVER_BINDIR} /openim/openim-server/_output/bin
-# COPY --from=builder ${OPENIM_SERVER_CMDDIR} /openim/openim-server/scripts
-# COPY --from=builder ${SERVER_WORKDIR}/config /openim/openim-server/config
+COPY --from=builder ${OPENIM_SERVER_CMDDIR} /openim/openim-server/scripts
+COPY --from=builder ${SERVER_WORKDIR}/config /openim/openim-server/config
+COPY --from=builder ${SERVER_WORKDIR}/deployments /openim/openim-server/deployments
CMD ["/openim/openim-server/scripts/docker-start-all.sh"]
diff --git a/config/alertmanager.yml b/config/alertmanager.yml
deleted file mode 100644
index ee14b6464..000000000
--- a/config/alertmanager.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-###################### AlertManager Configuration ######################
-# AlertManager configuration using environment variables
-#
-# Resolve timeout
-# SMTP configuration for sending alerts
-# Templates for email notifications
-# Routing configurations for alerts
-# Receiver configurations
-global:
- resolve_timeout: 5m
- smtp_from: alert@openim.io
- smtp_smarthost: smtp.163.com:465
- smtp_auth_username: alert@openim.io
- smtp_auth_password: YOURAUTHPASSWORD
- smtp_require_tls: false
- smtp_hello: xxx监控告警
-
-templates:
- - /etc/alertmanager/email.tmpl
-
-route:
- group_wait: 5s
- group_interval: 5s
- repeat_interval: 5m
- receiver: email
-receivers:
- - name: email
- email_configs:
- - to: '{EMAIL_TO:-'alert@example.com'}'
- html: '{{ template "email.to.html" . }}'
- headers: { Subject: "[OPENIM-SERVER]Alarm" }
- send_resolved: true
diff --git a/config/config.yaml b/config/config.yaml
deleted file mode 100644
index b17d10073..000000000
--- a/config/config.yaml
+++ /dev/null
@@ -1,409 +0,0 @@
-# Copyright © 2023 OpenIM. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the License);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# -----------------------------------------------------------------
-# TODO: This config file is the template file
-# --| source: deployments/templates/openim.yaml
-# --| env: scripts/install/environment
-# --| target: config/config.yaml
-# -----------------------------------------------------------------
-
-envs:
- discovery: zookeeper
-
-###################### Zookeeper ######################
-# Zookeeper configuration
-# It's not recommended to modify the schema
-#
-# Zookeeper address
-# Zookeeper username
-# Zookeeper password
-zookeeper:
- schema: openim
- address: [ 172.28.0.1:12181 ]
- username: ''
- password: ''
-
-###################### Mysql ######################
-# MySQL configuration
-# Currently, only single machine setup is supported
-#
-# Maximum number of open connections
-# Maximum number of idle connections
-# Maximum lifetime in seconds a connection can be reused
-# Log level: 1=slient, 2=error, 3=warn, 4=info
-# Slow query threshold in milliseconds
-mysql:
- address: [ 172.28.0.1:13306 ]
- username: root
- password: openIM123
- database: openIM_v3
- maxOpenConn: 1000
- maxIdleConn: 100
- maxLifeTime: 60
- logLevel: 4
- slowThreshold: 500
-
-###################### Mongo ######################
-# MongoDB configuration
-# If uri is not empty, it will be used directly
-#
-# MongoDB address for standalone setup, Mongos address for sharded cluster setup
-# Default MongoDB database name
-# Maximum connection pool size
-mongo:
- uri: ''
- address: [ 172.28.0.1:37017 ]
- database: openIM_v3
- username: root
- password: openIM123
- maxPoolSize: 100
-
-###################### Redis configuration information ######################
-# Redis configuration
-#
-# Username is required only for Redis version 6.0+
-redis:
- address: [ 172.28.0.1:16379 ]
- username: ''
- password: openIM123
-
-###################### Kafka configuration information ######################
-# Kafka configuration
-#
-# Kafka username
-# Kafka password
-# It's not recommended to modify this topic name
-# Consumer group ID, it's not recommended to modify
-kafka:
- username: ''
- password: ''
- addr: [ 172.28.0.1:19094 ]
- latestMsgToRedis:
- topic: "latestMsgToRedis"
- offlineMsgToMongo:
- topic: "offlineMsgToMongoMysql"
- msgToPush:
- topic: "msgToPush"
- consumerGroupID:
- msgToRedis: redis
- msgToMongo: mongo
- msgToMySql: mysql
- msgToPush: push
-
-###################### RPC configuration information ######################
-# RPC configuration
-#
-# IP address to register with zookeeper when starting RPC, the IP and corresponding rpcPort should be accessible by api/gateway
-# Default listen IP is 0.0.0.0
-rpc:
- registerIP: ''
- listenIP: 0.0.0.0
-
-###################### API configuration information ######################
-# API configuration
-#
-# API service port
-# Default listen IP is 0.0.0.0
-api:
- openImApiPort: [ 10002 ]
- listenIP: 0.0.0.0
-
-###################### Object configuration information ######################
-# Object storage configuration
-#
-# Use minio for object storage
-# API URL should be accessible by the app
-# It's not recommended to modify the bucket name
-# Endpoint should be accessible by the app
-# Session token
-# Configuration for Tencent COS
-# Configuration for Aliyun OSS
-# apiURL is the address of the api, the access address of the app, use s3 must be configured
-# minio.endpoint can be configured as an intranet address,
-# minio.signEndpoint is minio public network address
-object:
- enable: "minio"
- apiURL: "http://127.0.0.1:10002"
- minio:
- bucket: "openim"
- endpoint: "http://172.28.0.1:10005"
- accessKeyID: "root"
- secretAccessKey: "openIM123"
- sessionToken: ''
- signEndpoint: "http://127.0.0.1:10005"
- publicRead: false
- cos:
- bucketURL: https://temp-1252357374.cos.ap-chengdu.myqcloud.com
- secretID: ''
- secretKey: ''
- sessionToken: ''
- publicRead: false
- oss:
- endpoint: "https://oss-cn-chengdu.aliyuncs.com"
- bucket: "demo-9999999"
- bucketURL: "https://demo-9999999.oss-cn-chengdu.aliyuncs.com"
- accessKeyID: ''
- accessKeySecret: ''
- sessionToken: ''
- publicRead: false
- kodo:
- endpoint: "http://s3.cn-east-1.qiniucs.com"
- bucket: "demo-9999999"
- bucketURL: "http://your.domain.com"
- accessKeyID: ''
- accessKeySecret: ''
- sessionToken: ''
- publicRead: false
-###################### RPC Port Configuration ######################
-# RPC service ports
-# These ports are passed into the program by the script and are not recommended to modify
-# For launching multiple programs, just fill in multiple ports separated by commas
-# For example, [10110, 10111]
-rpcPort:
- openImUserPort: [ 10110 ]
- openImFriendPort: [ 10120 ]
- openImMessagePort: [ 10130 ]
- openImGroupPort: [ 10150 ]
- openImAuthPort: [ 10160 ]
- openImPushPort: [ 10170 ]
- openImConversationPort: [ 10180 ]
- openImThirdPort: [ 10190 ]
-
-###################### RPC Register Name Configuration ######################
-# RPC service names for registration, it's not recommended to modify these
-rpcRegisterName:
- openImUserName: User
- openImFriendName: Friend
- openImMsgName: Msg
- openImPushName: Push
- openImMessageGatewayName: MessageGateway
- openImGroupName: Group
- openImAuthName: Auth
- openImConversationName: Conversation
- openImThirdName: Third
-
-###################### Log Configuration ######################
-# Log configuration
-#
-# Storage directory
-# Log rotation time
-# Maximum number of logs to retain
-# Log level, 6 means all levels
-# Whether to output to stdout
-# Whether to output in json format
-# Whether to include stack trace in logs
-log:
- storageLocation: ../logs/
- rotationTime: 24
- remainRotationCount: 2
- remainLogLevel: 6
- isStdout: false
- isJson: false
- withStack: false
-
-###################### Variables definition ######################
-# Long connection server configuration
-#
-# Websocket port for msg_gateway
-# Maximum number of websocket connections
-# Maximum length of websocket request package
-# Websocket connection handshake timeout
-longConnSvr:
- openImWsPort: [ 10001 ]
- websocketMaxConnNum: 100000
- openImMessageGatewayPort: [ 10140 ]
- websocketMaxMsgLen: 4096
- websocketTimeout: 10
-
-# Push notification service configuration
-#
-# Use GeTui for push notifications
-# GeTui offline push configuration
-# FCM offline push configuration
-# Account file, place it in the config directory
-# JPush configuration, modify these after applying in JPush backend
-push:
- enable: getui
- geTui:
- pushUrl: "https://restapi.getui.com/v2/$appId"
- masterSecret: ''
- appKey: ''
- intent: ''
- channelID: ''
- channelName: ''
- fcm:
- serviceAccount: "x.json"
- jpns:
- appKey: ''
- masterSecret: ''
- pushUrl: ''
- pushIntent: ''
-
-# App manager configuration
-#
-# Built-in app manager user IDs
-# Built-in app manager nicknames
-manager:
- userID: [ "openIM123456", "openIM654321", "openIMAdmin" ]
- nickname: [ "system1", "system2", "system3" ]
-
-# Multi-platform login policy
-# For each platform(Android, iOS, Windows, Mac, web), only one can be online at a time
-multiLoginPolicy: 1
-
-# Whether to store messages in MySQL, messages in MySQL are only used for management background
-chatPersistenceMysql: true
-
-# Message cache timeout in seconds, it's not recommended to modify
-msgCacheTimeout: 86400
-
-# Whether to enable read receipts for group chat
-groupMessageHasReadReceiptEnable: true
-
-# Whether to enable read receipts for single chat
-singleMessageHasReadReceiptEnable: true
-
-# MongoDB offline message retention period in days
-retainChatRecords: 365
-
-# Schedule to clear expired messages(older than retainChatRecords days) in MongoDB every Wednesday at 2am
-# This deletion is just for cleaning up disk usage according to previous configuration retainChatRecords, no notification will be sent
-chatRecordsClearTime: "0 2 * * 3"
-
-# Schedule to auto delete messages every day at 2am
-# This deletion is for messages that have been retained for more than msg_destruct_time (seconds) in the conversation field
-msgDestructTime: "0 2 * * *"
-
-# Secret key
-secret: openIM123
-
-# Token policy
-#
-# Token expiration period in days
-tokenPolicy:
- expire: 90
-
-# Message verification policy
-#
-# Whether to verify friendship when sending messages
-messageVerify:
- friendVerify: false
-
-# iOS push notification configuration
-#
-# iOS push notification sound
-# Whether to count badge
-# Whether it's production environment
-iosPush:
- pushSound: "xxx"
- badgeCount: true
- production: false
-
-###################### Third-party service configuration ######################
-# Callback configuration
-#
-# Callback URL
-# Whether to enable this callback event
-# Timeout in seconds
-# Whether to continue execution if callback fails
-callback:
- url:
- beforeSendSingleMsg:
- enable: false
- timeout: 5
- failedContinue: true
- afterSendSingleMsg:
- enable: false
- timeout: 5
- beforeSendGroupMsg:
- enable: false
- timeout: 5
- failedContinue: true
- afterSendGroupMsg:
- enable: false
- timeout: 5
- msgModify:
- enable: false
- timeout: 5
- failedContinue: true
- userOnline:
- enable: false
- timeout: 5
- userOffline:
- enable: false
- timeout: 5
- userKickOff:
- enable: false
- timeout: 5
- offlinePush:
- enable: false
- timeout: 5
- failedContinue: true
- onlinePush:
- enable: false
- timeout: 5
- failedContinue: true
- superGroupOnlinePush:
- enable: false
- timeout: 5
- failedContinue: true
- beforeAddFriend:
- enable: false
- timeout: 5
- failedContinue: true
- beforeUpdateUserInfo:
- enable: false
- timeout: 5
- failedContinue: true
- beforeCreateGroup:
- enable: false
- timeout: 5
- failedContinue: true
- beforeMemberJoinGroup:
- enable: false
- timeout: 5
- failedContinue: true
- beforeInviteUserToGroup:
- enable: true
- timeout: 5
- failedContinue: true
- beforeSetGroupMemberInfo:
- enable: false
- timeout: 5
- failedContinue: true
- setMessageReactionExtensions:
- enable: false
- timeout: 5
- failedContinue: true
-
-###################### Prometheus ######################
-# Prometheus configuration for various services
-# The number of Prometheus ports per service needs to correspond to rpcPort
-# The number of ports needs to be consistent with msg_transfer_service_num in script/path_info.sh
-prometheus:
- enable: false
- prometheusUrl: "https://openim.prometheus"
- apiPrometheusPort: [20100]
- userPrometheusPort: [ 20110 ]
- friendPrometheusPort: [ 20120 ]
- messagePrometheusPort: [ 20130 ]
- messageGatewayPrometheusPort: [ 20140 ]
- groupPrometheusPort: [ 20150 ]
- authPrometheusPort: [ 20160 ]
- pushPrometheusPort: [ 20170 ]
- conversationPrometheusPort: [ 20230 ]
- rtcPrometheusPort: [ 21300 ]
- thirdPrometheusPort: [ 21301 ]
- messageTransferPrometheusPort: [ 21400, 21401, 21402, 21403 ] # List of ports
diff --git a/config/prometheus.yml b/config/prometheus.yml
deleted file mode 100644
index 7950c5d33..000000000
--- a/config/prometheus.yml
+++ /dev/null
@@ -1,85 +0,0 @@
-# my global config
-global:
- scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
- evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
- # scrape_timeout is set to the global default (10s).
-
-# Alertmanager configuration
-alerting:
- alertmanagers:
- - static_configs:
- - targets: ['172.28.0.1:19093']
-
-# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
-rule_files:
- - "instance-down-rules.yml"
-# - "first_rules.yml"
-# - "second_rules.yml"
-
-# A scrape configuration containing exactly one endpoint to scrape:
-# Here it's Prometheus itself.
-scrape_configs:
- # The job name is added as a label "job='job_name'"" to any timeseries scraped from this config.
- # Monitored information captured by prometheus
- - job_name: 'node-exporter'
- static_configs:
- - targets: [ '172.28.0.1:19100' ]
- labels:
- namespace: 'default'
-
- # prometheus fetches application services
- - job_name: 'openimserver-openim-api'
- static_configs:
- - targets: [ '172.28.0.1:20100' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-msggateway'
- static_configs:
- - targets: [ '172.28.0.1:20140' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-msgtransfer'
- static_configs:
- - targets: [ 172.28.0.1:21400, 172.28.0.1:21401, 172.28.0.1:21402, 172.28.0.1:21403 ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-push'
- static_configs:
- - targets: [ '172.28.0.1:20170' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-auth'
- static_configs:
- - targets: [ '172.28.0.1:20160' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-conversation'
- static_configs:
- - targets: [ '172.28.0.1:20230' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-friend'
- static_configs:
- - targets: [ '172.28.0.1:20120' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-group'
- static_configs:
- - targets: [ '172.28.0.1:20150' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-msg'
- static_configs:
- - targets: [ '172.28.0.1:20130' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-third'
- static_configs:
- - targets: [ '172.28.0.1:21301' ]
- labels:
- namespace: 'default'
- - job_name: 'openimserver-openim-rpc-user'
- static_configs:
- - targets: [ '172.28.0.1:20110' ]
- labels:
- namespace: 'default'
diff --git a/deployments/README.md b/deployments/README.md
index b24babb31..03f6d112b 100644
--- a/deployments/README.md
+++ b/deployments/README.md
@@ -154,8 +154,6 @@ GO111MODULE=on go get github.com/roboll/helmfile@latest
```
```bash
-export MYSQL_ADDRESS=im-mysql
-export MYSQL_PORT=3306
export MONGO_ADDRESS=im-mongo
export MONGO_PORT=27017
export REDIS_ADDRESS=im-redis-master
diff --git a/deployments/templates/chat.yaml b/deployments/templates/chat.yaml
index 3c3862bce..561d45d6e 100644
--- a/deployments/templates/chat.yaml
+++ b/deployments/templates/chat.yaml
@@ -53,19 +53,6 @@ rpcRegisterName:
openImAdminName: ${OPENIM_ADMIN_NAME}
openImChatName: ${OPENIM_CHAT_NAME}
-###################### MySQL ######################
-mysql:
- # address: [ 127.0.0.1:13306 ] #目前仅支持单机
- # username: root #用户名
- # password: openIM123 #密码
- # database: openIM_v2 #不建议修改
- # maxOpenConn: 1000 #最大连接数
- # maxIdleConn: 100 #最大空闲连接数
- # maxLifeTime: 60 #连接可以重复使用的最长时间(秒)
- # logLevel: 4 #日志级别 1=slient 2=error 3=warn 4=info
- # slowThreshold: 500 #慢语句阈值 (毫秒)
- database: openim_enterprise
-
###################### Log ######################
log:
storageLocation: ../logs/ #存放目录
diff --git a/deployments/templates/env_template.yaml b/deployments/templates/env_template.yaml
index 954b2cf65..4db838c8e 100644
--- a/deployments/templates/env_template.yaml
+++ b/deployments/templates/env_template.yaml
@@ -17,8 +17,8 @@
# ======================================
# The user for authentication or system operations.
-# Default: USER=root
-USER=${USER}
+# Default: OPENIM_USER=root
+USER=${OPENIM_USER}
# Password associated with the specified user for authentication.
# Default: PASSWORD=openIM123
@@ -55,61 +55,20 @@ DOCKER_BRIDGE_SUBNET=${DOCKER_BRIDGE_SUBNET}
# Default: DOCKER_BRIDGE_GATEWAY=172.28.0.1
DOCKER_BRIDGE_GATEWAY=${DOCKER_BRIDGE_GATEWAY}
-# Address or hostname for the MySQL network.
-# Default: MYSQL_NETWORK_ADDRESS=172.28.0.2
-MYSQL_NETWORK_ADDRESS=${MYSQL_NETWORK_ADDRESS}
-
-# Address or hostname for the MongoDB network.
-# Default: MONGO_NETWORK_ADDRESS=172.28.0.3
MONGO_NETWORK_ADDRESS=${MONGO_NETWORK_ADDRESS}
-
-# Address or hostname for the Redis network.
-# Default: REDIS_NETWORK_ADDRESS=172.28.0.4
REDIS_NETWORK_ADDRESS=${REDIS_NETWORK_ADDRESS}
-
-# Address or hostname for the Kafka network.
-# Default: KAFKA_NETWORK_ADDRESS=172.28.0.5
KAFKA_NETWORK_ADDRESS=${KAFKA_NETWORK_ADDRESS}
-
-# Address or hostname for the ZooKeeper network.
-# Default: ZOOKEEPER_NETWORK_ADDRESS=172.28.0.6
ZOOKEEPER_NETWORK_ADDRESS=${ZOOKEEPER_NETWORK_ADDRESS}
-
-# Address or hostname for the MinIO network.
-# Default: MINIO_NETWORK_ADDRESS=172.28.0.7
MINIO_NETWORK_ADDRESS=${MINIO_NETWORK_ADDRESS}
-
-# Address or hostname for the OpenIM web network.
-# Default: OPENIM_WEB_NETWORK_ADDRESS=172.28.0.8
OPENIM_WEB_NETWORK_ADDRESS=${OPENIM_WEB_NETWORK_ADDRESS}
-
-# Address or hostname for the OpenIM server network.
-# Default: OPENIM_SERVER_NETWORK_ADDRESS=172.28.0.9
OPENIM_SERVER_NETWORK_ADDRESS=${OPENIM_SERVER_NETWORK_ADDRESS}
-
-# Address or hostname for the OpenIM chat network.
-# Default: OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.10
OPENIM_CHAT_NETWORK_ADDRESS=${OPENIM_CHAT_NETWORK_ADDRESS}
-
-# Address or hostname for the Prometheus network.
-# Default: PROMETHEUS_NETWORK_ADDRESS=172.28.0.11
PROMETHEUS_NETWORK_ADDRESS=${PROMETHEUS_NETWORK_ADDRESS}
-
-# Address or hostname for the Grafana network.
-# Default: GRAFANA_NETWORK_ADDRESS=172.28.0.12
GRAFANA_NETWORK_ADDRESS=${GRAFANA_NETWORK_ADDRESS}
-
-# Address or hostname for the node_exporter network.
-# Default: NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.13
NODE_EXPORTER_NETWORK_ADDRESS=${NODE_EXPORTER_NETWORK_ADDRESS}
-
-# Address or hostname for the OpenIM admin network.
-# Default: OPENIM_ADMIN_NETWORK_ADDRESS=172.28.0.14
OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS}
-
-# Address or hostname for the alertmanager network.
-# Default: ALERT_MANAGER_NETWORK_ADDRESS=172.28.0.15
ALERT_MANAGER_NETWORK_ADDRESS=${ALERT_MANAGER_NETWORK_ADDRESS}
+
# ===============================================
# = Component Extension Configuration =
# ===============================================
@@ -124,20 +83,6 @@ ZOOKEEPER_ADDRESS=${ZOOKEEPER_NETWORK_ADDRESS}
# Default: ZOOKEEPER_PORT=12181
ZOOKEEPER_PORT=${ZOOKEEPER_PORT}
-# ----- MySQL Configuration -----
-
-# Address or hostname for the MySQL service.
-# Default: MYSQL_ADDRESS=172.28.0.1
-MYSQL_ADDRESS=${MYSQL_NETWORK_ADDRESS}
-
-# Port on which MySQL database service is running.
-# Default: MYSQL_PORT=13306
-MYSQL_PORT=${MYSQL_PORT}
-
-# Password to authenticate with the MySQL database service.
-# Default: MYSQL_PASSWORD=openIM123
-MYSQL_PASSWORD=${MYSQL_PASSWORD}
-
# ----- MongoDB Configuration -----
# Address or hostname for the MongoDB service.
# Default: MONGO_ADDRESS=172.28.0.1
diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml
index fc90bfc2f..d822fec13 100644
--- a/deployments/templates/openim.yaml
+++ b/deployments/templates/openim.yaml
@@ -35,26 +35,6 @@ zookeeper:
username: ${ZOOKEEPER_USERNAME}
password: ${ZOOKEEPER_PASSWORD}
-###################### Mysql ######################
-# MySQL configuration
-# Currently, only single machine setup is supported
-#
-# Maximum number of open connections
-# Maximum number of idle connections
-# Maximum lifetime in seconds a connection can be reused
-# Log level: 1=slient, 2=error, 3=warn, 4=info
-# Slow query threshold in milliseconds
-mysql:
- address: [ ${MYSQL_ADDRESS}:${MYSQL_PORT} ]
- username: ${MYSQL_USERNAME}
- password: ${MYSQL_PASSWORD}
- database: ${MYSQL_DATABASE}
- maxOpenConn: ${MYSQL_MAX_OPEN_CONN}
- maxIdleConn: ${MYSQL_MAX_IDLE_CONN}
- maxLifeTime: ${MYSQL_MAX_LIFETIME}
- logLevel: ${MYSQL_LOG_LEVEL}
- slowThreshold: ${MYSQL_SLOW_THRESHOLD}
-
###################### Mongo ######################
# MongoDB configuration
# If uri is not empty, it will be used directly
diff --git a/docker-compose.yml b/docker-compose.yml
index 1a6626add..233c8d492 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -11,21 +11,6 @@ networks:
gateway: '${DOCKER_BRIDGE_GATEWAY}'
services:
- mysql:
- image: mysql:5.7
- ports:
- - "${MYSQL_PORT}:3306"
- container_name: mysql
- volumes:
- - "${DATA_DIR}/components/mysql/data:/var/lib/mysql"
- - "/etc/localtime:/etc/localtime"
- environment:
- MYSQL_ROOT_PASSWORD: "${MYSQL_PASSWORD}"
- restart: always
- networks:
- server:
- ipv4_address: ${MYSQL_NETWORK_ADDRESS}
-
mongodb:
image: mongo:6.0.2
ports:
@@ -142,68 +127,68 @@ services:
server:
ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS}
- openim-admin:
- image: ${IMAGE_REGISTRY}/openim-admin-front:v3.4.0
- # image: ghcr.io/openimsdk/openim-admin-front:v3.4.0
- # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:v3.4.0
- # image: openim/openim-admin-front:v3.4.0
- container_name: openim-admin
- restart: always
- ports:
- - "${OPENIM_ADMIN_FRONT_PORT}:80"
- networks:
- server:
- ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS}
+ # openim-admin:
+ # image: ${IMAGE_REGISTRY}/openim-admin-front:v3.4.0
+ # # image: ghcr.io/openimsdk/openim-admin-front:v3.4.0
+ # # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:v3.4.0
+ # # image: openim/openim-admin-front:v3.4.0
+ # container_name: openim-admin
+ # restart: always
+ # ports:
+ # - "${OPENIM_ADMIN_FRONT_PORT}:80"
+ # networks:
+ # server:
+ # ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS}
- prometheus:
- image: prom/prometheus
- container_name: prometheus
- hostname: prometheus
- restart: always
- volumes:
- - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
- - ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml
- ports:
- - "${PROMETHEUS_PORT}:9090"
- networks:
- server:
- ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS}
+ # prometheus:
+ # image: prom/prometheus
+ # container_name: prometheus
+ # hostname: prometheus
+ # restart: always
+ # volumes:
+ # - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
+ # - ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml
+ # ports:
+ # - "${PROMETHEUS_PORT}:9090"
+ # networks:
+ # server:
+ # ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS}
- alertmanager:
- image: prom/alertmanager
- container_name: alertmanager
- hostname: alertmanager
- restart: always
- volumes:
- - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
- - ./config/email.tmpl:/etc/alertmanager/email.tmpl
- ports:
- - "${ALERT_MANAGER_PORT}:9093"
- networks:
- server:
- ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS}
+ # alertmanager:
+ # image: prom/alertmanager
+ # container_name: alertmanager
+ # hostname: alertmanager
+ # restart: always
+ # volumes:
+ # - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
+ # - ./config/email.tmpl:/etc/alertmanager/email.tmpl
+ # ports:
+ # - "${ALERT_MANAGER_PORT}:9093"
+ # networks:
+ # server:
+ # ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS}
- grafana:
- image: grafana/grafana
- container_name: grafana
- hostname: grafana
- user: root
- restart: always
- ports:
- - "${GRAFANA_PORT}:3000"
- volumes:
- - ${DATA_DIR}/components/grafana:/var/lib/grafana
- networks:
- server:
- ipv4_address: ${GRAFANA_NETWORK_ADDRESS}
+ # grafana:
+ # image: grafana/grafana
+ # container_name: grafana
+ # hostname: grafana
+ # user: root
+ # restart: always
+ # ports:
+ # - "${GRAFANA_PORT}:3000"
+ # volumes:
+ # - ${DATA_DIR}/components/grafana:/var/lib/grafana
+ # networks:
+ # server:
+ # ipv4_address: ${GRAFANA_NETWORK_ADDRESS}
- node-exporter:
- image: quay.io/prometheus/node-exporter
- container_name: node-exporter
- hostname: node-exporter
- restart: always
- ports:
- - "${NODE_EXPORTER_PORT}:9100"
- networks:
- server:
- ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS}
+ # node-exporter:
+ # image: quay.io/prometheus/node-exporter
+ # container_name: node-exporter
+ # hostname: node-exporter
+ # restart: always
+ # ports:
+ # - "${NODE_EXPORTER_PORT}:9100"
+ # networks:
+ # server:
+ # ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS}
diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS
index 95babf0d1..d1119eb61 100644
--- a/docs/CODEOWNERS
+++ b/docs/CODEOWNERS
@@ -2,28 +2,28 @@
# Each line is a file pattern followed by one or more owners.
# README files
-README.md @openimsdk/openim @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+README.md @openimsdk/openim @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# Contributing guidelines
-CONTRIBUTING.md @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+CONTRIBUTING.md @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# License files
-LICENSE @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+LICENSE @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# Makefile
-Makefile @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+Makefile @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
# @cubxxw and @openimsdk/bot will be requested for
# review when someone opens a pull request.
-* @openimsdk/openim @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+* @openimsdk/openim @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# Order is important; the last matching pattern takes the most
# precedence. When someone opens a pull request that only
# modifies JS files, only @js-owner and not the global
# owner(s) will be requested for a review.
-*.js @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+*.js @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# You can also use email addresses if you prefer. They'll be
# used to look up users just like we do for commit author
@@ -35,7 +35,7 @@ Makefile @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangch
# be identified in the format @org/team-name. Teams must have
# explicit write access to the repository. In this example,
# the OpenIMSDK team in the github organization owns all .txt files.
-*.txt @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @wangchuxiao-dev @withchao
+*.txt @cubxxw @openimsdk/bot @Bloomingg @FGadvancer @skiffer-git @rfyiamcool @withchao
# The `docs/*` pattern will match files like
# `docs/getting-started.md` but not further nested files like
diff --git a/docs/contrib/environment.md b/docs/contrib/environment.md
index 0279c750e..3dd090dcc 100644
--- a/docs/contrib/environment.md
+++ b/docs/contrib/environment.md
@@ -296,19 +296,6 @@ Feel free to explore the MinIO documentation for more advanced configurations an
| `ZOOKEEPER_USERNAME` | `""` | Username for Zookeeper. |
| `ZOOKEEPER_PASSWORD` | `""` | Password for Zookeeper. |
-### 2.6. MySQL Configuration
-
-**Description**: Configuration for MySQL, including port, address, and credentials.
-
-| Parameter | Example Value | Description |
-| ---------------- | ------------------------ | ------------------- |
-| `MYSQL_PORT` | `"13306"` | Port for MySQL. |
-| `MYSQL_ADDRESS` | Docker Bridge Gateway IP | Address for MySQL. |
-| `MYSQL_USERNAME` | User-defined | Username for MySQL. |
-| `MYSQL_PASSWORD` | User-defined | Password for MySQL. |
-
-Note: The configurations for other services (e.g., MONGO, REDIS, KAFKA, etc.) follow a similar pattern to MySQL and can be documented in a similar manner.
-
### 2.7. MongoDB Configuration
This section involves setting up MongoDB, including its port, address, and credentials.
diff --git a/go.mod b/go.mod
index cde9b2629..bdf7fbc14 100644
--- a/go.mod
+++ b/go.mod
@@ -10,10 +10,8 @@ require (
github.com/go-playground/validator/v10 v10.15.5
github.com/gogo/protobuf v1.3.2
github.com/golang-jwt/jwt/v4 v4.5.0
- github.com/golang/protobuf v1.5.3
github.com/gorilla/websocket v1.5.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
- github.com/jinzhu/copier v0.4.0
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
github.com/minio/minio-go/v7 v7.0.63
github.com/mitchellh/mapstructure v1.5.0
@@ -29,8 +27,6 @@ require (
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.31.0
gopkg.in/yaml.v3 v3.0.1
- gorm.io/driver/mysql v1.5.2
- gorm.io/gorm v1.25.5
)
require github.com/google/uuid v1.3.1
@@ -38,14 +34,13 @@ require github.com/google/uuid v1.3.1
require (
github.com/IBM/sarama v1.41.3
github.com/OpenIMSDK/protocol v0.0.31
- github.com/OpenIMSDK/tools v0.0.17
+ github.com/OpenIMSDK/tools v0.0.18
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/aws/aws-sdk-go-v2 v1.23.1
github.com/aws/aws-sdk-go-v2/config v1.25.4
github.com/aws/aws-sdk-go-v2/credentials v1.16.3
github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1
github.com/go-redis/redis v6.15.9+incompatible
- github.com/go-sql-driver/mysql v1.7.1
github.com/qiniu/go-sdk/v7 v7.18.2
github.com/redis/go-redis/v9 v9.2.1
github.com/tencentyun/cos-go-sdk-v5 v0.7.45
@@ -94,6 +89,7 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-zookeeper/zk v1.0.3 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
@@ -110,6 +106,7 @@ require (
github.com/jcmturner/gofork v1.7.6 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
+ github.com/jinzhu/copier v0.3.5 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@@ -152,7 +149,7 @@ require (
golang.org/x/arch v0.3.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
- golang.org/x/sys v0.13.0 // indirect
+ golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
@@ -162,6 +159,7 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
+ gorm.io/gorm v1.23.8 // indirect
)
require (
diff --git a/go.sum b/go.sum
index 11a0bdb80..7ed00c00c 100644
--- a/go.sum
+++ b/go.sum
@@ -496,8 +496,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
diff --git a/go.work b/go.work
index 1c819212c..63100b9f6 100644
--- a/go.work
+++ b/go.work
@@ -13,4 +13,5 @@ use (
./tools/component
./tools/url2im
./tools/data-conversion
+ ./tools/up35
)
diff --git a/install.sh b/install.sh
index 9318c33ba..7ff0f8739 100755
--- a/install.sh
+++ b/install.sh
@@ -63,7 +63,7 @@ PROXY=
GITHUB_TOKEN=
# Default user is "root". If you need to modify it, uncomment and replace accordingly.
-# USER=root
+# OPENIM_USER=root
# Default password for redis, mysql, mongo, as well as accessSecret in config/config.yaml.
# Remember, it should be a combination of 8 or more numbers and letters. If you want to set a different password, uncomment and replace "openIM123".
@@ -244,10 +244,10 @@ function download_source_code() {
function set_openim_env() {
warn "This command can only be executed once. It will modify the component passwords in docker-compose based on the PASSWORD variable in .env, and modify the component passwords in config/config.yaml. If the password in .env changes, you need to first execute docker-compose down; rm components -rf and then execute this command."
# Set default values for user input
- # If the USER environment variable is not set, it defaults to 'root'
- if [ -z "$USER" ]; then
- USER="root"
- debug "USER is not set. Defaulting to 'root'."
+ # If the OPENIM_USER environment variable is not set, it defaults to 'root'
+ if [ -z "$OPENIM_USER" ]; then
+ OPENIM_USER="root"
+ debug "OPENIM_USER is not set. Defaulting to 'root'."
fi
# If the PASSWORD environment variable is not set, it defaults to 'openIM123'
@@ -321,7 +321,7 @@ function cmd_help() {
function parseinput() {
# set default values
- # USER=root
+ # OPENIM_USER=root
# PASSWORD=openIM123
# ENDPOINT=http://127.0.0.1:10005
# API=http://127.0.0.1:10002/object/
@@ -347,7 +347,7 @@ function parseinput() {
;;
-u|--user)
shift
- USER=$1
+ OPENIM_USER=$1
;;
-p|--password)
shift
diff --git a/install_guide.sh b/install_guide.sh
index b10ab2edd..c4323d6a8 100755
--- a/install_guide.sh
+++ b/install_guide.sh
@@ -110,7 +110,7 @@ install_docker_compose() {
read NEW_USER
is_empty $NEW_USER
if [ $? -eq 0 ]; then
- USER=$NEW_USER
+ OPENIM_USER=$NEW_USER
fi
echo "Please input the password, default is openIM123, press enter to use default"
@@ -131,12 +131,12 @@ install_docker_compose() {
fi
set -e
export MINIO_ENDPOINT
- export USER
+ export OPENIM_USER
export PASSWORD
export DATA_DIR
cat < .env
-USER=${USER}
+OPENIM_USER=${OPENIM_USER}
PASSWORD=${PASSWORD}
MINIO_ENDPOINT=${MINIO_ENDPOINT}
DATA_DIR=${DATA_DIR}
diff --git a/internal/api/msg.go b/internal/api/msg.go
index 67b5f1eff..22182d985 100644
--- a/internal/api/msg.go
+++ b/internal/api/msg.go
@@ -150,7 +150,7 @@ func (m *MessageApi) DeleteMsgPhysical(c *gin.Context) {
}
func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendMsgReq *msg.SendMsgReq, err error) {
- var data interface{}
+ var data any
log.ZDebug(c, "getSendMsgReq", "req", req.Content)
switch req.ContentType {
case constant.Text:
diff --git a/internal/msggateway/encoder.go b/internal/msggateway/encoder.go
index 9791acb39..c5f1d00a8 100644
--- a/internal/msggateway/encoder.go
+++ b/internal/msggateway/encoder.go
@@ -22,8 +22,8 @@ import (
)
type Encoder interface {
- Encode(data interface{}) ([]byte, error)
- Decode(encodeData []byte, decodeData interface{}) error
+ Encode(data any) ([]byte, error)
+ Decode(encodeData []byte, decodeData any) error
}
type GobEncoder struct{}
@@ -32,7 +32,7 @@ func NewGobEncoder() *GobEncoder {
return &GobEncoder{}
}
-func (g *GobEncoder) Encode(data interface{}) ([]byte, error) {
+func (g *GobEncoder) Encode(data any) ([]byte, error) {
buff := bytes.Buffer{}
enc := gob.NewEncoder(&buff)
err := enc.Encode(data)
@@ -42,7 +42,7 @@ func (g *GobEncoder) Encode(data interface{}) ([]byte, error) {
return buff.Bytes(), nil
}
-func (g *GobEncoder) Decode(encodeData []byte, decodeData interface{}) error {
+func (g *GobEncoder) Decode(encodeData []byte, decodeData any) error {
buff := bytes.NewBuffer(encodeData)
dec := gob.NewDecoder(buff)
err := dec.Decode(decodeData)
diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go
index 5a061d7e1..737d5db14 100644
--- a/internal/msggateway/n_ws_server.go
+++ b/internal/msggateway/n_ws_server.go
@@ -49,7 +49,7 @@ type LongConnServer interface {
wsHandler(w http.ResponseWriter, r *http.Request)
GetUserAllCons(userID string) ([]*Client, bool)
GetUserPlatformCons(userID string, platform int) ([]*Client, bool, bool)
- Validate(s interface{}) error
+ Validate(s any) error
SetCacheHandler(cache cache.MsgModel)
SetDiscoveryRegistry(client discoveryregistry.SvcDiscoveryRegistry)
KickUserConn(client *Client) error
@@ -60,6 +60,12 @@ type LongConnServer interface {
MessageHandler
}
+var bufferPool = sync.Pool{
+ New: func() any {
+ return make([]byte, 1024)
+ },
+}
+
type WsServer struct {
port int
wsMaxConnNum int64
@@ -120,7 +126,7 @@ func (ws *WsServer) UnRegister(c *Client) {
ws.unregisterChan <- c
}
-func (ws *WsServer) Validate(s interface{}) error {
+func (ws *WsServer) Validate(s any) error {
//?question?
return nil
}
@@ -145,7 +151,7 @@ func NewWsServer(opts ...Option) (*WsServer, error) {
writeBufferSize: config.writeBufferSize,
handshakeTimeout: config.handshakeTimeout,
clientPool: sync.Pool{
- New: func() interface{} {
+ New: func() any {
return new(Client)
},
},
diff --git a/internal/msgtransfer/init.go b/internal/msgtransfer/init.go
index 8436317ee..a8d10799f 100644
--- a/internal/msgtransfer/init.go
+++ b/internal/msgtransfer/init.go
@@ -17,21 +17,20 @@ package msgtransfer
import (
"errors"
"fmt"
+ "log"
+ "net/http"
+ "sync"
+
"github.com/OpenIMSDK/tools/mw"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
- "log"
- "net/http"
- "sync"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
@@ -39,20 +38,12 @@ import (
)
type MsgTransfer struct {
- persistentCH *PersistentConsumerHandler // 聊天记录持久化到mysql的消费者 订阅的topic: ws2ms_chat
historyCH *OnlineHistoryRedisConsumerHandler // 这个消费者聚合消息, 订阅的topic:ws2ms_chat, 修改通知发往msg_to_modify topic, 消息存入redis后Incr Redis, 再发消息到ms2pschat topic推送, 发消息到msg_to_mongo topic持久化
historyMongoCH *OnlineHistoryMongoConsumerHandler // mongoDB批量插入, 成功后删除redis中消息,以及处理删除通知消息删除的 订阅的topic: msg_to_mongo
// modifyCH *ModifyMsgConsumerHandler // 负责消费修改消息通知的consumer, 订阅的topic: msg_to_modify
}
func StartTransfer(prometheusPort int) error {
- db, err := relation.NewGormDB()
- if err != nil {
- return err
- }
- if err := db.AutoMigrate(&relationtb.ChatLogModel{}); err != nil {
- fmt.Printf("gorm: AutoMigrate ChatLogModel err: %v\n", err)
- }
rdb, err := cache.NewRedis()
if err != nil {
return err
@@ -78,21 +69,16 @@ func StartTransfer(prometheusPort int) error {
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
msgModel := cache.NewMsgCacheModel(rdb)
msgDocModel := unrelation.NewMsgMongoDriver(mongo.GetDatabase())
- msgMysModel := relation.NewChatLogGorm(db)
- chatLogDatabase := controller.NewChatLogDatabase(msgMysModel)
msgDatabase := controller.NewCommonMsgDatabase(msgDocModel, msgModel)
conversationRpcClient := rpcclient.NewConversationRpcClient(client)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
- msgTransfer := NewMsgTransfer(chatLogDatabase, msgDatabase, &conversationRpcClient, &groupRpcClient)
+ msgTransfer := NewMsgTransfer(msgDatabase, &conversationRpcClient, &groupRpcClient)
return msgTransfer.Start(prometheusPort)
}
-func NewMsgTransfer(chatLogDatabase controller.ChatLogDatabase,
- msgDatabase controller.CommonMsgDatabase,
- conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient,
-) *MsgTransfer {
+func NewMsgTransfer(msgDatabase controller.CommonMsgDatabase, conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient) *MsgTransfer {
return &MsgTransfer{
- persistentCH: NewPersistentConsumerHandler(chatLogDatabase), historyCH: NewOnlineHistoryRedisConsumerHandler(msgDatabase, conversationRpcClient, groupRpcClient),
+ historyCH: NewOnlineHistoryRedisConsumerHandler(msgDatabase, conversationRpcClient, groupRpcClient),
historyMongoCH: NewOnlineHistoryMongoConsumerHandler(msgDatabase),
}
}
diff --git a/internal/msgtransfer/online_history_msg_handler.go b/internal/msgtransfer/online_history_msg_handler.go
index eb8e500fe..127cede71 100644
--- a/internal/msgtransfer/online_history_msg_handler.go
+++ b/internal/msgtransfer/online_history_msg_handler.go
@@ -61,7 +61,7 @@ type TriggerChannelValue struct {
type Cmd2Value struct {
Cmd int
- Value interface{}
+ Value any
}
type ContextMsg struct {
message *sdkws.MsgData
diff --git a/internal/msgtransfer/persistent_msg_handler.go b/internal/msgtransfer/persistent_msg_handler.go
deleted file mode 100644
index d105de2fe..000000000
--- a/internal/msgtransfer/persistent_msg_handler.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package msgtransfer
-
-import (
- "context"
-
- "github.com/OpenIMSDK/protocol/constant"
- pbmsg "github.com/OpenIMSDK/protocol/msg"
- "github.com/OpenIMSDK/tools/log"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/config"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- kfk "github.com/openimsdk/open-im-server/v3/pkg/common/kafka"
-
- "github.com/IBM/sarama"
- "google.golang.org/protobuf/proto"
-)
-
-type PersistentConsumerHandler struct {
- persistentConsumerGroup *kfk.MConsumerGroup
- chatLogDatabase controller.ChatLogDatabase
-}
-
-func NewPersistentConsumerHandler(database controller.ChatLogDatabase) *PersistentConsumerHandler {
- return &PersistentConsumerHandler{
- persistentConsumerGroup: kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{
- KafkaVersion: sarama.V2_0_0_0,
- OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
- }, []string{config.Config.Kafka.LatestMsgToRedis.Topic},
- config.Config.Kafka.Addr, config.Config.Kafka.ConsumerGroupID.MsgToMySql),
- chatLogDatabase: database,
- }
-}
-
-func (pc *PersistentConsumerHandler) handleChatWs2Mysql(
- ctx context.Context,
- cMsg *sarama.ConsumerMessage,
- msgKey string,
- _ sarama.ConsumerGroupSession,
-) {
- msg := cMsg.Value
- var tag bool
- msgFromMQ := pbmsg.MsgDataToMQ{}
- err := proto.Unmarshal(msg, &msgFromMQ)
- if err != nil {
- log.ZError(ctx, "msg_transfer Unmarshal msg err", err)
- return
- }
-
- log.ZDebug(ctx, "handleChatWs2Mysql", "msg", msgFromMQ.MsgData)
- // Control whether to store history messages (mysql)
- isPersist := utils.GetSwitchFromOptions(msgFromMQ.MsgData.Options, constant.IsPersistent)
- // Only process receiver data
- if isPersist {
- switch msgFromMQ.MsgData.SessionType {
- case constant.SingleChatType, constant.NotificationChatType:
- if msgKey == msgFromMQ.MsgData.RecvID {
- tag = true
- }
- case constant.GroupChatType:
- if msgKey == msgFromMQ.MsgData.SendID {
- tag = true
- }
- case constant.SuperGroupChatType:
- tag = true
- }
- if tag {
- log.ZInfo(ctx, "msg_transfer msg persisting", "msg", string(msg))
- if err = pc.chatLogDatabase.CreateChatLog(&msgFromMQ); err != nil {
- log.ZError(ctx, "Message insert failed", err, "msg", msgFromMQ.String())
- return
- }
- }
- }
-}
-func (PersistentConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
-func (PersistentConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
-
-func (pc *PersistentConsumerHandler) ConsumeClaim(
- sess sarama.ConsumerGroupSession,
- claim sarama.ConsumerGroupClaim,
-) error {
- for msg := range claim.Messages() {
- ctx := pc.persistentConsumerGroup.GetContextFromMsg(msg)
- log.ZDebug(
- ctx,
- "kafka get info to mysql",
- "msgTopic",
- msg.Topic,
- "msgPartition",
- msg.Partition,
- "msg",
- string(msg.Value),
- "key",
- string(msg.Key),
- )
- if len(msg.Value) != 0 {
- pc.handleChatWs2Mysql(ctx, msg, string(msg.Key), sess)
- } else {
- log.ZError(ctx, "msg get from kafka but is nil", nil, "key", msg.Key)
- }
- sess.MarkMessage(msg, "")
- }
- return nil
-}
diff --git a/internal/push/offlinepush/getui/body.go b/internal/push/offlinepush/getui/body.go
index 218ed67b4..01eb22e73 100644
--- a/internal/push/offlinepush/getui/body.go
+++ b/internal/push/offlinepush/getui/body.go
@@ -21,9 +21,9 @@ import (
)
type Resp struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
- Data interface{} `json:"data"`
+ Code int `json:"code"`
+ Msg string `json:"msg"`
+ Data any `json:"data"`
}
func (r *Resp) parseError() (err error) {
diff --git a/internal/push/offlinepush/getui/push.go b/internal/push/offlinepush/getui/push.go
index 1fd65647d..b657c9c23 100644
--- a/internal/push/offlinepush/getui/push.go
+++ b/internal/push/offlinepush/getui/push.go
@@ -159,7 +159,7 @@ func (g *Client) singlePush(ctx context.Context, token, userID string, pushReq P
return g.request(ctx, pushURL, pushReq, token, nil)
}
-func (g *Client) request(ctx context.Context, url string, input interface{}, token string, output interface{}) error {
+func (g *Client) request(ctx context.Context, url string, input any, token string, output any) error {
header := map[string]string{"token": token}
resp := &Resp{}
resp.Data = output
@@ -170,7 +170,7 @@ func (g *Client) postReturn(
ctx context.Context,
url string,
header map[string]string,
- input interface{},
+ input any,
output RespI,
timeout int,
) error {
diff --git a/internal/push/offlinepush/jpush/body/audience.go b/internal/push/offlinepush/jpush/body/audience.go
index f29930886..43a7148b8 100644
--- a/internal/push/offlinepush/jpush/body/audience.go
+++ b/internal/push/offlinepush/jpush/body/audience.go
@@ -23,7 +23,7 @@ const (
)
type Audience struct {
- Object interface{}
+ Object any
audience map[string][]string
}
diff --git a/internal/push/offlinepush/jpush/body/message.go b/internal/push/offlinepush/jpush/body/message.go
index 670cd4c78..e885d1d69 100644
--- a/internal/push/offlinepush/jpush/body/message.go
+++ b/internal/push/offlinepush/jpush/body/message.go
@@ -15,10 +15,10 @@
package body
type Message struct {
- MsgContent string `json:"msg_content"`
- Title string `json:"title,omitempty"`
- ContentType string `json:"content_type,omitempty"`
- Extras map[string]interface{} `json:"extras,omitempty"`
+ MsgContent string `json:"msg_content"`
+ Title string `json:"title,omitempty"`
+ ContentType string `json:"content_type,omitempty"`
+ Extras map[string]any `json:"extras,omitempty"`
}
func (m *Message) SetMsgContent(c string) {
@@ -33,9 +33,9 @@ func (m *Message) SetContentType(c string) {
m.ContentType = c
}
-func (m *Message) SetExtras(key string, value interface{}) {
+func (m *Message) SetExtras(key string, value any) {
if m.Extras == nil {
- m.Extras = make(map[string]interface{})
+ m.Extras = make(map[string]any)
}
m.Extras[key] = value
}
diff --git a/internal/push/offlinepush/jpush/body/platform.go b/internal/push/offlinepush/jpush/body/platform.go
index 9de2b8711..1ef136f2c 100644
--- a/internal/push/offlinepush/jpush/body/platform.go
+++ b/internal/push/offlinepush/jpush/body/platform.go
@@ -29,7 +29,7 @@ const (
)
type Platform struct {
- Os interface{}
+ Os any
osArry []string
}
diff --git a/internal/push/offlinepush/jpush/body/pushobj.go b/internal/push/offlinepush/jpush/body/pushobj.go
index c8c112f69..3dc133d0a 100644
--- a/internal/push/offlinepush/jpush/body/pushobj.go
+++ b/internal/push/offlinepush/jpush/body/pushobj.go
@@ -15,11 +15,11 @@
package body
type PushObj struct {
- Platform interface{} `json:"platform"`
- Audience interface{} `json:"audience"`
- Notification interface{} `json:"notification,omitempty"`
- Message interface{} `json:"message,omitempty"`
- Options interface{} `json:"options,omitempty"`
+ Platform any `json:"platform"`
+ Audience any `json:"audience"`
+ Notification any `json:"notification,omitempty"`
+ Message any `json:"message,omitempty"`
+ Options any `json:"options,omitempty"`
}
func (p *PushObj) SetPlatform(pf *Platform) {
diff --git a/internal/push/offlinepush/jpush/push.go b/internal/push/offlinepush/jpush/push.go
index 44de7ff65..567269f3c 100644
--- a/internal/push/offlinepush/jpush/push.go
+++ b/internal/push/offlinepush/jpush/push.go
@@ -69,11 +69,11 @@ func (j *JPush) Push(ctx context.Context, userIDs []string, title, content strin
pushObj.SetNotification(&no)
pushObj.SetMessage(&msg)
pushObj.SetOptions(&opt)
- var resp interface{}
+ var resp any
return j.request(ctx, pushObj, resp, 5)
}
-func (j *JPush) request(ctx context.Context, po body.PushObj, resp interface{}, timeout int) error {
+func (j *JPush) request(ctx context.Context, po body.PushObj, resp any, timeout int) error {
return http2.PostReturn(
ctx,
config.Config.Push.Jpns.PushUrl,
diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go
index 75a1c1380..2ee8c457f 100644
--- a/internal/push/push_to_client.go
+++ b/internal/push/push_to_client.go
@@ -133,7 +133,7 @@ func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.Msg
return nil
}
-func (p *Pusher) UnmarshalNotificationElem(bytes []byte, t interface{}) error {
+func (p *Pusher) UnmarshalNotificationElem(bytes []byte, t any) error {
var notification sdkws.NotificationElem
if err := json.Unmarshal(bytes, ¬ification); err != nil {
return err
diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go
index d39881b35..88c9ff7ff 100644
--- a/internal/rpc/conversation/conversaion.go
+++ b/internal/rpc/conversation/conversaion.go
@@ -16,6 +16,12 @@ package conversation
import (
"context"
+ "errors"
+
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"google.golang.org/grpc"
@@ -24,13 +30,11 @@ import (
"github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
- "github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
@@ -43,24 +47,24 @@ type conversationServer struct {
}
func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
- db, err := relation.NewGormDB()
+ rdb, err := cache.NewRedis()
if err != nil {
return err
}
- if err := db.AutoMigrate(&tablerelation.ConversationModel{}); err != nil {
+ mongo, err := unrelation.NewMongo()
+ if err != nil {
return err
}
- rdb, err := cache.NewRedis()
+ conversationDB, err := mgo.NewConversationMongo(mongo.GetDatabase())
if err != nil {
return err
}
- conversationDB := relation.NewConversationGorm(db)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)
pbconversation.RegisterConversationServer(server, &conversationServer{
conversationNotificationSender: notification.NewConversationNotificationSender(&msgRpcClient),
groupRpcClient: &groupRpcClient,
- conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx.NewGorm(db)),
+ conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx.NewMongo(mongo.GetClient())),
})
return nil
}
@@ -145,7 +149,7 @@ func (c *conversationServer) SetConversations(ctx context.Context,
conversation.ConversationType = req.Conversation.ConversationType
conversation.UserID = req.Conversation.UserID
conversation.GroupID = req.Conversation.GroupID
- m := make(map[string]interface{})
+ m := make(map[string]any)
if req.Conversation.RecvMsgOpt != nil {
m["recv_msg_opt"] = req.Conversation.RecvMsgOpt.Value
if req.Conversation.RecvMsgOpt.Value != conv.RecvMsgOpt {
@@ -229,11 +233,12 @@ func (c *conversationServer) SetConversations(ctx context.Context,
// 获取超级大群开启免打扰的用户ID.
func (c *conversationServer) GetRecvMsgNotNotifyUserIDs(ctx context.Context, req *pbconversation.GetRecvMsgNotNotifyUserIDsReq) (*pbconversation.GetRecvMsgNotNotifyUserIDsResp, error) {
- userIDs, err := c.conversationDatabase.FindRecvMsgNotNotifyUserIDs(ctx, req.GroupID)
- if err != nil {
- return nil, err
- }
- return &pbconversation.GetRecvMsgNotNotifyUserIDsResp{UserIDs: userIDs}, nil
+ //userIDs, err := c.conversationDatabase.FindRecvMsgNotNotifyUserIDs(ctx, req.GroupID)
+ //if err != nil {
+ // return nil, err
+ //}
+ //return &pbconversation.GetRecvMsgNotNotifyUserIDsResp{UserIDs: userIDs}, nil
+ return nil, errors.New("deprecated")
}
// create conversation without notification for msg redis transfer.
@@ -284,7 +289,7 @@ func (c *conversationServer) CreateGroupChatConversations(ctx context.Context, r
func (c *conversationServer) SetConversationMaxSeq(ctx context.Context, req *pbconversation.SetConversationMaxSeqReq) (*pbconversation.SetConversationMaxSeqResp, error) {
if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, req.OwnerUserID, req.ConversationID,
- map[string]interface{}{"max_seq": req.MaxSeq}); err != nil {
+ map[string]any{"max_seq": req.MaxSeq}); err != nil {
return nil, err
}
return &pbconversation.SetConversationMaxSeqResp{}, nil
diff --git a/internal/rpc/friend/black.go b/internal/rpc/friend/black.go
index fee2d5480..54cdbb2cc 100644
--- a/internal/rpc/friend/black.go
+++ b/internal/rpc/friend/black.go
@@ -27,19 +27,11 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
-func (s *friendServer) GetPaginationBlacks(
- ctx context.Context,
- req *pbfriend.GetPaginationBlacksReq,
-) (resp *pbfriend.GetPaginationBlacksResp, err error) {
+func (s *friendServer) GetPaginationBlacks(ctx context.Context, req *pbfriend.GetPaginationBlacksReq) (resp *pbfriend.GetPaginationBlacksResp, err error) {
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
- var pageNumber, showNumber int32
- if req.Pagination != nil {
- pageNumber = req.Pagination.PageNumber
- showNumber = req.Pagination.ShowNumber
- }
- blacks, total, err := s.blackDatabase.FindOwnerBlacks(ctx, req.UserID, pageNumber, showNumber)
+ total, blacks, err := s.blackDatabase.FindOwnerBlacks(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@@ -63,10 +55,7 @@ func (s *friendServer) IsBlack(ctx context.Context, req *pbfriend.IsBlackReq) (*
return resp, nil
}
-func (s *friendServer) RemoveBlack(
- ctx context.Context,
- req *pbfriend.RemoveBlackReq,
-) (*pbfriend.RemoveBlackResp, error) {
+func (s *friendServer) RemoveBlack(ctx context.Context, req *pbfriend.RemoveBlackReq) (*pbfriend.RemoveBlackResp, error) {
if err := s.userRpcClient.Access(ctx, req.OwnerUserID); err != nil {
return nil, err
}
@@ -74,9 +63,6 @@ func (s *friendServer) RemoveBlack(
return nil, err
}
s.notificationSender.BlackDeletedNotification(ctx, req)
- if err := CallbackAfterRemoveBlack(ctx, req); err != nil {
- return nil, err
- }
return &pbfriend.RemoveBlackResp{}, nil
}
@@ -88,9 +74,6 @@ func (s *friendServer) AddBlack(ctx context.Context, req *pbfriend.AddBlackReq)
if err != nil {
return nil, err
}
- if err := CallbackBeforeAddBlack(ctx, req); err != nil {
- return nil, err
- }
black := relation.BlackModel{
OwnerUserID: req.OwnerUserID,
BlockUserID: req.BlackUserID,
diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go
index 9ef0d6c83..fa7650b9f 100644
--- a/internal/rpc/friend/friend.go
+++ b/internal/rpc/friend/friend.go
@@ -17,6 +17,8 @@ package friend
import (
"context"
+ "github.com/OpenIMSDK/tools/tx"
+
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
@@ -32,13 +34,13 @@ import (
pbfriend "github.com/OpenIMSDK/protocol/friend"
registry "github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
)
@@ -52,49 +54,65 @@ type friendServer struct {
}
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
- db, err := relation.NewGormDB()
+ // Initialize MongoDB
+ mongo, err := unrelation.NewMongo()
if err != nil {
return err
}
- if err := db.AutoMigrate(&tablerelation.FriendModel{}, &tablerelation.FriendRequestModel{}, &tablerelation.BlackModel{}); err != nil {
+
+ // Initialize Redis
+ rdb, err := cache.NewRedis()
+ if err != nil {
return err
}
- rdb, err := cache.NewRedis()
+
+ friendMongoDB, err := mgo.NewFriendMongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
+
+ friendRequestMongoDB, err := mgo.NewFriendRequestMongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
+
+ blackMongoDB, err := mgo.NewBlackMongo(mongo.GetDatabase())
if err != nil {
return err
}
- blackDB := relation.NewBlackGorm(db)
- friendDB := relation.NewFriendGorm(db)
+
+ // Initialize RPC clients
userRpcClient := rpcclient.NewUserRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)
+
+ // Initialize notification sender
notificationSender := notification.NewFriendNotificationSender(
&msgRpcClient,
notification.WithRpcFunc(userRpcClient.GetUsersInfo),
)
+ // Register Friend server with refactored MongoDB and Redis integrations
pbfriend.RegisterFriendServer(server, &friendServer{
friendDatabase: controller.NewFriendDatabase(
- friendDB,
- relation.NewFriendRequestGorm(db),
- cache.NewFriendCacheRedis(rdb, friendDB, cache.GetDefaultOpt()),
- tx.NewGorm(db),
+ friendMongoDB,
+ friendRequestMongoDB,
+ cache.NewFriendCacheRedis(rdb, friendMongoDB, cache.GetDefaultOpt()),
+ tx.NewMongo(mongo.GetClient()),
),
blackDatabase: controller.NewBlackDatabase(
- blackDB,
- cache.NewBlackCacheRedis(rdb, blackDB, cache.GetDefaultOpt()),
+ blackMongoDB,
+ cache.NewBlackCacheRedis(rdb, blackMongoDB, cache.GetDefaultOpt()),
),
userRpcClient: &userRpcClient,
notificationSender: notificationSender,
RegisterCenter: client,
conversationRpcClient: rpcclient.NewConversationRpcClient(client),
})
+
return nil
}
// ok.
-func (s *friendServer) ApplyToAddFriend(
- ctx context.Context,
- req *pbfriend.ApplyToAddFriendReq,
-) (resp *pbfriend.ApplyToAddFriendResp, err error) {
+func (s *friendServer) ApplyToAddFriend(ctx context.Context, req *pbfriend.ApplyToAddFriendReq) (resp *pbfriend.ApplyToAddFriendResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.ApplyToAddFriendResp{}
if err := authverify.CheckAccessV3(ctx, req.FromUserID); err != nil {
@@ -127,10 +145,7 @@ func (s *friendServer) ApplyToAddFriend(
}
// ok.
-func (s *friendServer) ImportFriends(
- ctx context.Context,
- req *pbfriend.ImportFriendReq,
-) (resp *pbfriend.ImportFriendResp, err error) {
+func (s *friendServer) ImportFriends(ctx context.Context, req *pbfriend.ImportFriendReq) (resp *pbfriend.ImportFriendResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := authverify.CheckAdmin(ctx); err != nil {
return nil, err
@@ -165,10 +180,7 @@ func (s *friendServer) ImportFriends(
}
// ok.
-func (s *friendServer) RespondFriendApply(
- ctx context.Context,
- req *pbfriend.RespondFriendApplyReq,
-) (resp *pbfriend.RespondFriendApplyResp, err error) {
+func (s *friendServer) RespondFriendApply(ctx context.Context, req *pbfriend.RespondFriendApplyReq) (resp *pbfriend.RespondFriendApplyResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.RespondFriendApplyResp{}
if err := authverify.CheckAccessV3(ctx, req.ToUserID); err != nil {
@@ -204,10 +216,7 @@ func (s *friendServer) RespondFriendApply(
}
// ok.
-func (s *friendServer) DeleteFriend(
- ctx context.Context,
- req *pbfriend.DeleteFriendReq,
-) (resp *pbfriend.DeleteFriendResp, err error) {
+func (s *friendServer) DeleteFriend(ctx context.Context, req *pbfriend.DeleteFriendReq) (resp *pbfriend.DeleteFriendResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.DeleteFriendResp{}
if err := s.userRpcClient.Access(ctx, req.OwnerUserID); err != nil {
@@ -228,10 +237,7 @@ func (s *friendServer) DeleteFriend(
}
// ok.
-func (s *friendServer) SetFriendRemark(
- ctx context.Context,
- req *pbfriend.SetFriendRemarkReq,
-) (resp *pbfriend.SetFriendRemarkResp, err error) {
+func (s *friendServer) SetFriendRemark(ctx context.Context, req *pbfriend.SetFriendRemarkReq) (resp *pbfriend.SetFriendRemarkResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err = CallbackBeforeSetFriendRemark(ctx, req); err != nil && err != errs.ErrCallbackContinue {
@@ -256,10 +262,7 @@ func (s *friendServer) SetFriendRemark(
}
// ok.
-func (s *friendServer) GetDesignatedFriends(
- ctx context.Context,
- req *pbfriend.GetDesignatedFriendsReq,
-) (resp *pbfriend.GetDesignatedFriendsResp, err error) {
+func (s *friendServer) GetDesignatedFriends(ctx context.Context, req *pbfriend.GetDesignatedFriendsReq) (resp *pbfriend.GetDesignatedFriendsResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.GetDesignatedFriendsResp{}
if utils.Duplicate(req.FriendUserIDs) {
@@ -290,15 +293,12 @@ func (s *friendServer) GetDesignatedFriendsApply(ctx context.Context,
}
// ok 获取接收到的好友申请(即别人主动申请的).
-func (s *friendServer) GetPaginationFriendsApplyTo(
- ctx context.Context,
- req *pbfriend.GetPaginationFriendsApplyToReq,
-) (resp *pbfriend.GetPaginationFriendsApplyToResp, err error) {
+func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context, req *pbfriend.GetPaginationFriendsApplyToReq) (resp *pbfriend.GetPaginationFriendsApplyToResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
- friendRequests, total, err := s.friendDatabase.PageFriendRequestToMe(ctx, req.UserID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, friendRequests, err := s.friendDatabase.PageFriendRequestToMe(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@@ -312,16 +312,13 @@ func (s *friendServer) GetPaginationFriendsApplyTo(
}
// ok 获取主动发出去的好友申请列表.
-func (s *friendServer) GetPaginationFriendsApplyFrom(
- ctx context.Context,
- req *pbfriend.GetPaginationFriendsApplyFromReq,
-) (resp *pbfriend.GetPaginationFriendsApplyFromResp, err error) {
+func (s *friendServer) GetPaginationFriendsApplyFrom(ctx context.Context, req *pbfriend.GetPaginationFriendsApplyFromReq) (resp *pbfriend.GetPaginationFriendsApplyFromResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.GetPaginationFriendsApplyFromResp{}
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
- friendRequests, total, err := s.friendDatabase.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, friendRequests, err := s.friendDatabase.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@@ -368,10 +365,7 @@ func (s *friendServer) PinFriends(
}
// ok.
-func (s *friendServer) IsFriend(
- ctx context.Context,
- req *pbfriend.IsFriendReq,
-) (resp *pbfriend.IsFriendResp, err error) {
+func (s *friendServer) IsFriend(ctx context.Context, req *pbfriend.IsFriendReq) (resp *pbfriend.IsFriendResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.IsFriendResp{}
resp.InUser1Friends, resp.InUser2Friends, err = s.friendDatabase.CheckIn(ctx, req.UserID1, req.UserID2)
@@ -381,15 +375,12 @@ func (s *friendServer) IsFriend(
return resp, nil
}
-func (s *friendServer) GetPaginationFriends(
- ctx context.Context,
- req *pbfriend.GetPaginationFriendsReq,
-) (resp *pbfriend.GetPaginationFriendsResp, err error) {
+func (s *friendServer) GetPaginationFriends(ctx context.Context, req *pbfriend.GetPaginationFriendsReq) (resp *pbfriend.GetPaginationFriendsResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
- friends, total, err := s.friendDatabase.PageOwnerFriends(ctx, req.UserID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, friends, err := s.friendDatabase.PageOwnerFriends(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@@ -402,10 +393,7 @@ func (s *friendServer) GetPaginationFriends(
return resp, nil
}
-func (s *friendServer) GetFriendIDs(
- ctx context.Context,
- req *pbfriend.GetFriendIDsReq,
-) (resp *pbfriend.GetFriendIDsResp, err error) {
+func (s *friendServer) GetFriendIDs(ctx context.Context, req *pbfriend.GetFriendIDsReq) (resp *pbfriend.GetFriendIDsResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
diff --git a/internal/rpc/group/cache.go b/internal/rpc/group/cache.go
index 23c57ff89..fc387736d 100644
--- a/internal/rpc/group/cache.go
+++ b/internal/rpc/group/cache.go
@@ -26,7 +26,7 @@ func (s *groupServer) GetGroupInfoCache(
ctx context.Context,
req *pbgroup.GetGroupInfoCacheReq,
) (resp *pbgroup.GetGroupInfoCacheResp, err error) {
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -38,7 +38,7 @@ func (s *groupServer) GetGroupMemberCache(
ctx context.Context,
req *pbgroup.GetGroupMemberCacheReq,
) (resp *pbgroup.GetGroupMemberCacheResp, err error) {
- members, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.GroupMemberID)
+ members, err := s.db.TakeGroupMember(ctx, req.GroupID, req.GroupMemberID)
if err != nil {
return nil, err
}
diff --git a/internal/rpc/group/db_map.go b/internal/rpc/group/db_map.go
index f793582f8..07084873c 100644
--- a/internal/rpc/group/db_map.go
+++ b/internal/rpc/group/db_map.go
@@ -27,7 +27,7 @@ import (
func UpdateGroupInfoMap(ctx context.Context, group *sdkws.GroupInfoForSet) map[string]any {
m := make(map[string]any)
if group.GroupName != "" {
- m["name"] = group.GroupName
+ m["group_name"] = group.GroupName
}
if group.Notification != "" {
m["notification"] = group.Notification
diff --git a/internal/rpc/group/fill.go b/internal/rpc/group/fill.go
index cb47d9f6e..ac539de19 100644
--- a/internal/rpc/group/fill.go
+++ b/internal/rpc/group/fill.go
@@ -17,119 +17,9 @@ package group
import (
"context"
- "github.com/OpenIMSDK/tools/utils"
-
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
-func (s *groupServer) FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
- members, err := s.GroupDatabase.FindGroupMember(ctx, groupIDs, userIDs, roleLevels)
- if err != nil {
- return nil, err
- }
- emptyUserIDs := make(map[string]struct{})
- for _, member := range members {
- if member.Nickname == "" || member.FaceURL == "" {
- emptyUserIDs[member.UserID] = struct{}{}
- }
- }
- if len(emptyUserIDs) > 0 {
- users, err := s.User.GetPublicUserInfoMap(ctx, utils.Keys(emptyUserIDs), true)
- if err != nil {
- return nil, err
- }
- for i, member := range members {
- user, ok := users[member.UserID]
- if !ok {
- continue
- }
- if member.Nickname == "" {
- members[i].Nickname = user.Nickname
- }
- if member.FaceURL == "" {
- members[i].FaceURL = user.FaceURL
- }
- }
- }
- return members, nil
-}
-
-func (s *groupServer) TakeGroupMember(
- ctx context.Context,
- groupID string,
- userID string,
-) (*relationtb.GroupMemberModel, error) {
- member, err := s.GroupDatabase.TakeGroupMember(ctx, groupID, userID)
- if err != nil {
- return nil, err
- }
- if member.Nickname == "" || member.FaceURL == "" {
- user, err := s.User.GetPublicUserInfo(ctx, userID)
- if err != nil {
- return nil, err
- }
- if member.Nickname == "" {
- member.Nickname = user.Nickname
- }
- if member.FaceURL == "" {
- member.FaceURL = user.FaceURL
- }
- }
- return member, nil
-}
-
-func (s *groupServer) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
- owner, err := s.GroupDatabase.TakeGroupOwner(ctx, groupID)
- if err != nil {
- return nil, err
- }
- if owner.Nickname == "" || owner.FaceURL == "" {
- user, err := s.User.GetUserInfo(ctx, owner.UserID)
- if err != nil {
- return nil, err
- }
- if owner.Nickname == "" {
- owner.Nickname = user.Nickname
- }
- if owner.FaceURL == "" {
- owner.FaceURL = user.FaceURL
- }
- }
- return owner, nil
-}
-
-func (s *groupServer) PageGetGroupMember(
- ctx context.Context,
- groupID string,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupMemberModel, error) {
- total, members, err := s.GroupDatabase.PageGetGroupMember(ctx, groupID, pageNumber, showNumber)
- if err != nil {
- return 0, nil, err
- }
- emptyUserIDs := make(map[string]struct{})
- for _, member := range members {
- if member.Nickname == "" || member.FaceURL == "" {
- emptyUserIDs[member.UserID] = struct{}{}
- }
- }
- if len(emptyUserIDs) > 0 {
- users, err := s.User.GetPublicUserInfoMap(ctx, utils.Keys(emptyUserIDs), true)
- if err != nil {
- return 0, nil, err
- }
- for i, member := range members {
- user, ok := users[member.UserID]
- if !ok {
- continue
- }
- if member.Nickname == "" {
- members[i].Nickname = user.Nickname
- }
- if member.FaceURL == "" {
- members[i].FaceURL = user.FaceURL
- }
- }
- }
- return total, members, nil
+func (s *groupServer) PopulateGroupMember(ctx context.Context, members ...*relationtb.GroupMemberModel) error {
+ return s.Notification.PopulateGroupMember(ctx, members...)
}
diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go
index 67cd70817..5992ed031 100644
--- a/internal/rpc/group/group.go
+++ b/internal/rpc/group/group.go
@@ -16,24 +16,24 @@ package group
import (
"context"
- "crypto/md5"
- "encoding/binary"
- "encoding/json"
"fmt"
+ "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"math/big"
"math/rand"
"strconv"
"strings"
"time"
- "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
+ pbconversation "github.com/OpenIMSDK/protocol/conversation"
+ "github.com/OpenIMSDK/protocol/wrapperspb"
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+ "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/grouphash"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
- pbconversation "github.com/OpenIMSDK/protocol/conversation"
- "github.com/OpenIMSDK/protocol/wrapperspb"
-
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
"github.com/OpenIMSDK/tools/mw/specialerror"
@@ -54,24 +54,28 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
)
func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
- db, err := relation.NewGormDB()
+ mongo, err := unrelation.NewMongo()
if err != nil {
return err
}
- if err := db.AutoMigrate(&relationtb.GroupModel{}, &relationtb.GroupMemberModel{}, &relationtb.GroupRequestModel{}); err != nil {
+ rdb, err := cache.NewRedis()
+ if err != nil {
return err
}
- mongo, err := unrelation.NewMongo()
+ groupDB, err := mgo.NewGroupMongo(mongo.GetDatabase())
if err != nil {
return err
}
- rdb, err := cache.NewRedis()
+ groupMemberDB, err := mgo.NewGroupMember(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
+ groupRequestDB, err := mgo.NewGroupRequestMgo(mongo.GetDatabase())
if err != nil {
return err
}
@@ -79,8 +83,8 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
msgRpcClient := rpcclient.NewMessageRpcClient(client)
conversationRpcClient := rpcclient.NewConversationRpcClient(client)
var gs groupServer
- database := controller.InitGroupDatabase(db, rdb, mongo.GetDatabase(), gs.groupMemberHashCode)
- gs.GroupDatabase = database
+ database := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, tx.NewMongo(mongo.GetClient()), grouphash.NewGroupHashFromGroupServer(&gs))
+ gs.db = database
gs.User = userRpcClient
gs.Notification = notification.NewGroupNotificationSender(database, &msgRpcClient, &userRpcClient, func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error) {
users, err := userRpcClient.GetUsersInfo(ctx, userIDs)
@@ -92,24 +96,11 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
gs.conversationRpcClient = conversationRpcClient
gs.msgRpcClient = msgRpcClient
pbgroup.RegisterGroupServer(server, &gs)
- //pbgroup.RegisterGroupServer(server, &groupServer{
- // GroupDatabase: database,
- // User: userRpcClient,
- // Notification: notification.NewGroupNotificationSender(database, &msgRpcClient, &userRpcClient, func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error) {
- // users, err := userRpcClient.GetUsersInfo(ctx, userIDs)
- // if err != nil {
- // return nil, err
- // }
- // return utils.Slice(users, func(e *sdkws.UserInfo) notification.CommonUser { return e }), nil
- // }),
- // conversationRpcClient: conversationRpcClient,
- // msgRpcClient: msgRpcClient,
- //})
return nil
}
type groupServer struct {
- GroupDatabase controller.GroupDatabase
+ db controller.GroupDatabase
User rpcclient.UserRpcClient
Notification *notification.GroupNotificationSender
conversationRpcClient rpcclient.ConversationRpcClient
@@ -118,11 +109,13 @@ type groupServer struct {
func (s *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgroup.NotificationUserInfoUpdateReq) (*pbgroup.NotificationUserInfoUpdateResp, error) {
defer log.ZDebug(ctx, "return")
-
- members, err := s.GroupDatabase.FindGroupMember(ctx, nil, []string{req.UserID}, nil)
+ members, err := s.db.FindGroupMemberUser(ctx, nil, req.UserID)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
groupIDs := make([]string, 0, len(members))
for _, member := range members {
if member.Nickname != "" && member.FaceURL != "" {
@@ -136,7 +129,7 @@ func (s *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgro
log.ZError(ctx, "NotificationUserInfoUpdate setGroupMemberInfo notification failed", err, "groupID", groupID)
}
}
- if err := s.GroupDatabase.DeleteGroupMemberHash(ctx, groupIDs); err != nil {
+ if err := s.db.DeleteGroupMemberHash(ctx, groupIDs); err != nil {
log.ZError(ctx, "NotificationUserInfoUpdate DeleteGroupMemberHash", err, "groupID", groupIDs)
}
@@ -145,7 +138,7 @@ func (s *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgro
func (s *groupServer) CheckGroupAdmin(ctx context.Context, groupID string) error {
if !authverify.IsAppManagerUid(ctx) {
- groupMember, err := s.GroupDatabase.TakeGroupMember(ctx, groupID, mcontext.GetOpUserID(ctx))
+ groupMember, err := s.db.TakeGroupMember(ctx, groupID, mcontext.GetOpUserID(ctx))
if err != nil {
return err
}
@@ -175,7 +168,7 @@ func (s *groupServer) IsNotFound(err error) bool {
func (s *groupServer) GenGroupID(ctx context.Context, groupID *string) error {
if *groupID != "" {
- _, err := s.GroupDatabase.TakeGroup(ctx, *groupID)
+ _, err := s.db.TakeGroup(ctx, *groupID)
if err == nil {
return errs.ErrGroupIDExisted.Wrap("group id existed " + *groupID)
} else if s.IsNotFound(err) {
@@ -189,7 +182,7 @@ func (s *groupServer) GenGroupID(ctx context.Context, groupID *string) error {
bi := big.NewInt(0)
bi.SetString(id[0:8], 16)
id = bi.String()
- _, err := s.GroupDatabase.TakeGroup(ctx, id)
+ _, err := s.db.TakeGroup(ctx, id)
if err == nil {
continue
} else if s.IsNotFound(err) {
@@ -203,12 +196,12 @@ func (s *groupServer) GenGroupID(ctx context.Context, groupID *string) error {
}
func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupReq) (*pbgroup.CreateGroupResp, error) {
+ if req.GroupInfo.GroupType != constant.WorkingGroup {
+ return nil, errs.ErrArgs.Wrap(fmt.Sprintf("group type only supports %d", constant.WorkingGroup))
+ }
if req.OwnerUserID == "" {
return nil, errs.ErrArgs.Wrap("no group owner")
}
- if req.GroupInfo.GroupType != constant.WorkingGroup {
- return nil, errs.ErrArgs.Wrap(fmt.Sprintf("group type %d not support", req.GroupInfo.GroupType))
- }
if err := authverify.CheckAccessV3(ctx, req.OwnerUserID); err != nil {
return nil, err
}
@@ -256,28 +249,36 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
if err := joinGroup(req.OwnerUserID, constant.GroupOwner); err != nil {
return nil, err
}
- if req.GroupInfo.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.CreateSuperGroup(ctx, group.GroupID, userIDs); err != nil {
+ for _, userID := range req.AdminUserIDs {
+ if err := joinGroup(userID, constant.GroupAdmin); err != nil {
return nil, err
}
- } else {
- for _, userID := range req.AdminUserIDs {
- if err := joinGroup(userID, constant.GroupAdmin); err != nil {
- return nil, err
- }
- }
- for _, userID := range req.MemberUserIDs {
- if err := joinGroup(userID, constant.GroupOrdinaryUsers); err != nil {
- return nil, err
- }
+ }
+ for _, userID := range req.MemberUserIDs {
+ if err := joinGroup(userID, constant.GroupOrdinaryUsers); err != nil {
+ return nil, err
}
}
- if err := s.GroupDatabase.CreateGroup(ctx, []*relationtb.GroupModel{group}, groupMembers); err != nil {
+ if err := s.db.CreateGroup(ctx, []*relationtb.GroupModel{group}, groupMembers); err != nil {
return nil, err
}
resp := &pbgroup.CreateGroupResp{GroupInfo: &sdkws.GroupInfo{}}
resp.GroupInfo = convert.Db2PbGroupInfo(group, req.OwnerUserID, uint32(len(userIDs)))
resp.GroupInfo.MemberCount = uint32(len(userIDs))
+ tips := &sdkws.GroupCreatedTips{
+ Group: resp.GroupInfo,
+ OperationTime: group.CreateTime.UnixMilli(),
+ GroupOwnerUser: s.groupMemberDB2PB(groupMembers[0], userMap[groupMembers[0].UserID].AppMangerLevel),
+ }
+ for _, member := range groupMembers {
+ member.Nickname = userMap[member.UserID].Nickname
+ tips.MemberList = append(tips.MemberList, s.groupMemberDB2PB(member, userMap[member.UserID].AppMangerLevel))
+ if member.UserID == opUserID {
+ tips.OpUser = s.groupMemberDB2PB(member, userMap[member.UserID].AppMangerLevel)
+ break
+ }
+ }
+ s.Notification.GroupCreatedNotification(ctx, tips)
if req.GroupInfo.GroupType == constant.SuperGroup {
go func() {
for _, userID := range userIDs {
@@ -320,35 +321,32 @@ func (s *groupServer) GetJoinedGroupList(ctx context.Context, req *pbgroup.GetJo
if err := authverify.CheckAccessV3(ctx, req.FromUserID); err != nil {
return nil, err
}
- var pageNumber, showNumber int32
- if req.Pagination != nil {
- pageNumber = req.Pagination.PageNumber
- showNumber = req.Pagination.ShowNumber
- }
- // total, members, err := s.GroupDatabase.PageGroupMember(ctx, nil, []string{req.FromUserID}, nil, pageNumber, showNumber)
- total, members, err := s.GroupDatabase.PageGetJoinGroup(ctx, req.FromUserID, pageNumber, showNumber)
+ total, members, err := s.db.PageGetJoinGroup(ctx, req.FromUserID, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
+ resp.Total = uint32(total)
if len(members) == 0 {
return resp, nil
}
groupIDs := utils.Slice(members, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
- groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
+ groups, err := s.db.FindGroup(ctx, groupIDs)
if err != nil {
return nil, err
}
- groupMemberNum, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
@@ -373,7 +371,7 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
if utils.Duplicate(req.InvitedUserIDs) {
return nil, errs.ErrArgs.Wrap("userID duplicate")
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -392,14 +390,14 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
var opUserID string
if !authverify.IsAppManagerUid(ctx) {
opUserID = mcontext.GetOpUserID(ctx)
- groupMembers, err := s.FindGroupMember(ctx, []string{req.GroupID}, []string{opUserID}, nil)
+ var err error
+ groupMember, err = s.db.TakeGroupMember(ctx, req.GroupID, opUserID)
if err != nil {
return nil, err
}
- if len(groupMembers) <= 0 {
- return nil, errs.ErrNoPermission.Wrap("not in group")
+ if err := s.PopulateGroupMember(ctx, groupMember); err != nil {
+ return nil, err
}
- groupMember = groupMembers[0]
}
if err := CallbackBeforeInviteUserToGroup(ctx, req); err != nil {
@@ -419,8 +417,7 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
HandledTime: time.Unix(0, 0),
})
}
-
- if err := s.GroupDatabase.CreateGroupRequest(ctx, requests); err != nil {
+ if err := s.db.CreateGroupRequest(ctx, requests); err != nil {
return nil, err
}
for _, request := range requests {
@@ -435,75 +432,43 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
}
}
}
-
- if group.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.CreateSuperGroupMember(ctx, req.GroupID, req.InvitedUserIDs); err != nil {
- return nil, err
- }
- if err := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, req.InvitedUserIDs); err != nil {
- return nil, err
- }
- for _, userID := range req.InvitedUserIDs {
- s.Notification.SuperGroupNotification(ctx, userID, userID)
- }
- } else {
- opUserID := mcontext.GetOpUserID(ctx)
- var groupMembers []*relationtb.GroupMemberModel
- for _, userID := range req.InvitedUserIDs {
- member := &relationtb.GroupMemberModel{
- GroupID: req.GroupID,
- UserID: userID,
- RoleLevel: constant.GroupOrdinaryUsers,
- OperatorUserID: opUserID,
- InviterUserID: opUserID,
- JoinSource: constant.JoinByInvitation,
- JoinTime: time.Now(),
- MuteEndTime: time.UnixMilli(0),
- }
- if err := CallbackBeforeMemberJoinGroup(ctx, member, group.Ex); err != nil {
- return nil, err
- }
- groupMembers = append(groupMembers, member)
- }
- if err := s.GroupDatabase.CreateGroup(ctx, nil, groupMembers); err != nil {
- return nil, err
+ var groupMembers []*relationtb.GroupMemberModel
+ for _, userID := range req.InvitedUserIDs {
+ member := &relationtb.GroupMemberModel{
+ GroupID: req.GroupID,
+ UserID: userID,
+ RoleLevel: constant.GroupOrdinaryUsers,
+ OperatorUserID: opUserID,
+ InviterUserID: opUserID,
+ JoinSource: constant.JoinByInvitation,
+ JoinTime: time.Now(),
+ MuteEndTime: time.UnixMilli(0),
}
- if err := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, req.InvitedUserIDs); err != nil {
+ if err := CallbackBeforeMemberJoinGroup(ctx, member, group.Ex); err != nil {
return nil, err
}
- s.Notification.MemberInvitedNotification(ctx, req.GroupID, req.Reason, req.InvitedUserIDs)
+ groupMembers = append(groupMembers, member)
}
+ if err := s.db.CreateGroup(ctx, nil, groupMembers); err != nil {
+ return nil, err
+ }
+ if err := s.conversationRpcClient.GroupChatFirstCreateConversation(ctx, req.GroupID, req.InvitedUserIDs); err != nil {
+ return nil, err
+ }
+ s.Notification.MemberInvitedNotification(ctx, req.GroupID, req.Reason, req.InvitedUserIDs)
return resp, nil
}
func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGroupAllMemberReq) (*pbgroup.GetGroupAllMemberResp, error) {
- resp := &pbgroup.GetGroupAllMemberResp{}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
- if err != nil {
- return nil, err
- }
- if group.GroupType == constant.SuperGroup {
- return nil, errs.ErrArgs.Wrap("unsupported super group")
- }
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, nil, nil)
+ members, err := s.db.FindGroupMemberAll(ctx, req.GroupID)
if err != nil {
return nil, err
}
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
+ resp := &pbgroup.GetGroupAllMemberResp{}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
@@ -511,20 +476,21 @@ func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGro
func (s *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGroupMemberListReq) (*pbgroup.GetGroupMemberListResp, error) {
resp := &pbgroup.GetGroupMemberListResp{}
- total, members, err := s.PageGetGroupMember(ctx, req.GroupID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
- log.ZDebug(ctx, "GetGroupMemberList", "total", total, "members", members, "length", len(members))
+ total, members, err := s.db.PageGetGroupMember(ctx, req.GroupID, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
+ resp.Total = uint32(total)
resp.Members = utils.Batch(convert.Db2PbGroupMember, members)
- log.ZDebug(ctx, "GetGroupMemberList", "resp", resp, "length", len(resp.Members))
return resp, nil
}
func (s *groupServer) KickGroupMember(ctx context.Context, req *pbgroup.KickGroupMemberReq) (*pbgroup.KickGroupMemberResp, error) {
resp := &pbgroup.KickGroupMemberResp{}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -538,92 +504,85 @@ func (s *groupServer) KickGroupMember(ctx context.Context, req *pbgroup.KickGrou
if utils.IsContain(opUserID, req.KickedUserIDs) {
return nil, errs.ErrArgs.Wrap("opUserID in KickedUserIDs")
}
- if group.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.DeleteSuperGroupMember(ctx, req.GroupID, req.KickedUserIDs); err != nil {
- return nil, err
- }
- go func() {
- for _, userID := range req.KickedUserIDs {
- s.Notification.SuperGroupNotification(ctx, userID, userID)
- }
- }()
- } else {
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, append(req.KickedUserIDs, opUserID), nil)
- if err != nil {
- return nil, err
- }
- memberMap := make(map[string]*relationtb.GroupMemberModel)
- for i, member := range members {
- memberMap[member.UserID] = members[i]
+ members, err := s.db.FindGroupMembers(ctx, req.GroupID, append(req.KickedUserIDs, opUserID))
+ if err != nil {
+ return nil, err
+ }
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
+ memberMap := make(map[string]*relationtb.GroupMemberModel)
+ for i, member := range members {
+ memberMap[member.UserID] = members[i]
+ }
+ isAppManagerUid := authverify.IsAppManagerUid(ctx)
+ opMember := memberMap[opUserID]
+ for _, userID := range req.KickedUserIDs {
+ member, ok := memberMap[userID]
+ if !ok {
+ return nil, errs.ErrUserIDNotFound.Wrap(userID)
}
- isAppManagerUid := authverify.IsAppManagerUid(ctx)
- opMember := memberMap[opUserID]
- for _, userID := range req.KickedUserIDs {
- member, ok := memberMap[userID]
- if !ok {
- return nil, errs.ErrUserIDNotFound.Wrap(userID)
+ if !isAppManagerUid {
+ if opMember == nil {
+ return nil, errs.ErrNoPermission.Wrap("opUserID no in group")
}
- if !isAppManagerUid {
- if opMember == nil {
- return nil, errs.ErrNoPermission.Wrap("opUserID no in group")
- }
- switch opMember.RoleLevel {
- case constant.GroupOwner:
- case constant.GroupAdmin:
- if member.RoleLevel == constant.GroupOwner || member.RoleLevel == constant.GroupAdmin {
- return nil, errs.ErrNoPermission.Wrap("group admins cannot remove the group owner and other admins")
- }
- case constant.GroupOrdinaryUsers:
- return nil, errs.ErrNoPermission.Wrap("opUserID no permission")
- default:
- return nil, errs.ErrNoPermission.Wrap("opUserID roleLevel unknown")
+ switch opMember.RoleLevel {
+ case constant.GroupOwner:
+ case constant.GroupAdmin:
+ if member.RoleLevel == constant.GroupOwner || member.RoleLevel == constant.GroupAdmin {
+ return nil, errs.ErrNoPermission.Wrap("group admins cannot remove the group owner and other admins")
}
+ case constant.GroupOrdinaryUsers:
+ return nil, errs.ErrNoPermission.Wrap("opUserID no permission")
+ default:
+ return nil, errs.ErrNoPermission.Wrap("opUserID roleLevel unknown")
}
}
- num, err := s.GroupDatabase.FindGroupMemberNum(ctx, req.GroupID)
- if err != nil {
- return nil, err
- }
- owner, err := s.FindGroupMember(ctx, []string{req.GroupID}, nil, []int32{constant.GroupOwner})
- if err != nil {
- return nil, err
- }
- if err := s.GroupDatabase.DeleteGroupMember(ctx, group.GroupID, req.KickedUserIDs); err != nil {
- return nil, err
- }
- tips := &sdkws.MemberKickedTips{
- Group: &sdkws.GroupInfo{
- GroupID: group.GroupID,
- GroupName: group.GroupName,
- Notification: group.Notification,
- Introduction: group.Introduction,
- FaceURL: group.FaceURL,
- // OwnerUserID: owner[0].UserID,
- CreateTime: group.CreateTime.UnixMilli(),
- MemberCount: num,
- Ex: group.Ex,
- Status: group.Status,
- CreatorUserID: group.CreatorUserID,
- GroupType: group.GroupType,
- NeedVerification: group.NeedVerification,
- LookMemberInfo: group.LookMemberInfo,
- ApplyMemberFriend: group.ApplyMemberFriend,
- NotificationUpdateTime: group.NotificationUpdateTime.UnixMilli(),
- NotificationUserID: group.NotificationUserID,
- },
- KickedUserList: []*sdkws.GroupMemberFullInfo{},
- }
- if len(owner) > 0 {
- tips.Group.OwnerUserID = owner[0].UserID
- }
- if opMember, ok := memberMap[opUserID]; ok {
- tips.OpUser = convert.Db2PbGroupMember(opMember)
- }
- for _, userID := range req.KickedUserIDs {
- tips.KickedUserList = append(tips.KickedUserList, convert.Db2PbGroupMember(memberMap[userID]))
- }
- s.Notification.MemberKickedNotification(ctx, tips)
}
+ num, err := s.db.FindGroupMemberNum(ctx, req.GroupID)
+ if err != nil {
+ return nil, err
+ }
+ ownerUserIDs, err := s.db.GetGroupRoleLevelMemberIDs(ctx, req.GroupID, constant.GroupOwner)
+ if err != nil {
+ return nil, err
+ }
+ var ownerUserID string
+ if len(ownerUserIDs) > 0 {
+ ownerUserID = ownerUserIDs[0]
+ }
+ if err := s.db.DeleteGroupMember(ctx, group.GroupID, req.KickedUserIDs); err != nil {
+ return nil, err
+ }
+ tips := &sdkws.MemberKickedTips{
+ Group: &sdkws.GroupInfo{
+ GroupID: group.GroupID,
+ GroupName: group.GroupName,
+ Notification: group.Notification,
+ Introduction: group.Introduction,
+ FaceURL: group.FaceURL,
+ OwnerUserID: ownerUserID,
+ CreateTime: group.CreateTime.UnixMilli(),
+ MemberCount: num,
+ Ex: group.Ex,
+ Status: group.Status,
+ CreatorUserID: group.CreatorUserID,
+ GroupType: group.GroupType,
+ NeedVerification: group.NeedVerification,
+ LookMemberInfo: group.LookMemberInfo,
+ ApplyMemberFriend: group.ApplyMemberFriend,
+ NotificationUpdateTime: group.NotificationUpdateTime.UnixMilli(),
+ NotificationUserID: group.NotificationUserID,
+ },
+ KickedUserList: []*sdkws.GroupMemberFullInfo{},
+ }
+ if opMember, ok := memberMap[opUserID]; ok {
+ tips.OpUser = convert.Db2PbGroupMember(opMember)
+ }
+ for _, userID := range req.KickedUserIDs {
+ tips.KickedUserList = append(tips.KickedUserList, convert.Db2PbGroupMember(memberMap[userID]))
+ }
+ s.Notification.MemberKickedNotification(ctx, tips)
if err := s.deleteMemberAndSetConversationSeq(ctx, req.GroupID, req.KickedUserIDs); err != nil {
return nil, err
}
@@ -642,32 +601,21 @@ func (s *groupServer) GetGroupMembersInfo(ctx context.Context, req *pbgroup.GetG
if req.GroupID == "" {
return nil, errs.ErrArgs.Wrap("groupID empty")
}
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, req.UserIDs, nil)
+ members, err := s.db.FindGroupMembers(ctx, req.GroupID, req.UserIDs)
if err != nil {
return nil, err
}
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
}
func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.GetGroupApplicationListReq) (*pbgroup.GetGroupApplicationListResp, error) {
- groupIDs, err := s.GroupDatabase.FindUserManagedGroupID(ctx, req.FromUserID)
+ groupIDs, err := s.db.FindUserManagedGroupID(ctx, req.FromUserID)
if err != nil {
return nil, err
}
@@ -675,11 +623,11 @@ func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
if len(groupIDs) == 0 {
return resp, nil
}
- total, groupRequests, err := s.GroupDatabase.PageGroupRequest(ctx, groupIDs, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, groupRequests, err := s.db.PageGroupRequest(ctx, groupIDs, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
+ resp.Total = uint32(total)
if len(groupRequests) == 0 {
return resp, nil
}
@@ -693,7 +641,7 @@ func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
if err != nil {
return nil, err
}
- groups, err := s.GroupDatabase.FindGroup(ctx, utils.Distinct(groupIDs))
+ groups, err := s.db.FindGroup(ctx, utils.Distinct(groupIDs))
if err != nil {
return nil, err
}
@@ -703,14 +651,17 @@ func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
if ids := utils.Single(utils.Keys(groupMap), groupIDs); len(ids) > 0 {
return nil, errs.ErrGroupIDNotFound.Wrap(strings.Join(ids, ","))
}
- groupMemberNumMap, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNumMap, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, owners...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
@@ -729,18 +680,21 @@ func (s *groupServer) GetGroupsInfo(ctx context.Context, req *pbgroup.GetGroupsI
if len(req.GroupIDs) == 0 {
return nil, errs.ErrArgs.Wrap("groupID is empty")
}
- groups, err := s.GroupDatabase.FindGroup(ctx, req.GroupIDs)
+ groups, err := s.db.FindGroup(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
- groupMemberNumMap, err := s.GroupDatabase.MapGroupMemberNum(ctx, req.GroupIDs)
+ groupMemberNumMap, err := s.db.MapGroupMemberNum(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
- owners, err := s.FindGroupMember(ctx, req.GroupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, owners...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
@@ -760,7 +714,7 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
return nil, errs.ErrArgs.Wrap("HandleResult unknown")
}
if !authverify.IsAppManagerUid(ctx) {
- groupMember, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
+ groupMember, err := s.db.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
if err != nil {
return nil, err
}
@@ -768,11 +722,11 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
return nil, errs.ErrNoPermission.Wrap("no group owner or admin")
}
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
- groupRequest, err := s.GroupDatabase.TakeGroupRequest(ctx, req.GroupID, req.FromUserID)
+ groupRequest, err := s.db.TakeGroupRequest(ctx, req.GroupID, req.FromUserID)
if err != nil {
return nil, err
}
@@ -780,7 +734,7 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
return nil, errs.ErrGroupRequestHandled.Wrap("group request already processed")
}
var inGroup bool
- if _, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.FromUserID); err == nil {
+ if _, err := s.db.TakeGroupMember(ctx, req.GroupID, req.FromUserID); err == nil {
inGroup = true // 已经在群里了
} else if !s.IsNotFound(err) {
return nil, err
@@ -808,7 +762,7 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
}
}
log.ZDebug(ctx, "GroupApplicationResponse", "inGroup", inGroup, "HandleResult", req.HandleResult, "member", member)
- if err := s.GroupDatabase.HandlerGroupRequest(ctx, req.GroupID, req.FromUserID, req.HandledMsg, req.HandleResult, member); err != nil {
+ if err := s.db.HandlerGroupRequest(ctx, req.GroupID, req.FromUserID, req.HandledMsg, req.HandleResult, member); err != nil {
return nil, err
}
switch req.HandleResult {
@@ -835,7 +789,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
if err != nil {
return nil, err
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -853,7 +807,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
if err = CallbackApplyJoinGroupBefore(ctx, reqCall); err != nil {
return nil, err
}
- _, err = s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.InviterUserID)
+ _, err = s.db.TakeGroupMember(ctx, req.GroupID, req.InviterUserID)
if err == nil {
return nil, errs.ErrArgs.Wrap("already in group")
} else if !s.IsNotFound(err) && utils.Unwrap(err) != errs.ErrRecordNotFound {
@@ -862,9 +816,6 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
log.ZInfo(ctx, "JoinGroup.groupInfo", "group", group, "eq", group.NeedVerification == constant.Directly)
resp = &pbgroup.JoinGroupResp{}
if group.NeedVerification == constant.Directly {
- if group.GroupType == constant.SuperGroup {
- return nil, errs.ErrGroupTypeNotSupport.Wrap()
- }
groupMember := &relationtb.GroupMemberModel{
GroupID: group.GroupID,
UserID: user.UserID,
@@ -877,7 +828,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
if err := CallbackBeforeMemberJoinGroup(ctx, groupMember, group.Ex); err != nil {
return nil, err
}
- if err := s.GroupDatabase.CreateGroup(ctx, nil, []*relationtb.GroupMemberModel{groupMember}); err != nil {
+ if err := s.db.CreateGroup(ctx, nil, []*relationtb.GroupMemberModel{groupMember}); err != nil {
return nil, err
}
@@ -898,7 +849,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
ReqTime: time.Now(),
HandledTime: time.Unix(0, 0),
}
- if err := s.GroupDatabase.CreateGroupRequest(ctx, []*relationtb.GroupRequestModel{&groupRequest}); err != nil {
+ if err := s.db.CreateGroupRequest(ctx, []*relationtb.GroupRequestModel{&groupRequest}); err != nil {
return nil, err
}
s.Notification.JoinGroupApplicationNotification(ctx, req)
@@ -914,29 +865,21 @@ func (s *groupServer) QuitGroup(ctx context.Context, req *pbgroup.QuitGroupReq)
return nil, err
}
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ member, err := s.db.TakeGroupMember(ctx, req.GroupID, req.UserID)
if err != nil {
return nil, err
}
- if group.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.DeleteSuperGroupMember(ctx, req.GroupID, []string{req.UserID}); err != nil {
- return nil, err
- }
- _ = s.Notification.SuperGroupNotification(ctx, req.UserID, req.UserID)
- } else {
- info, err := s.TakeGroupMember(ctx, req.GroupID, req.UserID)
- if err != nil {
- return nil, err
- }
- if info.RoleLevel == constant.GroupOwner {
- return nil, errs.ErrNoPermission.Wrap("group owner can't quit")
- }
- err = s.GroupDatabase.DeleteGroupMember(ctx, req.GroupID, []string{req.UserID})
- if err != nil {
- return nil, err
- }
- _ = s.Notification.MemberQuitNotification(ctx, s.groupMemberDB2PB(info, 0))
+ if member.RoleLevel == constant.GroupOwner {
+ return nil, errs.ErrNoPermission.Wrap("group owner can't quit")
}
+ if err := s.PopulateGroupMember(ctx, member); err != nil {
+ return nil, err
+ }
+ err = s.db.DeleteGroupMember(ctx, req.GroupID, []string{req.UserID})
+ if err != nil {
+ return nil, err
+ }
+ _ = s.Notification.MemberQuitNotification(ctx, s.groupMemberDB2PB(member, 0))
if err := s.deleteMemberAndSetConversationSeq(ctx, req.GroupID, []string{req.UserID}); err != nil {
return nil, err
}
@@ -961,18 +904,21 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
var opMember *relationtb.GroupMemberModel
if !authverify.IsAppManagerUid(ctx) {
var err error
- opMember, err = s.TakeGroupMember(ctx, req.GroupInfoForSet.GroupID, mcontext.GetOpUserID(ctx))
+ opMember, err = s.db.TakeGroupMember(ctx, req.GroupInfoForSet.GroupID, mcontext.GetOpUserID(ctx))
if err != nil {
return nil, err
}
if !(opMember.RoleLevel == constant.GroupOwner || opMember.RoleLevel == constant.GroupAdmin) {
return nil, errs.ErrNoPermission.Wrap("no group owner or admin")
}
+ if err := s.PopulateGroupMember(ctx, opMember); err != nil {
+ return nil, err
+ }
}
if err := CallbackBeforeSetGroupInfo(ctx, req); err != nil {
return nil, err
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupInfoForSet.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupInfoForSet.GroupID)
if err != nil {
return nil, err
}
@@ -980,22 +926,25 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
return nil, utils.Wrap(errs.ErrDismissedAlready, "")
}
resp := &pbgroup.SetGroupInfoResp{}
- count, err := s.GroupDatabase.FindGroupMemberNum(ctx, group.GroupID)
+ count, err := s.db.FindGroupMemberNum(ctx, group.GroupID)
if err != nil {
return nil, err
}
- owner, err := s.TakeGroupOwner(ctx, group.GroupID)
+ owner, err := s.db.TakeGroupOwner(ctx, group.GroupID)
if err != nil {
return nil, err
}
- data := UpdateGroupInfoMap(ctx, req.GroupInfoForSet)
- if len(data) == 0 {
+ if err := s.PopulateGroupMember(ctx, owner); err != nil {
+ return nil, err
+ }
+ update := UpdateGroupInfoMap(ctx, req.GroupInfoForSet)
+ if len(update) == 0 {
return resp, nil
}
- if err := s.GroupDatabase.UpdateGroup(ctx, group.GroupID, data); err != nil {
+ if err := s.db.UpdateGroup(ctx, group.GroupID, update); err != nil {
return nil, err
}
- group, err = s.GroupDatabase.TakeGroup(ctx, req.GroupInfoForSet.GroupID)
+ group, err = s.db.TakeGroup(ctx, req.GroupInfoForSet.GroupID)
if err != nil {
return nil, err
}
@@ -1007,38 +956,33 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
if opMember != nil {
tips.OpUser = s.groupMemberDB2PB(opMember, 0)
}
- var num int
+ num := len(update)
if req.GroupInfoForSet.Notification != "" {
- go func() {
- nctx := mcontext.NewCtx("@@@" + mcontext.GetOperationID(ctx))
+ num--
+ func() {
conversation := &pbconversation.ConversationReq{
ConversationID: msgprocessor.GetConversationIDBySessionType(constant.SuperGroupChatType, req.GroupInfoForSet.GroupID),
ConversationType: constant.SuperGroupChatType,
GroupID: req.GroupInfoForSet.GroupID,
}
- resp, err := s.GetGroupMemberUserIDs(nctx, &pbgroup.GetGroupMemberUserIDsReq{GroupID: req.GroupInfoForSet.GroupID})
+ resp, err := s.GetGroupMemberUserIDs(ctx, &pbgroup.GetGroupMemberUserIDsReq{GroupID: req.GroupInfoForSet.GroupID})
if err != nil {
log.ZWarn(ctx, "GetGroupMemberIDs", err)
return
}
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.GroupNotification}
- if err := s.conversationRpcClient.SetConversations(nctx, resp.UserIDs, conversation); err != nil {
+ if err := s.conversationRpcClient.SetConversations(ctx, resp.UserIDs, conversation); err != nil {
log.ZWarn(ctx, "SetConversations", err, resp.UserIDs, conversation)
}
}()
- num++
- s.Notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{Group: tips.Group, OpUser: tips.OpUser})
- }
- switch len(data) - num {
- case 0:
- case 1:
- if req.GroupInfoForSet.GroupName == "" {
- s.Notification.GroupInfoSetNotification(ctx, tips)
- } else {
- s.Notification.GroupInfoSetNameNotification(ctx, &sdkws.GroupInfoSetNameTips{Group: tips.Group, OpUser: tips.OpUser})
- }
- default:
- s.Notification.GroupInfoSetNotification(ctx, tips)
+ _ = s.Notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{Group: tips.Group, OpUser: tips.OpUser})
+ }
+ if req.GroupInfoForSet.GroupName != "" {
+ num--
+ _ = s.Notification.GroupInfoSetNameNotification(ctx, &sdkws.GroupInfoSetNameTips{Group: tips.Group, OpUser: tips.OpUser})
+ }
+ if num > 0 {
+ _ = s.Notification.GroupInfoSetNotification(ctx, tips)
}
if err := CallbackAfterSetGroupInfo(ctx, req); err != nil {
return nil, err
@@ -1048,7 +992,7 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) (*pbgroup.TransferGroupOwnerResp, error) {
resp := &pbgroup.TransferGroupOwnerResp{}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -1058,10 +1002,13 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
if req.OldOwnerUserID == req.NewOwnerUserID {
return nil, errs.ErrArgs.Wrap("OldOwnerUserID == NewOwnerUserID")
}
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, []string{req.OldOwnerUserID, req.NewOwnerUserID}, nil)
+ members, err := s.db.FindGroupMembers(ctx, req.GroupID, []string{req.OldOwnerUserID, req.NewOwnerUserID})
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
memberMap := utils.SliceToMap(members, func(e *relationtb.GroupMemberModel) string { return e.UserID })
if ids := utils.Single([]string{req.OldOwnerUserID, req.NewOwnerUserID}, utils.Keys(memberMap)); len(ids) > 0 {
return nil, errs.ErrArgs.Wrap("user not in group " + strings.Join(ids, ","))
@@ -1079,7 +1026,7 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
return nil, errs.ErrNoPermission.Wrap("no permission transfer group owner")
}
}
- if err := s.GroupDatabase.TransferGroupOwner(ctx, req.GroupID, req.OldOwnerUserID, req.NewOwnerUserID, newOwner.RoleLevel); err != nil {
+ if err := s.db.TransferGroupOwner(ctx, req.GroupID, req.OldOwnerUserID, req.NewOwnerUserID, newOwner.RoleLevel); err != nil {
return nil, err
}
@@ -1097,10 +1044,12 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
err error
)
if req.GroupID != "" {
- groups, err = s.GroupDatabase.FindGroup(ctx, []string{req.GroupID})
+ groups, err = s.db.FindGroup(ctx, []string{req.GroupID})
resp.Total = uint32(len(groups))
} else {
- resp.Total, groups, err = s.GroupDatabase.SearchGroup(ctx, req.GroupName, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ var total int64
+ total, groups, err = s.db.SearchGroup(ctx, req.GroupName, req.Pagination)
+ resp.Total = uint32(total)
}
if err != nil {
return nil, err
@@ -1108,14 +1057,14 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
groupIDs := utils.Slice(groups, func(e *relationtb.GroupModel) string {
return e.GroupID
})
- ownerMembers, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ ownerMembers, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
ownerMemberMap := utils.SliceToMap(ownerMembers, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
- groupMemberNumMap, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNumMap, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
@@ -1135,26 +1084,15 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
func (s *groupServer) GetGroupMembersCMS(ctx context.Context, req *pbgroup.GetGroupMembersCMSReq) (*pbgroup.GetGroupMembersCMSResp, error) {
resp := &pbgroup.GetGroupMembersCMSResp{}
- total, members, err := s.GroupDatabase.SearchGroupMember(ctx, req.UserName, []string{req.GroupID}, nil, nil, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, members, err := s.db.SearchGroupMember(ctx, req.UserName, req.GroupID, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ resp.Total = uint32(total)
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
@@ -1166,37 +1104,35 @@ func (s *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou
if err != nil {
return nil, err
}
- var pageNumber, showNumber int32
- if req.Pagination != nil {
- pageNumber = req.Pagination.PageNumber
- showNumber = req.Pagination.ShowNumber
- }
- total, requests, err := s.GroupDatabase.PageGroupRequestUser(ctx, req.UserID, pageNumber, showNumber)
+ total, requests, err := s.db.PageGroupRequestUser(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
- resp.Total = total
+ resp.Total = uint32(total)
if len(requests) == 0 {
return resp, nil
}
groupIDs := utils.Distinct(utils.Slice(requests, func(e *relationtb.GroupRequestModel) string {
return e.GroupID
}))
- groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
+ groups, err := s.db.FindGroup(ctx, groupIDs)
if err != nil {
return nil, err
}
groupMap := utils.SliceToMap(groups, func(e *relationtb.GroupModel) string {
return e.GroupID
})
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, owners...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
- groupMemberNum, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
@@ -1213,7 +1149,7 @@ func (s *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou
func (s *groupServer) DismissGroup(ctx context.Context, req *pbgroup.DismissGroupReq) (*pbgroup.DismissGroupResp, error) {
defer log.ZInfo(ctx, "DismissGroup.return")
resp := &pbgroup.DismissGroupResp{}
- owner, err := s.TakeGroupOwner(ctx, req.GroupID)
+ owner, err := s.db.TakeGroupOwner(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -1222,41 +1158,34 @@ func (s *groupServer) DismissGroup(ctx context.Context, req *pbgroup.DismissGrou
return nil, errs.ErrNoPermission.Wrap("not group owner")
}
}
- group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID)
+ if err := s.PopulateGroupMember(ctx, owner); err != nil {
+ return nil, err
+ }
+ group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
if req.DeleteMember == false && group.Status == constant.GroupStatusDismissed {
return nil, errs.ErrDismissedAlready.Wrap("group status is dismissed")
}
- //if group.Status == constant.GroupStatusDismissed {
- // return nil, errs.ErrArgs.Wrap("group status is dismissed")
- //}
- if err := s.GroupDatabase.DismissGroup(ctx, req.GroupID, req.DeleteMember); err != nil {
+ if err := s.db.DismissGroup(ctx, req.GroupID, req.DeleteMember); err != nil {
return nil, err
}
- if group.GroupType == constant.SuperGroup {
- if err := s.GroupDatabase.DeleteSuperGroup(ctx, group.GroupID); err != nil {
+ if !req.DeleteMember {
+ num, err := s.db.FindGroupMemberNum(ctx, req.GroupID)
+ if err != nil {
return nil, err
}
- } else {
- if !req.DeleteMember {
- num, err := s.GroupDatabase.FindGroupMemberNum(ctx, req.GroupID)
- if err != nil {
- return nil, err
- }
- // s.Notification.GroupDismissedNotification(ctx, req)
- tips := &sdkws.GroupDismissedTips{
- Group: s.groupDB2PB(group, owner.UserID, num),
- OpUser: &sdkws.GroupMemberFullInfo{},
- }
- if mcontext.GetOpUserID(ctx) == owner.UserID {
- tips.OpUser = s.groupMemberDB2PB(owner, 0)
- }
- s.Notification.GroupDismissedNotification(ctx, tips)
+ tips := &sdkws.GroupDismissedTips{
+ Group: s.groupDB2PB(group, owner.UserID, num),
+ OpUser: &sdkws.GroupMemberFullInfo{},
}
+ if mcontext.GetOpUserID(ctx) == owner.UserID {
+ tips.OpUser = s.groupMemberDB2PB(owner, 0)
+ }
+ s.Notification.GroupDismissedNotification(ctx, tips)
}
- membersID, err := s.GroupDatabase.FindGroupMemberUserID(ctx, group.GroupID)
+ membersID, err := s.db.FindGroupMemberUserID(ctx, group.GroupID)
if err != nil {
return nil, err
}
@@ -1275,15 +1204,15 @@ func (s *groupServer) DismissGroup(ctx context.Context, req *pbgroup.DismissGrou
func (s *groupServer) MuteGroupMember(ctx context.Context, req *pbgroup.MuteGroupMemberReq) (*pbgroup.MuteGroupMemberResp, error) {
resp := &pbgroup.MuteGroupMemberResp{}
- //if err := tokenverify.CheckAccessV3(ctx, req.UserID); err != nil {
- // return nil, err
- //}
- member, err := s.TakeGroupMember(ctx, req.GroupID, req.UserID)
+ member, err := s.db.TakeGroupMember(ctx, req.GroupID, req.UserID)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, member); err != nil {
+ return nil, err
+ }
if !authverify.IsAppManagerUid(ctx) {
- opMember, err := s.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
+ opMember, err := s.db.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
if err != nil {
return nil, err
}
@@ -1301,7 +1230,7 @@ func (s *groupServer) MuteGroupMember(ctx context.Context, req *pbgroup.MuteGrou
}
}
data := UpdateGroupMemberMutedTimeMap(time.Now().Add(time.Second * time.Duration(req.MutedSeconds)))
- if err := s.GroupDatabase.UpdateGroupMember(ctx, member.GroupID, member.UserID, data); err != nil {
+ if err := s.db.UpdateGroupMember(ctx, member.GroupID, member.UserID, data); err != nil {
return nil, err
}
s.Notification.GroupMemberMutedNotification(ctx, req.GroupID, req.UserID, req.MutedSeconds)
@@ -1309,29 +1238,15 @@ func (s *groupServer) MuteGroupMember(ctx context.Context, req *pbgroup.MuteGrou
}
func (s *groupServer) CancelMuteGroupMember(ctx context.Context, req *pbgroup.CancelMuteGroupMemberReq) (*pbgroup.CancelMuteGroupMemberResp, error) {
- resp := &pbgroup.CancelMuteGroupMemberResp{}
- //member, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.UserID)
- //if err != nil {
- // return nil, err
- //}
- //if !(mcontext.GetOpUserID(ctx) == req.UserID || tokenverify.IsAppManagerUid(ctx)) {
- // opMember, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
- // if err != nil {
- // return nil, err
- // }
- // if opMember.RoleLevel <= member.RoleLevel {
- // return nil, errs.ErrNoPermission.Wrap(fmt.Sprintf("self RoleLevel %d target %d", opMember.RoleLevel, member.RoleLevel))
- // }
- //}
- //if err := tokenverify.CheckAccessV3(ctx, req.UserID); err != nil {
- // return nil, err
- //}
- member, err := s.TakeGroupMember(ctx, req.GroupID, req.UserID)
+ member, err := s.db.TakeGroupMember(ctx, req.GroupID, req.UserID)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, member); err != nil {
+ return nil, err
+ }
if !authverify.IsAppManagerUid(ctx) {
- opMember, err := s.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
+ opMember, err := s.db.TakeGroupMember(ctx, req.GroupID, mcontext.GetOpUserID(ctx))
if err != nil {
return nil, err
}
@@ -1349,11 +1264,11 @@ func (s *groupServer) CancelMuteGroupMember(ctx context.Context, req *pbgroup.Ca
}
}
data := UpdateGroupMemberMutedTimeMap(time.Unix(0, 0))
- if err := s.GroupDatabase.UpdateGroupMember(ctx, member.GroupID, member.UserID, data); err != nil {
+ if err := s.db.UpdateGroupMember(ctx, member.GroupID, member.UserID, data); err != nil {
return nil, err
}
s.Notification.GroupMemberCancelMutedNotification(ctx, req.GroupID, req.UserID)
- return resp, nil
+ return &pbgroup.CancelMuteGroupMemberResp{}, nil
}
func (s *groupServer) MuteGroup(ctx context.Context, req *pbgroup.MuteGroupReq) (*pbgroup.MuteGroupResp, error) {
@@ -1361,7 +1276,7 @@ func (s *groupServer) MuteGroup(ctx context.Context, req *pbgroup.MuteGroupReq)
if err := s.CheckGroupAdmin(ctx, req.GroupID); err != nil {
return nil, err
}
- if err := s.GroupDatabase.UpdateGroup(ctx, req.GroupID, UpdateGroupStatusMap(constant.GroupStatusMuted)); err != nil {
+ if err := s.db.UpdateGroup(ctx, req.GroupID, UpdateGroupStatusMap(constant.GroupStatusMuted)); err != nil {
return nil, err
}
s.Notification.GroupMutedNotification(ctx, req.GroupID)
@@ -1373,7 +1288,7 @@ func (s *groupServer) CancelMuteGroup(ctx context.Context, req *pbgroup.CancelMu
if err := s.CheckGroupAdmin(ctx, req.GroupID); err != nil {
return nil, err
}
- if err := s.GroupDatabase.UpdateGroup(ctx, req.GroupID, UpdateGroupStatusMap(constant.GroupOk)); err != nil {
+ if err := s.db.UpdateGroup(ctx, req.GroupID, UpdateGroupStatusMap(constant.GroupOk)); err != nil {
return nil, err
}
s.Notification.GroupCancelMutedNotification(ctx, req.GroupID)
@@ -1385,97 +1300,90 @@ func (s *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbgroup.SetGr
if len(req.Members) == 0 {
return nil, errs.ErrArgs.Wrap("members empty")
}
+ opUserID := mcontext.GetOpUserID(ctx)
+ if opUserID == "" {
+ return nil, errs.ErrNoPermission.Wrap("no op user id")
+ }
+ isAppManagerUid := authverify.IsAppManagerUid(ctx)
for i := range req.Members {
req.Members[i].FaceURL = nil
}
- duplicateMap := make(map[[2]string]struct{})
- userIDMap := make(map[string]struct{})
- groupIDMap := make(map[string]struct{})
- for _, member := range req.Members {
- key := [...]string{member.GroupID, member.UserID}
- if _, ok := duplicateMap[key]; ok {
- return nil, errs.ErrArgs.Wrap("group user duplicate")
+ groupMembers := make(map[string][]*pbgroup.SetGroupMemberInfo)
+ for i, member := range req.Members {
+ if member.RoleLevel != nil {
+ switch member.RoleLevel.Value {
+ case constant.GroupOwner:
+ return nil, errs.ErrNoPermission.Wrap("cannot set ungroup owner")
+ case constant.GroupAdmin, constant.GroupOrdinaryUsers:
+ default:
+ return nil, errs.ErrArgs.Wrap("invalid role level")
+ }
}
- duplicateMap[key] = struct{}{}
- userIDMap[member.UserID] = struct{}{}
- groupIDMap[member.GroupID] = struct{}{}
- }
- groupIDs := utils.Keys(groupIDMap)
- userIDs := utils.Keys(userIDMap)
- members, err := s.FindGroupMember(ctx, groupIDs, append(userIDs, mcontext.GetOpUserID(ctx)), nil)
- if err != nil {
- return nil, err
- }
- for _, member := range members {
- delete(duplicateMap, [...]string{member.GroupID, member.UserID})
- }
- if len(duplicateMap) > 0 {
- return nil, errs.ErrArgs.Wrap("user not found" + strings.Join(utils.Slice(utils.Keys(duplicateMap), func(e [2]string) string {
- return fmt.Sprintf("[group: %s user: %s]", e[0], e[1])
- }), ","))
+ groupMembers[member.GroupID] = append(groupMembers[member.GroupID], req.Members[i])
}
- memberMap := utils.SliceToMap(members, func(e *relationtb.GroupMemberModel) [2]string {
- return [...]string{e.GroupID, e.UserID}
- })
- if !authverify.IsAppManagerUid(ctx) {
- opUserID := mcontext.GetOpUserID(ctx)
- for _, member := range req.Members {
- if member.RoleLevel != nil {
- switch member.RoleLevel.Value {
- case constant.GroupOrdinaryUsers, constant.GroupAdmin:
- default:
- return nil, errs.ErrArgs.Wrap("invalid role level")
- }
- }
- opMember, ok := memberMap[[...]string{member.GroupID, opUserID}]
- if !ok {
- return nil, errs.ErrArgs.Wrap(fmt.Sprintf("user %s not in group %s", opUserID, member.GroupID))
+ for groupID, members := range groupMembers {
+ temp := make(map[string]struct{})
+ userIDs := make([]string, 0, len(members)+1)
+ for _, member := range members {
+ if _, ok := temp[member.UserID]; ok {
+ return nil, errs.ErrArgs.Wrap(fmt.Sprintf("repeat group %s user %s", member.GroupID, member.UserID))
}
+ temp[member.UserID] = struct{}{}
+ userIDs = append(userIDs, member.UserID)
+ }
+ if _, ok := temp[opUserID]; !ok {
+ userIDs = append(userIDs, opUserID)
+ }
+ dbMembers, err := s.db.FindGroupMembers(ctx, groupID, userIDs)
+ if err != nil {
+ return nil, err
+ }
+ opUserIndex := -1
+ for i, member := range dbMembers {
if member.UserID == opUserID {
- if member.RoleLevel != nil {
- return nil, errs.ErrNoPermission.Wrap("can not change self role level")
- }
- continue
+ opUserIndex = i
+ break
}
- if opMember.RoleLevel == constant.GroupOrdinaryUsers {
- return nil, errs.ErrNoPermission.Wrap("ordinary users can not change other role level")
+ }
+ switch len(userIDs) - len(dbMembers) {
+ case 0:
+ if !isAppManagerUid {
+ roleLevel := dbMembers[opUserIndex].RoleLevel
+ if roleLevel != constant.GroupOwner {
+ switch roleLevel {
+ case constant.GroupAdmin:
+ for _, member := range dbMembers {
+ if member.RoleLevel == constant.GroupOwner {
+ return nil, errs.ErrNoPermission.Wrap("admin can not change group owner")
+ }
+ if member.RoleLevel == constant.GroupAdmin && member.UserID != opUserID {
+ return nil, errs.ErrNoPermission.Wrap("admin can not change other group admin")
+ }
+ }
+ case constant.GroupOrdinaryUsers:
+ for _, member := range dbMembers {
+ if !(member.RoleLevel == constant.GroupOrdinaryUsers && member.UserID == opUserID) {
+ return nil, errs.ErrNoPermission.Wrap("ordinary users can not change other role level")
+ }
+ }
+ default:
+ for _, member := range dbMembers {
+ if member.RoleLevel >= roleLevel {
+ return nil, errs.ErrNoPermission.Wrap("can not change higher role level")
+ }
+ }
+ }
+ }
}
- dbMember, ok := memberMap[[...]string{member.GroupID, member.UserID}]
- if !ok {
- return nil, errs.ErrRecordNotFound.Wrap(fmt.Sprintf("user %s not in group %s", member.UserID, member.GroupID))
+ case 1:
+ if opUserIndex >= 0 {
+ return nil, errs.ErrArgs.Wrap("user not in group")
}
- //if opMember.RoleLevel == constant.GroupOwner {
- // continue
- //}
- //if dbMember.RoleLevel == constant.GroupOwner {
- // return nil, errs.ErrNoPermission.Wrap("change group owner")
- //}
- //if opMember.RoleLevel == constant.GroupAdmin && dbMember.RoleLevel == constant.GroupAdmin {
- // return nil, errs.ErrNoPermission.Wrap("admin can not change other admin role info")
- //}
- switch opMember.RoleLevel {
- case constant.GroupOrdinaryUsers:
- return nil, errs.ErrNoPermission.Wrap("ordinary users can not change other role level")
- case constant.GroupAdmin:
- if dbMember.RoleLevel != constant.GroupOrdinaryUsers {
- return nil, errs.ErrNoPermission.Wrap("admin can not change other role level")
- }
- if member.RoleLevel != nil {
- return nil, errs.ErrNoPermission.Wrap("admin can not change other role level")
- }
- case constant.GroupOwner:
- //if member.RoleLevel != nil && member.RoleLevel.Value == constant.GroupOwner {
- // return nil, errs.ErrNoPermission.Wrap("owner only one")
- //}
+ if !isAppManagerUid {
+ return nil, errs.ErrNoPermission.Wrap("user not in group")
}
- }
- }
- for _, member := range req.Members {
- if member.RoleLevel == nil {
- continue
- }
- if memberMap[[...]string{member.GroupID, member.UserID}].RoleLevel == constant.GroupOwner {
- return nil, errs.ErrArgs.Wrap(fmt.Sprintf("group %s user %s is owner", member.GroupID, member.UserID))
+ default:
+ return nil, errs.ErrArgs.Wrap("user not in group")
}
}
for i := 0; i < len(req.Members); i++ {
@@ -1483,7 +1391,7 @@ func (s *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbgroup.SetGr
return nil, err
}
}
- if err = s.GroupDatabase.UpdateGroupMembers(ctx, utils.Slice(req.Members, func(e *pbgroup.SetGroupMemberInfo) *relationtb.BatchUpdateGroupMember {
+ if err := s.db.UpdateGroupMembers(ctx, utils.Slice(req.Members, func(e *pbgroup.SetGroupMemberInfo) *relationtb.BatchUpdateGroupMember {
return &relationtb.BatchUpdateGroupMember{
GroupID: e.GroupID,
UserID: e.UserID,
@@ -1502,10 +1410,7 @@ func (s *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbgroup.SetGr
}
}
if member.Nickname != nil || member.FaceURL != nil || member.Ex != nil {
- log.ZDebug(ctx, "setGroupMemberInfo notification", "member", member.UserID)
- if err := s.Notification.GroupMemberInfoSetNotification(ctx, member.GroupID, member.UserID); err != nil {
- log.ZError(ctx, "setGroupMemberInfo notification failed", err, "member", member.UserID, "groupID", member.GroupID)
- }
+ s.Notification.GroupMemberInfoSetNotification(ctx, member.GroupID, member.UserID)
}
}
for i := 0; i < len(req.Members); i++ {
@@ -1525,7 +1430,7 @@ func (s *groupServer) GetGroupAbstractInfo(ctx context.Context, req *pbgroup.Get
if utils.Duplicate(req.GroupIDs) {
return nil, errs.ErrArgs.Wrap("groupIDs duplicate")
}
- groups, err := s.GroupDatabase.FindGroup(ctx, req.GroupIDs)
+ groups, err := s.db.FindGroup(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
@@ -1534,7 +1439,7 @@ func (s *groupServer) GetGroupAbstractInfo(ctx context.Context, req *pbgroup.Get
})); len(ids) > 0 {
return nil, errs.ErrGroupIDNotFound.Wrap("not found group " + strings.Join(ids, ","))
}
- groupUserMap, err := s.GroupDatabase.MapGroupMemberUserID(ctx, req.GroupIDs)
+ groupUserMap, err := s.db.MapGroupMemberUserID(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
@@ -1553,25 +1458,14 @@ func (s *groupServer) GetUserInGroupMembers(ctx context.Context, req *pbgroup.Ge
if len(req.GroupIDs) == 0 {
return nil, errs.ErrArgs.Wrap("groupIDs empty")
}
- members, err := s.FindGroupMember(ctx, []string{req.UserID}, req.GroupIDs, nil)
+ members, err := s.db.FindGroupMemberUser(ctx, req.GroupIDs, req.UserID)
if err != nil {
return nil, err
}
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
@@ -1579,7 +1473,7 @@ func (s *groupServer) GetUserInGroupMembers(ctx context.Context, req *pbgroup.Ge
func (s *groupServer) GetGroupMemberUserIDs(ctx context.Context, req *pbgroup.GetGroupMemberUserIDsReq) (resp *pbgroup.GetGroupMemberUserIDsResp, err error) {
resp = &pbgroup.GetGroupMemberUserIDsResp{}
- resp.UserIDs, err = s.GroupDatabase.FindGroupMemberUserID(ctx, req.GroupID)
+ resp.UserIDs, err = s.db.FindGroupMemberUserID(ctx, req.GroupID)
if err != nil {
return nil, err
}
@@ -1591,25 +1485,14 @@ func (s *groupServer) GetGroupMemberRoleLevel(ctx context.Context, req *pbgroup.
if len(req.RoleLevels) == 0 {
return nil, errs.ErrArgs.Wrap("RoleLevels empty")
}
- members, err := s.FindGroupMember(ctx, []string{req.GroupID}, nil, req.RoleLevels)
+ members, err := s.db.FindGroupMemberRoleLevels(ctx, req.GroupID, req.RoleLevels)
if err != nil {
return nil, err
}
- publicUserInfoMap, err := s.GetPublicUserInfoMap(ctx, utils.Filter(members, func(e *relationtb.GroupMemberModel) (string, bool) {
- return e.UserID, e.Nickname == "" || e.FaceURL == ""
- }), true)
- if err != nil {
+ if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
- if userInfo, ok := publicUserInfoMap[e.UserID]; ok {
- if e.Nickname == "" {
- e.Nickname = userInfo.Nickname
- }
- if e.FaceURL == "" {
- e.FaceURL = userInfo.FaceURL
- }
- }
return convert.Db2PbGroupMember(e)
})
return resp, nil
@@ -1617,7 +1500,7 @@ func (s *groupServer) GetGroupMemberRoleLevel(ctx context.Context, req *pbgroup.
func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *pbgroup.GetGroupUsersReqApplicationListReq) (*pbgroup.GetGroupUsersReqApplicationListResp, error) {
resp := &pbgroup.GetGroupUsersReqApplicationListResp{}
- total, requests, err := s.GroupDatabase.FindGroupRequests(ctx, req.GroupID, req.UserIDs)
+ requests, err := s.db.FindGroupRequests(ctx, req.GroupID, req.UserIDs)
if err != nil {
return nil, err
}
@@ -1627,7 +1510,7 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
groupIDs := utils.Distinct(utils.Slice(requests, func(e *relationtb.GroupRequestModel) string {
return e.GroupID
}))
- groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
+ groups, err := s.db.FindGroup(ctx, groupIDs)
if err != nil {
return nil, err
}
@@ -1637,14 +1520,17 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
if ids := utils.Single(groupIDs, utils.Keys(groupMap)); len(ids) > 0 {
return nil, errs.ErrGroupIDNotFound.Wrap(strings.Join(ids, ","))
}
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
+ owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
+ if err := s.PopulateGroupMember(ctx, owners...); err != nil {
+ return nil, err
+ }
ownerMap := utils.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})
- groupMemberNum, err := s.GroupDatabase.MapGroupMemberNum(ctx, groupIDs)
+ groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}
@@ -1655,40 +1541,6 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
}
return convert.Db2PbGroupRequest(e, nil, convert.Db2PbGroupInfo(groupMap[e.GroupID], ownerUserID, groupMemberNum[e.GroupID]))
})
- resp.Total = total
+ resp.Total = int64(len(resp.GroupRequests))
return resp, nil
}
-
-func (s *groupServer) groupMemberHashCode(ctx context.Context, groupID string) (uint64, error) {
- userIDs, err := s.GroupDatabase.FindGroupMemberUserID(ctx, groupID)
- if err != nil {
- return 0, err
- }
- var members []*sdkws.GroupMemberFullInfo
- if len(userIDs) > 0 {
- resp, err := s.GetGroupMembersInfo(ctx, &pbgroup.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs})
- if err != nil {
- return 0, err
- }
- members = resp.Members
- utils.Sort(userIDs, true)
- }
- memberMap := utils.SliceToMap(members, func(e *sdkws.GroupMemberFullInfo) string {
- return e.UserID
- })
- res := make([]*sdkws.GroupMemberFullInfo, 0, len(members))
- for _, userID := range userIDs {
- member, ok := memberMap[userID]
- if !ok {
- continue
- }
- member.AppMangerLevel = 0
- res = append(res, member)
- }
- data, err := json.Marshal(res)
- if err != nil {
- return 0, err
- }
- sum := md5.Sum(data)
- return binary.BigEndian.Uint64(sum[:]), nil
-}
diff --git a/internal/rpc/group/statistics.go b/internal/rpc/group/statistics.go
index 8aeefbee3..d909e9503 100644
--- a/internal/rpc/group/statistics.go
+++ b/internal/rpc/group/statistics.go
@@ -26,16 +26,16 @@ func (s *groupServer) GroupCreateCount(ctx context.Context, req *group.GroupCrea
if req.Start > req.End {
return nil, errs.ErrArgs.Wrap("start > end")
}
- total, err := s.GroupDatabase.CountTotal(ctx, nil)
+ total, err := s.db.CountTotal(ctx, nil)
if err != nil {
return nil, err
}
start := time.UnixMilli(req.Start)
- before, err := s.GroupDatabase.CountTotal(ctx, &start)
+ before, err := s.db.CountTotal(ctx, &start)
if err != nil {
return nil, err
}
- count, err := s.GroupDatabase.CountRangeEverydayTotal(ctx, start, time.UnixMilli(req.End))
+ count, err := s.db.CountRangeEverydayTotal(ctx, start, time.UnixMilli(req.End))
if err != nil {
return nil, err
}
diff --git a/internal/rpc/group/super_group.go b/internal/rpc/group/super_group.go
index 6cd1a2943..f893a79c2 100644
--- a/internal/rpc/group/super_group.go
+++ b/internal/rpc/group/super_group.go
@@ -16,99 +16,15 @@ package group
import (
"context"
- "fmt"
- "strings"
+ "errors"
- "github.com/OpenIMSDK/protocol/constant"
pbgroup "github.com/OpenIMSDK/protocol/group"
- sdkws "github.com/OpenIMSDK/protocol/sdkws"
- "github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/convert"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
)
-func (s *groupServer) GetJoinedSuperGroupList(
- ctx context.Context,
- req *pbgroup.GetJoinedSuperGroupListReq,
-) (*pbgroup.GetJoinedSuperGroupListResp, error) {
- resp := &pbgroup.GetJoinedSuperGroupListResp{}
- groupIDs, err := s.GroupDatabase.FindJoinSuperGroup(ctx, req.UserID)
- if err != nil {
- return nil, err
- }
- if len(groupIDs) == 0 {
- return resp, nil
- }
- owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
- if err != nil {
- return nil, err
- }
- ownerMap := utils.SliceToMap(owners, func(e *relation.GroupMemberModel) string {
- return e.GroupID
- })
- if ids := utils.Single(groupIDs, utils.Keys(ownerMap)); len(ids) > 0 {
- return nil, errs.ErrData.Wrap(fmt.Sprintf("super group %s not owner", strings.Join(ids, ",")))
- }
- groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
- if err != nil {
- return nil, err
- }
- groupMap := utils.SliceToMap(groups, func(e *relation.GroupModel) string {
- return e.GroupID
- })
- if ids := utils.Single(groupIDs, utils.Keys(groupMap)); len(ids) > 0 {
- return nil, errs.ErrData.Wrap(fmt.Sprintf("super group info %s not found", strings.Join(ids, ",")))
- }
- superGroupMembers, err := s.GroupDatabase.FindSuperGroup(ctx, groupIDs)
- if err != nil {
- return nil, err
- }
- superGroupMemberMap := utils.SliceToMapAny(
- superGroupMembers,
- func(e *unrelation.SuperGroupModel) (string, []string) {
- return e.GroupID, e.MemberIDs
- },
- )
- resp.Groups = utils.Slice(groupIDs, func(groupID string) *sdkws.GroupInfo {
- return convert.Db2PbGroupInfo(groupMap[groupID], ownerMap[groupID].UserID, uint32(len(superGroupMemberMap)))
- })
- return resp, nil
+func (s *groupServer) GetJoinedSuperGroupList(context.Context, *pbgroup.GetJoinedSuperGroupListReq) (*pbgroup.GetJoinedSuperGroupListResp, error) {
+ return nil, errors.New("deprecated")
}
-func (s *groupServer) GetSuperGroupsInfo(
- ctx context.Context,
- req *pbgroup.GetSuperGroupsInfoReq,
-) (resp *pbgroup.GetSuperGroupsInfoResp, err error) {
- resp = &pbgroup.GetSuperGroupsInfoResp{}
- if len(req.GroupIDs) == 0 {
- return nil, errs.ErrArgs.Wrap("groupIDs empty")
- }
- groups, err := s.GroupDatabase.FindGroup(ctx, req.GroupIDs)
- if err != nil {
- return nil, err
- }
- superGroupMembers, err := s.GroupDatabase.FindSuperGroup(ctx, req.GroupIDs)
- if err != nil {
- return nil, err
- }
- superGroupMemberMap := utils.SliceToMapAny(
- superGroupMembers,
- func(e *unrelation.SuperGroupModel) (string, []string) {
- return e.GroupID, e.MemberIDs
- },
- )
- owners, err := s.FindGroupMember(ctx, req.GroupIDs, nil, []int32{constant.GroupOwner})
- if err != nil {
- return nil, err
- }
- ownerMap := utils.SliceToMap(owners, func(e *relation.GroupMemberModel) string {
- return e.GroupID
- })
- resp.GroupInfos = utils.Slice(groups, func(e *relation.GroupModel) *sdkws.GroupInfo {
- return convert.Db2PbGroupInfo(e, ownerMap[e.GroupID].UserID, uint32(len(superGroupMemberMap[e.GroupID])))
- })
- return resp, nil
+func (s *groupServer) GetSuperGroupsInfo(context.Context, *pbgroup.GetSuperGroupsInfoReq) (resp *pbgroup.GetSuperGroupsInfoResp, err error) {
+ return nil, errors.New("deprecated")
}
diff --git a/internal/rpc/msg/utils.go b/internal/rpc/msg/utils.go
index 115df9946..e45d7b395 100644
--- a/internal/rpc/msg/utils.go
+++ b/internal/rpc/msg/utils.go
@@ -15,12 +15,11 @@
package msg
import (
- "github.com/redis/go-redis/v9"
- "gorm.io/gorm"
-
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
+ "github.com/redis/go-redis/v9"
+ "go.mongodb.org/mongo-driver/mongo"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
)
@@ -45,7 +44,7 @@ func isMessageHasReadEnabled(msgData *sdkws.MsgData) bool {
func IsNotFound(err error) bool {
switch utils.Unwrap(err) {
- case redis.Nil, gorm.ErrRecordNotFound:
+ case redis.Nil, mongo.ErrNoDocuments:
return true
default:
return false
diff --git a/internal/rpc/third/log.go b/internal/rpc/third/log.go
index aa83f58f7..57d4f536e 100644
--- a/internal/rpc/third/log.go
+++ b/internal/rpc/third/log.go
@@ -32,11 +32,11 @@ func genLogID() string {
}
func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq) (*third.UploadLogsResp, error) {
- var DBlogs []*relationtb.Log
+ var DBlogs []*relationtb.LogModel
userID := ctx.Value(constant.OpUserID).(string)
platform := constant.PlatformID2Name[int(req.Platform)]
for _, fileURL := range req.FileURLs {
- log := relationtb.Log{
+ log := relationtb.LogModel{
Version: req.Version,
SystemType: req.SystemType,
Platform: platform,
@@ -57,7 +57,7 @@ func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq)
}
}
if log.LogID == "" {
- return nil, errs.ErrData.Wrap("Log id gen error")
+ return nil, errs.ErrData.Wrap("LogModel id gen error")
}
DBlogs = append(DBlogs, &log)
}
@@ -92,8 +92,8 @@ func (t *thirdServer) DeleteLogs(ctx context.Context, req *third.DeleteLogsReq)
return &third.DeleteLogsResp{}, nil
}
-func dbToPbLogInfos(logs []*relationtb.Log) []*third.LogInfo {
- db2pbForLogInfo := func(log *relationtb.Log) *third.LogInfo {
+func dbToPbLogInfos(logs []*relationtb.LogModel) []*third.LogInfo {
+ db2pbForLogInfo := func(log *relationtb.LogModel) *third.LogInfo {
return &third.LogInfo{
Filename: log.FileName,
UserID: log.UserID,
@@ -120,7 +120,7 @@ func (t *thirdServer) SearchLogs(ctx context.Context, req *third.SearchLogsReq)
if req.StartTime > req.EndTime {
return nil, errs.ErrArgs.Wrap("startTime>endTime")
}
- total, logs, err := t.thirdDatabase.SearchLogs(ctx, req.Keyword, time.UnixMilli(req.StartTime), time.UnixMilli(req.EndTime), req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, logs, err := t.thirdDatabase.SearchLogs(ctx, req.Keyword, time.UnixMilli(req.StartTime), time.UnixMilli(req.EndTime), req.Pagination)
if err != nil {
return nil, err
}
@@ -128,18 +128,16 @@ func (t *thirdServer) SearchLogs(ctx context.Context, req *third.SearchLogsReq)
for _, log := range logs {
userIDs = append(userIDs, log.UserID)
}
- users, err := t.thirdDatabase.FindUsers(ctx, userIDs)
+ userMap, err := t.userRpcClient.GetUsersInfoMap(ctx, userIDs)
if err != nil {
return nil, err
}
- IDtoName := make(map[string]string)
- for _, user := range users {
- IDtoName[user.UserID] = user.Nickname
- }
for _, pbLog := range pbLogs {
- pbLog.Nickname = IDtoName[pbLog.UserID]
+ if user, ok := userMap[pbLog.UserID]; ok {
+ pbLog.Nickname = user.Nickname
+ }
}
resp.LogsInfos = pbLogs
- resp.Total = total
+ resp.Total = uint32(total)
return &resp, nil
}
diff --git a/internal/rpc/third/s3.go b/internal/rpc/third/s3.go
index 984af88e1..ca826e805 100644
--- a/internal/rpc/third/s3.go
+++ b/internal/rpc/third/s3.go
@@ -64,7 +64,7 @@ func (t *thirdServer) InitiateMultipartUpload(ctx context.Context, req *third.In
Key: haErr.Object.Key,
Size: haErr.Object.Size,
ContentType: req.ContentType,
- Cause: req.Cause,
+ Group: req.Cause,
CreateTime: time.Now(),
}
if err := t.s3dataBase.SetObject(ctx, obj); err != nil {
@@ -143,7 +143,7 @@ func (t *thirdServer) CompleteMultipartUpload(ctx context.Context, req *third.Co
Key: result.Key,
Size: result.Size,
ContentType: req.ContentType,
- Cause: req.Cause,
+ Group: req.Cause,
CreateTime: time.Now(),
}
if err := t.s3dataBase.SetObject(ctx, obj); err != nil {
diff --git a/internal/rpc/third/third.go b/internal/rpc/third/third.go
index eed3d4802..7a63d3526 100644
--- a/internal/rpc/third/third.go
+++ b/internal/rpc/third/third.go
@@ -17,15 +17,17 @@ package third
import (
"context"
"fmt"
-
"net/url"
"time"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
+
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/cos"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/kodo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/minio"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/oss"
+
"google.golang.org/grpc"
"github.com/OpenIMSDK/protocol/third"
@@ -34,13 +36,22 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
)
func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
+ mongo, err := unrelation.NewMongo()
+ if err != nil {
+ return err
+ }
+ logdb, err := mgo.NewLogMongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
+ s3db, err := mgo.NewS3Mongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
apiURL := config.Config.Object.ApiURL
if apiURL == "" {
return fmt.Errorf("api url is empty")
@@ -56,13 +67,6 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
if err != nil {
return err
}
- db, err := relation.NewGormDB()
- if err != nil {
- return err
- }
- if err := db.AutoMigrate(&relationtb.ObjectModel{}); err != nil {
- return err
- }
// 根据配置文件策略选择 oss 方式
enable := config.Config.Object.Enable
var o s3.Interface
@@ -73,25 +77,17 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
o, err = cos.NewCos()
case "oss":
o, err = oss.NewOSS()
- case "kodo":
- o, err = kodo.NewKodo()
default:
err = fmt.Errorf("invalid object enable: %s", enable)
}
if err != nil {
return err
}
- //specialerror.AddErrHandler(func(err error) errs.CodeError {
- // if o.IsNotFound(err) {
- // return errs.ErrRecordNotFound
- // }
- // return nil
- //})
third.RegisterThirdServer(server, &thirdServer{
apiURL: apiURL,
- thirdDatabase: controller.NewThirdDatabase(cache.NewMsgCacheModel(rdb), db),
+ thirdDatabase: controller.NewThirdDatabase(cache.NewMsgCacheModel(rdb), logdb),
userRpcClient: rpcclient.NewUserRpcClient(client),
- s3dataBase: controller.NewS3Database(rdb, o, relation.NewObjectInfo(db)),
+ s3dataBase: controller.NewS3Database(rdb, o, s3db),
defaultExpire: time.Hour * 24 * 7,
})
return nil
diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go
index f048db626..dd49e2167 100644
--- a/internal/rpc/user/user.go
+++ b/internal/rpc/user/user.go
@@ -20,11 +20,14 @@ import (
"strings"
"time"
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
- "github.com/OpenIMSDK/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
@@ -35,7 +38,6 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
@@ -55,10 +57,6 @@ type userServer struct {
}
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
- db, err := relation.NewGormDB()
- if err != nil {
- return err
- }
rdb, err := cache.NewRedis()
if err != nil {
return err
@@ -67,9 +65,6 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
if err != nil {
return err
}
- if err := db.AutoMigrate(&tablerelation.UserModel{}); err != nil {
- return err
- }
users := make([]*tablerelation.UserModel, 0)
if len(config.Config.Manager.UserID) != len(config.Config.Manager.Nickname) {
return errors.New("len(config.Config.Manager.AppManagerUid) != len(config.Config.Manager.Nickname)")
@@ -77,10 +72,13 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
for k, v := range config.Config.Manager.UserID {
users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.Manager.Nickname[k], AppMangerLevel: constant.AppAdmin})
}
- userDB := relation.NewUserGorm(db)
+ userDB, err := mgo.NewUserMongo(mongo.GetDatabase())
+ if err != nil {
+ return err
+ }
cache := cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
- database := controller.NewUserDatabase(userDB, cache, tx.NewGorm(db), userMongoDB)
+ database := controller.NewUserDatabase(userDB, cache, tx.NewMongo(mongo.GetClient()), userMongoDB)
friendRpcClient := rpcclient.NewFriendRpcClient(client)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)
@@ -118,12 +116,8 @@ func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserI
if err := CallbackBeforeUpdateUserInfo(ctx, req); err != nil {
return nil, err
}
- user := convert.UserPb2DB(req.UserInfo)
- if err != nil {
- return nil, err
- }
- err = s.Update(ctx, user)
- if err != nil {
+ data := convert.UserPb2DBMap(req.UserInfo)
+ if err := s.UpdateByMap(ctx, req.UserInfo.UserID, data); err != nil {
return nil, err
}
_ = s.friendNotificationSender.UserInfoUpdatedNotification(ctx, req.UserInfo.UserID)
@@ -153,7 +147,7 @@ func (s *userServer) SetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.Se
if _, err := s.FindWithError(ctx, []string{req.UserID}); err != nil {
return nil, err
}
- m := make(map[string]interface{}, 1)
+ m := make(map[string]any, 1)
m["global_recv_msg_opt"] = req.GlobalRecvMsgOpt
if err := s.UpdateByMap(ctx, req.UserID, m); err != nil {
return nil, err
@@ -175,7 +169,7 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
if err != nil {
return nil, err
}
- userIDs := make(map[string]interface{}, 0)
+ userIDs := make(map[string]any, 0)
for _, v := range users {
userIDs[v.UserID] = nil
}
@@ -192,12 +186,7 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
}
func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPaginationUsersReq) (resp *pbuser.GetPaginationUsersResp, err error) {
- var pageNumber, showNumber int32
- if req.Pagination != nil {
- pageNumber = req.Pagination.PageNumber
- showNumber = req.Pagination.ShowNumber
- }
- users, total, err := s.Page(ctx, pageNumber, showNumber)
+ total, users, err := s.Page(ctx, req.Pagination)
if err != nil {
return nil, err
}
@@ -269,11 +258,11 @@ func (s *userServer) GetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.Ge
// GetAllUserID Get user account by page.
func (s *userServer) GetAllUserID(ctx context.Context, req *pbuser.GetAllUserIDReq) (resp *pbuser.GetAllUserIDResp, err error) {
- userIDs, err := s.UserDatabase.GetAllUserID(ctx, req.Pagination.PageNumber, req.Pagination.ShowNumber)
+ total, userIDs, err := s.UserDatabase.GetAllUserID(ctx, req.Pagination)
if err != nil {
return nil, err
}
- return &pbuser.GetAllUserIDResp{UserIDs: userIDs}, nil
+ return &pbuser.GetAllUserIDResp{Total: int32(total), UserIDs: userIDs}, nil
}
// SubscribeOrCancelUsersStatus Subscribe online or cancel online users.
diff --git a/internal/tools/conversation.go b/internal/tools/conversation.go
index 05d963a17..0d0275339 100644
--- a/internal/tools/conversation.go
+++ b/internal/tools/conversation.go
@@ -19,6 +19,8 @@ import (
"math/rand"
"time"
+ "github.com/OpenIMSDK/protocol/sdkws"
+
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/utils"
@@ -91,7 +93,11 @@ func (c *MsgTool) ConversationsDestructMsgs() {
}
for i := 0; i < count; i++ {
pageNumber := rand.Int63() % maxPage
- conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, int32(pageNumber), batchNum)
+ pagination := &sdkws.RequestPagination{
+ PageNumber: int32(pageNumber),
+ ShowNumber: batchNum,
+ }
+ conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination)
if err != nil {
log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber)
continue
@@ -133,7 +139,7 @@ func (c *MsgTool) ConversationsDestructMsgs() {
continue
}
if len(seqs) > 0 {
- if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]interface{}{"latest_msg_destruct_time": now}); err != nil {
+ if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]any{"latest_msg_destruct_time": now}); err != nil {
log.ZError(ctx, "updateUsersConversationFiled failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID)
continue
}
diff --git a/internal/tools/msg.go b/internal/tools/msg.go
index ad8f5c471..97bb2988e 100644
--- a/internal/tools/msg.go
+++ b/internal/tools/msg.go
@@ -19,6 +19,11 @@ import (
"fmt"
"math"
+ "github.com/OpenIMSDK/protocol/sdkws"
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+
"github.com/redis/go-redis/v9"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
@@ -31,13 +36,11 @@ import (
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/mw"
- "github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
@@ -72,33 +75,45 @@ func InitMsgTool() (*MsgTool, error) {
if err != nil {
return nil, err
}
- db, err := relation.NewGormDB()
+ discov, err := kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery)
if err != nil {
return nil, err
}
- discov, err := kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery)
- /*
- discov, err := zookeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema,
- zookeeper.WithFreq(time.Hour), zookeeper.WithRoundRobin(), zookeeper.WithUserNameAndPassword(config.Config.Zookeeper.Username,
- config.Config.Zookeeper.Password), zookeeper.WithTimeout(10), zookeeper.WithLogger(log.NewZkLogger()))*/
+ discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
+ userDB, err := mgo.NewUserMongo(mongo.GetDatabase())
if err != nil {
return nil, err
}
- discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
- userDB := relation.NewUserGorm(db)
msgDatabase := controller.InitCommonMsgDatabase(rdb, mongo.GetDatabase())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
+ ctxTx := tx.NewMongo(mongo.GetClient())
userDatabase := controller.NewUserDatabase(
userDB,
- cache.NewUserCacheRedis(rdb, relation.NewUserGorm(db), cache.GetDefaultOpt()),
- tx.NewGorm(db),
+ cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt()),
+ ctxTx,
userMongoDB,
)
- groupDatabase := controller.InitGroupDatabase(db, rdb, mongo.GetDatabase(), nil)
+ groupDB, err := mgo.NewGroupMongo(mongo.GetDatabase())
+ if err != nil {
+ return nil, err
+ }
+ groupMemberDB, err := mgo.NewGroupMember(mongo.GetDatabase())
+ if err != nil {
+ return nil, err
+ }
+ groupRequestDB, err := mgo.NewGroupRequestMgo(mongo.GetDatabase())
+ if err != nil {
+ return nil, err
+ }
+ conversationDB, err := mgo.NewConversationMongo(mongo.GetDatabase())
+ if err != nil {
+ return nil, err
+ }
+ groupDatabase := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, ctxTx, nil)
conversationDatabase := controller.NewConversationDatabase(
- relation.NewConversationGorm(db),
- cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), relation.NewConversationGorm(db)),
- tx.NewGorm(db),
+ conversationDB,
+ cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB),
+ ctxTx,
)
msgRpcClient := rpcclient.NewMessageRpcClient(discov)
msgNotificationSender := notification.NewMsgNotificationSender(rpcclient.WithRpcClient(&msgRpcClient))
@@ -144,7 +159,11 @@ func (c *MsgTool) AllConversationClearMsgAndFixSeq() {
}
for i := 0; i < count; i++ {
pageNumber := rand.Int63() % maxPage
- conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, int32(pageNumber), batchNum)
+ pagination := &sdkws.RequestPagination{
+ PageNumber: int32(pageNumber),
+ ShowNumber: batchNum,
+ }
+ conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination)
if err != nil {
log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber)
continue
diff --git a/internal/tools/msg_doc_convert.go b/internal/tools/msg_doc_convert.go
index 758625be1..b9150c362 100644
--- a/internal/tools/msg_doc_convert.go
+++ b/internal/tools/msg_doc_convert.go
@@ -32,7 +32,7 @@ func (c *MsgTool) convertTools() {
for _, conversationID := range conversationIDs {
conversationIDs = append(conversationIDs, msgprocessor.GetNotificationConversationIDByConversationID(conversationID))
}
- userIDs, err := c.userDatabase.GetAllUserID(ctx, 0, 0)
+ _, userIDs, err := c.userDatabase.GetAllUserID(ctx, nil)
if err != nil {
log.ZError(ctx, "get all user ids failed", err)
return
diff --git a/pkg/apistruct/manage.go b/pkg/apistruct/manage.go
index 1e0ab3214..a48f5253c 100644
--- a/pkg/apistruct/manage.go
+++ b/pkg/apistruct/manage.go
@@ -36,7 +36,7 @@ type SendMsg struct {
SenderPlatformID int32 `json:"senderPlatformID"`
// Content is the actual content of the message, required and excluded from Swagger documentation.
- Content map[string]interface{} `json:"content" binding:"required" swaggerignore:"true"`
+ Content map[string]any `json:"content" binding:"required" swaggerignore:"true"`
// ContentType is an integer that represents the type of the content.
ContentType int32 `json:"contentType" binding:"required"`
diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go
index a8e577fde..fd01e8c5a 100644
--- a/pkg/authverify/token.go
+++ b/pkg/authverify/token.go
@@ -28,7 +28,7 @@ import (
)
func Secret() jwt.Keyfunc {
- return func(token *jwt.Token) (interface{}, error) {
+ return func(token *jwt.Token) (any, error) {
return []byte(config.Config.Secret), nil
}
}
@@ -55,7 +55,7 @@ func CheckAdmin(ctx context.Context) error {
return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx)))
}
-func ParseRedisInterfaceToken(redisToken interface{}) (*tokenverify.Claims, error) {
+func ParseRedisInterfaceToken(redisToken any) (*tokenverify.Claims, error) {
return tokenverify.GetClaimFromToken(string(redisToken.([]uint8)), Secret())
}
diff --git a/pkg/common/cmd/rpc.go b/pkg/common/cmd/rpc.go
index 6266c03b2..ea2a00b07 100644
--- a/pkg/common/cmd/rpc.go
+++ b/pkg/common/cmd/rpc.go
@@ -46,15 +46,13 @@ func (a *RpcCmd) Exec() error {
return a.Execute()
}
-func (a *RpcCmd) StartSvr(
- name string,
- rpcFn func(discov discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error,
-) error {
+func (a *RpcCmd) StartSvr(name string, rpcFn func(discov discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error) error {
if a.GetPortFlag() == 0 {
return errors.New("port is required")
}
return startrpc.Start(a.GetPortFlag(), name, a.GetPrometheusPortFlag(), rpcFn)
}
+
func (a *RpcCmd) GetPortFromConfig(portType string) int {
switch a.Name {
case RpcPushServer:
diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go
index 3c819ea2c..5fb8fe7e2 100644
--- a/pkg/common/config/config.go
+++ b/pkg/common/config/config.go
@@ -44,6 +44,18 @@ type POfflinePush struct {
Ext string `yaml:"ext"`
}
+type MYSQL struct {
+ Address []string `yaml:"address"`
+ Username string `yaml:"username"`
+ Password string `yaml:"password"`
+ Database string `yaml:"database"`
+ MaxOpenConn int `yaml:"maxOpenConn"`
+ MaxIdleConn int `yaml:"maxIdleConn"`
+ MaxLifeTime int `yaml:"maxLifeTime"`
+ LogLevel int `yaml:"logLevel"`
+ SlowThreshold int `yaml:"slowThreshold"`
+}
+
type configStruct struct {
Envs struct {
Discovery string `yaml:"discovery"`
@@ -55,17 +67,7 @@ type configStruct struct {
Password string `yaml:"password"`
} `yaml:"zookeeper"`
- Mysql struct {
- Address []string `yaml:"address"`
- Username string `yaml:"username"`
- Password string `yaml:"password"`
- Database string `yaml:"database"`
- MaxOpenConn int `yaml:"maxOpenConn"`
- MaxIdleConn int `yaml:"maxIdleConn"`
- MaxLifeTime int `yaml:"maxLifeTime"`
- LogLevel int `yaml:"logLevel"`
- SlowThreshold int `yaml:"slowThreshold"`
- } `yaml:"mysql"`
+ Mysql *MYSQL `yaml:"mysql"`
Mongo struct {
Uri string `yaml:"uri"`
diff --git a/pkg/common/config/parse.go b/pkg/common/config/parse.go
index f2ea962ee..22e458e00 100644
--- a/pkg/common/config/parse.go
+++ b/pkg/common/config/parse.go
@@ -71,7 +71,7 @@ func GetOptionsByNotification(cfg NotificationConf) msgprocessor.Options {
return opts
}
-func initConfig(config interface{}, configName, configFolderPath string) error {
+func initConfig(config any, configName, configFolderPath string) error {
configFolderPath = filepath.Join(configFolderPath, configName)
_, err := os.Stat(configFolderPath)
if err != nil {
diff --git a/pkg/common/config/parse_test.go b/pkg/common/config/parse_test.go
index e34aa5b7f..38171ec08 100644
--- a/pkg/common/config/parse_test.go
+++ b/pkg/common/config/parse_test.go
@@ -76,7 +76,7 @@ func TestGetOptionsByNotification(t *testing.T) {
func Test_initConfig(t *testing.T) {
type args struct {
- config interface{}
+ config any
configName string
configFolderPath string
}
diff --git a/pkg/common/convert/friend.go b/pkg/common/convert/friend.go
index 7003c8aa6..c81cd98d6 100644
--- a/pkg/common/convert/friend.go
+++ b/pkg/common/convert/friend.go
@@ -16,6 +16,7 @@ package convert
import (
"context"
+ "fmt"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
@@ -31,23 +32,22 @@ func FriendPb2DB(friend *sdkws.FriendInfo) *relation.FriendModel {
return dbFriend
}
-func FriendDB2Pb(
- ctx context.Context,
- friendDB *relation.FriendModel,
+func FriendDB2Pb(ctx context.Context, friendDB *relation.FriendModel,
getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error),
) (*sdkws.FriendInfo, error) {
- pbfriend := &sdkws.FriendInfo{FriendUser: &sdkws.UserInfo{}}
- utils.CopyStructFields(pbfriend, friendDB)
users, err := getUsers(ctx, []string{friendDB.FriendUserID})
if err != nil {
return nil, err
}
- pbfriend.FriendUser.UserID = users[friendDB.FriendUserID].UserID
- pbfriend.FriendUser.Nickname = users[friendDB.FriendUserID].Nickname
- pbfriend.FriendUser.FaceURL = users[friendDB.FriendUserID].FaceURL
- pbfriend.FriendUser.Ex = users[friendDB.FriendUserID].Ex
- pbfriend.CreateTime = friendDB.CreateTime.Unix()
- return pbfriend, nil
+ user, ok := users[friendDB.FriendUserID]
+ if !ok {
+ return nil, fmt.Errorf("user not found: %s", friendDB.FriendUserID)
+ }
+
+ return &sdkws.FriendInfo{
+ FriendUser: user,
+ CreateTime: friendDB.CreateTime.Unix(),
+ }, nil
}
func FriendsDB2Pb(
@@ -118,3 +118,37 @@ func FriendRequestDB2Pb(
}
return res, nil
}
+
+// FriendPb2DBMap converts a FriendInfo protobuf object to a map suitable for database operations.
+// It only includes non-zero or non-empty fields in the map.
+func FriendPb2DBMap(friend *sdkws.FriendInfo) map[string]any {
+ if friend == nil {
+ return nil
+ }
+
+ val := make(map[string]any)
+
+ // Assuming FriendInfo has similar fields to those in FriendModel.
+ // Add or remove fields based on your actual FriendInfo and FriendModel structures.
+ if friend.FriendUser != nil {
+ if friend.FriendUser.UserID != "" {
+ val["friend_user_id"] = friend.FriendUser.UserID
+ }
+ if friend.FriendUser.Nickname != "" {
+ val["nickname"] = friend.FriendUser.Nickname
+ }
+ if friend.FriendUser.FaceURL != "" {
+ val["face_url"] = friend.FriendUser.FaceURL
+ }
+ if friend.FriendUser.Ex != "" {
+ val["ex"] = friend.FriendUser.Ex
+ }
+ }
+ if friend.CreateTime != 0 {
+ val["create_time"] = friend.CreateTime // You might need to convert this to a proper time format.
+ }
+
+ // Include other fields from FriendInfo as needed, similar to the above pattern.
+
+ return val
+}
diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go
index 4ca1899be..0c71aac22 100644
--- a/pkg/common/convert/user.go
+++ b/pkg/common/convert/user.go
@@ -16,32 +16,58 @@ package convert
import (
"github.com/OpenIMSDK/protocol/sdkws"
+ "time"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
-func UsersDB2Pb(users []*relationtb.UserModel) (result []*sdkws.UserInfo) {
+func UsersDB2Pb(users []*relationtb.UserModel) []*sdkws.UserInfo {
+ result := make([]*sdkws.UserInfo, 0, len(users))
for _, user := range users {
- var userPb sdkws.UserInfo
- userPb.UserID = user.UserID
- userPb.Nickname = user.Nickname
- userPb.FaceURL = user.FaceURL
- userPb.Ex = user.Ex
- userPb.CreateTime = user.CreateTime.UnixMilli()
- userPb.AppMangerLevel = user.AppMangerLevel
- userPb.GlobalRecvMsgOpt = user.GlobalRecvMsgOpt
- result = append(result, &userPb)
+ userPb := &sdkws.UserInfo{
+ UserID: user.UserID,
+ Nickname: user.Nickname,
+ FaceURL: user.FaceURL,
+ Ex: user.Ex,
+ CreateTime: user.CreateTime.UnixMilli(),
+ AppMangerLevel: user.AppMangerLevel,
+ GlobalRecvMsgOpt: user.GlobalRecvMsgOpt,
+ }
+ result = append(result, userPb)
}
return result
}
func UserPb2DB(user *sdkws.UserInfo) *relationtb.UserModel {
- var userDB relationtb.UserModel
- userDB.UserID = user.UserID
- userDB.Nickname = user.Nickname
- userDB.FaceURL = user.FaceURL
- userDB.Ex = user.Ex
- userDB.AppMangerLevel = user.AppMangerLevel
- userDB.GlobalRecvMsgOpt = user.GlobalRecvMsgOpt
- return &userDB
+ return &relationtb.UserModel{
+ UserID: user.UserID,
+ Nickname: user.Nickname,
+ FaceURL: user.FaceURL,
+ Ex: user.Ex,
+ CreateTime: time.UnixMilli(user.CreateTime),
+ AppMangerLevel: user.AppMangerLevel,
+ GlobalRecvMsgOpt: user.GlobalRecvMsgOpt,
+ }
+}
+
+func UserPb2DBMap(user *sdkws.UserInfo) map[string]any {
+ if user == nil {
+ return nil
+ }
+ val := make(map[string]any)
+ fields := map[string]any{
+ "nickname": user.Nickname,
+ "face_url": user.FaceURL,
+ "ex": user.Ex,
+ "app_manager_level": user.AppMangerLevel,
+ "global_recv_msg_opt": user.GlobalRecvMsgOpt,
+ }
+ for key, value := range fields {
+ if v, ok := value.(string); ok && v != "" {
+ val[key] = v
+ } else if v, ok := value.(int32); ok && v != 0 {
+ val[key] = v
+ }
+ }
+ return val
}
diff --git a/pkg/common/convert/user_test.go b/pkg/common/convert/user_test.go
new file mode 100644
index 000000000..a24efb53c
--- /dev/null
+++ b/pkg/common/convert/user_test.go
@@ -0,0 +1,87 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package convert
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/OpenIMSDK/protocol/sdkws"
+
+ relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func TestUsersDB2Pb(t *testing.T) {
+ type args struct {
+ users []*relationtb.UserModel
+ }
+ tests := []struct {
+ name string
+ args args
+ wantResult []*sdkws.UserInfo
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if gotResult := UsersDB2Pb(tt.args.users); !reflect.DeepEqual(gotResult, tt.wantResult) {
+ t.Errorf("UsersDB2Pb() = %v, want %v", gotResult, tt.wantResult)
+ }
+ })
+ }
+}
+
+func TestUserPb2DB(t *testing.T) {
+ type args struct {
+ user *sdkws.UserInfo
+ }
+ tests := []struct {
+ name string
+ args args
+ want *relationtb.UserModel
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := UserPb2DB(tt.args.user); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("UserPb2DB() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestUserPb2DBMap(t *testing.T) {
+ user := &sdkws.UserInfo{
+ Nickname: "TestUser",
+ FaceURL: "http://openim.io/logo.jpg",
+ Ex: "Extra Data",
+ AppMangerLevel: 1,
+ GlobalRecvMsgOpt: 2,
+ }
+
+ expected := map[string]any{
+ "nickname": "TestUser",
+ "face_url": "http://openim.io/logo.jpg",
+ "ex": "Extra Data",
+ "app_manager_level": int32(1),
+ "global_recv_msg_opt": int32(2),
+ }
+
+ result := UserPb2DBMap(user)
+ if !reflect.DeepEqual(result, expected) {
+ t.Errorf("UserPb2DBMap returned unexpected map. Got %v, want %v", result, expected)
+ }
+}
diff --git a/pkg/common/db/cache/conversation.go b/pkg/common/db/cache/conversation.go
index 9c0bcfae4..a7018bc18 100644
--- a/pkg/common/db/cache/conversation.go
+++ b/pkg/common/db/cache/conversation.go
@@ -26,7 +26,6 @@ import (
"github.com/OpenIMSDK/tools/utils"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
@@ -67,10 +66,10 @@ type ConversationCache interface {
GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
DelUserRecvMsgOpt(ownerUserID, conversationID string) ConversationCache
// get one super group recv msg but do not notification userID list
- GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error)
+ //GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error)
DelSuperGroupRecvMsgNotNotifyUserIDs(groupID string) ConversationCache
// get one super group recv msg but do not notification userID list hash
- GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error)
+ //GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error)
DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache
//GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
@@ -101,20 +100,20 @@ type ConversationRedisCache struct {
expireTime time.Duration
}
-func NewNewConversationRedis(
- rdb redis.UniversalClient,
- conversationDB *relation.ConversationGorm,
- options rockscache.Options,
-) ConversationCache {
- rcClient := rockscache.NewClient(rdb, options)
-
- return &ConversationRedisCache{
- rcClient: rcClient,
- metaCache: NewMetaCacheRedis(rcClient),
- conversationDB: conversationDB,
- expireTime: conversationExpireTime,
- }
-}
+//func NewNewConversationRedis(
+// rdb redis.UniversalClient,
+// conversationDB *relation.ConversationGorm,
+// options rockscache.Options,
+//) ConversationCache {
+// rcClient := rockscache.NewClient(rdb, options)
+//
+// return &ConversationRedisCache{
+// rcClient: rcClient,
+// metaCache: NewMetaCacheRedis(rcClient),
+// conversationDB: conversationDB,
+// expireTime: conversationExpireTime,
+// }
+//}
func (c *ConversationRedisCache) NewCache() ConversationCache {
return &ConversationRedisCache{
@@ -282,11 +281,11 @@ func (c *ConversationRedisCache) GetUserRecvMsgOpt(ctx context.Context, ownerUse
})
}
-func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error) {
- return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsKey(groupID), c.expireTime, func(ctx context.Context) (userIDs []string, err error) {
- return c.conversationDB.FindSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
- })
-}
+//func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error) {
+// return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsKey(groupID), c.expireTime, func(ctx context.Context) (userIDs []string, err error) {
+// return c.conversationDB.FindSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
+// })
+//}
func (c *ConversationRedisCache) DelUsersConversation(conversationID string, ownerUserIDs ...string) ConversationCache {
keys := make([]string, 0, len(ownerUserIDs))
@@ -313,19 +312,19 @@ func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDs(groupID st
return cache
}
-func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error) {
- return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsHashKey(groupID), c.expireTime, func(ctx context.Context) (hash uint64, err error) {
- userIDs, err := c.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
- if err != nil {
- return 0, err
- }
- utils.Sort(userIDs, true)
- bi := big.NewInt(0)
- bi.SetString(utils.Md5(strings.Join(userIDs, ";"))[0:8], 16)
- return bi.Uint64(), nil
- },
- )
-}
+//func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error) {
+// return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsHashKey(groupID), c.expireTime, func(ctx context.Context) (hash uint64, err error) {
+// userIDs, err := c.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
+// if err != nil {
+// return 0, err
+// }
+// utils.Sort(userIDs, true)
+// bi := big.NewInt(0)
+// bi.SetString(utils.Md5(strings.Join(userIDs, ";"))[0:8], 16)
+// return bi.Uint64(), nil
+// },
+// )
+//}
func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache {
cache := c.NewCache()
diff --git a/pkg/common/db/cache/friend.go b/pkg/common/db/cache/friend.go
index 64a358984..1708f7664 100644
--- a/pkg/common/db/cache/friend.go
+++ b/pkg/common/db/cache/friend.go
@@ -33,19 +33,20 @@ const (
friendKey = "FRIEND_INFO:"
)
-// args fn will exec when no data in msgCache.
+// FriendCache is an interface for caching friend-related data.
type FriendCache interface {
metaCache
NewCache() FriendCache
GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error)
- // call when friendID List changed
+ // Called when friendID list changed
DelFriendIDs(ownerUserID ...string) FriendCache
- // get single friendInfo from msgCache
+ // Get single friendInfo from the cache
GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error)
- // del friend when friend info changed
+ // Delete friend when friend info changed
DelFriend(ownerUserID, friendUserID string) FriendCache
}
+// FriendCacheRedis is an implementation of the FriendCache interface using Redis.
type FriendCacheRedis struct {
metaCache
friendDB relationtb.FriendModelInterface
@@ -53,6 +54,7 @@ type FriendCacheRedis struct {
rcClient *rockscache.Client
}
+// NewFriendCacheRedis creates a new instance of FriendCacheRedis.
func NewFriendCacheRedis(rdb redis.UniversalClient, friendDB relationtb.FriendModelInterface,
options rockscache.Options) FriendCache {
rcClient := rockscache.NewClient(rdb, options)
@@ -64,6 +66,7 @@ func NewFriendCacheRedis(rdb redis.UniversalClient, friendDB relationtb.FriendMo
}
}
+// NewCache creates a new instance of FriendCacheRedis with the same configuration.
func (f *FriendCacheRedis) NewCache() FriendCache {
return &FriendCacheRedis{
rcClient: f.rcClient,
@@ -73,24 +76,29 @@ func (f *FriendCacheRedis) NewCache() FriendCache {
}
}
+// getFriendIDsKey returns the key for storing friend IDs in the cache.
func (f *FriendCacheRedis) getFriendIDsKey(ownerUserID string) string {
return friendIDsKey + ownerUserID
}
+// getTwoWayFriendsIDsKey returns the key for storing two-way friend IDs in the cache.
func (f *FriendCacheRedis) getTwoWayFriendsIDsKey(ownerUserID string) string {
return TwoWayFriendsIDsKey + ownerUserID
}
+// getFriendKey returns the key for storing friend info in the cache.
func (f *FriendCacheRedis) getFriendKey(ownerUserID, friendUserID string) string {
return friendKey + ownerUserID + "-" + friendUserID
}
+// GetFriendIDs retrieves friend IDs from the cache or the database if not found.
func (f *FriendCacheRedis) GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error) {
return getCache(ctx, f.rcClient, f.getFriendIDsKey(ownerUserID), f.expireTime, func(ctx context.Context) ([]string, error) {
return f.friendDB.FindFriendUserIDs(ctx, ownerUserID)
})
}
+// DelFriendIDs deletes friend IDs from the cache.
func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) FriendCache {
newGroupCache := f.NewCache()
keys := make([]string, 0, len(ownerUserIDs))
@@ -102,7 +110,7 @@ func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) FriendCache {
return newGroupCache
}
-// todo.
+// GetTwoWayFriendIDs retrieves two-way friend IDs from the cache.
func (f *FriendCacheRedis) GetTwoWayFriendIDs(ctx context.Context, ownerUserID string) (twoWayFriendIDs []string, err error) {
friendIDs, err := f.GetFriendIDs(ctx, ownerUserID)
if err != nil {
@@ -121,6 +129,7 @@ func (f *FriendCacheRedis) GetTwoWayFriendIDs(ctx context.Context, ownerUserID s
return twoWayFriendIDs, nil
}
+// DelTwoWayFriendIDs deletes two-way friend IDs from the cache.
func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, ownerUserID string) FriendCache {
newFriendCache := f.NewCache()
newFriendCache.AddKeys(f.getTwoWayFriendsIDsKey(ownerUserID))
@@ -128,14 +137,15 @@ func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, ownerUserID s
return newFriendCache
}
-func (f *FriendCacheRedis) GetFriend(ctx context.Context, ownerUserID,
- friendUserID string) (friend *relationtb.FriendModel, err error) {
+// GetFriend retrieves friend info from the cache or the database if not found.
+func (f *FriendCacheRedis) GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error) {
return getCache(ctx, f.rcClient, f.getFriendKey(ownerUserID,
friendUserID), f.expireTime, func(ctx context.Context) (*relationtb.FriendModel, error) {
return f.friendDB.Take(ctx, ownerUserID, friendUserID)
})
}
+// DelFriend deletes friend info from the cache.
func (f *FriendCacheRedis) DelFriend(ownerUserID, friendUserID string) FriendCache {
newFriendCache := f.NewCache()
newFriendCache.AddKeys(f.getFriendKey(ownerUserID, friendUserID))
diff --git a/pkg/common/db/cache/group.go b/pkg/common/db/cache/group.go
index 6a4b57813..603d8e534 100644
--- a/pkg/common/db/cache/group.go
+++ b/pkg/common/db/cache/group.go
@@ -16,8 +16,13 @@ package cache
import (
"context"
+ "fmt"
+ "strconv"
"time"
+ "github.com/OpenIMSDK/protocol/constant"
+ "github.com/OpenIMSDK/tools/errs"
+
"github.com/OpenIMSDK/tools/log"
"github.com/dtm-labs/rockscache"
@@ -26,21 +31,24 @@ import (
"github.com/OpenIMSDK/tools/utils"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
- unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
)
const (
- groupExpireTime = time.Second * 60 * 60 * 12
- groupInfoKey = "GROUP_INFO:"
- groupMemberIDsKey = "GROUP_MEMBER_IDS:"
- groupMembersHashKey = "GROUP_MEMBERS_HASH2:"
- groupMemberInfoKey = "GROUP_MEMBER_INFO:"
- joinedSuperGroupsKey = "JOIN_SUPER_GROUPS:"
- SuperGroupMemberIDsKey = "SUPER_GROUP_MEMBER_IDS:"
- joinedGroupsKey = "JOIN_GROUPS_KEY:"
- groupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:"
+ groupExpireTime = time.Second * 60 * 60 * 12
+ groupInfoKey = "GROUP_INFO:"
+ groupMemberIDsKey = "GROUP_MEMBER_IDS:"
+ groupMembersHashKey = "GROUP_MEMBERS_HASH2:"
+ groupMemberInfoKey = "GROUP_MEMBER_INFO:"
+ //groupOwnerInfoKey = "GROUP_OWNER_INFO:"
+ joinedGroupsKey = "JOIN_GROUPS_KEY:"
+ groupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:"
+ groupRoleLevelMemberIDsKey = "GROUP_ROLE_LEVEL_MEMBER_IDS:"
)
+type GroupHash interface {
+ GetGroupHash(ctx context.Context, groupID string) (uint64, error)
+}
+
type GroupCache interface {
metaCache
NewCache() GroupCache
@@ -48,11 +56,6 @@ type GroupCache interface {
GetGroupInfo(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error)
DelGroupsInfo(groupIDs ...string) GroupCache
- GetJoinedSuperGroupIDs(ctx context.Context, userID string) (joinedSuperGroupIDs []string, err error)
- DelJoinedSuperGroupIDs(userIDs ...string) GroupCache
- GetSuperGroupMemberIDs(ctx context.Context, groupIDs ...string) (models []*unrelationtb.SuperGroupModel, err error)
- DelSuperGroupMemberIDs(groupIDs ...string) GroupCache
-
GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error)
GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error)
DelGroupMembersHash(groupID string) GroupCache
@@ -69,9 +72,16 @@ type GroupCache interface {
GetGroupMembersInfo(ctx context.Context, groupID string, userID []string) (groupMembers []*relationtb.GroupMemberModel, err error)
GetAllGroupMembersInfo(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error)
GetGroupMembersPage(ctx context.Context, groupID string, userID []string, showNumber, pageNumber int32) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error)
+ FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*relationtb.GroupMemberModel, error)
+ GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
+ GetGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error)
+ GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error)
+ DelGroupRoleLevel(groupID string, roleLevel []int32) GroupCache
+ DelGroupAllRoleLevel(groupID string) GroupCache
DelGroupMembersInfo(groupID string, userID ...string) GroupCache
-
+ GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*relationtb.GroupMemberModel, error)
+ GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error)
GetGroupMemberNum(ctx context.Context, groupID string) (memberNum int64, err error)
DelGroupsMemberNum(groupID ...string) GroupCache
}
@@ -81,10 +91,9 @@ type GroupCacheRedis struct {
groupDB relationtb.GroupModelInterface
groupMemberDB relationtb.GroupMemberModelInterface
groupRequestDB relationtb.GroupRequestModelInterface
- mongoDB unrelationtb.SuperGroupModelInterface
expireTime time.Duration
rcClient *rockscache.Client
- hashCode func(ctx context.Context, groupID string) (uint64, error)
+ groupHash GroupHash
}
func NewGroupCacheRedis(
@@ -92,8 +101,7 @@ func NewGroupCacheRedis(
groupDB relationtb.GroupModelInterface,
groupMemberDB relationtb.GroupMemberModelInterface,
groupRequestDB relationtb.GroupRequestModelInterface,
- mongoClient unrelationtb.SuperGroupModelInterface,
- hashCode func(ctx context.Context, groupID string) (uint64, error),
+ hashCode GroupHash,
opts rockscache.Options,
) GroupCache {
rcClient := rockscache.NewClient(rdb, opts)
@@ -101,8 +109,7 @@ func NewGroupCacheRedis(
return &GroupCacheRedis{
rcClient: rcClient, expireTime: groupExpireTime,
groupDB: groupDB, groupMemberDB: groupMemberDB, groupRequestDB: groupRequestDB,
- mongoDB: mongoClient,
- hashCode: hashCode,
+ groupHash: hashCode,
metaCache: NewMetaCacheRedis(rcClient),
}
}
@@ -114,7 +121,6 @@ func (g *GroupCacheRedis) NewCache() GroupCache {
groupDB: g.groupDB,
groupMemberDB: g.groupMemberDB,
groupRequestDB: g.groupRequestDB,
- mongoDB: g.mongoDB,
metaCache: NewMetaCacheRedis(g.rcClient, g.metaCache.GetPreDelKeys()...),
}
}
@@ -123,18 +129,10 @@ func (g *GroupCacheRedis) getGroupInfoKey(groupID string) string {
return groupInfoKey + groupID
}
-func (g *GroupCacheRedis) getJoinedSuperGroupsIDKey(userID string) string {
- return joinedSuperGroupsKey + userID
-}
-
func (g *GroupCacheRedis) getJoinedGroupsKey(userID string) string {
return joinedGroupsKey + userID
}
-func (g *GroupCacheRedis) getSuperGroupMemberIDsKey(groupID string) string {
- return SuperGroupMemberIDsKey + groupID
-}
-
func (g *GroupCacheRedis) getGroupMembersHashKey(groupID string) string {
return groupMembersHashKey + groupID
}
@@ -151,6 +149,10 @@ func (g *GroupCacheRedis) getGroupMemberNumKey(groupID string) string {
return groupMemberNumKey + groupID
}
+func (g *GroupCacheRedis) getGroupRoleLevelMemberIDsKey(groupID string, roleLevel int32) string {
+ return groupRoleLevelMemberIDsKey + groupID + "-" + strconv.Itoa(int(roleLevel))
+}
+
func (g *GroupCacheRedis) GetGroupIndex(group *relationtb.GroupModel, keys []string) (int, error) {
key := g.getGroupInfoKey(group.GroupID)
for i, _key := range keys {
@@ -173,15 +175,7 @@ func (g *GroupCacheRedis) GetGroupMemberIndex(groupMember *relationtb.GroupMembe
return 0, errIndex
}
-// / groupInfo.
func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) {
- //var keys []string
- //for _, group := range groupIDs {
- // keys = append(keys, g.getGroupInfoKey(group))
- //}
- //return batchGetCache(ctx, g.rcClient, keys, g.expireTime, g.GetGroupIndex, func(ctx context.Context) ([]*relationtb.GroupModel, error) {
- // return g.groupDB.Find(ctx, groupIDs)
- //})
return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
return g.getGroupInfoKey(groupID)
}, func(ctx context.Context, groupID string) (*relationtb.GroupModel, error) {
@@ -206,123 +200,44 @@ func (g *GroupCacheRedis) DelGroupsInfo(groupIDs ...string) GroupCache {
return newGroupCache
}
-func (g *GroupCacheRedis) GetJoinedSuperGroupIDs(ctx context.Context, userID string) (joinedSuperGroupIDs []string, err error) {
- return getCache(ctx, g.rcClient, g.getJoinedSuperGroupsIDKey(userID), g.expireTime, func(ctx context.Context) ([]string, error) {
- userGroup, err := g.mongoDB.GetSuperGroupByUserID(ctx, userID)
- if err != nil {
- return nil, err
- }
- return userGroup.GroupIDs, nil
- },
- )
-}
-
-func (g *GroupCacheRedis) GetSuperGroupMemberIDs(ctx context.Context, groupIDs ...string) (models []*unrelationtb.SuperGroupModel, err error) {
- //var keys []string
- //for _, group := range groupIDs {
- // keys = append(keys, g.getSuperGroupMemberIDsKey(group))
- //}
- //return batchGetCache(ctx, g.rcClient, keys, g.expireTime, func(model *unrelationtb.SuperGroupModel, keys []string) (int, error) {
- // for i, key := range keys {
- // if g.getSuperGroupMemberIDsKey(model.GroupID) == key {
- // return i, nil
- // }
- // }
- // return 0, errIndex
- //},
- // func(ctx context.Context) ([]*unrelationtb.SuperGroupModel, error) {
- // return g.mongoDB.FindSuperGroup(ctx, groupIDs)
- // })
- return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
- return g.getSuperGroupMemberIDsKey(groupID)
- }, func(ctx context.Context, groupID string) (*unrelationtb.SuperGroupModel, error) {
- return g.mongoDB.TakeSuperGroup(ctx, groupID)
- })
-}
-
-// userJoinSuperGroup.
-func (g *GroupCacheRedis) DelJoinedSuperGroupIDs(userIDs ...string) GroupCache {
+func (g *GroupCacheRedis) DelGroupsOwner(groupIDs ...string) GroupCache {
newGroupCache := g.NewCache()
- keys := make([]string, 0, len(userIDs))
- for _, userID := range userIDs {
- keys = append(keys, g.getJoinedSuperGroupsIDKey(userID))
+ keys := make([]string, 0, len(groupIDs))
+ for _, groupID := range groupIDs {
+ keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, constant.GroupOwner))
}
newGroupCache.AddKeys(keys...)
return newGroupCache
}
-func (g *GroupCacheRedis) DelSuperGroupMemberIDs(groupIDs ...string) GroupCache {
+func (g *GroupCacheRedis) DelGroupRoleLevel(groupID string, roleLevels []int32) GroupCache {
newGroupCache := g.NewCache()
- keys := make([]string, 0, len(groupIDs))
- for _, groupID := range groupIDs {
- keys = append(keys, g.getSuperGroupMemberIDsKey(groupID))
+ keys := make([]string, 0, len(roleLevels))
+ for _, roleLevel := range roleLevels {
+ keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, roleLevel))
}
newGroupCache.AddKeys(keys...)
-
return newGroupCache
}
-// groupMembersHash.
+func (g *GroupCacheRedis) DelGroupAllRoleLevel(groupID string) GroupCache {
+ return g.DelGroupRoleLevel(groupID, []int32{constant.GroupOwner, constant.GroupAdmin, constant.GroupOrdinaryUsers})
+}
+
func (g *GroupCacheRedis) GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error) {
+ if g.groupHash == nil {
+ return 0, errs.ErrInternalServer.Wrap("group hash is nil")
+ }
return getCache(ctx, g.rcClient, g.getGroupMembersHashKey(groupID), g.expireTime, func(ctx context.Context) (uint64, error) {
- return g.hashCode(ctx, groupID)
+ return g.groupHash.GetGroupHash(ctx, groupID)
})
-
- //return getCache(ctx, g.rcClient, g.getGroupMembersHashKey(groupID), g.expireTime,
- // func(ctx context.Context) (uint64, error) {
- // userIDs, err := g.GetGroupMemberIDs(ctx, groupID)
- // if err != nil {
- // return 0, err
- // }
- // log.ZInfo(ctx, "GetGroupMembersHash", "groupID", groupID, "userIDs", userIDs)
- // var members []*relationtb.GroupMemberModel
- // if len(userIDs) > 0 {
- // members, err = g.GetGroupMembersInfo(ctx, groupID, userIDs)
- // if err != nil {
- // return 0, err
- // }
- // utils.Sort(userIDs, true)
- // }
- // memberMap := make(map[string]*relationtb.GroupMemberModel)
- // for i, member := range members {
- // memberMap[member.UserID] = members[i]
- // }
- // data := make([]string, 0, len(members)*11)
- // for _, userID := range userIDs {
- // member, ok := memberMap[userID]
- // if !ok {
- // continue
- // }
- // data = append(data,
- // member.GroupID,
- // member.UserID,
- // member.Nickname,
- // member.FaceURL,
- // strconv.Itoa(int(member.RoleLevel)),
- // strconv.FormatInt(member.JoinTime.UnixMilli(), 10),
- // strconv.Itoa(int(member.JoinSource)),
- // member.InviterUserID,
- // member.OperatorUserID,
- // strconv.FormatInt(member.MuteEndTime.UnixMilli(), 10),
- // member.Ex,
- // )
- // }
- // log.ZInfo(ctx, "hash data info", "userIDs.len", len(userIDs), "hash.data.len", len(data))
- // log.ZInfo(ctx, "json hash data", "groupID", groupID, "data", data)
- // val, err := json.Marshal(data)
- // if err != nil {
- // return 0, err
- // }
- // sum := md5.Sum(val)
- // code := binary.BigEndian.Uint64(sum[:])
- // log.ZInfo(ctx, "GetGroupMembersHash", "groupID", groupID, "hashCode", code, "num", len(members))
- // return code, nil
- // },
- //)
}
func (g *GroupCacheRedis) GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) {
+ if g.groupHash == nil {
+ return nil, errs.ErrInternalServer.Wrap("group hash is nil")
+ }
res := make(map[string]*relationtb.GroupSimpleUserID)
for _, groupID := range groupIDs {
hash, err := g.GetGroupMembersHash(ctx, groupID)
@@ -347,7 +262,6 @@ func (g *GroupCacheRedis) DelGroupMembersHash(groupID string) GroupCache {
return cache
}
-// groupMemberIDs.
func (g *GroupCacheRedis) GetGroupMemberIDs(ctx context.Context, groupID string) (groupMemberIDs []string, err error) {
return getCache(ctx, g.rcClient, g.getGroupMemberIDsKey(groupID), g.expireTime, func(ctx context.Context) ([]string, error) {
return g.groupMemberDB.FindMemberUserID(ctx, groupID)
@@ -398,13 +312,6 @@ func (g *GroupCacheRedis) GetGroupMemberInfo(ctx context.Context, groupID, userI
}
func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupMemberModel, error) {
- //var keys []string
- //for _, userID := range userIDs {
- // keys = append(keys, g.getGroupMemberInfoKey(groupID, userID))
- //}
- //return batchGetCache(ctx, g.rcClient, keys, g.expireTime, g.GetGroupMemberIndex, func(ctx context.Context) ([]*relationtb.GroupMemberModel, error) {
- // return g.groupMemberDB.Find(ctx, []string{groupID}, userIDs, nil)
- //})
return batchGetCache2(ctx, g.rcClient, g.expireTime, userIDs, func(userID string) string {
return g.getGroupMemberInfoKey(groupID, userID)
}, func(ctx context.Context, userID string) (*relationtb.GroupMemberModel, error) {
@@ -446,13 +353,6 @@ func (g *GroupCacheRedis) GetAllGroupMemberInfo(ctx context.Context, groupID str
if err != nil {
return nil, err
}
- //var keys []string
- //for _, groupMemberID := range groupMemberIDs {
- // keys = append(keys, g.getGroupMemberInfoKey(groupID, groupMemberID))
- //}
- //return batchGetCache(ctx, g.rcClient, keys, g.expireTime, g.GetGroupMemberIndex, func(ctx context.Context) ([]*relationtb.GroupMemberModel, error) {
- // return g.groupMemberDB.Find(ctx, []string{groupID}, groupMemberIDs, nil)
- //})
return g.GetGroupMembersInfo(ctx, groupID, groupMemberIDs)
}
@@ -483,3 +383,68 @@ func (g *GroupCacheRedis) DelGroupsMemberNum(groupID ...string) GroupCache {
return cache
}
+
+func (g *GroupCacheRedis) GetGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
+ members, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
+ if err != nil {
+ return nil, err
+ }
+ if len(members) == 0 {
+ return nil, errs.ErrRecordNotFound.Wrap(fmt.Sprintf("group %s owner not found", groupID))
+ }
+ return members[0], nil
+}
+
+func (g *GroupCacheRedis) GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error) {
+ members := make([]*relationtb.GroupMemberModel, 0, len(groupIDs))
+ for _, groupID := range groupIDs {
+ items, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
+ if err != nil {
+ return nil, err
+ }
+ if len(items) > 0 {
+ members = append(members, items[0])
+ }
+ }
+ return members, nil
+}
+
+func (g *GroupCacheRedis) GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) {
+ return getCache(ctx, g.rcClient, g.getGroupRoleLevelMemberIDsKey(groupID, roleLevel), g.expireTime, func(ctx context.Context) ([]string, error) {
+ return g.groupMemberDB.FindRoleLevelUserIDs(ctx, groupID, roleLevel)
+ })
+}
+
+func (g *GroupCacheRedis) GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*relationtb.GroupMemberModel, error) {
+ userIDs, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
+ if err != nil {
+ return nil, err
+ }
+ return g.GetGroupMembersInfo(ctx, groupID, userIDs)
+}
+
+func (g *GroupCacheRedis) GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
+ var userIDs []string
+ for _, roleLevel := range roleLevels {
+ ids, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
+ if err != nil {
+ return nil, err
+ }
+ userIDs = append(userIDs, ids...)
+ }
+ return g.GetGroupMembersInfo(ctx, groupID, userIDs)
+}
+
+func (g *GroupCacheRedis) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (_ []*relationtb.GroupMemberModel, err error) {
+ if len(groupIDs) == 0 {
+ groupIDs, err = g.GetJoinedGroupIDs(ctx, userID)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
+ return g.getGroupMemberInfoKey(groupID, userID)
+ }, func(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
+ return g.groupMemberDB.Take(ctx, groupID, userID)
+ })
+}
diff --git a/pkg/common/db/cache/meta_cache.go b/pkg/common/db/cache/meta_cache.go
index ccac88d68..4bc2a046a 100644
--- a/pkg/common/db/cache/meta_cache.go
+++ b/pkg/common/db/cache/meta_cache.go
@@ -38,7 +38,7 @@ const (
var errIndex = errors.New("err index")
type metaCache interface {
- ExecDel(ctx context.Context) error
+ ExecDel(ctx context.Context, distinct ...bool) error
// delete key rapid
DelKey(ctx context.Context, key string) error
AddKeys(keys ...string)
@@ -57,7 +57,10 @@ type metaCacheRedis struct {
retryInterval time.Duration
}
-func (m *metaCacheRedis) ExecDel(ctx context.Context) error {
+func (m *metaCacheRedis) ExecDel(ctx context.Context, distinct ...bool) error {
+ if len(distinct) > 0 && distinct[0] {
+ m.keys = utils.Distinct(m.keys)
+ }
if len(m.keys) > 0 {
log.ZDebug(ctx, "delete cache", "keys", m.keys)
for _, key := range m.keys {
diff --git a/pkg/common/db/cache/msg.go b/pkg/common/db/cache/msg.go
index f86b44d9b..5cd3cb22c 100644
--- a/pkg/common/db/cache/msg.go
+++ b/pkg/common/db/cache/msg.go
@@ -173,20 +173,7 @@ func (c *msgCache) getSeqs(ctx context.Context, items []string, getkey func(s st
}
func (c *msgCache) SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error {
- var retErr error
- for {
- select {
- case <-ctx.Done():
- return errs.Wrap(retErr, "SetMaxSeq redis retry too many amount")
- default:
- retErr = c.setSeq(ctx, conversationID, maxSeq, c.getMaxSeqKey)
- if retErr != nil {
- time.Sleep(time.Second * 2)
- continue
- }
- return nil
- }
- }
+ return c.setSeq(ctx, conversationID, maxSeq, c.getMaxSeqKey)
}
func (c *msgCache) GetMaxSeqs(ctx context.Context, conversationIDs []string) (m map[string]int64, err error) {
@@ -194,21 +181,7 @@ func (c *msgCache) GetMaxSeqs(ctx context.Context, conversationIDs []string) (m
}
func (c *msgCache) GetMaxSeq(ctx context.Context, conversationID string) (int64, error) {
- var retErr error
- var retData int64
- for {
- select {
- case <-ctx.Done():
- return -1, errs.Wrap(retErr, "GetMaxSeq redis retry too many amount")
- default:
- retData, retErr = c.getSeq(ctx, conversationID, c.getMaxSeqKey)
- if retErr != nil && errs.Unwrap(retErr) != redis.Nil {
- time.Sleep(time.Second * 2)
- continue
- }
- return retData, retErr
- }
- }
+ return c.getSeq(ctx, conversationID, c.getMaxSeqKey)
}
func (c *msgCache) SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error {
@@ -314,7 +287,7 @@ func (c *msgCache) GetTokensWithoutError(ctx context.Context, userID string, pla
func (c *msgCache) SetTokenMapByUidPid(ctx context.Context, userID string, platform int, m map[string]int) error {
key := uidPidToken + userID + ":" + constant.PlatformIDToName(platform)
- mm := make(map[string]interface{})
+ mm := make(map[string]any)
for k, v := range m {
mm[k] = v
}
@@ -672,35 +645,19 @@ func (c *msgCache) PipeDeleteMessages(ctx context.Context, conversationID string
}
func (c *msgCache) CleanUpOneConversationAllMsg(ctx context.Context, conversationID string) error {
- var (
- cursor uint64
- keys []string
- err error
-
- key = c.allMessageCacheKey(conversationID)
- )
-
- for {
- // scan up to 10000 at a time, the count (10000) param refers to the number of scans on redis server.
- // if the count is too small, needs to be run scan on redis frequently.
- var limit int64 = 10000
- keys, cursor, err = c.rdb.Scan(ctx, cursor, key, limit).Result()
- if err != nil {
+ vals, err := c.rdb.Keys(ctx, c.allMessageCacheKey(conversationID)).Result()
+ if errors.Is(err, redis.Nil) {
+ return nil
+ }
+ if err != nil {
+ return errs.Wrap(err)
+ }
+ for _, v := range vals {
+ if err := c.rdb.Del(ctx, v).Err(); err != nil {
return errs.Wrap(err)
}
-
- for _, key := range keys {
- err := c.rdb.Del(ctx, key).Err()
- if err != nil {
- return errs.Wrap(err)
- }
- }
-
- // scan end
- if cursor == 0 {
- return nil
- }
}
+ return nil
}
func (c *msgCache) DelMsgFromCache(ctx context.Context, userID string, seqs []int64) error {
diff --git a/pkg/common/db/cache/msg_test.go b/pkg/common/db/cache/msg_test.go
index a5be018ed..3fddf5965 100644
--- a/pkg/common/db/cache/msg_test.go
+++ b/pkg/common/db/cache/msg_test.go
@@ -385,50 +385,3 @@ func testParallelDeleteMessagesMix(t *testing.T, cid string, seqs []int64, input
assert.EqualValues(t, 1, val) // exists
}
}
-
-func TestCleanUpOneConversationAllMsg(t *testing.T) {
- rdb := redis.NewClient(&redis.Options{})
- defer rdb.Close()
-
- cacher := msgCache{rdb: rdb}
- count := 1000
- prefix := fmt.Sprintf("%v", rand.Int63())
-
- ids := []string{}
- for i := 0; i < count; i++ {
- id := fmt.Sprintf("%v-cid-%v", prefix, rand.Int63())
- ids = append(ids, id)
-
- key := cacher.allMessageCacheKey(id)
- rdb.Set(context.Background(), key, "openim", 0)
- }
-
- // delete 100 keys with scan.
- for i := 0; i < 100; i++ {
- pickedKey := ids[i]
- err := cacher.CleanUpOneConversationAllMsg(context.Background(), pickedKey)
- assert.Nil(t, err)
-
- ls, err := rdb.Keys(context.Background(), pickedKey).Result()
- assert.Nil(t, err)
- assert.Equal(t, 0, len(ls))
-
- rcode, err := rdb.Exists(context.Background(), pickedKey).Result()
- assert.Nil(t, err)
- assert.EqualValues(t, 0, rcode) // non-exists
- }
-
- sid := fmt.Sprintf("%v-cid-*", prefix)
- ls, err := rdb.Keys(context.Background(), cacher.allMessageCacheKey(sid)).Result()
- assert.Nil(t, err)
- assert.Equal(t, count-100, len(ls))
-
- // delete fuzzy matching keys.
- err = cacher.CleanUpOneConversationAllMsg(context.Background(), sid)
- assert.Nil(t, err)
-
- // don't contains keys matched `{prefix}-cid-{random}` on redis
- ls, err = rdb.Keys(context.Background(), cacher.allMessageCacheKey(sid)).Result()
- assert.Nil(t, err)
- assert.Equal(t, 0, len(ls))
-}
diff --git a/pkg/common/db/cache/s3.go b/pkg/common/db/cache/s3.go
index 3520ba2ec..ba40ceacc 100644
--- a/pkg/common/db/cache/s3.go
+++ b/pkg/common/db/cache/s3.go
@@ -14,8 +14,8 @@ import (
type ObjectCache interface {
metaCache
- GetName(ctx context.Context, name string) (*relationtb.ObjectModel, error)
- DelObjectName(names ...string) ObjectCache
+ GetName(ctx context.Context, engine string, name string) (*relationtb.ObjectModel, error)
+ DelObjectName(engine string, names ...string) ObjectCache
}
func NewObjectCacheRedis(rdb redis.UniversalClient, objDB relationtb.ObjectInfoModelInterface) ObjectCache {
@@ -44,23 +44,23 @@ func (g *objectCacheRedis) NewCache() ObjectCache {
}
}
-func (g *objectCacheRedis) DelObjectName(names ...string) ObjectCache {
+func (g *objectCacheRedis) DelObjectName(engine string, names ...string) ObjectCache {
objectCache := g.NewCache()
keys := make([]string, 0, len(names))
for _, name := range names {
- keys = append(keys, g.getObjectKey(name))
+ keys = append(keys, g.getObjectKey(name, engine))
}
objectCache.AddKeys(keys...)
return objectCache
}
-func (g *objectCacheRedis) getObjectKey(name string) string {
- return "OBJECT:" + name
+func (g *objectCacheRedis) getObjectKey(engine string, name string) string {
+ return "OBJECT:" + engine + ":" + name
}
-func (g *objectCacheRedis) GetName(ctx context.Context, name string) (*relationtb.ObjectModel, error) {
- return getCache(ctx, g.rcClient, g.getObjectKey(name), g.expireTime, func(ctx context.Context) (*relationtb.ObjectModel, error) {
- return g.objDB.Take(ctx, name)
+func (g *objectCacheRedis) GetName(ctx context.Context, engine string, name string) (*relationtb.ObjectModel, error) {
+ return getCache(ctx, g.rcClient, g.getObjectKey(name, engine), g.expireTime, func(ctx context.Context) (*relationtb.ObjectModel, error) {
+ return g.objDB.Take(ctx, engine, name)
})
}
diff --git a/pkg/common/db/cache/user.go b/pkg/common/db/cache/user.go
index d1164f2c0..979bd06e4 100644
--- a/pkg/common/db/cache/user.go
+++ b/pkg/common/db/cache/user.go
@@ -22,6 +22,8 @@ import (
"strconv"
"time"
+ relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/protocol/constant"
@@ -31,8 +33,6 @@ import (
"github.com/dtm-labs/rockscache"
"github.com/redis/go-redis/v9"
-
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
const (
@@ -59,7 +59,8 @@ type UserCache interface {
type UserCacheRedis struct {
metaCache
- rdb redis.UniversalClient
+ rdb redis.UniversalClient
+ //userDB relationtb.UserModelInterface
userDB relationtb.UserModelInterface
expireTime time.Duration
rcClient *rockscache.Client
@@ -100,39 +101,13 @@ func (u *UserCacheRedis) getUserGlobalRecvMsgOptKey(userID string) string {
}
func (u *UserCacheRedis) GetUserInfo(ctx context.Context, userID string) (userInfo *relationtb.UserModel, err error) {
- return getCache(
- ctx,
- u.rcClient,
- u.getUserInfoKey(userID),
- u.expireTime,
- func(ctx context.Context) (*relationtb.UserModel, error) {
- return u.userDB.Take(ctx, userID)
- },
+ return getCache(ctx, u.rcClient, u.getUserInfoKey(userID), u.expireTime, func(ctx context.Context) (*relationtb.UserModel, error) {
+ return u.userDB.Take(ctx, userID)
+ },
)
}
func (u *UserCacheRedis) GetUsersInfo(ctx context.Context, userIDs []string) ([]*relationtb.UserModel, error) {
- //var keys []string
- //for _, userID := range userIDs {
- // keys = append(keys, u.getUserInfoKey(userID))
- //}
- //return batchGetCache(
- // ctx,
- // u.rcClient,
- // keys,
- // u.expireTime,
- // func(user *relationtb.UserModel, keys []string) (int, error) {
- // for i, key := range keys {
- // if key == u.getUserInfoKey(user.UserID) {
- // return i, nil
- // }
- // }
- // return 0, errIndex
- // },
- // func(ctx context.Context) ([]*relationtb.UserModel, error) {
- // return u.userDB.Find(ctx, userIDs)
- // },
- //)
return batchGetCache2(ctx, u.rcClient, u.expireTime, userIDs, func(userID string) string {
return u.getUserInfoKey(userID)
}, func(ctx context.Context, userID string) (*relationtb.UserModel, error) {
@@ -214,8 +189,7 @@ func (u *UserCacheRedis) SetUserStatus(ctx context.Context, userID string, statu
UserIDNum := crc32.ChecksumIEEE([]byte(userID))
modKey := strconv.Itoa(int(UserIDNum % statusMod))
key := olineStatusKey + modKey
- log.ZDebug(ctx, "SetUserStatus args", "userID", userID, "status", status,
- "platformID", platformID, "modKey", modKey, "key", key)
+ log.ZDebug(ctx, "SetUserStatus args", "userID", userID, "status", status, "platformID", platformID, "modKey", modKey, "key", key)
isNewKey, err := u.rdb.Exists(ctx, key).Result()
if err != nil {
return errs.Wrap(err)
diff --git a/pkg/common/db/controller/black.go b/pkg/common/db/controller/black.go
index 70e942a77..e68d06b01 100644
--- a/pkg/common/db/controller/black.go
+++ b/pkg/common/db/controller/black.go
@@ -17,6 +17,8 @@ package controller
import (
"context"
+ "github.com/OpenIMSDK/tools/pagination"
+
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/utils"
@@ -30,12 +32,7 @@ type BlackDatabase interface {
// Delete 删除黑名单
Delete(ctx context.Context, blacks []*relation.BlackModel) (err error)
// FindOwnerBlacks 获取黑名单列表
- FindOwnerBlacks(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
- ) (blacks []*relation.BlackModel, total int64, err error)
- FindBlackIDs(ctx context.Context, ownerUserID string) (blackIDs []string, err error)
+ FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error)
FindBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error)
// CheckIn 检查user2是否在user1的黑名单列表中(inUser1Blacks==true) 检查user1是否在user2的黑名单列表中(inUser2Blacks==true)
CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Blacks bool, inUser2Blacks bool, err error)
@@ -75,12 +72,8 @@ func (b *blackDatabase) deleteBlackIDsCache(ctx context.Context, blacks []*relat
}
// FindOwnerBlacks 获取黑名单列表.
-func (b *blackDatabase) FindOwnerBlacks(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
-) (blacks []*relation.BlackModel, total int64, err error) {
- return b.black.FindOwnerBlacks(ctx, ownerUserID, pageNumber, showNumber)
+func (b *blackDatabase) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) {
+ return b.black.FindOwnerBlacks(ctx, ownerUserID, pagination)
}
// CheckIn 检查user2是否在user1的黑名单列表中(inUser1Blacks==true) 检查user1是否在user2的黑名单列表中(inUser2Blacks==true).
diff --git a/pkg/common/db/controller/chatlog.go b/pkg/common/db/controller/chatlog.go
deleted file mode 100644
index def490265..000000000
--- a/pkg/common/db/controller/chatlog.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package controller
-
-import (
- pbmsg "github.com/OpenIMSDK/protocol/msg"
-
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type ChatLogDatabase interface {
- CreateChatLog(msg *pbmsg.MsgDataToMQ) error
-}
-
-func NewChatLogDatabase(chatLogModelInterface relationtb.ChatLogModelInterface) ChatLogDatabase {
- return &chatLogDatabase{chatLogModel: chatLogModelInterface}
-}
-
-type chatLogDatabase struct {
- chatLogModel relationtb.ChatLogModelInterface
-}
-
-func (c *chatLogDatabase) CreateChatLog(msg *pbmsg.MsgDataToMQ) error {
- return c.chatLogModel.Create(msg)
-}
diff --git a/pkg/common/db/controller/conversation.go b/pkg/common/db/controller/conversation.go
index 0aaa95880..2a0cb63e4 100644
--- a/pkg/common/db/controller/conversation.go
+++ b/pkg/common/db/controller/conversation.go
@@ -18,6 +18,8 @@ import (
"context"
"time"
+ "github.com/OpenIMSDK/tools/pagination"
+
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
"github.com/OpenIMSDK/protocol/constant"
@@ -31,7 +33,7 @@ import (
type ConversationDatabase interface {
// UpdateUserConversationFiled 更新用户该会话的属性信息
- UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) error
+ UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error
// CreateConversation 创建一批新的会话
CreateConversation(ctx context.Context, conversations []*relationtb.ConversationModel) error
// SyncPeerUserPrivateConversation 同步对端私聊会话内部保证事务操作
@@ -39,26 +41,26 @@ type ConversationDatabase interface {
// FindConversations 根据会话ID获取某个用户的多个会话
FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error)
// FindRecvMsgNotNotifyUserIDs 获取超级大群开启免打扰的用户ID
- FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
+ //FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
// GetUserAllConversation 获取一个用户在服务器上所有的会话
GetUserAllConversation(ctx context.Context, ownerUserID string) ([]*relationtb.ConversationModel, error)
// SetUserConversations 设置用户多个会话属性,如果会话不存在则创建,否则更新,内部保证原子性
SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error
// SetUsersConversationFiledTx 设置多个用户会话关于某个字段的更新操作,如果会话不存在则创建,否则更新,内部保证事务操作
- SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]interface{}) error
+ SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]any) error
CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error
GetConversationIDs(ctx context.Context, userID string) ([]string, error)
GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error)
GetAllConversationIDs(ctx context.Context) ([]string, error)
GetAllConversationIDsNumber(ctx context.Context) (int64, error)
- PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error)
+ PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
//GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error)
GetConversationIDsNeedDestruct(ctx context.Context) ([]*relationtb.ConversationModel, error)
GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
}
-func NewConversationDatabase(conversation relationtb.ConversationModelInterface, cache cache.ConversationCache, tx tx.Tx) ConversationDatabase {
+func NewConversationDatabase(conversation relationtb.ConversationModelInterface, cache cache.ConversationCache, tx tx.CtxTx) ConversationDatabase {
return &conversationDatabase{
conversationDB: conversation,
cache: cache,
@@ -69,22 +71,21 @@ func NewConversationDatabase(conversation relationtb.ConversationModelInterface,
type conversationDatabase struct {
conversationDB relationtb.ConversationModelInterface
cache cache.ConversationCache
- tx tx.Tx
+ tx tx.CtxTx
}
-func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]interface{}) (err error) {
- cache := c.cache.NewCache()
- if conversation.GroupID != "" {
- cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(conversation.GroupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(conversation.GroupID)
- }
- if err := c.tx.Transaction(func(tx any) error {
- conversationTx := c.conversationDB.NewTx(tx)
- haveUserIDs, err := conversationTx.FindUserID(ctx, userIDs, []string{conversation.ConversationID})
+func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]any) (err error) {
+ return c.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := c.cache.NewCache()
+ if conversation.GroupID != "" {
+ cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(conversation.GroupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(conversation.GroupID)
+ }
+ haveUserIDs, err := c.conversationDB.FindUserID(ctx, userIDs, []string{conversation.ConversationID})
if err != nil {
return err
}
if len(haveUserIDs) > 0 {
- _, err = conversationTx.UpdateByMap(ctx, haveUserIDs, conversation.ConversationID, filedMap)
+ _, err = c.conversationDB.UpdateByMap(ctx, haveUserIDs, conversation.ConversationID, filedMap)
if err != nil {
return err
}
@@ -112,20 +113,17 @@ func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context,
conversations = append(conversations, temp)
}
if len(conversations) > 0 {
- err = conversationTx.Create(ctx, conversations)
+ err = c.conversationDB.Create(ctx, conversations)
if err != nil {
return err
}
cache = cache.DelConversationIDs(NotUserIDs...).DelUserConversationIDsHash(NotUserIDs...).DelConversations(conversation.ConversationID, NotUserIDs...)
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
+ })
}
-func (c *conversationDatabase) UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) error {
+func (c *conversationDatabase) UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error {
_, err := c.conversationDB.UpdateByMap(ctx, userIDs, conversationID, args)
if err != nil {
return err
@@ -153,19 +151,18 @@ func (c *conversationDatabase) CreateConversation(ctx context.Context, conversat
}
func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Context, conversations []*relationtb.ConversationModel) error {
- cache := c.cache.NewCache()
- if err := c.tx.Transaction(func(tx any) error {
- conversationTx := c.conversationDB.NewTx(tx)
+ return c.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := c.cache.NewCache()
for _, conversation := range conversations {
for _, v := range [][2]string{{conversation.OwnerUserID, conversation.UserID}, {conversation.UserID, conversation.OwnerUserID}} {
ownerUserID := v[0]
userID := v[1]
- haveUserIDs, err := conversationTx.FindUserID(ctx, []string{ownerUserID}, []string{conversation.ConversationID})
+ haveUserIDs, err := c.conversationDB.FindUserID(ctx, []string{ownerUserID}, []string{conversation.ConversationID})
if err != nil {
return err
}
if len(haveUserIDs) > 0 {
- _, err := conversationTx.UpdateByMap(ctx, []string{ownerUserID}, conversation.ConversationID, map[string]interface{}{"is_private_chat": conversation.IsPrivateChat})
+ _, err := c.conversationDB.UpdateByMap(ctx, []string{ownerUserID}, conversation.ConversationID, map[string]any{"is_private_chat": conversation.IsPrivateChat})
if err != nil {
return err
}
@@ -176,18 +173,15 @@ func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Con
newConversation.UserID = userID
newConversation.ConversationID = conversation.ConversationID
newConversation.IsPrivateChat = conversation.IsPrivateChat
- if err := conversationTx.Create(ctx, []*relationtb.ConversationModel{&newConversation}); err != nil {
+ if err := c.conversationDB.Create(ctx, []*relationtb.ConversationModel{&newConversation}); err != nil {
return err
}
cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID)
}
}
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
+ })
}
func (c *conversationDatabase) FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
@@ -203,28 +197,26 @@ func (c *conversationDatabase) GetUserAllConversation(ctx context.Context, owner
}
func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error {
- cache := c.cache.NewCache()
-
- groupIDs := utils.Distinct(utils.Filter(conversations, func(e *relationtb.ConversationModel) (string, bool) {
- return e.GroupID, e.GroupID != ""
- }))
- for _, groupID := range groupIDs {
- cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(groupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID)
- }
- if err := c.tx.Transaction(func(tx any) error {
+ return c.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := c.cache.NewCache()
+ groupIDs := utils.Distinct(utils.Filter(conversations, func(e *relationtb.ConversationModel) (string, bool) {
+ return e.GroupID, e.GroupID != ""
+ }))
+ for _, groupID := range groupIDs {
+ cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(groupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID)
+ }
var conversationIDs []string
for _, conversation := range conversations {
conversationIDs = append(conversationIDs, conversation.ConversationID)
cache = cache.DelConversations(conversation.OwnerUserID, conversation.ConversationID)
}
- conversationTx := c.conversationDB.NewTx(tx)
- existConversations, err := conversationTx.Find(ctx, ownerUserID, conversationIDs)
+ existConversations, err := c.conversationDB.Find(ctx, ownerUserID, conversationIDs)
if err != nil {
return err
}
if len(existConversations) > 0 {
for _, conversation := range conversations {
- err = conversationTx.Update(ctx, conversation)
+ err = c.conversationDB.Update(ctx, conversation)
if err != nil {
return err
}
@@ -246,23 +238,22 @@ func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUs
if err != nil {
return err
}
- cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID).DelConversationNotReceiveMessageUserIDs(utils.Slice(notExistConversations, func(e *relationtb.ConversationModel) string { return e.ConversationID })...)
+ cache = cache.DelConversationIDs(ownerUserID).
+ DelUserConversationIDsHash(ownerUserID).
+ DelConversationNotReceiveMessageUserIDs(utils.Slice(notExistConversations, func(e *relationtb.ConversationModel) string { return e.ConversationID })...)
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
+ })
}
-func (c *conversationDatabase) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) {
- return c.cache.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
-}
+//func (c *conversationDatabase) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) {
+// return c.cache.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
+//}
func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error {
- cache := c.cache.NewCache()
- conversationID := msgprocessor.GetConversationIDBySessionType(constant.SuperGroupChatType, groupID)
- if err := c.tx.Transaction(func(tx any) error {
+ return c.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := c.cache.NewCache()
+ conversationID := msgprocessor.GetConversationIDBySessionType(constant.SuperGroupChatType, groupID)
existConversationUserIDs, err := c.conversationDB.FindUserID(ctx, userIDs, []string{conversationID})
if err != nil {
return err
@@ -281,18 +272,15 @@ func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context,
return err
}
}
- _, err = c.conversationDB.UpdateByMap(ctx, existConversationUserIDs, conversationID, map[string]interface{}{"max_seq": 0})
+ _, err = c.conversationDB.UpdateByMap(ctx, existConversationUserIDs, conversationID, map[string]any{"max_seq": 0})
if err != nil {
return err
}
for _, v := range existConversationUserIDs {
cache = cache.DelConversations(v, conversationID)
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return c.cache.ExecDel(ctx)
+ })
}
func (c *conversationDatabase) GetConversationIDs(ctx context.Context, userID string) ([]string, error) {
@@ -311,14 +299,10 @@ func (c *conversationDatabase) GetAllConversationIDsNumber(ctx context.Context)
return c.conversationDB.GetAllConversationIDsNumber(ctx)
}
-func (c *conversationDatabase) PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) ([]string, error) {
- return c.conversationDB.PageConversationIDs(ctx, pageNumber, showNumber)
+func (c *conversationDatabase) PageConversationIDs(ctx context.Context, pagination pagination.Pagination) ([]string, error) {
+ return c.conversationDB.PageConversationIDs(ctx, pagination)
}
-//func (c *conversationDatabase) GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error) {
-// return c.cache.GetUserAllHasReadSeqs(ctx, ownerUserID)
-//}
-
func (c *conversationDatabase) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
return c.conversationDB.GetConversationsByConversationID(ctx, conversationIDs)
}
diff --git a/pkg/common/db/controller/friend.go b/pkg/common/db/controller/friend.go
index 270ac434f..2df5c0cd7 100644
--- a/pkg/common/db/controller/friend.go
+++ b/pkg/common/db/controller/friend.go
@@ -18,7 +18,7 @@ import (
"context"
"time"
- "gorm.io/gorm"
+ "github.com/OpenIMSDK/tools/pagination"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/errs"
@@ -47,35 +47,15 @@ type FriendDatabase interface {
// 更新好友备注
UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
// 获取ownerUserID的好友列表
- PageOwnerFriends(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
- ) (friends []*relation.FriendModel, total int64, err error)
+ PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
// friendUserID在哪些人的好友列表中
- PageInWhoseFriends(
- ctx context.Context,
- friendUserID string,
- pageNumber, showNumber int32,
- ) (friends []*relation.FriendModel, total int64, err error)
+ PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
// 获取我发出去的好友申请
- PageFriendRequestFromMe(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
- ) (friends []*relation.FriendRequestModel, total int64, err error)
+ PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
// 获取我收到的的好友申请
- PageFriendRequestToMe(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
- ) (friends []*relation.FriendRequestModel, total int64, err error)
+ PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
// 获取某人指定好友的信息
- FindFriendsWithError(
- ctx context.Context,
- ownerUserID string,
- friendUserIDs []string,
- ) (friends []*relation.FriendModel, err error)
+ FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error)
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error)
UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error)
@@ -84,24 +64,16 @@ type FriendDatabase interface {
type friendDatabase struct {
friend relation.FriendModelInterface
friendRequest relation.FriendRequestModelInterface
- tx tx.Tx
+ tx tx.CtxTx
cache cache.FriendCache
}
-func NewFriendDatabase(
- friend relation.FriendModelInterface,
- friendRequest relation.FriendRequestModelInterface,
- cache cache.FriendCache,
- tx tx.Tx,
-) FriendDatabase {
+func NewFriendDatabase(friend relation.FriendModelInterface, friendRequest relation.FriendRequestModelInterface, cache cache.FriendCache, tx tx.CtxTx) FriendDatabase {
return &friendDatabase{friend: friend, friendRequest: friendRequest, cache: cache, tx: tx}
}
// ok 检查user2是否在user1的好友列表中(inUser1Friends==true) 检查user1是否在user2的好友列表中(inUser2Friends==true).
-func (f *friendDatabase) CheckIn(
- ctx context.Context,
- userID1, userID2 string,
-) (inUser1Friends bool, inUser2Friends bool, err error) {
+func (f *friendDatabase) CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Friends bool, inUser2Friends bool, err error) {
userID1FriendIDs, err := f.cache.GetFriendIDs(ctx, userID1)
if err != nil {
return
@@ -114,50 +86,35 @@ func (f *friendDatabase) CheckIn(
}
// 增加或者更新好友申请 如果之前有记录则更新,没有记录则新增.
-func (f *friendDatabase) AddFriendRequest(
- ctx context.Context,
- fromUserID, toUserID string,
- reqMsg string,
- ex string,
-) (err error) {
- return f.tx.Transaction(func(tx any) error {
- _, err := f.friendRequest.NewTx(tx).Take(ctx, fromUserID, toUserID)
- // 有db错误
- if err != nil && errs.Unwrap(err) != gorm.ErrRecordNotFound {
- return err
- }
- // 无错误 则更新
- if err == nil {
- m := make(map[string]interface{}, 1)
+func (f *friendDatabase) AddFriendRequest(ctx context.Context, fromUserID, toUserID string, reqMsg string, ex string) (err error) {
+ return f.tx.Transaction(ctx, func(ctx context.Context) error {
+ _, err := f.friendRequest.Take(ctx, fromUserID, toUserID)
+ switch {
+ case err == nil:
+ m := make(map[string]any, 1)
m["handle_result"] = 0
m["handle_msg"] = ""
m["req_msg"] = reqMsg
m["ex"] = ex
m["create_time"] = time.Now()
- if err := f.friendRequest.NewTx(tx).UpdateByMap(ctx, fromUserID, toUserID, m); err != nil {
- return err
- }
- return nil
- }
- // gorm.ErrRecordNotFound 错误,则新增
- if err := f.friendRequest.NewTx(tx).Create(ctx, []*relation.FriendRequestModel{{FromUserID: fromUserID, ToUserID: toUserID, ReqMsg: reqMsg, Ex: ex, CreateTime: time.Now(), HandleTime: time.Unix(0, 0)}}); err != nil {
+ return f.friendRequest.UpdateByMap(ctx, fromUserID, toUserID, m)
+ case relation.IsNotFound(err):
+ return f.friendRequest.Create(
+ ctx,
+ []*relation.FriendRequestModel{{FromUserID: fromUserID, ToUserID: toUserID, ReqMsg: reqMsg, Ex: ex, CreateTime: time.Now(), HandleTime: time.Unix(0, 0)}},
+ )
+ default:
return err
}
- return nil
})
}
// (1)先判断是否在好友表 (在不在都不返回错误) (2)对于不在好友列表的 插入即可.
-func (f *friendDatabase) BecomeFriends(
- ctx context.Context,
- ownerUserID string,
- friendUserIDs []string,
- addSource int32,
-) (err error) {
- cache := f.cache.NewCache()
- if err := f.tx.Transaction(func(tx any) error {
+func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error) {
+ return f.tx.Transaction(ctx, func(ctx context.Context) error {
+ cache := f.cache.NewCache()
// 先find 找出重复的 去掉重复的
- fs1, err := f.friend.NewTx(tx).FindFriends(ctx, ownerUserID, friendUserIDs)
+ fs1, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return err
}
@@ -169,11 +126,11 @@ func (f *friendDatabase) BecomeFriends(
return e.FriendUserID
})
- err = f.friend.NewTx(tx).Create(ctx, fs11)
+ err = f.friend.Create(ctx, fs11)
if err != nil {
return err
}
- fs2, err := f.friend.NewTx(tx).FindReversalFriends(ctx, ownerUserID, friendUserIDs)
+ fs2, err := f.friend.FindReversalFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return err
}
@@ -185,24 +142,19 @@ func (f *friendDatabase) BecomeFriends(
fs22 := utils.DistinctAny(fs2, func(e *relation.FriendModel) string {
return e.OwnerUserID
})
- err = f.friend.NewTx(tx).Create(ctx, fs22)
+ err = f.friend.Create(ctx, fs22)
if err != nil {
return err
}
newFriendIDs = append(newFriendIDs, ownerUserID)
cache = cache.DelFriendIDs(newFriendIDs...)
- return nil
- }); err != nil {
- return nil
- }
- return cache.ExecDel(ctx)
+ return cache.ExecDel(ctx)
+
+ })
}
// 拒绝好友申请 (1)检查是否有申请记录且为未处理状态 (没有记录返回错误) (2)修改申请记录 已拒绝.
-func (f *friendDatabase) RefuseFriendRequest(
- ctx context.Context,
- friendRequest *relation.FriendRequestModel,
-) (err error) {
+func (f *friendDatabase) RefuseFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
if err != nil {
return err
@@ -221,14 +173,11 @@ func (f *friendDatabase) RefuseFriendRequest(
}
// AgreeFriendRequest 同意好友申请 (1)检查是否有申请记录且为未处理状态 (没有记录返回错误) (2)检查是否好友(不返回错误) (3) 建立双向好友关系(存在的忽略).
-func (f *friendDatabase) AgreeFriendRequest(
- ctx context.Context,
- friendRequest *relation.FriendRequestModel,
-) (err error) {
- return f.tx.Transaction(func(tx any) error {
+func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
+ return f.tx.Transaction(ctx, func(ctx context.Context) error {
defer log.ZDebug(ctx, "return line")
now := time.Now()
- fr, err := f.friendRequest.NewTx(tx).Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
+ fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
if err != nil {
return err
}
@@ -238,25 +187,25 @@ func (f *friendDatabase) AgreeFriendRequest(
friendRequest.HandlerUserID = mcontext.GetOpUserID(ctx)
friendRequest.HandleResult = constant.FriendResponseAgree
friendRequest.HandleTime = now
- err = f.friendRequest.NewTx(tx).Update(ctx, friendRequest)
+ err = f.friendRequest.Update(ctx, friendRequest)
if err != nil {
return err
}
- fr2, err := f.friendRequest.NewTx(tx).Take(ctx, friendRequest.ToUserID, friendRequest.FromUserID)
+ fr2, err := f.friendRequest.Take(ctx, friendRequest.ToUserID, friendRequest.FromUserID)
if err == nil && fr2.HandleResult == constant.FriendResponseNotHandle {
fr2.HandlerUserID = mcontext.GetOpUserID(ctx)
fr2.HandleResult = constant.FriendResponseAgree
fr2.HandleTime = now
- err = f.friendRequest.NewTx(tx).Update(ctx, fr2)
+ err = f.friendRequest.Update(ctx, fr2)
if err != nil {
return err
}
- } else if err != nil && errs.Unwrap(err) != gorm.ErrRecordNotFound {
+ } else if err != nil && (!relation.IsNotFound(err)) {
return err
}
- exists, err := f.friend.NewTx(tx).FindUserState(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
+ exists, err := f.friend.FindUserState(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
if err != nil {
return err
}
@@ -287,7 +236,7 @@ func (f *friendDatabase) AgreeFriendRequest(
)
}
if len(adds) > 0 {
- if err := f.friend.NewTx(tx).Create(ctx, adds); err != nil {
+ if err := f.friend.Create(ctx, adds); err != nil {
return err
}
}
@@ -312,47 +261,27 @@ func (f *friendDatabase) UpdateRemark(ctx context.Context, ownerUserID, friendUs
}
// 获取ownerUserID的好友列表 无结果不返回错误.
-func (f *friendDatabase) PageOwnerFriends(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendModel, total int64, err error) {
- return f.friend.FindOwnerFriends(ctx, ownerUserID, pageNumber, showNumber)
+func (f *friendDatabase) PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) {
+ return f.friend.FindOwnerFriends(ctx, ownerUserID, pagination)
}
// friendUserID在哪些人的好友列表中.
-func (f *friendDatabase) PageInWhoseFriends(
- ctx context.Context,
- friendUserID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendModel, total int64, err error) {
- return f.friend.FindInWhoseFriends(ctx, friendUserID, pageNumber, showNumber)
+func (f *friendDatabase) PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) {
+ return f.friend.FindInWhoseFriends(ctx, friendUserID, pagination)
}
// 获取我发出去的好友申请 无结果不返回错误.
-func (f *friendDatabase) PageFriendRequestFromMe(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendRequestModel, total int64, err error) {
- return f.friendRequest.FindFromUserID(ctx, userID, pageNumber, showNumber)
+func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) {
+ return f.friendRequest.FindFromUserID(ctx, userID, pagination)
}
// 获取我收到的的好友申请 无结果不返回错误.
-func (f *friendDatabase) PageFriendRequestToMe(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (friends []*relation.FriendRequestModel, total int64, err error) {
- return f.friendRequest.FindToUserID(ctx, userID, pageNumber, showNumber)
+func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) {
+ return f.friendRequest.FindToUserID(ctx, userID, pagination)
}
// 获取某人指定好友的信息 如果有好友不存在,也返回错误.
-func (f *friendDatabase) FindFriendsWithError(
- ctx context.Context,
- ownerUserID string,
- friendUserIDs []string,
-) (friends []*relation.FriendModel, err error) {
+func (f *friendDatabase) FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error) {
friends, err = f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return
@@ -363,10 +292,7 @@ func (f *friendDatabase) FindFriendsWithError(
return
}
-func (f *friendDatabase) FindFriendUserIDs(
- ctx context.Context,
- ownerUserID string,
-) (friendUserIDs []string, err error) {
+func (f *friendDatabase) FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) {
return f.cache.GetFriendIDs(ctx, ownerUserID)
}
diff --git a/pkg/common/db/controller/group.go b/pkg/common/db/controller/group.go
index 194f3e8b2..4147d59c0 100644
--- a/pkg/common/db/controller/group.go
+++ b/pkg/common/db/controller/group.go
@@ -16,23 +16,18 @@ package controller
import (
"context"
- "fmt"
"time"
+ "github.com/OpenIMSDK/tools/pagination"
"github.com/dtm-labs/rockscache"
- "github.com/redis/go-redis/v9"
- "go.mongodb.org/mongo-driver/mongo"
- "gorm.io/gorm"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
+ "github.com/redis/go-redis/v9"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
- unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
)
type GroupDatabase interface {
@@ -40,23 +35,26 @@ type GroupDatabase interface {
CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error
TakeGroup(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error)
FindGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error)
- FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error)
- SearchGroup(ctx context.Context, keyword string, pageNumber, showNumber int32) (uint32, []*relationtb.GroupModel, error)
+ SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*relationtb.GroupModel, error)
UpdateGroup(ctx context.Context, groupID string, data map[string]any) error
DismissGroup(ctx context.Context, groupID string, deleteMember bool) error // 解散群,并删除群成员
- GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error)
- // GroupMember
+
TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *relationtb.GroupMemberModel, err error)
TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error)
- FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error)
+ FindGroupMembers(ctx context.Context, groupID string, userIDs []string) (groupMembers []*relationtb.GroupMemberModel, err error) // *
+ FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (groupMembers []*relationtb.GroupMemberModel, err error) // *
+ FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) (groupMembers []*relationtb.GroupMemberModel, err error) // *
+ FindGroupMemberAll(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error) // *
+ FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error)
FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error)
FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error)
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
- PageGroupRequest(ctx context.Context, groupIDs []string, pageNumber, showNumber int32) (uint32, []*relationtb.GroupRequestModel, error)
+ PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error)
+ GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
- PageGetJoinGroup(ctx context.Context, userID string, pageNumber, showNumber int32) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error)
- PageGetGroupMember(ctx context.Context, groupID string, pageNumber, showNumber int32) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error)
- SearchGroupMember(ctx context.Context, keyword string, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32) (uint32, []*relationtb.GroupMemberModel, error)
+ PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error)
+ PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error)
+ SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*relationtb.GroupMemberModel, error)
HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error
DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error
MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error)
@@ -67,15 +65,8 @@ type GroupDatabase interface {
// GroupRequest
CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error
TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationtb.GroupRequestModel, error)
- FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*relationtb.GroupRequestModel, error)
- PageGroupRequestUser(ctx context.Context, userID string, pageNumber, showNumber int32) (uint32, []*relationtb.GroupRequestModel, error)
- // SuperGroupModelInterface
- FindSuperGroup(ctx context.Context, groupIDs []string) ([]*unrelationtb.SuperGroupModel, error)
- FindJoinSuperGroup(ctx context.Context, userID string) ([]string, error)
- CreateSuperGroup(ctx context.Context, groupID string, initMemberIDList []string) error
- DeleteSuperGroup(ctx context.Context, groupID string) error
- DeleteSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error
- CreateSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error
+ FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupRequestModel, error)
+ PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error)
// 获取群总数
CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
@@ -85,126 +76,115 @@ type GroupDatabase interface {
}
func NewGroupDatabase(
- group relationtb.GroupModelInterface,
- member relationtb.GroupMemberModelInterface,
- request relationtb.GroupRequestModelInterface,
- tx tx.Tx,
+ rdb redis.UniversalClient,
+ groupDB relationtb.GroupModelInterface,
+ groupMemberDB relationtb.GroupMemberModelInterface,
+ groupRequestDB relationtb.GroupRequestModelInterface,
ctxTx tx.CtxTx,
- superGroup unrelationtb.SuperGroupModelInterface,
- cache cache.GroupCache,
+ groupHash cache.GroupHash,
) GroupDatabase {
- database := &groupDatabase{
- groupDB: group,
- groupMemberDB: member,
- groupRequestDB: request,
- tx: tx,
- ctxTx: ctxTx,
- cache: cache,
- mongoDB: superGroup,
- }
- return database
-}
-
-func InitGroupDatabase(db *gorm.DB, rdb redis.UniversalClient, database *mongo.Database, hashCode func(ctx context.Context, groupID string) (uint64, error)) GroupDatabase {
rcOptions := rockscache.NewDefaultOptions()
rcOptions.StrongConsistency = true
rcOptions.RandomExpireAdjustment = 0.2
- return NewGroupDatabase(
- relation.NewGroupDB(db),
- relation.NewGroupMemberDB(db),
- relation.NewGroupRequest(db),
- tx.NewGorm(db),
- tx.NewMongo(database.Client()),
- unrelation.NewSuperGroupMongoDriver(database),
- cache.NewGroupCacheRedis(
- rdb,
- relation.NewGroupDB(db),
- relation.NewGroupMemberDB(db),
- relation.NewGroupRequest(db),
- unrelation.NewSuperGroupMongoDriver(database),
- hashCode,
- rcOptions,
- ),
- )
+ return &groupDatabase{
+ groupDB: groupDB,
+ groupMemberDB: groupMemberDB,
+ groupRequestDB: groupRequestDB,
+ ctxTx: ctxTx,
+ cache: cache.NewGroupCacheRedis(rdb, groupDB, groupMemberDB, groupRequestDB, groupHash, rcOptions),
+ }
}
type groupDatabase struct {
groupDB relationtb.GroupModelInterface
groupMemberDB relationtb.GroupMemberModelInterface
groupRequestDB relationtb.GroupRequestModelInterface
- tx tx.Tx
ctxTx tx.CtxTx
cache cache.GroupCache
- mongoDB unrelationtb.SuperGroupModelInterface
}
-func (g *groupDatabase) GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error) {
- return g.groupDB.GetGroupIDsByGroupType(ctx, groupType)
+func (g *groupDatabase) FindGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.GetGroupMembersInfo(ctx, groupID, userIDs)
}
-func (g *groupDatabase) FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) {
- return g.cache.GetGroupMemberIDs(ctx, groupID)
+func (g *groupDatabase) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.FindGroupMemberUser(ctx, groupIDs, userID)
}
-func (g *groupDatabase) FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error) {
- num, err := g.cache.GetGroupMemberNum(ctx, groupID)
- if err != nil {
- return 0, err
- }
- return uint32(num), nil
+func (g *groupDatabase) FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.GetGroupRolesLevelMemberInfo(ctx, groupID, roleLevels)
}
-func (g *groupDatabase) CreateGroup(
- ctx context.Context,
- groups []*relationtb.GroupModel,
- groupMembers []*relationtb.GroupMemberModel,
-) error {
- cache := g.cache.NewCache()
- if err := g.tx.Transaction(func(tx any) error {
+func (g *groupDatabase) FindGroupMemberAll(ctx context.Context, groupID string) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.GetAllGroupMembersInfo(ctx, groupID)
+}
+
+func (g *groupDatabase) FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error) {
+ return g.cache.GetGroupsOwner(ctx, groupIDs)
+}
+
+func (g *groupDatabase) GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) {
+ return g.cache.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
+}
+
+func (g *groupDatabase) CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error {
+ if len(groups)+len(groupMembers) == 0 {
+ return nil
+ }
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ c := g.cache.NewCache()
if len(groups) > 0 {
- if err := g.groupDB.NewTx(tx).Create(ctx, groups); err != nil {
+ if err := g.groupDB.Create(ctx, groups); err != nil {
return err
}
+ for _, group := range groups {
+ c = c.DelGroupsInfo(group.GroupID).
+ DelGroupMembersHash(group.GroupID).
+ DelGroupMembersHash(group.GroupID).
+ DelGroupsMemberNum(group.GroupID).
+ DelGroupMemberIDs(group.GroupID).
+ DelGroupAllRoleLevel(group.GroupID)
+ }
}
if len(groupMembers) > 0 {
- if err := g.groupMemberDB.NewTx(tx).Create(ctx, groupMembers); err != nil {
+ if err := g.groupMemberDB.Create(ctx, groupMembers); err != nil {
return err
}
- }
- createGroupIDs := utils.DistinctAnyGetComparable(groups, func(group *relationtb.GroupModel) string {
- return group.GroupID
- })
- m := make(map[string]struct{})
-
- for _, groupMember := range groupMembers {
- if _, ok := m[groupMember.GroupID]; !ok {
- m[groupMember.GroupID] = struct{}{}
- cache = cache.DelGroupMemberIDs(groupMember.GroupID).DelGroupMembersHash(groupMember.GroupID).DelGroupsMemberNum(groupMember.GroupID)
+ for _, groupMember := range groupMembers {
+ c = c.DelGroupMembersHash(groupMember.GroupID).
+ DelGroupsMemberNum(groupMember.GroupID).
+ DelGroupMemberIDs(groupMember.GroupID).
+ DelJoinedGroupID(groupMember.UserID).
+ DelGroupMembersInfo(groupMember.GroupID, groupMember.UserID).
+ DelGroupAllRoleLevel(groupMember.GroupID)
}
- cache = cache.DelJoinedGroupID(groupMember.UserID).DelGroupMembersInfo(groupMember.GroupID, groupMember.UserID)
}
- cache = cache.DelGroupsInfo(createGroupIDs...)
- return nil
- }); err != nil {
- return err
+ return c.ExecDel(ctx, true)
+ })
+}
+
+func (g *groupDatabase) FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) {
+ return g.cache.GetGroupMemberIDs(ctx, groupID)
+}
+
+func (g *groupDatabase) FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error) {
+ num, err := g.cache.GetGroupMemberNum(ctx, groupID)
+ if err != nil {
+ return 0, err
}
- return cache.ExecDel(ctx)
+ return uint32(num), nil
}
-func (g *groupDatabase) TakeGroup(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error) {
+func (g *groupDatabase) TakeGroup(ctx context.Context, groupID string) (*relationtb.GroupModel, error) {
return g.cache.GetGroupInfo(ctx, groupID)
}
-func (g *groupDatabase) FindGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) {
+func (g *groupDatabase) FindGroup(ctx context.Context, groupIDs []string) ([]*relationtb.GroupModel, error) {
return g.cache.GetGroupsInfo(ctx, groupIDs)
}
-func (g *groupDatabase) SearchGroup(
- ctx context.Context,
- keyword string,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupModel, error) {
- return g.groupDB.Search(ctx, keyword, pageNumber, showNumber)
+func (g *groupDatabase) SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*relationtb.GroupModel, error) {
+ return g.groupDB.Search(ctx, keyword, pagination)
}
func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data map[string]any) error {
@@ -215,166 +195,97 @@ func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data ma
}
func (g *groupDatabase) DismissGroup(ctx context.Context, groupID string, deleteMember bool) error {
- cache := g.cache.NewCache()
- if err := g.tx.Transaction(func(tx any) error {
- if err := g.groupDB.NewTx(tx).UpdateStatus(ctx, groupID, constant.GroupStatusDismissed); err != nil {
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ c := g.cache.NewCache()
+ if err := g.groupDB.UpdateState(ctx, groupID, constant.GroupStatusDismissed); err != nil {
return err
}
if deleteMember {
- if err := g.groupMemberDB.NewTx(tx).DeleteGroup(ctx, []string{groupID}); err != nil {
- return err
- }
userIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID)
if err != nil {
return err
}
- cache = cache.DelJoinedGroupID(userIDs...).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelGroupMembersHash(groupID)
+ if err := g.groupMemberDB.Delete(ctx, groupID, nil); err != nil {
+ return err
+ }
+ c = c.DelJoinedGroupID(userIDs...).
+ DelGroupMemberIDs(groupID).
+ DelGroupsMemberNum(groupID).
+ DelGroupMembersHash(groupID).
+ DelGroupAllRoleLevel(groupID).
+ DelGroupMembersInfo(groupID, userIDs...)
}
- cache = cache.DelGroupsInfo(groupID)
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return c.DelGroupsInfo(groupID).ExecDel(ctx)
+ })
}
-func (g *groupDatabase) TakeGroupMember(
- ctx context.Context,
- groupID string,
- userID string,
-) (groupMember *relationtb.GroupMemberModel, err error) {
+func (g *groupDatabase) TakeGroupMember(ctx context.Context, groupID string, userID string) (*relationtb.GroupMemberModel, error) {
return g.cache.GetGroupMemberInfo(ctx, groupID, userID)
}
func (g *groupDatabase) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
- return g.groupMemberDB.TakeOwner(ctx, groupID) // todo cache group owner
+ return g.cache.GetGroupOwner(ctx, groupID)
}
func (g *groupDatabase) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
return g.groupMemberDB.FindUserManagedGroupID(ctx, userID)
}
-func (g *groupDatabase) PageGroupRequest(
- ctx context.Context,
- groupIDs []string,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupRequestModel, error) {
- return g.groupRequestDB.PageGroup(ctx, groupIDs, pageNumber, showNumber)
-}
-
-func (g *groupDatabase) FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) (totalGroupMembers []*relationtb.GroupMemberModel, err error) {
- if len(groupIDs) == 0 && len(roleLevels) == 0 && len(userIDs) == 1 {
- gIDs, err := g.cache.GetJoinedGroupIDs(ctx, userIDs[0])
- if err != nil {
- return nil, err
- }
- var res []*relationtb.GroupMemberModel
- for _, groupID := range gIDs {
- v, err := g.cache.GetGroupMemberInfo(ctx, groupID, userIDs[0])
- if err != nil {
- return nil, err
- }
- res = append(res, v)
- }
- return res, nil
- }
- if len(roleLevels) == 0 {
- for _, groupID := range groupIDs {
- groupMembers, err := g.cache.GetGroupMembersInfo(ctx, groupID, userIDs)
- if err != nil {
- return nil, err
- }
- totalGroupMembers = append(totalGroupMembers, groupMembers...)
- }
- return totalGroupMembers, nil
- }
- return g.groupMemberDB.Find(ctx, groupIDs, userIDs, roleLevels)
+func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) {
+ return g.groupRequestDB.PageGroup(ctx, groupIDs, pagination)
}
-func (g *groupDatabase) PageGetJoinGroup(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
+func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
groupIDs, err := g.cache.GetJoinedGroupIDs(ctx, userID)
if err != nil {
return 0, nil, err
}
- for _, groupID := range utils.Paginate(groupIDs, int(pageNumber), int(showNumber)) {
+ for _, groupID := range utils.Paginate(groupIDs, int(pagination.GetPageNumber()), int(pagination.GetShowNumber())) {
groupMembers, err := g.cache.GetGroupMembersInfo(ctx, groupID, []string{userID})
if err != nil {
return 0, nil, err
}
totalGroupMembers = append(totalGroupMembers, groupMembers...)
}
- return uint32(len(groupIDs)), totalGroupMembers, nil
+ return int64(len(groupIDs)), totalGroupMembers, nil
}
-func (g *groupDatabase) PageGetGroupMember(
- ctx context.Context,
- groupID string,
- pageNumber, showNumber int32,
-) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
+func (g *groupDatabase) PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
groupMemberIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID)
if err != nil {
return 0, nil, err
}
- pageIDs := utils.Paginate(groupMemberIDs, int(pageNumber), int(showNumber))
+ pageIDs := utils.Paginate(groupMemberIDs, int(pagination.GetPageNumber()), int(pagination.GetShowNumber()))
if len(pageIDs) == 0 {
- return uint32(len(groupMemberIDs)), nil, nil
+ return int64(len(groupMemberIDs)), nil, nil
}
members, err := g.cache.GetGroupMembersInfo(ctx, groupID, pageIDs)
if err != nil {
return 0, nil, err
}
- return uint32(len(groupMemberIDs)), members, nil
+ return int64(len(groupMemberIDs)), members, nil
}
-func (g *groupDatabase) SearchGroupMember(
- ctx context.Context,
- keyword string,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupMemberModel, error) {
- return g.groupMemberDB.SearchMember(ctx, keyword, groupIDs, userIDs, roleLevels, pageNumber, showNumber)
+func (g *groupDatabase) SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*relationtb.GroupMemberModel, error) {
+ return g.groupMemberDB.SearchMember(ctx, keyword, groupID, pagination)
}
-func (g *groupDatabase) HandlerGroupRequest(
- ctx context.Context,
- groupID string,
- userID string,
- handledMsg string,
- handleResult int32,
- member *relationtb.GroupMemberModel,
-) error {
- //cache := g.cache.NewCache()
- //if err := g.tx.Transaction(func(tx any) error {
- // if err := g.groupRequestDB.NewTx(tx).UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
- // return err
- // }
- // if member != nil {
- // if err := g.groupMemberDB.NewTx(tx).Create(ctx, []*relationtb.GroupMemberModel{member}); err != nil {
- // return err
- // }
- // cache = cache.DelGroupMembersHash(groupID).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelJoinedGroupID(member.UserID)
- // }
- // return nil
- //}); err != nil {
- // return err
- //}
- //return cache.ExecDel(ctx)
-
- return g.tx.Transaction(func(tx any) error {
- if err := g.groupRequestDB.NewTx(tx).UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
+func (g *groupDatabase) HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error {
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ if err := g.groupRequestDB.UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
return err
}
if member != nil {
- if err := g.groupMemberDB.NewTx(tx).Create(ctx, []*relationtb.GroupMemberModel{member}); err != nil {
+ if err := g.groupMemberDB.Create(ctx, []*relationtb.GroupMemberModel{member}); err != nil {
return err
}
- if err := g.cache.NewCache().DelGroupMembersHash(groupID).DelGroupMembersInfo(groupID, member.UserID).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelJoinedGroupID(member.UserID).ExecDel(ctx); err != nil {
+ c := g.cache.DelGroupMembersHash(groupID).
+ DelGroupMembersInfo(groupID, member.UserID).
+ DelGroupMemberIDs(groupID).
+ DelGroupsMemberNum(groupID).
+ DelJoinedGroupID(member.UserID).
+ DelGroupRoleLevel(groupID, []int32{member.RoleLevel})
+ if err := c.ExecDel(ctx); err != nil {
return err
}
}
@@ -391,13 +302,11 @@ func (g *groupDatabase) DeleteGroupMember(ctx context.Context, groupID string, u
DelGroupsMemberNum(groupID).
DelJoinedGroupID(userIDs...).
DelGroupMembersInfo(groupID, userIDs...).
+ DelGroupAllRoleLevel(groupID).
ExecDel(ctx)
}
-func (g *groupDatabase) MapGroupMemberUserID(
- ctx context.Context,
- groupIDs []string,
-) (map[string]*relationtb.GroupSimpleUserID, error) {
+func (g *groupDatabase) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) {
return g.cache.GetGroupMemberHashMap(ctx, groupIDs)
}
@@ -414,62 +323,54 @@ func (g *groupDatabase) MapGroupMemberNum(ctx context.Context, groupIDs []string
}
func (g *groupDatabase) TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error {
- return g.tx.Transaction(func(tx any) error {
- rowsAffected, err := g.groupMemberDB.NewTx(tx).UpdateRoleLevel(ctx, groupID, oldOwnerUserID, roleLevel)
- if err != nil {
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ if err := g.groupMemberDB.UpdateRoleLevel(ctx, groupID, oldOwnerUserID, roleLevel); err != nil {
return err
}
- if rowsAffected != 1 {
- return utils.Wrap(fmt.Errorf("oldOwnerUserID %s rowsAffected = %d", oldOwnerUserID, rowsAffected), "")
- }
- rowsAffected, err = g.groupMemberDB.NewTx(tx).UpdateRoleLevel(ctx, groupID, newOwnerUserID, constant.GroupOwner)
- if err != nil {
+ if err := g.groupMemberDB.UpdateRoleLevel(ctx, groupID, newOwnerUserID, constant.GroupOwner); err != nil {
return err
}
- if rowsAffected != 1 {
- return utils.Wrap(fmt.Errorf("newOwnerUserID %s rowsAffected = %d", newOwnerUserID, rowsAffected), "")
- }
- return g.cache.DelGroupMembersInfo(groupID, oldOwnerUserID, newOwnerUserID).DelGroupMembersHash(groupID).ExecDel(ctx)
+ return g.cache.DelGroupMembersInfo(groupID, oldOwnerUserID, newOwnerUserID).
+ DelGroupAllRoleLevel(groupID).
+ DelGroupMembersHash(groupID).ExecDel(ctx)
})
}
-func (g *groupDatabase) UpdateGroupMember(
- ctx context.Context,
- groupID string,
- userID string,
- data map[string]any,
-) error {
+func (g *groupDatabase) UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error {
if err := g.groupMemberDB.Update(ctx, groupID, userID, data); err != nil {
return err
}
- return g.cache.DelGroupMembersInfo(groupID, userID).ExecDel(ctx)
+ c := g.cache.DelGroupMembersInfo(groupID, userID)
+ if g.groupMemberDB.IsUpdateRoleLevel(data) {
+ c = c.DelGroupAllRoleLevel(groupID)
+ }
+ return c.ExecDel(ctx)
}
func (g *groupDatabase) UpdateGroupMembers(ctx context.Context, data []*relationtb.BatchUpdateGroupMember) error {
- cache := g.cache.NewCache()
- if err := g.tx.Transaction(func(tx any) error {
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
+ c := g.cache.NewCache()
for _, item := range data {
- if err := g.groupMemberDB.NewTx(tx).Update(ctx, item.GroupID, item.UserID, item.Map); err != nil {
+ if err := g.groupMemberDB.Update(ctx, item.GroupID, item.UserID, item.Map); err != nil {
return err
}
- cache = cache.DelGroupMembersInfo(item.GroupID, item.UserID)
+ if g.groupMemberDB.IsUpdateRoleLevel(item.Map) {
+ c = c.DelGroupAllRoleLevel(item.GroupID)
+ }
+ c = c.DelGroupMembersInfo(item.GroupID, item.UserID).DelGroupMembersHash(item.GroupID)
}
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
+ return c.ExecDel(ctx, true)
+ })
}
func (g *groupDatabase) CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error {
- return g.tx.Transaction(func(tx any) error {
- db := g.groupRequestDB.NewTx(tx)
+ return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
for _, request := range requests {
- if err := db.Delete(ctx, request.GroupID, request.UserID); err != nil {
+ if err := g.groupRequestDB.Delete(ctx, request.GroupID, request.UserID); err != nil {
return err
}
}
- return db.Create(ctx, requests)
+ return g.groupRequestDB.Create(ctx, requests)
})
}
@@ -481,65 +382,8 @@ func (g *groupDatabase) TakeGroupRequest(
return g.groupRequestDB.Take(ctx, groupID, userID)
}
-func (g *groupDatabase) PageGroupRequestUser(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (uint32, []*relationtb.GroupRequestModel, error) {
- return g.groupRequestDB.Page(ctx, userID, pageNumber, showNumber)
-}
-
-func (g *groupDatabase) FindSuperGroup(
- ctx context.Context,
- groupIDs []string,
-) (models []*unrelationtb.SuperGroupModel, err error) {
- return g.cache.GetSuperGroupMemberIDs(ctx, groupIDs...)
-}
-
-func (g *groupDatabase) FindJoinSuperGroup(ctx context.Context, userID string) ([]string, error) {
- return g.cache.GetJoinedSuperGroupIDs(ctx, userID)
-}
-
-func (g *groupDatabase) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error {
- if err := g.mongoDB.CreateSuperGroup(ctx, groupID, initMemberIDs); err != nil {
- return err
- }
- return g.cache.DelSuperGroupMemberIDs(groupID).DelJoinedSuperGroupIDs(initMemberIDs...).ExecDel(ctx)
-}
-
-func (g *groupDatabase) DeleteSuperGroup(ctx context.Context, groupID string) error {
- cache := g.cache.NewCache()
- if err := g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
- if err := g.mongoDB.DeleteSuperGroup(ctx, groupID); err != nil {
- return err
- }
- models, err := g.cache.GetSuperGroupMemberIDs(ctx, groupID)
- if err != nil {
- return err
- }
- cache = cache.DelSuperGroupMemberIDs(groupID)
- if len(models) > 0 {
- cache = cache.DelJoinedSuperGroupIDs(models[0].MemberIDs...)
- }
- return nil
- }); err != nil {
- return err
- }
- return cache.ExecDel(ctx)
-}
-
-func (g *groupDatabase) DeleteSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error {
- if err := g.mongoDB.RemoverUserFromSuperGroup(ctx, groupID, userIDs); err != nil {
- return err
- }
- return g.cache.DelSuperGroupMemberIDs(groupID).DelJoinedSuperGroupIDs(userIDs...).ExecDel(ctx)
-}
-
-func (g *groupDatabase) CreateSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error {
- if err := g.mongoDB.AddUserToSuperGroup(ctx, groupID, userIDs); err != nil {
- return err
- }
- return g.cache.DelSuperGroupMemberIDs(groupID).DelJoinedSuperGroupIDs(userIDs...).ExecDel(ctx)
+func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) {
+ return g.groupRequestDB.Page(ctx, userID, pagination)
}
func (g *groupDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
@@ -550,14 +394,10 @@ func (g *groupDatabase) CountRangeEverydayTotal(ctx context.Context, start time.
return g.groupDB.CountRangeEverydayTotal(ctx, start, end)
}
-func (g *groupDatabase) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*relationtb.GroupRequestModel, error) {
+func (g *groupDatabase) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupRequestModel, error) {
return g.groupRequestDB.FindGroupRequests(ctx, groupID, userIDs)
}
-func (g *groupDatabase) FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) {
- return g.groupDB.FindNotDismissedGroup(ctx, groupIDs)
-}
-
func (g *groupDatabase) DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error {
if len(groupIDs) == 0 {
return nil
@@ -566,6 +406,5 @@ func (g *groupDatabase) DeleteGroupMemberHash(ctx context.Context, groupIDs []st
for _, groupID := range groupIDs {
c = c.DelGroupMembersHash(groupID)
}
-
return c.ExecDel(ctx)
}
diff --git a/pkg/common/db/controller/msg.go b/pkg/common/db/controller/msg.go
index cba0a6bbd..fb0a9c702 100644
--- a/pkg/common/db/controller/msg.go
+++ b/pkg/common/db/controller/msg.go
@@ -357,9 +357,7 @@ func (db *commonMsgDatabase) DelUserDeleteMsgsList(ctx context.Context, conversa
}
func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNew bool, err error) {
- cancelCtx, cancel := context.WithTimeout(ctx, 1*time.Minute)
- defer cancel()
- currentMaxSeq, err := db.cache.GetMaxSeq(cancelCtx, conversationID)
+ currentMaxSeq, err := db.cache.GetMaxSeq(ctx, conversationID)
if err != nil && errs.Unwrap(err) != redis.Nil {
log.ZError(ctx, "db.cache.GetMaxSeq", err)
return 0, false, err
@@ -386,21 +384,19 @@ func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversa
prommetrics.MsgInsertRedisFailedCounter.Add(float64(failedNum))
log.ZError(ctx, "setMessageToCache error", err, "len", len(msgs), "conversationID", conversationID)
} else {
- prommetrics.MsgInsertRedisSuccessCounter.Add(float64(len(msgs)))
+ prommetrics.MsgInsertRedisSuccessCounter.Inc()
}
- cancelCtx, cancel = context.WithTimeout(ctx, 1*time.Minute)
- defer cancel()
- err = db.cache.SetMaxSeq(cancelCtx, conversationID, currentMaxSeq)
+ err = db.cache.SetMaxSeq(ctx, conversationID, currentMaxSeq)
if err != nil {
log.ZError(ctx, "db.cache.SetMaxSeq error", err, "conversationID", conversationID)
prommetrics.SeqSetFailedCounter.Inc()
}
err2 := db.cache.SetHasReadSeqs(ctx, conversationID, userSeqMap)
- if err2 != nil {
+ if err != nil {
log.ZError(ctx, "SetHasReadSeqs error", err2, "userSeqMap", userSeqMap, "conversationID", conversationID)
prommetrics.SeqSetFailedCounter.Inc()
}
- return lastMaxSeq, isNew, errs.Wrap(err, "redis SetMaxSeq error")
+ return lastMaxSeq, isNew, utils.Wrap(err, "")
}
func (db *commonMsgDatabase) getMsgBySeqs(ctx context.Context, userID, conversationID string, seqs []int64) (totalMsgs []*sdkws.MsgData, err error) {
@@ -658,26 +654,16 @@ func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID strin
func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) (int64, int64, []*sdkws.MsgData, error) {
userMinSeq, err := db.cache.GetConversationUserMinSeq(ctx, conversationID, userID)
- if err != nil {
- log.ZError(ctx, "cache.GetConversationUserMinSeq error", err)
- if errs.Unwrap(err) != redis.Nil {
- return 0, 0, nil, err
- }
+ if err != nil && errs.Unwrap(err) != redis.Nil {
+ return 0, 0, nil, err
}
minSeq, err := db.cache.GetMinSeq(ctx, conversationID)
- if err != nil {
- log.ZError(ctx, "cache.GetMinSeq error", err)
- if errs.Unwrap(err) != redis.Nil {
- return 0, 0, nil, err
- }
+ if err != nil && errs.Unwrap(err) != redis.Nil {
+ return 0, 0, nil, err
}
maxSeq, err := db.cache.GetMaxSeq(ctx, conversationID)
- if err != nil {
- log.ZError(ctx, "cache.GetMaxSeq error", err)
- if errs.Unwrap(err) != redis.Nil {
- return 0, 0, nil, err
- }
-
+ if err != nil && errs.Unwrap(err) != redis.Nil {
+ return 0, 0, nil, err
}
if userMinSeq < minSeq {
minSeq = userMinSeq
@@ -690,16 +676,34 @@ func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, co
}
successMsgs, failedSeqs, err := db.cache.GetMessagesBySeq(ctx, conversationID, newSeqs)
if err != nil {
- log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID)
+ if err != redis.Nil {
+ log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID)
+ }
}
- log.ZInfo(ctx, "db.cache.GetMessagesBySeq", "userID", userID, "conversationID", conversationID, "seqs", seqs, "successMsgs",
- len(successMsgs), "failedSeqs", failedSeqs, "conversationID", conversationID)
+ log.ZInfo(
+ ctx,
+ "db.cache.GetMessagesBySeq",
+ "userID",
+ userID,
+ "conversationID",
+ conversationID,
+ "seqs",
+ seqs,
+ "successMsgs",
+ len(successMsgs),
+ "failedSeqs",
+ failedSeqs,
+ "conversationID",
+ conversationID,
+ )
if len(failedSeqs) > 0 {
mongoMsgs, err := db.getMsgBySeqs(ctx, userID, conversationID, failedSeqs)
if err != nil {
+
return 0, 0, nil, err
}
+
successMsgs = append(successMsgs, mongoMsgs...)
}
return minSeq, maxSeq, successMsgs, nil
diff --git a/pkg/common/db/controller/msg_test.go b/pkg/common/db/controller/msg_test.go
index ba5aecd25..cfb969b3e 100644
--- a/pkg/common/db/controller/msg_test.go
+++ b/pkg/common/db/controller/msg_test.go
@@ -235,7 +235,7 @@ func Test_FindBySeq(t *testing.T) {
func TestName(t *testing.T) {
db := GetDB()
var seqs []int64
- for i := int64(1); i <= 4; i++ {
+ for i := int64(1); i <= 50; i++ {
seqs = append(seqs, i)
}
msgs, err := db.getMsgBySeqsRange(context.Background(), "4931176757", "si_3866692501_4931176757", seqs, seqs[0], seqs[len(seqs)-1])
diff --git a/pkg/common/db/controller/s3.go b/pkg/common/db/controller/s3.go
index ddbd5d27f..6916a7d30 100644
--- a/pkg/common/db/controller/s3.go
+++ b/pkg/common/db/controller/s3.go
@@ -72,14 +72,15 @@ func (s *s3Database) CompleteMultipartUpload(ctx context.Context, uploadID strin
}
func (s *s3Database) SetObject(ctx context.Context, info *relation.ObjectModel) error {
+ info.Engine = s.s3.Engine()
if err := s.db.SetObject(ctx, info); err != nil {
return err
}
- return s.cache.DelObjectName(info.Name).ExecDel(ctx)
+ return s.cache.DelObjectName(info.Engine, info.Name).ExecDel(ctx)
}
func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error) {
- obj, err := s.cache.GetName(ctx, name)
+ obj, err := s.cache.GetName(ctx, s.s3.Engine(), name)
if err != nil {
return time.Time{}, "", err
}
diff --git a/pkg/common/db/controller/third.go b/pkg/common/db/controller/third.go
index 971719b1f..fb5b0ccbe 100644
--- a/pkg/common/db/controller/third.go
+++ b/pkg/common/db/controller/third.go
@@ -18,10 +18,9 @@ import (
"context"
"time"
- "gorm.io/gorm"
+ "github.com/OpenIMSDK/tools/pagination"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
- dbimpl "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
@@ -29,22 +28,15 @@ type ThirdDatabase interface {
FcmUpdateToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) error
SetAppBadge(ctx context.Context, userID string, value int) error
// about log for debug
- UploadLogs(ctx context.Context, logs []*relation.Log) error
+ UploadLogs(ctx context.Context, logs []*relation.LogModel) error
DeleteLogs(ctx context.Context, logID []string, userID string) error
- SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relation.Log, error)
- GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.Log, error)
- FindUsers(ctx context.Context, userIDs []string) ([]*relation.UserModel, error)
+ SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error)
+ GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.LogModel, error)
}
type thirdDatabase struct {
- cache cache.MsgModel
- logdb relation.LogInterface
- userdb relation.UserModelInterface
-}
-
-// FindUsers implements ThirdDatabase.
-func (t *thirdDatabase) FindUsers(ctx context.Context, userIDs []string) ([]*relation.UserModel, error) {
- return t.userdb.Find(ctx, userIDs)
+ cache cache.MsgModel
+ logdb relation.LogInterface
}
// DeleteLogs implements ThirdDatabase.
@@ -53,22 +45,22 @@ func (t *thirdDatabase) DeleteLogs(ctx context.Context, logID []string, userID s
}
// GetLogs implements ThirdDatabase.
-func (t *thirdDatabase) GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.Log, error) {
+func (t *thirdDatabase) GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.LogModel, error) {
return t.logdb.Get(ctx, LogIDs, userID)
}
// SearchLogs implements ThirdDatabase.
-func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relation.Log, error) {
- return t.logdb.Search(ctx, keyword, start, end, pageNumber, showNumber)
+func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error) {
+ return t.logdb.Search(ctx, keyword, start, end, pagination)
}
// UploadLogs implements ThirdDatabase.
-func (t *thirdDatabase) UploadLogs(ctx context.Context, logs []*relation.Log) error {
+func (t *thirdDatabase) UploadLogs(ctx context.Context, logs []*relation.LogModel) error {
return t.logdb.Create(ctx, logs)
}
-func NewThirdDatabase(cache cache.MsgModel, db *gorm.DB) ThirdDatabase {
- return &thirdDatabase{cache: cache, logdb: dbimpl.NewLogGorm(db), userdb: dbimpl.NewUserGorm(db)}
+func NewThirdDatabase(cache cache.MsgModel, logdb relation.LogInterface) ThirdDatabase {
+ return &thirdDatabase{cache: cache, logdb: logdb}
}
func (t *thirdDatabase) FcmUpdateToken(
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index 9c6fdc5c4..ca703b729 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -18,16 +18,19 @@ import (
"context"
"time"
+ "github.com/OpenIMSDK/tools/pagination"
+ "github.com/OpenIMSDK/tools/tx"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+
"github.com/OpenIMSDK/protocol/user"
unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
"github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
type UserDatabase interface {
@@ -38,15 +41,15 @@ type UserDatabase interface {
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db
Create(ctx context.Context, users []*relation.UserModel) (err error)
// Update update (non-zero value) external guarantee userID exists
- Update(ctx context.Context, user *relation.UserModel) (err error)
+ //Update(ctx context.Context, user *relation.UserModel) (err error)
// UpdateByMap update (zero value) external guarantee userID exists
- UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error)
+ UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
// Page If not found, no error is returned
- Page(ctx context.Context, pageNumber, showNumber int32) (users []*relation.UserModel, count int64, err error)
+ Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
// IsExist true as long as one exists
IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
// GetAllUserID Get all user IDs
- GetAllUserID(ctx context.Context, pageNumber, showNumber int32) ([]string, error)
+ GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error)
// InitOnce Inside the function, first query whether it exists in the db, if it exists, do nothing; if it does not exist, insert it
InitOnce(ctx context.Context, users []*relation.UserModel) (err error)
// CountTotal Get the total number of users
@@ -68,28 +71,40 @@ type UserDatabase interface {
}
type userDatabase struct {
+ tx tx.CtxTx
userDB relation.UserModelInterface
cache cache.UserCache
- tx tx.Tx
mongoDB unrelationtb.UserModelInterface
}
-func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache, tx tx.Tx, mongoDB unrelationtb.UserModelInterface) UserDatabase {
+func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache, tx tx.CtxTx, mongoDB unrelationtb.UserModelInterface) UserDatabase {
return &userDatabase{userDB: userDB, cache: cache, tx: tx, mongoDB: mongoDB}
}
-func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel) (err error) {
+func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel) error {
+ // Extract user IDs from the given user models.
userIDs := utils.Slice(users, func(e *relation.UserModel) string {
return e.UserID
})
- result, err := u.userDB.Find(ctx, userIDs)
+
+ // Find existing users in the database.
+ existingUsers, err := u.userDB.Find(ctx, userIDs)
if err != nil {
return err
}
- miss := utils.SliceAnySub(users, result, func(e *relation.UserModel) string { return e.UserID })
- if len(miss) > 0 {
- _ = u.userDB.Create(ctx, miss)
+
+ // Determine which users are missing from the database.
+ missingUsers := utils.SliceAnySub(users, existingUsers, func(e *relation.UserModel) string {
+ return e.UserID
+ })
+
+ // Create records for missing users.
+ if len(missingUsers) > 0 {
+ if err := u.userDB.Create(ctx, missingUsers); err != nil {
+ return err
+ }
}
+
return nil
}
@@ -107,50 +122,42 @@ func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (use
// Find Get the information of the specified user. If the userID is not found, no error will be returned.
func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
- users, err = u.cache.GetUsersInfo(ctx, userIDs)
- return
+ return u.cache.GetUsersInfo(ctx, userIDs)
}
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db.
func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) {
- if err := u.tx.Transaction(func(tx any) error {
- err = u.userDB.Create(ctx, users)
- if err != nil {
+ return u.tx.Transaction(ctx, func(ctx context.Context) error {
+ if err = u.userDB.Create(ctx, users); err != nil {
return err
}
- return nil
- }); err != nil {
- return err
- }
- var userIDs []string
- for _, user := range users {
- userIDs = append(userIDs, user.UserID)
- }
- return u.cache.DelUsersInfo(userIDs...).ExecDel(ctx)
+ return u.cache.DelUsersInfo(utils.Slice(users, func(e *relation.UserModel) string {
+ return e.UserID
+ })...).ExecDel(ctx)
+ })
}
-// Update (non-zero value) externally guarantees that userID exists.
-func (u *userDatabase) Update(ctx context.Context, user *relation.UserModel) (err error) {
- if err := u.userDB.Update(ctx, user); err != nil {
- return err
- }
- return u.cache.DelUsersInfo(user.UserID).ExecDel(ctx)
-}
+//// Update (non-zero value) externally guarantees that userID exists.
+//func (u *userDatabase) Update(ctx context.Context, user *relation.UserModel) (err error) {
+// if err := u.userDB.Update(ctx, user); err != nil {
+// return err
+// }
+// return u.cache.DelUsersInfo(user.UserID).ExecDel(ctx)
+//}
// UpdateByMap update (zero value) externally guarantees that userID exists.
-func (u *userDatabase) UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error) {
- if err := u.userDB.UpdateByMap(ctx, userID, args); err != nil {
- return err
- }
- return u.cache.DelUsersInfo(userID).ExecDel(ctx)
+func (u *userDatabase) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error) {
+ return u.tx.Transaction(ctx, func(ctx context.Context) error {
+ if err := u.userDB.UpdateByMap(ctx, userID, args); err != nil {
+ return err
+ }
+ return u.cache.DelUsersInfo(userID).ExecDel(ctx)
+ })
}
// Page Gets, returns no error if not found.
-func (u *userDatabase) Page(
- ctx context.Context,
- pageNumber, showNumber int32,
-) (users []*relation.UserModel, count int64, err error) {
- return u.userDB.Page(ctx, pageNumber, showNumber)
+func (u *userDatabase) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return u.userDB.Page(ctx, pagination)
}
// IsExist Does userIDs exist? As long as there is one, it will be true.
@@ -166,8 +173,8 @@ func (u *userDatabase) IsExist(ctx context.Context, userIDs []string) (exist boo
}
// GetAllUserID Get all user IDs.
-func (u *userDatabase) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) {
- return u.userDB.GetAllUserID(ctx, pageNumber, showNumber)
+func (u *userDatabase) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (total int64, userIDs []string, err error) {
+ return u.userDB.GetAllUserID(ctx, pagination)
}
// CountTotal Get the total number of users.
diff --git a/pkg/common/db/mgo/black.go b/pkg/common/db/mgo/black.go
new file mode 100644
index 000000000..6235639aa
--- /dev/null
+++ b/pkg/common/db/mgo/black.go
@@ -0,0 +1,91 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewBlackMongo(db *mongo.Database) (relation.BlackModelInterface, error) {
+ coll := db.Collection("black")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "owner_user_id", Value: 1},
+ {Key: "block_user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &BlackMgo{coll: coll}, nil
+}
+
+type BlackMgo struct {
+ coll *mongo.Collection
+}
+
+func (b *BlackMgo) blackFilter(ownerUserID, blockUserID string) bson.M {
+ return bson.M{
+ "owner_user_id": ownerUserID,
+ "block_user_id": blockUserID,
+ }
+}
+
+func (b *BlackMgo) blacksFilter(blacks []*relation.BlackModel) bson.M {
+ if len(blacks) == 0 {
+ return nil
+ }
+ or := make(bson.A, 0, len(blacks))
+ for _, black := range blacks {
+ or = append(or, b.blackFilter(black.OwnerUserID, black.BlockUserID))
+ }
+ return bson.M{"$or": or}
+}
+
+func (b *BlackMgo) Create(ctx context.Context, blacks []*relation.BlackModel) (err error) {
+ return mgoutil.InsertMany(ctx, b.coll, blacks)
+}
+
+func (b *BlackMgo) Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) {
+ if len(blacks) == 0 {
+ return nil
+ }
+ return mgoutil.DeleteMany(ctx, b.coll, b.blacksFilter(blacks))
+}
+
+func (b *BlackMgo) UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]any) (err error) {
+ if len(args) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, b.coll, b.blackFilter(ownerUserID, blockUserID), bson.M{"$set": args}, false)
+}
+
+func (b *BlackMgo) Find(ctx context.Context, blacks []*relation.BlackModel) (blackList []*relation.BlackModel, err error) {
+ return mgoutil.Find[*relation.BlackModel](ctx, b.coll, b.blacksFilter(blacks))
+}
+
+func (b *BlackMgo) Take(ctx context.Context, ownerUserID, blockUserID string) (black *relation.BlackModel, err error) {
+ return mgoutil.FindOne[*relation.BlackModel](ctx, b.coll, b.blackFilter(ownerUserID, blockUserID))
+}
+
+func (b *BlackMgo) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) {
+ return mgoutil.FindPage[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID}, pagination)
+}
+
+func (b *BlackMgo) FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) {
+ if len(userIDs) == 0 {
+ return mgoutil.Find[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID})
+ }
+ return mgoutil.Find[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID, "block_user_id": bson.M{"$in": userIDs}})
+}
+
+func (b *BlackMgo) FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error) {
+ return mgoutil.Find[string](ctx, b.coll, bson.M{"owner_user_id": ownerUserID}, options.Find().SetProjection(bson.M{"_id": 0, "block_user_id": 1}))
+}
diff --git a/pkg/common/db/mgo/conversation.go b/pkg/common/db/mgo/conversation.go
new file mode 100644
index 000000000..72d04ebb3
--- /dev/null
+++ b/pkg/common/db/mgo/conversation.go
@@ -0,0 +1,150 @@
+package mgo
+
+import (
+ "context"
+ "time"
+
+ "github.com/OpenIMSDK/protocol/constant"
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewConversationMongo(db *mongo.Database) (*ConversationMgo, error) {
+ coll := db.Collection("conversation")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "owner_user_id", Value: 1},
+ {Key: "conversation_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &ConversationMgo{coll: coll}, nil
+}
+
+type ConversationMgo struct {
+ coll *mongo.Collection
+}
+
+func (c *ConversationMgo) Create(ctx context.Context, conversations []*relation.ConversationModel) (err error) {
+ return mgoutil.InsertMany(ctx, c.coll, conversations)
+}
+
+func (c *ConversationMgo) Delete(ctx context.Context, groupIDs []string) (err error) {
+ return mgoutil.DeleteMany(ctx, c.coll, bson.M{"group_id": bson.M{"$in": groupIDs}})
+}
+
+func (c *ConversationMgo) UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]any) (rows int64, err error) {
+ res, err := mgoutil.UpdateMany(ctx, c.coll, bson.M{"owner_user_id": bson.M{"$in": userIDs}, "conversation_id": conversationID}, bson.M{"$set": args})
+ if err != nil {
+ return 0, err
+ }
+ return res.ModifiedCount, nil
+}
+
+func (c *ConversationMgo) Update(ctx context.Context, conversation *relation.ConversationModel) (err error) {
+ return mgoutil.UpdateOne(ctx, c.coll, bson.M{"owner_user_id": conversation.OwnerUserID, "conversation_id": conversation.ConversationID}, bson.M{"$set": conversation}, true)
+}
+
+func (c *ConversationMgo) Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*relation.ConversationModel, err error) {
+ return mgoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": ownerUserID, "conversation_id": bson.M{"$in": conversationIDs}})
+}
+
+func (c *ConversationMgo) FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error) {
+ return mgoutil.Find[string](
+ ctx,
+ c.coll,
+ bson.M{"owner_user_id": bson.M{"$in": userIDs}, "conversation_id": bson.M{"$in": conversationIDs}},
+ options.Find().SetProjection(bson.M{"_id": 0, "owner_user_id": 1}),
+ )
+}
+
+func (c *ConversationMgo) FindUserIDAllConversationID(ctx context.Context, userID string) ([]string, error) {
+ return mgoutil.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
+}
+
+func (c *ConversationMgo) Take(ctx context.Context, userID, conversationID string) (conversation *relation.ConversationModel, err error) {
+ return mgoutil.FindOne[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": conversationID})
+}
+
+func (c *ConversationMgo) FindConversationID(ctx context.Context, userID string, conversationIDs []string) (existConversationID []string, err error) {
+ return mgoutil.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": bson.M{"$in": conversationIDs}}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
+}
+
+func (c *ConversationMgo) FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*relation.ConversationModel, err error) {
+ return mgoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": userID})
+}
+
+func (c *ConversationMgo) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) {
+ return mgoutil.Find[string](ctx, c.coll, bson.M{"group_id": groupID, "recv_msg_opt": constant.ReceiveNotNotifyMessage}, options.Find().SetProjection(bson.M{"_id": 0, "owner_user_id": 1}))
+}
+
+func (c *ConversationMgo) GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error) {
+ return mgoutil.FindOne[int](ctx, c.coll, bson.M{"owner_user_id": ownerUserID, "conversation_id": conversationID}, options.FindOne().SetProjection(bson.M{"recv_msg_opt": 1}))
+}
+
+func (c *ConversationMgo) GetAllConversationIDs(ctx context.Context) ([]string, error) {
+ return mgoutil.Aggregate[string](ctx, c.coll, []bson.M{
+ {"$group": bson.M{"_id": "$conversation_id"}},
+ {"$project": bson.M{"_id": 0, "conversation_id": "$_id"}},
+ })
+}
+
+func (c *ConversationMgo) GetAllConversationIDsNumber(ctx context.Context) (int64, error) {
+ counts, err := mgoutil.Aggregate[int64](ctx, c.coll, []bson.M{
+ {"$group": bson.M{"_id": "$conversation_id"}},
+ {"$project": bson.M{"_id": 0, "conversation_id": "$_id"}},
+ })
+ if err != nil {
+ return 0, err
+ }
+ if len(counts) == 0 {
+ return 0, nil
+ }
+ return counts[0], nil
+}
+
+func (c *ConversationMgo) PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error) {
+ return mgoutil.FindPageOnly[string](ctx, c.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"conversation_id": 1}))
+}
+
+func (c *ConversationMgo) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relation.ConversationModel, error) {
+ return mgoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"conversation_id": bson.M{"$in": conversationIDs}})
+}
+
+func (c *ConversationMgo) GetConversationIDsNeedDestruct(ctx context.Context) ([]*relation.ConversationModel, error) {
+ //"is_msg_destruct = 1 && msg_destruct_time != 0 && (UNIX_TIMESTAMP(NOW()) > (msg_destruct_time + UNIX_TIMESTAMP(latest_msg_destruct_time)) || latest_msg_destruct_time is NULL)"
+ return mgoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{
+ "is_msg_destruct": 1,
+ "msg_destruct_time": bson.M{"$ne": 0},
+ "$or": []bson.M{
+ {
+ "$expr": bson.M{
+ "$gt": []any{
+ time.Now(),
+ bson.M{"$add": []any{"$msg_destruct_time", "$latest_msg_destruct_time"}},
+ },
+ },
+ },
+ {
+ "latest_msg_destruct_time": nil,
+ },
+ },
+ })
+}
+
+func (c *ConversationMgo) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) {
+ return mgoutil.Find[string](
+ ctx,
+ c.coll,
+ bson.M{"conversation_id": conversationID, "recv_msg_opt": bson.M{"$ne": constant.ReceiveMessage}},
+ options.Find().SetProjection(bson.M{"_id": 0, "owner_user_id": 1}),
+ )
+}
diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go
new file mode 100644
index 000000000..aa9cb0301
--- /dev/null
+++ b/pkg/common/db/mgo/friend.go
@@ -0,0 +1,131 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+// FriendMgo implements FriendModelInterface using MongoDB as the storage backend.
+type FriendMgo struct {
+ coll *mongo.Collection
+}
+
+// NewFriendMongo creates a new instance of FriendMgo with the provided MongoDB database.
+func NewFriendMongo(db *mongo.Database) (relation.FriendModelInterface, error) {
+ coll := db.Collection("friend")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "owner_user_id", Value: 1},
+ {Key: "friend_user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &FriendMgo{coll: coll}, nil
+}
+
+// Create inserts multiple friend records.
+func (f *FriendMgo) Create(ctx context.Context, friends []*relation.FriendModel) error {
+ return mgoutil.InsertMany(ctx, f.coll, friends)
+}
+
+// Delete removes specified friends of the owner user.
+func (f *FriendMgo) Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) error {
+ filter := bson.M{
+ "owner_user_id": ownerUserID,
+ "friend_user_id": bson.M{"$in": friendUserIDs},
+ }
+ return mgoutil.DeleteOne(ctx, f.coll, filter)
+}
+
+// UpdateByMap updates specific fields of a friend document using a map.
+func (f *FriendMgo) UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) error {
+ if len(args) == 0 {
+ return nil
+ }
+ filter := bson.M{
+ "owner_user_id": ownerUserID,
+ "friend_user_id": friendUserID,
+ }
+ return mgoutil.UpdateOne(ctx, f.coll, filter, bson.M{"$set": args}, true)
+}
+
+// Update modifies multiple friend documents.
+// func (f *FriendMgo) Update(ctx context.Context, friends []*relation.FriendModel) error {
+// filter := bson.M{
+// "owner_user_id": ownerUserID,
+// "friend_user_id": friendUserID,
+// }
+// return mgotool.UpdateMany(ctx, f.coll, filter, friends)
+// }
+
+// UpdateRemark updates the remark for a specific friend.
+func (f *FriendMgo) UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) error {
+ return f.UpdateByMap(ctx, ownerUserID, friendUserID, map[string]any{"remark": remark})
+}
+
+// Take retrieves a single friend document. Returns an error if not found.
+func (f *FriendMgo) Take(ctx context.Context, ownerUserID, friendUserID string) (*relation.FriendModel, error) {
+ filter := bson.M{
+ "owner_user_id": ownerUserID,
+ "friend_user_id": friendUserID,
+ }
+ return mgoutil.FindOne[*relation.FriendModel](ctx, f.coll, filter)
+}
+
+// FindUserState finds the friendship status between two users.
+func (f *FriendMgo) FindUserState(ctx context.Context, userID1, userID2 string) ([]*relation.FriendModel, error) {
+ filter := bson.M{
+ "$or": []bson.M{
+ {"owner_user_id": userID1, "friend_user_id": userID2},
+ {"owner_user_id": userID2, "friend_user_id": userID1},
+ },
+ }
+ return mgoutil.Find[*relation.FriendModel](ctx, f.coll, filter)
+}
+
+// FindFriends retrieves a list of friends for a given owner. Missing friends do not cause an error.
+func (f *FriendMgo) FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) ([]*relation.FriendModel, error) {
+ filter := bson.M{
+ "owner_user_id": ownerUserID,
+ "friend_user_id": bson.M{"$in": friendUserIDs},
+ }
+ return mgoutil.Find[*relation.FriendModel](ctx, f.coll, filter)
+}
+
+// FindReversalFriends finds users who have added the specified user as a friend.
+func (f *FriendMgo) FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) ([]*relation.FriendModel, error) {
+ filter := bson.M{
+ "owner_user_id": bson.M{"$in": ownerUserIDs},
+ "friend_user_id": friendUserID,
+ }
+ return mgoutil.Find[*relation.FriendModel](ctx, f.coll, filter)
+}
+
+// FindOwnerFriends retrieves a paginated list of friends for a given owner.
+func (f *FriendMgo) FindOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (int64, []*relation.FriendModel, error) {
+ filter := bson.M{"owner_user_id": ownerUserID}
+ return mgoutil.FindPage[*relation.FriendModel](ctx, f.coll, filter, pagination)
+}
+
+// FindInWhoseFriends finds users who have added the specified user as a friend, with pagination.
+func (f *FriendMgo) FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (int64, []*relation.FriendModel, error) {
+ filter := bson.M{"friend_user_id": friendUserID}
+ return mgoutil.FindPage[*relation.FriendModel](ctx, f.coll, filter, pagination)
+}
+
+// FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
+func (f *FriendMgo) FindFriendUserIDs(ctx context.Context, ownerUserID string) ([]string, error) {
+ filter := bson.M{"owner_user_id": ownerUserID}
+ return mgoutil.Find[string](ctx, f.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "friend_user_id": 1}))
+}
diff --git a/pkg/common/db/mgo/friend_request.go b/pkg/common/db/mgo/friend_request.go
new file mode 100644
index 000000000..c1be87ca2
--- /dev/null
+++ b/pkg/common/db/mgo/friend_request.go
@@ -0,0 +1,99 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewFriendRequestMongo(db *mongo.Database) (relation.FriendRequestModelInterface, error) {
+ coll := db.Collection("friend_request")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "from_user_id", Value: 1},
+ {Key: "to_user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &FriendRequestMgo{coll: coll}, nil
+}
+
+type FriendRequestMgo struct {
+ coll *mongo.Collection
+}
+
+func (f *FriendRequestMgo) FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*relation.FriendRequestModel, err error) {
+ return mgoutil.FindPage[*relation.FriendRequestModel](ctx, f.coll, bson.M{"to_user_id": toUserID}, pagination)
+}
+
+func (f *FriendRequestMgo) FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*relation.FriendRequestModel, err error) {
+ return mgoutil.FindPage[*relation.FriendRequestModel](ctx, f.coll, bson.M{"from_user_id": fromUserID}, pagination)
+}
+
+func (f *FriendRequestMgo) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
+ filter := bson.M{"$or": []bson.M{
+ {"from_user_id": fromUserID, "to_user_id": toUserID},
+ {"from_user_id": toUserID, "to_user_id": fromUserID},
+ }}
+ return mgoutil.Find[*relation.FriendRequestModel](ctx, f.coll, filter)
+}
+
+func (f *FriendRequestMgo) Create(ctx context.Context, friendRequests []*relation.FriendRequestModel) error {
+ return mgoutil.InsertMany(ctx, f.coll, friendRequests)
+}
+
+func (f *FriendRequestMgo) Delete(ctx context.Context, fromUserID, toUserID string) (err error) {
+ return mgoutil.DeleteOne(ctx, f.coll, bson.M{"from_user_id": fromUserID, "to_user_id": toUserID})
+}
+
+func (f *FriendRequestMgo) UpdateByMap(ctx context.Context, formUserID, toUserID string, args map[string]any) (err error) {
+ if len(args) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, f.coll, bson.M{"from_user_id": formUserID, "to_user_id": toUserID}, bson.M{"$set": args}, true)
+}
+
+func (f *FriendRequestMgo) Update(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
+ updater := bson.M{}
+ if friendRequest.HandleResult != 0 {
+ updater["handle_result"] = friendRequest.HandleResult
+ }
+ if friendRequest.ReqMsg != "" {
+ updater["req_msg"] = friendRequest.ReqMsg
+ }
+ if friendRequest.HandlerUserID != "" {
+ updater["handler_user_id"] = friendRequest.HandlerUserID
+ }
+ if friendRequest.HandleMsg != "" {
+ updater["handle_msg"] = friendRequest.HandleMsg
+ }
+ if !friendRequest.HandleTime.IsZero() {
+ updater["handle_time"] = friendRequest.HandleTime
+ }
+ if friendRequest.Ex != "" {
+ updater["ex"] = friendRequest.Ex
+ }
+ if len(updater) == 0 {
+ return nil
+ }
+ filter := bson.M{"from_user_id": friendRequest.FromUserID, "to_user_id": friendRequest.ToUserID}
+ return mgoutil.UpdateOne(ctx, f.coll, filter, bson.M{"$set": updater}, true)
+}
+
+func (f *FriendRequestMgo) Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *relation.FriendRequestModel, err error) {
+ return mgoutil.FindOne[*relation.FriendRequestModel](ctx, f.coll, bson.M{"from_user_id": fromUserID, "to_user_id": toUserID})
+}
+
+func (f *FriendRequestMgo) Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *relation.FriendRequestModel, err error) {
+ return f.Find(ctx, fromUserID, toUserID)
+}
diff --git a/pkg/common/db/mgo/group.go b/pkg/common/db/mgo/group.go
new file mode 100644
index 000000000..3553b6b56
--- /dev/null
+++ b/pkg/common/db/mgo/group.go
@@ -0,0 +1,105 @@
+package mgo
+
+import (
+ "context"
+ "time"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewGroupMongo(db *mongo.Database) (relation.GroupModelInterface, error) {
+ coll := db.Collection("group")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "group_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &GroupMgo{coll: coll}, nil
+}
+
+type GroupMgo struct {
+ coll *mongo.Collection
+}
+
+func (g *GroupMgo) Create(ctx context.Context, groups []*relation.GroupModel) (err error) {
+ return mgoutil.InsertMany(ctx, g.coll, groups)
+}
+
+func (g *GroupMgo) UpdateState(ctx context.Context, groupID string, state int32) (err error) {
+ return g.UpdateMap(ctx, groupID, map[string]any{"state": state})
+}
+
+func (g *GroupMgo) UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error) {
+ if len(args) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID}, bson.M{"$set": args}, true)
+}
+
+func (g *GroupMgo) Find(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
+ return mgoutil.Find[*relation.GroupModel](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}})
+}
+
+func (g *GroupMgo) Take(ctx context.Context, groupID string) (group *relation.GroupModel, err error) {
+ return mgoutil.FindOne[*relation.GroupModel](ctx, g.coll, bson.M{"group_id": groupID})
+}
+
+func (g *GroupMgo) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*relation.GroupModel, err error) {
+ return mgoutil.FindPage[*relation.GroupModel](ctx, g.coll, bson.M{"group_name": bson.M{"$regex": keyword}}, pagination)
+}
+
+func (g *GroupMgo) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
+ if before == nil {
+ return mgoutil.Count(ctx, g.coll, bson.M{})
+ }
+ return mgoutil.Count(ctx, g.coll, bson.M{"create_time": bson.M{"$lt": before}})
+}
+
+func (g *GroupMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
+ pipeline := bson.A{
+ bson.M{
+ "$match": bson.M{
+ "create_time": bson.M{
+ "$gte": start,
+ "$lt": end,
+ },
+ },
+ },
+ bson.M{
+ "$group": bson.M{
+ "_id": bson.M{
+ "$dateToString": bson.M{
+ "format": "%Y-%m-%d",
+ "date": "$create_time",
+ },
+ },
+ "count": bson.M{
+ "$sum": 1,
+ },
+ },
+ },
+ }
+ type Item struct {
+ Date string `bson:"_id"`
+ Count int64 `bson:"count"`
+ }
+ items, err := mgoutil.Aggregate[Item](ctx, g.coll, pipeline)
+ if err != nil {
+ return nil, err
+ }
+ res := make(map[string]int64, len(items))
+ for _, item := range items {
+ res[item.Date] = item.Count
+ }
+ return res, nil
+}
diff --git a/pkg/common/db/mgo/group_member.go b/pkg/common/db/mgo/group_member.go
new file mode 100644
index 000000000..ed09a028b
--- /dev/null
+++ b/pkg/common/db/mgo/group_member.go
@@ -0,0 +1,101 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/protocol/constant"
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewGroupMember(db *mongo.Database) (relation.GroupMemberModelInterface, error) {
+ coll := db.Collection("group_member")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "group_id", Value: 1},
+ {Key: "user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &GroupMemberMgo{coll: coll}, nil
+}
+
+type GroupMemberMgo struct {
+ coll *mongo.Collection
+}
+
+func (g *GroupMemberMgo) Create(ctx context.Context, groupMembers []*relation.GroupMemberModel) (err error) {
+ return mgoutil.InsertMany(ctx, g.coll, groupMembers)
+}
+
+func (g *GroupMemberMgo) Delete(ctx context.Context, groupID string, userIDs []string) (err error) {
+ return mgoutil.DeleteMany(ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
+}
+
+func (g *GroupMemberMgo) UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error {
+ return g.Update(ctx, groupID, userID, bson.M{"role_level": roleLevel})
+}
+
+func (g *GroupMemberMgo) Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error) {
+ return mgoutil.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID}, bson.M{"$set": data}, true)
+}
+
+func (g *GroupMemberMgo) Find(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) (groupMembers []*relation.GroupMemberModel, err error) {
+ //TODO implement me
+ panic("implement me")
+}
+
+func (g *GroupMemberMgo) FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error) {
+ return mgoutil.Find[string](ctx, g.coll, bson.M{"group_id": groupID}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
+}
+
+func (g *GroupMemberMgo) Take(ctx context.Context, groupID string, userID string) (groupMember *relation.GroupMemberModel, err error) {
+ return mgoutil.FindOne[*relation.GroupMemberModel](ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID})
+}
+
+func (g *GroupMemberMgo) TakeOwner(ctx context.Context, groupID string) (groupMember *relation.GroupMemberModel, err error) {
+ return mgoutil.FindOne[*relation.GroupMemberModel](ctx, g.coll, bson.M{"group_id": groupID, "role_level": constant.GroupOwner})
+}
+
+func (g *GroupMemberMgo) FindRoleLevelUserIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) {
+ return mgoutil.Find[string](ctx, g.coll, bson.M{"group_id": groupID, "role_level": roleLevel}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
+}
+
+func (g *GroupMemberMgo) SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*relation.GroupMemberModel, err error) {
+ //TODO implement me
+ panic("implement me")
+}
+
+func (g *GroupMemberMgo) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
+ return mgoutil.Find[string](ctx, g.coll, bson.M{"user_id": userID}, options.Find().SetProjection(bson.M{"_id": 0, "group_id": 1}))
+}
+
+func (g *GroupMemberMgo) TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error) {
+ return mgoutil.Count(ctx, g.coll, bson.M{"group_id": groupID})
+}
+
+func (g *GroupMemberMgo) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
+ filter := bson.M{
+ "user_id": userID,
+ "role_level": bson.M{
+ "$in": []int{constant.GroupOwner, constant.GroupAdmin},
+ },
+ }
+ return mgoutil.Find[string](ctx, g.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "group_id": 1}))
+}
+
+func (g *GroupMemberMgo) IsUpdateRoleLevel(data map[string]any) bool {
+ if len(data) == 0 {
+ return false
+ }
+ _, ok := data["role_level"]
+ return ok
+}
diff --git a/pkg/common/db/mgo/group_request.go b/pkg/common/db/mgo/group_request.go
new file mode 100644
index 000000000..e88a39bf5
--- /dev/null
+++ b/pkg/common/db/mgo/group_request.go
@@ -0,0 +1,60 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewGroupRequestMgo(db *mongo.Database) (relation.GroupRequestModelInterface, error) {
+ coll := db.Collection("group_request")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "group_id", Value: 1},
+ {Key: "user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &GroupRequestMgo{coll: coll}, nil
+}
+
+type GroupRequestMgo struct {
+ coll *mongo.Collection
+}
+
+func (g *GroupRequestMgo) Create(ctx context.Context, groupRequests []*relation.GroupRequestModel) (err error) {
+ return mgoutil.InsertMany(ctx, g.coll, groupRequests)
+}
+
+func (g *GroupRequestMgo) Delete(ctx context.Context, groupID string, userID string) (err error) {
+ return mgoutil.DeleteOne(ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID})
+}
+
+func (g *GroupRequestMgo) UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error) {
+ return mgoutil.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID}, bson.M{"$set": bson.M{"handle_msg": handledMsg, "handle_result": handleResult}}, true)
+}
+
+func (g *GroupRequestMgo) Take(ctx context.Context, groupID string, userID string) (groupRequest *relation.GroupRequestModel, err error) {
+ return mgoutil.FindOne[*relation.GroupRequestModel](ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID})
+}
+
+func (g *GroupRequestMgo) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relation.GroupRequestModel, error) {
+ return mgoutil.Find[*relation.GroupRequestModel](ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
+}
+
+func (g *GroupRequestMgo) Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*relation.GroupRequestModel, err error) {
+ return mgoutil.FindPage[*relation.GroupRequestModel](ctx, g.coll, bson.M{"user_id": userID}, pagination)
+}
+
+func (g *GroupRequestMgo) PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*relation.GroupRequestModel, err error) {
+ return mgoutil.FindPage[*relation.GroupRequestModel](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}}, pagination)
+}
diff --git a/pkg/common/db/mgo/log.go b/pkg/common/db/mgo/log.go
new file mode 100644
index 000000000..aa280fcf2
--- /dev/null
+++ b/pkg/common/db/mgo/log.go
@@ -0,0 +1,70 @@
+package mgo
+
+import (
+ "context"
+ "time"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewLogMongo(db *mongo.Database) (relation.LogInterface, error) {
+ coll := db.Collection("log")
+ _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
+ {
+ Keys: bson.D{
+ {Key: "log_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ },
+ {
+ Keys: bson.D{
+ {Key: "user_id", Value: 1},
+ },
+ },
+ {
+ Keys: bson.D{
+ {Key: "create_time", Value: -1},
+ },
+ },
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &LogMgo{coll: coll}, nil
+}
+
+type LogMgo struct {
+ coll *mongo.Collection
+}
+
+func (l *LogMgo) Create(ctx context.Context, log []*relation.LogModel) error {
+ return mgoutil.InsertMany(ctx, l.coll, log)
+}
+
+func (l *LogMgo) Search(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error) {
+ filter := bson.M{"create_time": bson.M{"$gte": start, "$lte": end}}
+ if keyword != "" {
+ filter["user_id"] = bson.M{"$regex": keyword}
+ }
+ return mgoutil.FindPage[*relation.LogModel](ctx, l.coll, filter, pagination, options.Find().SetSort(bson.M{"create_time": -1}))
+}
+
+func (l *LogMgo) Delete(ctx context.Context, logID []string, userID string) error {
+ if userID == "" {
+ return mgoutil.DeleteMany(ctx, l.coll, bson.M{"log_id": bson.M{"$in": logID}})
+ }
+ return mgoutil.DeleteMany(ctx, l.coll, bson.M{"log_id": bson.M{"$in": logID}, "user_id": userID})
+}
+
+func (l *LogMgo) Get(ctx context.Context, logIDs []string, userID string) ([]*relation.LogModel, error) {
+ if userID == "" {
+ return mgoutil.Find[*relation.LogModel](ctx, l.coll, bson.M{"log_id": bson.M{"$in": logIDs}})
+ }
+ return mgoutil.Find[*relation.LogModel](ctx, l.coll, bson.M{"log_id": bson.M{"$in": logIDs}, "user_id": userID})
+}
diff --git a/pkg/common/db/mgo/object.go b/pkg/common/db/mgo/object.go
new file mode 100644
index 000000000..5976b2d28
--- /dev/null
+++ b/pkg/common/db/mgo/object.go
@@ -0,0 +1,55 @@
+package mgo
+
+import (
+ "context"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewS3Mongo(db *mongo.Database) (relation.ObjectInfoModelInterface, error) {
+ coll := db.Collection("s3")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "name", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &S3Mongo{coll: coll}, nil
+}
+
+type S3Mongo struct {
+ coll *mongo.Collection
+}
+
+func (o *S3Mongo) SetObject(ctx context.Context, obj *relation.ObjectModel) error {
+ filter := bson.M{"name": obj.Name, "engine": obj.Engine}
+ update := bson.M{
+ "name": obj.Name,
+ "engine": obj.Engine,
+ "key": obj.Key,
+ "size": obj.Size,
+ "content_type": obj.ContentType,
+ "group": obj.Group,
+ "create_time": obj.CreateTime,
+ }
+ return mgoutil.UpdateOne(ctx, o.coll, filter, bson.M{"$set": update}, false, options.Update().SetUpsert(true))
+}
+
+func (o *S3Mongo) Take(ctx context.Context, engine string, name string) (*relation.ObjectModel, error) {
+ if engine == "" {
+ return mgoutil.FindOne[*relation.ObjectModel](ctx, o.coll, bson.M{"name": name})
+ }
+ return mgoutil.FindOne[*relation.ObjectModel](ctx, o.coll, bson.M{"name": name, "engine": engine})
+}
+
+func (o *S3Mongo) Delete(ctx context.Context, engine string, name string) error {
+ return mgoutil.DeleteOne(ctx, o.coll, bson.M{"name": name, "engine": engine})
+}
diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go
new file mode 100644
index 000000000..4a53cb3c4
--- /dev/null
+++ b/pkg/common/db/mgo/user.go
@@ -0,0 +1,113 @@
+package mgo
+
+import (
+ "context"
+ "time"
+
+ "github.com/OpenIMSDK/tools/mgoutil"
+ "github.com/OpenIMSDK/tools/pagination"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+)
+
+func NewUserMongo(db *mongo.Database) (relation.UserModelInterface, error) {
+ coll := db.Collection("user")
+ _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
+ Keys: bson.D{
+ {Key: "user_id", Value: 1},
+ },
+ Options: options.Index().SetUnique(true),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return &UserMgo{coll: coll}, nil
+}
+
+type UserMgo struct {
+ coll *mongo.Collection
+}
+
+func (u *UserMgo) Create(ctx context.Context, users []*relation.UserModel) error {
+ return mgoutil.InsertMany(ctx, u.coll, users)
+}
+
+func (u *UserMgo) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error) {
+ if len(args) == 0 {
+ return nil
+ }
+ return mgoutil.UpdateOne(ctx, u.coll, bson.M{"user_id": userID}, bson.M{"$set": args}, true)
+}
+
+func (u *UserMgo) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
+ return mgoutil.Find[*relation.UserModel](ctx, u.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
+}
+
+func (u *UserMgo) Take(ctx context.Context, userID string) (user *relation.UserModel, err error) {
+ return mgoutil.FindOne[*relation.UserModel](ctx, u.coll, bson.M{"user_id": userID})
+}
+
+func (u *UserMgo) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
+ return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, bson.M{}, pagination)
+}
+
+func (u *UserMgo) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error) {
+ return mgoutil.FindPage[string](ctx, u.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"user_id": 1}))
+}
+
+func (u *UserMgo) Exist(ctx context.Context, userID string) (exist bool, err error) {
+ return mgoutil.Exist(ctx, u.coll, bson.M{"user_id": userID})
+}
+
+func (u *UserMgo) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) {
+ return mgoutil.FindOne[int](ctx, u.coll, bson.M{"user_id": userID}, options.FindOne().SetProjection(bson.M{"global_recv_msg_opt": 1}))
+}
+
+func (u *UserMgo) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
+ if before == nil {
+ return mgoutil.Count(ctx, u.coll, bson.M{})
+ }
+ return mgoutil.Count(ctx, u.coll, bson.M{"create_time": bson.M{"$lt": before}})
+}
+
+func (u *UserMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
+ pipeline := bson.A{
+ bson.M{
+ "$match": bson.M{
+ "create_time": bson.M{
+ "$gte": start,
+ "$lt": end,
+ },
+ },
+ },
+ bson.M{
+ "$group": bson.M{
+ "_id": bson.M{
+ "$dateToString": bson.M{
+ "format": "%Y-%m-%d",
+ "date": "$create_time",
+ },
+ },
+ "count": bson.M{
+ "$sum": 1,
+ },
+ },
+ },
+ }
+ type Item struct {
+ Date string `bson:"_id"`
+ Count int64 `bson:"count"`
+ }
+ items, err := mgoutil.Aggregate[Item](ctx, u.coll, pipeline)
+ if err != nil {
+ return nil, err
+ }
+ res := make(map[string]int64, len(items))
+ for _, item := range items {
+ res[item.Date] = item.Count
+ }
+ return res, nil
+}
diff --git a/pkg/common/db/relation/black_model.go b/pkg/common/db/relation/black_model.go
deleted file mode 100644
index 34123c7a3..000000000
--- a/pkg/common/db/relation/black_model.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "context"
-
- "github.com/OpenIMSDK/tools/errs"
-
- "github.com/OpenIMSDK/tools/ormutil"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type BlackGorm struct {
- *MetaDB
-}
-
-func NewBlackGorm(db *gorm.DB) relation.BlackModelInterface {
- return &BlackGorm{NewMetaDB(db, &relation.BlackModel{})}
-}
-
-func (b *BlackGorm) Create(ctx context.Context, blacks []*relation.BlackModel) (err error) {
- return utils.Wrap(b.db(ctx).Create(&blacks).Error, "")
-}
-
-func (b *BlackGorm) Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) {
- return utils.Wrap(b.db(ctx).Delete(blacks).Error, "")
-}
-
-func (b *BlackGorm) UpdateByMap(
- ctx context.Context,
- ownerUserID, blockUserID string,
- args map[string]interface{},
-) (err error) {
- return utils.Wrap(
- b.db(ctx).Where("block_user_id = ? and block_user_id = ?", ownerUserID, blockUserID).Updates(args).Error,
- "",
- )
-}
-
-func (b *BlackGorm) Update(ctx context.Context, blacks []*relation.BlackModel) (err error) {
- return utils.Wrap(b.db(ctx).Updates(&blacks).Error, "")
-}
-
-func (b *BlackGorm) Find(
- ctx context.Context,
- blacks []*relation.BlackModel,
-) (blackList []*relation.BlackModel, err error) {
- var where [][]interface{}
- for _, black := range blacks {
- where = append(where, []interface{}{black.OwnerUserID, black.BlockUserID})
- }
- return blackList, utils.Wrap(
- b.db(ctx).Where("(owner_user_id, block_user_id) in ?", where).Find(&blackList).Error,
- "",
- )
-}
-
-func (b *BlackGorm) Take(ctx context.Context, ownerUserID, blockUserID string) (black *relation.BlackModel, err error) {
- black = &relation.BlackModel{}
- return black, utils.Wrap(
- b.db(ctx).Where("owner_user_id = ? and block_user_id = ?", ownerUserID, blockUserID).Take(black).Error,
- "",
- )
-}
-
-func (b *BlackGorm) FindOwnerBlacks(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
-) (blacks []*relation.BlackModel, total int64, err error) {
- err = b.db(ctx).Count(&total).Error
- if err != nil {
- return nil, 0, utils.Wrap(err, "")
- }
- totalUint32, blacks, err := ormutil.GormPage[relation.BlackModel](
- b.db(ctx).Where("owner_user_id = ?", ownerUserID),
- pageNumber,
- showNumber,
- )
- total = int64(totalUint32)
- return
-}
-
-func (b *BlackGorm) FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error) {
- return blackUserIDs, utils.Wrap(
- b.db(ctx).Where("owner_user_id = ?", ownerUserID).Pluck("block_user_id", &blackUserIDs).Error,
- "",
- )
-}
-
-func (b *BlackGorm) FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) {
- return blacks, errs.Wrap(b.db(ctx).Where("owner_user_id = ? and block_user_id in ?", ownerUserID, userIDs).Find(&blacks).Error)
-}
diff --git a/pkg/common/db/relation/chat_log_model.go b/pkg/common/db/relation/chat_log_model.go
deleted file mode 100644
index f183a543f..000000000
--- a/pkg/common/db/relation/chat_log_model.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "github.com/golang/protobuf/jsonpb"
- "github.com/jinzhu/copier"
- "google.golang.org/protobuf/proto"
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/protocol/constant"
- pbmsg "github.com/OpenIMSDK/protocol/msg"
- sdkws "github.com/OpenIMSDK/protocol/sdkws"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type ChatLogGorm struct {
- *MetaDB
-}
-
-func NewChatLogGorm(db *gorm.DB) relation.ChatLogModelInterface {
- return &ChatLogGorm{NewMetaDB(db, &relation.ChatLogModel{})}
-}
-
-func (c *ChatLogGorm) Create(msg *pbmsg.MsgDataToMQ) error {
- chatLog := new(relation.ChatLogModel)
- copier.Copy(chatLog, msg.MsgData)
- switch msg.MsgData.SessionType {
- case constant.GroupChatType, constant.SuperGroupChatType:
- chatLog.RecvID = msg.MsgData.GroupID
- case constant.SingleChatType:
- chatLog.RecvID = msg.MsgData.RecvID
- }
- if msg.MsgData.ContentType >= constant.NotificationBegin && msg.MsgData.ContentType <= constant.NotificationEnd {
- var tips sdkws.TipsComm
- _ = proto.Unmarshal(msg.MsgData.Content, &tips)
- marshaler := jsonpb.Marshaler{
- OrigName: true,
- EnumsAsInts: false,
- EmitDefaults: false,
- }
- chatLog.Content, _ = marshaler.MarshalToString(&tips)
- } else {
- chatLog.Content = string(msg.MsgData.Content)
- }
- chatLog.CreateTime = utils.UnixMillSecondToTime(msg.MsgData.CreateTime)
- chatLog.SendTime = utils.UnixMillSecondToTime(msg.MsgData.SendTime)
- return c.DB.Create(chatLog).Error
-}
diff --git a/pkg/common/db/relation/conversation_model.go b/pkg/common/db/relation/conversation_model.go
deleted file mode 100644
index f39047bf6..000000000
--- a/pkg/common/db/relation/conversation_model.go
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "context"
-
- "github.com/OpenIMSDK/tools/errs"
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/protocol/constant"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type ConversationGorm struct {
- *MetaDB
-}
-
-func NewConversationGorm(db *gorm.DB) relation.ConversationModelInterface {
- return &ConversationGorm{NewMetaDB(db, &relation.ConversationModel{})}
-}
-
-func (c *ConversationGorm) NewTx(tx any) relation.ConversationModelInterface {
- return &ConversationGorm{NewMetaDB(tx.(*gorm.DB), &relation.ConversationModel{})}
-}
-
-func (c *ConversationGorm) Create(ctx context.Context, conversations []*relation.ConversationModel) (err error) {
- return utils.Wrap(c.db(ctx).Create(&conversations).Error, "")
-}
-
-func (c *ConversationGorm) Delete(ctx context.Context, groupIDs []string) (err error) {
- return utils.Wrap(c.db(ctx).Where("group_id in (?)", groupIDs).Delete(&relation.ConversationModel{}).Error, "")
-}
-
-func (c *ConversationGorm) UpdateByMap(
- ctx context.Context,
- userIDList []string,
- conversationID string,
- args map[string]interface{},
-) (rows int64, err error) {
- result := c.db(ctx).Where("owner_user_id IN (?) and conversation_id=?", userIDList, conversationID).Updates(args)
- return result.RowsAffected, utils.Wrap(result.Error, "")
-}
-
-func (c *ConversationGorm) Update(ctx context.Context, conversation *relation.ConversationModel) (err error) {
- return utils.Wrap(
- c.db(ctx).
- Where("owner_user_id = ? and conversation_id = ?", conversation.OwnerUserID, conversation.ConversationID).
- Updates(conversation).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) Find(
- ctx context.Context,
- ownerUserID string,
- conversationIDs []string,
-) (conversations []*relation.ConversationModel, err error) {
- err = utils.Wrap(
- c.db(ctx).
- Where("owner_user_id=? and conversation_id IN (?)", ownerUserID, conversationIDs).
- Find(&conversations).
- Error,
- "",
- )
- return conversations, err
-}
-
-func (c *ConversationGorm) Take(
- ctx context.Context,
- userID, conversationID string,
-) (conversation *relation.ConversationModel, err error) {
- cc := &relation.ConversationModel{}
- return cc, utils.Wrap(
- c.db(ctx).Where("conversation_id = ? And owner_user_id = ?", conversationID, userID).Take(cc).Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindUserID(
- ctx context.Context,
- userIDs []string,
- conversationIDs []string,
-) (existUserID []string, err error) {
- return existUserID, utils.Wrap(
- c.db(ctx).
- Where(" owner_user_id IN (?) and conversation_id in (?)", userIDs, conversationIDs).
- Pluck("owner_user_id", &existUserID).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindConversationID(
- ctx context.Context,
- userID string,
- conversationIDList []string,
-) (existConversationID []string, err error) {
- return existConversationID, utils.Wrap(
- c.db(ctx).
- Where(" conversation_id IN (?) and owner_user_id=?", conversationIDList, userID).
- Pluck("conversation_id", &existConversationID).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindUserIDAllConversationID(
- ctx context.Context,
- userID string,
-) (conversationIDList []string, err error) {
- return conversationIDList, utils.Wrap(
- c.db(ctx).Where("owner_user_id=?", userID).Pluck("conversation_id", &conversationIDList).Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindUserIDAllConversations(
- ctx context.Context,
- userID string,
-) (conversations []*relation.ConversationModel, err error) {
- return conversations, utils.Wrap(c.db(ctx).Where("owner_user_id=?", userID).Find(&conversations).Error, "")
-}
-
-func (c *ConversationGorm) FindRecvMsgNotNotifyUserIDs(
- ctx context.Context,
- groupID string,
-) (userIDs []string, err error) {
- return userIDs, utils.Wrap(
- c.db(ctx).
- Where("group_id = ? and recv_msg_opt = ?", groupID, constant.ReceiveNotNotifyMessage).
- Pluck("owner_user_id", &userIDs).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) FindSuperGroupRecvMsgNotNotifyUserIDs(
- ctx context.Context,
- groupID string,
-) (userIDs []string, err error) {
- return userIDs, utils.Wrap(
- c.db(ctx).
- Where("group_id = ? and recv_msg_opt = ? and conversation_type = ?", groupID, constant.ReceiveNotNotifyMessage, constant.SuperGroupChatType).
- Pluck("owner_user_id", &userIDs).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetUserRecvMsgOpt(
- ctx context.Context,
- ownerUserID, conversationID string,
-) (opt int, err error) {
- var conversation relation.ConversationModel
- return int(
- conversation.RecvMsgOpt,
- ), utils.Wrap(
- c.db(ctx).
- Where("conversation_id = ? And owner_user_id = ?", conversationID, ownerUserID).
- Select("recv_msg_opt").
- Find(&conversation).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetAllConversationIDs(ctx context.Context) (conversationIDs []string, err error) {
- return conversationIDs, utils.Wrap(
- c.db(ctx).Distinct("conversation_id").Pluck("conversation_id", &conversationIDs).Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetAllConversationIDsNumber(ctx context.Context) (int64, error) {
- var num int64
- err := c.db(ctx).Select("COUNT(DISTINCT conversation_id)").Model(&relation.ConversationModel{}).Count(&num).Error
- return num, errs.Wrap(err)
-}
-
-func (c *ConversationGorm) PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error) {
- err = c.db(ctx).Distinct("conversation_id").Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("conversation_id", &conversationIDs).Error
- err = errs.Wrap(err)
- return
-}
-
-func (c *ConversationGorm) GetUserAllHasReadSeqs(
- ctx context.Context,
- ownerUserID string,
-) (hasReadSeqs map[string]int64, err error) {
- return nil, nil
-}
-
-func (c *ConversationGorm) GetConversationsByConversationID(
- ctx context.Context,
- conversationIDs []string,
-) (conversations []*relation.ConversationModel, err error) {
- return conversations, utils.Wrap(
- c.db(ctx).Where("conversation_id IN (?)", conversationIDs).Find(&conversations).Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetConversationIDsNeedDestruct(
- ctx context.Context,
-) (conversations []*relation.ConversationModel, err error) {
- return conversations, utils.Wrap(
- c.db(ctx).
- Where("is_msg_destruct = 1 && msg_destruct_time != 0 && (UNIX_TIMESTAMP(NOW()) > (msg_destruct_time + UNIX_TIMESTAMP(latest_msg_destruct_time)) || latest_msg_destruct_time is NULL)").
- Find(&conversations).
- Error,
- "",
- )
-}
-
-func (c *ConversationGorm) GetConversationRecvMsgOpt(ctx context.Context, userID string, conversationID string) (int32, error) {
- var recvMsgOpt int32
- return recvMsgOpt, errs.Wrap(
- c.db(ctx).
- Model(&relation.ConversationModel{}).
- Where("conversation_id = ? and owner_user_id in ?", conversationID, userID).
- Pluck("recv_msg_opt", &recvMsgOpt).
- Error,
- )
-}
-
-func (c *ConversationGorm) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) {
- var userIDs []string
- return userIDs, errs.Wrap(
- c.db(ctx).
- Model(&relation.ConversationModel{}).
- Where("conversation_id = ? and recv_msg_opt <> ?", conversationID, constant.ReceiveMessage).
- Pluck("owner_user_id", &userIDs).Error,
- )
-}
diff --git a/pkg/common/db/relation/doc.go b/pkg/common/db/relation/doc.go
deleted file mode 100644
index 41135ac97..000000000
--- a/pkg/common/db/relation/doc.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation // import "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
diff --git a/pkg/common/db/relation/friend_request_model.go b/pkg/common/db/relation/friend_request_model.go
deleted file mode 100644
index 5678f7b7b..000000000
--- a/pkg/common/db/relation/friend_request_model.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "context"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type FriendRequestGorm struct {
- *MetaDB
-}
-
-func NewFriendRequestGorm(db *gorm.DB) relation.FriendRequestModelInterface {
- return &FriendRequestGorm{NewMetaDB(db, &relation.FriendRequestModel{})}
-}
-
-func (f *FriendRequestGorm) NewTx(tx any) relation.FriendRequestModelInterface {
- return &FriendRequestGorm{NewMetaDB(tx.(*gorm.DB), &relation.FriendRequestModel{})}
-}
-
-// 插入多条记录.
-func (f *FriendRequestGorm) Create(ctx context.Context, friendRequests []*relation.FriendRequestModel) (err error) {
- return utils.Wrap(f.db(ctx).Create(&friendRequests).Error, "")
-}
-
-// 删除记录.
-func (f *FriendRequestGorm) Delete(ctx context.Context, fromUserID, toUserID string) (err error) {
- return utils.Wrap(
- f.db(ctx).
- Where("from_user_id = ? AND to_user_id = ?", fromUserID, toUserID).
- Delete(&relation.FriendRequestModel{}).
- Error,
- "",
- )
-}
-
-// 更新零值.
-func (f *FriendRequestGorm) UpdateByMap(
- ctx context.Context,
- fromUserID string,
- toUserID string,
- args map[string]interface{},
-) (err error) {
- return utils.Wrap(
- f.db(ctx).
- Model(&relation.FriendRequestModel{}).
- Where("from_user_id = ? AND to_user_id =?", fromUserID, toUserID).
- Updates(args).
- Error,
- "",
- )
-}
-
-// 更新记录 (非零值).
-func (f *FriendRequestGorm) Update(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
- fr2 := *friendRequest
- fr2.FromUserID = ""
- fr2.ToUserID = ""
- return utils.Wrap(
- f.db(ctx).
- Where("from_user_id = ? AND to_user_id =?", friendRequest.FromUserID, friendRequest.ToUserID).
- Updates(fr2).
- Error,
- "",
- )
-}
-
-// 获取来指定用户的好友申请 未找到 不返回错误.
-func (f *FriendRequestGorm) Find(
- ctx context.Context,
- fromUserID, toUserID string,
-) (friendRequest *relation.FriendRequestModel, err error) {
- friendRequest = &relation.FriendRequestModel{}
- err = utils.Wrap(
- f.db(ctx).Where("from_user_id = ? and to_user_id = ?", fromUserID, toUserID).Find(friendRequest).Error,
- "",
- )
- return friendRequest, err
-}
-
-func (f *FriendRequestGorm) Take(
- ctx context.Context,
- fromUserID, toUserID string,
-) (friendRequest *relation.FriendRequestModel, err error) {
- friendRequest = &relation.FriendRequestModel{}
- err = utils.Wrap(
- f.db(ctx).Where("from_user_id = ? and to_user_id = ?", fromUserID, toUserID).Take(friendRequest).Error,
- "",
- )
- return friendRequest, err
-}
-
-// 获取toUserID收到的好友申请列表.
-func (f *FriendRequestGorm) FindToUserID(
- ctx context.Context,
- toUserID string,
- pageNumber, showNumber int32,
-) (friendRequests []*relation.FriendRequestModel, total int64, err error) {
- err = f.db(ctx).Model(&relation.FriendRequestModel{}).Where("to_user_id = ? ", toUserID).Count(&total).Error
- if err != nil {
- return nil, 0, utils.Wrap(err, "")
- }
- err = utils.Wrap(
- f.db(ctx).
- Where("to_user_id = ? ", toUserID).
- Limit(int(showNumber)).
- Offset(int(pageNumber-1)*int(showNumber)).
- Find(&friendRequests).
- Error,
- "",
- )
- return
-}
-
-// 获取fromUserID发出去的好友申请列表.
-func (f *FriendRequestGorm) FindFromUserID(
- ctx context.Context,
- fromUserID string,
- pageNumber, showNumber int32,
-) (friendRequests []*relation.FriendRequestModel, total int64, err error) {
- err = f.db(ctx).Model(&relation.FriendRequestModel{}).Where("from_user_id = ? ", fromUserID).Count(&total).Error
- if err != nil {
- return nil, 0, utils.Wrap(err, "")
- }
- err = utils.Wrap(
- f.db(ctx).
- Where("from_user_id = ? ", fromUserID).
- Limit(int(showNumber)).
- Offset(int(pageNumber-1)*int(showNumber)).
- Find(&friendRequests).
- Error,
- "",
- )
- return
-}
-
-func (f *FriendRequestGorm) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
- err = utils.Wrap(
- f.db(ctx).
- Where("(from_user_id = ? AND to_user_id = ?) OR (from_user_id = ? AND to_user_id = ?)", fromUserID, toUserID, toUserID, fromUserID).
- Find(&friends).
- Error,
- "",
- )
- return
-}
diff --git a/pkg/common/db/relation/group_member_model.go b/pkg/common/db/relation/group_member_model.go
deleted file mode 100644
index 312e32054..000000000
--- a/pkg/common/db/relation/group_member_model.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "context"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/protocol/constant"
- "github.com/OpenIMSDK/tools/ormutil"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-var _ relation.GroupMemberModelInterface = (*GroupMemberGorm)(nil)
-
-type GroupMemberGorm struct {
- *MetaDB
-}
-
-func NewGroupMemberDB(db *gorm.DB) relation.GroupMemberModelInterface {
- return &GroupMemberGorm{NewMetaDB(db, &relation.GroupMemberModel{})}
-}
-
-func (g *GroupMemberGorm) NewTx(tx any) relation.GroupMemberModelInterface {
- return &GroupMemberGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupMemberModel{})}
-}
-
-func (g *GroupMemberGorm) Create(ctx context.Context, groupMemberList []*relation.GroupMemberModel) (err error) {
- return utils.Wrap(g.db(ctx).Create(&groupMemberList).Error, "")
-}
-
-func (g *GroupMemberGorm) Delete(ctx context.Context, groupID string, userIDs []string) (err error) {
- return utils.Wrap(
- g.db(ctx).Where("group_id = ? and user_id in (?)", groupID, userIDs).Delete(&relation.GroupMemberModel{}).Error,
- "",
- )
-}
-
-func (g *GroupMemberGorm) DeleteGroup(ctx context.Context, groupIDs []string) (err error) {
- return utils.Wrap(g.db(ctx).Where("group_id in (?)", groupIDs).Delete(&relation.GroupMemberModel{}).Error, "")
-}
-
-func (g *GroupMemberGorm) Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error) {
- return utils.Wrap(g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Updates(data).Error, "")
-}
-
-func (g *GroupMemberGorm) UpdateRoleLevel(
- ctx context.Context,
- groupID string,
- userID string,
- roleLevel int32,
-) (rowsAffected int64, err error) {
- db := g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Updates(map[string]any{
- "role_level": roleLevel,
- })
- return db.RowsAffected, utils.Wrap(db.Error, "")
-}
-
-func (g *GroupMemberGorm) Find(
- ctx context.Context,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
-) (groupMembers []*relation.GroupMemberModel, err error) {
- db := g.db(ctx)
- if len(groupIDs) > 0 {
- db = db.Where("group_id in (?)", groupIDs)
- }
- if len(userIDs) > 0 {
- db = db.Where("user_id in (?)", userIDs)
- }
- if len(roleLevels) > 0 {
- db = db.Where("role_level in (?)", roleLevels)
- }
- return groupMembers, utils.Wrap(db.Find(&groupMembers).Error, "")
-}
-
-func (g *GroupMemberGorm) Take(
- ctx context.Context,
- groupID string,
- userID string,
-) (groupMember *relation.GroupMemberModel, err error) {
- groupMember = &relation.GroupMemberModel{}
- return groupMember, utils.Wrap(
- g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Take(groupMember).Error,
- "",
- )
-}
-
-func (g *GroupMemberGorm) TakeOwner(
- ctx context.Context,
- groupID string,
-) (groupMember *relation.GroupMemberModel, err error) {
- groupMember = &relation.GroupMemberModel{}
- return groupMember, utils.Wrap(
- g.db(ctx).Where("group_id = ? and role_level = ?", groupID, constant.GroupOwner).Take(groupMember).Error,
- "",
- )
-}
-
-func (g *GroupMemberGorm) SearchMember(
- ctx context.Context,
- keyword string,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
- pageNumber, showNumber int32,
-) (total uint32, groupList []*relation.GroupMemberModel, err error) {
- db := g.db(ctx)
- ormutil.GormIn(&db, "group_id", groupIDs)
- ormutil.GormIn(&db, "user_id", userIDs)
- ormutil.GormIn(&db, "role_level", roleLevels)
- return ormutil.GormSearch[relation.GroupMemberModel](db, []string{"nickname"}, keyword, pageNumber, showNumber)
-}
-
-func (g *GroupMemberGorm) MapGroupMemberNum(
- ctx context.Context,
- groupIDs []string,
-) (count map[string]uint32, err error) {
- return ormutil.MapCount(g.db(ctx).Where("group_id in (?)", groupIDs), "group_id")
-}
-
-func (g *GroupMemberGorm) FindJoinUserID(
- ctx context.Context,
- groupIDs []string,
-) (groupUsers map[string][]string, err error) {
- var groupMembers []*relation.GroupMemberModel
- if err := g.db(ctx).Select("group_id, user_id").Where("group_id in (?)", groupIDs).Find(&groupMembers).Error; err != nil {
- return nil, utils.Wrap(err, "")
- }
- groupUsers = make(map[string][]string)
- for _, item := range groupMembers {
- v, ok := groupUsers[item.GroupID]
- if !ok {
- groupUsers[item.GroupID] = []string{item.UserID}
- } else {
- groupUsers[item.GroupID] = append(v, item.UserID)
- }
- }
- return groupUsers, nil
-}
-
-func (g *GroupMemberGorm) FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error) {
- return userIDs, utils.Wrap(g.db(ctx).Where("group_id = ?", groupID).Pluck("user_id", &userIDs).Error, "")
-}
-
-func (g *GroupMemberGorm) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
- return groupIDs, utils.Wrap(g.db(ctx).Where("user_id = ?", userID).Pluck("group_id", &groupIDs).Error, "")
-}
-
-func (g *GroupMemberGorm) TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error) {
- return count, utils.Wrap(g.db(ctx).Where("group_id = ?", groupID).Count(&count).Error, "")
-}
-
-func (g *GroupMemberGorm) FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error) {
- var groupMembers []*relation.GroupMemberModel
- err := g.db(ctx).Select("group_id, user_id").Where("user_id IN (?)", userIDs).Find(&groupMembers).Error
- if err != nil {
- return nil, err
- }
- result := make(map[string][]string)
- for _, groupMember := range groupMembers {
- v, ok := result[groupMember.UserID]
- if !ok {
- result[groupMember.UserID] = []string{groupMember.GroupID}
- } else {
- result[groupMember.UserID] = append(v, groupMember.GroupID)
- }
- }
- return result, nil
-}
-
-func (g *GroupMemberGorm) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
- return groupIDs, utils.Wrap(
- g.db(ctx).
- Model(&relation.GroupMemberModel{}).
- Where("user_id = ? and (role_level = ? or role_level = ?)", userID, constant.GroupOwner, constant.GroupAdmin).
- Pluck("group_id", &groupIDs).
- Error,
- "",
- )
-}
diff --git a/pkg/common/db/relation/group_model.go b/pkg/common/db/relation/group_model.go
deleted file mode 100644
index 7a8eee9f0..000000000
--- a/pkg/common/db/relation/group_model.go
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "context"
- "time"
-
- "github.com/OpenIMSDK/protocol/constant"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/ormutil"
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-var _ relation.GroupModelInterface = (*GroupGorm)(nil)
-
-type GroupGorm struct {
- *MetaDB
-}
-
-func NewGroupDB(db *gorm.DB) relation.GroupModelInterface {
- return &GroupGorm{NewMetaDB(db, &relation.GroupModel{})}
-}
-
-func (g *GroupGorm) NewTx(tx any) relation.GroupModelInterface {
- return &GroupGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupModel{})}
-}
-
-func (g *GroupGorm) Create(ctx context.Context, groups []*relation.GroupModel) (err error) {
- return utils.Wrap(g.DB.Create(&groups).Error, "")
-}
-
-func (g *GroupGorm) UpdateMap(ctx context.Context, groupID string, args map[string]interface{}) (err error) {
- return utils.Wrap(g.DB.Where("group_id = ?", groupID).Model(&relation.GroupModel{}).Updates(args).Error, "")
-}
-
-func (g *GroupGorm) UpdateStatus(ctx context.Context, groupID string, status int32) (err error) {
- return utils.Wrap(g.DB.Where("group_id = ?", groupID).Model(&relation.GroupModel{}).Updates(map[string]any{"status": status}).Error, "")
-}
-
-func (g *GroupGorm) Find(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
- return groups, utils.Wrap(g.DB.Where("group_id in (?)", groupIDs).Find(&groups).Error, "")
-}
-
-func (g *GroupGorm) Take(ctx context.Context, groupID string) (group *relation.GroupModel, err error) {
- group = &relation.GroupModel{}
- return group, utils.Wrap(g.DB.Where("group_id = ?", groupID).Take(group).Error, "")
-}
-
-func (g *GroupGorm) Search(ctx context.Context, keyword string, pageNumber, showNumber int32) (total uint32, groups []*relation.GroupModel, err error) {
- db := g.DB
- db = db.WithContext(ctx).Where("status!=?", constant.GroupStatusDismissed)
- return ormutil.GormSearch[relation.GroupModel](db, []string{"name"}, keyword, pageNumber, showNumber)
-}
-
-func (g *GroupGorm) GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error) {
- return groupIDs, utils.Wrap(g.DB.Model(&relation.GroupModel{}).Where("group_type = ? ", groupType).Pluck("group_id", &groupIDs).Error, "")
-}
-
-func (g *GroupGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
- db := g.db(ctx).Model(&relation.GroupModel{})
- if before != nil {
- db = db.Where("create_time < ?", before)
- }
- if err := db.Count(&count).Error; err != nil {
- return 0, err
- }
- return count, nil
-}
-
-func (g *GroupGorm) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
- var res []struct {
- Date time.Time `gorm:"column:date"`
- Count int64 `gorm:"column:count"`
- }
- err := g.db(ctx).Model(&relation.GroupModel{}).Select("DATE(create_time) AS date, count(1) AS count").Where("create_time >= ? and create_time < ?", start, end).Group("date").Find(&res).Error
- if err != nil {
- return nil, errs.Wrap(err)
- }
- v := make(map[string]int64)
- for _, r := range res {
- v[r.Date.Format("2006-01-02")] = r.Count
- }
- return v, nil
-}
-
-func (g *GroupGorm) FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
- return groups, utils.Wrap(g.DB.Where("group_id in (?) and status != ?", groupIDs, constant.GroupStatusDismissed).Find(&groups).Error, "")
-}
diff --git a/pkg/common/db/relation/group_request_model.go b/pkg/common/db/relation/group_request_model.go
deleted file mode 100644
index af3f277e8..000000000
--- a/pkg/common/db/relation/group_request_model.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "context"
-
- "github.com/OpenIMSDK/tools/ormutil"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type GroupRequestGorm struct {
- *MetaDB
-}
-
-func NewGroupRequest(db *gorm.DB) relation.GroupRequestModelInterface {
- return &GroupRequestGorm{
- NewMetaDB(db, &relation.GroupRequestModel{}),
- }
-}
-
-func (g *GroupRequestGorm) NewTx(tx any) relation.GroupRequestModelInterface {
- return &GroupRequestGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupRequestModel{})}
-}
-
-func (g *GroupRequestGorm) Create(ctx context.Context, groupRequests []*relation.GroupRequestModel) (err error) {
- return utils.Wrap(g.DB.WithContext(ctx).Create(&groupRequests).Error, utils.GetSelfFuncName())
-}
-
-func (g *GroupRequestGorm) Delete(ctx context.Context, groupID string, userID string) (err error) {
- return utils.Wrap(
- g.DB.WithContext(ctx).
- Where("group_id = ? and user_id = ? ", groupID, userID).
- Delete(&relation.GroupRequestModel{}).
- Error,
- utils.GetSelfFuncName(),
- )
-}
-
-func (g *GroupRequestGorm) UpdateHandler(
- ctx context.Context,
- groupID string,
- userID string,
- handledMsg string,
- handleResult int32,
-) (err error) {
- return utils.Wrap(
- g.DB.WithContext(ctx).
- Model(&relation.GroupRequestModel{}).
- Where("group_id = ? and user_id = ? ", groupID, userID).
- Updates(map[string]any{
- "handle_msg": handledMsg,
- "handle_result": handleResult,
- }).
- Error,
- utils.GetSelfFuncName(),
- )
-}
-
-func (g *GroupRequestGorm) Take(
- ctx context.Context,
- groupID string,
- userID string,
-) (groupRequest *relation.GroupRequestModel, err error) {
- groupRequest = &relation.GroupRequestModel{}
- return groupRequest, utils.Wrap(
- g.DB.WithContext(ctx).Where("group_id = ? and user_id = ? ", groupID, userID).Take(groupRequest).Error,
- utils.GetSelfFuncName(),
- )
-}
-
-func (g *GroupRequestGorm) Page(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
-) (total uint32, groups []*relation.GroupRequestModel, err error) {
- return ormutil.GormSearch[relation.GroupRequestModel](
- g.DB.WithContext(ctx).Where("user_id = ?", userID),
- nil,
- "",
- pageNumber,
- showNumber,
- )
-}
-
-func (g *GroupRequestGorm) PageGroup(
- ctx context.Context,
- groupIDs []string,
- pageNumber, showNumber int32,
-) (total uint32, groups []*relation.GroupRequestModel, err error) {
- return ormutil.GormPage[relation.GroupRequestModel](
- g.DB.WithContext(ctx).Where("group_id in ?", groupIDs),
- pageNumber,
- showNumber,
- )
-}
-
-func (g *GroupRequestGorm) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (total int64, groupRequests []*relation.GroupRequestModel, err error) {
- err = g.DB.WithContext(ctx).Where("group_id = ? and user_id in ?", groupID, userIDs).Find(&groupRequests).Error
- return int64(len(groupRequests)), groupRequests, utils.Wrap(err, utils.GetSelfFuncName())
-}
diff --git a/pkg/common/db/relation/log_model.go b/pkg/common/db/relation/log_model.go
deleted file mode 100644
index 53365ca5b..000000000
--- a/pkg/common/db/relation/log_model.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package relation
-
-import (
- "context"
- "time"
-
- "github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/ormutil"
- "gorm.io/gorm"
-
- relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type LogGorm struct {
- db *gorm.DB
-}
-
-func (l *LogGorm) Create(ctx context.Context, log []*relationtb.Log) error {
- return errs.Wrap(l.db.WithContext(ctx).Create(log).Error)
-}
-
-func (l *LogGorm) Search(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relationtb.Log, error) {
- db := l.db.WithContext(ctx).Where("create_time >= ?", start)
- if end.UnixMilli() != 0 {
- db = l.db.WithContext(ctx).Where("create_time <= ?", end)
- }
- db = db.Order("create_time desc")
- return ormutil.GormSearch[relationtb.Log](db, []string{"user_id"}, keyword, pageNumber, showNumber)
-}
-
-func (l *LogGorm) Delete(ctx context.Context, logIDs []string, userID string) error {
- if userID == "" {
- return errs.Wrap(l.db.WithContext(ctx).Where("log_id in ?", logIDs).Delete(&relationtb.Log{}).Error)
- }
- return errs.Wrap(l.db.WithContext(ctx).Where("log_id in ? and user_id=?", logIDs, userID).Delete(&relationtb.Log{}).Error)
-}
-
-func (l *LogGorm) Get(ctx context.Context, logIDs []string, userID string) ([]*relationtb.Log, error) {
- var logs []*relationtb.Log
- if userID == "" {
- return logs, errs.Wrap(l.db.WithContext(ctx).Where("log_id in ?", logIDs).Find(&logs).Error)
- }
- return logs, errs.Wrap(l.db.WithContext(ctx).Where("log_id in ? and user_id=?", logIDs, userID).Find(&logs).Error)
-}
-
-func NewLogGorm(db *gorm.DB) relationtb.LogInterface {
- db.AutoMigrate(&relationtb.Log{})
- return &LogGorm{db: db}
-}
diff --git a/pkg/common/db/relation/mysql_init.go b/pkg/common/db/relation/mysql_init.go
deleted file mode 100644
index 41399d5ca..000000000
--- a/pkg/common/db/relation/mysql_init.go
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "fmt"
- "time"
-
- "github.com/OpenIMSDK/tools/errs"
- "github.com/OpenIMSDK/tools/log"
- "github.com/OpenIMSDK/tools/mw/specialerror"
- mysqldriver "github.com/go-sql-driver/mysql"
- "gorm.io/driver/mysql"
- "gorm.io/gorm"
- "gorm.io/gorm/logger"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/config"
-)
-
-const (
- maxRetry = 100 // number of retries
-)
-
-type option struct {
- Username string
- Password string
- Address []string
- Database string
- LogLevel int
- SlowThreshold int
- MaxLifeTime int
- MaxOpenConn int
- MaxIdleConn int
- Connect func(dsn string, maxRetry int) (*gorm.DB, error)
-}
-
-// newMysqlGormDB Initialize the database connection.
-func newMysqlGormDB(o *option) (*gorm.DB, error) {
- err := maybeCreateTable(o)
- if err != nil {
- return nil, err
- }
- dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
- o.Username, o.Password, o.Address[0], o.Database)
- sqlLogger := log.NewSqlLogger(
- logger.LogLevel(o.LogLevel),
- true,
- time.Duration(o.SlowThreshold)*time.Millisecond,
- )
- db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
- Logger: sqlLogger,
- })
- if err != nil {
- return nil, err
- }
- sqlDB, err := db.DB()
- if err != nil {
- return nil, err
- }
- sqlDB.SetConnMaxLifetime(time.Second * time.Duration(o.MaxLifeTime))
- sqlDB.SetMaxOpenConns(o.MaxOpenConn)
- sqlDB.SetMaxIdleConns(o.MaxIdleConn)
- return db, nil
-}
-
-// maybeCreateTable creates a database if it does not exists.
-func maybeCreateTable(o *option) error {
- dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
- o.Username, o.Password, o.Address[0], "mysql")
-
- var db *gorm.DB
- var err error
- if f := o.Connect; f != nil {
- db, err = f(dsn, maxRetry)
- } else {
- db, err = connectToDatabase(dsn, maxRetry)
- }
- if err != nil {
- panic(err.Error() + " Open failed " + dsn)
- }
-
- sqlDB, err := db.DB()
- if err != nil {
- return err
- }
- defer sqlDB.Close()
- sql := fmt.Sprintf(
- "CREATE DATABASE IF NOT EXISTS `%s` default charset utf8mb4 COLLATE utf8mb4_unicode_ci",
- o.Database,
- )
- err = db.Exec(sql).Error
- if err != nil {
- return fmt.Errorf("init db %w", err)
- }
- return nil
-}
-
-// connectToDatabase Connection retry for mysql.
-func connectToDatabase(dsn string, maxRetry int) (*gorm.DB, error) {
- var db *gorm.DB
- var err error
- for i := 0; i <= maxRetry; i++ {
- db, err = gorm.Open(mysql.Open(dsn), nil)
- if err == nil {
- return db, nil
- }
- if mysqlErr, ok := err.(*mysqldriver.MySQLError); ok && mysqlErr.Number == 1045 {
- return nil, err
- }
- time.Sleep(time.Duration(1) * time.Second)
- }
- return nil, err
-}
-
-// NewGormDB gorm mysql.
-func NewGormDB() (*gorm.DB, error) {
- specialerror.AddReplace(gorm.ErrRecordNotFound, errs.ErrRecordNotFound)
- specialerror.AddErrHandler(replaceDuplicateKey)
-
- return newMysqlGormDB(&option{
- Username: config.Config.Mysql.Username,
- Password: config.Config.Mysql.Password,
- Address: config.Config.Mysql.Address,
- Database: config.Config.Mysql.Database,
- LogLevel: config.Config.Mysql.LogLevel,
- SlowThreshold: config.Config.Mysql.SlowThreshold,
- MaxLifeTime: config.Config.Mysql.MaxLifeTime,
- MaxOpenConn: config.Config.Mysql.MaxOpenConn,
- MaxIdleConn: config.Config.Mysql.MaxIdleConn,
- })
-}
-
-func replaceDuplicateKey(err error) errs.CodeError {
- if IsMysqlDuplicateKey(err) {
- return errs.ErrDuplicateKey
- }
- return nil
-}
-
-func IsMysqlDuplicateKey(err error) bool {
- if mysqlErr, ok := err.(*mysqldriver.MySQLError); ok {
- return mysqlErr.Number == 1062
- }
- return false
-}
diff --git a/pkg/common/db/relation/mysql_init_test.go b/pkg/common/db/relation/mysql_init_test.go
deleted file mode 100644
index c321dfd9f..000000000
--- a/pkg/common/db/relation/mysql_init_test.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package relation
-
-import (
- "context"
- "database/sql"
- "database/sql/driver"
- "errors"
- "fmt"
- "reflect"
- "testing"
-
- "gorm.io/driver/mysql"
- "gorm.io/gorm"
- "gorm.io/gorm/logger"
-)
-
-func TestMaybeCreateTable(t *testing.T) {
- t.Run("normal", func(t *testing.T) {
- err := maybeCreateTable(&option{
- Username: "root",
- Password: "openIM123",
- Address: []string{"172.28.0.1:13306"},
- Database: "openIM_v3",
- LogLevel: 4,
- SlowThreshold: 500,
- MaxOpenConn: 1000,
- MaxIdleConn: 100,
- MaxLifeTime: 60,
- Connect: connect(expectExec{
- query: "CREATE DATABASE IF NOT EXISTS `openIM_v3` default charset utf8mb4 COLLATE utf8mb4_unicode_ci",
- args: nil,
- }),
- })
- if err != nil {
- t.Fatal(err)
- }
- })
-
- t.Run("im-db", func(t *testing.T) {
- err := maybeCreateTable(&option{
- Username: "root",
- Password: "openIM123",
- Address: []string{"172.28.0.1:13306"},
- Database: "im-db",
- LogLevel: 4,
- SlowThreshold: 500,
- MaxOpenConn: 1000,
- MaxIdleConn: 100,
- MaxLifeTime: 60,
- Connect: connect(expectExec{
- query: "CREATE DATABASE IF NOT EXISTS `im-db` default charset utf8mb4 COLLATE utf8mb4_unicode_ci",
- args: nil,
- }),
- })
- if err != nil {
- t.Fatal(err)
- }
- })
-
- t.Run("err", func(t *testing.T) {
- e := errors.New("e")
- err := maybeCreateTable(&option{
- Username: "root",
- Password: "openIM123",
- Address: []string{"172.28.0.1:13306"},
- Database: "openIM_v3",
- LogLevel: 4,
- SlowThreshold: 500,
- MaxOpenConn: 1000,
- MaxIdleConn: 100,
- MaxLifeTime: 60,
- Connect: connect(expectExec{
- err: e,
- }),
- })
- if !errors.Is(err, e) {
- t.Fatalf("err not is e: %v", err)
- }
- })
-}
-
-func connect(e expectExec) func(string, int) (*gorm.DB, error) {
- return func(string, int) (*gorm.DB, error) {
- return gorm.Open(mysql.New(mysql.Config{
- SkipInitializeWithVersion: true,
- Conn: sql.OpenDB(e),
- }), &gorm.Config{
- Logger: logger.Discard,
- })
- }
-}
-
-type expectExec struct {
- err error
- query string
- args []driver.NamedValue
-}
-
-func (c expectExec) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
- if c.err != nil {
- return nil, c.err
- }
- if query != c.query {
- return nil, fmt.Errorf("query mismatch. expect: %s, got: %s", c.query, query)
- }
- if reflect.DeepEqual(args, c.args) {
- return nil, fmt.Errorf("args mismatch. expect: %v, got: %v", c.args, args)
- }
- return noEffectResult{}, nil
-}
-
-func (e expectExec) Connect(context.Context) (driver.Conn, error) { return e, nil }
-func (expectExec) Driver() driver.Driver { panic("not implemented") }
-func (expectExec) Prepare(query string) (driver.Stmt, error) { panic("not implemented") }
-func (expectExec) Close() (e error) { return }
-func (expectExec) Begin() (driver.Tx, error) { panic("not implemented") }
-
-type noEffectResult struct{}
-
-func (noEffectResult) LastInsertId() (i int64, e error) { return }
-func (noEffectResult) RowsAffected() (i int64, e error) { return }
diff --git a/pkg/common/db/relation/object_model.go b/pkg/common/db/relation/object_model.go
deleted file mode 100644
index c5624a8d4..000000000
--- a/pkg/common/db/relation/object_model.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "context"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/errs"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type ObjectInfoGorm struct {
- *MetaDB
-}
-
-func NewObjectInfo(db *gorm.DB) relation.ObjectInfoModelInterface {
- return &ObjectInfoGorm{
- NewMetaDB(db, &relation.ObjectModel{}),
- }
-}
-
-func (o *ObjectInfoGorm) NewTx(tx any) relation.ObjectInfoModelInterface {
- return &ObjectInfoGorm{
- NewMetaDB(tx.(*gorm.DB), &relation.ObjectModel{}),
- }
-}
-
-func (o *ObjectInfoGorm) SetObject(ctx context.Context, obj *relation.ObjectModel) (err error) {
- if err := o.DB.WithContext(ctx).Where("name = ?", obj.Name).FirstOrCreate(obj).Error; err != nil {
- return errs.Wrap(err)
- }
- return nil
-}
-
-func (o *ObjectInfoGorm) Take(ctx context.Context, name string) (info *relation.ObjectModel, err error) {
- info = &relation.ObjectModel{}
- return info, errs.Wrap(o.DB.WithContext(ctx).Where("name = ?", name).Take(info).Error)
-}
diff --git a/pkg/common/db/relation/user_model.go b/pkg/common/db/relation/user_model.go
deleted file mode 100644
index b04c29816..000000000
--- a/pkg/common/db/relation/user_model.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package relation
-
-import (
- "context"
- "time"
-
- "github.com/OpenIMSDK/tools/errs"
-
- "gorm.io/gorm"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
-)
-
-type UserGorm struct {
- *MetaDB
-}
-
-func NewUserGorm(db *gorm.DB) relation.UserModelInterface {
- return &UserGorm{NewMetaDB(db, &relation.UserModel{})}
-}
-
-// 插入多条.
-func (u *UserGorm) Create(ctx context.Context, users []*relation.UserModel) (err error) {
- return utils.Wrap(u.db(ctx).Create(&users).Error, "")
-}
-
-// 更新用户信息 零值.
-func (u *UserGorm) UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error) {
- return utils.Wrap(u.db(ctx).Model(&relation.UserModel{}).Where("user_id = ?", userID).Updates(args).Error, "")
-}
-
-// 更新多个用户信息 非零值.
-func (u *UserGorm) Update(ctx context.Context, user *relation.UserModel) (err error) {
- return utils.Wrap(u.db(ctx).Model(user).Updates(user).Error, "")
-}
-
-// 获取指定用户信息 不存在,也不返回错误.
-func (u *UserGorm) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
- err = utils.Wrap(u.db(ctx).Where("user_id in (?)", userIDs).Find(&users).Error, "")
- return users, err
-}
-
-// 获取某个用户信息 不存在,则返回错误.
-func (u *UserGorm) Take(ctx context.Context, userID string) (user *relation.UserModel, err error) {
- user = &relation.UserModel{}
- err = utils.Wrap(u.db(ctx).Where("user_id = ?", userID).Take(&user).Error, "")
- return user, err
-}
-
-// 获取用户信息 不存在,不返回错误.
-func (u *UserGorm) Page(
- ctx context.Context,
- pageNumber, showNumber int32,
-) (users []*relation.UserModel, count int64, err error) {
- err = utils.Wrap(u.db(ctx).Count(&count).Error, "")
- if err != nil {
- return
- }
- err = utils.Wrap(
- u.db(ctx).
- Limit(int(showNumber)).
- Offset(int((pageNumber-1)*showNumber)).
- Find(&users).
- Order("create_time DESC").
- Error,
- "",
- )
- return
-}
-
-// 获取所有用户ID.
-func (u *UserGorm) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) {
- if pageNumber == 0 || showNumber == 0 {
- return userIDs, errs.Wrap(u.db(ctx).Pluck("user_id", &userIDs).Error)
- } else {
- return userIDs, errs.Wrap(u.db(ctx).Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("user_id", &userIDs).Error)
- }
-}
-
-func (u *UserGorm) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) {
- err = u.db(ctx).Model(&relation.UserModel{}).Where("user_id = ?", userID).Pluck("global_recv_msg_opt", &opt).Error
- return opt, err
-}
-
-func (u *UserGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
- db := u.db(ctx).Model(&relation.UserModel{})
- if before != nil {
- db = db.Where("create_time < ?", before)
- }
- if err := db.Count(&count).Error; err != nil {
- return 0, err
- }
- return count, nil
-}
-
-func (u *UserGorm) CountRangeEverydayTotal(
- ctx context.Context,
- start time.Time,
- end time.Time,
-) (map[string]int64, error) {
- var res []struct {
- Date time.Time `gorm:"column:date"`
- Count int64 `gorm:"column:count"`
- }
- err := u.db(ctx).
- Model(&relation.UserModel{}).
- Select("DATE(create_time) AS date, count(1) AS count").
- Where("create_time >= ? and create_time < ?", start, end).
- Group("date").
- Find(&res).
- Error
- if err != nil {
- return nil, errs.Wrap(err)
- }
- v := make(map[string]int64)
- for _, r := range res {
- v[r.Date.Format("2006-01-02")] = r.Count
- }
- return v, nil
-}
diff --git a/pkg/common/db/s3/cont/controller.go b/pkg/common/db/s3/cont/controller.go
index 7040c7306..1bf1a4b12 100644
--- a/pkg/common/db/s3/cont/controller.go
+++ b/pkg/common/db/s3/cont/controller.go
@@ -46,6 +46,10 @@ type Controller struct {
impl s3.Interface
}
+func (c *Controller) Engine() string {
+ return c.impl.Engine()
+}
+
func (c *Controller) HashPath(md5 string) string {
return path.Join(hashPath, md5)
}
diff --git a/pkg/common/db/s3/cos/internal.go b/pkg/common/db/s3/cos/internal.go
index 0e58a851c..02afde684 100644
--- a/pkg/common/db/s3/cos/internal.go
+++ b/pkg/common/db/s3/cos/internal.go
@@ -10,4 +10,4 @@ import (
)
//go:linkname newRequest github.com/tencentyun/cos-go-sdk-v5.(*Client).newRequest
-func newRequest(c *cos.Client, ctx context.Context, baseURL *url.URL, uri, method string, body interface{}, optQuery interface{}, optHeader interface{}) (req *http.Request, err error)
+func newRequest(c *cos.Client, ctx context.Context, baseURL *url.URL, uri, method string, body any, optQuery any, optHeader any) (req *http.Request, err error)
diff --git a/pkg/common/db/s3/kodo/internal.go b/pkg/common/db/s3/kodo/internal.go
deleted file mode 100644
index 3a4943e62..000000000
--- a/pkg/common/db/s3/kodo/internal.go
+++ /dev/null
@@ -1 +0,0 @@
-package kodo
diff --git a/pkg/common/db/s3/kodo/kodo.go b/pkg/common/db/s3/kodo/kodo.go
deleted file mode 100644
index d73220b3b..000000000
--- a/pkg/common/db/s3/kodo/kodo.go
+++ /dev/null
@@ -1,323 +0,0 @@
-package kodo
-
-import (
- "context"
- "errors"
- "fmt"
- "net/http"
- "net/url"
- "strconv"
- "strings"
- "time"
-
- "github.com/aws/aws-sdk-go-v2/aws"
- awss3config "github.com/aws/aws-sdk-go-v2/config"
- "github.com/aws/aws-sdk-go-v2/credentials"
- awss3 "github.com/aws/aws-sdk-go-v2/service/s3"
- awss3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
- "github.com/openimsdk/open-im-server/v3/pkg/common/config"
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3"
- "github.com/qiniu/go-sdk/v7/auth"
- "github.com/qiniu/go-sdk/v7/storage"
-)
-
-const (
- minPartSize = 1024 * 1024 * 1 // 1MB
- maxPartSize = 1024 * 1024 * 1024 * 5 // 5GB
- maxNumSize = 10000
-)
-
-type Kodo struct {
- AccessKey string
- SecretKey string
- Region string
- Token string
- Endpoint string
- BucketURL string
- Auth *auth.Credentials
- Client *awss3.Client
- PresignClient *awss3.PresignClient
-}
-
-func NewKodo() (s3.Interface, error) {
- conf := config.Config.Object.Kodo
- //init client
- cfg, err := awss3config.LoadDefaultConfig(context.TODO(),
- awss3config.WithRegion(conf.Bucket),
- awss3config.WithEndpointResolverWithOptions(
- aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
- return aws.Endpoint{URL: conf.Endpoint}, nil
- })),
- awss3config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
- conf.AccessKeyID,
- conf.AccessKeySecret,
- conf.SessionToken),
- ),
- )
- if err != nil {
- panic(err)
- }
- client := awss3.NewFromConfig(cfg)
- presignClient := awss3.NewPresignClient(client)
-
- return &Kodo{
- AccessKey: conf.AccessKeyID,
- SecretKey: conf.AccessKeySecret,
- Region: conf.Bucket,
- BucketURL: conf.BucketURL,
- Auth: auth.New(conf.AccessKeyID, conf.AccessKeySecret),
- Client: client,
- PresignClient: presignClient,
- }, nil
-}
-
-func (k Kodo) Engine() string {
- return "kodo"
-}
-
-func (k Kodo) PartLimit() *s3.PartLimit {
- return &s3.PartLimit{
- MinPartSize: minPartSize,
- MaxPartSize: maxPartSize,
- MaxNumSize: maxNumSize,
- }
-}
-
-func (k Kodo) InitiateMultipartUpload(ctx context.Context, name string) (*s3.InitiateMultipartUploadResult, error) {
- result, err := k.Client.CreateMultipartUpload(ctx, &awss3.CreateMultipartUploadInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- if err != nil {
- return nil, err
- }
- return &s3.InitiateMultipartUploadResult{
- UploadID: aws.ToString(result.UploadId),
- Bucket: aws.ToString(result.Bucket),
- Key: aws.ToString(result.Key),
- }, nil
-}
-
-func (k Kodo) CompleteMultipartUpload(ctx context.Context, uploadID string, name string, parts []s3.Part) (*s3.CompleteMultipartUploadResult, error) {
- kodoParts := make([]awss3types.CompletedPart, len(parts))
- for i, part := range parts {
- kodoParts[i] = awss3types.CompletedPart{
- PartNumber: aws.Int32(int32(part.PartNumber)),
- ETag: aws.String(part.ETag),
- }
- }
- result, err := k.Client.CompleteMultipartUpload(ctx, &awss3.CompleteMultipartUploadInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- UploadId: aws.String(uploadID),
- MultipartUpload: &awss3types.CompletedMultipartUpload{Parts: kodoParts},
- })
- if err != nil {
- return nil, err
- }
- return &s3.CompleteMultipartUploadResult{
- Location: aws.ToString(result.Location),
- Bucket: aws.ToString(result.Bucket),
- Key: aws.ToString(result.Key),
- ETag: strings.ToLower(strings.ReplaceAll(aws.ToString(result.ETag), `"`, ``)),
- }, nil
-}
-
-func (k Kodo) PartSize(ctx context.Context, size int64) (int64, error) {
- if size <= 0 {
- return 0, errors.New("size must be greater than 0")
- }
- if size > maxPartSize*maxNumSize {
- return 0, fmt.Errorf("size must be less than %db", maxPartSize*maxNumSize)
- }
- if size <= minPartSize*maxNumSize {
- return minPartSize, nil
- }
- partSize := size / maxNumSize
- if size%maxNumSize != 0 {
- partSize++
- }
- return partSize, nil
-}
-
-func (k Kodo) AuthSign(ctx context.Context, uploadID string, name string, expire time.Duration, partNumbers []int) (*s3.AuthSignResult, error) {
- result := s3.AuthSignResult{
- URL: k.BucketURL + "/" + name,
- Query: url.Values{"uploadId": {uploadID}},
- Header: make(http.Header),
- Parts: make([]s3.SignPart, len(partNumbers)),
- }
- for i, partNumber := range partNumbers {
- part, _ := k.PresignClient.PresignUploadPart(ctx, &awss3.UploadPartInput{
- Bucket: aws.String(k.Region),
- UploadId: aws.String(uploadID),
- Key: aws.String(name),
- PartNumber: aws.Int32(int32(partNumber)),
- })
- result.Parts[i] = s3.SignPart{
- PartNumber: partNumber,
- URL: part.URL,
- Header: part.SignedHeader,
- }
- }
- return &result, nil
-
-}
-
-func (k Kodo) PresignedPutObject(ctx context.Context, name string, expire time.Duration) (string, error) {
- object, err := k.PresignClient.PresignPutObject(ctx, &awss3.PutObjectInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- }, func(po *awss3.PresignOptions) {
- po.Expires = expire
- })
- return object.URL, err
-
-}
-
-func (k Kodo) DeleteObject(ctx context.Context, name string) error {
- _, err := k.Client.DeleteObject(ctx, &awss3.DeleteObjectInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- return err
-}
-
-func (k Kodo) CopyObject(ctx context.Context, src string, dst string) (*s3.CopyObjectInfo, error) {
- result, err := k.Client.CopyObject(ctx, &awss3.CopyObjectInput{
- Bucket: aws.String(k.Region),
- CopySource: aws.String(k.Region + "/" + src),
- Key: aws.String(dst),
- })
- if err != nil {
- return nil, err
- }
- return &s3.CopyObjectInfo{
- Key: dst,
- ETag: strings.ToLower(strings.ReplaceAll(aws.ToString(result.CopyObjectResult.ETag), `"`, ``)),
- }, nil
-}
-
-func (k Kodo) StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error) {
- info, err := k.Client.HeadObject(ctx, &awss3.HeadObjectInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- if err != nil {
- return nil, err
- }
- res := &s3.ObjectInfo{Key: name}
- res.Size = aws.ToInt64(info.ContentLength)
- res.ETag = strings.ToLower(strings.ReplaceAll(aws.ToString(info.ETag), `"`, ``))
- return res, nil
-}
-
-func (k Kodo) IsNotFound(err error) bool {
- return true
-}
-
-func (k Kodo) AbortMultipartUpload(ctx context.Context, uploadID string, name string) error {
- _, err := k.Client.AbortMultipartUpload(ctx, &awss3.AbortMultipartUploadInput{
- UploadId: aws.String(uploadID),
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- return err
-}
-
-func (k Kodo) ListUploadedParts(ctx context.Context, uploadID string, name string, partNumberMarker int, maxParts int) (*s3.ListUploadedPartsResult, error) {
- result, err := k.Client.ListParts(ctx, &awss3.ListPartsInput{
- Key: aws.String(name),
- UploadId: aws.String(uploadID),
- Bucket: aws.String(k.Region),
- MaxParts: aws.Int32(int32(maxParts)),
- PartNumberMarker: aws.String(strconv.Itoa(partNumberMarker)),
- })
- if err != nil {
- return nil, err
- }
- res := &s3.ListUploadedPartsResult{
- Key: aws.ToString(result.Key),
- UploadID: aws.ToString(result.UploadId),
- MaxParts: int(aws.ToInt32(result.MaxParts)),
- UploadedParts: make([]s3.UploadedPart, len(result.Parts)),
- }
- // int to string
- NextPartNumberMarker, err := strconv.Atoi(aws.ToString(result.NextPartNumberMarker))
- if err != nil {
- return nil, err
- }
- res.NextPartNumberMarker = NextPartNumberMarker
- for i, part := range result.Parts {
- res.UploadedParts[i] = s3.UploadedPart{
- PartNumber: int(aws.ToInt32(part.PartNumber)),
- LastModified: aws.ToTime(part.LastModified),
- ETag: aws.ToString(part.ETag),
- Size: aws.ToInt64(part.Size),
- }
- }
- return res, nil
-}
-
-func (k Kodo) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (string, error) {
- //get object head
- info, err := k.Client.HeadObject(ctx, &awss3.HeadObjectInput{
- Bucket: aws.String(k.Region),
- Key: aws.String(name),
- })
- if err != nil {
- return "", errors.New("AccessURL object not found")
- }
- if opt != nil {
- if opt.ContentType != aws.ToString(info.ContentType) {
- //修改文件类型
- err := k.SetObjectContentType(ctx, name, opt.ContentType)
- if err != nil {
- return "", errors.New("AccessURL setContentType error")
- }
- }
- }
- imageMogr := ""
- //image dispose
- if opt != nil {
- if opt.Image != nil {
- //https://developer.qiniu.com/dora/8255/the-zoom
- process := ""
- if opt.Image.Width > 0 {
- process += strconv.Itoa(opt.Image.Width) + "x"
- }
- if opt.Image.Height > 0 {
- if opt.Image.Width > 0 {
- process += strconv.Itoa(opt.Image.Height)
- } else {
- process += "x" + strconv.Itoa(opt.Image.Height)
- }
- }
- imageMogr = "imageMogr2/thumbnail/" + process
- }
- }
- //expire
- deadline := time.Now().Add(time.Second * expire).Unix()
- domain := k.BucketURL
- query := url.Values{}
- if opt != nil && opt.Filename != "" {
- query.Add("attname", opt.Filename)
- }
- privateURL := storage.MakePrivateURLv2WithQuery(k.Auth, domain, name, query, deadline)
- if imageMogr != "" {
- privateURL += "&" + imageMogr
- }
- return privateURL, nil
-}
-
-func (k *Kodo) SetObjectContentType(ctx context.Context, name string, contentType string) error {
- //set object content-type
- _, err := k.Client.CopyObject(ctx, &awss3.CopyObjectInput{
- Bucket: aws.String(k.Region),
- CopySource: aws.String(k.Region + "/" + name),
- Key: aws.String(name),
- ContentType: aws.String(contentType),
- MetadataDirective: awss3types.MetadataDirectiveReplace,
- })
- return err
-}
diff --git a/pkg/common/db/s3/oss/internal.go b/pkg/common/db/s3/oss/internal.go
index 4ca1acc47..155708ffd 100644
--- a/pkg/common/db/s3/oss/internal.go
+++ b/pkg/common/db/s3/oss/internal.go
@@ -26,7 +26,7 @@ import (
func signHeader(c oss.Conn, req *http.Request, canonicalizedResource string)
//go:linkname getURLParams github.com/aliyun/aliyun-oss-go-sdk/oss.Conn.getURLParams
-func getURLParams(c oss.Conn, params map[string]interface{}) string
+func getURLParams(c oss.Conn, params map[string]any) string
//go:linkname getURL github.com/aliyun/aliyun-oss-go-sdk/oss.urlMaker.getURL
func getURL(um urlMaker, bucket, object, params string) *url.URL
diff --git a/pkg/common/db/s3/oss/oss.go b/pkg/common/db/s3/oss/oss.go
old mode 100755
new mode 100644
diff --git a/pkg/common/db/table/relation/black.go b/pkg/common/db/table/relation/black.go
index 59dd12122..50499054c 100644
--- a/pkg/common/db/table/relation/black.go
+++ b/pkg/common/db/table/relation/black.go
@@ -17,33 +17,27 @@ package relation
import (
"context"
"time"
-)
-const (
- BlackModelTableName = "blacks"
+ "github.com/OpenIMSDK/tools/pagination"
)
type BlackModel struct {
- OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
- BlockUserID string `gorm:"column:block_user_id;primary_key;size:64"`
- CreateTime time.Time `gorm:"column:create_time"`
- AddSource int32 `gorm:"column:add_source"`
- OperatorUserID string `gorm:"column:operator_user_id;size:64"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (BlackModel) TableName() string {
- return BlackModelTableName
+ OwnerUserID string `bson:"owner_user_id"`
+ BlockUserID string `bson:"block_user_id"`
+ CreateTime time.Time `bson:"create_time"`
+ AddSource int32 `bson:"add_source"`
+ OperatorUserID string `bson:"operator_user_id"`
+ Ex string `bson:"ex"`
}
type BlackModelInterface interface {
Create(ctx context.Context, blacks []*BlackModel) (err error)
Delete(ctx context.Context, blacks []*BlackModel) (err error)
- UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]interface{}) (err error)
- Update(ctx context.Context, blacks []*BlackModel) (err error)
+ //UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]any) (err error)
+ //Update(ctx context.Context, blacks []*BlackModel) (err error)
Find(ctx context.Context, blacks []*BlackModel) (blackList []*BlackModel, err error)
Take(ctx context.Context, ownerUserID, blockUserID string) (black *BlackModel, err error)
- FindOwnerBlacks(ctx context.Context, ownerUserID string, pageNumber, showNumber int32) (blacks []*BlackModel, total int64, err error)
+ FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*BlackModel, err error)
FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*BlackModel, err error)
FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error)
}
diff --git a/pkg/common/db/table/relation/conversation.go b/pkg/common/db/table/relation/conversation.go
index e9680873f..e0a5268ca 100644
--- a/pkg/common/db/table/relation/conversation.go
+++ b/pkg/common/db/table/relation/conversation.go
@@ -17,41 +17,35 @@ package relation
import (
"context"
"time"
-)
-const (
- conversationModelTableName = "conversations"
+ "github.com/OpenIMSDK/tools/pagination"
)
type ConversationModel struct {
- OwnerUserID string `gorm:"column:owner_user_id;primary_key;type:char(128)" json:"OwnerUserID"`
- ConversationID string `gorm:"column:conversation_id;primary_key;type:char(128)" json:"conversationID"`
- ConversationType int32 `gorm:"column:conversation_type" json:"conversationType"`
- UserID string `gorm:"column:user_id;type:char(64)" json:"userID"`
- GroupID string `gorm:"column:group_id;type:char(128)" json:"groupID"`
- RecvMsgOpt int32 `gorm:"column:recv_msg_opt" json:"recvMsgOpt"`
- IsPinned bool `gorm:"column:is_pinned" json:"isPinned"`
- IsPrivateChat bool `gorm:"column:is_private_chat" json:"isPrivateChat"`
- BurnDuration int32 `gorm:"column:burn_duration;default:30" json:"burnDuration"`
- GroupAtType int32 `gorm:"column:group_at_type" json:"groupAtType"`
- AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
- Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
- MaxSeq int64 `gorm:"column:max_seq" json:"maxSeq"`
- MinSeq int64 `gorm:"column:min_seq" json:"minSeq"`
- CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
- IsMsgDestruct bool `gorm:"column:is_msg_destruct;default:false"`
- MsgDestructTime int64 `gorm:"column:msg_destruct_time;default:604800"`
- LatestMsgDestructTime time.Time `gorm:"column:latest_msg_destruct_time;autoCreateTime"`
-}
-
-func (ConversationModel) TableName() string {
- return conversationModelTableName
+ OwnerUserID string `bson:"owner_user_id"`
+ ConversationID string `bson:"conversation_id"`
+ ConversationType int32 `bson:"conversation_type"`
+ UserID string `bson:"user_id"`
+ GroupID string `bson:"group_id"`
+ RecvMsgOpt int32 `bson:"recv_msg_opt"`
+ IsPinned bool `bson:"is_pinned"`
+ IsPrivateChat bool `bson:"is_private_chat"`
+ BurnDuration int32 `bson:"burn_duration"`
+ GroupAtType int32 `bson:"group_at_type"`
+ AttachedInfo string `bson:"attached_info"`
+ Ex string `bson:"ex"`
+ MaxSeq int64 `bson:"max_seq"`
+ MinSeq int64 `bson:"min_seq"`
+ CreateTime time.Time `bson:"create_time"`
+ IsMsgDestruct bool `bson:"is_msg_destruct"`
+ MsgDestructTime int64 `bson:"msg_destruct_time"`
+ LatestMsgDestructTime time.Time `bson:"latest_msg_destruct_time"`
}
type ConversationModelInterface interface {
Create(ctx context.Context, conversations []*ConversationModel) (err error)
Delete(ctx context.Context, groupIDs []string) (err error)
- UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) (rows int64, err error)
+ UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]any) (rows int64, err error)
Update(ctx context.Context, conversation *ConversationModel) (err error)
Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*ConversationModel, err error)
FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error)
@@ -61,13 +55,10 @@ type ConversationModelInterface interface {
FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*ConversationModel, err error)
FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
- FindSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
GetAllConversationIDs(ctx context.Context) ([]string, error)
GetAllConversationIDsNumber(ctx context.Context) (int64, error)
- PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error)
- GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (hashReadSeqs map[string]int64, err error)
+ PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*ConversationModel, error)
GetConversationIDsNeedDestruct(ctx context.Context) ([]*ConversationModel, error)
GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
- NewTx(tx any) ConversationModelInterface
}
diff --git a/pkg/common/db/table/relation/friend.go b/pkg/common/db/table/relation/friend.go
index f05f53881..5dae95cb2 100644
--- a/pkg/common/db/table/relation/friend.go
+++ b/pkg/common/db/table/relation/friend.go
@@ -17,62 +17,44 @@ package relation
import (
"context"
"time"
-)
-const (
- FriendModelTableName = "friends"
+ "github.com/OpenIMSDK/tools/pagination"
)
+// FriendModel represents the data structure for a friend relationship in MongoDB.
type FriendModel struct {
- OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
- FriendUserID string `gorm:"column:friend_user_id;primary_key;size:64"`
- Remark string `gorm:"column:remark;size:255"`
- CreateTime time.Time `gorm:"column:create_time;autoCreateTime"`
- AddSource int32 `gorm:"column:add_source"`
- OperatorUserID string `gorm:"column:operator_user_id;size:64"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (FriendModel) TableName() string {
- return FriendModelTableName
+ OwnerUserID string `bson:"owner_user_id"`
+ FriendUserID string `bson:"friend_user_id"`
+ Remark string `bson:"remark"`
+ CreateTime time.Time `bson:"create_time"`
+ AddSource int32 `bson:"add_source"`
+ OperatorUserID string `bson:"operator_user_id"`
+ Ex string `bson:"ex"`
}
+// FriendModelInterface defines the operations for managing friends in MongoDB.
type FriendModelInterface interface {
- // 插入多条记录
+ // Create inserts multiple friend records.
Create(ctx context.Context, friends []*FriendModel) (err error)
- // 删除ownerUserID指定的好友
+ // Delete removes specified friends of the owner user.
Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
- // 更新ownerUserID单个好友信息 更新零值
- UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) (err error)
- // 更新好友信息的非零值
- Update(ctx context.Context, friends []*FriendModel) (err error)
- // 更新好友备注(也支持零值 )
+ // UpdateByMap updates specific fields of a friend document using a map.
+ UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]any) (err error)
+ // UpdateRemark modify remarks.
UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
- // 获取单个好友信息,如没找到 返回错误
+ // Take retrieves a single friend document. Returns an error if not found.
Take(ctx context.Context, ownerUserID, friendUserID string) (friend *FriendModel, err error)
- // 查找好友关系,如果是双向关系,则都返回
+ // FindUserState finds the friendship status between two users.
FindUserState(ctx context.Context, userID1, userID2 string) (friends []*FriendModel, err error)
- // 获取 owner指定的好友列表 如果有friendUserIDs不存在,也不返回错误
+ // FindFriends retrieves a list of friends for a given owner. Missing friends do not cause an error.
FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*FriendModel, err error)
- // 获取哪些人添加了friendUserID 如果有ownerUserIDs不存在,也不返回错误
- FindReversalFriends(
- ctx context.Context,
- friendUserID string,
- ownerUserIDs []string,
- ) (friends []*FriendModel, err error)
- // 获取ownerUserID好友列表 支持翻页
- FindOwnerFriends(
- ctx context.Context,
- ownerUserID string,
- pageNumber, showNumber int32,
- ) (friends []*FriendModel, total int64, err error)
- // 获取哪些人添加了friendUserID 支持翻页
- FindInWhoseFriends(
- ctx context.Context,
- friendUserID string,
- pageNumber, showNumber int32,
- ) (friends []*FriendModel, total int64, err error)
- // 获取好友UserID列表
+ // FindReversalFriends finds users who have added the specified user as a friend.
+ FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) (friends []*FriendModel, err error)
+ // FindOwnerFriends retrieves a paginated list of friends for a given owner.
+ FindOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
+ // FindInWhoseFriends finds users who have added the specified user as a friend, with pagination.
+ FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
+ // FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
NewTx(tx any) FriendModelInterface
UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error)
diff --git a/pkg/common/db/table/relation/friend_request.go b/pkg/common/db/table/relation/friend_request.go
index 51ea0ef6e..8dceb0778 100644
--- a/pkg/common/db/table/relation/friend_request.go
+++ b/pkg/common/db/table/relation/friend_request.go
@@ -17,50 +17,37 @@ package relation
import (
"context"
"time"
-)
-const FriendRequestModelTableName = "friend_requests"
+ "github.com/OpenIMSDK/tools/pagination"
+)
type FriendRequestModel struct {
- FromUserID string `gorm:"column:from_user_id;primary_key;size:64"`
- ToUserID string `gorm:"column:to_user_id;primary_key;size:64"`
- HandleResult int32 `gorm:"column:handle_result"`
- ReqMsg string `gorm:"column:req_msg;size:255"`
- CreateTime time.Time `gorm:"column:create_time; autoCreateTime"`
- HandlerUserID string `gorm:"column:handler_user_id;size:64"`
- HandleMsg string `gorm:"column:handle_msg;size:255"`
- HandleTime time.Time `gorm:"column:handle_time"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (FriendRequestModel) TableName() string {
- return FriendRequestModelTableName
+ FromUserID string `bson:"from_user_id"`
+ ToUserID string `bson:"to_user_id"`
+ HandleResult int32 `bson:"handle_result"`
+ ReqMsg string `bson:"req_msg"`
+ CreateTime time.Time `bson:"create_time"`
+ HandlerUserID string `bson:"handler_user_id"`
+ HandleMsg string `bson:"handle_msg"`
+ HandleTime time.Time `bson:"handle_time"`
+ Ex string `bson:"ex"`
}
type FriendRequestModelInterface interface {
- // 插入多条记录
+ // Insert multiple records
Create(ctx context.Context, friendRequests []*FriendRequestModel) (err error)
- // 删除记录
+ // Delete record
Delete(ctx context.Context, fromUserID, toUserID string) (err error)
- // 更新零值
- UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]interface{}) (err error)
- // 更新多条记录 (非零值)
+ // Update with zero values
+ UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]any) (err error)
+ // Update multiple records (non-zero values)
Update(ctx context.Context, friendRequest *FriendRequestModel) (err error)
- // 获取来指定用户的好友申请 未找到 不返回错误
+ // Get friend requests sent to a specific user, no error returned if not found
Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
- // 获取toUserID收到的好友申请列表
- FindToUserID(
- ctx context.Context,
- toUserID string,
- pageNumber, showNumber int32,
- ) (friendRequests []*FriendRequestModel, total int64, err error)
- // 获取fromUserID发出去的好友申请列表
- FindFromUserID(
- ctx context.Context,
- fromUserID string,
- pageNumber, showNumber int32,
- ) (friendRequests []*FriendRequestModel, total int64, err error)
+ // Get list of friend requests received by toUserID
+ FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*FriendRequestModel, err error)
+ // Get list of friend requests sent by fromUserID
+ FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*FriendRequestModel, err error)
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*FriendRequestModel, err error)
- NewTx(tx any) FriendRequestModelInterface
}
diff --git a/pkg/common/db/table/relation/group.go b/pkg/common/db/table/relation/group.go
index 6759e0d35..bb1ddd878 100644
--- a/pkg/common/db/table/relation/group.go
+++ b/pkg/common/db/table/relation/group.go
@@ -17,48 +17,35 @@ package relation
import (
"context"
"time"
-)
-const (
- GroupModelTableName = "groups"
+ "github.com/OpenIMSDK/tools/pagination"
)
type GroupModel struct {
- GroupID string `gorm:"column:group_id;primary_key;size:64" json:"groupID" binding:"required"`
- GroupName string `gorm:"column:name;size:255" json:"groupName"`
- Notification string `gorm:"column:notification;size:255" json:"notification"`
- Introduction string `gorm:"column:introduction;size:255" json:"introduction"`
- FaceURL string `gorm:"column:face_url;size:255" json:"faceURL"`
- CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
- Ex string `gorm:"column:ex" json:"ex;size:1024"`
- Status int32 `gorm:"column:status"`
- CreatorUserID string `gorm:"column:creator_user_id;size:64"`
- GroupType int32 `gorm:"column:group_type"`
- NeedVerification int32 `gorm:"column:need_verification"`
- LookMemberInfo int32 `gorm:"column:look_member_info" json:"lookMemberInfo"`
- ApplyMemberFriend int32 `gorm:"column:apply_member_friend" json:"applyMemberFriend"`
- NotificationUpdateTime time.Time `gorm:"column:notification_update_time"`
- NotificationUserID string `gorm:"column:notification_user_id;size:64"`
-}
-
-func (GroupModel) TableName() string {
- return GroupModelTableName
+ GroupID string `bson:"group_id"`
+ GroupName string `bson:"group_name"`
+ Notification string `bson:"notification"`
+ Introduction string `bson:"introduction"`
+ FaceURL string `bson:"face_url"`
+ CreateTime time.Time `bson:"create_time"`
+ Ex string `bson:"ex"`
+ Status int32 `bson:"status"`
+ CreatorUserID string `bson:"creator_user_id"`
+ GroupType int32 `bson:"group_type"`
+ NeedVerification int32 `bson:"need_verification"`
+ LookMemberInfo int32 `bson:"look_member_info"`
+ ApplyMemberFriend int32 `bson:"apply_member_friend"`
+ NotificationUpdateTime time.Time `bson:"notification_update_time"`
+ NotificationUserID string `bson:"notification_user_id"`
}
type GroupModelInterface interface {
- NewTx(tx any) GroupModelInterface
Create(ctx context.Context, groups []*GroupModel) (err error)
- UpdateMap(ctx context.Context, groupID string, args map[string]interface{}) (err error)
- UpdateStatus(ctx context.Context, groupID string, status int32) (err error)
+ UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error)
+ UpdateState(ctx context.Context, groupID string, state int32) (err error)
Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
- FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
Take(ctx context.Context, groupID string) (group *GroupModel, err error)
- Search(
- ctx context.Context,
- keyword string,
- pageNumber, showNumber int32,
- ) (total uint32, groups []*GroupModel, err error)
- GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error)
+ Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*GroupModel, err error)
// 获取群总数
CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
// 获取范围内群增量
diff --git a/pkg/common/db/table/relation/group_member.go b/pkg/common/db/table/relation/group_member.go
index bfde72834..88ab87739 100644
--- a/pkg/common/db/table/relation/group_member.go
+++ b/pkg/common/db/table/relation/group_member.go
@@ -17,58 +17,41 @@ package relation
import (
"context"
"time"
-)
-const (
- GroupMemberModelTableName = "group_members"
+ "github.com/OpenIMSDK/tools/pagination"
)
type GroupMemberModel struct {
- GroupID string `gorm:"column:group_id;primary_key;size:64"`
- UserID string `gorm:"column:user_id;primary_key;size:64"`
- Nickname string `gorm:"column:nickname;size:255"`
- FaceURL string `gorm:"column:user_group_face_url;size:255"`
- RoleLevel int32 `gorm:"column:role_level"`
- JoinTime time.Time `gorm:"column:join_time"`
- JoinSource int32 `gorm:"column:join_source"`
- InviterUserID string `gorm:"column:inviter_user_id;size:64"`
- OperatorUserID string `gorm:"column:operator_user_id;size:64"`
- MuteEndTime time.Time `gorm:"column:mute_end_time"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (GroupMemberModel) TableName() string {
- return GroupMemberModelTableName
+ GroupID string `bson:"group_id"`
+ UserID string `bson:"user_id"`
+ Nickname string `bson:"nickname"`
+ FaceURL string `bson:"face_url"`
+ RoleLevel int32 `bson:"role_level"`
+ JoinTime time.Time `bson:"join_time"`
+ JoinSource int32 `bson:"join_source"`
+ InviterUserID string `bson:"inviter_user_id"`
+ OperatorUserID string `bson:"operator_user_id"`
+ MuteEndTime time.Time `bson:"mute_end_time"`
+ Ex string `bson:"ex"`
}
type GroupMemberModelInterface interface {
- NewTx(tx any) GroupMemberModelInterface
+ //NewTx(tx any) GroupMemberModelInterface
Create(ctx context.Context, groupMembers []*GroupMemberModel) (err error)
Delete(ctx context.Context, groupID string, userIDs []string) (err error)
- DeleteGroup(ctx context.Context, groupIDs []string) (err error)
+ //DeleteGroup(ctx context.Context, groupIDs []string) (err error)
Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error)
- UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) (rowsAffected int64, err error)
- Find(
- ctx context.Context,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
- ) (groupMembers []*GroupMemberModel, err error)
+ UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error
FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error)
Take(ctx context.Context, groupID string, userID string) (groupMember *GroupMemberModel, err error)
TakeOwner(ctx context.Context, groupID string) (groupMember *GroupMemberModel, err error)
- SearchMember(
- ctx context.Context,
- keyword string,
- groupIDs []string,
- userIDs []string,
- roleLevels []int32,
- pageNumber, showNumber int32,
- ) (total uint32, groupList []*GroupMemberModel, err error)
- MapGroupMemberNum(ctx context.Context, groupIDs []string) (count map[string]uint32, err error)
- FindJoinUserID(ctx context.Context, groupIDs []string) (groupUsers map[string][]string, err error)
+ SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*GroupMemberModel, err error)
+ FindRoleLevelUserIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
+ //MapGroupMemberNum(ctx context.Context, groupIDs []string) (count map[string]uint32, err error)
+ //FindJoinUserID(ctx context.Context, groupIDs []string) (groupUsers map[string][]string, err error)
FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error)
- FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error)
+ //FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error)
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
+ IsUpdateRoleLevel(data map[string]any) bool
}
diff --git a/pkg/common/db/table/relation/group_request.go b/pkg/common/db/table/relation/group_request.go
index 063b83938..39999d799 100644
--- a/pkg/common/db/table/relation/group_request.go
+++ b/pkg/common/db/table/relation/group_request.go
@@ -17,45 +17,30 @@ package relation
import (
"context"
"time"
-)
-const (
- GroupRequestModelTableName = "group_requests"
+ "github.com/OpenIMSDK/tools/pagination"
)
type GroupRequestModel struct {
- UserID string `gorm:"column:user_id;primary_key;size:64"`
- GroupID string `gorm:"column:group_id;primary_key;size:64"`
- HandleResult int32 `gorm:"column:handle_result"`
- ReqMsg string `gorm:"column:req_msg;size:1024"`
- HandledMsg string `gorm:"column:handle_msg;size:1024"`
- ReqTime time.Time `gorm:"column:req_time"`
- HandleUserID string `gorm:"column:handle_user_id;size:64"`
- HandledTime time.Time `gorm:"column:handle_time"`
- JoinSource int32 `gorm:"column:join_source"`
- InviterUserID string `gorm:"column:inviter_user_id;size:64"`
- Ex string `gorm:"column:ex;size:1024"`
-}
-
-func (GroupRequestModel) TableName() string {
- return GroupRequestModelTableName
+ UserID string `bson:"user_id"`
+ GroupID string `bson:"group_id"`
+ HandleResult int32 `bson:"handle_result"`
+ ReqMsg string `bson:"req_msg"`
+ HandledMsg string `bson:"handled_msg"`
+ ReqTime time.Time `bson:"req_time"`
+ HandleUserID string `bson:"handle_user_id"`
+ HandledTime time.Time `bson:"handled_time"`
+ JoinSource int32 `bson:"join_source"`
+ InviterUserID string `bson:"inviter_user_id"`
+ Ex string `bson:"ex"`
}
type GroupRequestModelInterface interface {
- NewTx(tx any) GroupRequestModelInterface
Create(ctx context.Context, groupRequests []*GroupRequestModel) (err error)
Delete(ctx context.Context, groupID string, userID string) (err error)
UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
Take(ctx context.Context, groupID string, userID string) (groupRequest *GroupRequestModel, err error)
- FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*GroupRequestModel, error)
- Page(
- ctx context.Context,
- userID string,
- pageNumber, showNumber int32,
- ) (total uint32, groups []*GroupRequestModel, err error)
- PageGroup(
- ctx context.Context,
- groupIDs []string,
- pageNumber, showNumber int32,
- ) (total uint32, groups []*GroupRequestModel, err error)
+ FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*GroupRequestModel, error)
+ Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*GroupRequestModel, err error)
+ PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*GroupRequestModel, err error)
}
diff --git a/pkg/common/db/table/relation/log.go b/pkg/common/db/table/relation/log.go
index 72d0fa64e..f690ff8aa 100644
--- a/pkg/common/db/table/relation/log.go
+++ b/pkg/common/db/table/relation/log.go
@@ -3,23 +3,25 @@ package relation
import (
"context"
"time"
+
+ "github.com/OpenIMSDK/tools/pagination"
)
-type Log struct {
- LogID string `gorm:"column:log_id;primary_key;type:char(64)"`
- Platform string `gorm:"column:platform;type:varchar(32)"`
- UserID string `gorm:"column:user_id;type:char(64)"`
- CreateTime time.Time `gorm:"index:,sort:desc"`
- Url string `gorm:"column:url;type varchar(255)"`
- FileName string `gorm:"column:filename;type varchar(255)"`
- SystemType string `gorm:"column:system_type;type varchar(255)"`
- Version string `gorm:"column:version;type varchar(255)"`
- Ex string `gorm:"column:ex;type varchar(255)"`
+type LogModel struct {
+ LogID string `bson:"log_id"`
+ Platform string `bson:"platform"`
+ UserID string `bson:"user_id"`
+ CreateTime time.Time `bson:"create_time"`
+ Url string `bson:"url"`
+ FileName string `bson:"file_name"`
+ SystemType string `bson:"system_type"`
+ Version string `bson:"version"`
+ Ex string `bson:"ex"`
}
type LogInterface interface {
- Create(ctx context.Context, log []*Log) error
- Search(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*Log, error)
+ Create(ctx context.Context, log []*LogModel) error
+ Search(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*LogModel, error)
Delete(ctx context.Context, logID []string, userID string) error
- Get(ctx context.Context, logIDs []string, userID string) ([]*Log, error)
+ Get(ctx context.Context, logIDs []string, userID string) ([]*LogModel, error)
}
diff --git a/pkg/common/db/table/relation/object.go b/pkg/common/db/table/relation/object.go
index 0ed4130a6..678fddcfd 100644
--- a/pkg/common/db/table/relation/object.go
+++ b/pkg/common/db/table/relation/object.go
@@ -19,27 +19,20 @@ import (
"time"
)
-const (
- ObjectInfoModelTableName = "object"
-)
-
type ObjectModel struct {
- Name string `gorm:"column:name;primary_key"`
- UserID string `gorm:"column:user_id"`
- Hash string `gorm:"column:hash"`
- Key string `gorm:"column:key"`
- Size int64 `gorm:"column:size"`
- ContentType string `gorm:"column:content_type"`
- Cause string `gorm:"column:cause"`
- CreateTime time.Time `gorm:"column:create_time"`
-}
-
-func (ObjectModel) TableName() string {
- return ObjectInfoModelTableName
+ Name string `bson:"name"`
+ UserID string `bson:"user_id"`
+ Hash string `bson:"hash"`
+ Engine string `bson:"engine"`
+ Key string `bson:"key"`
+ Size int64 `bson:"size"`
+ ContentType string `bson:"content_type"`
+ Group string `bson:"group"`
+ CreateTime time.Time `bson:"create_time"`
}
type ObjectInfoModelInterface interface {
- NewTx(tx any) ObjectInfoModelInterface
SetObject(ctx context.Context, obj *ObjectModel) error
- Take(ctx context.Context, name string) (*ObjectModel, error)
+ Take(ctx context.Context, engine string, name string) (*ObjectModel, error)
+ Delete(ctx context.Context, engine string, name string) error
}
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index 10a715bda..1f26d751f 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -17,20 +17,18 @@ package relation
import (
"context"
"time"
-)
-const (
- UserModelTableName = "users"
+ "github.com/OpenIMSDK/tools/pagination"
)
type UserModel struct {
- UserID string `gorm:"column:user_id;primary_key;size:64"`
- Nickname string `gorm:"column:name;size:255"`
- FaceURL string `gorm:"column:face_url;size:255"`
- Ex string `gorm:"column:ex;size:1024"`
- CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
- AppMangerLevel int32 `gorm:"column:app_manger_level;default:1"`
- GlobalRecvMsgOpt int32 `gorm:"column:global_recv_msg_opt"`
+ UserID string `bson:"user_id"`
+ Nickname string `bson:"nickname"`
+ FaceURL string `bson:"face_url"`
+ Ex string `bson:"ex"`
+ AppMangerLevel int32 `bson:"app_manger_level"`
+ GlobalRecvMsgOpt int32 `bson:"global_recv_msg_opt"`
+ CreateTime time.Time `bson:"create_time"`
}
func (u *UserModel) GetNickname() string {
@@ -41,29 +39,22 @@ func (u *UserModel) GetFaceURL() string {
return u.FaceURL
}
-func (u *UserModel) GetUserID() string {
+func (u UserModel) GetUserID() string {
return u.UserID
}
-func (u *UserModel) GetEx() string {
+func (u UserModel) GetEx() string {
return u.Ex
}
-func (UserModel) TableName() string {
- return UserModelTableName
-}
-
type UserModelInterface interface {
Create(ctx context.Context, users []*UserModel) (err error)
- UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error)
- Update(ctx context.Context, user *UserModel) (err error)
- // 获取指定用户信息 不存在,也不返回错误
+ UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
Find(ctx context.Context, userIDs []string) (users []*UserModel, err error)
- // 获取某个用户信息 不存在,则返回错误
Take(ctx context.Context, userID string) (user *UserModel, err error)
- // 获取用户信息 不存在,不返回错误
- Page(ctx context.Context, pageNumber, showNumber int32) (users []*UserModel, count int64, err error)
- GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error)
+ Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
+ Exist(ctx context.Context, userID string) (exist bool, err error)
+ GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error)
GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
// 获取用户总数
CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
diff --git a/pkg/common/db/table/relation/utils.go b/pkg/common/db/table/relation/utils.go
index c944eae8b..380f2410e 100644
--- a/pkg/common/db/table/relation/utils.go
+++ b/pkg/common/db/table/relation/utils.go
@@ -15,9 +15,8 @@
package relation
import (
- "gorm.io/gorm"
-
"github.com/OpenIMSDK/tools/utils"
+ "go.mongodb.org/mongo-driver/mongo"
)
type BatchUpdateGroupMember struct {
@@ -32,5 +31,5 @@ type GroupSimpleUserID struct {
}
func IsNotFound(err error) bool {
- return utils.Unwrap(err) == gorm.ErrRecordNotFound
+ return utils.Unwrap(err) == mongo.ErrNoDocuments
}
diff --git a/pkg/common/db/table/unrelation/super_group.go b/pkg/common/db/table/unrelation/super_group.go
index 80c3ef9c7..1fd80c67a 100644
--- a/pkg/common/db/table/unrelation/super_group.go
+++ b/pkg/common/db/table/unrelation/super_group.go
@@ -14,40 +14,40 @@
package unrelation
-import (
- "context"
-)
-
-const (
- CSuperGroup = "super_group"
- CUserToSuperGroup = "user_to_super_group"
-)
-
-type SuperGroupModel struct {
- GroupID string `bson:"group_id" json:"groupID"`
- MemberIDs []string `bson:"member_id_list" json:"memberIDList"`
-}
-
-func (SuperGroupModel) TableName() string {
- return CSuperGroup
-}
-
-type UserToSuperGroupModel struct {
- UserID string `bson:"user_id" json:"userID"`
- GroupIDs []string `bson:"group_id_list" json:"groupIDList"`
-}
-
-func (UserToSuperGroupModel) TableName() string {
- return CUserToSuperGroup
-}
-
-type SuperGroupModelInterface interface {
- CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error
- TakeSuperGroup(ctx context.Context, groupID string) (group *SuperGroupModel, err error)
- FindSuperGroup(ctx context.Context, groupIDs []string) (groups []*SuperGroupModel, err error)
- AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error
- RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error
- GetSuperGroupByUserID(ctx context.Context, userID string) (*UserToSuperGroupModel, error)
- DeleteSuperGroup(ctx context.Context, groupID string) error
- RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error
-}
+//import (
+// "context"
+//)
+//
+//const (
+// CSuperGroup = "super_group"
+// CUserToSuperGroup = "user_to_super_group"
+//)
+//
+//type SuperGroupModel struct {
+// GroupID string `bson:"group_id" json:"groupID"`
+// MemberIDs []string `bson:"member_id_list" json:"memberIDList"`
+//}
+//
+//func (SuperGroupModel) TableName() string {
+// return CSuperGroup
+//}
+//
+//type UserToSuperGroupModel struct {
+// UserID string `bson:"user_id" json:"userID"`
+// GroupIDs []string `bson:"group_id_list" json:"groupIDList"`
+//}
+//
+//func (UserToSuperGroupModel) TableName() string {
+// return CUserToSuperGroup
+//}
+//
+//type SuperGroupModelInterface interface {
+// CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error
+// TakeSuperGroup(ctx context.Context, groupID string) (group *SuperGroupModel, err error)
+// FindSuperGroup(ctx context.Context, groupIDs []string) (groups []*SuperGroupModel, err error)
+// AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error
+// RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error
+// GetSuperGroupByUserID(ctx context.Context, userID string) (*UserToSuperGroupModel, error)
+// DeleteSuperGroup(ctx context.Context, groupID string) error
+// RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error
+//}
diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go
old mode 100755
new mode 100644
index 09e3e904e..38a335567
--- a/pkg/common/db/unrelation/mongo.go
+++ b/pkg/common/db/unrelation/mongo.go
@@ -99,16 +99,6 @@ func (m *Mongo) CreateMsgIndex() error {
return m.createMongoIndex(unrelation.Msg, true, "doc_id")
}
-func (m *Mongo) CreateSuperGroupIndex() error {
- if err := m.createMongoIndex(unrelation.CSuperGroup, true, "group_id"); err != nil {
- return err
- }
- if err := m.createMongoIndex(unrelation.CUserToSuperGroup, true, "user_id"); err != nil {
- return err
- }
- return nil
-}
-
func (m *Mongo) createMongoIndex(collection string, isUnique bool, keys ...string) error {
db := m.db.Database(config.Config.Mongo.Database).Collection(collection)
opts := options.CreateIndexes().SetMaxTime(10 * time.Second)
diff --git a/pkg/common/db/unrelation/msg.go b/pkg/common/db/unrelation/msg.go
old mode 100755
new mode 100644
diff --git a/pkg/common/db/unrelation/msg_convert.go b/pkg/common/db/unrelation/msg_convert.go
index 810b4f419..373bc843e 100644
--- a/pkg/common/db/unrelation/msg_convert.go
+++ b/pkg/common/db/unrelation/msg_convert.go
@@ -48,7 +48,7 @@ func (m *MsgMongoDriver) ConvertMsgsDocLen(ctx context.Context, conversationIDs
log.ZError(ctx, "convertAll delete many failed", err, "conversationID", conversationID)
continue
}
- var newMsgDocs []interface{}
+ var newMsgDocs []any
for _, msgDoc := range msgDocs {
if int64(len(msgDoc.Msg)) == m.model.GetSingleGocMsgNum() {
continue
diff --git a/pkg/common/db/unrelation/super_group.go b/pkg/common/db/unrelation/super_group.go
index c762140a2..6c2bb6aaf 100644
--- a/pkg/common/db/unrelation/super_group.go
+++ b/pkg/common/db/unrelation/super_group.go
@@ -14,149 +14,150 @@
package unrelation
-import (
- "context"
-
- "go.mongodb.org/mongo-driver/bson"
- "go.mongodb.org/mongo-driver/mongo"
- "go.mongodb.org/mongo-driver/mongo/options"
-
- "github.com/OpenIMSDK/tools/utils"
-
- "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
-)
-
-func NewSuperGroupMongoDriver(database *mongo.Database) unrelation.SuperGroupModelInterface {
- return &SuperGroupMongoDriver{
- superGroupCollection: database.Collection(unrelation.CSuperGroup),
- userToSuperGroupCollection: database.Collection(unrelation.CUserToSuperGroup),
- }
-}
-
-type SuperGroupMongoDriver struct {
- superGroupCollection *mongo.Collection
- userToSuperGroupCollection *mongo.Collection
-}
-
-func (s *SuperGroupMongoDriver) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error {
- _, err := s.superGroupCollection.InsertOne(ctx, &unrelation.SuperGroupModel{
- GroupID: groupID,
- MemberIDs: initMemberIDs,
- })
- if err != nil {
- return err
- }
- for _, userID := range initMemberIDs {
- _, err = s.userToSuperGroupCollection.UpdateOne(
- ctx,
- bson.M{"user_id": userID},
- bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
- &options.UpdateOptions{
- Upsert: utils.ToPtr(true),
- },
- )
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-func (s *SuperGroupMongoDriver) TakeSuperGroup(
- ctx context.Context,
- groupID string,
-) (group *unrelation.SuperGroupModel, err error) {
- if err := s.superGroupCollection.FindOne(ctx, bson.M{"group_id": groupID}).Decode(&group); err != nil {
- return nil, utils.Wrap(err, "")
- }
- return group, nil
-}
-
-func (s *SuperGroupMongoDriver) FindSuperGroup(
- ctx context.Context,
- groupIDs []string,
-) (groups []*unrelation.SuperGroupModel, err error) {
- cursor, err := s.superGroupCollection.Find(ctx, bson.M{"group_id": bson.M{
- "$in": groupIDs,
- }})
- if err != nil {
- return nil, err
- }
- defer cursor.Close(ctx)
- if err := cursor.All(ctx, &groups); err != nil {
- return nil, utils.Wrap(err, "")
- }
- return groups, nil
-}
-
-func (s *SuperGroupMongoDriver) AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
- _, err := s.superGroupCollection.UpdateOne(
- ctx,
- bson.M{"group_id": groupID},
- bson.M{"$addToSet": bson.M{"member_id_list": bson.M{"$each": userIDs}}},
- )
- if err != nil {
- return err
- }
- upsert := true
- opts := &options.UpdateOptions{
- Upsert: &upsert,
- }
- for _, userID := range userIDs {
- _, err = s.userToSuperGroupCollection.UpdateOne(
- ctx,
- bson.M{"user_id": userID},
- bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
- opts,
- )
- if err != nil {
- return utils.Wrap(err, "transaction failed")
- }
- }
- return nil
-}
-
-func (s *SuperGroupMongoDriver) RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
- _, err := s.superGroupCollection.UpdateOne(
- ctx,
- bson.M{"group_id": groupID},
- bson.M{"$pull": bson.M{"member_id_list": bson.M{"$in": userIDs}}},
- )
- if err != nil {
- return err
- }
- err = s.RemoveGroupFromUser(ctx, groupID, userIDs)
- if err != nil {
- return err
- }
- return nil
-}
-
-func (s *SuperGroupMongoDriver) GetSuperGroupByUserID(
- ctx context.Context,
- userID string,
-) (*unrelation.UserToSuperGroupModel, error) {
- var user unrelation.UserToSuperGroupModel
- err := s.userToSuperGroupCollection.FindOne(ctx, bson.M{"user_id": userID}).Decode(&user)
- return &user, utils.Wrap(err, "")
-}
-
-func (s *SuperGroupMongoDriver) DeleteSuperGroup(ctx context.Context, groupID string) error {
- group, err := s.TakeSuperGroup(ctx, groupID)
- if err != nil {
- return err
- }
- if _, err := s.superGroupCollection.DeleteOne(ctx, bson.M{"group_id": groupID}); err != nil {
- return utils.Wrap(err, "")
- }
- return s.RemoveGroupFromUser(ctx, groupID, group.MemberIDs)
-}
-
-func (s *SuperGroupMongoDriver) RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error {
- _, err := s.userToSuperGroupCollection.UpdateOne(
- ctx,
- bson.M{"user_id": bson.M{"$in": userIDs}},
- bson.M{"$pull": bson.M{"group_id_list": groupID}},
- )
- return utils.Wrap(err, "")
-}
+//
+//import (
+// "context"
+//
+// "go.mongodb.org/mongo-driver/bson"
+// "go.mongodb.org/mongo-driver/mongo"
+// "go.mongodb.org/mongo-driver/mongo/options"
+//
+// "github.com/OpenIMSDK/tools/utils"
+//
+// "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
+//)
+//
+//func NewSuperGroupMongoDriver(database *mongo.Database) unrelation.SuperGroupModelInterface {
+// return &SuperGroupMongoDriver{
+// superGroupCollection: database.Collection(unrelation.CSuperGroup),
+// userToSuperGroupCollection: database.Collection(unrelation.CUserToSuperGroup),
+// }
+//}
+//
+//type SuperGroupMongoDriver struct {
+// superGroupCollection *mongo.Collection
+// userToSuperGroupCollection *mongo.Collection
+//}
+//
+//func (s *SuperGroupMongoDriver) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error {
+// _, err := s.superGroupCollection.InsertOne(ctx, &unrelation.SuperGroupModel{
+// GroupID: groupID,
+// MemberIDs: initMemberIDs,
+// })
+// if err != nil {
+// return err
+// }
+// for _, userID := range initMemberIDs {
+// _, err = s.userToSuperGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"user_id": userID},
+// bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
+// &options.UpdateOptions{
+// Upsert: utils.ToPtr(true),
+// },
+// )
+// if err != nil {
+// return err
+// }
+// }
+// return nil
+//}
+//
+//func (s *SuperGroupMongoDriver) TakeSuperGroup(
+// ctx context.Context,
+// groupID string,
+//) (group *unrelation.SuperGroupModel, err error) {
+// if err := s.superGroupCollection.FindOne(ctx, bson.M{"group_id": groupID}).Decode(&group); err != nil {
+// return nil, utils.Wrap(err, "")
+// }
+// return group, nil
+//}
+//
+//func (s *SuperGroupMongoDriver) FindSuperGroup(
+// ctx context.Context,
+// groupIDs []string,
+//) (groups []*unrelation.SuperGroupModel, err error) {
+// cursor, err := s.superGroupCollection.Find(ctx, bson.M{"group_id": bson.M{
+// "$in": groupIDs,
+// }})
+// if err != nil {
+// return nil, err
+// }
+// defer cursor.Close(ctx)
+// if err := cursor.All(ctx, &groups); err != nil {
+// return nil, utils.Wrap(err, "")
+// }
+// return groups, nil
+//}
+//
+//func (s *SuperGroupMongoDriver) AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
+// _, err := s.superGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"group_id": groupID},
+// bson.M{"$addToSet": bson.M{"member_id_list": bson.M{"$each": userIDs}}},
+// )
+// if err != nil {
+// return err
+// }
+// upsert := true
+// opts := &options.UpdateOptions{
+// Upsert: &upsert,
+// }
+// for _, userID := range userIDs {
+// _, err = s.userToSuperGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"user_id": userID},
+// bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
+// opts,
+// )
+// if err != nil {
+// return utils.Wrap(err, "transaction failed")
+// }
+// }
+// return nil
+//}
+//
+//func (s *SuperGroupMongoDriver) RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
+// _, err := s.superGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"group_id": groupID},
+// bson.M{"$pull": bson.M{"member_id_list": bson.M{"$in": userIDs}}},
+// )
+// if err != nil {
+// return err
+// }
+// err = s.RemoveGroupFromUser(ctx, groupID, userIDs)
+// if err != nil {
+// return err
+// }
+// return nil
+//}
+//
+//func (s *SuperGroupMongoDriver) GetSuperGroupByUserID(
+// ctx context.Context,
+// userID string,
+//) (*unrelation.UserToSuperGroupModel, error) {
+// var user unrelation.UserToSuperGroupModel
+// err := s.userToSuperGroupCollection.FindOne(ctx, bson.M{"user_id": userID}).Decode(&user)
+// return &user, utils.Wrap(err, "")
+//}
+//
+//func (s *SuperGroupMongoDriver) DeleteSuperGroup(ctx context.Context, groupID string) error {
+// group, err := s.TakeSuperGroup(ctx, groupID)
+// if err != nil {
+// return err
+// }
+// if _, err := s.superGroupCollection.DeleteOne(ctx, bson.M{"group_id": groupID}); err != nil {
+// return utils.Wrap(err, "")
+// }
+// return s.RemoveGroupFromUser(ctx, groupID, group.MemberIDs)
+//}
+//
+//func (s *SuperGroupMongoDriver) RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error {
+// _, err := s.userToSuperGroupCollection.UpdateOne(
+// ctx,
+// bson.M{"user_id": bson.M{"$in": userIDs}},
+// bson.M{"$pull": bson.M{"group_id_list": groupID}},
+// )
+// return utils.Wrap(err, "")
+//}
diff --git a/pkg/common/db/unrelation/user.go b/pkg/common/db/unrelation/user.go
old mode 100755
new mode 100644
diff --git a/pkg/common/http/http_client.go b/pkg/common/http/http_client.go
index f0fde3099..e1bc83d38 100644
--- a/pkg/common/http/http_client.go
+++ b/pkg/common/http/http_client.go
@@ -57,7 +57,7 @@ func Get(url string) (response []byte, err error) {
return body, nil
}
-func Post(ctx context.Context, url string, header map[string]string, data interface{}, timeout int) (content []byte, err error) {
+func Post(ctx context.Context, url string, header map[string]string, data any, timeout int) (content []byte, err error) {
if timeout > 0 {
var cancel func()
ctx, cancel = context.WithTimeout(ctx, time.Second*time.Duration(timeout))
@@ -96,7 +96,7 @@ func Post(ctx context.Context, url string, header map[string]string, data interf
return result, nil
}
-func PostReturn(ctx context.Context, url string, header map[string]string, input, output interface{}, timeOutSecond int) error {
+func PostReturn(ctx context.Context, url string, header map[string]string, input, output any, timeOutSecond int) error {
b, err := Post(ctx, url, header, input, timeOutSecond)
if err != nil {
return err
diff --git a/pkg/common/http/http_client_test.go b/pkg/common/http/http_client_test.go
index 1735a3da7..5d2588673 100644
--- a/pkg/common/http/http_client_test.go
+++ b/pkg/common/http/http_client_test.go
@@ -54,7 +54,7 @@ func TestPost(t *testing.T) {
ctx context.Context
url string
header map[string]string
- data interface{}
+ data any
timeout int
}
tests := []struct {
@@ -84,8 +84,8 @@ func TestPostReturn(t *testing.T) {
ctx context.Context
url string
header map[string]string
- input interface{}
- output interface{}
+ input any
+ output any
timeOutSecond int
}
tests := []struct {
@@ -109,7 +109,7 @@ func Test_callBackPostReturn(t *testing.T) {
ctx context.Context
url string
command string
- input interface{}
+ input any
output callbackstruct.CallbackResp
callbackConfig config.CallBackConfig
}
diff --git a/pkg/rpcclient/grouphash/grouphash.go b/pkg/rpcclient/grouphash/grouphash.go
new file mode 100644
index 000000000..b5570dccd
--- /dev/null
+++ b/pkg/rpcclient/grouphash/grouphash.go
@@ -0,0 +1,88 @@
+package grouphash
+
+import (
+ "context"
+ "crypto/md5"
+ "encoding/binary"
+ "encoding/json"
+
+ "github.com/OpenIMSDK/protocol/group"
+ "github.com/OpenIMSDK/protocol/sdkws"
+ "github.com/OpenIMSDK/tools/utils"
+)
+
+func NewGroupHashFromGroupClient(x group.GroupClient) *GroupHash {
+ return &GroupHash{
+ getGroupAllUserIDs: func(ctx context.Context, groupID string) ([]string, error) {
+ resp, err := x.GetGroupMemberUserIDs(ctx, &group.GetGroupMemberUserIDsReq{GroupID: groupID})
+ if err != nil {
+ return nil, err
+ }
+ return resp.UserIDs, nil
+ },
+ getGroupMemberInfo: func(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
+ resp, err := x.GetGroupMembersInfo(ctx, &group.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs})
+ if err != nil {
+ return nil, err
+ }
+ return resp.Members, nil
+ },
+ }
+}
+
+func NewGroupHashFromGroupServer(x group.GroupServer) *GroupHash {
+ return &GroupHash{
+ getGroupAllUserIDs: func(ctx context.Context, groupID string) ([]string, error) {
+ resp, err := x.GetGroupMemberUserIDs(ctx, &group.GetGroupMemberUserIDsReq{GroupID: groupID})
+ if err != nil {
+ return nil, err
+ }
+ return resp.UserIDs, nil
+ },
+ getGroupMemberInfo: func(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
+ resp, err := x.GetGroupMembersInfo(ctx, &group.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs})
+ if err != nil {
+ return nil, err
+ }
+ return resp.Members, nil
+ },
+ }
+}
+
+type GroupHash struct {
+ getGroupAllUserIDs func(ctx context.Context, groupID string) ([]string, error)
+ getGroupMemberInfo func(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error)
+}
+
+func (gh *GroupHash) GetGroupHash(ctx context.Context, groupID string) (uint64, error) {
+ userIDs, err := gh.getGroupAllUserIDs(ctx, groupID)
+ if err != nil {
+ return 0, err
+ }
+ var members []*sdkws.GroupMemberFullInfo
+ if len(userIDs) > 0 {
+ members, err = gh.getGroupMemberInfo(ctx, groupID, userIDs)
+ if err != nil {
+ return 0, err
+ }
+ utils.Sort(userIDs, true)
+ }
+ memberMap := utils.SliceToMap(members, func(e *sdkws.GroupMemberFullInfo) string {
+ return e.UserID
+ })
+ res := make([]*sdkws.GroupMemberFullInfo, 0, len(members))
+ for _, userID := range userIDs {
+ member, ok := memberMap[userID]
+ if !ok {
+ continue
+ }
+ member.AppMangerLevel = 0
+ res = append(res, member)
+ }
+ data, err := json.Marshal(res)
+ if err != nil {
+ return 0, err
+ }
+ sum := md5.Sum(data)
+ return binary.BigEndian.Uint64(sum[:]), nil
+}
diff --git a/pkg/rpcclient/notification/group.go b/pkg/rpcclient/notification/group.go
index 8e71f61c3..cbae7c49b 100755
--- a/pkg/rpcclient/notification/group.go
+++ b/pkg/rpcclient/notification/group.go
@@ -52,6 +52,41 @@ type GroupNotificationSender struct {
db controller.GroupDatabase
}
+func (g *GroupNotificationSender) PopulateGroupMember(ctx context.Context, members ...*relation.GroupMemberModel) error {
+ if len(members) == 0 {
+ return nil
+ }
+ emptyUserIDs := make(map[string]struct{})
+ for _, member := range members {
+ if member.Nickname == "" || member.FaceURL == "" {
+ emptyUserIDs[member.UserID] = struct{}{}
+ }
+ }
+ if len(emptyUserIDs) > 0 {
+ users, err := g.getUsersInfo(ctx, utils.Keys(emptyUserIDs))
+ if err != nil {
+ return err
+ }
+ userMap := make(map[string]CommonUser)
+ for i, user := range users {
+ userMap[user.GetUserID()] = users[i]
+ }
+ for i, member := range members {
+ user, ok := userMap[member.UserID]
+ if !ok {
+ continue
+ }
+ if member.Nickname == "" {
+ members[i].Nickname = user.GetNickname()
+ }
+ if member.FaceURL == "" {
+ members[i].FaceURL = user.GetFaceURL()
+ }
+ }
+ }
+ return nil
+}
+
func (g *GroupNotificationSender) getUser(ctx context.Context, userID string) (*sdkws.PublicUserInfo, error) {
users, err := g.getUsersInfo(ctx, []string{userID})
if err != nil {
@@ -77,17 +112,21 @@ func (g *GroupNotificationSender) getGroupInfo(ctx context.Context, groupID stri
if err != nil {
return nil, err
}
- owner, err := g.db.TakeGroupOwner(ctx, groupID)
+ ownerUserIDs, err := g.db.GetGroupRoleLevelMemberIDs(ctx, groupID, constant.GroupOwner)
if err != nil {
return nil, err
}
+ var ownerUserID string
+ if len(ownerUserIDs) > 0 {
+ ownerUserID = ownerUserIDs[0]
+ }
return &sdkws.GroupInfo{
GroupID: gm.GroupID,
GroupName: gm.GroupName,
Notification: gm.Notification,
Introduction: gm.Introduction,
FaceURL: gm.FaceURL,
- OwnerUserID: owner.UserID,
+ OwnerUserID: ownerUserID,
CreateTime: gm.CreateTime.UnixMilli(),
MemberCount: num,
Ex: gm.Ex,
@@ -103,39 +142,18 @@ func (g *GroupNotificationSender) getGroupInfo(ctx context.Context, groupID stri
}
func (g *GroupNotificationSender) getGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
- members, err := g.db.FindGroupMember(ctx, []string{groupID}, userIDs, nil)
+ members, err := g.db.FindGroupMembers(ctx, groupID, userIDs)
if err != nil {
return nil, err
}
- log.ZDebug(ctx, "getGroupMembers", "members", members)
- users, err := g.getUsersInfoMap(ctx, userIDs)
- if err != nil {
+ if err := g.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
- log.ZDebug(ctx, "getUsersInfoMap", "users", users)
+ log.ZDebug(ctx, "getGroupMembers", "members", members)
res := make([]*sdkws.GroupMemberFullInfo, 0, len(members))
for _, member := range members {
- user, ok := users[member.UserID]
- if !ok {
- return nil, errs.ErrUserIDNotFound.Wrap(fmt.Sprintf("group %s member %s not in user", member.GroupID, member.UserID))
- }
- if member.Nickname == "" {
- member.Nickname = user.Nickname
- }
- res = append(res, g.groupMemberDB2PB(member, user.AppMangerLevel))
- delete(users, member.UserID)
- }
- //for userID, info := range users {
- // if info.AppMangerLevel == constant.AppAdmin {
- // res = append(res, &sdkws.GroupMemberFullInfo{
- // GroupID: groupID,
- // UserID: userID,
- // Nickname: info.Nickname,
- // FaceURL: info.FaceURL,
- // AppMangerLevel: info.AppMangerLevel,
- // })
- // }
- //}
+ res = append(res, g.groupMemberDB2PB(member, 0))
+ }
return res, nil
}
@@ -163,10 +181,13 @@ func (g *GroupNotificationSender) getGroupMember(ctx context.Context, groupID st
}
func (g *GroupNotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, groupID string) ([]string, error) {
- members, err := g.db.FindGroupMember(ctx, []string{groupID}, nil, []int32{constant.GroupOwner, constant.GroupAdmin})
+ members, err := g.db.FindGroupMemberRoleLevels(ctx, groupID, []int32{constant.GroupOwner, constant.GroupAdmin})
if err != nil {
return nil, err
}
+ if err := g.PopulateGroupMember(ctx, members...); err != nil {
+ return nil, err
+ }
fn := func(e *relation.GroupMemberModel) string { return e.UserID }
return utils.Slice(members, fn), nil
}
diff --git a/scripts/init-config.sh b/scripts/init-config.sh
index a4672c62d..f20fc7e73 100755
--- a/scripts/init-config.sh
+++ b/scripts/init-config.sh
@@ -35,14 +35,35 @@ declare -A TEMPLATES=(
["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/alertmanager.yml"
)
+openim::log::info "Read more configuration information: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md"
+
for template in "${!TEMPLATES[@]}"; do
if [[ ! -f "${template}" ]]; then
- openim::log::error_exit "template file ${template} does not exist..."
+ openim::log::error_exit "Template file ${template} does not exist..."
+ exit 1
fi
+done
+for template in "${!TEMPLATES[@]}"; do
IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}"
for output_file in "${OUTPUT_FILES[@]}"; do
+ if [[ -f "${output_file}" ]]; then
+ echo -n "File ${output_file} already exists. Overwrite? (Y/N): "
+ read -r -n 1 REPLY
+ echo # Adds a line to wrap after user input
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
+ openim::log::info "Overwriting ${output_file}. Previous configuration will be lost."
+ else
+ openim::log::info "Skipping generation of ${output_file}."
+ continue
+ fi
+ fi
+
openim::log::info "⌚ Working with template file: ${template} to ${output_file}..."
+ if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then
+ openim::log::error "genconfig.sh script not found"
+ exit 1
+ fi
"${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || {
openim::log::error "Error processing template file ${template}"
exit 1
@@ -51,4 +72,5 @@ for template in "${!TEMPLATES[@]}"; do
done
done
+
openim::log::success "✨ All configuration files have been successfully generated!"
diff --git a/scripts/init-pwd.sh b/scripts/init-pwd.sh
deleted file mode 100755
index 5e2e162aa..000000000
--- a/scripts/init-pwd.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright © 2023 OpenIM. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-#Include shell font styles and some basic information
-SCRIPTS_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
-OPENIM_ROOT=$(dirname "${SCRIPTS_ROOT}")/..
-
-#Include shell font styles and some basic information
-source $SCRIPTS_ROOT/lib/init.sh
-source $SCRIPTS_ROOT/path_info.sh
-
-cd $SCRIPTS_ROOT
-
-source $OPENIM_ROOT/.env
-
-# Check if PASSWORD only contains letters and numbers
-if [[ "$PASSWORD" =~ ^[a-zA-Z0-9]+$ ]]
-then
- echo "PASSWORD is valid."
-else
- echo "ERR: PASSWORD should only contain letters and numbers. " $PASSWORD
- exit
-fi
-
-echo ""
-echo -e "===> ${PURPLE_PREFIX} you user is:$USER ${COLOR_SUFFIX}"
-echo -e "===> ${PURPLE_PREFIX} you password is:$PASSWORD ${COLOR_SUFFIX}"
-echo -e "===> ${PURPLE_PREFIX} you minio endpoint is:$MINIO_ENDPOINT ${COLOR_SUFFIX}"
-echo -e "===> ${PURPLE_PREFIX} you api url is:$API_URL ${COLOR_SUFFIX}"
-echo ""
-
-# Specify the config file
-config_file="${OPENIM_ROOT}"/config/config.yaml
-
-# Load variables from .env file
-source "${OPENIM_ROOT}"/.env
-
-# Replace the password and username field for mysql
-sed -i "/mysql:/,/database:/ s/password:.*/password: $PASSWORD/" $config_file
-sed -i "/mysql:/,/database:/ s/username:.*/username: $USER/" $config_file
-
-# Replace the password and username field for mongo
-sed -i "/mongo:/,/maxPoolSize:/ s/password:.*/password: $PASSWORD/" $config_file
-sed -i "/mongo:/,/maxPoolSize:/ s/username:.*/username: $USER/" $config_file
-
-# Replace the password field for redis
-sed -i '/redis:/,/password:/s/password: .*/password: '${PASSWORD}'/' $config_file
-
-# Replace accessKeyID and secretAccessKey for minio
-sed -i "/minio:/,/isDistributedMod:/ s/accessKeyID:.*/accessKeyID: $USER/" $config_file
-sed -i "/minio:/,/isDistributedMod:/ s/secretAccessKey:.*/secretAccessKey: $PASSWORD/" $config_file
-sed -i '/minio:/,/endpoint:/s|endpoint: .*|endpoint: '${MINIO_ENDPOINT}'|' $config_file
-sed -i '/object:/,/apiURL:/s|apiURL: .*|apiURL: '${API_URL}'|' $config_file
-
-
-# Replace secret for token
-sed -i "s/secret: .*/secret: $PASSWORD/" $config_file
diff --git a/scripts/install-im-server.sh b/scripts/install-im-server.sh
index 26ab35b0d..47db34433 100755
--- a/scripts/install-im-server.sh
+++ b/scripts/install-im-server.sh
@@ -40,13 +40,13 @@ else
DOCKER_COMPOSE_COMMAND="docker-compose"
fi
+"${OPENIM_ROOT}"/scripts/init-config.sh
pushd "${OPENIM_ROOT}"
${DOCKER_COMPOSE_COMMAND} stop
-curl https://gitee.com/openimsdk/openim-docker/raw/main/example/full-openim-server-and-chat.yml -o docker-compose.yml && make init && docker compose up -d
-"${OPENIM_ROOT}"/scripts/init-config.sh
-${DOCKER_COMPOSE_COMMAND} up --remove-orphans -d
+curl https://gitee.com/openimsdk/openim-docker/raw/main/example/full-openim-server-and-chat.yml -o docker-compose.yml
+${DOCKER_COMPOSE_COMMAND} up -d
sleep 60
${DOCKER_COMPOSE_COMMAND} logs openim-server
${DOCKER_COMPOSE_COMMAND} ps
-popd
+popd
\ No newline at end of file
diff --git a/scripts/install/common.sh b/scripts/install/common.sh
index dd8bf614e..f6ee5d3ad 100755
--- a/scripts/install/common.sh
+++ b/scripts/install/common.sh
@@ -101,7 +101,6 @@ readonly OPENIM_SERVER_PORT_LISTARIES=("${OPENIM_SERVER_PORT_TARGETS[@]##*/}")
openim::common::dependency_name() {
local targets=(
- mysql
redis
zookeeper
kafka
@@ -117,13 +116,11 @@ readonly OPENIM_DEPENDENCY_TARGETS
# This function returns a list of ports for various services
# - zookeeper
# - kafka
-# - mysql
# - mongodb
# - redis
# - minio
openim::common::dependency_port() {
local targets=(
- ${MYSQL_PORT} # MySQL port
${REDIS_PORT} # Redis port
${ZOOKEEPER_PORT} # Zookeeper port
${KAFKA_PORT} # Kafka port
diff --git a/scripts/install/dependency.sh b/scripts/install/dependency.sh
index 7d6685186..bfa0909e2 100755
--- a/scripts/install/dependency.sh
+++ b/scripts/install/dependency.sh
@@ -22,17 +22,6 @@ set -o pipefail
OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd -P)
[[ -z ${COMMON_SOURCED} ]] && source "${OPENIM_ROOT}"/scripts/install/common.sh
-# Start MySQL service
-docker run -d \
- --name mysql \
- -p 13306:3306 \
- -p 23306:33060 \
- -v "${DATA_DIR}/components/mysql/data:/var/lib/mysql" \
- -v "/etc/localtime:/etc/localtime" \
- -e MYSQL_ROOT_PASSWORD=${PASSWORD} \
- --restart always \
- mysql:5.7
-
# Start MongoDB service
docker run -d \
--name mongo \
diff --git a/scripts/install/environment.sh b/scripts/install/environment.sh
index b7c8a5dcb..643f621b6 100755
--- a/scripts/install/environment.sh
+++ b/scripts/install/environment.sh
@@ -95,8 +95,6 @@ generate_ip() {
LAST_OCTET=$((LAST_OCTET + 1))
DOCKER_BRIDGE_GATEWAY=$(generate_ip)
LAST_OCTET=$((LAST_OCTET + 1))
-MYSQL_NETWORK_ADDRESS=$(generate_ip)
-LAST_OCTET=$((LAST_OCTET + 1))
MONGO_NETWORK_ADDRESS=$(generate_ip)
LAST_OCTET=$((LAST_OCTET + 1))
REDIS_NETWORK_ADDRESS=$(generate_ip)
@@ -168,19 +166,6 @@ def "ZOOKEEPER_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # Zookeeper的地址
def "ZOOKEEPER_USERNAME" "" # Zookeeper的用户名
def "ZOOKEEPER_PASSWORD" "" # Zookeeper的密码
-###################### MySQL 配置信息 ######################
-def "MYSQL_PORT" "13306" # MySQL的端口
-def "MYSQL_ADDRESS" "${DOCKER_BRIDGE_GATEWAY}" # MySQL的地址
-def "MYSQL_USERNAME" "${OPENIM_USER}" # MySQL的用户名
-# MySQL的密码
-readonly MYSQL_PASSWORD=${MYSQL_PASSWORD:-"${PASSWORD}"}
-def "MYSQL_DATABASE" "${DATABASE_NAME}" # MySQL的数据库名
-def "MYSQL_MAX_OPEN_CONN" "1000" # 最大打开的连接数
-def "MYSQL_MAX_IDLE_CONN" "100" # 最大空闲连接数
-def "MYSQL_MAX_LIFETIME" "60" # 连接可以重用的最大生命周期(秒)
-def "MYSQL_LOG_LEVEL" "4" # 日志级别
-def "MYSQL_SLOW_THRESHOLD" "500" # 慢查询阈值(毫秒)
-
###################### MongoDB 配置信息 ######################
def "MONGO_URI" # MongoDB的URI
def "MONGO_PORT" "37017" # MongoDB的端口
diff --git a/scripts/install/openim-tools.sh b/scripts/install/openim-tools.sh
index fd95dc00d..f97b9d836 100755
--- a/scripts/install/openim-tools.sh
+++ b/scripts/install/openim-tools.sh
@@ -61,6 +61,7 @@ openim::tools::pre_start_name() {
local targets=(
ncpu
component
+ up35
)
echo "${targets[@]}"
}
diff --git a/scripts/install/test.sh b/scripts/install/test.sh
index eb3f6a200..049dc19c8 100755
--- a/scripts/install/test.sh
+++ b/scripts/install/test.sh
@@ -1202,6 +1202,40 @@ EOF
openim::test::check_error "$response"
}
+# Pulls messages by sequence.
+openim::test::pull_msg_by_seq() {
+ local userID="${1}"
+ local conversationID="${2}"
+ local beginSeq="${3}"
+ local endSeq="${4}"
+ local num="${5}"
+ local order="${6}" # Assuming 0 for ascending, 1 for descending
+
+ # Construct the request body
+ local request_body=$(cat < 1 {
+ redisClient = redis.NewClusterClient(&redis.ClusterOptions{
+ Addrs: config.Config.Redis.Address,
+ Username: config.Config.Redis.Username,
+ Password: config.Config.Redis.Password,
+ })
+ } else {
+ redisClient = redis.NewClient(&redis.Options{
+ Addr: config.Config.Redis.Address[0],
+ Username: config.Config.Redis.Username,
+ Password: config.Config.Redis.Password,
+ })
+ }
+ _, err := redisClient.Ping(context.Background()).Result()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for i := 0; i < 1000000; i++ {
+ val, err := redisClient.Set(context.Background(), "b_"+strconv.Itoa(i), "test", time.Second*10).Result()
+ t.Log("index", i, "resp", val, "err", err)
+ if err != nil {
+ return
+ }
+ }
+
+}
diff --git a/tools/data-conversion/README.md b/tools/data-conversion/README.md
index 8d1bf8629..22126e4d8 100644
--- a/tools/data-conversion/README.md
+++ b/tools/data-conversion/README.md
@@ -13,8 +13,8 @@
### 2. 迁移 OpenIM MySQL 数据
-+ 位置: `open-im-server/v3/tools/data-conversion/openim/mysql.go`
-+ 配置 `mysql.go` 文件中的数据库信息。
++ 位置: `open-im-server/tools/data-conversion/openim/cmd/conversion-mysql.go`
++ 配置 `conversion-mysql.go` 文件中的数据库信息。
+ 手动创建 V3 版本的数据库,并确保字符集为 `utf8mb4`。
```bash
@@ -47,7 +47,7 @@ make build BINS="conversion-mysql"
### 3. 转换聊天消息(可选)
+ 只支持转换存储在 Kafka 中的消息。
-+ 位置: `open-im-server/v3/tools/data-conversion/openim/msg.go`
++ 位置: `open-im-server/tools/data-conversion/openim/conversion-msg/conversion-msg.go`
+ 配置 `msg.go` 文件中的消息和服务器信息。
```bash
@@ -69,7 +69,7 @@ make build BINS="conversion-msg"
### 4. 转换业务服务器数据
+ 只支持转换存储在 Kafka 中的消息。
-+ 位置: `open-im-server/v3/tools/data-conversion/chat/chat.go`
++ 位置: `open-im-server/tools/data-conversion/chat/cmd/conversion-chat/chat.go`
+ 需要手动创建 V3 版本的数据库,并确保字符集为 `utf8mb4`。
+ 配置 `main.go` 文件中的数据库信息。
diff --git a/tools/data-conversion/openim/mysql/conversion/conversion.go b/tools/data-conversion/openim/mysql/conversion/conversion.go
index 298eefb50..54cf90edf 100644
--- a/tools/data-conversion/openim/mysql/conversion/conversion.go
+++ b/tools/data-conversion/openim/mysql/conversion/conversion.go
@@ -3,8 +3,8 @@ package conversion
import (
"github.com/OpenIMSDK/protocol/constant"
- v3 "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
v2 "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v2"
+ v3 "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
"github.com/openimsdk/open-im-server/v3/tools/data-conversion/utils"
)
diff --git a/tools/data-conversion/openim/mysql/v3/black.go b/tools/data-conversion/openim/mysql/v3/black.go
new file mode 100644
index 000000000..59dd12122
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/black.go
@@ -0,0 +1,49 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ BlackModelTableName = "blacks"
+)
+
+type BlackModel struct {
+ OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
+ BlockUserID string `gorm:"column:block_user_id;primary_key;size:64"`
+ CreateTime time.Time `gorm:"column:create_time"`
+ AddSource int32 `gorm:"column:add_source"`
+ OperatorUserID string `gorm:"column:operator_user_id;size:64"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (BlackModel) TableName() string {
+ return BlackModelTableName
+}
+
+type BlackModelInterface interface {
+ Create(ctx context.Context, blacks []*BlackModel) (err error)
+ Delete(ctx context.Context, blacks []*BlackModel) (err error)
+ UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]interface{}) (err error)
+ Update(ctx context.Context, blacks []*BlackModel) (err error)
+ Find(ctx context.Context, blacks []*BlackModel) (blackList []*BlackModel, err error)
+ Take(ctx context.Context, ownerUserID, blockUserID string) (black *BlackModel, err error)
+ FindOwnerBlacks(ctx context.Context, ownerUserID string, pageNumber, showNumber int32) (blacks []*BlackModel, total int64, err error)
+ FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*BlackModel, err error)
+ FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error)
+}
diff --git a/pkg/common/db/table/relation/chatlog.go b/tools/data-conversion/openim/mysql/v3/chatlog.go
similarity index 100%
rename from pkg/common/db/table/relation/chatlog.go
rename to tools/data-conversion/openim/mysql/v3/chatlog.go
diff --git a/tools/data-conversion/openim/mysql/v3/conversation.go b/tools/data-conversion/openim/mysql/v3/conversation.go
new file mode 100644
index 000000000..e9680873f
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/conversation.go
@@ -0,0 +1,73 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ conversationModelTableName = "conversations"
+)
+
+type ConversationModel struct {
+ OwnerUserID string `gorm:"column:owner_user_id;primary_key;type:char(128)" json:"OwnerUserID"`
+ ConversationID string `gorm:"column:conversation_id;primary_key;type:char(128)" json:"conversationID"`
+ ConversationType int32 `gorm:"column:conversation_type" json:"conversationType"`
+ UserID string `gorm:"column:user_id;type:char(64)" json:"userID"`
+ GroupID string `gorm:"column:group_id;type:char(128)" json:"groupID"`
+ RecvMsgOpt int32 `gorm:"column:recv_msg_opt" json:"recvMsgOpt"`
+ IsPinned bool `gorm:"column:is_pinned" json:"isPinned"`
+ IsPrivateChat bool `gorm:"column:is_private_chat" json:"isPrivateChat"`
+ BurnDuration int32 `gorm:"column:burn_duration;default:30" json:"burnDuration"`
+ GroupAtType int32 `gorm:"column:group_at_type" json:"groupAtType"`
+ AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
+ Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
+ MaxSeq int64 `gorm:"column:max_seq" json:"maxSeq"`
+ MinSeq int64 `gorm:"column:min_seq" json:"minSeq"`
+ CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
+ IsMsgDestruct bool `gorm:"column:is_msg_destruct;default:false"`
+ MsgDestructTime int64 `gorm:"column:msg_destruct_time;default:604800"`
+ LatestMsgDestructTime time.Time `gorm:"column:latest_msg_destruct_time;autoCreateTime"`
+}
+
+func (ConversationModel) TableName() string {
+ return conversationModelTableName
+}
+
+type ConversationModelInterface interface {
+ Create(ctx context.Context, conversations []*ConversationModel) (err error)
+ Delete(ctx context.Context, groupIDs []string) (err error)
+ UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) (rows int64, err error)
+ Update(ctx context.Context, conversation *ConversationModel) (err error)
+ Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*ConversationModel, err error)
+ FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error)
+ FindUserIDAllConversationID(ctx context.Context, userID string) ([]string, error)
+ Take(ctx context.Context, userID, conversationID string) (conversation *ConversationModel, err error)
+ FindConversationID(ctx context.Context, userID string, conversationIDs []string) (existConversationID []string, err error)
+ FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*ConversationModel, err error)
+ FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
+ GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
+ FindSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
+ GetAllConversationIDs(ctx context.Context) ([]string, error)
+ GetAllConversationIDsNumber(ctx context.Context) (int64, error)
+ PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error)
+ GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (hashReadSeqs map[string]int64, err error)
+ GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*ConversationModel, error)
+ GetConversationIDsNeedDestruct(ctx context.Context) ([]*ConversationModel, error)
+ GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
+ NewTx(tx any) ConversationModelInterface
+}
diff --git a/pkg/common/db/table/relation/doc.go b/tools/data-conversion/openim/mysql/v3/doc.go
similarity index 100%
rename from pkg/common/db/table/relation/doc.go
rename to tools/data-conversion/openim/mysql/v3/doc.go
diff --git a/tools/data-conversion/openim/mysql/v3/friend.go b/tools/data-conversion/openim/mysql/v3/friend.go
new file mode 100644
index 000000000..58d8d1d34
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/friend.go
@@ -0,0 +1,78 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ FriendModelTableName = "friends"
+)
+
+type FriendModel struct {
+ OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
+ FriendUserID string `gorm:"column:friend_user_id;primary_key;size:64"`
+ Remark string `gorm:"column:remark;size:255"`
+ CreateTime time.Time `gorm:"column:create_time;autoCreateTime"`
+ AddSource int32 `gorm:"column:add_source"`
+ OperatorUserID string `gorm:"column:operator_user_id;size:64"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (FriendModel) TableName() string {
+ return FriendModelTableName
+}
+
+type FriendModelInterface interface {
+ // 插入多条记录
+ Create(ctx context.Context, friends []*FriendModel) (err error)
+ // 删除ownerUserID指定的好友
+ Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
+ // 更新ownerUserID单个好友信息 更新零值
+ UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) (err error)
+ // 更新好友信息的非零值
+ Update(ctx context.Context, friends []*FriendModel) (err error)
+ // 更新好友备注(也支持零值 )
+ UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
+ // 获取单个好友信息,如没找到 返回错误
+ Take(ctx context.Context, ownerUserID, friendUserID string) (friend *FriendModel, err error)
+ // 查找好友关系,如果是双向关系,则都返回
+ FindUserState(ctx context.Context, userID1, userID2 string) (friends []*FriendModel, err error)
+ // 获取 owner指定的好友列表 如果有friendUserIDs不存在,也不返回错误
+ FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*FriendModel, err error)
+ // 获取哪些人添加了friendUserID 如果有ownerUserIDs不存在,也不返回错误
+ FindReversalFriends(
+ ctx context.Context,
+ friendUserID string,
+ ownerUserIDs []string,
+ ) (friends []*FriendModel, err error)
+ // 获取ownerUserID好友列表 支持翻页
+ FindOwnerFriends(
+ ctx context.Context,
+ ownerUserID string,
+ pageNumber, showNumber int32,
+ ) (friends []*FriendModel, total int64, err error)
+ // 获取哪些人添加了friendUserID 支持翻页
+ FindInWhoseFriends(
+ ctx context.Context,
+ friendUserID string,
+ pageNumber, showNumber int32,
+ ) (friends []*FriendModel, total int64, err error)
+ // 获取好友UserID列表
+ FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
+ NewTx(tx any) FriendModelInterface
+}
diff --git a/tools/data-conversion/openim/mysql/v3/friend_request.go b/tools/data-conversion/openim/mysql/v3/friend_request.go
new file mode 100644
index 000000000..51ea0ef6e
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/friend_request.go
@@ -0,0 +1,66 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+const FriendRequestModelTableName = "friend_requests"
+
+type FriendRequestModel struct {
+ FromUserID string `gorm:"column:from_user_id;primary_key;size:64"`
+ ToUserID string `gorm:"column:to_user_id;primary_key;size:64"`
+ HandleResult int32 `gorm:"column:handle_result"`
+ ReqMsg string `gorm:"column:req_msg;size:255"`
+ CreateTime time.Time `gorm:"column:create_time; autoCreateTime"`
+ HandlerUserID string `gorm:"column:handler_user_id;size:64"`
+ HandleMsg string `gorm:"column:handle_msg;size:255"`
+ HandleTime time.Time `gorm:"column:handle_time"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (FriendRequestModel) TableName() string {
+ return FriendRequestModelTableName
+}
+
+type FriendRequestModelInterface interface {
+ // 插入多条记录
+ Create(ctx context.Context, friendRequests []*FriendRequestModel) (err error)
+ // 删除记录
+ Delete(ctx context.Context, fromUserID, toUserID string) (err error)
+ // 更新零值
+ UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]interface{}) (err error)
+ // 更新多条记录 (非零值)
+ Update(ctx context.Context, friendRequest *FriendRequestModel) (err error)
+ // 获取来指定用户的好友申请 未找到 不返回错误
+ Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
+ Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
+ // 获取toUserID收到的好友申请列表
+ FindToUserID(
+ ctx context.Context,
+ toUserID string,
+ pageNumber, showNumber int32,
+ ) (friendRequests []*FriendRequestModel, total int64, err error)
+ // 获取fromUserID发出去的好友申请列表
+ FindFromUserID(
+ ctx context.Context,
+ fromUserID string,
+ pageNumber, showNumber int32,
+ ) (friendRequests []*FriendRequestModel, total int64, err error)
+ FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*FriendRequestModel, err error)
+ NewTx(tx any) FriendRequestModelInterface
+}
diff --git a/tools/data-conversion/openim/mysql/v3/group.go b/tools/data-conversion/openim/mysql/v3/group.go
new file mode 100644
index 000000000..6759e0d35
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/group.go
@@ -0,0 +1,66 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ GroupModelTableName = "groups"
+)
+
+type GroupModel struct {
+ GroupID string `gorm:"column:group_id;primary_key;size:64" json:"groupID" binding:"required"`
+ GroupName string `gorm:"column:name;size:255" json:"groupName"`
+ Notification string `gorm:"column:notification;size:255" json:"notification"`
+ Introduction string `gorm:"column:introduction;size:255" json:"introduction"`
+ FaceURL string `gorm:"column:face_url;size:255" json:"faceURL"`
+ CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
+ Ex string `gorm:"column:ex" json:"ex;size:1024"`
+ Status int32 `gorm:"column:status"`
+ CreatorUserID string `gorm:"column:creator_user_id;size:64"`
+ GroupType int32 `gorm:"column:group_type"`
+ NeedVerification int32 `gorm:"column:need_verification"`
+ LookMemberInfo int32 `gorm:"column:look_member_info" json:"lookMemberInfo"`
+ ApplyMemberFriend int32 `gorm:"column:apply_member_friend" json:"applyMemberFriend"`
+ NotificationUpdateTime time.Time `gorm:"column:notification_update_time"`
+ NotificationUserID string `gorm:"column:notification_user_id;size:64"`
+}
+
+func (GroupModel) TableName() string {
+ return GroupModelTableName
+}
+
+type GroupModelInterface interface {
+ NewTx(tx any) GroupModelInterface
+ Create(ctx context.Context, groups []*GroupModel) (err error)
+ UpdateMap(ctx context.Context, groupID string, args map[string]interface{}) (err error)
+ UpdateStatus(ctx context.Context, groupID string, status int32) (err error)
+ Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
+ FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
+ Take(ctx context.Context, groupID string) (group *GroupModel, err error)
+ Search(
+ ctx context.Context,
+ keyword string,
+ pageNumber, showNumber int32,
+ ) (total uint32, groups []*GroupModel, err error)
+ GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error)
+ // 获取群总数
+ CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
+ // 获取范围内群增量
+ CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/group_member.go b/tools/data-conversion/openim/mysql/v3/group_member.go
new file mode 100644
index 000000000..bfde72834
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/group_member.go
@@ -0,0 +1,74 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ GroupMemberModelTableName = "group_members"
+)
+
+type GroupMemberModel struct {
+ GroupID string `gorm:"column:group_id;primary_key;size:64"`
+ UserID string `gorm:"column:user_id;primary_key;size:64"`
+ Nickname string `gorm:"column:nickname;size:255"`
+ FaceURL string `gorm:"column:user_group_face_url;size:255"`
+ RoleLevel int32 `gorm:"column:role_level"`
+ JoinTime time.Time `gorm:"column:join_time"`
+ JoinSource int32 `gorm:"column:join_source"`
+ InviterUserID string `gorm:"column:inviter_user_id;size:64"`
+ OperatorUserID string `gorm:"column:operator_user_id;size:64"`
+ MuteEndTime time.Time `gorm:"column:mute_end_time"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (GroupMemberModel) TableName() string {
+ return GroupMemberModelTableName
+}
+
+type GroupMemberModelInterface interface {
+ NewTx(tx any) GroupMemberModelInterface
+ Create(ctx context.Context, groupMembers []*GroupMemberModel) (err error)
+ Delete(ctx context.Context, groupID string, userIDs []string) (err error)
+ DeleteGroup(ctx context.Context, groupIDs []string) (err error)
+ Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error)
+ UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) (rowsAffected int64, err error)
+ Find(
+ ctx context.Context,
+ groupIDs []string,
+ userIDs []string,
+ roleLevels []int32,
+ ) (groupMembers []*GroupMemberModel, err error)
+ FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error)
+ Take(ctx context.Context, groupID string, userID string) (groupMember *GroupMemberModel, err error)
+ TakeOwner(ctx context.Context, groupID string) (groupMember *GroupMemberModel, err error)
+ SearchMember(
+ ctx context.Context,
+ keyword string,
+ groupIDs []string,
+ userIDs []string,
+ roleLevels []int32,
+ pageNumber, showNumber int32,
+ ) (total uint32, groupList []*GroupMemberModel, err error)
+ MapGroupMemberNum(ctx context.Context, groupIDs []string) (count map[string]uint32, err error)
+ FindJoinUserID(ctx context.Context, groupIDs []string) (groupUsers map[string][]string, err error)
+ FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
+ TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error)
+ FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error)
+ FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/group_request.go b/tools/data-conversion/openim/mysql/v3/group_request.go
new file mode 100644
index 000000000..063b83938
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/group_request.go
@@ -0,0 +1,61 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ GroupRequestModelTableName = "group_requests"
+)
+
+type GroupRequestModel struct {
+ UserID string `gorm:"column:user_id;primary_key;size:64"`
+ GroupID string `gorm:"column:group_id;primary_key;size:64"`
+ HandleResult int32 `gorm:"column:handle_result"`
+ ReqMsg string `gorm:"column:req_msg;size:1024"`
+ HandledMsg string `gorm:"column:handle_msg;size:1024"`
+ ReqTime time.Time `gorm:"column:req_time"`
+ HandleUserID string `gorm:"column:handle_user_id;size:64"`
+ HandledTime time.Time `gorm:"column:handle_time"`
+ JoinSource int32 `gorm:"column:join_source"`
+ InviterUserID string `gorm:"column:inviter_user_id;size:64"`
+ Ex string `gorm:"column:ex;size:1024"`
+}
+
+func (GroupRequestModel) TableName() string {
+ return GroupRequestModelTableName
+}
+
+type GroupRequestModelInterface interface {
+ NewTx(tx any) GroupRequestModelInterface
+ Create(ctx context.Context, groupRequests []*GroupRequestModel) (err error)
+ Delete(ctx context.Context, groupID string, userID string) (err error)
+ UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
+ Take(ctx context.Context, groupID string, userID string) (groupRequest *GroupRequestModel, err error)
+ FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*GroupRequestModel, error)
+ Page(
+ ctx context.Context,
+ userID string,
+ pageNumber, showNumber int32,
+ ) (total uint32, groups []*GroupRequestModel, err error)
+ PageGroup(
+ ctx context.Context,
+ groupIDs []string,
+ pageNumber, showNumber int32,
+ ) (total uint32, groups []*GroupRequestModel, err error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/log.go b/tools/data-conversion/openim/mysql/v3/log.go
new file mode 100644
index 000000000..5904a790e
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/log.go
@@ -0,0 +1,29 @@
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+type Log struct {
+ LogID string `gorm:"column:log_id;primary_key;type:char(64)"`
+ Platform string `gorm:"column:platform;type:varchar(32)"`
+ UserID string `gorm:"column:user_id;type:char(64)"`
+ CreateTime time.Time `gorm:"index:,sort:desc"`
+ Url string `gorm:"column:url;type varchar(255)"`
+ FileName string `gorm:"column:filename;type varchar(255)"`
+ SystemType string `gorm:"column:system_type;type varchar(255)"`
+ Version string `gorm:"column:version;type varchar(255)"`
+ Ex string `gorm:"column:ex;type varchar(255)"`
+}
+
+func (Log) TableName() string {
+ return "logs"
+}
+
+type LogInterface interface {
+ Create(ctx context.Context, log []*Log) error
+ Search(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*Log, error)
+ Delete(ctx context.Context, logID []string, userID string) error
+ Get(ctx context.Context, logIDs []string, userID string) ([]*Log, error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/object.go b/tools/data-conversion/openim/mysql/v3/object.go
new file mode 100644
index 000000000..0ed4130a6
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/object.go
@@ -0,0 +1,45 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ ObjectInfoModelTableName = "object"
+)
+
+type ObjectModel struct {
+ Name string `gorm:"column:name;primary_key"`
+ UserID string `gorm:"column:user_id"`
+ Hash string `gorm:"column:hash"`
+ Key string `gorm:"column:key"`
+ Size int64 `gorm:"column:size"`
+ ContentType string `gorm:"column:content_type"`
+ Cause string `gorm:"column:cause"`
+ CreateTime time.Time `gorm:"column:create_time"`
+}
+
+func (ObjectModel) TableName() string {
+ return ObjectInfoModelTableName
+}
+
+type ObjectInfoModelInterface interface {
+ NewTx(tx any) ObjectInfoModelInterface
+ SetObject(ctx context.Context, obj *ObjectModel) error
+ Take(ctx context.Context, name string) (*ObjectModel, error)
+}
diff --git a/tools/data-conversion/openim/mysql/v3/user.go b/tools/data-conversion/openim/mysql/v3/user.go
new file mode 100644
index 000000000..10a715bda
--- /dev/null
+++ b/tools/data-conversion/openim/mysql/v3/user.go
@@ -0,0 +1,72 @@
+// Copyright © 2023 OpenIM. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package relation
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ UserModelTableName = "users"
+)
+
+type UserModel struct {
+ UserID string `gorm:"column:user_id;primary_key;size:64"`
+ Nickname string `gorm:"column:name;size:255"`
+ FaceURL string `gorm:"column:face_url;size:255"`
+ Ex string `gorm:"column:ex;size:1024"`
+ CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
+ AppMangerLevel int32 `gorm:"column:app_manger_level;default:1"`
+ GlobalRecvMsgOpt int32 `gorm:"column:global_recv_msg_opt"`
+}
+
+func (u *UserModel) GetNickname() string {
+ return u.Nickname
+}
+
+func (u *UserModel) GetFaceURL() string {
+ return u.FaceURL
+}
+
+func (u *UserModel) GetUserID() string {
+ return u.UserID
+}
+
+func (u *UserModel) GetEx() string {
+ return u.Ex
+}
+
+func (UserModel) TableName() string {
+ return UserModelTableName
+}
+
+type UserModelInterface interface {
+ Create(ctx context.Context, users []*UserModel) (err error)
+ UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error)
+ Update(ctx context.Context, user *UserModel) (err error)
+ // 获取指定用户信息 不存在,也不返回错误
+ Find(ctx context.Context, userIDs []string) (users []*UserModel, err error)
+ // 获取某个用户信息 不存在,则返回错误
+ Take(ctx context.Context, userID string) (user *UserModel, err error)
+ // 获取用户信息 不存在,不返回错误
+ Page(ctx context.Context, pageNumber, showNumber int32) (users []*UserModel, count int64, err error)
+ GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error)
+ GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
+ // 获取用户总数
+ CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
+ // 获取范围内用户增量
+ CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
+}
diff --git a/pkg/common/db/relation/meta_db.go b/tools/data-conversion/openim/mysql/v3/utils.go
similarity index 70%
rename from pkg/common/db/relation/meta_db.go
rename to tools/data-conversion/openim/mysql/v3/utils.go
index 6ab980120..c944eae8b 100644
--- a/pkg/common/db/relation/meta_db.go
+++ b/tools/data-conversion/openim/mysql/v3/utils.go
@@ -15,24 +15,22 @@
package relation
import (
- "context"
-
"gorm.io/gorm"
+
+ "github.com/OpenIMSDK/tools/utils"
)
-type MetaDB struct {
- DB *gorm.DB
- table any
+type BatchUpdateGroupMember struct {
+ GroupID string
+ UserID string
+ Map map[string]any
}
-func NewMetaDB(db *gorm.DB, table any) *MetaDB {
- return &MetaDB{
- DB: db,
- table: table,
- }
+type GroupSimpleUserID struct {
+ Hash uint64
+ MemberNum uint32
}
-func (g *MetaDB) db(ctx context.Context) *gorm.DB {
- db := g.DB.WithContext(ctx).Model(g.table)
- return db
+func IsNotFound(err error) bool {
+ return utils.Unwrap(err) == gorm.ErrRecordNotFound
}
diff --git a/tools/data-conversion/openim/proto/msg/msg.pb.go b/tools/data-conversion/openim/proto/msg/msg.pb.go
index 2954a3a76..a0a6cdf02 100644
--- a/tools/data-conversion/openim/proto/msg/msg.pb.go
+++ b/tools/data-conversion/openim/proto/msg/msg.pb.go
@@ -2703,7 +2703,7 @@ func RegisterMsgServer(s *grpc.Server, srv MsgServer) {
s.RegisterService(&_Msg_serviceDesc, srv)
}
-func _Msg_GetMaxAndMinSeq_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetMaxAndMinSeq_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(sdk_ws.GetMaxAndMinSeqReq)
if err := dec(in); err != nil {
return nil, err
@@ -2715,13 +2715,13 @@ func _Msg_GetMaxAndMinSeq_Handler(srv interface{}, ctx context.Context, dec func
Server: srv,
FullMethod: "/msg.msg/GetMaxAndMinSeq",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetMaxAndMinSeq(ctx, req.(*sdk_ws.GetMaxAndMinSeqReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_PullMessageBySeqList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_PullMessageBySeqList_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(sdk_ws.PullMessageBySeqListReq)
if err := dec(in); err != nil {
return nil, err
@@ -2733,13 +2733,13 @@ func _Msg_PullMessageBySeqList_Handler(srv interface{}, ctx context.Context, dec
Server: srv,
FullMethod: "/msg.msg/PullMessageBySeqList",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).PullMessageBySeqList(ctx, req.(*sdk_ws.PullMessageBySeqListReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_SendMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_SendMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(SendMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2751,13 +2751,13 @@ func _Msg_SendMsg_Handler(srv interface{}, ctx context.Context, dec func(interfa
Server: srv,
FullMethod: "/msg.msg/SendMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).SendMsg(ctx, req.(*SendMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_DelMsgList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_DelMsgList_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(sdk_ws.DelMsgListReq)
if err := dec(in); err != nil {
return nil, err
@@ -2769,13 +2769,13 @@ func _Msg_DelMsgList_Handler(srv interface{}, ctx context.Context, dec func(inte
Server: srv,
FullMethod: "/msg.msg/DelMsgList",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).DelMsgList(ctx, req.(*sdk_ws.DelMsgListReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_DelSuperGroupMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_DelSuperGroupMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(DelSuperGroupMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2787,13 +2787,13 @@ func _Msg_DelSuperGroupMsg_Handler(srv interface{}, ctx context.Context, dec fun
Server: srv,
FullMethod: "/msg.msg/DelSuperGroupMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).DelSuperGroupMsg(ctx, req.(*DelSuperGroupMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_ClearMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_ClearMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(ClearMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2805,13 +2805,13 @@ func _Msg_ClearMsg_Handler(srv interface{}, ctx context.Context, dec func(interf
Server: srv,
FullMethod: "/msg.msg/ClearMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).ClearMsg(ctx, req.(*ClearMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_SetMsgMinSeq_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_SetMsgMinSeq_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(SetMsgMinSeqReq)
if err := dec(in); err != nil {
return nil, err
@@ -2823,13 +2823,13 @@ func _Msg_SetMsgMinSeq_Handler(srv interface{}, ctx context.Context, dec func(in
Server: srv,
FullMethod: "/msg.msg/SetMsgMinSeq",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).SetMsgMinSeq(ctx, req.(*SetMsgMinSeqReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_SetSendMsgStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_SetSendMsgStatus_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(SetSendMsgStatusReq)
if err := dec(in); err != nil {
return nil, err
@@ -2841,13 +2841,13 @@ func _Msg_SetSendMsgStatus_Handler(srv interface{}, ctx context.Context, dec fun
Server: srv,
FullMethod: "/msg.msg/SetSendMsgStatus",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).SetSendMsgStatus(ctx, req.(*SetSendMsgStatusReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_GetSendMsgStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetSendMsgStatus_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetSendMsgStatusReq)
if err := dec(in); err != nil {
return nil, err
@@ -2859,13 +2859,13 @@ func _Msg_GetSendMsgStatus_Handler(srv interface{}, ctx context.Context, dec fun
Server: srv,
FullMethod: "/msg.msg/GetSendMsgStatus",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetSendMsgStatus(ctx, req.(*GetSendMsgStatusReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_GetSuperGroupMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetSuperGroupMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetSuperGroupMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2877,13 +2877,13 @@ func _Msg_GetSuperGroupMsg_Handler(srv interface{}, ctx context.Context, dec fun
Server: srv,
FullMethod: "/msg.msg/GetSuperGroupMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetSuperGroupMsg(ctx, req.(*GetSuperGroupMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_GetWriteDiffMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetWriteDiffMsg_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetWriteDiffMsgReq)
if err := dec(in); err != nil {
return nil, err
@@ -2895,13 +2895,13 @@ func _Msg_GetWriteDiffMsg_Handler(srv interface{}, ctx context.Context, dec func
Server: srv,
FullMethod: "/msg.msg/GetWriteDiffMsg",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetWriteDiffMsg(ctx, req.(*GetWriteDiffMsgReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_SetMessageReactionExtensions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_SetMessageReactionExtensions_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(SetMessageReactionExtensionsReq)
if err := dec(in); err != nil {
return nil, err
@@ -2913,13 +2913,13 @@ func _Msg_SetMessageReactionExtensions_Handler(srv interface{}, ctx context.Cont
Server: srv,
FullMethod: "/msg.msg/SetMessageReactionExtensions",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).SetMessageReactionExtensions(ctx, req.(*SetMessageReactionExtensionsReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_GetMessageListReactionExtensions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_GetMessageListReactionExtensions_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetMessageListReactionExtensionsReq)
if err := dec(in); err != nil {
return nil, err
@@ -2931,13 +2931,13 @@ func _Msg_GetMessageListReactionExtensions_Handler(srv interface{}, ctx context.
Server: srv,
FullMethod: "/msg.msg/GetMessageListReactionExtensions",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).GetMessageListReactionExtensions(ctx, req.(*GetMessageListReactionExtensionsReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_AddMessageReactionExtensions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_AddMessageReactionExtensions_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(AddMessageReactionExtensionsReq)
if err := dec(in); err != nil {
return nil, err
@@ -2949,13 +2949,13 @@ func _Msg_AddMessageReactionExtensions_Handler(srv interface{}, ctx context.Cont
Server: srv,
FullMethod: "/msg.msg/AddMessageReactionExtensions",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).AddMessageReactionExtensions(ctx, req.(*AddMessageReactionExtensionsReq))
}
return interceptor(ctx, in, info, handler)
}
-func _Msg_DeleteMessageReactionExtensions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+func _Msg_DeleteMessageReactionExtensions_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(DeleteMessageListReactionExtensionsReq)
if err := dec(in); err != nil {
return nil, err
@@ -2967,7 +2967,7 @@ func _Msg_DeleteMessageReactionExtensions_Handler(srv interface{}, ctx context.C
Server: srv,
FullMethod: "/msg.msg/DeleteMessageReactionExtensions",
}
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ handler := func(ctx context.Context, req any) (any, error) {
return srv.(MsgServer).DeleteMessageReactionExtensions(ctx, req.(*DeleteMessageListReactionExtensionsReq))
}
return interceptor(ctx, in, info, handler)
diff --git a/tools/data-conversion/openim/proto/sdk_ws/ws.pb.go b/tools/data-conversion/openim/proto/sdk_ws/ws.pb.go
index 097280860..94b6f9be6 100644
--- a/tools/data-conversion/openim/proto/sdk_ws/ws.pb.go
+++ b/tools/data-conversion/openim/proto/sdk_ws/ws.pb.go
@@ -4156,8 +4156,8 @@ func (m *SignalReq) GetGetTokenByRoomID() *SignalGetTokenByRoomIDReq {
}
// XXX_OneofFuncs is for the internal use of the proto package.
-func (*SignalReq) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
- return _SignalReq_OneofMarshaler, _SignalReq_OneofUnmarshaler, _SignalReq_OneofSizer, []interface{}{
+func (*SignalReq) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []any) {
+ return _SignalReq_OneofMarshaler, _SignalReq_OneofUnmarshaler, _SignalReq_OneofSizer, []any{
(*SignalReq_Invite)(nil),
(*SignalReq_InviteInGroup)(nil),
(*SignalReq_Cancel)(nil),
@@ -4523,8 +4523,8 @@ func (m *SignalResp) GetGetTokenByRoomID() *SignalGetTokenByRoomIDReply {
}
// XXX_OneofFuncs is for the internal use of the proto package.
-func (*SignalResp) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
- return _SignalResp_OneofMarshaler, _SignalResp_OneofUnmarshaler, _SignalResp_OneofSizer, []interface{}{
+func (*SignalResp) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []any) {
+ return _SignalResp_OneofMarshaler, _SignalResp_OneofUnmarshaler, _SignalResp_OneofSizer, []any{
(*SignalResp_Invite)(nil),
(*SignalResp_InviteInGroup)(nil),
(*SignalResp_Cancel)(nil),
diff --git a/tools/up35/README.md b/tools/up35/README.md
new file mode 100644
index 000000000..c5bdcd3b6
--- /dev/null
+++ b/tools/up35/README.md
@@ -0,0 +1,67 @@
+# README for OpenIM Server Data Conversion Tool
+
+## Overview
+
+This tool is part of the OpenIM Server suite, specifically designed for data conversion between MySQL and MongoDB databases. It handles the migration of various data types, including user information, friendships, group memberships, and more from a MySQL database to MongoDB, ensuring data consistency and integrity during the transition.
+
+## Features
+
++ **Configurable Database Connections:** Supports connections to both MySQL and MongoDB, configurable through a YAML file.
++ **Data Conversion Tasks:** Converts a range of data models, including user profiles, friend requests, group memberships, and logs.
++ **Version Control:** Maintains data versioning, ensuring only necessary migrations are performed.
++ **Error Handling:** Robust error handling for database connectivity and query execution.
+
+## Requirements
+
++ Go programming environment
++ MySQL and MongoDB servers
++ OpenIM Server dependencies installed
+
+## Installation
+
+1. Ensure Go is installed and set up on your system.
+2. Clone the OpenIM Server repository.
+3. Navigate to the directory containing this tool.
+4. Install required dependencies.
+
+## Configuration
+
++ Configuration is managed through a YAML file specified at runtime.
++ Set up the MySQL and MongoDB connection parameters in the config file.
+
+## Usage
+
+To run the tool, use the following command from the terminal:
+
+```go
+make build BINS="up35"
+```
+
+Where `path/to/config.yaml` is the path to your configuration file.
+
+## Functionality
+
+The main functions of the script include:
+
++ `InitConfig(path string)`: Reads and parses the YAML configuration file.
++ `GetMysql()`: Establishes a connection to the MySQL database.
++ `GetMongo()`: Establishes a connection to the MongoDB database.
++ `Main(path string)`: Orchestrates the data migration process.
++ `SetMongoDataVersion(db *mongo.Database, curver string)`: Updates the data version in MongoDB after migration.
++ `NewTask(...)`: Generic function to handle the migration of different data types.
++ `insertMany(coll *mongo.Collection, objs []any)`: Inserts multiple records into a MongoDB collection.
++ `getColl(obj any)`: Retrieves the MongoDB collection associated with a given object.
++ `convert struct`: Contains methods for converting MySQL models to MongoDB models.
+
+## Notes
+
++ Ensure that the MySQL and MongoDB instances are accessible and that the credentials provided in the config file are correct.
++ It is advisable to backup databases before running the migration to prevent data loss.
+
+## Contributing
+
+Contributions to improve the tool or address issues are welcome. Please follow the project's contribution guidelines.
+
+## License
+
+Refer to the project's license document for usage and distribution rights.
\ No newline at end of file
diff --git a/tools/up35/go.mod b/tools/up35/go.mod
new file mode 100644
index 000000000..5ae3907bf
--- /dev/null
+++ b/tools/up35/go.mod
@@ -0,0 +1,51 @@
+module github.com/openimsdk/open-im-server/v3/tools/up35
+
+go 1.19
+
+require (
+ github.com/go-sql-driver/mysql v1.7.1
+ github.com/openimsdk/open-im-server/v3 v3.5.0
+ github.com/openimsdk/open-im-server/v3/tools/data-conversion v0.0.0-00010101000000-000000000000
+ go.mongodb.org/mongo-driver v1.12.1
+ gopkg.in/yaml.v3 v3.0.1
+ gorm.io/driver/mysql v1.5.1
+ gorm.io/gorm v1.25.4
+)
+
+require (
+ github.com/OpenIMSDK/protocol v0.0.31 // indirect
+ github.com/OpenIMSDK/tools v0.0.18 // indirect
+ github.com/bwmarrin/snowflake v0.3.0 // indirect
+ github.com/golang/protobuf v1.5.3 // indirect
+ github.com/golang/snappy v0.0.4 // indirect
+ github.com/jinzhu/copier v0.4.0 // indirect
+ github.com/jinzhu/inflection v1.0.0 // indirect
+ github.com/jinzhu/now v1.1.5 // indirect
+ github.com/klauspost/compress v1.16.7 // indirect
+ github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
+ github.com/lestrrat-go/strftime v1.0.6 // indirect
+ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
+ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/xdg-go/pbkdf2 v1.0.0 // indirect
+ github.com/xdg-go/scram v1.1.2 // indirect
+ github.com/xdg-go/stringprep v1.0.4 // indirect
+ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
+ go.uber.org/atomic v1.7.0 // indirect
+ go.uber.org/multierr v1.6.0 // indirect
+ go.uber.org/zap v1.24.0 // indirect
+ golang.org/x/crypto v0.14.0 // indirect
+ golang.org/x/image v0.13.0 // indirect
+ golang.org/x/net v0.17.0 // indirect
+ golang.org/x/sync v0.4.0 // indirect
+ golang.org/x/sys v0.14.0 // indirect
+ golang.org/x/text v0.13.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
+ google.golang.org/grpc v1.59.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
+)
+
+replace (
+ github.com/openimsdk/open-im-server/v3 => ./../../../open-im-server
+ github.com/openimsdk/open-im-server/v3/tools/data-conversion => ./../data-conversion
+)
diff --git a/tools/up35/go.sum b/tools/up35/go.sum
new file mode 100644
index 000000000..1a81e5b33
--- /dev/null
+++ b/tools/up35/go.sum
@@ -0,0 +1,125 @@
+github.com/OpenIMSDK/protocol v0.0.31 h1:ax43x9aqA6EKNXNukS5MT5BSTqkUmwO4uTvbJLtzCgE=
+github.com/OpenIMSDK/protocol v0.0.31/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
+github.com/OpenIMSDK/tools v0.0.18 h1:h3CvKB90DNd2aIJcOQ99cqgeW6C0na0PzR1TNsfxwL0=
+github.com/OpenIMSDK/tools v0.0.18/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
+github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
+github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
+github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
+github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
+github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
+github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
+github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
+github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
+github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
+github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ=
+github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
+github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
+github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
+github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE=
+go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
+go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg=
+golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0=
+google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
+google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
+gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
+gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
+gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
diff --git a/tools/up35/up35.go b/tools/up35/up35.go
new file mode 100644
index 000000000..5d4740fca
--- /dev/null
+++ b/tools/up35/up35.go
@@ -0,0 +1,367 @@
+package main
+
+import (
+ "context"
+ "errors"
+ "flag"
+ "fmt"
+ "github.com/go-sql-driver/mysql"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/config"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
+ mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
+ "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
+ mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "gopkg.in/yaml.v3"
+ gormMysql "gorm.io/driver/mysql"
+ "gorm.io/gorm"
+ "gorm.io/gorm/logger"
+ "log"
+ "os"
+ "reflect"
+ "strconv"
+)
+
+const (
+ versionTable = "dataver"
+ versionKey = "data_version"
+ versionValue = 35
+)
+
+func main() {
+ var path string
+ flag.StringVar(&path, "c", "", "path config file")
+ flag.Parse()
+ if err := Main(path); err != nil {
+ log.Fatal(err)
+ return
+ }
+ os.Exit(0)
+}
+
+func InitConfig(path string) error {
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return err
+ }
+ return yaml.Unmarshal(data, &config.Config)
+}
+
+func GetMysql() (*gorm.DB, error) {
+ conf := config.Config.Mysql
+ mysqlDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.Username, conf.Password, conf.Address[0], conf.Database)
+ return gorm.Open(gormMysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard})
+}
+
+func GetMongo() (*mongo.Database, error) {
+ mgo, err := unrelation.NewMongo()
+ if err != nil {
+ return nil, err
+ }
+ return mgo.GetDatabase(), nil
+}
+
+func Main(path string) error {
+ if err := InitConfig(path); err != nil {
+ return err
+ }
+ if config.Config.Mysql == nil {
+ return nil
+ }
+ mongoDB, err := GetMongo()
+ if err != nil {
+ return err
+ }
+ var version struct {
+ Key string `bson:"key"`
+ Value string `bson:"value"`
+ }
+ switch mongoDB.Collection(versionTable).FindOne(context.Background(), bson.M{"key": versionKey}).Decode(&version) {
+ case nil:
+ if ver, _ := strconv.Atoi(version.Value); ver >= versionValue {
+ return nil
+ }
+ case mongo.ErrNoDocuments:
+ default:
+ return err
+ }
+ mysqlDB, err := GetMysql()
+ if err != nil {
+ if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1049 {
+ if err := SetMongoDataVersion(mongoDB, version.Value); err != nil {
+ return err
+ }
+ return nil // database not exist
+ }
+ return err
+ }
+
+ var c convert
+ var tasks []func() error
+ tasks = append(tasks,
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewUserMongo, c.User) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendMongo, c.Friend) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendRequestMongo, c.FriendRequest) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewBlackMongo, c.Black) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMongo, c.Group) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMember, c.GroupMember) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupRequestMgo, c.GroupRequest) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewConversationMongo, c.Conversation) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewS3Mongo, c.Object(config.Config.Object.Enable)) },
+ func() error { return NewTask(mysqlDB, mongoDB, mgo.NewLogMongo, c.Log) },
+ )
+
+ for _, task := range tasks {
+ if err := task(); err != nil {
+ return err
+ }
+ }
+
+ if err := SetMongoDataVersion(mongoDB, version.Value); err != nil {
+ return err
+ }
+ return nil
+}
+
+func SetMongoDataVersion(db *mongo.Database, curver string) error {
+ filter := bson.M{"key": versionKey, "value": curver}
+ update := bson.M{"$set": bson.M{"key": versionKey, "value": strconv.Itoa(versionValue)}}
+ _, err := db.Collection(versionTable).UpdateOne(context.Background(), filter, update, options.Update().SetUpsert(true))
+ return err
+}
+
+// NewTask A mysql table B mongodb model C mongodb table
+func NewTask[A interface{ TableName() string }, B any, C any](gormDB *gorm.DB, mongoDB *mongo.Database, mongoDBInit func(db *mongo.Database) (B, error), convert func(v A) C) error {
+ obj, err := mongoDBInit(mongoDB)
+ if err != nil {
+ return err
+ }
+ var zero A
+ tableName := zero.TableName()
+ coll, err := getColl(obj)
+ if err != nil {
+ return fmt.Errorf("get mongo collection %s failed, err: %w", tableName, err)
+ }
+ var count int
+ defer func() {
+ log.Printf("completed convert %s total %d\n", tableName, count)
+ }()
+ const batch = 100
+ for page := 0; ; page++ {
+ res := make([]A, 0, batch)
+ if err := gormDB.Limit(batch).Offset(page * batch).Find(&res).Error; err != nil {
+ if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1146 {
+ return nil // table not exist
+ }
+ return fmt.Errorf("find mysql table %s failed, err: %w", tableName, err)
+ }
+ if len(res) == 0 {
+ return nil
+ }
+ temp := make([]any, len(res))
+ for i := range res {
+ temp[i] = convert(res[i])
+ }
+ if err := insertMany(coll, temp); err != nil {
+ return fmt.Errorf("insert mongo table %s failed, err: %w", tableName, err)
+ }
+ count += len(res)
+ if len(res) < batch {
+ return nil
+ }
+ log.Printf("current convert %s completed %d\n", tableName, count)
+ }
+}
+
+func insertMany(coll *mongo.Collection, objs []any) error {
+ if _, err := coll.InsertMany(context.Background(), objs); err != nil {
+ if !mongo.IsDuplicateKeyError(err) {
+ return err
+ }
+ }
+ for i := range objs {
+ _, err := coll.InsertOne(context.Background(), objs[i])
+ switch {
+ case err == nil:
+ case mongo.IsDuplicateKeyError(err):
+ default:
+ return err
+ }
+ }
+ return nil
+}
+
+func getColl(obj any) (_ *mongo.Collection, err error) {
+ defer func() {
+ if e := recover(); e != nil {
+ err = fmt.Errorf("not found %+v", e)
+ }
+ }()
+ stu := reflect.ValueOf(obj).Elem()
+ typ := reflect.TypeOf(&mongo.Collection{}).String()
+ for i := 0; i < stu.NumField(); i++ {
+ field := stu.Field(i)
+ if field.Type().String() == typ {
+ return (*mongo.Collection)(field.UnsafePointer()), nil
+ }
+ }
+ return nil, errors.New("not found")
+}
+
+type convert struct{}
+
+func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel {
+ return mongoModel.UserModel{
+ UserID: v.UserID,
+ Nickname: v.Nickname,
+ FaceURL: v.FaceURL,
+ Ex: v.Ex,
+ AppMangerLevel: v.AppMangerLevel,
+ GlobalRecvMsgOpt: v.GlobalRecvMsgOpt,
+ CreateTime: v.CreateTime,
+ }
+}
+
+func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel {
+ return mongoModel.FriendModel{
+ OwnerUserID: v.OwnerUserID,
+ FriendUserID: v.FriendUserID,
+ Remark: v.Remark,
+ CreateTime: v.CreateTime,
+ AddSource: v.AddSource,
+ OperatorUserID: v.OperatorUserID,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendRequestModel {
+ return mongoModel.FriendRequestModel{
+ FromUserID: v.FromUserID,
+ ToUserID: v.ToUserID,
+ HandleResult: v.HandleResult,
+ ReqMsg: v.ReqMsg,
+ CreateTime: v.CreateTime,
+ HandlerUserID: v.HandlerUserID,
+ HandleMsg: v.HandleMsg,
+ HandleTime: v.HandleTime,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel {
+ return mongoModel.BlackModel{
+ OwnerUserID: v.OwnerUserID,
+ BlockUserID: v.BlockUserID,
+ CreateTime: v.CreateTime,
+ AddSource: v.AddSource,
+ OperatorUserID: v.OperatorUserID,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel {
+ return mongoModel.GroupModel{
+ GroupID: v.GroupID,
+ GroupName: v.GroupName,
+ Notification: v.Notification,
+ Introduction: v.Introduction,
+ FaceURL: v.FaceURL,
+ CreateTime: v.CreateTime,
+ Ex: v.Ex,
+ Status: v.Status,
+ CreatorUserID: v.CreatorUserID,
+ GroupType: v.GroupType,
+ NeedVerification: v.NeedVerification,
+ LookMemberInfo: v.LookMemberInfo,
+ ApplyMemberFriend: v.ApplyMemberFriend,
+ NotificationUpdateTime: v.NotificationUpdateTime,
+ NotificationUserID: v.NotificationUserID,
+ }
+}
+
+func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMemberModel {
+ return mongoModel.GroupMemberModel{
+ GroupID: v.GroupID,
+ UserID: v.UserID,
+ Nickname: v.Nickname,
+ FaceURL: v.FaceURL,
+ RoleLevel: v.RoleLevel,
+ JoinTime: v.JoinTime,
+ JoinSource: v.JoinSource,
+ InviterUserID: v.InviterUserID,
+ OperatorUserID: v.OperatorUserID,
+ MuteEndTime: v.MuteEndTime,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequestModel {
+ return mongoModel.GroupRequestModel{
+ UserID: v.UserID,
+ GroupID: v.GroupID,
+ HandleResult: v.HandleResult,
+ ReqMsg: v.ReqMsg,
+ HandledMsg: v.HandledMsg,
+ ReqTime: v.ReqTime,
+ HandleUserID: v.HandleUserID,
+ HandledTime: v.HandledTime,
+ JoinSource: v.JoinSource,
+ InviterUserID: v.InviterUserID,
+ Ex: v.Ex,
+ }
+}
+
+func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.ConversationModel {
+ return mongoModel.ConversationModel{
+ OwnerUserID: v.OwnerUserID,
+ ConversationID: v.ConversationID,
+ ConversationType: v.ConversationType,
+ UserID: v.UserID,
+ GroupID: v.GroupID,
+ RecvMsgOpt: v.RecvMsgOpt,
+ IsPinned: v.IsPinned,
+ IsPrivateChat: v.IsPrivateChat,
+ BurnDuration: v.BurnDuration,
+ GroupAtType: v.GroupAtType,
+ AttachedInfo: v.AttachedInfo,
+ Ex: v.Ex,
+ MaxSeq: v.MaxSeq,
+ MinSeq: v.MinSeq,
+ CreateTime: v.CreateTime,
+ IsMsgDestruct: v.IsMsgDestruct,
+ MsgDestructTime: v.MsgDestructTime,
+ LatestMsgDestructTime: v.LatestMsgDestructTime,
+ }
+}
+
+func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
+ return func(v mysqlModel.ObjectModel) mongoModel.ObjectModel {
+ return mongoModel.ObjectModel{
+ Name: v.Name,
+ UserID: v.UserID,
+ Hash: v.Hash,
+ Engine: engine,
+ Key: v.Key,
+ Size: v.Size,
+ ContentType: v.ContentType,
+ Group: v.Cause,
+ CreateTime: v.CreateTime,
+ }
+ }
+}
+
+func (convert) Log(v mysqlModel.Log) mongoModel.LogModel {
+ return mongoModel.LogModel{
+ LogID: v.LogID,
+ Platform: v.Platform,
+ UserID: v.UserID,
+ CreateTime: v.CreateTime,
+ Url: v.Url,
+ FileName: v.FileName,
+ SystemType: v.SystemType,
+ Version: v.Version,
+ Ex: v.Ex,
+ }
+}