Преглед изворни кода

feat: 增加deep_chat_hit,playmate_proactive_chat事件上报

DoggyZhang пре 1 недеља
родитељ
комит
8e3a4195dd

+ 63 - 0
app/src/main/java/com/adealink/weparty/stat/HttpEvent.kt

@@ -0,0 +1,63 @@
+package com.adealink.weparty.stat
+
+import com.adealink.frame.log.Log
+import com.adealink.frame.statistics.BaseStatEvent
+import com.adealink.frame.statistics.CommonEventValue
+import com.adealink.frame.statistics.IEventValue
+import com.adealink.frame.statistics.TAG_STAT
+import com.adealink.weparty.App
+import com.adealink.weparty.stat.data.ReportEventReq
+import com.adealink.weparty.stat.datasource.remote.EventHttpService
+import kotlinx.coroutines.launch
+
+open class HttpEvent(override val eventId: String) : BaseStatEvent(eventId) {
+
+    private val eventHttpService by lazy {
+        App.instance.networkService.getHttpService(EventHttpService::class.java)
+    }
+
+    override val action: IEventValue = CommonEventValue.Action.EMPTY
+
+    val scene = Param("scene")
+    val targetUid = Param("targetUserNo")
+    val businessId = Param("businessId")
+    val extra = Param("extra")
+
+    override fun send() {
+        launch {
+            Log.d(TAG_STAT, "report http event($eventId), scene:${scene.value}")
+            val scene = scene.value as? String ?: return@launch
+            val targetUid = targetUid.value as? String
+            val businessId = businessId.value as? String
+
+            eventHttpService.reportEvent(
+                ReportEventReq(
+                    eventId = eventId,
+                    scene = scene,
+
+                    targetUid = targetUid,
+                    businessId = businessId,
+                    extra = getExtraParams()
+                )
+            )
+        }
+    }
+
+    private fun getExtraParams(): Map<String, String> {
+        val extraMap = mutableMapOf<String, String>()
+
+        val commonEvent = createEventMap()
+        for (entry in commonEvent.entries) {
+            extraMap[entry.key] = extra.value.toString()
+        }
+
+        val extra = extra.value as? Map<String, String>
+        if (!extra.isNullOrEmpty()) {
+            for (entry in extra.entries) {
+                extraMap[entry.key] = entry.value
+            }
+        }
+        return extraMap
+    }
+
+}

+ 16 - 0
app/src/main/java/com/adealink/weparty/stat/data/StatData.kt

@@ -0,0 +1,16 @@
+package com.adealink.weparty.stat.data
+
+import com.google.gson.annotations.GsonNullable
+import com.google.gson.annotations.SerializedName
+
+data class ReportEventReq(
+    @SerializedName("eventType") val eventId: String, //事件类型(统一事件名),示例值(profile_visit)
+    @SerializedName("scene") val scene: String, //事件场景(页面、入口位等),示例值(user_visitor_report)
+
+    @GsonNullable
+    @SerializedName("targetUserNo") val targetUid: String? = null, //目标用户编号(userNo),示例值(U100001)
+    @GsonNullable
+    @SerializedName("businessId") val businessId: String? = null, //业务对象ID(订单号、卡片ID等),示例值(order_no_xxx)
+    @GsonNullable
+    @SerializedName("extra") val extra: Map<String, String>? = null, //扩展字段
+)

+ 16 - 0
app/src/main/java/com/adealink/weparty/stat/datasource/remote/EventHttpService.kt

@@ -0,0 +1,16 @@
+package com.adealink.weparty.stat.datasource.remote
+
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.network.data.Res
+import com.adealink.weparty.stat.data.ReportEventReq
+import retrofit2.http.Body
+import retrofit2.http.Core
+import retrofit2.http.POST
+
+interface EventHttpService {
+
+    @Core
+    @POST("event/report")
+    suspend fun reportEvent(@Body req: ReportEventReq): Rlt<Res<Any>>
+
+}

+ 17 - 0
app/src/main/java/com/adealink/weparty/util/CollectionsExt.kt

@@ -0,0 +1,17 @@
+package com.adealink.weparty.util
+
+public inline fun <T> List<T>.takeLastIf(n: Int, predicate: (T) -> Boolean): List<T> {
+    if (isEmpty())
+        return emptyList()
+    val iterator = listIterator(size)
+    val list = mutableListOf<T>()
+    while (iterator.hasPrevious()) {
+        val previous = iterator.previous()
+        if (predicate(previous)) {
+            list.add(previous)
+            if (list.size == n)
+                break
+        }
+    }
+    return list.reversed()
+}

+ 2 - 0
module/im/src/main/java/com/adealink/weparty/im/session/SessionActivity.kt

@@ -14,6 +14,7 @@ import com.adealink.weparty.commonui.ext.dp
 import com.adealink.weparty.im.databinding.ActivitySessionBinding
 import com.adealink.weparty.im.session.comp.SessionTopComp
 import com.adealink.weparty.im.session.viewmodel.SessionSettingViewModel
+import com.adealink.weparty.im.stat.PlaymateInitiateChatEvent
 import com.adealink.weparty.im.stat.StartSessionEvent
 import com.adealink.weparty.im.viewmodel.IMViewModelFactory
 import com.adealink.weparty.module.im.IM
@@ -64,6 +65,7 @@ class SessionActivity : BaseActivity() {
             userId to chatInfo?.id
             sessionId to chatInfo?.id
         }.send()
