From c5891b4e8bb03a328c3932d88cfeccaaf692a9fc Mon Sep 17 00:00:00 2001 From: chao <48119764+withchao@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:47:08 +0800 Subject: [PATCH 1/8] feat: support conversation input status and wasm websocket message returns the connection status (#463) * entering * entering * entering * entering * entering * wasm callback * wasm callback * ws --- go.mod | 4 +- go.sum | 62 +---- internal/conversation_msg/conversation_msg.go | 28 +++ internal/conversation_msg/entering.go | 217 ++++++++++++++++++ internal/interaction/long_conn_mgr.go | 41 ++-- internal/interaction/ws_js.go | 44 +++- msgtest/sdk_user_simulator/listener.go | 4 + open_im_sdk/apicb.go | 2 + open_im_sdk/conversation_msg.go | 8 + open_im_sdk/em.go | 4 + open_im_sdk/userRelated.go | 1 + open_im_sdk_callback/callback_client.go | 1 + pkg/constant/constant.go | 1 + sdk_struct/sdk_struct.go | 6 + test/t_friend_sdk.go | 4 + testv2/config.go | 6 +- testv2/empty_test.go | 14 +- testv2/init.go | 6 +- wasm/cmd/main.go | 3 + wasm/event_listener/listener.go | 4 + wasm/wasm_wrapper/wasm_conversation_msg.go | 10 + 21 files changed, 386 insertions(+), 84 deletions(-) create mode 100644 internal/conversation_msg/entering.go diff --git a/go.mod b/go.mod index cc825ee2d..1c8f38e27 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20220106031843-2efeb10ca2f6 google.golang.org/protobuf v1.31.0 // indirect gorm.io/driver/sqlite v1.3.6 - nhooyr.io/websocket v1.8.7 + nhooyr.io/websocket v1.8.10 ) require golang.org/x/net v0.19.0 @@ -21,6 +21,7 @@ require ( github.com/OpenIMSDK/protocol v0.0.40 github.com/OpenIMSDK/tools v0.0.5 github.com/google/go-cmp v0.5.9 + github.com/patrickmn/go-cache v2.1.0+incompatible golang.org/x/image v0.14.0 gorm.io/gorm v1.23.8 ) @@ -29,7 +30,6 @@ require ( github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.16.5 // indirect github.com/lestrrat-go/strftime v1.0.6 // indirect github.com/mattn/go-sqlite3 v1.14.12 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect diff --git a/go.sum b/go.sum index daf2ec7fc..0e9d2df15 100644 --- a/go.sum +++ b/go.sum @@ -5,41 +5,15 @@ github.com/OpenIMSDK/tools v0.0.5/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= -github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= @@ -50,48 +24,29 @@ github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= -github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20220106031843-2efeb10ca2f6 h1:SLcMxS3gIswMN5mHHeVo+85lHBau10lZmrZ3Ukji510= github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20220106031843-2efeb10ca2f6/go.mod h1:b18KQa4IxHbxeseW1GcZox53d7J0z39VNONTxvvlkXw= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= @@ -99,20 +54,14 @@ go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 h1:XUODHrpzJEUeWmVo/jfNTLj0YyVveOo28oE6vkFbkO4= google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= @@ -122,14 +71,11 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gorm.io/driver/sqlite v1.3.6 h1:Fi8xNYCUplOqWiPa3/GuCeowRNBRGTf62DEmhMDHeQQ= gorm.io/driver/sqlite v1.3.6/go.mod h1:Sg1/pvnKtbQ7jLXxfZa+jSHvoX8hoZA8cn4xllOMTgE= gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= +nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= diff --git a/internal/conversation_msg/conversation_msg.go b/internal/conversation_msg/conversation_msg.go index fdc32425c..d2d35671d 100644 --- a/internal/conversation_msg/conversation_msg.go +++ b/internal/conversation_msg/conversation_msg.go @@ -56,6 +56,7 @@ type Conversation struct { msgListener func() open_im_sdk_callback.OnAdvancedMsgListener msgKvListener func() open_im_sdk_callback.OnMessageKvInfoListener batchMsgListener func() open_im_sdk_callback.OnBatchMsgListener + userListener func() open_im_sdk_callback.OnUserListener recvCH chan common.Cmd2Value loginUserID string platformID int32 @@ -72,6 +73,8 @@ type Conversation struct { IsExternalExtensions bool startTime time.Time + + entering *entering } func (c *Conversation) SetMsgListener(msgListener func() open_im_sdk_callback.OnAdvancedMsgListener) { @@ -86,6 +89,10 @@ func (c *Conversation) SetBatchMsgListener(batchMsgListener func() open_im_sdk_c c.batchMsgListener = batchMsgListener } +func (c *Conversation) SetOnUserListener(userListener func() open_im_sdk_callback.OnUserListener) { + c.userListener = userListener +} + func NewConversation(ctx context.Context, longConnMgr *interaction.LongConnMgr, db db_interface.DataBase, ch chan common.Cmd2Value, friend *friend.Friend, group *group.Group, user *user.User, business *business.Business, full *full.Full, file *file.File) *Conversation { @@ -106,6 +113,7 @@ func NewConversation(ctx context.Context, longConnMgr *interaction.LongConnMgr, IsExternalExtensions: info.IsExternalExtensions(), maxSeqRecorder: NewMaxSeqRecorder(), } + n.entering = newEntering(n) n.initSyncer() n.cache = cache.NewCache[string, *model_struct.LocalConversation]() return n @@ -379,6 +387,14 @@ func (c *Conversation) doMsgNew(c2v common.Cmd2Value) { if isTriggerUnReadCount { c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{Action: constant.TotalUnreadMessageChanged, Args: ""}}) } + + for _, msgs := range allMsg { + for _, msg := range msgs.Msgs { + if msg.ContentType == constant.Entering { + c.entering.onNewMsg(ctx, msg) + } + } + } log.ZDebug(ctx, "insert msg", "cost time", time.Since(b), "len", len(allMsg)) } @@ -821,6 +837,10 @@ func (c *Conversation) msgHandleByContentType(msg *sdk_struct.MsgStruct) (err er t := sdk_struct.CardElem{} err = utils.JsonStringToStruct(msg.Content, &t) msg.CardElem = &t + case constant.Entering: + t := sdk_struct.EnteringElem{} + err = utils.JsonStringToStruct(msg.Content, &t) + msg.EnteringElem = &t default: t := sdk_struct.NotificationElem{} err = utils.JsonStringToStruct(msg.Content, &t) @@ -1030,3 +1050,11 @@ func (c *Conversation) getUserNameAndFaceURL(ctx context.Context, userID string) c.user.UserBasicCache.Store(userID, &user.BasicInfo{FaceURL: users[0].FaceURL, Nickname: users[0].Nickname}) return users[0].FaceURL, users[0].Nickname, nil } + +func (c *Conversation) GetInputStates(ctx context.Context, conversationID string, userID string) ([]int32, error) { + return c.entering.GetInputStates(conversationID, userID), nil +} + +func (c *Conversation) ChangeInputStates(ctx context.Context, conversationID string, focus bool) error { + return c.entering.ChangeInputStates(ctx, conversationID, focus) +} diff --git a/internal/conversation_msg/entering.go b/internal/conversation_msg/entering.go new file mode 100644 index 000000000..725a66009 --- /dev/null +++ b/internal/conversation_msg/entering.go @@ -0,0 +1,217 @@ +package conversation_msg + +import ( + "context" + "encoding/json" + "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/tools/errs" + "github.com/OpenIMSDK/tools/log" + utils2 "github.com/OpenIMSDK/tools/utils" + "github.com/jinzhu/copier" + "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" + "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" + "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" + "github.com/openimsdk/openim-sdk-core/v3/sdk_struct" + "github.com/patrickmn/go-cache" + "time" +) + +const ( + _ int = iota + stateCodeSuccess + stateCodeEnd +) + +const ( + inputStatesSendTime = time.Second * 10 // input status sending interval time + inputStatesTimeout = inputStatesSendTime + inputStatesSendTime/2 // input status timeout + inputStatesMsgTimeout = inputStatesSendTime / 2 // message sending timeout +) + +func newEntering(c *Conversation) *entering { + e := &entering{ + conv: c, + send: cache.New(inputStatesSendTime, inputStatesTimeout), + state: cache.New(inputStatesTimeout, inputStatesTimeout), + } + e.platformIDs = make([]int32, 0, len(constant.PlatformID2Name)) + e.platformIDSet = make(map[int32]struct{}) + for id := range constant.PlatformID2Name { + if id != 7 { + continue + } + e.platformIDSet[int32(id)] = struct{}{} + e.platformIDs = append(e.platformIDs, int32(id)) + } + utils2.Sort(e.platformIDs, true) + e.state.OnEvicted(func(key string, val interface{}) { + var data inputStatesKey + if err := json.Unmarshal([]byte(key), &data); err != nil { + return + } + e.changes(data.ConversationID, data.UserID) + }) + return e +} + +type entering struct { + send *cache.Cache + state *cache.Cache + + conv *Conversation + + platformIDs []int32 + platformIDSet map[int32]struct{} +} + +func (e *entering) ChangeInputStates(ctx context.Context, conversationID string, focus bool) error { + if conversationID == "" { + return errs.ErrArgs.Wrap("conversationID can't be empty") + } + conversation, err := e.conv.db.GetConversation(ctx, conversationID) + if err != nil { + return err + } + key := conversation.ConversationID + if focus { + if val, ok := e.send.Get(key); ok { + if val.(int) == stateCodeSuccess { + log.ZDebug(ctx, "entering stateCodeSuccess", "conversationID", conversationID, "focus", focus) + return nil + } + } + e.send.SetDefault(key, stateCodeSuccess) + } else { + if val, ok := e.send.Get(key); ok { + if val.(int) == stateCodeEnd { + log.ZDebug(ctx, "entering stateCodeEnd", "conversationID", conversationID, "focus", focus) + return nil + } + e.send.SetDefault(key, stateCodeEnd) + } else { + log.ZDebug(ctx, "entering send not found", "conversationID", conversationID, "focus", focus) + return nil + } + } + ctx, cancel := context.WithTimeout(ctx, inputStatesMsgTimeout) + defer cancel() + if err := e.sendMsg(ctx, conversation, focus); err != nil { + e.send.Delete(key) + return err + } + return nil +} + +func (e *entering) sendMsg(ctx context.Context, conversation *model_struct.LocalConversation, focus bool) error { + s := sdk_struct.MsgStruct{} + err := e.conv.initBasicInfo(ctx, &s, constant.UserMsgType, constant.Entering) + if err != nil { + return err + } + s.RecvID = conversation.UserID + s.GroupID = conversation.GroupID + s.SessionType = conversation.ConversationType + enteringElem := sdk_struct.EnteringElem{ + Focus: focus, + } + s.Content = utils.StructToJsonString(enteringElem) + options := make(map[string]bool, 6) + utils.SetSwitchFromOptions(options, constant.IsHistory, false) + utils.SetSwitchFromOptions(options, constant.IsPersistent, false) + utils.SetSwitchFromOptions(options, constant.IsSenderSync, false) + utils.SetSwitchFromOptions(options, constant.IsConversationUpdate, false) + utils.SetSwitchFromOptions(options, constant.IsSenderConversationUpdate, false) + utils.SetSwitchFromOptions(options, constant.IsUnreadCount, false) + utils.SetSwitchFromOptions(options, constant.IsOfflinePush, false) + var wsMsgData sdkws.MsgData + copier.Copy(&wsMsgData, s) + wsMsgData.Content = []byte(s.Content) + wsMsgData.CreateTime = s.CreateTime + wsMsgData.Options = options + var sendMsgResp sdkws.UserSendMsgResp + err = e.conv.LongConnMgr.SendReqWaitResp(ctx, &wsMsgData, constant.SendMsg, &sendMsgResp) + if err != nil { + log.ZError(ctx, "entering msg to server failed", err, "message", s) + return err + } + return nil +} + +type inputStatesKey struct { + ConversationID string `json:"cid,omitempty"` + UserID string `json:"uid,omitempty"` + PlatformID int32 `json:"pid,omitempty"` +} + +func (e *entering) getStateKey(conversationID string, userID string, platformID int32) string { + data, err := json.Marshal(inputStatesKey{ConversationID: conversationID, UserID: userID, PlatformID: platformID}) + if err != nil { + panic(err) + } + return string(data) +} + +func (e *entering) onNewMsg(ctx context.Context, msg *sdkws.MsgData) { + var enteringElem sdk_struct.EnteringElem + if err := json.Unmarshal(msg.Content, &enteringElem); err != nil { + log.ZError(ctx, "entering onNewMsg Unmarshal failed", err, "message", msg) + return + } + if msg.SendID == e.conv.loginUserID { + return + } + if _, ok := e.platformIDSet[msg.SenderPlatformID]; !ok { + return + } + now := time.Now().UnixMilli() + expirationTimestamp := msg.SendTime + int64(inputStatesSendTime/time.Millisecond) + if msg.SendTime > now || expirationTimestamp <= now { + return + } + var sourceID string + if msg.GroupID == "" { + sourceID = msg.SendID + } else { + sourceID = msg.GroupID + } + conversationID := e.conv.getConversationIDBySessionType(sourceID, int(msg.SessionType)) + key := e.getStateKey(conversationID, msg.SendID, msg.SenderPlatformID) + if enteringElem.Focus { + d := time.Duration(expirationTimestamp-now) * time.Millisecond + if v, t, ok := e.state.GetWithExpiration(key); ok { + if t.UnixMilli() >= expirationTimestamp { + return + } + e.state.Set(key, v, d) + } else { + e.state.Set(key, struct{}{}, d) + e.changes(conversationID, msg.SendID) + } + } else { + if _, ok := e.state.Get(key); ok { + e.state.Delete(key) + } + } +} + +type InputStatesChangedData struct { + ConversationID string `json:"conversationID"` + UserID string `json:"userID"` + PlatformIDs []int32 `json:"platformIDs"` +} + +func (e *entering) changes(conversationID string, userID string) { + data := InputStatesChangedData{ConversationID: conversationID, UserID: userID, PlatformIDs: e.GetInputStates(conversationID, userID)} + e.conv.userListener().OnUserInputStatusChanged(utils.StructToJsonString(data)) +} + +func (e *entering) GetInputStates(conversationID string, userID string) []int32 { + platformIDs := make([]int32, 0, 1) + for _, platformID := range e.platformIDs { + key := e.getStateKey(conversationID, userID, platformID) + if _, ok := e.state.Get(key); ok { + platformIDs = append(platformIDs, platformID) + } + } + return platformIDs +} diff --git a/internal/interaction/long_conn_mgr.go b/internal/interaction/long_conn_mgr.go index e124e0f34..c2d9761c0 100644 --- a/internal/interaction/long_conn_mgr.go +++ b/internal/interaction/long_conn_mgr.go @@ -177,6 +177,13 @@ func (c *LongConnMgr) readPump(ctx context.Context) { //c.conn.SetPongHandler(function(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil }) for { ctx = ccontext.WithOperationID(ctx, utils.OperationIDGenerator()) + select { + case <-ctx.Done(): + log.ZDebug(ctx, "readPump stop by ctx done") + c.closedErr = ctx.Err() + return + default: + } needRecon, err := c.reConn(ctx, &connNum) if !needRecon { c.closedErr = err @@ -522,26 +529,24 @@ func (c *LongConnMgr) reConn(ctx context.Context, num *int) (needRecon bool, err if err := json.Unmarshal(body, &apiResp); err != nil { return true, err } - //switch apiResp.ErrCode { - //case - // errs.TokenExpiredError, - // errs.TokenInvalidError, - // errs.TokenMalformedError, - // errs.TokenNotValidYetError, - // errs.TokenUnknownError, - // errs.TokenNotExistError: - // c.listener.OnUserTokenExpired() - // _ = common.TriggerCmdLogOut(ctx, c.loginMgrCh) - //case errs.TokenKickedError: - // c.listener.OnKickedOffline() - // _ = common.TriggerCmdLogOut(ctx, c.loginMgrCh) - //default: - // c.listener.OnConnectFailed(int32(apiResp.ErrCode), apiResp.ErrMsg) - //} - //log.ZWarn(ctx, "long conn establish failed", sdkerrs.New(apiResp.ErrCode, apiResp.ErrMsg, apiResp.ErrDlt)) + if apiResp.ErrCode == 0 { + return true, nil + } err = errs.NewCodeError(apiResp.ErrCode, apiResp.ErrMsg).WithDetail(apiResp.ErrDlt).Wrap() ccontext.GetApiErrCodeCallback(ctx).OnError(ctx, err) - return false, err + switch apiResp.ErrCode { + case + errs.TokenExpiredError, + errs.TokenInvalidError, + errs.TokenMalformedError, + errs.TokenNotValidYetError, + errs.TokenUnknownError, + errs.TokenNotExistError, + errs.TokenKickedError: + return false, err + default: + return true, err + } } c.listener.OnConnectFailed(sdkerrs.NetworkError, err.Error()) return true, err diff --git a/internal/interaction/ws_js.go b/internal/interaction/ws_js.go index fe1fd1af3..7c75589fe 100644 --- a/internal/interaction/ws_js.go +++ b/internal/interaction/ws_js.go @@ -18,8 +18,13 @@ package interaction import ( + "bytes" "context" + "fmt" + "github.com/OpenIMSDK/tools/log" + "io" "net/http" + "net/url" "nhooyr.io/websocket" "time" ) @@ -67,16 +72,53 @@ func (w *JSWebSocket) ReadMessage() (int, []byte, error) { return int(messageType), b, err } +func (w *JSWebSocket) dial(ctx context.Context, urlStr string) (*websocket.Conn, *http.Response, error) { + u, err := url.Parse(urlStr) + if err != nil { + return nil, nil, err + } + query := u.Query() + query.Set("isMsgResp", "true") + u.RawQuery = query.Encode() + conn, httpResp, err := websocket.Dial(ctx, u.String(), nil) + if err != nil { + return nil, nil, err + } + if httpResp == nil { + httpResp = &http.Response{ + StatusCode: http.StatusSwitchingProtocols, + } + } + _, data, err := conn.Read(ctx) + if err != nil { + _ = conn.CloseNow() + return nil, nil, fmt.Errorf("read response error %w", err) + } + log.ZDebug(ctx, "ws msg read resp", "data", string(data)) + httpResp.Body = io.NopCloser(bytes.NewReader(data)) + return conn, httpResp, nil +} + func (w *JSWebSocket) Dial(urlStr string, _ http.Header) (*http.Response, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() - conn, httpResp, err := websocket.Dial(ctx, urlStr, nil) + conn, httpResp, err := w.dial(ctx, urlStr) if err == nil { w.conn = conn } return httpResp, err } +//func (w *JSWebSocket) Dial(urlStr string, _ http.Header) (*http.Response, error) { +// ctx, cancel := context.WithTimeout(context.Background(), time.Minute) +// defer cancel() +// conn, httpResp, err := websocket.Dial(ctx, urlStr, nil) +// if err == nil { +// w.conn = conn +// } +// return httpResp, err +//} + func (w *JSWebSocket) IsNil() bool { if w.conn != nil { return false diff --git a/msgtest/sdk_user_simulator/listener.go b/msgtest/sdk_user_simulator/listener.go index a77260038..265c5e540 100644 --- a/msgtest/sdk_user_simulator/listener.go +++ b/msgtest/sdk_user_simulator/listener.go @@ -41,6 +41,10 @@ func (c *conversationCallBack) OnSyncServerFinish() { type userCallback struct { } +func (c userCallback) OnUserInputStatusChanged(change string) { + +} + func (c userCallback) OnUserStatusChanged(statusMap string) { } diff --git a/open_im_sdk/apicb.go b/open_im_sdk/apicb.go index 240e0f7cc..bb3f42d4a 100644 --- a/open_im_sdk/apicb.go +++ b/open_im_sdk/apicb.go @@ -22,8 +22,10 @@ func (c *apiErrCallback) OnError(ctx context.Context, err error) { } codeErr, ok := errs.Unwrap(err).(errs.CodeError) if !ok { + log.ZError(ctx, "OnError callback not CodeError", err) return } + log.ZError(ctx, "OnError callback CodeError", err, "code", codeErr.Code(), "msg", codeErr.Msg(), "detail", codeErr.Detail()) switch codeErr.Code() { case errs.TokenExpiredError, diff --git a/open_im_sdk/conversation_msg.go b/open_im_sdk/conversation_msg.go index 2269d4a6b..3bc9403ed 100644 --- a/open_im_sdk/conversation_msg.go +++ b/open_im_sdk/conversation_msg.go @@ -247,3 +247,11 @@ func SetMessageLocalEx(callback open_im_sdk_callback.Base, operationID string, c func SearchConversation(callback open_im_sdk_callback.Base, operationID string, searchParam string) { call(callback, operationID, UserForSDK.Conversation().SearchConversation, searchParam) } + +func ChangeInputStates(callback open_im_sdk_callback.Base, operationID string, conversationID string, focus bool) { + call(callback, operationID, UserForSDK.Conversation().ChangeInputStates, conversationID, focus) +} + +func GetInputStates(callback open_im_sdk_callback.Base, operationID string, conversationID string, userID string) { + call(callback, operationID, UserForSDK.Conversation().GetInputStates, conversationID, userID) +} diff --git a/open_im_sdk/em.go b/open_im_sdk/em.go index 878913979..e69140cb2 100644 --- a/open_im_sdk/em.go +++ b/open_im_sdk/em.go @@ -242,6 +242,10 @@ type emptyUserListener struct { ctx context.Context } +func (e *emptyUserListener) OnUserInputStatusChanged(change string) { + log.ZWarn(e.ctx, "UserListener OnUserInputStatusChanged is not implemented", nil, "change", change) +} + func newEmptyUserListener(ctx context.Context) open_im_sdk_callback.OnUserListener { return &emptyUserListener{ctx: ctx} } diff --git a/open_im_sdk/userRelated.go b/open_im_sdk/userRelated.go index 43e9b21ac..f653b6218 100644 --- a/open_im_sdk/userRelated.go +++ b/open_im_sdk/userRelated.go @@ -363,6 +363,7 @@ func (u *LoginMgr) setListener(ctx context.Context) { setListener(ctx, &u.advancedMsgListener, u.AdvancedMsgListener, u.conversation.SetMsgListener, newEmptyAdvancedMsgListener) setListener(ctx, &u.batchMsgListener, u.BatchMsgListener, u.conversation.SetBatchMsgListener, nil) setListener(ctx, &u.businessListener, u.BusinessListener, u.business.SetListener, newEmptyCustomBusinessListener) + setListener(ctx, &u.userListener, u.UserListener, u.conversation.SetOnUserListener, newEmptyUserListener) } func setListener[T any](ctx context.Context, listener *T, getter func() T, setFunc func(listener func() T), newFunc func(context.Context) T) { diff --git a/open_im_sdk_callback/callback_client.go b/open_im_sdk_callback/callback_client.go index 67960590f..e1ea6ff59 100644 --- a/open_im_sdk_callback/callback_client.go +++ b/open_im_sdk_callback/callback_client.go @@ -85,6 +85,7 @@ type OnBatchMsgListener interface { type OnUserListener interface { OnSelfInfoUpdated(userInfo string) OnUserStatusChanged(userOnlineStatus string) + OnUserInputStatusChanged(change string) } type OnCustomBusinessListener interface { diff --git a/pkg/constant/constant.go b/pkg/constant/constant.go index c07fd37ad..f9c7f1d5f 100644 --- a/pkg/constant/constant.go +++ b/pkg/constant/constant.go @@ -66,6 +66,7 @@ const ( CustomMsgOnlineOnly = 120 ReactionMessageModifier = 121 ReactionMessageDeleter = 122 + Entering = 123 ////////////////////////////////////////// NotificationBegin = 1000 diff --git a/sdk_struct/sdk_struct.go b/sdk_struct/sdk_struct.go index d94eee0b0..71dd080f9 100644 --- a/sdk_struct/sdk_struct.go +++ b/sdk_struct/sdk_struct.go @@ -196,10 +196,15 @@ type AdvancedTextElem struct { Text string `json:"text,omitempty"` MessageEntityList []*MessageEntity `json:"messageEntityList,omitempty"` } + type TypingElem struct { MsgTips string `json:"msgTips,omitempty"` } +type EnteringElem struct { + Focus bool `json:"focus"` +} + type MsgStruct struct { ClientMsgID string `json:"clientMsgID,omitempty"` ServerMsgID string `json:"serverMsgID,omitempty"` @@ -239,6 +244,7 @@ type MsgStruct struct { NotificationElem *NotificationElem `json:"notificationElem,omitempty"` AdvancedTextElem *AdvancedTextElem `json:"advancedTextElem,omitempty"` TypingElem *TypingElem `json:"typingElem,omitempty"` + EnteringElem *EnteringElem `json:"enteringElem,omitempty"` AttachedInfoElem *AttachedInfoElem `json:"attachedInfoElem,omitempty"` } diff --git a/test/t_friend_sdk.go b/test/t_friend_sdk.go index ddc50287f..23a3a5d80 100644 --- a/test/t_friend_sdk.go +++ b/test/t_friend_sdk.go @@ -666,6 +666,10 @@ func InOutDoTestSendMsg(sendId, receiverID string) { type userCallback struct { } +func (c userCallback) OnUserInputStatusChanged(change string) { + +} + func (c userCallback) OnUserStatusChanged(statusMap string) { log.ZInfo(ctx, "User Status Changed", "statusMap", statusMap) } diff --git a/testv2/config.go b/testv2/config.go index dac91ed85..d9f5065f5 100644 --- a/testv2/config.go +++ b/testv2/config.go @@ -20,9 +20,9 @@ import ( ) const ( - APIADDR = "http://14.29.168.56:10002" - WSADDR = "ws://14.29.168.56:10001" - UserID = "1" + APIADDR = "http://172.16.8.38:10002" + WSADDR = "ws://172.16.8.38:10001" + UserID = "1600918051" friendUserID = "3281432310" ) diff --git a/testv2/empty_test.go b/testv2/empty_test.go index 8f2c7b1f4..3824f62d7 100644 --- a/testv2/empty_test.go +++ b/testv2/empty_test.go @@ -15,13 +15,25 @@ package testv2 import ( + "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/openim-sdk-core/v3/open_im_sdk" "testing" "time" ) +func Test_ChangeInputState(t *testing.T) { + for { + err := open_im_sdk.UserForSDK.Conversation().ChangeInputStates(ctx, "sg_2309860938", true) + if err != nil { + log.ZError(ctx, "ChangeInputStates", err) + } + time.Sleep(time.Second * 1) + } +} + func Test_Empty(t *testing.T) { for { - time.Sleep(time.Second * 10) + time.Sleep(time.Second * 1) } } diff --git a/testv2/init.go b/testv2/init.go index 333feb0e5..e6ebf4eed 100644 --- a/testv2/init.go +++ b/testv2/init.go @@ -63,7 +63,7 @@ func init() { open_im_sdk.UserForSDK.SetAdvancedMsgListener(&onAdvancedMsgListener{ctx: ctx}) open_im_sdk.UserForSDK.SetFriendListener(&onFriendListener{ctx: ctx}) open_im_sdk.UserForSDK.SetUserListener(&onUserListener{ctx: ctx}) - time.Sleep(time.Second * 10) + time.Sleep(time.Second * 2) } func GetUserToken(ctx context.Context, userID string) (string, error) { @@ -311,6 +311,10 @@ type onUserListener struct { ctx context.Context } +func (o *onUserListener) OnUserInputStatusChanged(change string) { + +} + func (o *onUserListener) OnSelfInfoUpdated(userInfo string) { log.ZDebug(context.Background(), "OnBlackDeleted", "blackInfo", userInfo) } diff --git a/wasm/cmd/main.go b/wasm/cmd/main.go index f6b1fbda6..d4a468fc7 100644 --- a/wasm/cmd/main.go +++ b/wasm/cmd/main.go @@ -123,6 +123,9 @@ func registerFunc() { js.Global().Set("searchLocalMessages", js.FuncOf(wrapperConMsg.SearchLocalMessages)) js.Global().Set("setMessageLocalEx", js.FuncOf(wrapperConMsg.SetMessageLocalEx)) + js.Global().Set("changeInputStates", js.FuncOf(wrapperConMsg.ChangeInputStates)) + js.Global().Set("getInputStates", js.FuncOf(wrapperConMsg.GetInputStates)) + //register group funcation wrapperGroup := wasm_wrapper.NewWrapperGroup(globalFuc) js.Global().Set("createGroup", js.FuncOf(wrapperGroup.CreateGroup)) diff --git a/wasm/event_listener/listener.go b/wasm/event_listener/listener.go index 07fb7eda4..08d0f2fc8 100644 --- a/wasm/event_listener/listener.go +++ b/wasm/event_listener/listener.go @@ -386,6 +386,10 @@ func (u UserCallback) OnUserStatusChanged(statusMap string) { u.CallbackWriter.SetEvent(utils.GetSelfFuncName()).SetData(statusMap).SendMessage() } +func (u UserCallback) OnUserInputStatusChanged(change string) { + u.CallbackWriter.SetEvent(utils.GetSelfFuncName()).SetData(change).SendMessage() +} + func NewUserCallback(callback *js.Value) *UserCallback { return &UserCallback{CallbackWriter: NewEventData(callback)} } diff --git a/wasm/wasm_wrapper/wasm_conversation_msg.go b/wasm/wasm_wrapper/wasm_conversation_msg.go index f4131964c..8215960e2 100644 --- a/wasm/wasm_wrapper/wasm_conversation_msg.go +++ b/wasm/wasm_wrapper/wasm_conversation_msg.go @@ -317,3 +317,13 @@ func (w *WrapperConMsg) SetConversationBurnDuration(_ js.Value, args []js.Value) callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) return event_listener.NewCaller(open_im_sdk.SetConversationBurnDuration, callback, &args).AsyncCallWithCallback() } + +func (w *WrapperConMsg) ChangeInputStates(_ js.Value, args []js.Value) interface{} { + callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) + return event_listener.NewCaller(open_im_sdk.ChangeInputStates, callback, &args).AsyncCallWithCallback() +} + +func (w *WrapperConMsg) GetInputStates(_ js.Value, args []js.Value) interface{} { + callback := event_listener.NewBaseCallback(utils.FirstLower(utils.GetSelfFuncName()), w.commonFunc) + return event_listener.NewCaller(open_im_sdk.GetInputStates, callback, &args).AsyncCallWithCallback() +} From f73b878f9d3e2fc27a8c02d5392fbe7eef8db679 Mon Sep 17 00:00:00 2001 From: Gordon <46924906+FGadvancer@users.noreply.github.com> Date: Tue, 2 Jan 2024 18:07:20 +0800 Subject: [PATCH 2/8] fix: kicked user invited again into group,the group info do not changed. (#464) Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> --- internal/group/group.go | 23 ++++++++++++++++++----- internal/group/notification.go | 1 + 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/internal/group/group.go b/internal/group/group.go index ad2c8aa79..dec3996d5 100644 --- a/internal/group/group.go +++ b/internal/group/group.go @@ -76,11 +76,17 @@ func (g *Group) initSyncer() { }, nil, func(ctx context.Context, state int, server, local *model_struct.LocalGroup) error { switch state { case syncer.Insert: + //when a user kicked to the group and invited to the group again, group info maybe updated,so conversation + //info need to be updated g.listener().OnJoinedGroupAdded(utils.StructToJsonString(server)) + _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.UpdateConFaceUrlAndNickName, + Args: common.SourceIDAndSessionType{SourceID: server.GroupID, SessionType: constant.SuperGroupChatType, + FaceURL: server.FaceURL, Nickname: server.GroupName}}, g.conversationCh) case syncer.Delete: g.listener().OnJoinedGroupDeleted(utils.StructToJsonString(local)) case syncer.Update: - log.ZInfo(ctx, "groupSyncer trigger update", "groupID", server.GroupID, "data", server, "isDismissed", server.Status == constant.GroupStatusDismissed) + log.ZInfo(ctx, "groupSyncer trigger update", "groupID", + server.GroupID, "data", server, "isDismissed", server.Status == constant.GroupStatusDismissed) if server.Status == constant.GroupStatusDismissed { if err := g.db.DeleteGroupAllMembers(ctx, server.GroupID); err != nil { log.ZError(ctx, "delete group all members failed", err) @@ -89,8 +95,8 @@ func (g *Group) initSyncer() { } else { g.listener().OnGroupInfoChanged(utils.StructToJsonString(server)) if server.GroupName != local.GroupName || local.FaceURL != server.FaceURL { - _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.UpdateConFaceUrlAndNickName, Args: common.SourceIDAndSessionType{SourceID: server.GroupID, - SessionType: constant.SuperGroupChatType, FaceURL: server.FaceURL, Nickname: server.GroupName}}, g.conversationCh) + _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.UpdateConFaceUrlAndNickName, + Args: common.SourceIDAndSessionType{SourceID: server.GroupID, SessionType: constant.SuperGroupChatType, FaceURL: server.FaceURL, Nickname: server.GroupName}}, g.conversationCh) } } } @@ -110,13 +116,20 @@ func (g *Group) initSyncer() { switch state { case syncer.Insert: g.listener().OnGroupMemberAdded(utils.StructToJsonString(server)) + //when a user kicked and invited to the group again, group member info will be updated + _ = common.TriggerCmdUpdateMessage(ctx, + common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, + Args: common.UpdateMessageInfo{UserID: server.UserID, FaceURL: server.FaceURL, + Nickname: server.Nickname, GroupID: server.GroupID}}, g.conversationCh) case syncer.Delete: g.listener().OnGroupMemberDeleted(utils.StructToJsonString(local)) case syncer.Update: g.listener().OnGroupMemberInfoChanged(utils.StructToJsonString(server)) if server.Nickname != local.Nickname || server.FaceURL != local.FaceURL { - _ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, Args: common.UpdateMessageInfo{UserID: server.UserID, FaceURL: server.FaceURL, - Nickname: server.Nickname, GroupID: server.GroupID}}, g.conversationCh) + _ = common.TriggerCmdUpdateMessage(ctx, + common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, + Args: common.UpdateMessageInfo{UserID: server.UserID, FaceURL: server.FaceURL, + Nickname: server.Nickname, GroupID: server.GroupID}}, g.conversationCh) } } return nil diff --git a/internal/group/notification.go b/internal/group/notification.go index 1bcc44472..7ffa00eef 100644 --- a/internal/group/notification.go +++ b/internal/group/notification.go @@ -137,6 +137,7 @@ func (g *Group) doNotification(ctx context.Context, msg *sdkws.MsgData) error { return err } g.listener().OnGroupInfoChanged(string(data)) + g.listener().OnJoinedGroupDeleted(string(data)) return nil } else { var userIDs []string From d05c73a09501e8b96cd9b43da2be906f84fa3dec Mon Sep 17 00:00:00 2001 From: Gordon <46924906+FGadvancer@users.noreply.github.com> Date: Tue, 2 Jan 2024 19:52:12 +0800 Subject: [PATCH 3/8] fix: wasm parse data. (#465) * fix: kicked user invited again into group,the group info do not changed. Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> * fix: wasm parse data. Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> --------- Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> --- internal/interaction/long_conn_mgr.go | 10 ---------- internal/interaction/ws_js.go | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/internal/interaction/long_conn_mgr.go b/internal/interaction/long_conn_mgr.go index c2d9761c0..d437a343d 100644 --- a/internal/interaction/long_conn_mgr.go +++ b/internal/interaction/long_conn_mgr.go @@ -177,13 +177,6 @@ func (c *LongConnMgr) readPump(ctx context.Context) { //c.conn.SetPongHandler(function(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil }) for { ctx = ccontext.WithOperationID(ctx, utils.OperationIDGenerator()) - select { - case <-ctx.Done(): - log.ZDebug(ctx, "readPump stop by ctx done") - c.closedErr = ctx.Err() - return - default: - } needRecon, err := c.reConn(ctx, &connNum) if !needRecon { c.closedErr = err @@ -529,9 +522,6 @@ func (c *LongConnMgr) reConn(ctx context.Context, num *int) (needRecon bool, err if err := json.Unmarshal(body, &apiResp); err != nil { return true, err } - if apiResp.ErrCode == 0 { - return true, nil - } err = errs.NewCodeError(apiResp.ErrCode, apiResp.ErrMsg).WithDetail(apiResp.ErrDlt).Wrap() ccontext.GetApiErrCodeCallback(ctx).OnError(ctx, err) switch apiResp.ErrCode { diff --git a/internal/interaction/ws_js.go b/internal/interaction/ws_js.go index 7c75589fe..2b31f269c 100644 --- a/internal/interaction/ws_js.go +++ b/internal/interaction/ws_js.go @@ -20,6 +20,7 @@ package interaction import ( "bytes" "context" + "encoding/json" "fmt" "github.com/OpenIMSDK/tools/log" "io" @@ -94,9 +95,21 @@ func (w *JSWebSocket) dial(ctx context.Context, urlStr string) (*websocket.Conn, _ = conn.CloseNow() return nil, nil, fmt.Errorf("read response error %w", err) } + var apiResp struct { + ErrCode int `json:"errCode"` + ErrMsg string `json:"errMsg"` + ErrDlt string `json:"errDlt"` + } + if err := json.Unmarshal(data, &apiResp); err != nil { + return nil, nil, fmt.Errorf("unmarshal response error %w", err) + } + if apiResp.ErrCode == 0 { + return conn, httpResp, nil + } log.ZDebug(ctx, "ws msg read resp", "data", string(data)) httpResp.Body = io.NopCloser(bytes.NewReader(data)) - return conn, httpResp, nil + return conn, httpResp, fmt.Errorf("read response error %d %s %s", + apiResp.ErrCode, apiResp.ErrMsg, apiResp.ErrDlt) } func (w *JSWebSocket) Dial(urlStr string, _ http.Header) (*http.Response, error) { From 55aa72271b92e6294771d448eb7a680c88d4a932 Mon Sep 17 00:00:00 2001 From: Xinwei Xiong <3293172751@qq.com> Date: Tue, 2 Jan 2024 21:34:20 +0800 Subject: [PATCH 4/8] Update .goreleaser.yaml (#466) --- .goreleaser.yaml | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 0df4c5f8a..6be41a5d4 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -21,6 +21,31 @@ before: # you may remove this if you don't need go generate - go generate ./... + + +git: + # What should be used to sort tags when gathering the current and previous + # tags if there are more than one tag in the same commit. + # + # Default: '-version:refname' + tag_sort: -version:creatordate + + # What should be used to specify prerelease suffix while sorting tags when gathering + # the current and previous tags if there are more than one tag in the same commit. + # + # Since: v1.17 + prerelease_suffix: "-" + + # Tags to be ignored by GoReleaser. + # This means that GoReleaser will not pick up tags that match any of the + # provided values as either previous or current tags. + # + # Templates: allowed. + # Since: v1.21. + ignore_tags: + - nightly + # - "{{.Env.IGNORE_TAG}}" + report_sizes: true builds: @@ -195,4 +220,4 @@ checksum: algorithm: sha256 release: - prerelease: auto \ No newline at end of file + prerelease: auto From 5e648e676c92930eb8e6a2bb14b3043579d01be1 Mon Sep 17 00:00:00 2001 From: Gordon <46924906+FGadvancer@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:52:45 +0800 Subject: [PATCH 5/8] fix: conversation and message's sender info change when notification user's info changed. (#468) * fix: kicked user invited again into group,the group info do not changed. Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> * fix: wasm parse data. Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> * fix: conversation and message's sender info change when notification user's info changed. Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> --------- Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> --- .../conversation_notification.go | 20 +++++++++++++++---- internal/friend/friend.go | 2 +- internal/full/open_im_sdk_full.go | 8 ++++---- internal/group/group.go | 4 ++-- internal/user/user.go | 2 +- pkg/common/trigger_channel.go | 11 +++++----- 6 files changed, 30 insertions(+), 17 deletions(-) diff --git a/internal/conversation_msg/conversation_notification.go b/internal/conversation_msg/conversation_notification.go index c37662603..31ec48e3a 100644 --- a/internal/conversation_msg/conversation_notification.go +++ b/internal/conversation_msg/conversation_notification.go @@ -156,12 +156,15 @@ func (c *Conversation) doUpdateConversation(c2v common.Cmd2Value) { case constant.SuperGroupChatType: conversationID, conversationType, err := c.getConversationTypeByGroupID(ctx, st.SourceID) if err != nil { - // log.Error("internal", "getConversationTypeByGroupID database err:", err.Error()) return } lc.GroupID = st.SourceID lc.ConversationID = conversationID lc.ConversationType = conversationType + case constant.NotificationChatType: + lc.UserID = st.SourceID + lc.ConversationID = c.getConversationIDBySessionType(st.SourceID, constant.NotificationChatType) + lc.ConversationType = constant.NotificationChatType default: log.ZError(ctx, "not support sessionType", nil, "sessionType", st.SessionType) return @@ -273,7 +276,8 @@ func (c *Conversation) doUpdateMessage(c2v common.Cmd2Value) { switch node.Action { case constant.UpdateMsgFaceUrlAndNickName: args := node.Args.(common.UpdateMessageInfo) - if args.GroupID == "" { + switch args.SessionType { + case constant.SingleChatType: if args.UserID == c.loginUserID { conversationIDList, err := c.db.GetAllSingleConversationIDList(ctx) if err != nil { @@ -298,14 +302,22 @@ func (c *Conversation) doUpdateMessage(c2v common.Cmd2Value) { } } - } else { + case constant.SuperGroupChatType: conversationID := c.getConversationIDBySessionType(args.GroupID, constant.SuperGroupChatType) err := c.db.UpdateMsgSenderFaceURLAndSenderNickname(ctx, conversationID, args.UserID, args.FaceURL, args.Nickname) if err != nil { log.ZError(ctx, "UpdateMsgSenderFaceURLAndSenderNickname err", err) } + case constant.NotificationChatType: + conversationID := c.getConversationIDBySessionType(args.UserID, constant.NotificationChatType) + err := c.db.UpdateMsgSenderFaceURLAndSenderNickname(ctx, conversationID, args.UserID, args.FaceURL, args.Nickname) + if err != nil { + log.ZError(ctx, "UpdateMsgSenderFaceURLAndSenderNickname err", err) + } + default: + log.ZError(ctx, "not support sessionType", nil, "args", args) + return } - } } diff --git a/internal/friend/friend.go b/internal/friend/friend.go index 8e61b7d39..faf67605c 100644 --- a/internal/friend/friend.go +++ b/internal/friend/friend.go @@ -75,7 +75,7 @@ func (f *Friend) initSyncer() { _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.UpdateConFaceUrlAndNickName, Args: common.SourceIDAndSessionType{SourceID: server.FriendUserID, SessionType: constant.SingleChatType, FaceURL: server.FaceURL, Nickname: server.Nickname}}, f.conversationCh) _ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, - Args: common.UpdateMessageInfo{UserID: server.FriendUserID, FaceURL: server.FaceURL, Nickname: server.Nickname}}, f.conversationCh) + Args: common.UpdateMessageInfo{SessionType: constant.SingleChatType, UserID: server.FriendUserID, FaceURL: server.FaceURL, Nickname: server.Nickname}}, f.conversationCh) } } diff --git a/internal/full/open_im_sdk_full.go b/internal/full/open_im_sdk_full.go index 0ddd6e967..5af5471dd 100644 --- a/internal/full/open_im_sdk_full.go +++ b/internal/full/open_im_sdk_full.go @@ -79,9 +79,9 @@ func (u *Full) GetUsersInfo(ctx context.Context, userIDs []string) ([]*api.FullU log.ZDebug(ctx, "GetConversationByUserID", "conversation", conversation) if conversation.ShowName != info.Nickname || conversation.FaceURL != info.FaceURL { _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.UpdateConFaceUrlAndNickName, - Args: common.SourceIDAndSessionType{SourceID: userID, SessionType: constant.SingleChatType, FaceURL: info.FaceURL, Nickname: info.Nickname}}, u.ch) + Args: common.SourceIDAndSessionType{SourceID: userID, SessionType: conversation.ConversationType, FaceURL: info.FaceURL, Nickname: info.Nickname}}, u.ch) _ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, - Args: common.UpdateMessageInfo{UserID: userID, FaceURL: info.FaceURL, Nickname: info.Nickname}}, u.ch) + Args: common.UpdateMessageInfo{SessionType: conversation.ConversationType, UserID: userID, FaceURL: info.FaceURL, Nickname: info.Nickname}}, u.ch) } } } @@ -189,9 +189,9 @@ func (u *Full) GetUsersInfoWithCache(ctx context.Context, userIDs []string, grou log.ZDebug(ctx, "GetConversationByUserID", "conversation", conversation) if conversation.ShowName != info.Nickname || conversation.FaceURL != info.FaceURL { _ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{Action: constant.UpdateConFaceUrlAndNickName, - Args: common.SourceIDAndSessionType{SourceID: userID, SessionType: constant.SingleChatType, FaceURL: info.FaceURL, Nickname: info.Nickname}}, u.ch) + Args: common.SourceIDAndSessionType{SourceID: userID, SessionType: conversation.ConversationType, FaceURL: info.FaceURL, Nickname: info.Nickname}}, u.ch) _ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, - Args: common.UpdateMessageInfo{UserID: userID, FaceURL: info.FaceURL, Nickname: info.Nickname}}, u.ch) + Args: common.UpdateMessageInfo{SessionType: conversation.ConversationType, UserID: userID, FaceURL: info.FaceURL, Nickname: info.Nickname}}, u.ch) } } } diff --git a/internal/group/group.go b/internal/group/group.go index dec3996d5..150814d08 100644 --- a/internal/group/group.go +++ b/internal/group/group.go @@ -119,7 +119,7 @@ func (g *Group) initSyncer() { //when a user kicked and invited to the group again, group member info will be updated _ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, - Args: common.UpdateMessageInfo{UserID: server.UserID, FaceURL: server.FaceURL, + Args: common.UpdateMessageInfo{SessionType: constant.SuperGroupChatType, UserID: server.UserID, FaceURL: server.FaceURL, Nickname: server.Nickname, GroupID: server.GroupID}}, g.conversationCh) case syncer.Delete: g.listener().OnGroupMemberDeleted(utils.StructToJsonString(local)) @@ -128,7 +128,7 @@ func (g *Group) initSyncer() { if server.Nickname != local.Nickname || server.FaceURL != local.FaceURL { _ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, - Args: common.UpdateMessageInfo{UserID: server.UserID, FaceURL: server.FaceURL, + Args: common.UpdateMessageInfo{SessionType: constant.SuperGroupChatType, UserID: server.UserID, FaceURL: server.FaceURL, Nickname: server.Nickname, GroupID: server.GroupID}}, g.conversationCh) } } diff --git a/internal/user/user.go b/internal/user/user.go index 92e25d397..c3e63389d 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -87,7 +87,7 @@ func (u *User) initSyncer() { u.listener().OnSelfInfoUpdated(utils.StructToJsonString(server)) if server.Nickname != local.Nickname || server.FaceURL != local.FaceURL { _ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName, - Args: common.UpdateMessageInfo{UserID: server.UserID, FaceURL: server.FaceURL, Nickname: server.Nickname}}, u.conversationCh) + Args: common.UpdateMessageInfo{SessionType: constant.SingleChatType, UserID: server.UserID, FaceURL: server.FaceURL, Nickname: server.Nickname}}, u.conversationCh) } } return nil diff --git a/pkg/common/trigger_channel.go b/pkg/common/trigger_channel.go index e6702b2f1..5d0ca4f0a 100644 --- a/pkg/common/trigger_channel.go +++ b/pkg/common/trigger_channel.go @@ -181,15 +181,16 @@ type UpdateConInfo struct { GroupID string } type UpdateMessageInfo struct { - UserID string - FaceURL string - Nickname string - GroupID string + SessionType int32 + UserID string + FaceURL string + Nickname string + GroupID string } type SourceIDAndSessionType struct { SourceID string - SessionType int + SessionType int32 FaceURL string Nickname string } From 01c5f8b20d25a2f3c0843d33c2e8d5235eff5587 Mon Sep 17 00:00:00 2001 From: Gordon <46924906+FGadvancer@users.noreply.github.com> Date: Wed, 3 Jan 2024 20:11:34 +0800 Subject: [PATCH 6/8] Release v3.5 conversation's info update (#471) * fix: conversation and message's sender info change when notification user's info changed. Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> * fix: conversation and message's sender info change when notification user's info changed. Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> --------- Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> --- internal/conversation_msg/sdk.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/conversation_msg/sdk.go b/internal/conversation_msg/sdk.go index bad5f7c01..12b5f2ac5 100644 --- a/internal/conversation_msg/sdk.go +++ b/internal/conversation_msg/sdk.go @@ -371,7 +371,7 @@ func (c *Conversation) getConversationIDBySessionType(sourceID string, sessionTy case constant.SuperGroupChatType: return "sg_" + sourceID // super group chat case constant.NotificationChatType: - return "sn_" + sourceID // server notification chat + return "sn_" + sourceID + "_" + c.loginUserID // server notification chat } return "" } From 1408f1c6d1e286c268d6c76576524e8abbf6c845 Mon Sep 17 00:00:00 2001 From: chao <48119764+withchao@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:09:18 +0800 Subject: [PATCH 7/8] feat: support conversation input status and wasm websocket message returns the connection status (#470) * entering * entering * entering * entering * entering * wasm callback * wasm callback * ws * feat: typing * feat: typing * feat: typing * fix: ws js * fix: ws js --- internal/conversation_msg/conversation_msg.go | 45 +++++++++-------- internal/conversation_msg/entering.go | 48 +++++++++---------- msgtest/sdk_user_simulator/listener.go | 10 ++-- open_im_sdk/em.go | 12 +++-- open_im_sdk/userRelated.go | 1 - open_im_sdk_callback/callback_client.go | 4 +- pkg/constant/constant.go | 1 - sdk_struct/sdk_struct.go | 5 -- test/t_conversation_msg.go | 8 ++++ test/t_friend_sdk.go | 4 -- testv2/init.go | 12 +++-- wasm/event_listener/listener.go | 8 ++++ 12 files changed, 92 insertions(+), 66 deletions(-) diff --git a/internal/conversation_msg/conversation_msg.go b/internal/conversation_msg/conversation_msg.go index d2d35671d..086458723 100644 --- a/internal/conversation_msg/conversation_msg.go +++ b/internal/conversation_msg/conversation_msg.go @@ -56,7 +56,6 @@ type Conversation struct { msgListener func() open_im_sdk_callback.OnAdvancedMsgListener msgKvListener func() open_im_sdk_callback.OnMessageKvInfoListener batchMsgListener func() open_im_sdk_callback.OnBatchMsgListener - userListener func() open_im_sdk_callback.OnUserListener recvCH chan common.Cmd2Value loginUserID string platformID int32 @@ -74,7 +73,7 @@ type Conversation struct { startTime time.Time - entering *entering + typing *typing } func (c *Conversation) SetMsgListener(msgListener func() open_im_sdk_callback.OnAdvancedMsgListener) { @@ -89,10 +88,6 @@ func (c *Conversation) SetBatchMsgListener(batchMsgListener func() open_im_sdk_c c.batchMsgListener = batchMsgListener } -func (c *Conversation) SetOnUserListener(userListener func() open_im_sdk_callback.OnUserListener) { - c.userListener = userListener -} - func NewConversation(ctx context.Context, longConnMgr *interaction.LongConnMgr, db db_interface.DataBase, ch chan common.Cmd2Value, friend *friend.Friend, group *group.Group, user *user.User, business *business.Business, full *full.Full, file *file.File) *Conversation { @@ -113,7 +108,7 @@ func NewConversation(ctx context.Context, longConnMgr *interaction.LongConnMgr, IsExternalExtensions: info.IsExternalExtensions(), maxSeqRecorder: NewMaxSeqRecorder(), } - n.entering = newEntering(n) + n.typing = newTyping(n) n.initSyncer() n.cache = cache.NewCache[string, *model_struct.LocalConversation]() return n @@ -167,6 +162,11 @@ func (c *Conversation) GetCh() chan common.Cmd2Value { return c.recvCH } +type onlineMsgKey struct { + ClientMsgID string + ServerMsgID string +} + func (c *Conversation) doMsgNew(c2v common.Cmd2Value) { allMsg := c2v.Value.(sdk_struct.CmdNewMsgComeToConversation).Msgs ctx := c2v.Ctx @@ -185,6 +185,7 @@ func (c *Conversation) doMsgNew(c2v common.Cmd2Value) { phNewConversationSet := make(map[string]*model_struct.LocalConversation) log.ZDebug(ctx, "message come here conversation ch", "conversation length", len(allMsg)) b := time.Now() + onlineMap := make(map[onlineMsgKey]struct{}) for conversationID, msgs := range allMsg { log.ZDebug(ctx, "parse message in one conversation", "conversationID", conversationID, "message length", len(msgs.Msgs)) @@ -193,6 +194,9 @@ func (c *Conversation) doMsgNew(c2v common.Cmd2Value) { for _, v := range msgs.Msgs { log.ZDebug(ctx, "parse message ", "conversationID", conversationID, "msg", v) isHistory = utils.GetSwitchFromOptions(v.Options, constant.IsHistory) + if !isHistory { + onlineMap[onlineMsgKey{ClientMsgID: v.ClientMsgID, ServerMsgID: v.ServerMsgID}] = struct{}{} + } isUnreadCount = utils.GetSwitchFromOptions(v.Options, constant.IsUnreadCount) isConversationUpdate = utils.GetSwitchFromOptions(v.Options, constant.IsConversationUpdate) isNotPrivate = utils.GetSwitchFromOptions(v.Options, constant.IsNotPrivate) @@ -375,7 +379,7 @@ func (c *Conversation) doMsgNew(c2v common.Cmd2Value) { if c.batchMsgListener() != nil { c.batchNewMessages(ctx, newMessages) } else { - c.newMessage(ctx, newMessages, conversationChangedSet, newConversationSet) + c.newMessage(ctx, newMessages, conversationChangedSet, newConversationSet, onlineMap) } if len(newConversationSet) > 0 { c.doUpdateConversation(common.Cmd2Value{Value: common.UpdateConNode{Action: constant.NewConDirect, Args: utils.StructToJsonString(mapConversationToList(newConversationSet))}}) @@ -390,8 +394,8 @@ func (c *Conversation) doMsgNew(c2v common.Cmd2Value) { for _, msgs := range allMsg { for _, msg := range msgs.Msgs { - if msg.ContentType == constant.Entering { - c.entering.onNewMsg(ctx, msg) + if msg.ContentType == constant.Typing { + c.typing.onNewMsg(ctx, msg) } } } @@ -653,7 +657,7 @@ func isContainRevokedList(target string, List []*sdk_struct.MessageRevoked) (boo return false, nil } -func (c *Conversation) newMessage(ctx context.Context, newMessagesList sdk_struct.NewMsgList, cc, nc map[string]*model_struct.LocalConversation) { +func (c *Conversation) newMessage(ctx context.Context, newMessagesList sdk_struct.NewMsgList, cc, nc map[string]*model_struct.LocalConversation, onlineMsg map[onlineMsgKey]struct{}) { sort.Sort(newMessagesList) if c.GetBackground() { u, err := c.user.GetSelfUserInfo(ctx) @@ -675,11 +679,18 @@ func (c *Conversation) newMessage(ctx context.Context, newMessagesList sdk_struc } } else { for _, w := range newMessagesList { - c.msgListener().OnRecvNewMessage(utils.StructToJsonString(w)) + if w.ContentType == constant.Typing { + continue + } + if _, ok := onlineMsg[onlineMsgKey{ClientMsgID: w.ClientMsgID, ServerMsgID: w.ServerMsgID}]; ok { + c.msgListener().OnRecvOnlineOnlyMessage(utils.StructToJsonString(w)) + } else { + c.msgListener().OnRecvNewMessage(utils.StructToJsonString(w)) + } } } - } + func (c *Conversation) batchNewMessages(ctx context.Context, newMessagesList sdk_struct.NewMsgList) { sort.Sort(newMessagesList) if len(newMessagesList) > 0 { @@ -837,10 +848,6 @@ func (c *Conversation) msgHandleByContentType(msg *sdk_struct.MsgStruct) (err er t := sdk_struct.CardElem{} err = utils.JsonStringToStruct(msg.Content, &t) msg.CardElem = &t - case constant.Entering: - t := sdk_struct.EnteringElem{} - err = utils.JsonStringToStruct(msg.Content, &t) - msg.EnteringElem = &t default: t := sdk_struct.NotificationElem{} err = utils.JsonStringToStruct(msg.Content, &t) @@ -1052,9 +1059,9 @@ func (c *Conversation) getUserNameAndFaceURL(ctx context.Context, userID string) } func (c *Conversation) GetInputStates(ctx context.Context, conversationID string, userID string) ([]int32, error) { - return c.entering.GetInputStates(conversationID, userID), nil + return c.typing.GetInputStates(conversationID, userID), nil } func (c *Conversation) ChangeInputStates(ctx context.Context, conversationID string, focus bool) error { - return c.entering.ChangeInputStates(ctx, conversationID, focus) + return c.typing.ChangeInputStates(ctx, conversationID, focus) } diff --git a/internal/conversation_msg/entering.go b/internal/conversation_msg/entering.go index 725a66009..2b0ecd299 100644 --- a/internal/conversation_msg/entering.go +++ b/internal/conversation_msg/entering.go @@ -28,8 +28,8 @@ const ( inputStatesMsgTimeout = inputStatesSendTime / 2 // message sending timeout ) -func newEntering(c *Conversation) *entering { - e := &entering{ +func newTyping(c *Conversation) *typing { + e := &typing{ conv: c, send: cache.New(inputStatesSendTime, inputStatesTimeout), state: cache.New(inputStatesTimeout, inputStatesTimeout), @@ -37,9 +37,6 @@ func newEntering(c *Conversation) *entering { e.platformIDs = make([]int32, 0, len(constant.PlatformID2Name)) e.platformIDSet = make(map[int32]struct{}) for id := range constant.PlatformID2Name { - if id != 7 { - continue - } e.platformIDSet[int32(id)] = struct{}{} e.platformIDs = append(e.platformIDs, int32(id)) } @@ -54,7 +51,7 @@ func newEntering(c *Conversation) *entering { return e } -type entering struct { +type typing struct { send *cache.Cache state *cache.Cache @@ -64,7 +61,7 @@ type entering struct { platformIDSet map[int32]struct{} } -func (e *entering) ChangeInputStates(ctx context.Context, conversationID string, focus bool) error { +func (e *typing) ChangeInputStates(ctx context.Context, conversationID string, focus bool) error { if conversationID == "" { return errs.ErrArgs.Wrap("conversationID can't be empty") } @@ -76,7 +73,7 @@ func (e *entering) ChangeInputStates(ctx context.Context, conversationID string, if focus { if val, ok := e.send.Get(key); ok { if val.(int) == stateCodeSuccess { - log.ZDebug(ctx, "entering stateCodeSuccess", "conversationID", conversationID, "focus", focus) + log.ZDebug(ctx, "typing stateCodeSuccess", "conversationID", conversationID, "focus", focus) return nil } } @@ -84,12 +81,12 @@ func (e *entering) ChangeInputStates(ctx context.Context, conversationID string, } else { if val, ok := e.send.Get(key); ok { if val.(int) == stateCodeEnd { - log.ZDebug(ctx, "entering stateCodeEnd", "conversationID", conversationID, "focus", focus) + log.ZDebug(ctx, "typing stateCodeEnd", "conversationID", conversationID, "focus", focus) return nil } e.send.SetDefault(key, stateCodeEnd) } else { - log.ZDebug(ctx, "entering send not found", "conversationID", conversationID, "focus", focus) + log.ZDebug(ctx, "typing send not found", "conversationID", conversationID, "focus", focus) return nil } } @@ -102,19 +99,22 @@ func (e *entering) ChangeInputStates(ctx context.Context, conversationID string, return nil } -func (e *entering) sendMsg(ctx context.Context, conversation *model_struct.LocalConversation, focus bool) error { +func (e *typing) sendMsg(ctx context.Context, conversation *model_struct.LocalConversation, focus bool) error { s := sdk_struct.MsgStruct{} - err := e.conv.initBasicInfo(ctx, &s, constant.UserMsgType, constant.Entering) + err := e.conv.initBasicInfo(ctx, &s, constant.UserMsgType, constant.Typing) if err != nil { return err } s.RecvID = conversation.UserID s.GroupID = conversation.GroupID s.SessionType = conversation.ConversationType - enteringElem := sdk_struct.EnteringElem{ - Focus: focus, + var typingElem sdk_struct.TypingElem + if focus { + typingElem.MsgTips = "yes" + } else { + typingElem.MsgTips = "no" } - s.Content = utils.StructToJsonString(enteringElem) + s.Content = utils.StructToJsonString(typingElem) options := make(map[string]bool, 6) utils.SetSwitchFromOptions(options, constant.IsHistory, false) utils.SetSwitchFromOptions(options, constant.IsPersistent, false) @@ -131,7 +131,7 @@ func (e *entering) sendMsg(ctx context.Context, conversation *model_struct.Local var sendMsgResp sdkws.UserSendMsgResp err = e.conv.LongConnMgr.SendReqWaitResp(ctx, &wsMsgData, constant.SendMsg, &sendMsgResp) if err != nil { - log.ZError(ctx, "entering msg to server failed", err, "message", s) + log.ZError(ctx, "typing msg to server failed", err, "message", s) return err } return nil @@ -143,7 +143,7 @@ type inputStatesKey struct { PlatformID int32 `json:"pid,omitempty"` } -func (e *entering) getStateKey(conversationID string, userID string, platformID int32) string { +func (e *typing) getStateKey(conversationID string, userID string, platformID int32) string { data, err := json.Marshal(inputStatesKey{ConversationID: conversationID, UserID: userID, PlatformID: platformID}) if err != nil { panic(err) @@ -151,10 +151,10 @@ func (e *entering) getStateKey(conversationID string, userID string, platformID return string(data) } -func (e *entering) onNewMsg(ctx context.Context, msg *sdkws.MsgData) { - var enteringElem sdk_struct.EnteringElem +func (e *typing) onNewMsg(ctx context.Context, msg *sdkws.MsgData) { + var enteringElem sdk_struct.TypingElem if err := json.Unmarshal(msg.Content, &enteringElem); err != nil { - log.ZError(ctx, "entering onNewMsg Unmarshal failed", err, "message", msg) + log.ZError(ctx, "typing onNewMsg Unmarshal failed", err, "message", msg) return } if msg.SendID == e.conv.loginUserID { @@ -176,7 +176,7 @@ func (e *entering) onNewMsg(ctx context.Context, msg *sdkws.MsgData) { } conversationID := e.conv.getConversationIDBySessionType(sourceID, int(msg.SessionType)) key := e.getStateKey(conversationID, msg.SendID, msg.SenderPlatformID) - if enteringElem.Focus { + if enteringElem.MsgTips == "yes" { d := time.Duration(expirationTimestamp-now) * time.Millisecond if v, t, ok := e.state.GetWithExpiration(key); ok { if t.UnixMilli() >= expirationTimestamp { @@ -200,12 +200,12 @@ type InputStatesChangedData struct { PlatformIDs []int32 `json:"platformIDs"` } -func (e *entering) changes(conversationID string, userID string) { +func (e *typing) changes(conversationID string, userID string) { data := InputStatesChangedData{ConversationID: conversationID, UserID: userID, PlatformIDs: e.GetInputStates(conversationID, userID)} - e.conv.userListener().OnUserInputStatusChanged(utils.StructToJsonString(data)) + e.conv.ConversationListener().OnConversationUserInputStatusChanged(utils.StructToJsonString(data)) } -func (e *entering) GetInputStates(conversationID string, userID string) []int32 { +func (e *typing) GetInputStates(conversationID string, userID string) []int32 { platformIDs := make([]int32, 0, 1) for _, platformID := range e.platformIDs { key := e.getStateKey(conversationID, userID, platformID) diff --git a/msgtest/sdk_user_simulator/listener.go b/msgtest/sdk_user_simulator/listener.go index 265c5e540..baf072d2a 100644 --- a/msgtest/sdk_user_simulator/listener.go +++ b/msgtest/sdk_user_simulator/listener.go @@ -38,11 +38,11 @@ func (c *conversationCallBack) OnSyncServerFinish() { } -type userCallback struct { -} +func (c *conversationCallBack) OnConversationUserInputStatusChanged(change string) { -func (c userCallback) OnUserInputStatusChanged(change string) { +} +type userCallback struct { } func (c userCallback) OnUserStatusChanged(statusMap string) { @@ -108,6 +108,10 @@ func (m *MsgListenerCallBak) OnRecvMessageExtensionsChanged(msgID string, reacti func (m *MsgListenerCallBak) OnRecvMessageExtensionsDeleted(msgID string, reactionExtensionKeyList string) { } +func (m *MsgListenerCallBak) OnRecvOnlineOnlyMessage(message string) { + +} + type testFriendListener struct { } diff --git a/open_im_sdk/em.go b/open_im_sdk/em.go index e69140cb2..6ea102f26 100644 --- a/open_im_sdk/em.go +++ b/open_im_sdk/em.go @@ -174,6 +174,10 @@ func (e *emptyConversationListener) OnTotalUnreadMessageCountChanged(totalUnread "totalUnreadCount", totalUnreadCount) } +func (e *emptyConversationListener) OnConversationUserInputStatusChanged(change string) { + +} + type emptyAdvancedMsgListener struct { ctx context.Context } @@ -182,6 +186,10 @@ func newEmptyAdvancedMsgListener(ctx context.Context) open_im_sdk_callback.OnAdv return &emptyAdvancedMsgListener{ctx} } +func (e *emptyAdvancedMsgListener) OnRecvOnlineOnlyMessage(message string) { + +} + func (e *emptyAdvancedMsgListener) OnRecvNewMessage(message string) { log.ZWarn(e.ctx, "AdvancedMsgListener is not implemented", nil, "message", message) } @@ -242,10 +250,6 @@ type emptyUserListener struct { ctx context.Context } -func (e *emptyUserListener) OnUserInputStatusChanged(change string) { - log.ZWarn(e.ctx, "UserListener OnUserInputStatusChanged is not implemented", nil, "change", change) -} - func newEmptyUserListener(ctx context.Context) open_im_sdk_callback.OnUserListener { return &emptyUserListener{ctx: ctx} } diff --git a/open_im_sdk/userRelated.go b/open_im_sdk/userRelated.go index f653b6218..43e9b21ac 100644 --- a/open_im_sdk/userRelated.go +++ b/open_im_sdk/userRelated.go @@ -363,7 +363,6 @@ func (u *LoginMgr) setListener(ctx context.Context) { setListener(ctx, &u.advancedMsgListener, u.AdvancedMsgListener, u.conversation.SetMsgListener, newEmptyAdvancedMsgListener) setListener(ctx, &u.batchMsgListener, u.BatchMsgListener, u.conversation.SetBatchMsgListener, nil) setListener(ctx, &u.businessListener, u.BusinessListener, u.business.SetListener, newEmptyCustomBusinessListener) - setListener(ctx, &u.userListener, u.UserListener, u.conversation.SetOnUserListener, newEmptyUserListener) } func setListener[T any](ctx context.Context, listener *T, getter func() T, setFunc func(listener func() T), newFunc func(context.Context) T) { diff --git a/open_im_sdk_callback/callback_client.go b/open_im_sdk_callback/callback_client.go index e1ea6ff59..68285396c 100644 --- a/open_im_sdk_callback/callback_client.go +++ b/open_im_sdk_callback/callback_client.go @@ -63,7 +63,9 @@ type OnConversationListener interface { OnNewConversation(conversationList string) OnConversationChanged(conversationList string) OnTotalUnreadMessageCountChanged(totalUnreadCount int32) + OnConversationUserInputStatusChanged(change string) } + type OnAdvancedMsgListener interface { OnRecvNewMessage(message string) OnRecvC2CReadReceipt(msgReceiptList string) @@ -75,6 +77,7 @@ type OnAdvancedMsgListener interface { OnRecvMessageExtensionsAdded(msgID string, reactionExtensionList string) OnRecvOfflineNewMessage(message string) OnMsgDeleted(message string) + OnRecvOnlineOnlyMessage(message string) } type OnBatchMsgListener interface { @@ -85,7 +88,6 @@ type OnBatchMsgListener interface { type OnUserListener interface { OnSelfInfoUpdated(userInfo string) OnUserStatusChanged(userOnlineStatus string) - OnUserInputStatusChanged(change string) } type OnCustomBusinessListener interface { diff --git a/pkg/constant/constant.go b/pkg/constant/constant.go index f9c7f1d5f..c07fd37ad 100644 --- a/pkg/constant/constant.go +++ b/pkg/constant/constant.go @@ -66,7 +66,6 @@ const ( CustomMsgOnlineOnly = 120 ReactionMessageModifier = 121 ReactionMessageDeleter = 122 - Entering = 123 ////////////////////////////////////////// NotificationBegin = 1000 diff --git a/sdk_struct/sdk_struct.go b/sdk_struct/sdk_struct.go index 71dd080f9..20a246afe 100644 --- a/sdk_struct/sdk_struct.go +++ b/sdk_struct/sdk_struct.go @@ -201,10 +201,6 @@ type TypingElem struct { MsgTips string `json:"msgTips,omitempty"` } -type EnteringElem struct { - Focus bool `json:"focus"` -} - type MsgStruct struct { ClientMsgID string `json:"clientMsgID,omitempty"` ServerMsgID string `json:"serverMsgID,omitempty"` @@ -244,7 +240,6 @@ type MsgStruct struct { NotificationElem *NotificationElem `json:"notificationElem,omitempty"` AdvancedTextElem *AdvancedTextElem `json:"advancedTextElem,omitempty"` TypingElem *TypingElem `json:"typingElem,omitempty"` - EnteringElem *EnteringElem `json:"enteringElem,omitempty"` AttachedInfoElem *AttachedInfoElem `json:"attachedInfoElem,omitempty"` } diff --git a/test/t_conversation_msg.go b/test/t_conversation_msg.go index d71932798..c4802cff6 100644 --- a/test/t_conversation_msg.go +++ b/test/t_conversation_msg.go @@ -564,6 +564,10 @@ func (m *MsgListenerCallBak) OnRecvMessageExtensionsDeleted(msgID string, reacti log.ZInfo(ctx, "internal", "OnRecvMessageExtensionsDeleted", "msgID", msgID, "reactionExtensionKeyList", reactionExtensionKeyList) } +func (m *MsgListenerCallBak) OnRecvOnlineOnlyMessage(message string) { + +} + type BatchMsg struct { } @@ -673,6 +677,10 @@ func (c *conversationCallBack) OnTotalUnreadMessageCountChanged(totalUnreadCount log.ZInfo(ctx, "OnTotalUnreadMessageCountChanged returnTotalUnreadCount is", totalUnreadCount) } +func (c *conversationCallBack) OnConversationUserInputStatusChanged(change string) { + +} + type testMarkC2CMessageAsRead struct { } diff --git a/test/t_friend_sdk.go b/test/t_friend_sdk.go index 23a3a5d80..ddc50287f 100644 --- a/test/t_friend_sdk.go +++ b/test/t_friend_sdk.go @@ -666,10 +666,6 @@ func InOutDoTestSendMsg(sendId, receiverID string) { type userCallback struct { } -func (c userCallback) OnUserInputStatusChanged(change string) { - -} - func (c userCallback) OnUserStatusChanged(statusMap string) { log.ZInfo(ctx, "User Status Changed", "statusMap", statusMap) } diff --git a/testv2/init.go b/testv2/init.go index e6ebf4eed..e4b705be4 100644 --- a/testv2/init.go +++ b/testv2/init.go @@ -162,6 +162,10 @@ func (o *onConversationListener) OnTotalUnreadMessageCountChanged(totalUnreadCou log.ZInfo(o.ctx, "OnTotalUnreadMessageCountChanged", "totalUnreadCount", totalUnreadCount) } +func (o *onConversationListener) OnConversationUserInputStatusChanged(change string) { + log.ZInfo(o.ctx, "OnConversationUserInputStatusChanged", "change", change) +} + type onGroupListener struct { ctx context.Context } @@ -214,6 +218,10 @@ type onAdvancedMsgListener struct { ctx context.Context } +func (o *onAdvancedMsgListener) OnRecvOnlineOnlyMessage(message string) { + log.ZDebug(o.ctx, "OnRecvOnlineOnlyMessage", "message", message) +} + func (o *onAdvancedMsgListener) OnRecvOfflineNewMessage(message string) { //TODO implement me panic("implement me") @@ -311,10 +319,6 @@ type onUserListener struct { ctx context.Context } -func (o *onUserListener) OnUserInputStatusChanged(change string) { - -} - func (o *onUserListener) OnSelfInfoUpdated(userInfo string) { log.ZDebug(context.Background(), "OnBlackDeleted", "blackInfo", userInfo) } diff --git a/wasm/event_listener/listener.go b/wasm/event_listener/listener.go index 08d0f2fc8..65410f638 100644 --- a/wasm/event_listener/listener.go +++ b/wasm/event_listener/listener.go @@ -93,6 +93,10 @@ func (c ConversationCallback) OnTotalUnreadMessageCountChanged(totalUnreadCount c.CallbackWriter.SetEvent(utils.GetSelfFuncName()).SetData(totalUnreadCount).SendMessage() } +func (c ConversationCallback) OnConversationUserInputStatusChanged(change string) { + c.CallbackWriter.SetEvent(utils.GetSelfFuncName()).SetData(change).SendMessage() +} + type AdvancedMsgCallback struct { CallbackWriter } @@ -149,6 +153,10 @@ func (a AdvancedMsgCallback) OnMsgDeleted(message string) { a.CallbackWriter.SetEvent(utils.GetSelfFuncName()).SetData(message).SendMessage() } +func (a AdvancedMsgCallback) OnRecvOnlineOnlyMessage(message string) { + a.CallbackWriter.SetEvent(utils.GetSelfFuncName()).SetData(message).SendMessage() +} + type BaseCallback struct { CallbackWriter } From e53e06f493dc20b5f49229084ae19c19a936b290 Mon Sep 17 00:00:00 2001 From: zhaolibo Date: Fri, 5 Jan 2024 10:14:52 +0800 Subject: [PATCH 8/8] Fix #475 (#476) * fix: pull message unread count remove. Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> * BUG: Fix getUpload, fill UploadID and ExpireTime only if dbUpload != nil. * BUG: Fix sending video message, fill VideoElem.VideoURL only if UploadFile result is not nil. --------- Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com> Co-authored-by: Gordon <46924906+FGadvancer@users.noreply.github.com> (cherry picked from commit af64509d38c087284fe2b50ff59658404c61346d) --- internal/conversation_msg/sdk.go | 4 +++- internal/file/upload.go | 15 +++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/internal/conversation_msg/sdk.go b/internal/conversation_msg/sdk.go index 12b5f2ac5..3365429d3 100644 --- a/internal/conversation_msg/sdk.go +++ b/internal/conversation_msg/sdk.go @@ -554,7 +554,9 @@ func (c *Conversation) SendMessage(ctx context.Context, s *sdk_struct.MsgStruct, c.updateMsgStatusAndTriggerConversation(ctx, s.ClientMsgID, "", s.CreateTime, constant.MsgStatusSendFailed, s, lc) putErrs = err } - s.VideoElem.VideoURL = res.URL + if res != nil { + s.VideoElem.VideoURL = res.URL + } }() wg.Wait() if err := putErrs; err != nil { diff --git a/internal/file/upload.go b/internal/file/upload.go index ae15e3737..b693a4ad0 100644 --- a/internal/file/upload.go +++ b/internal/file/upload.go @@ -435,17 +435,20 @@ func (f *File) getUpload(ctx context.Context, req *third.InitiateMultipartUpload } else { bitmap = ParseBitmap(bitmapBytes, partNum) } + tUpInfo := &third.UploadInfo{ + PartSize: req.PartSize, + Sign: &third.AuthSignParts{}, + } + if dbUpload != nil { + tUpInfo.UploadID = dbUpload.UploadID + tUpInfo.ExpireTime = dbUpload.ExpireTime + } return &UploadInfo{ PartNum: partNum, Bitmap: bitmap, DBInfo: dbUpload, Resp: &third.InitiateMultipartUploadResp{ - Upload: &third.UploadInfo{ - UploadID: dbUpload.UploadID, - PartSize: req.PartSize, - ExpireTime: dbUpload.ExpireTime, - Sign: &third.AuthSignParts{}, - }, + Upload: tUpInfo, }, BatchSignNum: req.MaxParts, f: f,