diff --git a/config/templates/README.md b/config/templates/README.md new file mode 100644 index 000000000..6a979c6bb --- /dev/null +++ b/config/templates/README.md @@ -0,0 +1,36 @@ +# Examples Directory + +Welcome to the `examples` directory of our project! This directory contains a collection of example files that demonstrate various configurations and setups for our software. These examples are designed to provide you with templates that can be used as a starting point for your own configurations. + +## Overview + +In this directory, you'll find examples for a variety of use cases. Each file is a template with default values and configurations that illustrate best practices and typical scenarios. Whether you're just getting started or looking to implement a complex setup, these examples should help you get on the right track. + +## Structure + +Here's a quick overview of what you'll find in this directory: + ++ `env-example.yaml`: Demonstrates how to set up environment variables. ++ `openim-example.yaml`: A sample configuration file for the OpenIM application. ++ `prometheus-example.yml`: An example Prometheus configuration for monitoring. ++ `alertmanager-example.yml`: A template for setting up Alertmanager configurations. + +## How to Use These Examples + +To use these examples, simply copy the relevant file to your working directory and rename it as needed (e.g., removing the `-example` suffix). Then, modify the file according to your requirements. + +### Tips for Using Example Files: + +1. **Read the Comments**: Each file contains comments that explain various sections and settings. Make sure to read these comments for a better understanding of how to customize the file. +2. **Check for Required Changes**: Some examples might require mandatory changes (like setting specific environment variables) before they can be used effectively. +3. **Version Compatibility**: Ensure that the example files are compatible with the version of the software you are using. + +## Contributing + +If you have a configuration that you believe would be beneficial to others, please feel free to contribute by opening a pull request with your proposed changes. We appreciate contributions that expand our examples with new scenarios and use cases. + +## Support + +If you encounter any issues or have questions regarding the example files, please open an issue on our repository. Our community is here to help you navigate through any challenges you might face. + +Thank you for exploring our examples, and we hope they will be helpful in setting up and configuring your environment! diff --git a/config/templates/alertmanager.yml.template b/config/templates/alertmanager.yml.template new file mode 100644 index 000000000..da5f99b19 --- /dev/null +++ b/config/templates/alertmanager.yml.template @@ -0,0 +1,33 @@ +###################### 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_by: ['alertname'] + group_wait: 5s + group_interval: 5s + repeat_interval: 5m + receiver: email +receivers: + - name: email + email_configs: + - to: 'alert@example.com' + html: '{{ template "email.to.html" . }}' + headers: { Subject: "[OPENIM-SERVER]Alarm" } + send_resolved: true diff --git a/config/templates/config.yaml.template b/config/templates/config.yaml.template new file mode 100644 index 000000000..a35d06c8c --- /dev/null +++ b/config/templates/config.yaml.template @@ -0,0 +1,506 @@ +# 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: '' + +###################### 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://172.28.0.1:10002" + minio: + bucket: "openim" + endpoint: "http://172.28.0.1:10005" + accessKeyID: "root" + secretAccessKey: "openIM123" + sessionToken: '' + signEndpoint: "http://172.28.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 + failedContinue: true + beforeSendGroupMsg: + enable: false + timeout: 5 + failedContinue: true + afterSendGroupMsg: + enable: false + timeout: 5 + failedContinue: true + msgModify: + enable: false + timeout: 5 + failedContinue: true + userOnline: + enable: false + timeout: 5 + failedContinue: true + userOffline: + enable: false + timeout: 5 + failedContinue: true + userKickOff: + enable: false + timeout: 5 + failedContinue: true + 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 + afterCreateGroup: + enable: false + timeout: 5 + failedContinue: true + beforeMemberJoinGroup: + enable: false + timeout: 5 + failedContinue: true + beforeSetGroupMemberInfo: + enable: false + timeout: 5 + failedContinue: true + afterSetGroupMemberInfo: + enable: false + timeout: 5 + failedContinue: true + setMessageReactionExtensions: + enable: false + timeout: 5 + failedContinue: true + quitGroup: + enable: false + timeout: 5 + failedContinue: true + killGroupMember: + enable: false + timeout: 5 + failedContinue: true + dismissGroup: + enable: false + timeout: 5 + failedContinue: true + joinGroup: + enable: false + timeout: 5 + failedContinue: true + groupMsgRead: + enable: false + timeout: 5 + failedContinue: true + singleMsgRead: + enable: false + timeout: 5 + failedContinue: true + updateUserInfo: + enable: false + timeout: 5 + failedContinue: true + beforeUserRegister: + enable: false + timeout: 5 + failedContinue: true + afterUserRegister: + enable: false + timeout: 5 + failedContinue: true + transferGroupOwner: + enable: false + timeout: 5 + failedContinue: true + beforeSetFriendRemark: + enable: false + timeout: 5 + failedContinue: true + afterSetFriendRemark: + enable: false + timeout: 5 + failedContinue: true + afterGroupMsgRead: + enable: false + timeout: 5 + failedContinue: true + afterGroupMsgRevoke: + enable: false + timeout: 5 + failedContinue: true + afterJoinGroup: + enable: false + timeout: 5 + failedContinue: true + beforeInviteUserToGroup: + enable: false + timeout: 5 + failedContinue: true + joinGroupAfter: + enable: false + timeout: 5 + failedContinue: true + setGroupInfoAfter: + enable: false + timeout: 5 + failedContinue: true + setGroupInfoBefore: + enable: false + timeout: 5 + failedContinue: true + revokeMsgAfter: + enable: false + timeout: 5 + failedContinue: true + addBlackBefore: + enable: false + timeout: 5 + failedContinue: true + addFriendAfter: + enable: false + timeout: 5 + failedContinue: true + addFriendAgreeBefore: + enable: false + timeout: 5 + failedContinue: true + deleteFriendAfter: + enable: false + timeout: 5 + failedContinue: true + importFriendsBefore: + enable: false + timeout: 5 + failedContinue: true + importFriendsAfter: + enable: false + timeout: 5 + failedContinue: true + removeBlackAfter: + 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: 172.28.0.1:13000 + apiPrometheusPort: [20100] + userPrometheusPort: [ 20110 ] + friendPrometheusPort: [ 20120 ] + messagePrometheusPort: [ 20130 ] + messageGatewayPrometheusPort: [ 20140 ] + groupPrometheusPort: [ 20150 ] + authPrometheusPort: [ 20160 ] + pushPrometheusPort: [ 20170 ] + conversationPrometheusPort: [ 20230 ] + rtcPrometheusPort: [ 21300 ] + thirdPrometheusPort: [ 21301 ] + messageTransferPrometheusPort: [ 21400, 21401, 21402, 21403 ] # List of ports diff --git a/config/templates/env.template b/config/templates/env.template new file mode 100644 index 000000000..e47a9c073 --- /dev/null +++ b/config/templates/env.template @@ -0,0 +1,249 @@ +# ====================================== +# ========= Basic Configuration ======== +# ====================================== + +# The user for authentication or system operations. +# Default: OPENIM_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 + +MONGO_NETWORK_ADDRESS=172.28.0.2 +REDIS_NETWORK_ADDRESS=172.28.0.3 +KAFKA_NETWORK_ADDRESS=172.28.0.4 +ZOOKEEPER_NETWORK_ADDRESS=172.28.0.5 +MINIO_NETWORK_ADDRESS=172.28.0.6 +OPENIM_WEB_NETWORK_ADDRESS=172.28.0.7 +OPENIM_SERVER_NETWORK_ADDRESS=172.28.0.8 +OPENIM_CHAT_NETWORK_ADDRESS=172.28.0.9 +PROMETHEUS_NETWORK_ADDRESS=172.28.0.10 +GRAFANA_NETWORK_ADDRESS=172.28.0.11 +NODE_EXPORTER_NETWORK_ADDRESS=172.28.0.12 +OPENIM_ADMIN_FRONT_NETWORK_ADDRESS=172.28.0.13 +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.5 + +# Port for ZooKeeper service. +# Default: ZOOKEEPER_PORT=12181 +ZOOKEEPER_PORT=12181 + +# ----- MongoDB Configuration ----- +# Address or hostname for the MongoDB service. +# Default: MONGO_ADDRESS=172.28.0.1 +MONGO_ADDRESS=172.28.0.2 + +# 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.3 + +# 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.4 + +# Kakfa username to authenticate with the Kafka service. +# KAFKA_USERNAME='' + +# 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.6 + +# 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.10 + +# 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.11 + +# Port on which Grafana service is running. +# Default: GRAFANA_PORT=13000 +GRAFANA_PORT=13000 + +# ====================================== +# ============ 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.7 + +# ====================================== +# ========= OpenIM Server ============== +# ====================================== + +# Address or hostname for the OpenIM server. +# Default: OPENIM_SERVER_ADDRESS=172.28.0.1 +OPENIM_SERVER_ADDRESS=172.28.0.8 + +# 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.9 + +# 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=13000 +GRAFANA_PORT=13000 + +# Port for the admin front. +# Default: OPENIM_ADMIN_FRONT_PORT=11002 +OPENIM_ADMIN_FRONT_PORT=11002 + +# Port for the alertmanager. +# Default: ALERT_MANAGER_PORT=19093 +ALERT_MANAGER_PORT=19093 diff --git a/config/templates/prometheus.yml.template b/config/templates/prometheus.yml.template new file mode 100644 index 000000000..7950c5d33 --- /dev/null +++ b/config/templates/prometheus.yml.template @@ -0,0 +1,85 @@ +# my global config +global: + scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. + evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. + # scrape_timeout is set to the global default (10s). + +# Alertmanager configuration +alerting: + alertmanagers: + - static_configs: + - targets: ['172.28.0.1:19093'] + +# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. +rule_files: + - "instance-down-rules.yml" +# - "first_rules.yml" +# - "second_rules.yml" + +# A scrape configuration containing exactly one endpoint to scrape: +# Here it's Prometheus itself. +scrape_configs: + # The job name is added as a label "job='job_name'"" to any timeseries scraped from this config. + # Monitored information captured by prometheus + - job_name: 'node-exporter' + static_configs: + - targets: [ '172.28.0.1:19100' ] + labels: + namespace: 'default' + + # prometheus fetches application services + - job_name: 'openimserver-openim-api' + static_configs: + - targets: [ '172.28.0.1:20100' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-msggateway' + static_configs: + - targets: [ '172.28.0.1:20140' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-msgtransfer' + static_configs: + - targets: [ 172.28.0.1:21400, 172.28.0.1:21401, 172.28.0.1:21402, 172.28.0.1:21403 ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-push' + static_configs: + - targets: [ '172.28.0.1:20170' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-auth' + static_configs: + - targets: [ '172.28.0.1:20160' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-conversation' + static_configs: + - targets: [ '172.28.0.1:20230' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-friend' + static_configs: + - targets: [ '172.28.0.1:20120' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-group' + static_configs: + - targets: [ '172.28.0.1:20150' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-msg' + static_configs: + - targets: [ '172.28.0.1:20130' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-third' + static_configs: + - targets: [ '172.28.0.1:21301' ] + labels: + namespace: 'default' + - job_name: 'openimserver-openim-rpc-user' + static_configs: + - targets: [ '172.28.0.1:20110' ] + labels: + namespace: 'default' diff --git a/deployments/templates/env_template.yaml b/deployments/templates/env-template.yaml similarity index 91% rename from deployments/templates/env_template.yaml rename to deployments/templates/env-template.yaml index 4db838c8e..b62543aba 100644 --- a/deployments/templates/env_template.yaml +++ b/deployments/templates/env-template.yaml @@ -1,17 +1,3 @@ -# 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 ======== # ====================================== @@ -90,11 +76,11 @@ MONGO_ADDRESS=${MONGO_NETWORK_ADDRESS} # Port on which MongoDB service is running. # Default: MONGO_PORT=37017 -MONGO_PORT=${MONGO_PORT} +# MONGO_PORT=${MONGO_PORT} # Username to authenticate with the MongoDB service. # Default: MONGO_USERNAME=root -MONGO_USERNAME=${MONGO_USERNAME} +# MONGO_USERNAME=${MONGO_USERNAME} # Password to authenticate with the MongoDB service. # Default: MONGO_PASSWORD=openIM123 @@ -122,6 +108,9 @@ REDIS_PASSWORD=${REDIS_PASSWORD} # Default: KAFKA_ADDRESS=172.28.0.1 KAFKA_ADDRESS=${KAFKA_NETWORK_ADDRESS} +# Kakfa username to authenticate with the Kafka service. +# KAFKA_USERNAME=${KAFKA_USERNAME} + # Port on which Kafka distributed streaming platform is running. # Default: KAFKA_PORT=19092 KAFKA_PORT=${KAFKA_PORT} @@ -149,7 +138,7 @@ MINIO_PORT=${MINIO_PORT} # Access key to authenticate with the MinIO service. # Default: MINIO_ACCESS_KEY=root -MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} +# MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} # Secret key corresponding to the access key for MinIO authentication. # Default: MINIO_SECRET_KEY=openIM123 diff --git a/docker-compose.yml b/docker-compose.yml index 233c8d492..22f57d329 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,55 +7,57 @@ networks: ipam: driver: default config: - - subnet: '${DOCKER_BRIDGE_SUBNET}' - gateway: '${DOCKER_BRIDGE_GATEWAY}' + - subnet: '${DOCKER_BRIDGE_SUBNET:-172.28.0.0/16}' + gateway: '${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}' services: mongodb: - image: mongo:6.0.2 + image: mongo:${MONGODB_IMAGE_VERSION-6.0.2} ports: - - "${MONGO_PORT}:27017" + - "${MONGO_PORT:-37017}:27017" container_name: mongo command: --wiredTigerCacheSizeGB 1 --auth volumes: - - "${DATA_DIR}/components/mongodb/data/db:/data/db" - - "${DATA_DIR}/components/mongodb/data/logs:/data/logs" - - "${DATA_DIR}/components/mongodb/data/conf:/etc/mongo" - - ./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro" + - "${DATA_DIR:-./}/components/mongodb/data/db:/data/db" + - "${DATA_DIR:-./}/components/mongodb/data/logs:/data/logs" + - "${DATA_DIR:-./}/components/mongodb/data/conf:/etc/mongo" + - ./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro environment: - TZ=Asia/Shanghai - wiredTigerCacheSizeGB=1 - - MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME} - - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD} - - MONGO_INITDB_DATABASE=${MONGO_DATABASE} + - MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME:-root} + - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD:-openIM123} + - MONGO_INITDB_DATABASE=${MONGO_DATABASE:-openIM_v3} restart: always networks: server: - ipv4_address: ${MONGO_NETWORK_ADDRESS} + ipv4_address: ${MONGO_NETWORK_ADDRESS:-172.28.0.2} redis: - image: redis:7.0.0 + # image: redis:7.0.0 + image: redis:${REDIS_IMAGE_VERSION:-7.0.0} container_name: redis ports: - - "${REDIS_PORT}:6379" + - "${REDIS_PORT:-16379}:6379" volumes: - - "${DATA_DIR}/components/redis/data:/data" - - "${DATA_DIR}/components/redis/config/redis.conf:/usr/local/redis/config/redis.conf" + - "${DATA_DIR:-./}/components/redis/data:/data" + - "${DATA_DIR:-./}/components/redis/config/redis.conf:/usr/local/redis/config/redis.conf" environment: TZ: Asia/Shanghai restart: always sysctls: net.core.somaxconn: 1024 - command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes + command: redis-server --requirepass ${REDIS_PASSWORD:-openIM123} --appendonly yes networks: server: - ipv4_address: ${REDIS_NETWORK_ADDRESS} + ipv4_address: ${REDIS_NETWORK_ADDRESS:-172.28.0.3} zookeeper: - image: bitnami/zookeeper:3.8 + # image: bitnami/zookeeper:3.8 + image: bitnami/zookeeper:${ZOOKEEPER_IMAGE_VERSION:-3.8} container_name: zookeeper ports: - - "${ZOOKEEPER_PORT}:2181" + - "${ZOOKEEPER_PORT:-12181}:2181" volumes: - "/etc/localtime:/etc/localtime" environment: @@ -64,81 +66,77 @@ services: restart: always networks: server: - ipv4_address: ${ZOOKEEPER_NETWORK_ADDRESS} + ipv4_address: ${ZOOKEEPER_NETWORK_ADDRESS:-172.28.0.5} kafka: - image: 'bitnami/kafka:3.5.1' + # image: 'bitnami/kafka:3.5.1' + image: 'bitnami/kafka:${KAFKA_IMAGE_VERSION:-3.5.1}' container_name: kafka - user: root restart: always + user: ${KAFKA_USER:-root} ports: - - "${KAFKA_PORT}:9094" + - "${KAFKA_PORT:-19094}:9094" volumes: - ./scripts/create-topic.sh:/opt/bitnami/kafka/create-topic.sh - - ${DATA_DIR}/components/kafka:/bitnami/kafka + - "${DATA_DIR:-./}/components/kafka:/bitnami/kafka" command: > - bash -c " - /opt/bitnami/scripts/kafka/run.sh & sleep 5; /opt/bitnami/kafka/create-topic.sh; wait - " + bash -c "/opt/bitnami/scripts/kafka/run.sh & sleep 5; /opt/bitnami/kafka/create-topic.sh; wait" environment: - TZ=Asia/Shanghai - KAFKA_CFG_NODE_ID=0 - KAFKA_CFG_PROCESS_ROLES=controller,broker - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@:9093 - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094 - - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://${DOCKER_BRIDGE_GATEWAY}:${KAFKA_PORT} + - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://${DOCKER_BRIDGE_GATEWAY:-172.28.0.1}:${KAFKA_PORT:-19094} - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER networks: server: - ipv4_address: ${KAFKA_NETWORK_ADDRESS} + ipv4_address: ${KAFKA_NETWORK_ADDRESS:-172.28.0.4} minio: - image: minio/minio + # image: minio/minio + image: minio/minio:${MINIO_IMAGE_VERSION:-latest} ports: - - "${MINIO_PORT}:9000" + - "${MINIO_PORT:-10005}:9000" - "9090:9090" container_name: minio volumes: - - "${DATA_DIR}/components/mnt/data:/data" - - "${DATA_DIR}/components/mnt/config:/root/.minio" + - "${DATA_DIR:-./}/components/mnt/data:/data" + - "${DATA_DIR:-./}/components/mnt/config:/root/.minio" environment: - MINIO_ROOT_USER: "${MINIO_ACCESS_KEY}" - MINIO_ROOT_PASSWORD: "${MINIO_SECRET_KEY}" + MINIO_ROOT_USER: "${MINIO_ACCESS_KEY:-root}" + MINIO_ROOT_PASSWORD: "${MINIO_SECRET_KEY:-openIM123}" restart: always command: minio server /data --console-address ':9090' networks: server: - ipv4_address: ${MINIO_NETWORK_ADDRESS} + ipv4_address: ${MINIO_NETWORK_ADDRESS:-172.28.0.6} openim-web: - # image: ghcr.io/openimsdk/openim-web:latest - # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web:latest - # image: openim/openim-web:latest - image: ${IMAGE_REGISTRY}/openim-web:latest + # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:latest + image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-web:${OPENIM_WEB_IMAGE_VERSION:-latest} container_name: openim-web environment: - - OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH} - - OPENIM_WEB_PORT=${OPENIM_WEB_PORT} + - OPENIM_WEB_DIST_PATH=${OPENIM_WEB_DIST_PATH:-/app/dist} + - OPENIM_WEB_PORT=${OPENIM_WEB_PORT:-11001} restart: always ports: - - "${OPENIM_WEB_PORT}:11001" + - "${OPENIM_WEB_PORT:-11001}:11001" networks: server: - ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS} + ipv4_address: ${OPENIM_WEB_NETWORK_ADDRESS:-172.28.0.7} + # Uncomment and configure the following services as needed # openim-admin: - # image: ${IMAGE_REGISTRY}/openim-admin-front:v3.4.0 - # # image: ghcr.io/openimsdk/openim-admin-front:v3.4.0 - # # image: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:v3.4.0 - # # image: openim/openim-admin-front:v3.4.0 + # image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-admin-front:v3.4.0 # container_name: openim-admin # restart: always # ports: - # - "${OPENIM_ADMIN_FRONT_PORT}:80" + # - "${OPENIM_ADMIN_FRONT_PORT:-11002}:80" # networks: # server: - # ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS} + # ipv4_address: ${OPENIM_ADMIN_FRONT_NETWORK_ADDRESS:-172.28.0.13} # prometheus: # image: prom/prometheus @@ -149,10 +147,10 @@ services: # - ./config/prometheus.yml:/etc/prometheus/prometheus.yml # - ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml # ports: - # - "${PROMETHEUS_PORT}:9090" + # - "${PROMETHEUS_PORT:-19090}:9090" # networks: # server: - # ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS} + # ipv4_address: ${PROMETHEUS_NETWORK_ADDRESS:-172.28.0.10} # alertmanager: # image: prom/alertmanager @@ -163,10 +161,10 @@ services: # - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml # - ./config/email.tmpl:/etc/alertmanager/email.tmpl # ports: - # - "${ALERT_MANAGER_PORT}:9093" + # - "${ALERT_MANAGER_PORT:-19093}:9093" # networks: # server: - # ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS} + # ipv4_address: ${ALERT_MANAGER_NETWORK_ADDRESS:-172.28.0.14} # grafana: # image: grafana/grafana @@ -175,12 +173,12 @@ services: # user: root # restart: always # ports: - # - "${GRAFANA_PORT}:3000" + # - "${GRAFANA_PORT:-13000}:3000" # volumes: - # - ${DATA_DIR}/components/grafana:/var/lib/grafana + # - ${DATA_DIR:-./}/components/grafana:/var/lib/grafana # networks: # server: - # ipv4_address: ${GRAFANA_NETWORK_ADDRESS} + # ipv4_address: ${GRAFANA_NETWORK_ADDRESS:-172.28.0.11} # node-exporter: # image: quay.io/prometheus/node-exporter @@ -188,7 +186,7 @@ services: # hostname: node-exporter # restart: always # ports: - # - "${NODE_EXPORTER_PORT}:9100" + # - "${NODE_EXPORTER_PORT:-19100}:9100" # networks: # server: - # ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS} + # ipv4_address: ${NODE_EXPORTER_NETWORK_ADDRESS:-172.28.0.12} diff --git a/docs/contrib/bash-log.md b/docs/contrib/bash-log.md index 86acb1d33..7725d5589 100644 --- a/docs/contrib/bash-log.md +++ b/docs/contrib/bash-log.md @@ -11,7 +11,7 @@ OpenIM, an intricate project, requires a robust logging mechanism to diagnose is 1. **Initialization**: The system begins by determining the verbosity level through the `OPENIM_VERBOSE` variable. If it's not set, a default value of 5 is assigned. This verbosity level dictates the depth of the log details. 2. **Log File Setup**: Logs are stored in the directory specified by `OPENIM_OUTPUT`. If this variable isn't explicitly set, it defaults to the `_output` directory relative to the script location. Each log file is named based on the date to facilitate easy identification. 3. **Logging Function**: The `echo_log()` function plays a pivotal role by writing messages to both the console (stdout) and the log file. -4. **Logging to a file**: The `echo_log()` function writes to the log file by appending the message to the file. It also adds a timestamp to the message. path: `_output/logs/*`, Enable logging by default. Set to false to disable. If you wish to turn off output to log files set `ENABLE_LOGGING=flase`. +4. **Logging to a file**: The `echo_log()` function writes to the log file by appending the message to the file. It also adds a timestamp to the message. path: `_output/logs/*`, Enable logging by default. Set to false to disable. If you wish to turn off output to log files set `export ENABLE_LOGGING=flase`. ### Key Functions & Their Usages diff --git a/docs/contrib/util-makefile.md b/docs/contrib/util-makefile.md index e0331f50e..8bde02874 100644 --- a/docs/contrib/util-makefile.md +++ b/docs/contrib/util-makefile.md @@ -30,7 +30,7 @@ Executing `make tools` ensures verification and installation of the default tool - go-junit-report - go-gitlint -The installation path is situated at `/root/workspaces/openim/Open-IM-Server/_output/tools/`. +The installation path is situated at `./_output/tools/`. ## Toolset Categories diff --git a/go.sum b/go.sum index 2f9198c9f..30e4b3cb4 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c= github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= github.com/OpenIMSDK/protocol v0.0.31 h1:ax43x9aqA6EKNXNukS5MT5BSTqkUmwO4uTvbJLtzCgE= github.com/OpenIMSDK/protocol v0.0.31/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= -github.com/OpenIMSDK/tools v0.0.18 h1:h3CvKB90DNd2aIJcOQ99cqgeW6C0na0PzR1TNsfxwL0= -github.com/OpenIMSDK/tools v0.0.18/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= +github.com/OpenIMSDK/tools v0.0.20 h1:zBTjQZRJ5lR1FIzP9mtWyAvh5dKsmJXQugi4p8X/97k= +github.com/OpenIMSDK/tools v0.0.20/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= diff --git a/install_guide.sh b/install_guide.sh deleted file mode 100755 index c4323d6a8..000000000 --- a/install_guide.sh +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env bash - -echo "Welcome to the Open-IM-Server installation scripts." -echo "Please select an deploy option:" -echo "1. docker-compose install" -echo "2. exit" - -clear_openimlog() { - rm -rf ./logs/* -} - -is_path() { - if [ -e "$1" ]; then - return 1 - else - return 0 - fi -} - -is_empty() { - if [ -z "$1" ]; then - return 1 - else - return 0 - fi -} - -is_directory_exists() { - if [ -d "$1" ]; then - return 1 - else - return 0 - fi -} - -edit_config() { - echo "Is edit config.yaml?" - echo "1. vi edit config" - echo "2. do not edit config" - read choice - case $choice in - 1) - vi config/config.yaml - ;; - 2) - echo "do not edit config" - ;; - esac -} - -edit_enterprise_config() { - echo "Is edit enterprise config.yaml?" - echo "1. vi edit enterprise config" - echo "2. do not edit enterprise config" - read choice - case $choice in - 1) - vi ./.docker-compose_cfg/config.yaml - ;; - 2) - echo "Do not edit enterprise config" - ;; - esac -} - -install_docker_compose() { - echo "Please input the installation path, default is $(pwd)/Open-IM-Server, press enter to use default" - read install_path - is_empty $install_path - if [ $? -eq 1 ]; then - install_path="." - fi - echo "Installing Open-IM-Server to ${install_path}/Open-IM-Server..." - is_path $install_path - mkdir -p $install_path - cd $install_path - is_directory_exists "${install_path}/Open-IM-Server" - if [ $? -eq 1 ]; then - echo "WARNING: Directory $install_path/Open-IM-Server exist, please ensure your path" - echo "1. delete the directory and install" - echo "2. exit" - read choice - case $choice in - 1) - rm -rf "${install_path}/Open-IM-Server" - ;; - 2) - exit 1 - ;; - esac - fi - rm -rf ./Open-IM-Server - set -e - git clone https://github.com/openimsdk/open-im-server.git --recursive; - set +e - cd ./Open-IM-Server - git checkout errcode - echo "======== git clone success ========" - source .env - if [ $DATA_DIR = "./" ]; then - DATA_DIR=$(pwd)/components - fi - echo "Please input the components data directory, deault is ${DATA_DIR}, press enter to use default" - read NEW_DATA_DIR - is_empty $NEW_DATA_DIR - if [ $? -eq 0 ]; then - DATA_DIR=$NEW_DATA_DIR - fi - echo "Please input the user, deault is root, press enter to use default" - read NEW_USER - is_empty $NEW_USER - if [ $? -eq 0 ]; then - OPENIM_USER=$NEW_USER - fi - - echo "Please input the password, default is openIM123, press enter to use default" - read NEW_PASSWORD - is_empty $NEW_PASSWORD - if [ $? -eq 0 ]; then - PASSWORD=$NEW_PASSWORD - fi - - echo "Please input the minio_endpoint, default will detect auto, press enter to use default" - read NEW_MINIO_ENDPOINT - is_empty $NEW_MINIO_ENDPOINT - if [ $? -eq 1 ]; then - internet_ip=`curl ifconfig.me -s` - MINIO_ENDPOINT="http://${internet_ip}:10005" - else - MINIO_ENDPOINT=$NEW_MINIO_ENDPOINT - fi - set -e - export MINIO_ENDPOINT - export OPENIM_USER - export PASSWORD - export DATA_DIR - - cat < .env -OPENIM_USER=${OPENIM_USER} -PASSWORD=${PASSWORD} -MINIO_ENDPOINT=${MINIO_ENDPOINT} -DATA_DIR=${DATA_DIR} -EOF - - edit_config - edit_enterprise_config - - cd scripts; - chmod +x *.sh; - ./init-pwd.sh; - ./env_check.sh; - cd ..; - docker-compose up -d; - cd scripts; - ./docker-check-service.sh; -} - -read choice - -case $choice in - 1) - install_docker_compose - ;; - 2) - - ;; - 3) - ;; - 4) - echo "Exiting installation scripts..." - exit 0 - ;; - *) - echo "Invalid option, please try again." - ;; -esac diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index 24c4d7e58..fcdcc7d98 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -52,6 +52,10 @@ type friendServer struct { RegisterCenter registry.SvcDiscoveryRegistry } +func (s *friendServer) PinFriends(ctx context.Context, req *pbfriend.PinFriendsReq) (*pbfriend.PinFriendsResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { // Initialize MongoDB mongo, err := unrelation.NewMongo() diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go index 49113aa0b..061498abb 100644 --- a/internal/rpc/msg/as_read.go +++ b/internal/rpc/msg/as_read.go @@ -16,14 +16,12 @@ package msg import ( "context" - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" - utils2 "github.com/OpenIMSDK/tools/utils" "github.com/redis/go-redis/v9" + cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/OpenIMSDK/protocol/constant" - "github.com/OpenIMSDK/protocol/conversation" "github.com/OpenIMSDK/protocol/msg" "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/errs" @@ -92,7 +90,10 @@ func (m *msgServer) SetConversationHasReadSeq( return &msg.SetConversationHasReadSeqResp{}, nil } -func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadReq) (resp *msg.MarkMsgsAsReadResp, err error) { +func (m *msgServer) MarkMsgsAsRead( + ctx context.Context, + req *msg.MarkMsgsAsReadReq, +) (resp *msg.MarkMsgsAsReadResp, err error) { if len(req.Seqs) < 1 { return nil, errs.ErrArgs.Wrap("seqs must not be empty") } @@ -111,6 +112,7 @@ func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadR if err = m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, req.Seqs); err != nil { return } + currentHasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID) if err != nil && errs.Unwrap(err) != redis.Nil { return @@ -128,7 +130,10 @@ func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadR return &msg.MarkMsgsAsReadResp{}, nil } -func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkConversationAsReadReq) (resp *msg.MarkConversationAsReadResp, err error) { +func (m *msgServer) MarkConversationAsRead( + ctx context.Context, + req *msg.MarkConversationAsReadReq, +) (resp *msg.MarkConversationAsReadResp, err error) { conversation, err := m.Conversation.GetConversation(ctx, req.UserID, req.ConversationID) if err != nil { return nil, err @@ -137,34 +142,54 @@ func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkCon if err != nil && errs.Unwrap(err) != redis.Nil { return nil, err } - seqs := generateSeqs(hasReadSeq, req) + var seqs []int64 - if len(seqs) > 0 || req.HasReadSeq > hasReadSeq { - err = m.updateReadStatus(ctx, req, conversation, seqs, hasReadSeq) - if err != nil { + log.ZDebug(ctx, "MarkConversationAsRead", "hasReadSeq", hasReadSeq, + "req.HasReadSeq", req.HasReadSeq) + if conversation.ConversationType == constant.SingleChatType { + for i := hasReadSeq + 1; i <= req.HasReadSeq; i++ { + seqs = append(seqs, i) + } + //avoid client missed call MarkConversationMessageAsRead by order + for _, val := range req.Seqs { + if !utils2.Contain(val, seqs...) { + seqs = append(seqs, val) + } + } + if len(seqs) > 0 { + log.ZDebug(ctx, "MarkConversationAsRead", "seqs", seqs, "conversationID", req.ConversationID) + if err = m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, seqs); err != nil { + return nil, err + } + } + if req.HasReadSeq > hasReadSeq { + err = m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq) + if err != nil { + return nil, err + } + hasReadSeq = req.HasReadSeq + } + if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID, + m.conversationAndGetRecvID(conversation, req.UserID), seqs, hasReadSeq); err != nil { return nil, err } - } - return &msg.MarkConversationAsReadResp{}, nil -} - -func generateSeqs(hasReadSeq int64, req *msg.MarkConversationAsReadReq) []int64 { - var seqs []int64 - for _, val := range req.Seqs { - if val > hasReadSeq && !utils2.Contain(val, seqs...) { - seqs = append(seqs, val) + + } else if conversation.ConversationType == constant.SuperGroupChatType || + conversation.ConversationType == constant.NotificationChatType { + if req.HasReadSeq > hasReadSeq { + err = m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq) + if err != nil { + return nil, err + } + hasReadSeq = req.HasReadSeq } - } - return seqs -} - -func (m *msgServer) updateReadStatus(ctx context.Context, req *msg.MarkConversationAsReadReq, conversation *conversation.Conversation, seqs []int64, hasReadSeq int64) error { - if conversation.ConversationType == constant.SingleChatType && len(seqs) > 0 { - log.ZDebug(ctx, "MarkConversationAsRead", "seqs", seqs, "conversationID", req.ConversationID) - if err := m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, seqs); err != nil { - return err + if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID, + req.UserID, seqs, hasReadSeq); err != nil { + return nil, err } + } + reqCall := &cbapi.CallbackGroupMsgReadReq{ SendID: conversation.OwnerUserID, ReceiveID: req.UserID, @@ -172,21 +197,10 @@ func (m *msgServer) updateReadStatus(ctx context.Context, req *msg.MarkConversat ContentType: int64(conversation.ConversationType), } if err := CallbackGroupMsgRead(ctx, reqCall); err != nil { - return err - } - - if req.HasReadSeq > hasReadSeq { - if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil { - return err - } - } - - recvID := m.conversationAndGetRecvID(conversation, req.UserID) - if conversation.ConversationType == constant.SuperGroupChatType || conversation.ConversationType == constant.NotificationChatType { - recvID = req.UserID + return nil, err } - return m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID, recvID, seqs, req.HasReadSeq) + return &msg.MarkConversationAsReadResp{}, nil } func (m *msgServer) sendMarkAsReadNotification( @@ -208,4 +222,4 @@ func (m *msgServer) sendMarkAsReadNotification( log.ZWarn(ctx, "send has read Receipt err", err) } return nil -} +} \ No newline at end of file diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index 51e277e8c..cde975a6e 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -56,6 +56,22 @@ type userServer struct { RegisterCenter registry.SvcDiscoveryRegistry } +func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + +func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + +func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + +func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) { + return nil, errs.ErrInternalServer.Wrap("not implemented") +} + func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { rdb, err := cache.NewRedis() if err != nil { diff --git a/scripts/init-config.sh b/scripts/init-config.sh index f20fc7e73..631bd68d7 100755 --- a/scripts/init-config.sh +++ b/scripts/init-config.sh @@ -2,7 +2,7 @@ # 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 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 @@ -13,64 +13,173 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This script automatically initializes the various configuration files -# Read: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/init-config.md +# This script automatically initializes various configuration files and can generate example files. set -o errexit set -o nounset set -o pipefail +# Root directory of the OpenIM project OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +# Source initialization script source "${OPENIM_ROOT}/scripts/lib/init.sh" -# (en: Define a profile array that contains the name path of the profile to be generated.) +# Default environment file readonly ENV_FILE=${ENV_FILE:-"${OPENIM_ROOT}/scripts/install/environment.sh"} -# (en: Defines an associative array where the keys are the template files and the values are the corresponding output files.) +# Templates for configuration files declare -A TEMPLATES=( - ["${OPENIM_ROOT}/deployments/templates/env_template.yaml"]="${OPENIM_ROOT}/.env" + ["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/.env" ["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/config.yaml" ["${OPENIM_ROOT}/deployments/templates/prometheus.yml"]="${OPENIM_ROOT}/config/prometheus.yml" ["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/alertmanager.yml" ) -openim::log::info "Read more configuration information: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md" +# Templates for example files +declare -A EXAMPLES=( + ["${OPENIM_ROOT}/deployments/templates/env-template.yaml"]="${OPENIM_ROOT}/config/templates/env.template" + ["${OPENIM_ROOT}/deployments/templates/openim.yaml"]="${OPENIM_ROOT}/config/templates/config.yaml.template" + ["${OPENIM_ROOT}/deployments/templates/prometheus.yml"]="${OPENIM_ROOT}/config/templates/prometheus.yml.template" + ["${OPENIM_ROOT}/deployments/templates/alertmanager.yml"]="${OPENIM_ROOT}/config/templates/alertmanager.yml.template" +) -for template in "${!TEMPLATES[@]}"; do - if [[ ! -f "${template}" ]]; then - openim::log::error_exit "Template file ${template} does not exist..." - exit 1 - fi -done +# Command-line options +FORCE_OVERWRITE=false +SKIP_EXISTING=false +GENERATE_EXAMPLES=false +CLEAN_ENV_EXAMPLES=false + +# Function to display help information +show_help() { + echo "Usage: $(basename "$0") [options]" + echo "Options:" + echo " -h, --help Show this help message" + echo " --force Overwrite existing files without prompt" + echo " --skip Skip generation if file exists" + echo " --examples Generate example files" + echo " --clean-env-examples Generate example files in a clean environment" +} -for template in "${!TEMPLATES[@]}"; do - IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}" - for output_file in "${OUTPUT_FILES[@]}"; do - if [[ -f "${output_file}" ]]; then - echo -n "File ${output_file} already exists. Overwrite? (Y/N): " - read -r -n 1 REPLY - echo # Adds a line to wrap after user input - if [[ $REPLY =~ ^[Yy]$ ]]; then - openim::log::info "Overwriting ${output_file}. Previous configuration will be lost." - else - openim::log::info "Skipping generation of ${output_file}." - continue +# Function to generate configuration files +generate_config_files() { + # Loop through each template in TEMPLATES + for template in "${!TEMPLATES[@]}"; do + # Read the corresponding output files for the template + IFS=';' read -ra OUTPUT_FILES <<< "${TEMPLATES[$template]}" + for output_file in "${OUTPUT_FILES[@]}"; do + # Check if the output file already exists + if [[ -f "${output_file}" ]]; then + # Handle existing file based on command-line options + if [[ "${FORCE_OVERWRITE}" == true ]]; then + openim::log::info "Force overwriting ${output_file}." + elif [[ "${SKIP_EXISTING}" == true ]]; then + openim::log::info "Skipping generation of ${output_file} as it already exists." + continue + else + # Ask user for confirmation to overwrite + echo -n "File ${output_file} already exists. Overwrite? (Y/N): " + read -r -n 1 REPLY + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + openim::log::info "Skipping generation of ${output_file}." + continue + fi + fi fi - fi - openim::log::info "⌚ Working with template file: ${template} to ${output_file}..." - if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then - openim::log::error "genconfig.sh script not found" - exit 1 + # Process the template file to generate the output file + openim::log::info "⌚ Working with template file: ${template} to generate ${output_file}..." + if [[ ! -f "${OPENIM_ROOT}/scripts/genconfig.sh" ]]; then + openim::log::error "genconfig.sh script not found" + exit 1 + fi + "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || { + openim::log::error "Error processing template file ${template}" + exit 1 + } + sleep 0.5 + done + done +} + +# Function to generate example files +generate_example_files() { + for template in "${!EXAMPLES[@]}"; do + local example_file="${EXAMPLES[$template]}" + if [[ ! -f "${example_file}" ]]; then + openim::log::info "Generating example file: ${example_file} from ${template}..." + cp "${template}" "${example_file}" fi - "${OPENIM_ROOT}/scripts/genconfig.sh" "${ENV_FILE}" "${template}" > "${output_file}" || { + done +} + +declare -A env_vars=( + ["OPENIM_IP"]="172.28.0.1" + ["DATA_DIR"]="./" + ["LOG_STORAGE_LOCATION"]="../logs/" +) + +generate_clean_environment_examples() { + env_cmd="env -i" + for var in "${!env_vars[@]}"; do + env_cmd+=" $var='${env_vars[$var]}'" + done + + for template in "${!EXAMPLES[@]}"; do + local example_file="${EXAMPLES[$template]}" + openim::log::info "Generating example file: ${example_file} from ${template}..." + + eval "$env_cmd ${OPENIM_ROOT}/scripts/genconfig.sh '${ENV_FILE}' '${template}' > '${example_file}'" || { openim::log::error "Error processing template file ${template}" exit 1 } - sleep 0.5 done +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + show_help + exit 0 + ;; + --force) + FORCE_OVERWRITE=true + shift + ;; + --skip) + SKIP_EXISTING=true + shift + ;; + --examples) + GENERATE_EXAMPLES=true + shift + ;; + --clean-env-examples) + CLEAN_ENV_EXAMPLES=true + shift + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac done +# Generate configuration files if requested +if [[ "${FORCE_OVERWRITE}" == true || "${SKIP_EXISTING}" == false ]]; then + generate_config_files +fi + +# Generate example files if --examples option is provided +if [[ "${GENERATE_EXAMPLES}" == true ]]; then + generate_example_files +fi + +# Generate example files in a clean environment if --clean-env-examples option is provided +if [[ "${CLEAN_ENV_EXAMPLES}" == true ]]; then + generate_clean_environment_examples +fi -openim::log::success "✨ All configuration files have been successfully generated!" +openim::log::success "Configuration and example files generation complete!" \ No newline at end of file diff --git a/scripts/install/openim-api.sh b/scripts/install/openim-api.sh index a40e23611..9f66d0ba0 100755 --- a/scripts/install/openim-api.sh +++ b/scripts/install/openim-api.sh @@ -66,7 +66,7 @@ function openim::api::start() { for ((j = 0; j < ${#OPENIM_API_SERVICE_PORTS[@]}; j++)); do openim::log::info "Starting ${OPENIM_API_SERVICE_LISTARIES[$i]} service, port: ${OPENIM_API_SERVICE_PORTS[j]}, binary root: ${OPENIM_OUTPUT_HOSTBIN}/${OPENIM_API_SERVICE_LISTARIES[$i]}" openim::api::start_service "${OPENIM_API_SERVICE_LISTARIES[$i]}" "${OPENIM_API_PORT_LISTARIES[j]}" - sleep 1 + sleep 2 done done diff --git a/scripts/install/openim-rpc.sh b/scripts/install/openim-rpc.sh index bd00ff9f2..b66004191 100755 --- a/scripts/install/openim-rpc.sh +++ b/scripts/install/openim-rpc.sh @@ -138,7 +138,7 @@ function openim::rpc::start() { done done - sleep 0.5 + sleep 1 openim::util::check_ports ${OPENIM_RPC_PORT_TARGETS[@]} # openim::util::check_ports ${OPENIM_RPC_PROM_PORT_TARGETS[@]} diff --git a/scripts/lib/logging.sh b/scripts/lib/logging.sh index 90f9d0c7f..9d28aa284 100755 --- a/scripts/lib/logging.sh +++ b/scripts/lib/logging.sh @@ -17,7 +17,7 @@ OPENIM_VERBOSE="${OPENIM_VERBOSE:-5}" # Enable logging by default. Set to false to disable. -ENABLE_LOGGING=true +ENABLE_LOGGING="${ENABLE_LOGGING:-true}" # If OPENIM_OUTPUT is not set, set it to the default value if [[ ! -v OPENIM_OUTPUT ]]; then diff --git a/tools/data-conversion/go.mod b/tools/data-conversion/go.mod index b0d7aea13..37d1776c2 100644 --- a/tools/data-conversion/go.mod +++ b/tools/data-conversion/go.mod @@ -3,16 +3,16 @@ module github.com/openimsdk/open-im-server/v3/tools/data-conversion go 1.19 require ( - github.com/IBM/sarama v1.41.2 - github.com/OpenIMSDK/protocol v0.0.23 - github.com/OpenIMSDK/tools v0.0.14 + github.com/IBM/sarama v1.42.1 + github.com/OpenIMSDK/protocol v0.0.33 + github.com/OpenIMSDK/tools v0.0.20 github.com/golang/protobuf v1.5.3 - github.com/openimsdk/open-im-server/v3 v3.3.2 - golang.org/x/net v0.17.0 - google.golang.org/grpc v1.57.0 + github.com/openimsdk/open-im-server/v3 v3.4.0 + golang.org/x/net v0.19.0 + google.golang.org/grpc v1.60.0 google.golang.org/protobuf v1.31.0 - gorm.io/driver/mysql v1.5.1 - gorm.io/gorm v1.25.4 + gorm.io/driver/mysql v1.5.2 + gorm.io/gorm v1.25.5 ) require ( @@ -28,7 +28,7 @@ require ( github.com/gin-gonic/gin v1.9.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.15.3 // indirect + github.com/go-playground/validator/v10 v10.15.5 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -63,10 +63,10 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/image v0.12.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect + golang.org/x/crypto v0.16.0 // indirect + golang.org/x/image v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tools/data-conversion/go.sum b/tools/data-conversion/go.sum index 9223f6e36..66f85785b 100644 --- a/tools/data-conversion/go.sum +++ b/tools/data-conversion/go.sum @@ -1,9 +1,9 @@ -github.com/IBM/sarama v1.41.2 h1:ZDBZfGPHAD4uuAtSv4U22fRZBgst0eEwGFzLj0fb85c= -github.com/IBM/sarama v1.41.2/go.mod h1:xdpu7sd6OE1uxNdjYTSKUfY8FaKkJES9/+EyjSgiGQk= -github.com/OpenIMSDK/protocol v0.0.23 h1:L545aRQez6Ro+AaJB1Z6Mz7ojnDtp41WqASxYveCkcE= -github.com/OpenIMSDK/protocol v0.0.23/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= -github.com/OpenIMSDK/tools v0.0.14 h1:WLof/+WxyPyRST+QkoTKubYCiV73uCLiL8pgnpH/yKQ= -github.com/OpenIMSDK/tools v0.0.14/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= +github.com/IBM/sarama v1.42.1 h1:wugyWa15TDEHh2kvq2gAy1IHLjEjuYOYgXz/ruC/OSQ= +github.com/IBM/sarama v1.42.1/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= +github.com/OpenIMSDK/protocol v0.0.33 h1:T07KWD0jt7IRlrYRujCa+eXmfgcSi8sRgLL8t2ZlHQA= +github.com/OpenIMSDK/protocol v0.0.33/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= +github.com/OpenIMSDK/tools v0.0.20 h1:zBTjQZRJ5lR1FIzP9mtWyAvh5dKsmJXQugi4p8X/97k= +github.com/OpenIMSDK/tools v0.0.20/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= @@ -34,8 +34,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.15.3 h1:S+sSpunYjNPDuXkWbK+x+bA7iXiW296KG4dL3X7xUZo= -github.com/go-playground/validator/v10 v10.15.3/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= +github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= @@ -47,7 +47,7 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= @@ -103,8 +103,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/openimsdk/open-im-server/v3 v3.3.2 h1:uK6glaidrnWlYXFSwzOEq7fXS6jT1OyesUJENZJeptI= -github.com/openimsdk/open-im-server/v3 v3.3.2/go.mod h1:rqKiCkjav5P7tQmyqaixnMJcayWlM4XtXmwG+cZNw78= +github.com/openimsdk/open-im-server/v3 v3.4.0 h1:e7nslaWEHYc5xD1A3zHtnhbIWgfgtJSnPGHIqwjARaE= +github.com/openimsdk/open-im-server/v3 v3.4.0/go.mod h1:HKqjLZSMjD7ec59VV694Yfqnj9SIVotzDSPWgAei2Tg= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= @@ -146,24 +146,22 @@ golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= -golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= +golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -171,8 +169,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -180,18 +178,17 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= +google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= @@ -202,9 +199,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw= -gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= -gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= -gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs= +gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8= +gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/tools/up35/go.mod b/tools/up35/go.mod index 5ae3907bf..23163a4dc 100644 --- a/tools/up35/go.mod +++ b/tools/up35/go.mod @@ -1,51 +1,3 @@ module github.com/openimsdk/open-im-server/v3/tools/up35 go 1.19 - -require ( - github.com/go-sql-driver/mysql v1.7.1 - github.com/openimsdk/open-im-server/v3 v3.5.0 - github.com/openimsdk/open-im-server/v3/tools/data-conversion v0.0.0-00010101000000-000000000000 - go.mongodb.org/mongo-driver v1.12.1 - gopkg.in/yaml.v3 v3.0.1 - gorm.io/driver/mysql v1.5.1 - gorm.io/gorm v1.25.4 -) - -require ( - github.com/OpenIMSDK/protocol v0.0.31 // indirect - github.com/OpenIMSDK/tools v0.0.18 // indirect - github.com/bwmarrin/snowflake v0.3.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/jinzhu/copier v0.4.0 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.16.7 // indirect - github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect - github.com/lestrrat-go/strftime v1.0.6 // indirect - github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect - github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/xdg-go/pbkdf2 v1.0.0 // indirect - github.com/xdg-go/scram v1.1.2 // indirect - github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/image v0.13.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect -) - -replace ( - github.com/openimsdk/open-im-server/v3 => ./../../../open-im-server - github.com/openimsdk/open-im-server/v3/tools/data-conversion => ./../data-conversion -) diff --git a/tools/up35/pkg/convert.go b/tools/up35/pkg/convert.go new file mode 100644 index 000000000..91fdb474e --- /dev/null +++ b/tools/up35/pkg/convert.go @@ -0,0 +1,227 @@ +package pkg + +import ( + mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3" + mongoModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + mysqlModelRtc "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mysql" + "time" +) + +type convert struct{} + +func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel { + return mongoModel.UserModel{ + UserID: v.UserID, + Nickname: v.Nickname, + FaceURL: v.FaceURL, + Ex: v.Ex, + AppMangerLevel: v.AppMangerLevel, + GlobalRecvMsgOpt: v.GlobalRecvMsgOpt, + CreateTime: v.CreateTime, + } +} + +func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel { + return mongoModel.FriendModel{ + OwnerUserID: v.OwnerUserID, + FriendUserID: v.FriendUserID, + Remark: v.Remark, + CreateTime: v.CreateTime, + AddSource: v.AddSource, + OperatorUserID: v.OperatorUserID, + Ex: v.Ex, + } +} + +func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendRequestModel { + return mongoModel.FriendRequestModel{ + FromUserID: v.FromUserID, + ToUserID: v.ToUserID, + HandleResult: v.HandleResult, + ReqMsg: v.ReqMsg, + CreateTime: v.CreateTime, + HandlerUserID: v.HandlerUserID, + HandleMsg: v.HandleMsg, + HandleTime: v.HandleTime, + Ex: v.Ex, + } +} + +func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel { + return mongoModel.BlackModel{ + OwnerUserID: v.OwnerUserID, + BlockUserID: v.BlockUserID, + CreateTime: v.CreateTime, + AddSource: v.AddSource, + OperatorUserID: v.OperatorUserID, + Ex: v.Ex, + } +} + +func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel { + return mongoModel.GroupModel{ + GroupID: v.GroupID, + GroupName: v.GroupName, + Notification: v.Notification, + Introduction: v.Introduction, + FaceURL: v.FaceURL, + CreateTime: v.CreateTime, + Ex: v.Ex, + Status: v.Status, + CreatorUserID: v.CreatorUserID, + GroupType: v.GroupType, + NeedVerification: v.NeedVerification, + LookMemberInfo: v.LookMemberInfo, + ApplyMemberFriend: v.ApplyMemberFriend, + NotificationUpdateTime: v.NotificationUpdateTime, + NotificationUserID: v.NotificationUserID, + } +} + +func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMemberModel { + return mongoModel.GroupMemberModel{ + GroupID: v.GroupID, + UserID: v.UserID, + Nickname: v.Nickname, + FaceURL: v.FaceURL, + RoleLevel: v.RoleLevel, + JoinTime: v.JoinTime, + JoinSource: v.JoinSource, + InviterUserID: v.InviterUserID, + OperatorUserID: v.OperatorUserID, + MuteEndTime: v.MuteEndTime, + Ex: v.Ex, + } +} + +func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequestModel { + return mongoModel.GroupRequestModel{ + UserID: v.UserID, + GroupID: v.GroupID, + HandleResult: v.HandleResult, + ReqMsg: v.ReqMsg, + HandledMsg: v.HandledMsg, + ReqTime: v.ReqTime, + HandleUserID: v.HandleUserID, + HandledTime: v.HandledTime, + JoinSource: v.JoinSource, + InviterUserID: v.InviterUserID, + Ex: v.Ex, + } +} + +func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.ConversationModel { + return mongoModel.ConversationModel{ + OwnerUserID: v.OwnerUserID, + ConversationID: v.ConversationID, + ConversationType: v.ConversationType, + UserID: v.UserID, + GroupID: v.GroupID, + RecvMsgOpt: v.RecvMsgOpt, + IsPinned: v.IsPinned, + IsPrivateChat: v.IsPrivateChat, + BurnDuration: v.BurnDuration, + GroupAtType: v.GroupAtType, + AttachedInfo: v.AttachedInfo, + Ex: v.Ex, + MaxSeq: v.MaxSeq, + MinSeq: v.MinSeq, + CreateTime: v.CreateTime, + IsMsgDestruct: v.IsMsgDestruct, + MsgDestructTime: v.MsgDestructTime, + LatestMsgDestructTime: v.LatestMsgDestructTime, + } +} + +func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.ObjectModel { + return func(v mysqlModel.ObjectModel) mongoModel.ObjectModel { + return mongoModel.ObjectModel{ + Name: v.Name, + UserID: v.UserID, + Hash: v.Hash, + Engine: engine, + Key: v.Key, + Size: v.Size, + ContentType: v.ContentType, + Group: v.Cause, + CreateTime: v.CreateTime, + } + } +} + +func (convert) Log(v mysqlModel.Log) mongoModel.LogModel { + return mongoModel.LogModel{ + LogID: v.LogID, + Platform: v.Platform, + UserID: v.UserID, + CreateTime: v.CreateTime, + Url: v.Url, + FileName: v.FileName, + SystemType: v.SystemType, + Version: v.Version, + Ex: v.Ex, + } +} + +func (convert) SignalModel(v mysqlModelRtc.SignalModel) mongoModelRtc.SignalModel { + return mongoModelRtc.SignalModel{ + SID: v.SID, + InviterUserID: v.InviterUserID, + CustomData: v.CustomData, + GroupID: v.GroupID, + RoomID: v.RoomID, + Timeout: v.Timeout, + MediaType: v.MediaType, + PlatformID: v.PlatformID, + SessionType: v.SessionType, + InitiateTime: v.InitiateTime, + EndTime: v.EndTime, + FileURL: v.FileURL, + Title: v.Title, + Desc: v.Desc, + Ex: v.Ex, + IOSPushSound: v.IOSPushSound, + IOSBadgeCount: v.IOSBadgeCount, + SignalInfo: v.SignalInfo, + } +} + +func (convert) SignalInvitationModel(v mysqlModelRtc.SignalInvitationModel) mongoModelRtc.SignalInvitationModel { + return mongoModelRtc.SignalInvitationModel{ + SID: v.SID, + UserID: v.UserID, + Status: v.Status, + InitiateTime: v.InitiateTime, + HandleTime: v.HandleTime, + } +} + +func (convert) Meeting(v mysqlModelRtc.MeetingInfo) mongoModelRtc.MeetingInfo { + return mongoModelRtc.MeetingInfo{ + RoomID: v.RoomID, + MeetingName: v.MeetingName, + HostUserID: v.HostUserID, + Status: v.Status, + StartTime: time.Unix(v.StartTime, 0), + EndTime: time.Unix(v.EndTime, 0), + CreateTime: v.CreateTime, + Ex: v.Ex, + } +} + +func (convert) MeetingInvitationInfo(v mysqlModelRtc.MeetingInvitationInfo) mongoModelRtc.MeetingInvitationInfo { + return mongoModelRtc.MeetingInvitationInfo{ + RoomID: v.RoomID, + UserID: v.UserID, + CreateTime: v.CreateTime, + } +} + +func (convert) MeetingVideoRecord(v mysqlModelRtc.MeetingVideoRecord) mongoModelRtc.MeetingVideoRecord { + return mongoModelRtc.MeetingVideoRecord{ + RoomID: v.RoomID, + FileURL: v.FileURL, + CreateTime: v.CreateTime, + } +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go new file mode 100644 index 000000000..e3bab7af9 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting.go @@ -0,0 +1,86 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "time" +) + +func NewMeeting(db *mongo.Database) (table.MeetingInterface, error) { + coll := db.Collection("meeting") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "room_id", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "host_user_id", Value: 1}, + }, + }, + { + Keys: bson.D{ + {Key: "create_time", Value: -1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &meeting{coll: coll}, nil +} + +type meeting struct { + coll *mongo.Collection +} + +func (x *meeting) Find(ctx context.Context, roomIDs []string) ([]*table.MeetingInfo, error) { + return mgoutil.Find[*table.MeetingInfo](ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}}) +} + +func (x *meeting) CreateMeetingInfo(ctx context.Context, meetingInfo *table.MeetingInfo) error { + return mgoutil.InsertMany(ctx, x.coll, []*table.MeetingInfo{meetingInfo}) +} + +func (x *meeting) UpdateMeetingInfo(ctx context.Context, roomID string, update map[string]any) error { + if len(update) == 0 { + return nil + } + return mgoutil.UpdateOne(ctx, x.coll, bson.M{"room_id": roomID}, bson.M{"$set": update}, false) +} + +func (x *meeting) GetUnCompleteMeetingIDList(ctx context.Context, roomIDs []string) ([]string, error) { + if len(roomIDs) == 0 { + return nil, nil + } + return mgoutil.Find[string](ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}, "status": 0}, options.Find().SetProjection(bson.M{"_id": 0, "room_id": 1})) +} + +func (x *meeting) Delete(ctx context.Context, roomIDs []string) error { + return mgoutil.DeleteMany(ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}}) +} + +func (x *meeting) GetMeetingRecords(ctx context.Context, hostUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*table.MeetingInfo, error) { + var and []bson.M + if hostUserID != "" { + and = append(and, bson.M{"host_user_id": hostUserID}) + } + if !startTime.IsZero() { + and = append(and, bson.M{"create_time": bson.M{"$gte": startTime}}) + } + if !endTime.IsZero() { + and = append(and, bson.M{"create_time": bson.M{"$lte": endTime}}) + } + filter := bson.M{} + if len(and) > 0 { + filter["$and"] = and + } + return mgoutil.FindPage[*table.MeetingInfo](ctx, x.coll, filter, pagination, options.Find().SetSort(bson.M{"create_time": -1})) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go new file mode 100644 index 000000000..5286ffa95 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_invitation.go @@ -0,0 +1,76 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/OpenIMSDK/tools/pagination" + "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "time" +) + +func NewMeetingInvitation(db *mongo.Database) (table.MeetingInvitationInterface, error) { + coll := db.Collection("meeting_invitation") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "room_id", Value: 1}, + {Key: "user_id", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "create_time", Value: -1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &meetingInvitation{coll: coll}, nil +} + +type meetingInvitation struct { + coll *mongo.Collection +} + +func (x *meetingInvitation) FindUserIDs(ctx context.Context, roomID string) ([]string, error) { + return mgoutil.Find[string](ctx, x.coll, bson.M{"room_id": roomID}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1})) +} + +func (x *meetingInvitation) CreateMeetingInvitationInfo(ctx context.Context, roomID string, inviteeUserIDs []string) error { + now := time.Now() + return mgoutil.InsertMany(ctx, x.coll, utils.Slice(inviteeUserIDs, func(userID string) *table.MeetingInvitationInfo { + return &table.MeetingInvitationInfo{ + RoomID: roomID, + UserID: userID, + CreateTime: now, + } + })) +} + +func (x *meetingInvitation) GetUserInvitedMeetingIDs(ctx context.Context, userID string) (meetingIDs []string, err error) { + fiveDaysAgo := time.Now().AddDate(0, 0, -5) + return mgoutil.Find[string](ctx, x.coll, bson.M{"user_id": userID, "create_time": bson.M{"$gte": fiveDaysAgo}}, options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1})) +} + +func (x *meetingInvitation) Delete(ctx context.Context, roomIDs []string) error { + return mgoutil.DeleteMany(ctx, x.coll, bson.M{"room_id": bson.M{"$in": roomIDs}}) +} + +func (x *meetingInvitation) GetMeetingRecords(ctx context.Context, joinedUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) { + var and []bson.M + and = append(and, bson.M{"user_id": joinedUserID}) + if !startTime.IsZero() { + and = append(and, bson.M{"create_time": bson.M{"$gte": startTime}}) + } + if !endTime.IsZero() { + and = append(and, bson.M{"create_time": bson.M{"$lte": endTime}}) + } + opt := options.Find().SetSort(bson.M{"create_time": -1}).SetProjection(bson.M{"_id": 0, "room_id": 1}) + return mgoutil.FindPage[string](ctx, x.coll, bson.M{"$and": and}, pagination, opt) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go new file mode 100644 index 000000000..90fc9cdca --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/meeting_record.go @@ -0,0 +1,32 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" +) + +func NewMeetingRecord(db *mongo.Database) (table.MeetingRecordInterface, error) { + coll := db.Collection("meeting_record") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "room_id", Value: 1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &meetingRecord{coll: coll}, nil +} + +type meetingRecord struct { + coll *mongo.Collection +} + +func (x *meetingRecord) CreateMeetingVideoRecord(ctx context.Context, meetingVideoRecord *table.MeetingVideoRecord) error { + return mgoutil.InsertMany(ctx, x.coll, []*table.MeetingVideoRecord{meetingVideoRecord}) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go new file mode 100644 index 000000000..0c1879007 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal.go @@ -0,0 +1,89 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/OpenIMSDK/tools/pagination" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "time" +) + +func NewSignal(db *mongo.Database) (table.SignalInterface, error) { + coll := db.Collection("signal") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "sid", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "inviter_user_id", Value: 1}, + }, + }, + { + Keys: bson.D{ + {Key: "initiate_time", Value: -1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &signal{coll: coll}, nil +} + +type signal struct { + coll *mongo.Collection +} + +func (x *signal) Find(ctx context.Context, sids []string) ([]*table.SignalModel, error) { + return mgoutil.Find[*table.SignalModel](ctx, x.coll, bson.M{"sid": bson.M{"$in": sids}}) +} + +func (x *signal) CreateSignal(ctx context.Context, signalModel *table.SignalModel) error { + return mgoutil.InsertMany(ctx, x.coll, []*table.SignalModel{signalModel}) +} + +func (x *signal) Update(ctx context.Context, sid string, update map[string]any) error { + if len(update) == 0 { + return nil + } + return mgoutil.UpdateOne(ctx, x.coll, bson.M{"sid": sid}, bson.M{"$set": update}, false) +} + +func (x *signal) UpdateSignalFileURL(ctx context.Context, sID, fileURL string) error { + return x.Update(ctx, sID, map[string]any{"file_url": fileURL}) +} + +func (x *signal) UpdateSignalEndTime(ctx context.Context, sID string, endTime time.Time) error { + return x.Update(ctx, sID, map[string]any{"end_time": endTime}) +} + +func (x *signal) Delete(ctx context.Context, sids []string) error { + if len(sids) == 0 { + return nil + } + return mgoutil.DeleteMany(ctx, x.coll, bson.M{"sid": bson.M{"$in": sids}}) +} + +func (x *signal) PageSignal(ctx context.Context, sesstionType int32, sendID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*table.SignalModel, error) { + var and []bson.M + if !startTime.IsZero() { + and = append(and, bson.M{"initiate_time": bson.M{"$gte": startTime}}) + } + if !endTime.IsZero() { + and = append(and, bson.M{"initiate_time": bson.M{"$lte": endTime}}) + } + if sesstionType != 0 { + and = append(and, bson.M{"sesstion_type": sesstionType}) + } + if sendID != "" { + and = append(and, bson.M{"inviter_user_id": sendID}) + } + return mgoutil.FindPage[*table.SignalModel](ctx, x.coll, bson.M{"$and": and}, pagination, options.Find().SetSort(bson.M{"initiate_time": -1})) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go new file mode 100644 index 000000000..274f2f11f --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/mgo/signal_invitation.go @@ -0,0 +1,78 @@ +package mgo + +import ( + "context" + "github.com/OpenIMSDK/tools/mgoutil" + "github.com/OpenIMSDK/tools/pagination" + "github.com/OpenIMSDK/tools/utils" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/table" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "time" +) + +func NewSignalInvitation(db *mongo.Database) (table.SignalInvitationInterface, error) { + coll := db.Collection("signal_invitation") + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "sid", Value: 1}, + {Key: "user_id", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "initiate_time", Value: -1}, + }, + }, + }) + if err != nil { + return nil, err + } + return &signalInvitation{coll: coll}, nil +} + +type signalInvitation struct { + coll *mongo.Collection +} + +func (x *signalInvitation) Find(ctx context.Context, sid string) ([]*table.SignalInvitationModel, error) { + return mgoutil.Find[*table.SignalInvitationModel](ctx, x.coll, bson.M{"sid": sid}) +} + +func (x *signalInvitation) CreateSignalInvitation(ctx context.Context, sid string, inviteeUserIDs []string) error { + now := time.Now() + return mgoutil.InsertMany(ctx, x.coll, utils.Slice(inviteeUserIDs, func(userID string) *table.SignalInvitationModel { + return &table.SignalInvitationModel{ + UserID: userID, + SID: sid, + InitiateTime: now, + HandleTime: time.Unix(0, 0), + } + })) +} + +func (x *signalInvitation) HandleSignalInvitation(ctx context.Context, sID, InviteeUserID string, status int32) error { + return mgoutil.UpdateOne(ctx, x.coll, bson.M{"sid": sID, "user_id": InviteeUserID}, bson.M{"$set": bson.M{"status": status, "handle_time": time.Now()}}, true) +} + +func (x *signalInvitation) PageSID(ctx context.Context, recvID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) { + var and []bson.M + and = append(and, bson.M{"user_id": recvID}) + if !startTime.IsZero() { + and = append(and, bson.M{"initiate_time": bson.M{"$gte": startTime}}) + } + if !endTime.IsZero() { + and = append(and, bson.M{"initiate_time": bson.M{"$lte": endTime}}) + } + return mgoutil.FindPage[string](ctx, x.coll, bson.M{"$and": and}, pagination, options.Find().SetProjection(bson.M{"_id": 0, "sid": 1}).SetSort(bson.M{"initiate_time": -1})) +} + +func (x *signalInvitation) Delete(ctx context.Context, sids []string) error { + if len(sids) == 0 { + return nil + } + return mgoutil.DeleteMany(ctx, x.coll, bson.M{"sid": bson.M{"$in": sids}}) +} diff --git a/tools/up35/pkg/internal/rtc/mongo/table/meeting.go b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go new file mode 100644 index 000000000..3b341cfb1 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/table/meeting.go @@ -0,0 +1,51 @@ +package table + +import ( + "context" + "github.com/OpenIMSDK/tools/pagination" + "time" +) + +type MeetingInfo struct { + RoomID string `bson:"room_id"` + MeetingName string `bson:"meeting_name"` + HostUserID string `bson:"host_user_id"` + Status int64 `bson:"status"` + StartTime time.Time `bson:"start_time"` + EndTime time.Time `bson:"end_time"` + CreateTime time.Time `bson:"create_time"` + Ex string `bson:"ex"` +} + +type MeetingInterface interface { + Find(ctx context.Context, roomIDs []string) ([]*MeetingInfo, error) + CreateMeetingInfo(ctx context.Context, meetingInfo *MeetingInfo) error + UpdateMeetingInfo(ctx context.Context, roomID string, update map[string]any) error + GetUnCompleteMeetingIDList(ctx context.Context, roomIDs []string) ([]string, error) + Delete(ctx context.Context, roomIDs []string) error + GetMeetingRecords(ctx context.Context, hostUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*MeetingInfo, error) +} + +type MeetingInvitationInfo struct { + RoomID string `bson:"room_id"` + UserID string `bson:"user_id"` + CreateTime time.Time `bson:"create_time"` +} + +type MeetingInvitationInterface interface { + FindUserIDs(ctx context.Context, roomID string) ([]string, error) + CreateMeetingInvitationInfo(ctx context.Context, roomID string, inviteeUserIDs []string) error + GetUserInvitedMeetingIDs(ctx context.Context, userID string) (meetingIDs []string, err error) + Delete(ctx context.Context, roomIDs []string) error + GetMeetingRecords(ctx context.Context, joinedUserID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) +} + +type MeetingVideoRecord struct { + RoomID string `bson:"room_id"` + FileURL string `bson:"file_url"` + CreateTime time.Time `bson:"create_time"` +} + +type MeetingRecordInterface interface { + CreateMeetingVideoRecord(ctx context.Context, meetingVideoRecord *MeetingVideoRecord) error +} diff --git a/tools/up35/pkg/internal/rtc/mongo/table/signal.go b/tools/up35/pkg/internal/rtc/mongo/table/signal.go new file mode 100644 index 000000000..0cec050ff --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mongo/table/signal.go @@ -0,0 +1,73 @@ +package table + +import ( + "context" + "github.com/OpenIMSDK/tools/errs" + "github.com/OpenIMSDK/tools/pagination" + "github.com/redis/go-redis/v9" + "go.mongodb.org/mongo-driver/mongo" + "time" +) + +type SignalModel struct { + SID string `bson:"sid"` + InviterUserID string `bson:"inviter_user_id"` + CustomData string `bson:"custom_data"` + GroupID string `bson:"group_id"` + RoomID string `bson:"room_id"` + Timeout int32 `bson:"timeout"` + MediaType string `bson:"media_type"` + PlatformID int32 `bson:"platform_id"` + SessionType int32 `bson:"session_type"` + InitiateTime time.Time `bson:"initiate_time"` + EndTime time.Time `bson:"end_time"` + FileURL string `bson:"file_url"` + + Title string `bson:"title"` + Desc string `bson:"desc"` + Ex string `bson:"ex"` + IOSPushSound string `bson:"ios_push_sound"` + IOSBadgeCount bool `bson:"ios_badge_count"` + SignalInfo string `bson:"signal_info"` +} + +type SignalInterface interface { + Find(ctx context.Context, sids []string) ([]*SignalModel, error) + CreateSignal(ctx context.Context, signalModel *SignalModel) error + Update(ctx context.Context, sid string, update map[string]any) error + UpdateSignalFileURL(ctx context.Context, sID, fileURL string) error + UpdateSignalEndTime(ctx context.Context, sID string, endTime time.Time) error + Delete(ctx context.Context, sids []string) error + PageSignal(ctx context.Context, sesstionType int32, sendID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []*SignalModel, error) +} + +type SignalInvitationModel struct { + SID string `bson:"sid"` + UserID string `bson:"user_id"` + Status int32 `bson:"status"` + InitiateTime time.Time `bson:"initiate_time"` + HandleTime time.Time `bson:"handle_time"` +} + +type SignalInvitationInterface interface { + Find(ctx context.Context, sid string) ([]*SignalInvitationModel, error) + CreateSignalInvitation(ctx context.Context, sid string, inviteeUserIDs []string) error + HandleSignalInvitation(ctx context.Context, sID, InviteeUserID string, status int32) error + PageSID(ctx context.Context, recvID string, startTime, endTime time.Time, pagination pagination.Pagination) (int64, []string, error) + Delete(ctx context.Context, sids []string) error +} + +func IsNotFound(err error) bool { + if err == nil { + return false + } + err = errs.Unwrap(err) + return err == mongo.ErrNoDocuments || err == redis.Nil +} + +func IsDuplicate(err error) bool { + if err == nil { + return false + } + return mongo.IsDuplicateKeyError(errs.Unwrap(err)) +} diff --git a/tools/up35/pkg/internal/rtc/mysql/meeting.go b/tools/up35/pkg/internal/rtc/mysql/meeting.go new file mode 100644 index 000000000..2c5bbed32 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mysql/meeting.go @@ -0,0 +1,40 @@ +package relation + +import ( + "time" +) + +type MeetingInfo struct { + RoomID string `gorm:"column:room_id;primary_key;size:128;index:room_id;index:status,priority:1"` + MeetingName string `gorm:"column:meeting_name;size:64"` + HostUserID string `gorm:"column:host_user_id;size:64;index:host_user_id"` + Status int64 `gorm:"column:status;index:status,priority:2"` + StartTime int64 `gorm:"column:start_time"` + EndTime int64 `gorm:"column:end_time"` + CreateTime time.Time `gorm:"column:create_time"` + Ex string `gorm:"column:ex;size:1024"` +} + +func (MeetingInfo) TableName() string { + return "meeting" +} + +type MeetingInvitationInfo struct { + RoomID string `gorm:"column:room_id;primary_key;size:128"` + UserID string `gorm:"column:user_id;primary_key;size:64;index:user_id"` + CreateTime time.Time `gorm:"column:create_time"` +} + +func (MeetingInvitationInfo) TableName() string { + return "meeting_invitation" +} + +type MeetingVideoRecord struct { + RoomID string `gorm:"column:room_id;size:128"` + FileURL string `gorm:"column:file_url"` + CreateTime time.Time `gorm:"column:create_time"` +} + +func (MeetingVideoRecord) TableName() string { + return "meeting_video_record" +} diff --git a/tools/up35/pkg/internal/rtc/mysql/signal.go b/tools/up35/pkg/internal/rtc/mysql/signal.go new file mode 100644 index 000000000..3a4d607d4 --- /dev/null +++ b/tools/up35/pkg/internal/rtc/mysql/signal.go @@ -0,0 +1,43 @@ +package relation + +import ( + "time" +) + +type SignalModel struct { + SID string `gorm:"column:sid;type:char(128);primary_key"` + InviterUserID string `gorm:"column:inviter_user_id;type:char(64);index:inviter_user_id_index"` + CustomData string `gorm:"column:custom_data;type:text"` + GroupID string `gorm:"column:group_id;type:char(64)"` + RoomID string `gorm:"column:room_id;primary_key;type:char(128)"` + Timeout int32 `gorm:"column:timeout"` + MediaType string `gorm:"column:media_type;type:char(64)"` + PlatformID int32 `gorm:"column:platform_id"` + SessionType int32 `gorm:"column:sesstion_type"` + InitiateTime time.Time `gorm:"column:initiate_time"` + EndTime time.Time `gorm:"column:end_time"` + FileURL string `gorm:"column:file_url" json:"-"` + + Title string `gorm:"column:title;size:128"` + Desc string `gorm:"column:desc;size:1024"` + Ex string `gorm:"column:ex;size:1024"` + IOSPushSound string `gorm:"column:ios_push_sound"` + IOSBadgeCount bool `gorm:"column:ios_badge_count"` + SignalInfo string `gorm:"column:signal_info;size:1024"` +} + +func (SignalModel) TableName() string { + return "signal" +} + +type SignalInvitationModel struct { + UserID string `gorm:"column:user_id;primary_key"` + SID string `gorm:"column:sid;type:char(128);primary_key"` + Status int32 `gorm:"column:status"` + InitiateTime time.Time `gorm:"column:initiate_time;primary_key"` + HandleTime time.Time `gorm:"column:handle_time"` +} + +func (SignalInvitationModel) TableName() string { + return "signal_invitation" +} diff --git a/tools/up35/pkg/pkg.go b/tools/up35/pkg/pkg.go new file mode 100644 index 000000000..d834b8492 --- /dev/null +++ b/tools/up35/pkg/pkg.go @@ -0,0 +1,206 @@ +package pkg + +import ( + "context" + "errors" + "fmt" + "gopkg.in/yaml.v3" + "log" + "os" + "reflect" + "strconv" + + "github.com/go-sql-driver/mysql" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + gormMysql "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" + + "github.com/openimsdk/open-im-server/v3/pkg/common/config" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" + rtcMgo "github.com/openimsdk/open-im-server/v3/tools/up35/pkg/internal/rtc/mongo/mgo" +) + +const ( + versionTable = "dataver" + versionKey = "data_version" + versionValue = 35 +) + +func InitConfig(path string) error { + data, err := os.ReadFile(path) + if err != nil { + return err + } + return yaml.Unmarshal(data, &config.Config) +} + +func GetMysql() (*gorm.DB, error) { + conf := config.Config.Mysql + mysqlDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.Username, conf.Password, conf.Address[0], conf.Database) + return gorm.Open(gormMysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard}) +} + +func GetMongo() (*mongo.Database, error) { + mgo, err := unrelation.NewMongo() + if err != nil { + return nil, err + } + return mgo.GetDatabase(), nil +} + +func Main(path string) error { + if err := InitConfig(path); err != nil { + return err + } + if config.Config.Mysql == nil { + return nil + } + mongoDB, err := GetMongo() + if err != nil { + return err + } + var version struct { + Key string `bson:"key"` + Value string `bson:"value"` + } + switch mongoDB.Collection(versionTable).FindOne(context.Background(), bson.M{"key": versionKey}).Decode(&version) { + case nil: + if ver, _ := strconv.Atoi(version.Value); ver >= versionValue { + return nil + } + case mongo.ErrNoDocuments: + default: + return err + } + mysqlDB, err := GetMysql() + if err != nil { + if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1049 { + if err := SetMongoDataVersion(mongoDB, version.Value); err != nil { + return err + } + return nil // database not exist + } + return err + } + + var c convert + var tasks []func() error + tasks = append(tasks, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewUserMongo, c.User) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendMongo, c.Friend) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendRequestMongo, c.FriendRequest) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewBlackMongo, c.Black) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMongo, c.Group) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMember, c.GroupMember) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupRequestMgo, c.GroupRequest) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewConversationMongo, c.Conversation) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewS3Mongo, c.Object(config.Config.Object.Enable)) }, + func() error { return NewTask(mysqlDB, mongoDB, mgo.NewLogMongo, c.Log) }, + + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewSignal, c.SignalModel) }, + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewSignalInvitation, c.SignalInvitationModel) }, + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeeting, c.Meeting) }, + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeetingInvitation, c.MeetingInvitationInfo) }, + func() error { return NewTask(mysqlDB, mongoDB, rtcMgo.NewMeetingRecord, c.MeetingVideoRecord) }, + ) + + for _, task := range tasks { + if err := task(); err != nil { + return err + } + } + + if err := SetMongoDataVersion(mongoDB, version.Value); err != nil { + return err + } + return nil +} + +func SetMongoDataVersion(db *mongo.Database, curver string) error { + filter := bson.M{"key": versionKey, "value": curver} + update := bson.M{"$set": bson.M{"key": versionKey, "value": strconv.Itoa(versionValue)}} + _, err := db.Collection(versionTable).UpdateOne(context.Background(), filter, update, options.Update().SetUpsert(true)) + return err +} + +// NewTask A mysql table B mongodb model C mongodb table +func NewTask[A interface{ TableName() string }, B any, C any](gormDB *gorm.DB, mongoDB *mongo.Database, mongoDBInit func(db *mongo.Database) (B, error), convert func(v A) C) error { + obj, err := mongoDBInit(mongoDB) + if err != nil { + return err + } + var zero A + tableName := zero.TableName() + coll, err := getColl(obj) + if err != nil { + return fmt.Errorf("get mongo collection %s failed, err: %w", tableName, err) + } + var count int + defer func() { + log.Printf("completed convert %s total %d\n", tableName, count) + }() + const batch = 100 + for page := 0; ; page++ { + res := make([]A, 0, batch) + if err := gormDB.Limit(batch).Offset(page * batch).Find(&res).Error; err != nil { + if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1146 { + return nil // table not exist + } + return fmt.Errorf("find mysql table %s failed, err: %w", tableName, err) + } + if len(res) == 0 { + return nil + } + temp := make([]any, len(res)) + for i := range res { + temp[i] = convert(res[i]) + } + if err := insertMany(coll, temp); err != nil { + return fmt.Errorf("insert mongo table %s failed, err: %w", tableName, err) + } + count += len(res) + if len(res) < batch { + return nil + } + log.Printf("current convert %s completed %d\n", tableName, count) + } +} + +func insertMany(coll *mongo.Collection, objs []any) error { + if _, err := coll.InsertMany(context.Background(), objs); err != nil { + if !mongo.IsDuplicateKeyError(err) { + return err + } + } + for i := range objs { + _, err := coll.InsertOne(context.Background(), objs[i]) + switch { + case err == nil: + case mongo.IsDuplicateKeyError(err): + default: + return err + } + } + return nil +} + +func getColl(obj any) (_ *mongo.Collection, err error) { + defer func() { + if e := recover(); e != nil { + err = fmt.Errorf("not found %+v", e) + } + }() + stu := reflect.ValueOf(obj).Elem() + typ := reflect.TypeOf(&mongo.Collection{}).String() + for i := 0; i < stu.NumField(); i++ { + field := stu.Field(i) + if field.Type().String() == typ { + return (*mongo.Collection)(field.UnsafePointer()), nil + } + } + return nil, errors.New("not found") +} diff --git a/tools/up35/up35.go b/tools/up35/up35.go index 5d4740fca..0ce56ee13 100644 --- a/tools/up35/up35.go +++ b/tools/up35/up35.go @@ -1,367 +1,19 @@ package main import ( - "context" - "errors" "flag" - "fmt" - "github.com/go-sql-driver/mysql" - "github.com/openimsdk/open-im-server/v3/pkg/common/config" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" - mongoModel "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" - mysqlModel "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "gopkg.in/yaml.v3" - gormMysql "gorm.io/driver/mysql" - "gorm.io/gorm" - "gorm.io/gorm/logger" + "github.com/openimsdk/open-im-server/v3/tools/up35/pkg" "log" "os" - "reflect" - "strconv" -) - -const ( - versionTable = "dataver" - versionKey = "data_version" - versionValue = 35 ) func main() { var path string flag.StringVar(&path, "c", "", "path config file") flag.Parse() - if err := Main(path); err != nil { + if err := pkg.Main(path); err != nil { log.Fatal(err) return } os.Exit(0) } - -func InitConfig(path string) error { - data, err := os.ReadFile(path) - if err != nil { - return err - } - return yaml.Unmarshal(data, &config.Config) -} - -func GetMysql() (*gorm.DB, error) { - conf := config.Config.Mysql - mysqlDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.Username, conf.Password, conf.Address[0], conf.Database) - return gorm.Open(gormMysql.Open(mysqlDSN), &gorm.Config{Logger: logger.Discard}) -} - -func GetMongo() (*mongo.Database, error) { - mgo, err := unrelation.NewMongo() - if err != nil { - return nil, err - } - return mgo.GetDatabase(), nil -} - -func Main(path string) error { - if err := InitConfig(path); err != nil { - return err - } - if config.Config.Mysql == nil { - return nil - } - mongoDB, err := GetMongo() - if err != nil { - return err - } - var version struct { - Key string `bson:"key"` - Value string `bson:"value"` - } - switch mongoDB.Collection(versionTable).FindOne(context.Background(), bson.M{"key": versionKey}).Decode(&version) { - case nil: - if ver, _ := strconv.Atoi(version.Value); ver >= versionValue { - return nil - } - case mongo.ErrNoDocuments: - default: - return err - } - mysqlDB, err := GetMysql() - if err != nil { - if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1049 { - if err := SetMongoDataVersion(mongoDB, version.Value); err != nil { - return err - } - return nil // database not exist - } - return err - } - - var c convert - var tasks []func() error - tasks = append(tasks, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewUserMongo, c.User) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendMongo, c.Friend) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewFriendRequestMongo, c.FriendRequest) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewBlackMongo, c.Black) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMongo, c.Group) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupMember, c.GroupMember) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewGroupRequestMgo, c.GroupRequest) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewConversationMongo, c.Conversation) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewS3Mongo, c.Object(config.Config.Object.Enable)) }, - func() error { return NewTask(mysqlDB, mongoDB, mgo.NewLogMongo, c.Log) }, - ) - - for _, task := range tasks { - if err := task(); err != nil { - return err - } - } - - if err := SetMongoDataVersion(mongoDB, version.Value); err != nil { - return err - } - return nil -} - -func SetMongoDataVersion(db *mongo.Database, curver string) error { - filter := bson.M{"key": versionKey, "value": curver} - update := bson.M{"$set": bson.M{"key": versionKey, "value": strconv.Itoa(versionValue)}} - _, err := db.Collection(versionTable).UpdateOne(context.Background(), filter, update, options.Update().SetUpsert(true)) - return err -} - -// NewTask A mysql table B mongodb model C mongodb table -func NewTask[A interface{ TableName() string }, B any, C any](gormDB *gorm.DB, mongoDB *mongo.Database, mongoDBInit func(db *mongo.Database) (B, error), convert func(v A) C) error { - obj, err := mongoDBInit(mongoDB) - if err != nil { - return err - } - var zero A - tableName := zero.TableName() - coll, err := getColl(obj) - if err != nil { - return fmt.Errorf("get mongo collection %s failed, err: %w", tableName, err) - } - var count int - defer func() { - log.Printf("completed convert %s total %d\n", tableName, count) - }() - const batch = 100 - for page := 0; ; page++ { - res := make([]A, 0, batch) - if err := gormDB.Limit(batch).Offset(page * batch).Find(&res).Error; err != nil { - if mysqlErr, ok := err.(*mysql.MySQLError); ok && mysqlErr.Number == 1146 { - return nil // table not exist - } - return fmt.Errorf("find mysql table %s failed, err: %w", tableName, err) - } - if len(res) == 0 { - return nil - } - temp := make([]any, len(res)) - for i := range res { - temp[i] = convert(res[i]) - } - if err := insertMany(coll, temp); err != nil { - return fmt.Errorf("insert mongo table %s failed, err: %w", tableName, err) - } - count += len(res) - if len(res) < batch { - return nil - } - log.Printf("current convert %s completed %d\n", tableName, count) - } -} - -func insertMany(coll *mongo.Collection, objs []any) error { - if _, err := coll.InsertMany(context.Background(), objs); err != nil { - if !mongo.IsDuplicateKeyError(err) { - return err - } - } - for i := range objs { - _, err := coll.InsertOne(context.Background(), objs[i]) - switch { - case err == nil: - case mongo.IsDuplicateKeyError(err): - default: - return err - } - } - return nil -} - -func getColl(obj any) (_ *mongo.Collection, err error) { - defer func() { - if e := recover(); e != nil { - err = fmt.Errorf("not found %+v", e) - } - }() - stu := reflect.ValueOf(obj).Elem() - typ := reflect.TypeOf(&mongo.Collection{}).String() - for i := 0; i < stu.NumField(); i++ { - field := stu.Field(i) - if field.Type().String() == typ { - return (*mongo.Collection)(field.UnsafePointer()), nil - } - } - return nil, errors.New("not found") -} - -type convert struct{} - -func (convert) User(v mysqlModel.UserModel) mongoModel.UserModel { - return mongoModel.UserModel{ - UserID: v.UserID, - Nickname: v.Nickname, - FaceURL: v.FaceURL, - Ex: v.Ex, - AppMangerLevel: v.AppMangerLevel, - GlobalRecvMsgOpt: v.GlobalRecvMsgOpt, - CreateTime: v.CreateTime, - } -} - -func (convert) Friend(v mysqlModel.FriendModel) mongoModel.FriendModel { - return mongoModel.FriendModel{ - OwnerUserID: v.OwnerUserID, - FriendUserID: v.FriendUserID, - Remark: v.Remark, - CreateTime: v.CreateTime, - AddSource: v.AddSource, - OperatorUserID: v.OperatorUserID, - Ex: v.Ex, - } -} - -func (convert) FriendRequest(v mysqlModel.FriendRequestModel) mongoModel.FriendRequestModel { - return mongoModel.FriendRequestModel{ - FromUserID: v.FromUserID, - ToUserID: v.ToUserID, - HandleResult: v.HandleResult, - ReqMsg: v.ReqMsg, - CreateTime: v.CreateTime, - HandlerUserID: v.HandlerUserID, - HandleMsg: v.HandleMsg, - HandleTime: v.HandleTime, - Ex: v.Ex, - } -} - -func (convert) Black(v mysqlModel.BlackModel) mongoModel.BlackModel { - return mongoModel.BlackModel{ - OwnerUserID: v.OwnerUserID, - BlockUserID: v.BlockUserID, - CreateTime: v.CreateTime, - AddSource: v.AddSource, - OperatorUserID: v.OperatorUserID, - Ex: v.Ex, - } -} - -func (convert) Group(v mysqlModel.GroupModel) mongoModel.GroupModel { - return mongoModel.GroupModel{ - GroupID: v.GroupID, - GroupName: v.GroupName, - Notification: v.Notification, - Introduction: v.Introduction, - FaceURL: v.FaceURL, - CreateTime: v.CreateTime, - Ex: v.Ex, - Status: v.Status, - CreatorUserID: v.CreatorUserID, - GroupType: v.GroupType, - NeedVerification: v.NeedVerification, - LookMemberInfo: v.LookMemberInfo, - ApplyMemberFriend: v.ApplyMemberFriend, - NotificationUpdateTime: v.NotificationUpdateTime, - NotificationUserID: v.NotificationUserID, - } -} - -func (convert) GroupMember(v mysqlModel.GroupMemberModel) mongoModel.GroupMemberModel { - return mongoModel.GroupMemberModel{ - GroupID: v.GroupID, - UserID: v.UserID, - Nickname: v.Nickname, - FaceURL: v.FaceURL, - RoleLevel: v.RoleLevel, - JoinTime: v.JoinTime, - JoinSource: v.JoinSource, - InviterUserID: v.InviterUserID, - OperatorUserID: v.OperatorUserID, - MuteEndTime: v.MuteEndTime, - Ex: v.Ex, - } -} - -func (convert) GroupRequest(v mysqlModel.GroupRequestModel) mongoModel.GroupRequestModel { - return mongoModel.GroupRequestModel{ - UserID: v.UserID, - GroupID: v.GroupID, - HandleResult: v.HandleResult, - ReqMsg: v.ReqMsg, - HandledMsg: v.HandledMsg, - ReqTime: v.ReqTime, - HandleUserID: v.HandleUserID, - HandledTime: v.HandledTime, - JoinSource: v.JoinSource, - InviterUserID: v.InviterUserID, - Ex: v.Ex, - } -} - -func (convert) Conversation(v mysqlModel.ConversationModel) mongoModel.ConversationModel { - return mongoModel.ConversationModel{ - OwnerUserID: v.OwnerUserID, - ConversationID: v.ConversationID, - ConversationType: v.ConversationType, - UserID: v.UserID, - GroupID: v.GroupID, - RecvMsgOpt: v.RecvMsgOpt, - IsPinned: v.IsPinned, - IsPrivateChat: v.IsPrivateChat, - BurnDuration: v.BurnDuration, - GroupAtType: v.GroupAtType, - AttachedInfo: v.AttachedInfo, - Ex: v.Ex, - MaxSeq: v.MaxSeq, - MinSeq: v.MinSeq, - CreateTime: v.CreateTime, - IsMsgDestruct: v.IsMsgDestruct, - MsgDestructTime: v.MsgDestructTime, - LatestMsgDestructTime: v.LatestMsgDestructTime, - } -} - -func (convert) Object(engine string) func(v mysqlModel.ObjectModel) mongoModel.ObjectModel { - return func(v mysqlModel.ObjectModel) mongoModel.ObjectModel { - return mongoModel.ObjectModel{ - Name: v.Name, - UserID: v.UserID, - Hash: v.Hash, - Engine: engine, - Key: v.Key, - Size: v.Size, - ContentType: v.ContentType, - Group: v.Cause, - CreateTime: v.CreateTime, - } - } -} - -func (convert) Log(v mysqlModel.Log) mongoModel.LogModel { - return mongoModel.LogModel{ - LogID: v.LogID, - Platform: v.Platform, - UserID: v.UserID, - CreateTime: v.CreateTime, - Url: v.Url, - FileName: v.FileName, - SystemType: v.SystemType, - Version: v.Version, - Ex: v.Ex, - } -}