mirror of
				https://github.com/openimsdk/open-im-server.git
				synced 2025-10-26 21:22:16 +08:00 
			
		
		
		
	Merge branch 'main' of github.com:openimsdk/open-im-server into build/k8s
This commit is contained in:
		
						commit
						e767d2c127
					
				
							
								
								
									
										4
									
								
								.env
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								.env
									
									
									
									
									
								
							| @ -8,10 +8,10 @@ ALERTMANAGER_IMAGE=prom/alertmanager:v0.27.0 | |||||||
| GRAFANA_IMAGE=grafana/grafana:11.0.1 | GRAFANA_IMAGE=grafana/grafana:11.0.1 | ||||||
| 
 | 
 | ||||||
| OPENIM_WEB_FRONT_IMAGE=openim/openim-web-front:release-v3.8.1 | OPENIM_WEB_FRONT_IMAGE=openim/openim-web-front:release-v3.8.1 | ||||||
| OPENIM_ADMIN_FRONT_IMAGE=openim/openim-admin-front:release-v1.8.2 | OPENIM_ADMIN_FRONT_IMAGE=openim/openim-admin-front:release-v1.8.3 | ||||||
| 
 | 
 | ||||||
| #FRONT_IMAGE: use aliyun images | #FRONT_IMAGE: use aliyun images | ||||||
| #OPENIM_WEB_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web-front:release-v3.8.1 | #OPENIM_WEB_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web-front:release-v3.8.1 | ||||||
| #OPENIM_ADMIN_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:release-v1.8.2 | #OPENIM_ADMIN_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:release-v1.8.3 | ||||||
| 
 | 
 | ||||||
| DATA_DIR=./ | DATA_DIR=./ | ||||||
|  | |||||||
							
								
								
									
										78
									
								
								.github/workflows/changelog.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								.github/workflows/changelog.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | |||||||
|  | name: Release Changelog | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   release: | ||||||
|  |     types: [released] | ||||||
|  | 
 | ||||||
|  | permissions: | ||||||
|  |   contents: write | ||||||
|  |   pull-requests: write | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   update-changelog: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |     - name: Checkout code | ||||||
|  |       uses: actions/checkout@v4 | ||||||
|  | 
 | ||||||
|  |     - name: Run Go Changelog Generator | ||||||
|  |       run: | | ||||||
|  |         # Run the Go changelog generator, passing the release tag if available | ||||||
|  |         if [ "${{ github.event.release.tag_name }}" = "latest" ]; then | ||||||
|  |           go run tools/changelog/changelog.go > "${{ github.event.release.tag_name }}-changelog.md" | ||||||
|  |         else | ||||||
|  |           go run tools/changelog/changelog.go "${{ github.event.release.tag_name }}" > "${{ github.event.release.tag_name }}-changelog.md" | ||||||
|  |         fi | ||||||
|  | 
 | ||||||
|  |     - name: Handle changelog files | ||||||
|  |       run: | | ||||||
|  |         # Ensure that the CHANGELOG directory exists | ||||||
|  |         mkdir -p CHANGELOG | ||||||
|  | 
 | ||||||
|  |         # Extract Major.Minor version by removing the 'v' prefix from the tag name | ||||||
|  |         TAG_NAME=${{ github.event.release.tag_name }} | ||||||
|  |         CHANGELOG_VERSION_NUMBER=$(echo "$TAG_NAME" | sed 's/^v//' | grep -oP '^\d+\.\d+') | ||||||
|  | 
 | ||||||
|  |         # Define the new changelog file path | ||||||
|  |         CHANGELOG_FILENAME="CHANGELOG-$CHANGELOG_VERSION_NUMBER.md" | ||||||
|  |         CHANGELOG_PATH="CHANGELOG/$CHANGELOG_FILENAME" | ||||||
|  | 
 | ||||||
|  |         # Check if the changelog file for the current release already exists | ||||||
|  |         if [ -f "$CHANGELOG_PATH" ]; then | ||||||
|  |           # If the file exists, append the new changelog to the existing one | ||||||
|  |           cat "$CHANGELOG_PATH" >> "${TAG_NAME}-changelog.md" | ||||||
|  |           # Overwrite the existing changelog with the updated content | ||||||
|  |           mv "${TAG_NAME}-changelog.md" "$CHANGELOG_PATH" | ||||||
|  |         else | ||||||
|  |           # If the changelog file doesn't exist, rename the temp changelog file to the new changelog file | ||||||
|  |           mv "${TAG_NAME}-changelog.md" "$CHANGELOG_PATH" | ||||||
|  | 
 | ||||||
|  |           # Ensure that README.md exists | ||||||
|  |           if [ ! -f "CHANGELOG/README.md" ]; then | ||||||
|  |             echo -e "# CHANGELOGs\n\n" > CHANGELOG/README.md | ||||||
|  |           fi | ||||||
|  |            | ||||||
|  |             # Add the new changelog entry at the top of the README.md | ||||||
|  |             if ! grep -q "\[$CHANGELOG_FILENAME\]" CHANGELOG/README.md; then | ||||||
|  |             sed -i "3i- [$CHANGELOG_FILENAME](./$CHANGELOG_FILENAME)" CHANGELOG/README.md | ||||||
|  |             # Remove the extra newline character added by sed | ||||||
|  |             # sed -i '4d' CHANGELOG/README.md | ||||||
|  |             fi | ||||||
|  |           fi | ||||||
|  | 
 | ||||||
|  |     - name: Clean up | ||||||
|  |       run: | | ||||||
|  |         # Remove any temporary files that were created during the process | ||||||
|  |         rm -f "${{ github.event.release.tag_name }}-changelog.md" | ||||||
|  | 
 | ||||||
|  |     - name: Create Pull Request | ||||||
|  |       uses: peter-evans/create-pull-request@v7.0.5 | ||||||
|  |       with: | ||||||
|  |         token: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |         commit-message: "Update CHANGELOG for release ${{ github.event.release.tag_name }}" | ||||||
|  |         title: "Update CHANGELOG for release ${{ github.event.release.tag_name }}" | ||||||
|  |         body: "This PR updates the CHANGELOG files for release ${{ github.event.release.tag_name }}" | ||||||
|  |         branch: changelog-${{ github.event.release.tag_name }}  | ||||||
|  |         base: main  | ||||||
|  |         delete-branch: true | ||||||
|  |         labels: changelog | ||||||
							
								
								
									
										2
									
								
								.github/workflows/go-build-test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/go-build-test.yml
									
									
									
									
										vendored
									
									
								
							| @ -149,7 +149,7 @@ jobs: | |||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     strategy: |     strategy: | ||||||
|       matrix: |       matrix: | ||||||
|         go_version: ["1.21"] |         go_version: ["1.22"] | ||||||
| 
 | 
 | ||||||
|     steps: |     steps: | ||||||
|       - name: Checkout Repository |       - name: Checkout Repository | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ ENV SERVER_DIR=/openim-server | |||||||
| WORKDIR $SERVER_DIR | WORKDIR $SERVER_DIR | ||||||
| 
 | 
 | ||||||
| # Set the Go proxy to improve dependency resolution speed | # Set the Go proxy to improve dependency resolution speed | ||||||
| ENV GOPROXY=https://goproxy.io,direct | # ENV GOPROXY=https://goproxy.io,direct | ||||||
| 
 | 
 | ||||||
| # Copy all files from the current directory into the container | # Copy all files from the current directory into the container | ||||||
| COPY . . | COPY . . | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
| cronExecuteTime: 0 2 * * * | cronExecuteTime: 0 2 * * * | ||||||
| retainChatRecords: 365 | retainChatRecords: 365 | ||||||
| fileExpireTime: 90 | fileExpireTime: 180 | ||||||
|  | deleteObjectType: ["msg-picture","msg-file", "msg-voice","msg-video","msg-video-snapshot","sdklog"] | ||||||
| @ -13,8 +13,8 @@ prometheus: | |||||||
|   ports: [ 12170, 12171, 12172, 12173, 12174, 12175, 12176, 12177, 12178, 12179, 12180, 12182, 12183, 12184, 12185, 12186 ] |   ports: [ 12170, 12171, 12172, 12173, 12174, 12175, 12176, 12177, 12178, 12179, 12180, 12182, 12183, 12184, 12185, 12186 ] | ||||||
| 
 | 
 | ||||||
| maxConcurrentWorkers: 3 | maxConcurrentWorkers: 3 | ||||||
| #Use geTui for offline push notifications, or choose fcm or jpush; corresponding configuration settings must be specified. | #Use geTui for offline push notifications, or choose fcm or jpns; corresponding configuration settings must be specified. | ||||||
| enable: geTui | enable: | ||||||
| geTui: | geTui: | ||||||
|   pushUrl: https://restapi.getui.com/v2/$appId |   pushUrl: https://restapi.getui.com/v2/$appId | ||||||
|   masterSecret: |   masterSecret: | ||||||
|  | |||||||
| @ -16,14 +16,3 @@ imAdminUserID: [ imAdmin ] | |||||||
| multiLogin: | multiLogin: | ||||||
|   policy: 1 |   policy: 1 | ||||||
|   maxNumOneEnd: 30 |   maxNumOneEnd: 30 | ||||||
|   customizeLoginNum: |  | ||||||
|     ios: 1 |  | ||||||
|     android: 1 |  | ||||||
|     windows: 1 |  | ||||||
|     osx: 1 |  | ||||||
|     web: 1 |  | ||||||
|     miniWeb: 1 |  | ||||||
|     linux: 1 |  | ||||||
|     aPad: 1 |  | ||||||
|     iPad: 1 |  | ||||||
|     admin: 1 |  | ||||||
|  | |||||||
							
								
								
									
										44
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								go.mod
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | |||||||
| module github.com/openimsdk/open-im-server/v3 | module github.com/openimsdk/open-im-server/v3 | ||||||
| 
 | 
 | ||||||
| go 1.22.0 | go 1.22.7 | ||||||
| 
 | 
 | ||||||
| toolchain go1.23.2 | toolchain go1.23.2 | ||||||
| 
 | 
 | ||||||