+        PlaymateInitiateChatEvent.checkInitiateChat(chatInfo?.id)
     }
 
     override fun onNewIntent(intent: Intent) {

+ 2 - 1
module/im/src/main/java/com/adealink/weparty/im/session/SessionFragment.kt

@@ -251,7 +251,8 @@ class SessionFragment : BaseFragment(R.layout.fragment_session) {
         SessionBottomComp(
             this,
             binding.bottomBar,
-            chatInfo as? C2CChatInfo
+            chatInfo as? C2CChatInfo,
+            sessionPresenter
         ).attach()
     }
 

+ 8 - 3
module/im/src/main/java/com/adealink/weparty/im/session/comp/SessionBottomComp.kt

@@ -11,10 +11,12 @@ import com.adealink.weparty.im.databinding.LayoutSessionBottomBarBinding
 import com.adealink.weparty.im.session.comp.input.InputAction
 import com.adealink.weparty.im.session.comp.input.InputState
 import com.adealink.weparty.im.session.comp.viewmodel.SessionInputViewModel
+import com.adealink.weparty.im.stat.DeepChatEvent
 import com.adealink.weparty.module.im.IM
 import com.adealink.weparty.module.im.data.SessionSource
-import com.adealink.weparty.module.im.data.sendIMMessageLD
 import com.adealink.weparty.module.playmate.PlaymateModule
+import com.adealink.weparty.module.profile.ProfileModule
+import com.adealink.weparty.util.takeLastIf
 import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean
 import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo
 import com.tencent.qcloud.tuikit.tuichat.presenter.ChatPresenter
@@ -22,8 +24,8 @@ import com.tencent.qcloud.tuikit.tuichat.presenter.ChatPresenter
 class SessionBottomComp(
     lifecycleOwner: LifecycleOwner,
     val bottomBar: LayoutSessionBottomBarBinding,
-    val chatInfo: ChatInfo? = null,
-    val presenter: ChatPresenter? = null
+    val chatInfo: ChatInfo?,
+    val presenter: ChatPresenter?
 ) : ViewComponent(lifecycleOwner) {
 
     private val inputViewModel by activityViewModels<SessionInputViewModel>()
@@ -92,6 +94,9 @@ class SessionBottomComp(
                 PlaymateModule.reportUserPushChat(uid)
             }
         }
+        //深度聊天检查
+        val lastMessages = presenter?.loadedMessageList?.takeLastIf(5) { it.sender == ProfileModule.getMyUid() }
+        DeepChatEvent.checkDeepChat(lastMessages)
     }
 
 }

+ 38 - 0
module/im/src/main/java/com/adealink/weparty/im/stat/DeepChatEvent.kt

@@ -0,0 +1,38 @@
+package com.adealink.weparty.im.stat
+
+import com.adealink.frame.statistics.CommonEventValue
+import com.adealink.frame.statistics.IEventValue
+import com.adealink.weparty.stat.HttpEvent
+import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean
+
+/**
+ * 存在任意连续10分钟内,陪玩师向同一用户发送消息数量≥5条的去重用户数
+ */
+class DeepChatEvent : HttpEvent("deep_chat_hit") {
+
+    override val action: IEventValue = CommonEventValue.Action.EMPTY
+    override fun toString(): String {
+        return "DeepChatEvent(targetUid:${targetUid.value}, scene:${scene.value})"
+    }
+
+    companion object {
+        @JvmStatic
+        fun checkDeepChat(lastMessageList: List<TUIMessageBean>?) {
+            if (lastMessageList.isNullOrEmpty() || lastMessageList.size != 5) {
+                return
+            }
+            val firstMessage = lastMessageList.firstOrNull()
+            val lastMessage = lastMessageList.lastOrNull()
+            if (firstMessage == null || lastMessage == null) {
+                return
+            }
+            val timeOffset = lastMessage.messageTime - firstMessage.messageTime //单位:秒
+            if (timeOffset < 600) {
+                DeepChatEvent().apply {
+                    scene to "playmate_deep_chat_report"
+                    targetUid to firstMessage.userId
+                }.send()
+            }
+        }
+    }
+}

+ 39 - 0
module/im/src/main/java/com/adealink/weparty/im/stat/PlaymateInitiateChatEvent.kt

@@ -0,0 +1,39 @@
+package com.adealink.weparty.im.stat
+
+import com.adealink.frame.router.Router
+import com.adealink.frame.statistics.CommonEventValue
+import com.adealink.frame.statistics.IEventValue
+import com.adealink.frame.util.AppUtil
+import com.adealink.weparty.module.profile.Profile
+import com.adealink.weparty.stat.HttpEvent
+
+/**
+ * 陪玩师主动聊天
+ */
+class PlaymateInitiateChatEvent : HttpEvent("playmate_proactive_chat") {
+
+    override val action: IEventValue = CommonEventValue.Action.EMPTY
+    override fun toString(): String {
+        return "PlaymateInitiateChatEvent(targetUid:${targetUid.value}, scene${scene.value})"
+    }
+
+    companion object {
+        @JvmStatic
+        fun checkInitiateChat(targetUid: String?) {
+            if (targetUid.isNullOrEmpty()) {
+                return
+            }
+            val visitActivity = Router.getClazz(Profile.Visitor.PATH) ?: return
+            val fromVisit = AppUtil.runningActivities.find {
+                it.contains(visitActivity.name)
+            } != null
+            if (!fromVisit) {
+                return
+            }
+            PlaymateInitiateChatEvent().apply {
+                this.scene to "playmate_proactive_chat_report"
+                this.targetUid to targetUid
+            }.send()
+        }
+    }
+}