Skip to main content

Discord Bot Integration Example

A concise example showing how to integrate Cirvia Parental monitoring into a Discord bot that monitors children's server activity.

Bot Setup

DiscordMonitorBot.java

public class DiscordMonitorBot {
private static final String PLATFORM = "discord";

// Monitor text messages
public void onMessageReceived(String channelId, String authorId, String content) {
if (content != null && !content.trim().isEmpty()) {
ParentalAI.sendTextIncident(PLATFORM + "-message", content);
}
processMessage(channelId, authorId, content);
}

// Monitor direct messages
public void onDirectMessage(String senderId, String content) {
ParentalAI.sendTextIncident(PLATFORM + "-dm", content);
processDirectMessage(senderId, content);
}

// Monitor image attachments
public void onImageAttachment(String channelId, String imageUrl) {
new Thread(() -> {
try {
Bitmap image = downloadImageFromUrl(imageUrl);
if (image != null) {
String base64 = ImageEncoder.encodeImageToBase64(image);
ParentalAI.sendImageIncident(PLATFORM + "-image", base64);
}
} catch (Exception e) {
Log.e("DiscordBot", "Failed to monitor image", e);
}
}).start();
}

// Monitor channel/server creation
public void onChannelCreated(String channelName, String topic) {
ParentalAI.sendTextIncident(PLATFORM + "-channel", channelName);
if (topic != null && !topic.trim().isEmpty()) {
ParentalAI.sendTextIncident(PLATFORM + "-topic", topic);
}
}

// Monitor nickname changes
public void onNicknameChanged(String userId, String newNickname) {
ParentalAI.sendTextIncident(PLATFORM + "-nickname", newNickname);
updateUserNickname(userId, newNickname);
}
}

Message Listener

MessageEventHandler.java

public class MessageEventHandler {
private final DiscordMonitorBot monitor = new DiscordMonitorBot();

public void handleTextMessage(MessageEvent event) {
String content = event.getMessage().getContent();
String channelId = event.getChannel().getId();
String authorId = event.getAuthor().getId();

// Skip bot messages
if (event.getAuthor().isBot()) {
return;
}

// Monitor the message
monitor.onMessageReceived(channelId, authorId, content);

// Handle bot commands if any
if (content.startsWith("!")) {
handleBotCommand(event);
}
}

public void handleDirectMessage(DirectMessageEvent event) {
String content = event.getMessage().getContent();
String senderId = event.getAuthor().getId();

monitor.onDirectMessage(senderId, content);
}

public void handleImageMessage(MessageEvent event) {
List<String> attachments = event.getMessage().getAttachments();

for (String attachmentUrl : attachments) {
if (isImageUrl(attachmentUrl)) {
monitor.onImageAttachment(event.getChannel().getId(), attachmentUrl);
}
}
}
}

Bot Commands

CommandHandler.java

public class CommandHandler {

public void handleParentCommand(MessageEvent event) {
String command = event.getMessage().getContent();

if (command.equals("!monitoring status")) {
showMonitoringStatus(event);
} else if (command.equals("!monitoring enable")) {
enableMonitoring(event);
} else if (command.equals("!monitoring disable")) {
disableMonitoring(event);
}
}

private void showMonitoringStatus(MessageEvent event) {
boolean enabled = MonitoringConfig.isEnabled();
String status = enabled ? "✅ Enabled" : "❌ Disabled";

event.getChannel().sendMessage("Parental monitoring: " + status);
}

private void enableMonitoring(MessageEvent event) {
// Verify user has permission (parent/admin)
if (hasParentPermission(event.getAuthor())) {
MonitoringConfig.setEnabled(true);
event.getChannel().sendMessage("✅ Parental monitoring enabled");
} else {
event.getChannel().sendMessage("❌ Only parents can control monitoring");
}
}
}

Configuration

BotConfig.java

public class BotConfig {
private static final String PREFS_NAME = "discord_bot_config";

public static class MonitoringConfig {
private static SharedPreferences getPrefs() {
return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
}

public static boolean isEnabled() {
return getPrefs().getBoolean("monitoring_enabled", true);
}

public static void setEnabled(boolean enabled) {
getPrefs().edit().putBoolean("monitoring_enabled", enabled).apply();
}

public static Set<String> getMonitoredChannels() {
return getPrefs().getStringSet("monitored_channels", new HashSet<>());
}

public static void addMonitoredChannel(String channelId) {
Set<String> channels = new HashSet<>(getMonitoredChannels());
channels.add(channelId);
getPrefs().edit().putStringSet("monitored_channels", channels).apply();
}
}
}

Advanced Features

ReactionMonitor.java

public class ReactionMonitor {

public void onReactionAdded(String messageId, String emoji, String userId) {
// Monitor custom emoji names for inappropriate content
if (emoji.length() > 2 && !isDefaultEmoji(emoji)) {
ParentalAI.sendTextIncident("discord-emoji", emoji);
}
}

public void onStatusUpdate(String userId, String status) {
if (status != null && !status.trim().isEmpty()) {
ParentalAI.sendTextIncident("discord-status", status);
}
}

private boolean isDefaultEmoji(String emoji) {
// Check if it's a standard Unicode emoji
return emoji.matches("[\\u2600-\\u27BF]|[\\uD83C-\\uD83D][\\uDC00-\\uDFFF]");
}
}

Error Handling

BotErrorHandler.java

public class BotErrorHandler {
private static final String TAG = "DiscordBot";

public static void handleMonitoringError(Exception error, String content, String context) {
Log.e(TAG, "Monitoring failed for " + context, error);

// Continue bot functionality regardless of monitoring errors
if (error instanceof IllegalStateException) {
Log.w(TAG, "SDK not ready - queuing content for later monitoring");
OfflineQueue.getInstance().addItem(content, "discord-" + context);
}
}

public static void handleNetworkError(Exception error) {
Log.w(TAG, "Network error - monitoring will resume when connection restored");
// Bot continues to function, monitoring queued offline
}
}

Bot Initialization

DiscordBotApplication.java

public class DiscordBotApplication extends Application {

@Override
public void onCreate() {
super.onCreate();

// Initialize Cirvia SDK first
initializeCirvia();

// Then start Discord bot
initializeDiscordBot();
}

private void initializeCirvia() {
ParentalAIConfig config = new ParentalAIConfig(
BuildConfig.CIRVIA_API_KEY,
BuildConfig.CIRVIA_INGEST_URL,
BuildConfig.CIRVIA_AUTH_URL,
BuildConfig.DEBUG
);

ParentalAI.init(this, config,
() -> Log.i("DiscordBot", "Cirvia monitoring ready"),
() -> Log.w("DiscordBot", "Cirvia monitoring declined")
);
}

private void initializeDiscordBot() {
// Initialize your Discord bot here
// Register event handlers with monitoring
}
}

Testing

BotTest.java

@RunWith(AndroidJUnit4.class)
public class BotTest {

@Test
public void testMessageMonitoring() {
DiscordMonitorBot bot = new DiscordMonitorBot();

// Test message monitoring
bot.onMessageReceived("channel123", "user456", "Hello world!");

// Test direct message
bot.onDirectMessage("user789", "Private message here");

// Should complete without errors
assertTrue("Bot monitoring works", true);
}

@Test
public void testCommandHandling() {
CommandHandler handler = new CommandHandler();

// Mock message event
MessageEvent mockEvent = createMockMessageEvent("!monitoring status");

handler.handleParentCommand(mockEvent);

// Verify command was processed
assertTrue("Command handled successfully", true);
}
}

Deployment Notes

Parent Dashboard Integration

The Discord bot automatically categorizes incidents by:

  • discord-message - Public channel messages
  • discord-dm - Direct messages
  • discord-image - Image attachments
  • discord-channel - New channel names
  • discord-emoji - Custom emoji usage

Parents will see Discord incidents in their dashboard with full context about which server/channel the content came from.

Security Considerations

  • Store Discord bot token securely
  • Validate user permissions for monitoring commands
  • Don't log sensitive Discord API tokens
  • Use rate limiting to respect Discord API limits

Next Steps


Discord monitoring ready! This bot will monitor all key Discord interactions while maintaining smooth server performance. Customize the monitored content types based on your specific needs.