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
- Parent Dashboard → - How parents view Discord incidents
- API Reference → - Complete SDK documentation
- Troubleshooting → - Common Discord integration issues
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.