Merge branch 'features' of https://github.com/AndrewZuo01/open-im-server into features
commit
709a4af17b
@ -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
|
@ -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
|
@ -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
|
@ -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'
|
@ -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
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
@ -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}))
|
||||
}
|
@ -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}),
|
||||
)
|
||||
}
|
@ -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}))
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
@ -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})
|
||||
}
|
@ -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})
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
@ -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,
|
||||
)
|
||||
}
|
@ -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"
|
@ -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
|
||||
}
|
@ -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,
|
||||
"",
|
||||
)
|
||||
}
|
@ -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, "")
|
||||
}
|
@ -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())
|
||||
}
|
@ -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}
|
||||
}
|
@ -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
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue