Skip to main content

Overview

The discord_utils module provides utilities for working with Discord threads, channels, permissions, and user interactions.

Permission Checking

isAdmin(member)

Checks if a Discord member has administrator permissions.
member
discord.Member
required
Discord member to check
return
bool
True if member has administrator permissions, False otherwise
import discord
from mcdis_rcon.utils.discord_utils import isAdmin

# In an addon or plugin
async def on_message(self, message: discord.Message):
    if not isAdmin(message.author):
        await message.channel.send("❌ You need admin permissions")
        return
    
    # Admin-only command logic
    await message.channel.send("✅ Admin command executed")
Source code from /home/daytona/workspace/source/mcdis_rcon/utils/discord_utils.py:3-4:
def isAdmin(member: discord.Member) -> bool:
    return member.guild_permissions.administrator

Thread Management

thread(name, channel, public)

Finds or creates a Discord thread.
name
str
required
Thread name to find or create
channel
discord.TextChannel
required
Parent channel for the thread
public
bool
default:"False"
Whether the thread should be public (visible to all)
return
discord.Thread
The found or newly created thread
import discord
from mcdis_rcon.utils.discord_utils import thread

# In a plugin
class mdplugin:
    def __init__(self, process):
        self.process = process
    
    async def send_log(self, message: str):
        # Get or create a thread
        log_thread = await thread(
            name="Plugin Logs",
            channel=self.process.client.panel,
            public=True
        )
        await log_thread.send(message)
How it works:
  1. Unarchives all archived threads in the channel
  2. Searches for an existing thread with the given name
  3. Returns existing thread if found
  4. Creates a new thread if not found
Source code from /home/daytona/workspace/source/mcdis_rcon/utils/discord_utils.py:6-23:
async def thread(name: str, channel: discord.TextChannel, *, public: bool = False) -> discord.Thread:
    async for thread in channel.archived_threads():
        await thread.edit(archived = False)
    
    thread = next(filter(lambda x: x.name == name, channel.threads), None)

    if thread: 
        return thread
    
    if not public:
        thread = await channel.create_thread(name = name.strip())
        return thread
    else:
        message = await channel.send('_')
        thread = await channel.create_thread(name = name.strip(), message = message)
        await message.delete()
        return thread
This function is used extensively by McDis-RCON to manage console threads for each process.

Confirmation Dialogs

confirmation_request(description, on_confirmation, on_reject, interaction, channel, ephemeral)

Creates an interactive confirmation dialog with ✔ and ✖ buttons.
description
str
required
Message to display in the confirmation embed
on_confirmation
Callable
Function to call when ✔ is clicked
on_reject
Callable
Function to call when ✖ is clicked
interaction
discord.Interaction
Interaction to respond to (for slash commands)
channel
discord.TextChannel
Channel to send the confirmation to
ephemeral
bool
default:"True"
Whether the message should be ephemeral (only visible to user)
import discord
from mcdis_rcon.utils.discord_utils import confirmation_request

class mdaddon:
    def __init__(self, client):
        self.client = client
    
    async def on_message(self, message: discord.Message):
        if message.content == "!delete-all":
            async def confirm(interaction):
                await interaction.response.edit_message(
                    content="Deleting all data...",
                    embed=None,
                    view=None
                )
                # Perform deletion
                await interaction.followup.send("✅ All data deleted")
            
            async def reject(interaction):
                await interaction.response.edit_message(
                    content="❌ Deletion cancelled",
                    embed=None,
                    view=None
                )
            
            await confirmation_request(
                description="⚠️ Are you sure you want to delete all data?",
                on_confirmation=confirm,
                on_reject=reject,
                channel=message.channel,
                ephemeral=False
            )
Source code from /home/daytona/workspace/source/mcdis_rcon/utils/discord_utils.py:25-69:
async def confirmation_request(
    description: str, *,
    on_confirmation: Callable = None,
    on_reject: Callable = None, 
    interaction: discord.Interaction = None,
    channel: discord.TextChannel = None,
    ephemeral: bool = True
):
    class confirmation_views(discord.ui.View):
        def __init__(self):
            super().__init__(timeout = None)

        @discord.ui.button(label = '✔', style = discord.ButtonStyle.gray)
        async def proceed_button(self, interaction: discord.Interaction, button: discord.ui.Button):
            if not on_confirmation: 
                await interaction.response.edit_message(delete_after = 0)
                return
            if inspect.iscoroutinefunction(on_confirmation):
                await on_confirmation(interaction)
            else:
                on_confirmation(interaction)
        
        @discord.ui.button(label = '✖', style = discord.ButtonStyle.red)
        async def reject_button(self, interaction: discord.Interaction, button: discord.ui.Button):
            if not on_reject:
                await interaction.response.edit_message(delete_after = 0)
                return
            if inspect.iscoroutinefunction(on_confirmation):
                await on_reject(interaction)
            else:
                on_reject(interaction)

Usage Examples

Admin-Only Command

import discord
from mcdis_rcon.utils.discord_utils import isAdmin

class mdaddon:
    def __init__(self, client):
        self.client = client
    
    async def on_message(self, message: discord.Message):
        if message.content == "!restart-all":
            # Check permissions
            if not isAdmin(message.author):
                await message.channel.send(
                    "❌ You must be an administrator to use this command"
                )
                return
            
            # Execute admin command
            for process in self.client.processes:
                if process.is_running():
                    await process.restart()
            
            await message.channel.send("✅ All processes restarted")

Logging to Custom Thread

import discord
import asyncio
from mcdis_rcon.utils.discord_utils import thread

class mdplugin:
    def __init__(self, process):
        self.process = process
        self.event_count = 0
    
    def listener_events(self, log: str):
        if "joined the game" in log:
            self.event_count += 1
            asyncio.create_task(self.log_event(log))
    
    async def log_event(self, log: str):
        # Create/get custom thread
        event_thread = await thread(
            name=f"Events - {self.process.name}",
            channel=self.process.client.panel,
            public=True
        )
        
        await event_thread.send(
            f"Event #{self.event_count}: {log}"
        )

Dangerous Operation Confirmation

import discord
from mcdis_rcon.utils.discord_utils import confirmation_request, isAdmin

class mdaddon:
    def __init__(self, client):
        self.client = client
    
    async def on_message(self, message: discord.Message):
        if message.content == "!wipe-server":
            # Check admin
            if not isAdmin(message.author):
                await message.channel.send("❌ Admin only")
                return
            
            async def confirmed(interaction):
                await interaction.response.edit_message(
                    content="🛠️ Wiping server...",
                    embed=None,
                    view=None
                )
                # Perform wipe
                # ...
                await interaction.followup.send("✅ Server wiped")
            
            async def rejected(interaction):
                await interaction.response.edit_message(
                    content="❌ Wipe cancelled",
                    embed=None,
                    view=None
                )
            
            await confirmation_request(
                description="⚠️ **WARNING:** This will permanently delete all server data!\nAre you sure?",
                on_confirmation=confirmed,
                on_reject=rejected,
                channel=message.channel,
                ephemeral=True
            )

Multi-Thread Organization

import discord
import asyncio
from mcdis_rcon.utils.discord_utils import thread

class mdaddon:
    def __init__(self, client):
        self.client = client
    
    async def on_ready(self):
        # Organize logs into categorized threads
        await self.setup_threads()
    
    async def setup_threads(self):
        # Create organizational threads
        self.info_thread = await thread(
            name="📄 Information",
            channel=self.client.panel,
            public=True
        )
        
        self.warn_thread = await thread(
            name="⚠️ Warnings",
            channel=self.client.panel,
            public=True
        )
        
        self.error_thread = await thread(
            name="🔴 Errors",
            channel=self.client.panel,
            public=True
        )
        
        await self.info_thread.send("Information logging started")

Best Practices

Use isAdmin() to protect sensitive commands and operations.
Always unarchive threads before trying to send messages to them.
Confirmation dialogs with ephemeral=False are visible to all users. Use ephemeral=True for sensitive operations.
The thread() function handles both finding existing threads and creating new ones, making it safe to call repeatedly.

Next Steps

File Utilities

File and path utilities

Minecraft Utilities

Minecraft-specific functions

Discord.py Views

Learn about Discord UI components

Build docs developers (and LLMs) love