Report offensive messages
Chat SDK provides a mechanism for users to report offensive content in messages directly from their applications.
In each case, a user must provide a reason for flagging a given message. As a result of flagging, a reported message gets published on the dedicated administrative channel (with the ID of PUBNUB_INTERNAL_MODERATION_{channel_id}) and an event of the Report type gets created.
As a developer, you can add custom logic that uses the emitted events and defines what an admin can later do with such reported messages. For example, an admin can delete an inappropriate message.
Message Persistence
To work with stored message data, make sure you have Message Persistence enabled for your app's keyset in the Admin Portal.
Flag/Report messages
report() lets you flag and report an inappropriate message to the admin.
All messages (events of type Report) reported on a given channel are sent to a PUBNUB_INTERNAL_MODERATION_{channel_id} channel which is a child channel for the main one where a reported message was published. For example, an event on a message reported on the support channel will be sent to the PUBNUB_INTERNAL_MODERATION_support channel.
Method signature
This method takes the following parameters:
1message.report(
2    reason: String
3) async throws -> Timetoken
Input
| Parameter | Description | 
|---|---|
| reason*Type:  StringDefault: n/a | Reason for reporting/flagging a given message. | 
Output
| Parameter | Description | 
|---|---|
| Timetoken | The Timetokenvalue of the reported message. | 
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Report the last message on the support channel as offensive.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3  if let channel = try await chat.getChannel(channelId: "support") {
4    if let message = try await channel.getHistory(count: 1).messages.first {
5      let timetoken = try await message.report(reason: "Offensive Content")
6      debugPrint("Reported message successfully: \(timetoken)")
7    } else {
8      debugPrint("No messages found in the \"support\" channel")
9    }
10  } else {
11    debugPrint("Channel not found")
12  }
13}
Get historical reported messages
getMessageReportsHistory() fetches a list of reported message events for a specified channel within optional time and count constraints, returning the events and a boolean indicating if there are more events to fetch.
This method prefixes the internal channel ID with a predefined string (PUBNUB_INTERNAL_MODERATION_) and calls the getEventsHistory method of the chat instance, passing along the constructed channel ID and any additional parameters.
Method signature
This method takes the following parameters:
1channel.getMessageReportsHistory(
2    startTimetoken: Timetoken? = nil,
3    endTimetoken: Timetoken? = nil,
4    count: Int = 25
5) async throws -> (events: [EventWrapper<EventContent>], isMore: Bool)
Input
| Parameter | Description | 
|---|---|
| startTimetokenType:  TimetokenDefault: n/a | The start timetoken for fetching the history of reported messages, which allows specifying the point in time where the history retrieval should begin. | 
| endTimetokenType:  TimetokenDefault: n/a | The end time token for fetching the history of reported messages, which allows specifying the point in time where the history retrieval should end. | 
| countType:  IntDefault: 25 | The number of reported message events to fetch from the history. | 
Output
| Parameter | Description | 
|---|---|
| (events: [EventWrapper<EventContent>], isMore: Bool) | Returned tuple containing these fields: eventsandisMore. | 
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Fetch historical messages reported on the support channel between the 1725100800000 (July 1, 2024, 00:00:00 UTC) and 1726780799000 (July 21, 2024, 23:59:59 UTC) timetokens.
1// Define timetokens for the message history period
2let startTimetoken: Timetoken = 1725100800000 // July 1, 2024, 00:00:00 UTC
3let endTimetoken: Timetoken = 1726780799000 // July 21, 2024, 23:59:59 UTC
4
5// Assuming you have a reference of type "ChatImpl" named "chat"
6Task {
7  if let channel = try await chat.getChannel(channelId: "support") {
8    let historyResponse = try await channel.getMessageReportsHistory(
9      startTimetoken: startTimetoken,
10      endTimetoken: endTimetoken,
11      count: 25
12    )
13    historyResponse.events.forEach { eventWrapper in
14      print("Payload: \(eventWrapper.event.payload)")
15    }
Listen to Report events
As an admin of your chat app, you can monitor all events emitted when someone reports an offensive message using the streamMessageReports() method.
You can use this method to create moderation dashboard alerts.
Events documentation
To read more about the events of type Report, refer to the Chat events documentation.
Method signature
This method has the following parameters:
1channel.streamMessageReports() -> AsyncStream<EventWrapper<EventContent.Report>>
Input
This method doesn't take any parameters.
Output
| Parameter | Description | 
|---|---|
| AsyncStream<EventWrapper<EventContent.Report>> | An asynchronous stream that emits a new value whenever a message is reported. | 
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Print a notification for an offensive message reported on the support channel.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3  if let channel = try await chat.getChannel(channelId: "support") {
4    for await event in channel.streamMessageReports() {
5      // Access the report details from the event's payload
6      let reportPayload = event.event.payload
7      let reportReason = reportPayload.reason
8      // Print the notification
9      if reportReason.lowercased() == "offensive" {
10        print("Notification: An offensive message was reported on the 'support' channel by user \(event.event.userId). Reason: \(reportReason)")
11      }
12    }
13  } else {
14    debugPrint("Channel not found")
15  }