Skip to content

Commit

Permalink
Add "PUBNUB_INTERNAL_MODERATION." channel prefix for delivering Moder…
Browse files Browse the repository at this point in the history
…ation events to users (#121)
  • Loading branch information
wkal-pubnub authored Dec 11, 2024
1 parent e5fa4be commit 3cc7416
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
*.podspec
**/*.podspec
node_modules
js-chat/dist
test.properties
Expand Down
3 changes: 3 additions & 0 deletions pubnub-chat-api/api/pubnub-chat-api.api
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,9 @@ public final class com/pubnub/chat/types/EmitEventMethod : java/lang/Enum {
public abstract class com/pubnub/chat/types/EventContent {
public static final field Companion Lcom/pubnub/chat/types/EventContent$Companion;
public synthetic fun <init> (ILkotlinx/serialization/internal/SerializationConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getCustomMessageType ()Ljava/lang/String;
public static final synthetic fun write$Self (Lcom/pubnub/chat/types/EventContent;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ class File(
/**
* Represents the content of various types of events emitted during chat operations.
* This is a sealed class with different subclasses representing specific types of events.
*
* @property customMessageType the `customMessageType` that will be passed as a parameter into
* [com.pubnub.api.PubNub.publish] or [com.pubnub.api.PubNub.signal] when sending this event.
*/
@Serializable
sealed class EventContent {
sealed class EventContent(
@Transient val customMessageType: String? = null
) {
/**
* Represents a typing event that indicates whether a user is typing.
*
Expand Down Expand Up @@ -120,7 +125,7 @@ sealed class EventContent {
@Serializable
@SerialName("moderation")
class Moderation(val channelId: String, val restriction: RestrictionType, val reason: String? = null) :
EventContent()
EventContent(CUSTOM_MESSAGE_TYPE_MODERATED)

/**
* Represents a text message event, containing the message text and any associated files.
Expand Down Expand Up @@ -189,3 +194,5 @@ enum class EmitEventMethod {
*/
PUBLISH
}

private const val CUSTOM_MESSAGE_TYPE_MODERATED = "moderated"
Original file line number Diff line number Diff line change
Expand Up @@ -497,9 +497,17 @@ class ChatImpl(
): PNFuture<PNPublishResult> {
val emitMethod = payload::class.getEmitMethod() ?: (payload as? EventContent.Custom)?.method
return if (emitMethod == EmitEventMethod.SIGNAL) {
pubNub.signal(channel = channelId, message = payload.encodeForSending(mergePayloadWith))
pubNub.signal(
channel = channelId,
message = payload.encodeForSending(mergePayloadWith),
customMessageType = payload.customMessageType
)
} else {
pubNub.publish(channel = channelId, message = payload.encodeForSending(mergePayloadWith))
pubNub.publish(
channel = channelId,
message = payload.encodeForSending(mergePayloadWith),
customMessageType = payload.customMessageType
)
}
}

Expand Down Expand Up @@ -699,7 +707,7 @@ class ChatImpl(
pubNub.removeChannelMembers(channel = channel, uuids = listOf(userId))
.alsoAsync { _ ->
emitEvent(
channelId = userId,
channelId = INTERNAL_USER_MODERATION_CHANNEL_PREFIX + userId,
payload = EventContent.Moderation(
channelId = channel,
restriction = RestrictionType.LIFT,
Expand All @@ -710,16 +718,16 @@ class ChatImpl(
} else {
val custom = createCustomObject(
mapOf(
"ban" to restriction.ban,
"mute" to restriction.mute,
"reason" to restriction.reason
RESTRICTION_BAN to restriction.ban,
RESTRICTION_MUTE to restriction.mute,
RESTRICTION_REASON to restriction.reason
)
)
val uuids = listOf(PNMember.Partial(uuidId = userId, custom = custom, null))
pubNub.setChannelMembers(channel = channel, uuids = uuids)
.alsoAsync { _ ->
emitEvent(
channelId = userId,
channelId = INTERNAL_USER_MODERATION_CHANNEL_PREFIX + userId,
payload = EventContent.Moderation(
channelId = channel,
restriction = if (restriction.ban) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ internal const val ORIGINAL_PUBLISHER = "originalPublisher"
internal const val ORIGINAL_CHANNEL_ID = "originalChannelId"
internal const val HTTP_ERROR_404 = 404
internal const val INTERNAL_MODERATION_PREFIX = "PUBNUB_INTERNAL_MODERATION_"
internal const val INTERNAL_USER_MODERATION_CHANNEL_PREFIX = "PUBNUB_INTERNAL_MODERATION."
internal const val PUBNUB_INTERNAL_AUTOMODERATED = "PUBNUB_INTERNAL_AUTOMODERATED"
internal const val INTERNAL_MODERATOR_DATA_ID = "PUBNUB_INTERNAL_MODERATOR"
internal const val INTERNAL_MODERATOR_DATA_TYPE = "internal"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ class ChannelIntegrationTest : BaseChatIntegrationTest() {
val channel01withChat = channel01
val join01 = channel01withChat.join { }.await()
val join02 = channel01Chat02.join { }.await()
delayInMillis(1000)
delayInMillis(1500)
val whoIsPresent01: Collection<String> = channel01withChat.whoIsPresent().await()
val whoIsPresent02: Collection<String> = channel01Chat02.whoIsPresent().await()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.pubnub.chat.User
import com.pubnub.chat.config.ChatConfiguration
import com.pubnub.chat.config.PushNotificationsConfig
import com.pubnub.chat.internal.ChatImpl
import com.pubnub.chat.internal.INTERNAL_USER_MODERATION_CHANNEL_PREFIX
import com.pubnub.chat.internal.UserImpl
import com.pubnub.chat.internal.error.PubNubErrorMessage
import com.pubnub.chat.internal.utils.cyrb53a
Expand Down Expand Up @@ -621,10 +622,10 @@ class ChatIntegrationTest : BaseChatIntegrationTest() {
val restrictionUnban = Restriction(userId = userId, channelId = channelId, ban = false, mute = false, reason = "ok")
pubnub.test(backgroundScope, checkAllEvents = false) {
var removeListenerAndUnsubscribe: AutoCloseable? = null
pubnub.awaitSubscribe(channels = listOf(userId)) {
pubnub.awaitSubscribe(channels = listOf(INTERNAL_USER_MODERATION_CHANNEL_PREFIX + userId)) {
removeListenerAndUnsubscribe = chat.listenForEvents(
type = EventContent.Moderation::class,
channelId = userId
channelId = INTERNAL_USER_MODERATION_CHANNEL_PREFIX + userId
) { event: Event<EventContent.Moderation> ->
val restrictionType: RestrictionType = event.payload.restriction
if (restrictionType == RestrictionType.BAN) {
Expand Down
36 changes: 32 additions & 4 deletions pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/kmp/ChatTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ import com.pubnub.chat.config.ChatConfiguration
import com.pubnub.chat.config.PushNotificationsConfig
import com.pubnub.chat.internal.ChatImpl
import com.pubnub.chat.internal.ChatInternal
import com.pubnub.chat.internal.INTERNAL_USER_MODERATION_CHANNEL_PREFIX
import com.pubnub.chat.internal.message.MessageImpl
import com.pubnub.chat.internal.timer.TimerManager
import com.pubnub.chat.message.GetUnreadMessagesCounts
import com.pubnub.chat.restrictions.Restriction
import com.pubnub.chat.restrictions.RestrictionType
import com.pubnub.chat.types.ChannelType
import com.pubnub.chat.types.EventContent
import com.pubnub.chat.types.GetEventsHistoryResult
Expand Down Expand Up @@ -650,6 +652,31 @@ class ChatTest : BaseTest() {
assertEquals(forwardedChannelId, actualForwardedChannelId)
}

@Test
fun shouldPassCustomMessageTypeOfEventContentToPublish() {
every { pubnub.publish(any(), any(), any(), any(), any(), any(), any(), any()) } returns publishEndpoint
every { publishEndpoint.async(any()) } calls { (callback1: Consumer<Result<PNPublishResult>>) ->
callback1.accept(Result.success(PNPublishResult(timetoken)))
}
val payload = EventContent.Moderation("a", RestrictionType.BAN, null)

objectUnderTest.emitEvent(
channelId = channelId,
payload = payload,
).async { result ->
assertTrue(result.isSuccess)
assertEquals(timetoken, result.getOrNull()?.timetoken)
}

verify {
pubnub.publish(
channel = channelId,
message = mapOf("type" to "moderation", "channelId" to "a", "restriction" to "banned", "reason" to null),
customMessageType = payload.customMessageType
)
}
}

@Test
fun shouldCalSignalWhenEmitEventWithMethodSignal() {
every { pubnub.signal(any(), any()) } returns signalEndpoint
Expand Down Expand Up @@ -1336,7 +1363,7 @@ class ChatTest : BaseTest() {
every { manageChannelMembersEndpoint.async(any()) } calls { (callback: Consumer<Result<PNMemberArrayResult>>) ->
callback.accept(Result.success(pnMemberArrayResult))
}
every { pubnub.publish(channel = capture(userIdSlot), message = any()) } returns publishEndpoint
every { pubnub.publish(channel = capture(userIdSlot), message = any(), customMessageType = "moderated") } returns publishEndpoint
every { publishEndpoint.async(any()) } calls { (callback1: Consumer<Result<PNPublishResult>>) ->
callback1.accept(Result.success(PNPublishResult(timetoken)))
}
Expand All @@ -1350,7 +1377,7 @@ class ChatTest : BaseTest() {
val actualModerationEventChannelId = userIdSlot.get()
assertEquals(restrictedUserId, actualRestrictedUserId)
assertEquals("PUBNUB_INTERNAL_MODERATION_$restrictedChannelId", actualRestrictedChannelId)
assertEquals(restrictedUserId, actualModerationEventChannelId)
assertEquals(INTERNAL_USER_MODERATION_CHANNEL_PREFIX + restrictedUserId, actualModerationEventChannelId)
}

@Test
Expand Down Expand Up @@ -1390,7 +1417,8 @@ class ChatTest : BaseTest() {
every {
pubnub.publish(
channel = capture(userIdSlot),
message = capture(encodedMessageSlot)
message = capture(encodedMessageSlot),
customMessageType = any()
)
} returns publishEndpoint
every { publishEndpoint.async(any()) } calls { (callback1: Consumer<Result<PNPublishResult>>) ->
Expand All @@ -1409,7 +1437,7 @@ class ChatTest : BaseTest() {
assertEquals(reason, actualRestriction.get("reason"))
assertEquals("banned", actualEncodedMessageSlot["restriction"])
assertEquals("PUBNUB_INTERNAL_MODERATION_$restrictedChannelId", actualRestrictedChannelId)
assertEquals(restrictedUserId, actualModerationEventChannelId)
assertEquals(INTERNAL_USER_MODERATION_CHANNEL_PREFIX + restrictedUserId, actualModerationEventChannelId)
}

private fun createMessage(chId: String = channelId, uId: String = userId): Message {
Expand Down

0 comments on commit 3cc7416

Please sign in to comment.