| @ -10,19 +10,19 @@ require ( | |||||||
| 	github.com/gin-gonic/gin v1.9.1 | 	github.com/gin-gonic/gin v1.9.1 | ||||||
| 	github.com/go-playground/validator/v10 v10.20.0 | 	github.com/go-playground/validator/v10 v10.20.0 | ||||||
| 	github.com/gogo/protobuf v1.3.2 // indirect | 	github.com/gogo/protobuf v1.3.2 // indirect | ||||||
| 	github.com/golang-jwt/jwt/v4 v4.5.0 | 	github.com/golang-jwt/jwt/v4 v4.5.1 | ||||||
| 	github.com/gorilla/websocket v1.5.1 | 	github.com/gorilla/websocket v1.5.1 | ||||||
| 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 | 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 | ||||||
| 	github.com/mitchellh/mapstructure v1.5.0 | 	github.com/mitchellh/mapstructure v1.5.0 | ||||||
| 	github.com/openimsdk/protocol v0.0.72-alpha.54 | 	github.com/openimsdk/protocol v0.0.72-alpha.57 | ||||||
| 	github.com/openimsdk/tools v0.0.50-alpha.32 | 	github.com/openimsdk/tools v0.0.50-alpha.38 | ||||||
| 	github.com/pkg/errors v0.9.1 // indirect | 	github.com/pkg/errors v0.9.1 // indirect | ||||||
| 	github.com/prometheus/client_golang v1.18.0 | 	github.com/prometheus/client_golang v1.18.0 | ||||||
| 	github.com/stretchr/testify v1.9.0 | 	github.com/stretchr/testify v1.9.0 | ||||||
| 	go.mongodb.org/mongo-driver v1.14.0 | 	go.mongodb.org/mongo-driver v1.14.0 | ||||||
| 	google.golang.org/api v0.170.0 | 	google.golang.org/api v0.170.0 | ||||||
| 	google.golang.org/grpc v1.66.2 | 	google.golang.org/grpc v1.68.0 | ||||||
| 	google.golang.org/protobuf v1.34.2 | 	google.golang.org/protobuf v1.35.1 | ||||||
| 	gopkg.in/yaml.v3 v3.0.1 | 	gopkg.in/yaml.v3 v3.0.1 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -50,31 +50,31 @@ require ( | |||||||
| 
 | 
 | ||||||
| require ( | require ( | ||||||
| 	cloud.google.com/go v0.112.1 // indirect | 	cloud.google.com/go v0.112.1 // indirect | ||||||
| 	cloud.google.com/go/compute/metadata v0.3.0 // indirect | 	cloud.google.com/go/compute/metadata v0.5.0 // indirect | ||||||
| 	cloud.google.com/go/firestore v1.15.0 // indirect | 	cloud.google.com/go/firestore v1.15.0 // indirect | ||||||
| 	cloud.google.com/go/iam v1.1.7 // indirect | 	cloud.google.com/go/iam v1.1.7 // indirect | ||||||
| 	cloud.google.com/go/longrunning v0.5.5 // indirect | 	cloud.google.com/go/longrunning v0.5.5 // indirect | ||||||
| 	cloud.google.com/go/storage v1.40.0 // indirect | 	cloud.google.com/go/storage v1.40.0 // indirect | ||||||
| 	github.com/MicahParks/keyfunc v1.9.0 // indirect | 	github.com/MicahParks/keyfunc v1.9.0 // indirect | ||||||
| 	github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible // indirect | 	github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2 v1.23.1 // indirect | 	github.com/aws/aws-sdk-go-v2 v1.32.5 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 // indirect | 	github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/config v1.25.4 // indirect | 	github.com/aws/aws-sdk-go-v2/config v1.28.5 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/credentials v1.16.3 // indirect | 	github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 // indirect | 	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 // indirect | 	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 // indirect | 	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect | 	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 // indirect | 	github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 // indirect | 	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 // indirect | 	github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 // indirect | 	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 // indirect | 	github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1 // indirect | 	github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 // indirect | 	github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 // indirect | 	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 // indirect | 	github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect | ||||||
| 	github.com/aws/smithy-go v1.17.0 // indirect | 	github.com/aws/smithy-go v1.22.1 // indirect | ||||||
| 	github.com/beorn7/perks v1.0.1 // indirect | 	github.com/beorn7/perks v1.0.1 // indirect | ||||||
| 	github.com/bytedance/sonic v1.11.6 // indirect | 	github.com/bytedance/sonic v1.11.6 // indirect | ||||||
| 	github.com/bytedance/sonic/loader v0.1.1 // indirect | 	github.com/bytedance/sonic/loader v0.1.1 // indirect | ||||||
| @ -189,14 +189,14 @@ require ( | |||||||
| 	golang.org/x/arch v0.7.0 // indirect | 	golang.org/x/arch v0.7.0 // indirect | ||||||
| 	golang.org/x/image v0.15.0 // indirect | 	golang.org/x/image v0.15.0 // indirect | ||||||
| 	golang.org/x/net v0.29.0 // indirect | 	golang.org/x/net v0.29.0 // indirect | ||||||
| 	golang.org/x/oauth2 v0.21.0 // indirect | 	golang.org/x/oauth2 v0.23.0 // indirect | ||||||
| 	golang.org/x/sys v0.25.0 // indirect | 	golang.org/x/sys v0.25.0 // indirect | ||||||
| 	golang.org/x/term v0.24.0 // indirect | 	golang.org/x/term v0.24.0 // indirect | ||||||
| 	golang.org/x/text v0.18.0 // indirect | 	golang.org/x/text v0.18.0 // indirect | ||||||
| 	golang.org/x/time v0.5.0 // indirect | 	golang.org/x/time v0.5.0 // indirect | ||||||
| 	google.golang.org/appengine/v2 v2.0.2 // indirect | 	google.golang.org/appengine/v2 v2.0.2 // indirect | ||||||
| 	google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect | 	google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect | ||||||
| 	google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect | 	google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect | ||||||
| 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect | 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect | ||||||
| 	gopkg.in/inf.v0 v0.9.1 // indirect | 	gopkg.in/inf.v0 v0.9.1 // indirect | ||||||
| 	gopkg.in/yaml.v2 v2.4.0 // indirect | 	gopkg.in/yaml.v2 v2.4.0 // indirect | ||||||
|  | |||||||
							
								
								
									
										84
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,8 +1,8 @@ | |||||||
| cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | ||||||
| cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= | cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= | ||||||
| cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= | cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= | ||||||
| cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= | cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= | ||||||
| cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= | cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= | ||||||
| cloud.google.com/go/firestore v1.15.0 h1:/k8ppuWOtNuDHt2tsRV42yI21uaGnKDEQnRFeBpbFF8= | cloud.google.com/go/firestore v1.15.0 h1:/k8ppuWOtNuDHt2tsRV42yI21uaGnKDEQnRFeBpbFF8= | ||||||
| cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= | cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= | ||||||
| cloud.google.com/go/iam v1.1.7 h1:z4VHOhwKLF/+UYXAJDFwGtNF0b6gjsW1Pk9Ml0U/IoM= | cloud.google.com/go/iam v1.1.7 h1:z4VHOhwKLF/+UYXAJDFwGtNF0b6gjsW1Pk9Ml0U/IoM= | ||||||
| @ -21,42 +21,42 @@ github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x9 | |||||||
| github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= | github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= | ||||||
| github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= | github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= | ||||||
| github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= | github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= | ||||||
| github.com/aws/aws-sdk-go-v2 v1.23.1 h1:qXaFsOOMA+HsZtX8WoCa+gJnbyW7qyFFBlPqvTSzbaI= | github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo= | ||||||
| github.com/aws/aws-sdk-go-v2 v1.23.1/go.mod h1:i1XDttT4rnf6vxc9AuskLc6s7XBee8rlLilKlc03uAA= | github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= | ||||||
| github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 h1:ZY3108YtBNq96jNZTICHxN1gSBSbnvIdYwwqnvCV4Mc= | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 h1:ZY3108YtBNq96jNZTICHxN1gSBSbnvIdYwwqnvCV4Mc= | ||||||
| github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1/go.mod h1:t8PYl/6LzdAqsU4/9tz28V/kU+asFePvpOMkdul0gEQ= | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1/go.mod h1:t8PYl/6LzdAqsU4/9tz28V/kU+asFePvpOMkdul0gEQ= | ||||||
| github.com/aws/aws-sdk-go-v2/config v1.25.4 h1:r+X1x8QI6FEPdJDWCNBDZHyAcyFwSjHN8q8uuus+Axs= | github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0= | ||||||
| github.com/aws/aws-sdk-go-v2/config v1.25.4/go.mod h1:8GTjImECskr7D88P/Nn9uM4M4rLY9i77hLJZgkZEWV8= | github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o= | ||||||
| github.com/aws/aws-sdk-go-v2/credentials v1.16.3 h1:8PeI2krzzjDJ5etmgaMiD1JswsrLrWvKKu/uBUtNy1g= | github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg= | ||||||
| github.com/aws/aws-sdk-go-v2/credentials v1.16.3/go.mod h1:Kdh/okh+//vQ/AjEt81CjvkTo64+/zIE4OewP7RpfXk= | github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA= | ||||||
| github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 h1:KehRNiVzIfAcj6gw98zotVbb/K67taJE0fkfgM6vzqU= | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA= | ||||||
| github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5/go.mod h1:VhnExhw6uXy9QzetvpXDolo1/hjhx4u9qukBGkuUwjs= | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY= | ||||||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 h1:LAm3Ycm9HJfbSCd5I+wqC2S9Ej7FPrgr5CQoOljJZcE= | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI= | ||||||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4/go.mod h1:xEhvbJcyUf/31yfGSQBe01fukXwXJ0gxDp7rLfymWE0= | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY= | ||||||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 h1:4GV0kKZzUxiWxSVpn/9gwR0g21NF1Jsyduzo9rHgC/Q= | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o= | ||||||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4/go.mod h1:dYvTNAggxDZy6y1AF7YDwXsPuHFy/VNEpEI/2dWK9IU= | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg= | ||||||
| github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 h1:uR9lXYjdPX0xY+NhvaJ4dD8rpSRz5VY81ccIIoNG+lw= | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= | ||||||
| github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY= | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= | ||||||
| github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 h1:40Q4X5ebZruRtknEZH/bg91sT5pR853F7/1X9QRbI54= | github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 h1:40Q4X5ebZruRtknEZH/bg91sT5pR853F7/1X9QRbI54= | ||||||
| github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4/go.mod h1:u77N7eEECzUv7F0xl2gcfK/vzc8wcjWobpy+DcrLJ5E= | github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4/go.mod h1:u77N7eEECzUv7F0xl2gcfK/vzc8wcjWobpy+DcrLJ5E= | ||||||
| github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 h1:rpkF4n0CyFcrJUG/rNNohoTmhtWlFTRI4BsZOh9PvLs= | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= | ||||||
| github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1/go.mod h1:l9ymW25HOqymeU2m1gbUQ3rUIsTwKs8gYHXkqDQUhiI= | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= | ||||||
| github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 h1:6DRKQc+9cChgzL5gplRGusI5dBGeiEod4m/pmGbcX48= | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 h1:6DRKQc+9cChgzL5gplRGusI5dBGeiEod4m/pmGbcX48= | ||||||
| github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4/go.mod h1:s8ORvrW4g4v7IvYKIAoBg17w3GQ+XuwXDXYrQ5SkzU0= | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4/go.mod h1:s8ORvrW4g4v7IvYKIAoBg17w3GQ+XuwXDXYrQ5SkzU0= | ||||||
| github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 h1:rdovz3rEu0vZKbzoMYPTehp0E8veoE9AyfzqCr5Eeao= | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4= | ||||||
| github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4/go.mod h1:aYCGNjyUCUelhofxlZyj63srdxWUSsBSGg5l6MCuXuE= | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E= | ||||||
| github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 h1:o3DcfCxGDIT20pTbVKVhp3vWXOj/VvgazNJvumWeYW0= | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 h1:o3DcfCxGDIT20pTbVKVhp3vWXOj/VvgazNJvumWeYW0= | ||||||
| github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4/go.mod h1:Uy0KVOxuTK2ne+/PKQ+VvEeWmjMMksE17k/2RK/r5oM= | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4/go.mod h1:Uy0KVOxuTK2ne+/PKQ+VvEeWmjMMksE17k/2RK/r5oM= | ||||||
| github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1 h1:1w11lfXOa8HoHoSlNtt4mqv/N3HmDOa+OnUH3Y9DHm8= | github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1 h1:1w11lfXOa8HoHoSlNtt4mqv/N3HmDOa+OnUH3Y9DHm8= | ||||||
| github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1/go.mod h1:dqJ5JBL0clzgHriH35Amx3LRFY6wNIPUX7QO/BerSBo= | github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1/go.mod h1:dqJ5JBL0clzgHriH35Amx3LRFY6wNIPUX7QO/BerSBo= | ||||||
| github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 h1:CdsSOGlFF3Pn+koXOIpTtvX7st0IuGsZ8kJqcWMlX54= | github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM= | ||||||
| github.com/aws/aws-sdk-go-v2/service/sso v1.17.3/go.mod h1:oA6VjNsLll2eVuUoF2D+CMyORgNzPEW/3PyUdq6WQjI= | github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y= | ||||||
| github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 h1:cbRqFTVnJV+KRpwFl76GJdIZJKKCdTPnjUZ7uWh3pIU= | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8= | ||||||
| github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1/go.mod h1:hHL974p5auvXlZPIjJTblXJpbkfK4klBczlsEaMCGVY= | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc= | ||||||
| github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 h1:yEvZ4neOQ/KpUqyR+X0ycUTW/kVRNR4nDZ38wStHGAA= | github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU= | ||||||
| github.com/aws/aws-sdk-go-v2/service/sts v1.25.4/go.mod h1:feTnm2Tk/pJxdX+eooEsxvlvTWBvDm6CasRZ+JOs2IY= | github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg= | ||||||
| github.com/aws/smithy-go v1.17.0 h1:wWJD7LX6PBV6etBUwO0zElG0nWN9rUhp0WdYeHSHAaI= | github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= | ||||||
| github.com/aws/smithy-go v1.17.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= | github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= | ||||||
| github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= | github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= | ||||||
| github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= | github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= | ||||||
| github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= | ||||||
| @ -171,8 +171,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x | |||||||
| github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= | ||||||
| github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= | ||||||
| github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= | github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= | ||||||
| github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= | github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= | ||||||
| github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= | github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= | ||||||
| github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | ||||||
| github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | ||||||
| github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= | ||||||
| @ -347,10 +347,10 @@ github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= | |||||||
| github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= | github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= | ||||||
| github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y= | github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y= | ||||||
| github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= | github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= | ||||||
| github.com/openimsdk/protocol v0.0.72-alpha.54 h1:opato7N4QjjRq/SHD54bDSVBpOEEDp1VLWVk5Os2A9s= | github.com/openimsdk/protocol v0.0.72-alpha.57 h1:oAVg0SJkDK15L8yDrL0KPG32f3iB/vjEpfpX577p5n4= | ||||||
| github.com/openimsdk/protocol v0.0.72-alpha.54/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= | github.com/openimsdk/protocol v0.0.72-alpha.57/go.mod h1:Iet+piS/jaS+kWWyj6EEr36mk4ISzIRYjoMSVA4dq2M= | ||||||
| github.com/openimsdk/tools v0.0.50-alpha.32 h1:JEsUFHFnaYg230TG+Ke3SUnaA2h44t4kABAzEdv5VZw= | github.com/openimsdk/tools v0.0.50-alpha.38 h1:AU6/cvDfN4ciIOwAj8IWEwze3DeEp2cHYPgW3y0OlbU= | ||||||
| github.com/openimsdk/tools v0.0.50-alpha.32/go.mod h1:r5U6RbxcR4xhKb2fhTmKGC9Yt5LcErHBVt3lhXQIHSo= | github.com/openimsdk/tools v0.0.50-alpha.38/go.mod h1:/Em/fQH46CuWf60+hcmvZyboGCQpSDEb2MdQ4nmQRAk= | ||||||
| github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= | github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= | ||||||
| github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= | github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= | ||||||
| github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= | github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= | ||||||
| @ -527,8 +527,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= | |||||||
| golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= | golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= | ||||||
| golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= | golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= | ||||||
| golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||||
| golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= | golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= | ||||||
| golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= | golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= | ||||||
| golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| @ -599,8 +599,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 | |||||||
| google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= | ||||||
| google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= | google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= | ||||||
| google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= | google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= | ||||||
| google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= | google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= | ||||||
| google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= | google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= | ||||||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= | google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= | ||||||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= | google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= | ||||||
| google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | ||||||
| @ -608,8 +608,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac | |||||||
| google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= | ||||||
| google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= | ||||||
| google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= | ||||||
| google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= | google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= | ||||||
| google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= | google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= | ||||||
| google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | ||||||
| google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | ||||||
| google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | ||||||
| @ -619,8 +619,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 | |||||||
| google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||||
| google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||||
| google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= | ||||||
| google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= | google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= | ||||||
| google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= | google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
| gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
| gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= | ||||||
|  | |||||||
| @ -74,7 +74,7 @@ func newGinRouter(disCov discovery.SvcDiscoveryRegistry, config *Config) *gin.En | |||||||
| 	case BestSpeed: | 	case BestSpeed: | ||||||
| 		r.Use(gzip.Gzip(gzip.BestSpeed)) | 		r.Use(gzip.Gzip(gzip.BestSpeed)) | ||||||
| 	} | 	} | ||||||
| 	r.Use(prommetricsGin(), gin.Recovery(), mw.CorsHandler(), mw.GinParseOperationID(), GinParseToken(authRpc)) | 	r.Use(prommetricsGin(), gin.RecoveryWithWriter(gin.DefaultErrorWriter, mw.GinPanicErr), mw.CorsHandler(), mw.GinParseOperationID(), GinParseToken(authRpc)) | ||||||
| 	u := NewUserApi(*userRpc) | 	u := NewUserApi(*userRpc) | ||||||
| 	m := NewMessageApi(messageRpc, userRpc, config.Share.IMAdminUserID) | 	m := NewMessageApi(messageRpc, userRpc, config.Share.IMAdminUserID) | ||||||
| 	j := jssdk.NewJSSdkApi(userRpc.Client, friendRpc.Client, groupRpc.Client, messageRpc.Client, conversationRpc.Client) | 	j := jssdk.NewJSSdkApi(userRpc.Client, friendRpc.Client, groupRpc.Client, messageRpc.Client, conversationRpc.Client) | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"github.com/openimsdk/tools/mw" | ||||||
| 	"runtime/debug" | 	"runtime/debug" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
| @ -375,6 +376,11 @@ func (c *Client) writeBinaryMsg(resp Resp) error { | |||||||
| func (c *Client) activeHeartbeat(ctx context.Context) { | func (c *Client) activeHeartbeat(ctx context.Context) { | ||||||
| 	if c.PlatformID == constant.WebPlatformID { | 	if c.PlatformID == constant.WebPlatformID { | ||||||
| 		go func() { | 		go func() { | ||||||
|  | 			defer func() { | ||||||
|  | 				if r := recover(); r != nil { | ||||||
|  | 					mw.PanicStackToLog(ctx, r) | ||||||
|  | 				} | ||||||
|  | 			}() | ||||||
| 			log.ZDebug(ctx, "server initiative send heartbeat start.") | 			log.ZDebug(ctx, "server initiative send heartbeat start.") | ||||||
| 			ticker := time.NewTicker(pingPeriod) | 			ticker := time.NewTicker(pingPeriod) | ||||||
| 			defer ticker.Stop() | 			defer ticker.Stop() | ||||||
| @ -446,6 +452,8 @@ func (c *Client) handlerTextMessage(b []byte) error { | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  | 		c.w.Lock() | ||||||
|  | 		defer c.w.Unlock() | ||||||
| 		if err := c.conn.SetWriteDeadline(writeWait); err != nil { | 		if err := c.conn.SetWriteDeadline(writeWait); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -56,6 +56,7 @@ func (s *Server) Start(ctx context.Context, index int, conf *Config) error { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type Server struct { | type Server struct { | ||||||
|  | 	msggateway.UnimplementedMsgGatewayServer | ||||||
| 	rpcPort        int | 	rpcPort        int | ||||||
| 	LongConnServer LongConnServer | 	LongConnServer LongConnServer | ||||||
| 	config         *Config | 	config         *Config | ||||||
|  | |||||||
| @ -136,6 +136,11 @@ func (m *MsgTransfer) Start(index int, config *Config) error { | |||||||
| 
 | 
 | ||||||
| 	if config.MsgTransfer.Prometheus.Enable { | 	if config.MsgTransfer.Prometheus.Enable { | ||||||
| 		go func() { | 		go func() { | ||||||
|  | 			defer func() { | ||||||
|  | 				if r := recover(); r != nil { | ||||||
|  | 					mw.PanicStackToLog(m.ctx, r) | ||||||
|  | 				} | ||||||
|  | 			}() | ||||||
| 			prometheusPort, err := datautil.GetElemByIndex(config.MsgTransfer.Prometheus.Ports, index) | 			prometheusPort, err := datautil.GetElemByIndex(config.MsgTransfer.Prometheus.Ports, index) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				netErr = err | 				netErr = err | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" | 	"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" | ||||||
|  | 	"github.com/openimsdk/tools/mw" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
| @ -346,6 +347,12 @@ func (och *OnlineHistoryRedisConsumerHandler) handleNotification(ctx context.Con | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| func (och *OnlineHistoryRedisConsumerHandler) HandleUserHasReadSeqMessages(ctx context.Context) { | func (och *OnlineHistoryRedisConsumerHandler) HandleUserHasReadSeqMessages(ctx context.Context) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			mw.PanicStackToLog(ctx, r) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 
 | ||||||
| 	defer och.wg.Done() | 	defer och.wg.Done() | ||||||
| 
 | 
 | ||||||
| 	for msg := range och.conversationUserHasReadChan { | 	for msg := range och.conversationUserHasReadChan { | ||||||
|  | |||||||
| @ -29,5 +29,6 @@ type Dummy struct { | |||||||
| 
 | 
 | ||||||
| func (d *Dummy) Push(ctx context.Context, userIDs []string, title, content string, opts *options.Opts) error { | func (d *Dummy) Push(ctx context.Context, userIDs []string, title, content string, opts *options.Opts) error { | ||||||
| 	log.ZDebug(ctx, "dummy push") | 	log.ZDebug(ctx, "dummy push") | ||||||
|  | 	log.ZWarn(ctx, "Dummy push", nil, "ps", "The offline push is not configured. To configure it, please go to config/openim-push.yml.") | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,8 +23,6 @@ import ( | |||||||
| 	"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options" | 	"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options" | ||||||
| 	"github.com/openimsdk/open-im-server/v3/pkg/common/config" | 	"github.com/openimsdk/open-im-server/v3/pkg/common/config" | ||||||
| 	"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache" | 	"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache" | ||||||
| 	"github.com/openimsdk/tools/log" |  | ||||||
| 	"github.com/openimsdk/tools/mcontext" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -51,7 +49,6 @@ func NewOfflinePusher(pushConf *config.Push, cache cache.ThirdCache, fcmConfigPa | |||||||
| 		offlinePusher = jpush.NewClient(pushConf) | 		offlinePusher = jpush.NewClient(pushConf) | ||||||
| 	default: | 	default: | ||||||
| 		offlinePusher = dummy.NewClient() | 		offlinePusher = dummy.NewClient() | ||||||
| 		log.ZWarn(mcontext.WithMustInfoCtx([]string{"push start", "admin", "admin", ""}), "Unknown push config", nil) |  | ||||||
| 	} | 	} | ||||||
| 	return offlinePusher, nil | 	return offlinePusher, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type pushServer struct { | type pushServer struct { | ||||||
|  | 	pbpush.UnimplementedPushMsgServiceServer | ||||||
| 	database      controller.PushDatabase | 	database      controller.PushDatabase | ||||||
| 	disCov        discovery.SvcDiscoveryRegistry | 	disCov        discovery.SvcDiscoveryRegistry | ||||||
| 	offlinePusher offlinepush.OfflinePusher | 	offlinePusher offlinepush.OfflinePusher | ||||||
|  | |||||||
| @ -166,17 +166,21 @@ func (c *ConsumerHandler) Push2User(ctx context.Context, userIDs []string, msg * | |||||||
| 			return nil | 			return nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	offlinePushUserID := []string{msg.RecvID} | 	needOfflinePushUserID := []string{msg.RecvID} | ||||||
|  | 	var offlinePushUserID []string | ||||||
| 
 | 
 | ||||||
| 	//receiver offline push | 	//receiver offline push | ||||||
| 	if err = c.webhookBeforeOfflinePush(ctx, &c.config.WebhooksConfig.BeforeOfflinePush, | 	if err = c.webhookBeforeOfflinePush(ctx, &c.config.WebhooksConfig.BeforeOfflinePush, needOfflinePushUserID, msg, &offlinePushUserID); err != nil { | ||||||
| 		offlinePushUserID, msg, nil); err != nil { |  | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	log.ZInfo(ctx, "webhookBeforeOfflinePush end") | 	log.ZInfo(ctx, "webhookBeforeOfflinePush end") | ||||||
| 	err = c.offlinePushMsg(ctx, msg, offlinePushUserID) | 
 | ||||||
|  | 	if len(offlinePushUserID) > 0 { | ||||||
|  | 		needOfflinePushUserID = offlinePushUserID | ||||||
|  | 	} | ||||||
|  | 	err = c.offlinePushMsg(ctx, msg, needOfflinePushUserID) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.ZWarn(ctx, "offlinePushMsg failed", err, "offlinePushUserID", offlinePushUserID, "msg", msg) | 		log.ZWarn(ctx, "offlinePushMsg failed", err, "needOfflinePushUserID", needOfflinePushUserID, "msg", msg) | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ package auth | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"errors" | ||||||
| 
 | 
 | ||||||
| 	"github.com/openimsdk/open-im-server/v3/pkg/common/config" | 	"github.com/openimsdk/open-im-server/v3/pkg/common/config" | ||||||
| 	redis2 "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis" | 	redis2 "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis" | ||||||
| @ -39,6 +40,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type authServer struct { | type authServer struct { | ||||||
|  | 	pbauth.UnimplementedAuthServer | ||||||
| 	authDatabase   controller.AuthDatabase | 	authDatabase   controller.AuthDatabase | ||||||
| 	userRpcClient  *rpcclient.UserRpcClient | 	userRpcClient  *rpcclient.UserRpcClient | ||||||
| 	RegisterCenter discovery.SvcDiscoveryRegistry | 	RegisterCenter discovery.SvcDiscoveryRegistry | ||||||
| @ -66,6 +68,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg | |||||||
| 			config.Share.Secret, | 			config.Share.Secret, | ||||||
| 			config.RpcConfig.TokenPolicy.Expire, | 			config.RpcConfig.TokenPolicy.Expire, | ||||||
| 			config.Share.MultiLogin, | 			config.Share.MultiLogin, | ||||||
|  | 			config.Share.IMAdminUserID, | ||||||
| 		), | 		), | ||||||
| 		config: config, | 		config: config, | ||||||
| 	}) | 	}) | ||||||
| @ -129,6 +132,10 @@ func (s *authServer) parseToken(ctx context.Context, tokensString string) (claim | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, errs.Wrap(err) | 		return nil, errs.Wrap(err) | ||||||
| 	} | 	} | ||||||
|  | 	isAdmin := authverify.IsManagerUserID(claims.UserID, s.config.Share.IMAdminUserID) | ||||||
|  | 	if isAdmin { | ||||||
|  | 		return claims, nil | ||||||
|  | 	} | ||||||
| 	m, err := s.authDatabase.GetTokensWithoutError(ctx, claims.UserID, claims.PlatformID) | 	m, err := s.authDatabase.GetTokensWithoutError(ctx, claims.UserID, claims.PlatformID) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| @ -190,7 +197,7 @@ func (s *authServer) forceKickOff(ctx context.Context, userID string, platformID | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	m, err := s.authDatabase.GetTokensWithoutError(ctx, userID, int(platformID)) | 	m, err := s.authDatabase.GetTokensWithoutError(ctx, userID, int(platformID)) | ||||||
| 	if err != nil && err != redis.Nil { | 	if err != nil && !errors.Is(err, redis.Nil) { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	for k := range m { | 	for k := range m { | ||||||
| @ -208,7 +215,7 @@ func (s *authServer) forceKickOff(ctx context.Context, userID string, platformID | |||||||
| 
 | 
 | ||||||
| func (s *authServer) InvalidateToken(ctx context.Context, req *pbauth.InvalidateTokenReq) (*pbauth.InvalidateTokenResp, error) { | func (s *authServer) InvalidateToken(ctx context.Context, req *pbauth.InvalidateTokenReq) (*pbauth.InvalidateTokenResp, error) { | ||||||
| 	m, err := s.authDatabase.GetTokensWithoutError(ctx, req.UserID, int(req.PlatformID)) | 	m, err := s.authDatabase.GetTokensWithoutError(ctx, req.UserID, int(req.PlatformID)) | ||||||
| 	if err != nil && err != redis.Nil { | 	if err != nil && !errors.Is(err, redis.Nil) { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	if m == nil { | 	if m == nil { | ||||||
|  | |||||||
| @ -43,6 +43,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type conversationServer struct { | type conversationServer struct { | ||||||
|  | 	pbconversation.UnimplementedConversationServer | ||||||
| 	msgRpcClient         *rpcclient.MessageRpcClient | 	msgRpcClient         *rpcclient.MessageRpcClient | ||||||
| 	user                 *rpcclient.UserRpcClient | 	user                 *rpcclient.UserRpcClient | ||||||
| 	groupRpcClient       *rpcclient.GroupRpcClient | 	groupRpcClient       *rpcclient.GroupRpcClient | ||||||
|  | |||||||
| @ -110,7 +110,7 @@ func UpdateGroupMemberMap(req *pbgroup.SetGroupMemberInfo) map[string]any { | |||||||
| 		m["nickname"] = req.Nickname.Value | 		m["nickname"] = req.Nickname.Value | ||||||
| 	} | 	} | ||||||
| 	if req.FaceURL != nil { | 	if req.FaceURL != nil { | ||||||
| 		m["user_group_face_url"] = req.FaceURL.Value | 		m["face_url"] = req.FaceURL.Value | ||||||
| 	} | 	} | ||||||
| 	if req.RoleLevel != nil { | 	if req.RoleLevel != nil { | ||||||
| 		m["role_level"] = req.RoleLevel.Value | 		m["role_level"] = req.RoleLevel.Value | ||||||
|  | |||||||
| @ -57,6 +57,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type groupServer struct { | type groupServer struct { | ||||||
|  | 	pbgroup.UnimplementedGroupServer | ||||||
| 	db                    controller.GroupDatabase | 	db                    controller.GroupDatabase | ||||||
| 	user                  rpcclient.UserRpcClient | 	user                  rpcclient.UserRpcClient | ||||||
| 	notification          *GroupNotificationSender | 	notification          *GroupNotificationSender | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ package msg | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"errors" | ||||||
| 
 | 
 | ||||||
| 	cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" | 	cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" | ||||||
| 	"github.com/openimsdk/protocol/constant" | 	"github.com/openimsdk/protocol/constant" | ||||||
| @ -108,7 +109,7 @@ func (m *msgServer) MarkMsgsAsRead(ctx context.Context, req *msg.MarkMsgsAsReadR | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	currentHasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID) | 	currentHasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID) | ||||||
| 	if err != nil && errs.Unwrap(err) != redis.Nil { | 	if err != nil && !errors.Is(err, redis.Nil) { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	if hasReadSeq > currentHasReadSeq { | 	if hasReadSeq > currentHasReadSeq { | ||||||
| @ -136,7 +137,7 @@ func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkCon | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	hasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID) | 	hasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID) | ||||||
| 	if err != nil && errs.Unwrap(err) != redis.Nil { | 	if err != nil && !errors.Is(err, redis.Nil) { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	var seqs []int64 | 	var seqs []int64 | ||||||
| @ -180,14 +181,23 @@ func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkCon | |||||||
| 			req.UserID, seqs, hasReadSeq) | 			req.UserID, seqs, hasReadSeq) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	reqCall := &cbapi.CallbackGroupMsgReadReq{ | 	if conversation.ConversationType == constant.SingleChatType { | ||||||
| 		SendID:       conversation.OwnerUserID, | 		reqCall := &cbapi.CallbackSingleMsgReadReq{ | ||||||
| 		ReceiveID:    req.UserID, | 			ConversationID: conversation.ConversationID, | ||||||
| 		UnreadMsgNum: req.HasReadSeq, | 			UserID:         conversation.OwnerUserID, | ||||||
| 		ContentType:  int64(conversation.ConversationType), | 			Seqs:           req.Seqs, | ||||||
|  | 			ContentType:    conversation.ConversationType, | ||||||
|  | 		} | ||||||
|  | 		m.webhookAfterSingleMsgRead(ctx, &m.config.WebhooksConfig.AfterSingleMsgRead, reqCall) | ||||||
|  | 	} else if conversation.ConversationType == constant.ReadGroupChatType { | ||||||
|  | 		reqCall := &cbapi.CallbackGroupMsgReadReq{ | ||||||
|  | 			SendID:       conversation.OwnerUserID, | ||||||
|  | 			ReceiveID:    req.UserID, | ||||||
|  | 			UnreadMsgNum: req.HasReadSeq, | ||||||
|  | 			ContentType:  int64(conversation.ConversationType), | ||||||
|  | 		} | ||||||
|  | 		m.webhookAfterGroupMsgRead(ctx, &m.config.WebhooksConfig.AfterGroupMsgRead, reqCall) | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	m.webhookAfterGroupMsgRead(ctx, &m.config.WebhooksConfig.AfterGroupMsgRead, reqCall) |  | ||||||
| 	return &msg.MarkConversationAsReadResp{}, nil | 	return &msg.MarkConversationAsReadResp{}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ package msg | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"github.com/openimsdk/tools/mw" | ||||||
| 
 | 
 | ||||||
| 	"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" | 	"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" | ||||||
| 	"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" | 	"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" | ||||||
| @ -83,8 +84,15 @@ func (m *msgServer) sendMsgGroupChat(ctx context.Context, req *pbmsg.SendMsgReq) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdkws.MsgData) { | func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdkws.MsgData) { | ||||||
|  | 
 | ||||||
| 	log.ZDebug(nctx, "setConversationAtInfo", "msg", msg) | 	log.ZDebug(nctx, "setConversationAtInfo", "msg", msg) | ||||||
| 
 | 
 | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			mw.PanicStackToLog(nctx, r) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 
 | ||||||
| 	ctx := mcontext.NewCtx("@@@" + mcontext.GetOperationID(nctx)) | 	ctx := mcontext.NewCtx("@@@" + mcontext.GetOperationID(nctx)) | ||||||
| 
 | 
 | ||||||
| 	var atUserID []string | 	var atUserID []string | ||||||
| @ -171,9 +179,6 @@ func (m *msgServer) sendMsgSingleChat(ctx context.Context, req *pbmsg.SendMsgReq | |||||||
| 		prommetrics.SingleChatMsgProcessFailedCounter.Inc() | 		prommetrics.SingleChatMsgProcessFailedCounter.Inc() | ||||||
| 		return nil, nil | 		return nil, nil | ||||||
| 	} else { | 	} else { | ||||||
| 		if err = m.webhookBeforeSendSingleMsg(ctx, &m.config.WebhooksConfig.BeforeSendSingleMsg, req); err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		if err := m.webhookBeforeMsgModify(ctx, &m.config.WebhooksConfig.BeforeMsgModify, req); err != nil { | 		if err := m.webhookBeforeMsgModify(ctx, &m.config.WebhooksConfig.BeforeMsgModify, req); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -16,15 +16,15 @@ package msg | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"errors" | ||||||
| 	pbmsg "github.com/openimsdk/protocol/msg" | 	pbmsg "github.com/openimsdk/protocol/msg" | ||||||
| 	"github.com/openimsdk/tools/errs" |  | ||||||
| 	"github.com/redis/go-redis/v9" | 	"github.com/redis/go-redis/v9" | ||||||
| 	"sort" | 	"sort" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (m *msgServer) GetConversationMaxSeq(ctx context.Context, req *pbmsg.GetConversationMaxSeqReq) (*pbmsg.GetConversationMaxSeqResp, error) { | func (m *msgServer) GetConversationMaxSeq(ctx context.Context, req *pbmsg.GetConversationMaxSeqReq) (*pbmsg.GetConversationMaxSeqResp, error) { | ||||||
| 	maxSeq, err := m.MsgDatabase.GetMaxSeq(ctx, req.ConversationID) | 	maxSeq, err := m.MsgDatabase.GetMaxSeq(ctx, req.ConversationID) | ||||||
| 	if err != nil && errs.Unwrap(err) != redis.Nil { | 	if err != nil && !errors.Is(err, redis.Nil) { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	return &pbmsg.GetConversationMaxSeqResp{MaxSeq: maxSeq}, nil | 	return &pbmsg.GetConversationMaxSeqResp{MaxSeq: maxSeq}, nil | ||||||
|  | |||||||
| @ -55,6 +55,7 @@ type ( | |||||||
| 		msgNotificationSender  *MsgNotificationSender           // RPC client for sending msg notifications. | 		msgNotificationSender  *MsgNotificationSender           // RPC client for sending msg notifications. | ||||||
| 		config                 *Config                          // Global configuration settings. | 		config                 *Config                          // Global configuration settings. | ||||||
| 		webhookClient          *webhook.Client | 		webhookClient          *webhook.Client | ||||||
|  | 		msg.UnimplementedMsgServer | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Config struct { | 	Config struct { | ||||||
|  | |||||||
| @ -59,6 +59,9 @@ func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgRe | |||||||
| 			data.MsgData.ContentType >= constant.NotificationBegin { | 			data.MsgData.ContentType >= constant.NotificationBegin { | ||||||
| 			return nil | 			return nil | ||||||
| 		} | 		} | ||||||
|  | 		if err := m.webhookBeforeSendSingleMsg(ctx, &m.config.WebhooksConfig.BeforeSendSingleMsg, data); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
| 		black, err := m.FriendLocalCache.IsBlack(ctx, data.MsgData.SendID, data.MsgData.RecvID) | 		black, err := m.FriendLocalCache.IsBlack(ctx, data.MsgData.SendID, data.MsgData.RecvID) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
|  | |||||||
| @ -43,6 +43,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type friendServer struct { | type friendServer struct { | ||||||
|  | 	relation.UnimplementedFriendServer | ||||||
| 	db                    controller.FriendDatabase | 	db                    controller.FriendDatabase | ||||||
| 	blackDatabase         controller.BlackDatabase | 	blackDatabase         controller.BlackDatabase | ||||||
| 	userRpcClient         *rpcclient.UserRpcClient | 	userRpcClient         *rpcclient.UserRpcClient | ||||||
|  | |||||||
| @ -290,48 +290,85 @@ func (t *thirdServer) apiAddress(prefix, name string) string { | |||||||
| func (t *thirdServer) DeleteOutdatedData(ctx context.Context, req *third.DeleteOutdatedDataReq) (*third.DeleteOutdatedDataResp, error) { | func (t *thirdServer) DeleteOutdatedData(ctx context.Context, req *third.DeleteOutdatedDataReq) (*third.DeleteOutdatedDataResp, error) { | ||||||
| 	var conf config.Third | 	var conf config.Third | ||||||
| 	expireTime := time.UnixMilli(req.ExpireTime) | 	expireTime := time.UnixMilli(req.ExpireTime) | ||||||
| 	var deltotal int | 
 | ||||||
| 	findPagination := &sdkws.RequestPagination{ | 	findPagination := &sdkws.RequestPagination{ | ||||||
| 		PageNumber: 1, | 		PageNumber: 1, | ||||||
| 		ShowNumber: 1000, | 		ShowNumber: 500, | ||||||
| 	} | 	} | ||||||
| 	for { | 
 | ||||||
| 		total, models, err := t.s3dataBase.FindByExpires(ctx, expireTime, findPagination) | 	// Find all expired data in S3 database | ||||||
|  | 	total, models, err := t.s3dataBase.FindNeedDeleteObjectByDB(ctx, expireTime, req.ObjectGroup, findPagination) | ||||||
|  | 	if err != nil && errs.Unwrap(err) != mongo.ErrNoDocuments { | ||||||
|  | 		return nil, errs.Wrap(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if total == 0 { | ||||||
|  | 		log.ZDebug(ctx, "Not have OutdatedData", "delete Total", total) | ||||||
|  | 		return &third.DeleteOutdatedDataResp{Count: int32(total)}, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	needDelObjectKeys := make([]string, len(models)) | ||||||
|  | 	for _, model := range models { | ||||||
|  | 		needDelObjectKeys = append(needDelObjectKeys, model.Key) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Remove duplicate keys, have the same key use in different models | ||||||
|  | 	needDelObjectKeys = datautil.Distinct(needDelObjectKeys) | ||||||
|  | 
 | ||||||
|  | 	for _, key := range needDelObjectKeys { | ||||||
|  | 		// Find all models by key | ||||||
|  | 		keyModels, err := t.s3dataBase.FindModelsByKey(ctx, key) | ||||||
| 		if err != nil && errs.Unwrap(err) != mongo.ErrNoDocuments { | 		if err != nil && errs.Unwrap(err) != mongo.ErrNoDocuments { | ||||||
| 			return nil, errs.Wrap(err) | 			return nil, errs.Wrap(err) | ||||||
| 		} | 		} | ||||||
| 		needDelObjectKeys := make([]string, 0) |  | ||||||
| 		for _, model := range models { |  | ||||||
| 			needDelObjectKeys = append(needDelObjectKeys, model.Key) |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		needDelObjectKeys = datautil.Distinct(needDelObjectKeys) | 		// check keyModels, if all keyModels. | ||||||
| 		for _, key := range needDelObjectKeys { | 		needDelKey := true // Default can delete | ||||||
| 			count, err := t.s3dataBase.FindNotDelByS3(ctx, key, expireTime) | 		for _, keymodel := range keyModels { | ||||||
| 			if err != nil && errs.Unwrap(err) != mongo.ErrNoDocuments { | 			// If group is empty or CreateTime is after expireTime, can't delete this key | ||||||
| 				return nil, errs.Wrap(err) | 			if keymodel.Group == "" || keymodel.CreateTime.After(expireTime) { | ||||||
| 			} | 				needDelKey = false | ||||||
| 			if int(count) < 1 && t.minio != nil { | 				break | ||||||
| 				thumbnailKey, _ := t.getMinioImageThumbnailKey(ctx, key) |  | ||||||
| 
 |  | ||||||
| 				t.s3dataBase.DeleteObject(ctx, thumbnailKey) |  | ||||||
| 				t.s3dataBase.DelS3Key(ctx, conf.Object.Enable, needDelObjectKeys...) |  | ||||||
| 				t.s3dataBase.DeleteObject(ctx, key) |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		for _, model := range models { | 
 | ||||||
| 			err := t.s3dataBase.DeleteSpecifiedData(ctx, model.Engine, model.Name) | 		// If this object is not referenced by not expire data, delete it | ||||||
|  | 		if needDelKey && t.minio != nil { | ||||||
|  | 			// If have a thumbnail, delete it | ||||||
|  | 			thumbnailKey, _ := t.getMinioImageThumbnailKey(ctx, key) | ||||||
|  | 			if thumbnailKey != "" { | ||||||
|  | 				err := t.s3dataBase.DeleteObject(ctx, thumbnailKey) | ||||||
|  | 				if err != nil { | ||||||
|  | 					log.ZWarn(ctx, "Delete thumbnail object is error:", errs.Wrap(err), "thumbnailKey", thumbnailKey) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Delete object | ||||||
|  | 			err = t.s3dataBase.DeleteObject(ctx, key) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return nil, errs.Wrap(err) | 				log.ZWarn(ctx, "Delete object is error", errs.Wrap(err), "object key", key) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Delete cache key | ||||||
|  | 			err = t.s3dataBase.DelS3Key(ctx, conf.Object.Enable, key) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.ZWarn(ctx, "Delete cache key is error:", errs.Wrap(err), "cache S3 key:", key) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if total < int64(findPagination.ShowNumber) { |  | ||||||
| 			break |  | ||||||
| 		} |  | ||||||
| 		deltotal += int(total) |  | ||||||
| 	} | 	} | ||||||
| 	log.ZDebug(ctx, "DeleteOutdatedData", "delete Total", deltotal) | 
 | ||||||
| 	return &third.DeleteOutdatedDataResp{}, nil | 	// handle delete data in S3 database | ||||||
|  | 	for _, model := range models { | ||||||
|  | 		// Delete all expired data row in S3 database | ||||||
|  | 		err := t.s3dataBase.DeleteSpecifiedData(ctx, model.Engine, model.Name) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, errs.Wrap(err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	log.ZDebug(ctx, "DeleteOutdatedData", "delete Total", total) | ||||||
|  | 
 | ||||||
|  | 	return &third.DeleteOutdatedDataResp{Count: int32(total)}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type FormDataMate struct { | type FormDataMate struct { | ||||||
|  | |||||||
| @ -38,6 +38,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type thirdServer struct { | type thirdServer struct { | ||||||
|  | 	third.UnimplementedThirdServer | ||||||
| 	thirdDatabase controller.ThirdDatabase | 	thirdDatabase controller.ThirdDatabase | ||||||
| 	s3dataBase    controller.S3Database | 	s3dataBase    controller.S3Database | ||||||
| 	userRpcClient rpcclient.UserRpcClient | 	userRpcClient rpcclient.UserRpcClient | ||||||
|  | |||||||
| @ -52,6 +52,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type userServer struct { | type userServer struct { | ||||||
|  | 	pbuser.UnimplementedUserServer | ||||||
| 	online                   cache.OnlineCache | 	online                   cache.OnlineCache | ||||||
| 	db                       controller.UserDatabase | 	db                       controller.UserDatabase | ||||||
| 	friendNotificationSender *relation.FriendNotificationSender | 	friendNotificationSender *relation.FriendNotificationSender | ||||||
|  | |||||||
| @ -24,6 +24,7 @@ import ( | |||||||
| 	kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister" | 	kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister" | ||||||
| 	pbconversation "github.com/openimsdk/protocol/conversation" | 	pbconversation "github.com/openimsdk/protocol/conversation" | ||||||
| 	"github.com/openimsdk/protocol/msg" | 	"github.com/openimsdk/protocol/msg" | ||||||
|  | 	"github.com/openimsdk/protocol/third" | ||||||
| 
 | 
 | ||||||
| 	"github.com/openimsdk/tools/mcontext" | 	"github.com/openimsdk/tools/mcontext" | ||||||
| 	"github.com/openimsdk/tools/mw" | 	"github.com/openimsdk/tools/mw" | ||||||
| @ -58,10 +59,10 @@ func Start(ctx context.Context, config *CronTaskConfig) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// thirdConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Third) | 	thirdConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Third) | ||||||
| 	// if err != nil { | 	if err != nil { | ||||||
| 	// 	return err | 		return err | ||||||
| 	// } | 	} | ||||||
| 
 | 
 | ||||||
| 	conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation) | 	conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -70,7 +71,7 @@ func Start(ctx context.Context, config *CronTaskConfig) error { | |||||||
| 
 | 
 | ||||||
| 	msgClient := msg.NewMsgClient(msgConn) | 	msgClient := msg.NewMsgClient(msgConn) | ||||||
| 	conversationClient := pbconversation.NewConversationClient(conversationConn) | 	conversationClient := pbconversation.NewConversationClient(conversationConn) | ||||||
| 	// thirdClient := third.NewThirdClient(thirdConn) | 	thirdClient := third.NewThirdClient(thirdConn) | ||||||
| 
 | 
 | ||||||
| 	crontab := cron.New() | 	crontab := cron.New() | ||||||
| 
 | 
 | ||||||
| @ -114,21 +115,37 @@ func Start(ctx context.Context, config *CronTaskConfig) error { | |||||||
| 		return errs.Wrap(err) | 		return errs.Wrap(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// // scheduled delete outdated file Objects and their datas in specific time. | 	// scheduled delete outdated file Objects and their datas in specific time. | ||||||
| 	// deleteObjectFunc := func() { | 	deleteObjectFunc := func() { | ||||||
| 	// 	now := time.Now() | 		now := time.Now() | ||||||
| 	// 	deleteTime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.FileExpireTime)) | 		executeNum := 5 | ||||||
| 	// 	ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deleteTime.UnixMilli())) | 		// number of pagination. if need modify, need update value in third.DeleteOutdatedData | ||||||
| 	// 	log.ZDebug(ctx, "deleteoutDatedData ", "deletetime", deleteTime, "timestamp", deleteTime.UnixMilli()) | 		pageShowNumber := 500 | ||||||
| 	// 	if _, err := thirdClient.DeleteOutdatedData(ctx, &third.DeleteOutdatedDataReq{ExpireTime: deleteTime.UnixMilli()}); err != nil { | 		deleteTime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.FileExpireTime)) | ||||||
| 	// 		log.ZError(ctx, "cron deleteoutDatedData failed", err, "deleteTime", deleteTime, "cont", time.Since(now)) | 		ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deleteTime.UnixMilli())) | ||||||
| 	// 		return | 		log.ZDebug(ctx, "deleteoutDatedData", "deletetime", deleteTime, "timestamp", deleteTime.UnixMilli()) | ||||||
| 	// 	} | 
 | ||||||
| 	// 	log.ZDebug(ctx, "cron deleteoutDatedData success", "deltime", deleteTime, "cont", time.Since(now)) | 		if len(config.CronTask.DeleteObjectType) == 0 { | ||||||
| 	// } | 			log.ZDebug(ctx, "cron deleteoutDatedData not type need delete", "deletetime", deleteTime, "DeleteObjectType", config.CronTask.DeleteObjectType, "cont", time.Since(now)) | ||||||
| 	// if _, err := crontab.AddFunc(config.CronTask.CronExecuteTime, deleteObjectFunc); err != nil { | 			return | ||||||
| 	// 	return errs.Wrap(err) | 		} | ||||||
| 	// } | 
 | ||||||
|  | 		for i := 0; i < executeNum; i++ { | ||||||
|  | 			resp, err := thirdClient.DeleteOutdatedData(ctx, &third.DeleteOutdatedDataReq{ExpireTime: deleteTime.UnixMilli(), ObjectGroup: config.CronTask.DeleteObjectType}) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.ZError(ctx, "cron deleteoutDatedData failed", err, "deleteTime", deleteTime, "cont", time.Since(now)) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			if resp.Count == 0 || resp.Count < int32(pageShowNumber) { | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		log.ZDebug(ctx, "cron deleteoutDatedData success", "deltime", deleteTime, "cont", time.Since(now)) | ||||||
|  | 	} | ||||||
|  | 	if _, err := crontab.AddFunc(config.CronTask.CronExecuteTime, deleteObjectFunc); err != nil { | ||||||
|  | 		return errs.Wrap(err) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	log.ZDebug(ctx, "start cron task", "CronExecuteTime", config.CronTask.CronExecuteTime) | 	log.ZDebug(ctx, "start cron task", "CronExecuteTime", config.CronTask.CronExecuteTime) | ||||||
| 	crontab.Start() | 	crontab.Start() | ||||||
|  | |||||||
| @ -113,9 +113,10 @@ type API struct { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type CronTask struct { | type CronTask struct { | ||||||
| 	CronExecuteTime   string `mapstructure:"cronExecuteTime"` | 	CronExecuteTime   string   `mapstructure:"cronExecuteTime"` | ||||||
| 	RetainChatRecords int    `mapstructure:"retainChatRecords"` | 	RetainChatRecords int      `mapstructure:"retainChatRecords"` | ||||||
| 	FileExpireTime    int    `mapstructure:"fileExpireTime"` | 	FileExpireTime    int      `mapstructure:"fileExpireTime"` | ||||||
|  | 	DeleteObjectType  []string `mapstructure:"deleteObjectType"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type OfflinePushConfig struct { | type OfflinePushConfig struct { | ||||||
| @ -369,20 +370,8 @@ type Share struct { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type MultiLogin struct { | type MultiLogin struct { | ||||||
| 	Policy            int `mapstructure:"policy"` | 	Policy       int `mapstructure:"policy"` | ||||||
| 	MaxNumOneEnd      int `mapstructure:"maxNumOneEnd"` | 	MaxNumOneEnd int `mapstructure:"maxNumOneEnd"` | ||||||
| 	CustomizeLoginNum struct { |  | ||||||
| 		IOS     int `mapstructure:"ios"` |  | ||||||
| 		Android int `mapstructure:"android"` |  | ||||||
| 		Windows int `mapstructure:"windows"` |  | ||||||
| 		OSX     int `mapstructure:"osx"` |  | ||||||
| 		Web     int `mapstructure:"web"` |  | ||||||
| 		MiniWeb int `mapstructure:"miniWeb"` |  | ||||||
| 		Linux   int `mapstructure:"linux"` |  | ||||||
| 		APad    int `mapstructure:"aPad"` |  | ||||||
| 		IPad    int `mapstructure:"iPad"` |  | ||||||
| 		Admin   int `mapstructure:"admin"` |  | ||||||
| 	} `mapstructure:"customizeLoginNum"` |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type RpcRegisterName struct { | type RpcRegisterName struct { | ||||||
|  | |||||||
| @ -38,7 +38,7 @@ const ( | |||||||
| func NewConversationRedis(rdb redis.UniversalClient, localCache *config.LocalCache, opts *rockscache.Options, db database.Conversation) cache.ConversationCache { | func NewConversationRedis(rdb redis.UniversalClient, localCache *config.LocalCache, opts *rockscache.Options, db database.Conversation) cache.ConversationCache { | ||||||
| 	batchHandler := NewBatchDeleterRedis(rdb, opts, []string{localCache.Conversation.Topic}) | 	batchHandler := NewBatchDeleterRedis(rdb, opts, []string{localCache.Conversation.Topic}) | ||||||
| 	c := localCache.Conversation | 	c := localCache.Conversation | ||||||
| 	log.ZDebug(context.Background(), "black local cache init", "Topic", c.Topic, "SlotNum", c.SlotNum, "SlotSize", c.SlotSize, "enable", c.Enable()) | 	log.ZDebug(context.Background(), "conversation local cache init", "Topic", c.Topic, "SlotNum", c.SlotNum, "SlotSize", c.SlotSize, "enable", c.Enable()) | ||||||
| 	return &ConversationRedisCache{ | 	return &ConversationRedisCache{ | ||||||
| 		BatchDeleter:   batchHandler, | 		BatchDeleter:   batchHandler, | ||||||
| 		rcClient:       rockscache.NewClient(rdb, *opts), | 		rcClient:       rockscache.NewClient(rdb, *opts), | ||||||
|  | |||||||
| @ -25,9 +25,8 @@ type AuthDatabase interface { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type multiLoginConfig struct { | type multiLoginConfig struct { | ||||||
| 	Policy            int | 	Policy       int | ||||||
| 	MaxNumOneEnd      int | 	MaxNumOneEnd int | ||||||
| 	CustomizeLoginNum map[int]int |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type authDatabase struct { | type authDatabase struct { | ||||||
| @ -35,25 +34,16 @@ type authDatabase struct { | |||||||
| 	accessSecret string | 	accessSecret string | ||||||
| 	accessExpire int64 | 	accessExpire int64 | ||||||
| 	multiLogin   multiLoginConfig | 	multiLogin   multiLoginConfig | ||||||
|  | 	adminUserIDs []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NewAuthDatabase(cache cache.TokenModel, accessSecret string, accessExpire int64, multiLogin config.MultiLogin) AuthDatabase { | func NewAuthDatabase(cache cache.TokenModel, accessSecret string, accessExpire int64, multiLogin config.MultiLogin, adminUserIDs []string) AuthDatabase { | ||||||
| 	return &authDatabase{cache: cache, accessSecret: accessSecret, accessExpire: accessExpire, multiLogin: multiLoginConfig{ | 	return &authDatabase{cache: cache, accessSecret: accessSecret, accessExpire: accessExpire, multiLogin: multiLoginConfig{ | ||||||
| 		Policy:       multiLogin.Policy, | 		Policy:       multiLogin.Policy, | ||||||
| 		MaxNumOneEnd: multiLogin.MaxNumOneEnd, | 		MaxNumOneEnd: multiLogin.MaxNumOneEnd, | ||||||
| 		CustomizeLoginNum: map[int]int{ | 	}, | ||||||
| 			constant.IOSPlatformID:        multiLogin.CustomizeLoginNum.IOS, | 		adminUserIDs: adminUserIDs, | ||||||
| 			constant.AndroidPlatformID:    multiLogin.CustomizeLoginNum.Android, | 	} | ||||||
| 			constant.WindowsPlatformID:    multiLogin.CustomizeLoginNum.Windows, |  | ||||||
| 			constant.OSXPlatformID:        multiLogin.CustomizeLoginNum.OSX, |  | ||||||
| 			constant.WebPlatformID:        multiLogin.CustomizeLoginNum.Web, |  | ||||||
| 			constant.MiniWebPlatformID:    multiLogin.CustomizeLoginNum.MiniWeb, |  | ||||||
| 			constant.LinuxPlatformID:      multiLogin.CustomizeLoginNum.Linux, |  | ||||||
| 			constant.AndroidPadPlatformID: multiLogin.CustomizeLoginNum.APad, |  | ||||||
| 			constant.IPadPlatformID:       multiLogin.CustomizeLoginNum.IPad, |  | ||||||
| 			constant.AdminPlatformID:      multiLogin.CustomizeLoginNum.Admin, |  | ||||||
| 		}, |  | ||||||
| 	}} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // If the result is empty. | // If the result is empty. | ||||||
| @ -90,27 +80,31 @@ func (a *authDatabase) BatchSetTokenMapByUidPid(ctx context.Context, tokens []st | |||||||
| 
 | 
 | ||||||
| // Create Token. | // Create Token. | ||||||
| func (a *authDatabase) CreateToken(ctx context.Context, userID string, platformID int) (string, error) { | func (a *authDatabase) CreateToken(ctx context.Context, userID string, platformID int) (string, error) { | ||||||
| 	tokens, err := a.cache.GetAllTokensWithoutError(ctx, userID) | 	isAdmin := authverify.IsManagerUserID(userID, a.adminUserIDs) | ||||||
| 	if err != nil { | 	if !isAdmin { | ||||||
| 		return "", err | 		tokens, err := a.cache.GetAllTokensWithoutError(ctx, userID) | ||||||
| 	} |  | ||||||
| 	deleteTokenKey, kickedTokenKey, err := a.checkToken(ctx, tokens, platformID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	if len(deleteTokenKey) != 0 { |  | ||||||
| 		err = a.cache.DeleteTokenByUidPid(ctx, userID, platformID, deleteTokenKey) |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return "", err | 			return "", err | ||||||
| 		} | 		} | ||||||
| 	} | 
 | ||||||
| 	if len(kickedTokenKey) != 0 { | 		deleteTokenKey, kickedTokenKey, err := a.checkToken(ctx, tokens, platformID) | ||||||
| 		for _, k := range kickedTokenKey { | 		if err != nil { | ||||||
| 			err := a.cache.SetTokenFlagEx(ctx, userID, platformID, k, constant.KickedToken) | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		if len(deleteTokenKey) != 0 { | ||||||
|  | 			err = a.cache.DeleteTokenByUidPid(ctx, userID, platformID, deleteTokenKey) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return "", err | 				return "", err | ||||||
| 			} | 			} | ||||||
| 			log.ZDebug(ctx, "kicked token in create token", "token", k) | 		} | ||||||
|  | 		if len(kickedTokenKey) != 0 { | ||||||
|  | 			for _, k := range kickedTokenKey { | ||||||
|  | 				err := a.cache.SetTokenFlagEx(ctx, userID, platformID, k, constant.KickedToken) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return "", err | ||||||
|  | 				} | ||||||
|  | 				log.ZDebug(ctx, "kicked token in create token", "token", k) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -121,9 +115,12 @@ func (a *authDatabase) CreateToken(ctx context.Context, userID string, platformI | |||||||
| 		return "", errs.WrapMsg(err, "token.SignedString") | 		return "", errs.WrapMsg(err, "token.SignedString") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err = a.cache.SetTokenFlagEx(ctx, userID, platformID, tokenString, constant.NormalToken); err != nil { | 	if !isAdmin { | ||||||
| 		return "", err | 		if err = a.cache.SetTokenFlagEx(ctx, userID, platformID, tokenString, constant.NormalToken); err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	return tokenString, nil | 	return tokenString, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -226,16 +223,16 @@ func (a *authDatabase) checkToken(ctx context.Context, tokens map[int]map[string | |||||||
| 		return nil, nil, errs.New("unknown multiLogin policy").Wrap() | 		return nil, nil, errs.New("unknown multiLogin policy").Wrap() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var adminTokenMaxNum = a.multiLogin.MaxNumOneEnd | 	//var adminTokenMaxNum = a.multiLogin.MaxNumOneEnd | ||||||
| 	if a.multiLogin.Policy == constant.Customize { | 	//if a.multiLogin.Policy == constant.Customize { | ||||||
| 		adminTokenMaxNum = a.multiLogin.CustomizeLoginNum[constant.AdminPlatformID] | 	//	adminTokenMaxNum = a.multiLogin.CustomizeLoginNum[constant.AdminPlatformID] | ||||||
| 	} | 	//} | ||||||
| 	l := len(adminToken) | 	//l := len(adminToken) | ||||||
| 	if platformID == constant.AdminPlatformID { | 	//if platformID == constant.AdminPlatformID { | ||||||
| 		l++ | 	//	l++ | ||||||
| 	} | 	//} | ||||||
| 	if l > adminTokenMaxNum { | 	//if l > adminTokenMaxNum { | ||||||
| 		kickToken = append(kickToken, adminToken[:l-adminTokenMaxNum]...) | 	//	kickToken = append(kickToken, adminToken[:l-adminTokenMaxNum]...) | ||||||
| 	} | 	//} | ||||||
| 	return deleteToken, kickToken, nil | 	return deleteToken, kickToken, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -372,7 +372,7 @@ func (db *commonMsgDatabase) getMsgBySeqsRange(ctx context.Context, userID strin | |||||||
| // This ensures that their message retrieval starts from the point they joined. | // This ensures that their message retrieval starts from the point they joined. | ||||||
| func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID string, conversationID string, begin, end, num, userMaxSeq int64) (int64, int64, []*sdkws.MsgData, error) { | func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID string, conversationID string, begin, end, num, userMaxSeq int64) (int64, int64, []*sdkws.MsgData, error) { | ||||||
| 	userMinSeq, err := db.seqUser.GetUserMinSeq(ctx, conversationID, userID) | 	userMinSeq, err := db.seqUser.GetUserMinSeq(ctx, conversationID, userID) | ||||||
| 	if err != nil && errs.Unwrap(err) != redis.Nil { | 	if err != nil && !errors.Is(err, redis.Nil) { | ||||||
| 		return 0, 0, nil, err | 		return 0, 0, nil, err | ||||||
| 	} | 	} | ||||||
| 	minSeq, err := db.seqConversation.GetMinSeq(ctx, conversationID) | 	minSeq, err := db.seqConversation.GetMinSeq(ctx, conversationID) | ||||||
| @ -444,10 +444,10 @@ func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID strin | |||||||
| 		} | 		} | ||||||
| 		successMsgs = append(mongoMsgs, successMsgs...) | 		successMsgs = append(mongoMsgs, successMsgs...) | ||||||
| 
 | 
 | ||||||
| 		_, err = db.msg.SetMessagesToCache(ctx, conversationID, mongoMsgs) | 		//_, err = db.msg.SetMessagesToCache(ctx, conversationID, mongoMsgs) | ||||||
| 		if err != nil { | 		//if err != nil { | ||||||
| 			return 0, 0, nil, err | 		//	return 0, 0, nil, err | ||||||
| 		} | 		//} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return minSeq, maxSeq, successMsgs, nil | 	return minSeq, maxSeq, successMsgs, nil | ||||||
| @ -490,8 +490,8 @@ func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, co | |||||||
| 	} | 	} | ||||||
| 	successMsgs, failedSeqs, err := db.msg.GetMessagesBySeq(ctx, conversationID, newSeqs) | 	successMsgs, failedSeqs, err := db.msg.GetMessagesBySeq(ctx, conversationID, newSeqs) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if err != redis.Nil { | 		if !errors.Is(err, redis.Nil) { | ||||||
| 			log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID) | 			log.ZWarn(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	log.ZDebug(ctx, "db.seq.GetMessagesBySeq", "userID", userID, "conversationID", conversationID, "seqs", | 	log.ZDebug(ctx, "db.seq.GetMessagesBySeq", "userID", userID, "conversationID", conversationID, "seqs", | ||||||
| @ -506,10 +506,10 @@ func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, co | |||||||
| 
 | 
 | ||||||
| 		successMsgs = append(successMsgs, mongoMsgs...) | 		successMsgs = append(successMsgs, mongoMsgs...) | ||||||
| 
 | 
 | ||||||
| 		_, err = db.msg.SetMessagesToCache(ctx, conversationID, mongoMsgs) | 		//_, err = db.msg.SetMessagesToCache(ctx, conversationID, mongoMsgs) | ||||||
| 		if err != nil { | 		//if err != nil { | ||||||
| 			return 0, 0, nil, err | 		//	return 0, 0, nil, err | ||||||
| 		} | 		//} | ||||||
| 	} | 	} | ||||||
| 	return minSeq, maxSeq, successMsgs, nil | 	return minSeq, maxSeq, successMsgs, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -40,10 +40,10 @@ type S3Database interface { | |||||||
| 	SetObject(ctx context.Context, info *model.Object) error | 	SetObject(ctx context.Context, info *model.Object) error | ||||||
| 	StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error) | 	StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error) | ||||||
| 	FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) | 	FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) | ||||||
| 	FindByExpires(ctx context.Context, duration time.Time, pagination pagination.Pagination) (total int64, objects []*model.Object, err error) | 	FindNeedDeleteObjectByDB(ctx context.Context, duration time.Time, needDelType []string, pagination pagination.Pagination) (total int64, objects []*model.Object, err error) | ||||||
| 	DeleteObject(ctx context.Context, name string) error | 	DeleteObject(ctx context.Context, name string) error | ||||||
| 	DeleteSpecifiedData(ctx context.Context, engine string, name string) error | 	DeleteSpecifiedData(ctx context.Context, engine string, name string) error | ||||||
| 	FindNotDelByS3(ctx context.Context, key string, duration time.Time) (int64, error) | 	FindModelsByKey(ctx context.Context, key string) (objects []*model.Object, err error) | ||||||
| 	DelS3Key(ctx context.Context, engine string, keys ...string) error | 	DelS3Key(ctx context.Context, engine string, keys ...string) error | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -120,9 +120,8 @@ func (s *s3Database) StatObject(ctx context.Context, name string) (*s3.ObjectInf | |||||||
| func (s *s3Database) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) { | func (s *s3Database) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) { | ||||||
| 	return s.s3.FormData(ctx, name, size, contentType, duration) | 	return s.s3.FormData(ctx, name, size, contentType, duration) | ||||||
| } | } | ||||||
| func (s *s3Database) FindByExpires(ctx context.Context, duration time.Time, pagination pagination.Pagination) (total int64, objects []*model.Object, err error) { | func (s *s3Database) FindNeedDeleteObjectByDB(ctx context.Context, duration time.Time, needDelType []string, pagination pagination.Pagination) (total int64, objects []*model.Object, err error) { | ||||||
| 
 | 	return s.db.FindNeedDeleteObjectByDB(ctx, duration, needDelType, pagination) | ||||||
| 	return s.db.FindByExpires(ctx, duration, pagination) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (s *s3Database) DeleteObject(ctx context.Context, name string) error { | func (s *s3Database) DeleteObject(ctx context.Context, name string) error { | ||||||
| @ -132,8 +131,8 @@ func (s *s3Database) DeleteSpecifiedData(ctx context.Context, engine string, nam | |||||||
| 	return s.db.Delete(ctx, engine, name) | 	return s.db.Delete(ctx, engine, name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (s *s3Database) FindNotDelByS3(ctx context.Context, key string, duration time.Time) (int64, error) { | func (s *s3Database) FindModelsByKey(ctx context.Context, key string) (objects []*model.Object, err error) { | ||||||
| 	return s.db.FindNotDelByS3(ctx, key, duration) | 	return s.db.FindModelsByKey(ctx, key) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (s *s3Database) DelS3Key(ctx context.Context, engine string, keys ...string) error { | func (s *s3Database) DelS3Key(ctx context.Context, engine string, keys ...string) error { | ||||||
|  | |||||||
| @ -31,6 +31,8 @@ import ( | |||||||
| 
 | 
 | ||||||
| func NewS3Mongo(db *mongo.Database) (database.ObjectInfo, error) { | func NewS3Mongo(db *mongo.Database) (database.ObjectInfo, error) { | ||||||
| 	coll := db.Collection(database.ObjectName) | 	coll := db.Collection(database.ObjectName) | ||||||
|  | 
 | ||||||
|  | 	// Create index for name | ||||||
| 	_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{ | 	_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{ | ||||||
| 		Keys: bson.D{ | 		Keys: bson.D{ | ||||||
| 			{Key: "name", Value: 1}, | 			{Key: "name", Value: 1}, | ||||||
| @ -40,6 +42,27 @@ func NewS3Mongo(db *mongo.Database) (database.ObjectInfo, error) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, errs.Wrap(err) | 		return nil, errs.Wrap(err) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	// Create index for create_time | ||||||
|  | 	_, err = coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{ | ||||||
|  | 		Keys: bson.D{ | ||||||
|  | 			{Key: "create_time", Value: 1}, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, errs.Wrap(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Create index for key | ||||||
|  | 	_, err = coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{ | ||||||
|  | 		Keys: bson.D{ | ||||||
|  | 			{Key: "key", Value: 1}, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, errs.Wrap(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return &S3Mongo{coll: coll}, nil | 	return &S3Mongo{coll: coll}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -71,14 +94,18 @@ func (o *S3Mongo) Take(ctx context.Context, engine string, name string) (*model. | |||||||
| func (o *S3Mongo) Delete(ctx context.Context, engine string, name string) error { | func (o *S3Mongo) Delete(ctx context.Context, engine string, name string) error { | ||||||
| 	return mongoutil.DeleteOne(ctx, o.coll, bson.M{"name": name, "engine": engine}) | 	return mongoutil.DeleteOne(ctx, o.coll, bson.M{"name": name, "engine": engine}) | ||||||
| } | } | ||||||
| func (o *S3Mongo) FindByExpires(ctx context.Context, duration time.Time, pagination pagination.Pagination) (total int64, objects []*model.Object, err error) { | 
 | ||||||
|  | // Find Expires object | ||||||
|  | func (o *S3Mongo) FindNeedDeleteObjectByDB(ctx context.Context, duration time.Time, needDelType []string, pagination pagination.Pagination) (total int64, objects []*model.Object, err error) { | ||||||
| 	return mongoutil.FindPage[*model.Object](ctx, o.coll, bson.M{ | 	return mongoutil.FindPage[*model.Object](ctx, o.coll, bson.M{ | ||||||
| 		"create_time": bson.M{"$lt": duration}, | 		"create_time": bson.M{"$lt": duration}, | ||||||
|  | 		"group":       bson.M{"$in": needDelType}, | ||||||
| 	}, pagination) | 	}, pagination) | ||||||
| } | } | ||||||
| func (o *S3Mongo) FindNotDelByS3(ctx context.Context, key string, duration time.Time) (int64, error) { | 
 | ||||||
| 	return mongoutil.Count(ctx, o.coll, bson.M{ | // Find object by key | ||||||
| 		"key":         key, | func (o *S3Mongo) FindModelsByKey(ctx context.Context, key string) (objects []*model.Object, err error) { | ||||||
| 		"create_time": bson.M{"$gt": duration}, | 	return mongoutil.Find[*model.Object](ctx, o.coll, bson.M{ | ||||||
|  | 		"key": key, | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  | |||||||
| @ -26,6 +26,6 @@ type ObjectInfo interface { | |||||||
| 	SetObject(ctx context.Context, obj *model.Object) error | 	SetObject(ctx context.Context, obj *model.Object) error | ||||||
| 	Take(ctx context.Context, engine string, name string) (*model.Object, error) | 	Take(ctx context.Context, engine string, name string) (*model.Object, error) | ||||||
| 	Delete(ctx context.Context, engine string, name string) error | 	Delete(ctx context.Context, engine string, name string) error | ||||||
| 	FindByExpires(ctx context.Context, duration time.Time, pagination pagination.Pagination) (total int64, objects []*model.Object, err error) | 	FindNeedDeleteObjectByDB(ctx context.Context, duration time.Time, needDelType []string, pagination pagination.Pagination) (total int64, objects []*model.Object, err error) | ||||||
| 	FindNotDelByS3(ctx context.Context, key string, duration time.Time) (int64, error) | 	FindModelsByKey(ctx context.Context, key string) (objects []*model.Object, err error) | ||||||
| } | } | ||||||
|  | |||||||
| @ -17,12 +17,18 @@ package rpccache | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
|  | 	"github.com/openimsdk/tools/mw" | ||||||
| 
 | 
 | ||||||
| 	"github.com/openimsdk/tools/log" | 	"github.com/openimsdk/tools/log" | ||||||
| 	"github.com/redis/go-redis/v9" | 	"github.com/redis/go-redis/v9" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func subscriberRedisDeleteCache(ctx context.Context, client redis.UniversalClient, channel string, del func(ctx context.Context, key ...string)) { | func subscriberRedisDeleteCache(ctx context.Context, client redis.UniversalClient, channel string, del func(ctx context.Context, key ...string)) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			mw.PanicStackToLog(ctx, r) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
| 	for message := range client.Subscribe(ctx, channel).Channel() { | 	for message := range client.Subscribe(ctx, channel).Channel() { | ||||||
| 		log.ZDebug(ctx, "subscriberRedisDeleteCache", "channel", channel, "payload", message.Payload) | 		log.ZDebug(ctx, "subscriberRedisDeleteCache", "channel", channel, "payload", message.Payload) | ||||||
| 		var keys []string | 		var keys []string | ||||||
|  | |||||||
							
								
								
									
										198
									
								
								tools/changelog/changelog.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								tools/changelog/changelog.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,198 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"net/http" | ||||||
|  | 	"os" | ||||||
|  | 	"regexp" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // You can specify a tag as a command line argument to generate the changelog for a specific version. | ||||||
|  | // Example: go run tools/changelog/changelog.go v0.0.33 | ||||||
|  | // If no tag is provided, the latest release will be used. | ||||||
|  | 
 | ||||||
|  | // Setting repo owner and repo name by generate changelog | ||||||
|  | const ( | ||||||
|  | 	repoOwner = "openimsdk" | ||||||
|  | 	repoName  = "open-im-server" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // GitHubRepo struct represents the repo details. | ||||||
|  | type GitHubRepo struct { | ||||||
|  | 	Owner         string | ||||||
|  | 	Repo          string | ||||||
|  | 	FullChangelog string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ReleaseData represents the JSON structure for release data. | ||||||
|  | type ReleaseData struct { | ||||||
|  | 	TagName   string `json:"tag_name"` | ||||||
|  | 	Body      string `json:"body"` | ||||||
|  | 	HtmlUrl   string `json:"html_url"` | ||||||
|  | 	Published string `json:"published_at"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Method to classify and format release notes. | ||||||
|  | func (g *GitHubRepo) classifyReleaseNotes(body string) map[string][]string { | ||||||
|  | 	result := map[string][]string{ | ||||||
|  | 		"feat":     {}, | ||||||
|  | 		"fix":      {}, | ||||||
|  | 		"chore":    {}, | ||||||
|  | 		"refactor": {}, | ||||||
|  | 		"build":    {}, | ||||||
|  | 		"other":    {}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Regular expression to extract PR number and URL (case insensitive) | ||||||
|  | 	rePR := regexp.MustCompile(`(?i)in (https://github\.com/[^\s]+/pull/(\d+))`) | ||||||
|  | 
 | ||||||
|  | 	// Split the body into individual lines. | ||||||
|  | 	lines := strings.Split(body, "\n") | ||||||
|  | 
 | ||||||
|  | 	for _, line := range lines { | ||||||
|  | 		// Skip lines that contain "deps: Merge" | ||||||
|  | 		if strings.Contains(strings.ToLower(line), "deps: merge #") { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Use a regular expression to extract Full Changelog link and its title (case insensitive). | ||||||
|  | 		if strings.Contains(strings.ToLower(line), "**full changelog**") { | ||||||
|  | 			matches := regexp.MustCompile(`(?i)\*\*full changelog\*\*: (https://github\.com/[^\s]+/compare/([^\s]+))`).FindStringSubmatch(line) | ||||||
|  | 			if len(matches) > 2 { | ||||||
|  | 				// Format the Full Changelog link with title | ||||||
|  | 				g.FullChangelog = fmt.Sprintf("[%s](%s)", matches[2], matches[1]) | ||||||
|  | 			} | ||||||
|  | 			continue // Skip further processing for this line. | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if strings.HasPrefix(line, "*") { | ||||||
|  | 			var category string | ||||||
|  | 
 | ||||||
|  | 			// Use strings.ToLower to make the matching case insensitive | ||||||
|  | 			lowerLine := strings.ToLower(line) | ||||||
|  | 
 | ||||||
|  | 			// Determine the category based on the prefix (case insensitive). | ||||||
|  | 			if strings.HasPrefix(lowerLine, "* feat") { | ||||||
|  | 				category = "feat" | ||||||
|  | 			} else if strings.HasPrefix(lowerLine, "* fix") { | ||||||
|  | 				category = "fix" | ||||||
|  | 			} else if strings.HasPrefix(lowerLine, "* chore") { | ||||||
|  | 				category = "chore" | ||||||
|  | 			} else if strings.HasPrefix(lowerLine, "* refactor") { | ||||||
|  | 				category = "refactor" | ||||||
|  | 			} else if strings.HasPrefix(lowerLine, "* build") { | ||||||
|  | 				category = "build" | ||||||
|  | 			} else { | ||||||
|  | 				category = "other" | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Extract PR number and URL (case insensitive) | ||||||
|  | 			matches := rePR.FindStringSubmatch(line) | ||||||
|  | 			if len(matches) == 3 { | ||||||
|  | 				prURL := matches[1] | ||||||
|  | 				prNumber := matches[2] | ||||||
|  | 				// Format the line with the PR link and use original content for the final result | ||||||
|  | 				formattedLine := fmt.Sprintf("* %s [#%s](%s)", strings.Split(line, " by ")[0][2:], prNumber, prURL) | ||||||
|  | 				result[category] = append(result[category], formattedLine) | ||||||
|  | 			} else { | ||||||
|  | 				// If no PR link is found, just add the line as is | ||||||
|  | 				result[category] = append(result[category], line) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return result | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Method to generate the final changelog. | ||||||
|  | func (g *GitHubRepo) generateChangelog(tag, date, htmlURL, body string) string { | ||||||
|  | 	sections := g.classifyReleaseNotes(body) | ||||||
|  | 
 | ||||||
|  | 	// Convert ISO 8601 date to simpler format (YYYY-MM-DD) | ||||||
|  | 	formattedDate := date[:10] | ||||||
|  | 
 | ||||||
|  | 	// Changelog header with tag, date, and links. | ||||||
|  | 	changelog := fmt.Sprintf("## [%s](%s) \t(%s)\n\n", tag, htmlURL, formattedDate) | ||||||
|  | 
 | ||||||
|  | 	if len(sections["feat"]) > 0 { | ||||||
|  | 		changelog += "### New Features\n" + strings.Join(sections["feat"], "\n") + "\n\n" | ||||||
|  | 	} | ||||||
|  | 	if len(sections["fix"]) > 0 { | ||||||
|  | 		changelog += "### Bug Fixes\n" + strings.Join(sections["fix"], "\n") + "\n\n" | ||||||
|  | 	} | ||||||
|  | 	if len(sections["chore"]) > 0 { | ||||||
|  | 		changelog += "### Chores\n" + strings.Join(sections["chore"], "\n") + "\n\n" | ||||||
|  | 	} | ||||||
|  | 	if len(sections["refactor"]) > 0 { | ||||||
|  | 		changelog += "### Refactors\n" + strings.Join(sections["refactor"], "\n") + "\n\n" | ||||||
|  | 	} | ||||||
|  | 	if len(sections["build"]) > 0 { | ||||||
|  | 		changelog += "### Builds\n" + strings.Join(sections["build"], "\n") + "\n\n" | ||||||
|  | 	} | ||||||
|  | 	if len(sections["other"]) > 0 { | ||||||
|  | 		changelog += "### Others\n" + strings.Join(sections["other"], "\n") + "\n\n" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if g.FullChangelog != "" { | ||||||
|  | 		changelog += fmt.Sprintf("**Full Changelog**: %s\n", g.FullChangelog) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return changelog | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Method to fetch release data from GitHub API. | ||||||
|  | func (g *GitHubRepo) fetchReleaseData(version string) (*ReleaseData, error) { | ||||||
|  | 	var apiURL string | ||||||
|  | 
 | ||||||
|  | 	if version == "" { | ||||||
|  | 		// Fetch the latest release. | ||||||
|  | 		apiURL = fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", g.Owner, g.Repo) | ||||||
|  | 	} else { | ||||||
|  | 		// Fetch a specific version. | ||||||
|  | 		apiURL = fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/tags/%s", g.Owner, g.Repo, version) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	resp, err := http.Get(apiURL) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	defer resp.Body.Close() | ||||||
|  | 
 | ||||||
|  | 	body, err := io.ReadAll(resp.Body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var releaseData ReleaseData | ||||||
|  | 	err = json.Unmarshal(body, &releaseData) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &releaseData, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	repo := &GitHubRepo{Owner: repoOwner, Repo: repoName} | ||||||
|  | 
 | ||||||
|  | 	// Get the version from command line arguments, if provided | ||||||
|  | 	var version string // Default is use latest | ||||||
|  | 
 | ||||||
|  | 	if len(os.Args) > 1 { | ||||||
|  | 		version = os.Args[1] // Use the provided version | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Fetch release data (either for latest or specific version) | ||||||
|  | 	releaseData, err := repo.fetchReleaseData(version) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println("Error fetching release data:", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Generate and print the formatted changelog | ||||||
|  | 	changelog := repo.generateChangelog(releaseData.TagName, releaseData.Published, releaseData.HtmlUrl, releaseData.Body) | ||||||
|  | 	fmt.Println(changelog) | ||||||
|  | } | ||||||
| @ -1,308 +0,0 @@ | |||||||
| // Copyright © 2023 OpenIM. All rights reserved. |  | ||||||
| // |  | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
| // you may not use this file except in compliance with the License. |  | ||||||
| // You may obtain a copy of the License at |  | ||||||
| // |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
| // |  | ||||||
| // Unless required by applicable law or agreed to in writing, software |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
| // See the License for the specific language governing permissions and |  | ||||||
| // limitations under the License. |  | ||||||
| 
 |  | ||||||
| package main |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"log" |  | ||||||
| 	"os" |  | ||||||
| 	"os/exec" |  | ||||||
| 	"regexp" |  | ||||||
| 	"sort" |  | ||||||
| 	"strings" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| var ( |  | ||||||
| 	mergeRequest   = regexp.MustCompile(`Merge pull request #([\d]+)`) |  | ||||||
| 	webconsoleBump = regexp.MustCompile(regexp.QuoteMeta("bump(github.com/openshift/origin-web-console): ") + `([\w]+)`) |  | ||||||
| 	upstreamKube   = regexp.MustCompile(`^UPSTREAM: (\d+)+:(.+)`) |  | ||||||
| 	upstreamRepo   = regexp.MustCompile(`^UPSTREAM: ([\w/-]+): (\d+)+:(.+)`) |  | ||||||
| 	prefix         = regexp.MustCompile(`^[\w-]: `) |  | ||||||
| 
 |  | ||||||
| 	assignments = []prefixAssignment{ |  | ||||||
| 		{"cluster up", "cluster"}, |  | ||||||
| 		{" pv ", "storage"}, |  | ||||||
| 		{"haproxy", "router"}, |  | ||||||
| 		{"router", "router"}, |  | ||||||
| 		{"route", "route"}, |  | ||||||
| 		{"authoriz", "auth"}, |  | ||||||
| 		{"rbac", "auth"}, |  | ||||||
| 		{"authent", "auth"}, |  | ||||||
| 		{"reconcil", "auth"}, |  | ||||||
| 		{"auth", "auth"}, |  | ||||||
| 		{"role", "auth"}, |  | ||||||
| 		{" dc ", "deploy"}, |  | ||||||
| 		{"deployment", "deploy"}, |  | ||||||
| 		{"rolling", "deploy"}, |  | ||||||
| 		{"security context constr", "security"}, |  | ||||||
| 		{"scc", "security"}, |  | ||||||
| 		{"pipeline", "build"}, |  | ||||||
| 		{"build", "build"}, |  | ||||||
| 		{"registry", "registry"}, |  | ||||||
| 		{"registries", "image"}, |  | ||||||
| 		{"image", "image"}, |  | ||||||
| 		{" arp ", "network"}, |  | ||||||
| 		{" cni ", "network"}, |  | ||||||
| 		{"egress", "network"}, |  | ||||||
| 		{"network", "network"}, |  | ||||||
| 		{"oc ", "cli"}, |  | ||||||
| 		{"template", "template"}, |  | ||||||
| 		{"etcd", "server"}, |  | ||||||
| 		{"pod", "node"}, |  | ||||||
| 		{"scripts/", "hack"}, |  | ||||||
| 		{"e2e", "test"}, |  | ||||||
| 		{"integration", "test"}, |  | ||||||
| 		{"cluster", "cluster"}, |  | ||||||
| 		{"master", "server"}, |  | ||||||
| 		{"packages", "hack"}, |  | ||||||
| 		{"api", "server"}, |  | ||||||
| 	} |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| type prefixAssignment struct { |  | ||||||
| 	term   string |  | ||||||
| 	prefix string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type commit struct { |  | ||||||
| 	short   string |  | ||||||
| 	parents []string |  | ||||||
| 	message string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func contains(arr []string, value string) bool { |  | ||||||
| 	for _, s := range arr { |  | ||||||
| 		if s == value { |  | ||||||
| 			return true |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return false |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func main() { |  | ||||||
| 	log.SetFlags(0) |  | ||||||
| 	if len(os.Args) != 3 { |  | ||||||
| 		log.Fatalf("Must specify two arguments, FROM and TO") |  | ||||||
| 	} |  | ||||||
| 	from := os.Args[1] |  | ||||||
| 	to := os.Args[2] |  | ||||||
| 
 |  | ||||||
| 	out, err := exec.Command("git", "log", "--topo-order", "--pretty=tformat:%h %p|%s", "--reverse", fmt.Sprintf("%s..%s", from, to)).CombinedOutput() |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	hide := make(map[string]struct{}) |  | ||||||
| 	var apiChanges []string |  | ||||||
| 	var webconsole []string |  | ||||||
| 	var commits []commit |  | ||||||
| 	var upstreams []commit |  | ||||||
| 	var bumps []commit |  | ||||||
| 	for _, line := range strings.Split(string(out), "\n") { |  | ||||||
| 		if len(strings.TrimSpace(line)) == 0 { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		parts := strings.SplitN(line, "|", 2) |  | ||||||
| 		hashes := strings.Split(parts[0], " ") |  | ||||||
| 		c := commit{short: hashes[0], parents: hashes[1:], message: parts[1]} |  | ||||||
| 
 |  | ||||||
| 		if strings.HasPrefix(c.message, "UPSTREAM: ") { |  | ||||||
| 			hide[c.short] = struct{}{} |  | ||||||
| 			upstreams = append(upstreams, c) |  | ||||||
| 		} |  | ||||||
| 		if strings.HasPrefix(c.message, "bump(") { |  | ||||||
| 			hide[c.short] = struct{}{} |  | ||||||
| 			bumps = append(bumps, c) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if len(c.parents) == 1 { |  | ||||||
| 			commits = append(commits, c) |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		matches := mergeRequest.FindStringSubmatch(line) |  | ||||||
| 		if len(matches) == 0 { |  | ||||||
| 			// this may have been a human pressing the merge button, we'll just record this as a direct push |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// split the accumulated commits into any that are force merges (assumed to be the initial set due |  | ||||||
| 		// to --topo-order) from the PR commits as soon as we see any of our merge parents. Then print |  | ||||||
| 		// any of the force merges |  | ||||||
| 		var first int |  | ||||||
| 		for i := range commits { |  | ||||||
| 			first = i |  | ||||||
| 			if contains(c.parents, commits[i].short) { |  | ||||||
| 				first++ |  | ||||||
| 				break |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		individual := commits[:first] |  | ||||||
| 		merged := commits[first:] |  | ||||||
| 		for _, commit := range individual { |  | ||||||
| 			if len(commit.parents) > 1 { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			if _, ok := hide[commit.short]; ok { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			fmt.Printf("force-merge: %s %s\n", commit.message, commit.short) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// try to find either the PR title or the first commit title from the merge commit |  | ||||||
| 		out, err := exec.Command("git", "show", "--pretty=tformat:%b", c.short).CombinedOutput() |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatal(err) |  | ||||||
| 		} |  | ||||||
| 		var message string |  | ||||||
| 		para := strings.Split(string(out), "\n\n") |  | ||||||
| 		if len(para) > 0 && strings.HasPrefix(para[0], "Automatic merge from submit-queue") { |  | ||||||
| 			para = para[1:] |  | ||||||
| 		} |  | ||||||
| 		// this is no longer necessary with the submit queue in place |  | ||||||
| 		if len(para) > 0 && strings.HasPrefix(para[0], "Merged by ") { |  | ||||||
| 			para = para[1:] |  | ||||||
| 		} |  | ||||||
| 		// post submit-queue, the merge bot will add the PR title, which is usually pretty good |  | ||||||
| 		if len(para) > 0 { |  | ||||||
| 			message = strings.Split(para[0], "\n")[0] |  | ||||||
| 		} |  | ||||||
| 		if len(message) == 0 && len(merged) > 0 { |  | ||||||
| 			message = merged[0].message |  | ||||||
| 		} |  | ||||||
| 		if len(message) > 0 && len(merged) == 1 && message == merged[0].message { |  | ||||||
| 			merged = nil |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// try to calculate a prefix based on the diff |  | ||||||
| 		if len(message) > 0 && !prefix.MatchString(message) { |  | ||||||
| 			prefix, ok := findPrefixFor(message, merged) |  | ||||||
| 			if ok { |  | ||||||
| 				message = prefix + ": " + message |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// github merge |  | ||||||
| 
 |  | ||||||
| 		// has api changes |  | ||||||
| 		display := fmt.Sprintf("%s [\\#%s](https://github.com/openimsdk/Open-IM-Server/pull/%s)", message, matches[1], matches[1]) |  | ||||||
| 		if hasFileChanges(c.short, "pkg/apistruct/") { |  | ||||||
| 			apiChanges = append(apiChanges, display) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		var filtered []commit |  | ||||||
| 		for _, commit := range merged { |  | ||||||
| 			if _, ok := hide[commit.short]; ok { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			filtered = append(filtered, commit) |  | ||||||
| 		} |  | ||||||
| 		if len(filtered) > 0 { |  | ||||||
| 			fmt.Printf("- %s\n", display) |  | ||||||
| 			for _, commit := range filtered { |  | ||||||
| 				fmt.Printf("  - %s (%s)\n", commit.message, commit.short) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// stick the merge commit in at the beginning of the next list so we can anchor the previous parent |  | ||||||
| 		commits = []commit{c} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// chunk the bumps |  | ||||||
| 	var lines []string |  | ||||||
| 	for _, commit := range bumps { |  | ||||||
| 		if m := webconsoleBump.FindStringSubmatch(commit.message); len(m) > 0 { |  | ||||||
| 			webconsole = append(webconsole, m[1]) |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		lines = append(lines, commit.message) |  | ||||||
| 	} |  | ||||||
| 	lines = sortAndUniq(lines) |  | ||||||
| 	for _, line := range lines { |  | ||||||
| 		fmt.Printf("- %s\n", line) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// chunk the upstreams |  | ||||||
| 	lines = nil |  | ||||||
| 	for _, commit := range upstreams { |  | ||||||
| 		lines = append(lines, commit.message) |  | ||||||
| 	} |  | ||||||
| 	lines = sortAndUniq(lines) |  | ||||||
| 	for _, line := range lines { |  | ||||||
| 		fmt.Printf("- %s\n", upstreamLinkify(line)) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if len(webconsole) > 0 { |  | ||||||
| 		fmt.Printf("- web: from %s^..%s\n", webconsole[0], webconsole[len(webconsole)-1]) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, apiChange := range apiChanges { |  | ||||||
| 		fmt.Printf("  - %s\n", apiChange) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func findPrefixFor(message string, commits []commit) (string, bool) { |  | ||||||
| 	message = strings.ToLower(message) |  | ||||||
| 	for _, m := range assignments { |  | ||||||
| 		if strings.Contains(message, m.term) { |  | ||||||
| 			return m.prefix, true |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	for _, c := range commits { |  | ||||||
| 		if prefix, ok := findPrefixFor(c.message, nil); ok { |  | ||||||
| 			return prefix, ok |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return "", false |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func hasFileChanges(commit string, prefixes ...string) bool { |  | ||||||
| 	out, err := exec.Command("git", "diff", "--name-only", fmt.Sprintf("%s^..%s", commit, commit)).CombinedOutput() |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 	for _, file := range strings.Split(string(out), "\n") { |  | ||||||
| 		for _, prefix := range prefixes { |  | ||||||
| 			if strings.HasPrefix(file, prefix) { |  | ||||||
| 				return true |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return false |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func sortAndUniq(lines []string) []string { |  | ||||||
| 	sort.Strings(lines) |  | ||||||
| 	out := make([]string, 0, len(lines)) |  | ||||||
| 	last := "" |  | ||||||
| 	for _, s := range lines { |  | ||||||
| 		if last == s { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		last = s |  | ||||||
| 		out = append(out, s) |  | ||||||
| 	} |  | ||||||
| 	return out |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func upstreamLinkify(line string) string { |  | ||||||
| 	if m := upstreamKube.FindStringSubmatch(line); len(m) > 0 { |  | ||||||
| 		return fmt.Sprintf("UPSTREAM: [#%s](https://github.com/openimsdk/open-im-server/pull/%s):%s", m[1], m[1], m[2]) |  | ||||||
| 	} |  | ||||||
| 	if m := upstreamRepo.FindStringSubmatch(line); len(m) > 0 { |  | ||||||
| 		return fmt.Sprintf("UPSTREAM: [%s#%s](https://github.com/%s/pull/%s):%s", m[1], m[2], m[1], m[2], m[3]) |  | ||||||
| 	} |  | ||||||
| 	return line |  | ||||||
| } |  | ||||||
| @ -1 +1 @@ | |||||||
| 3.8.1 | main | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user