Overview
Administration commands provide powerful server management capabilities to staff members. These commands handle everything from user verification lookups to rule management and meal plan posting.
Permission Checks
Most admin commands use a custom permission check:
async fn executor_is_dev_or_admin ( ctx : Context <' _ >) -> Result < bool , Error > {
let member = ctx . author_member () . await . unwrap ();
// Check if user has semestermod or staff role
let has_perms = member
. roles
. contains ( & ctx . data () . config . roles . semestermodrole)
|| member . roles . contains ( & ctx . data () . config . roles . staffrole);
if has_perms {
Ok ( true )
} else if member
. permissions ( ctx ) ?
. contains ( Permissions :: ADMINISTRATOR )
{
return Ok ( true );
} else {
return Ok ( false );
}
}
Reference: src/commands/administration.rs:4-24
User Management
Email Lookup
Retrieve the email address a user verified with:
#[poise :: command(
slash_command,
prefix_command,
track_edits,
ephemeral,
required_permissions = "MANAGE_GUILD" ,
guild_only
)]
pub async fn getmail (
ctx : Context <' _ >,
user : serenity :: User ,
) -> Result <(), Error > {
let pool = & ctx . data () . db;
let uid = user . id . 0 as i64 ;
let db_user = sqlx :: query_as :: < _ , structs :: VerifiedUsers >(
"select * from verified_users where user_id = $1"
)
. bind ( uid )
. fetch_optional ( pool )
. await ? ;
let response = match db_user {
Some ( db_usr ) => format! ( "{} is verified with {}" , user . tag (), db_usr . user_email),
None => format! ( "{} is not verified" , user . tag ()),
};
ctx . say ( & response ) . await ? ;
Ok (())
}
Reference: src/commands/administration.rs:27-70
This command is ephemeral and only visible to the administrator who runs it, protecting user privacy.
XP Management
Manually set a userโs XP and level:
pub async fn set_xp (
ctx : Context <' _ >,
user : serenity :: User ,
xp : i64 ,
) -> Result <(), Error > {
let pool = & ctx . data () . db;
let uid = user . id . 0 as i64 ;
// Calculate level (100 XP per level)
let new_level = ( xp as f64 / 100.0 ) . floor () as i32 ;
// Upsert user XP
sqlx :: query ( "INSERT INTO user_xp (user_id, user_xp, user_level) VALUES ($1, $2, $3)" )
. bind ( uid )
. bind ( xp as f64 )
. bind ( new_level )
. execute ( pool )
. await ? ;
ctx . say ( & format! ( "Set XP of {} to {}" , user . tag (), xp ))
. await ? ;
Ok (())
}
Reference: src/commands/administration.rs:125-172
Command: /set-xp <user> <xp>
Meal Plan Management
Force Post Meal Plan
Manually trigger meal plan posting outside the automatic schedule:
pub async fn force_post_mensaplan ( ctx : Context <' _ >) -> Result <(), Error > {
let mensaplan_url = & ctx . data () . config . mealplan . url;
let mensaplan_channel = & ctx . data () . config . channels . mealplan;
// Fetch meal plan image
let mp_bytestream = utils :: fetch_mensaplan ( mensaplan_url ) . await ? ;
let now = chrono :: Local :: now ();
let today = now . date_naive () . format ( "%Y-%m-%d" ) . to_string ();
// Post to channel
let force_post = mensaplan_channel
. send_message ( & ctx , | msg | {
msg . add_file ( serenity :: AttachmentType :: Bytes {
data : std :: borrow :: Cow :: Borrowed ( & mp_bytestream ),
filename : "mensaplan.png" . to_string (),
})
})
. await ? ;
// Crosspost to announcement channel
force_post . crosspost ( & ctx ) . await ? ;
// Update database
sqlx :: query ( "INSERT INTO mensaplan (date, posted) VALUES ($1, $2) ON CONFLICT DO NOTHING" )
. bind ( & today )
. bind ( true )
. execute ( & ctx . data () . db)
. await ? ;
ctx . say ( & format! ( "Mensaplan fรผr {} gepostet" , today ))
. await ? ;
Ok (())
}
Reference: src/commands/administration.rs:184-221
Command: /force-post-mensaplan
Requirements: MANAGE_GUILD permission
Rule Management
The bot includes a comprehensive rule management system with the following subcommands:
/rule add Add a new rule to the database Automatically assigns the next rule number.
/rule remove Delete a rule by number Permanently removes the rule from the database.
/rule edit Modify an existing ruleโs text Updates the rule content while keeping the number.
/rule list Show all rules Displays numbered list of all server rules.
/rule get Retrieve a specific rule Shows a single rule by number.
/rule post Post rules embed to a channel Creates formatted embed with all rules.
Add Rule
pub async fn add (
ctx : Context <' _ >,
text : String ,
) -> Result <(), Error > {
let pool = & ctx . data () . db;
// Get highest rule number
let number = sqlx :: query_as :: < sqlx :: Postgres , structs :: Rules >(
"SELECT * FROM rules ORDER BY rule_number DESC LIMIT 1" ,
)
. fetch_optional ( pool )
. await ?
. map_or ( 1 , | n | n . rule_number + 1 );
let rule = structs :: Rules {
rule_number : number ,
rule_text : text ,
};
sqlx :: query ( "INSERT INTO rules (number, rule_text) VALUES ($1, $2)" )
. bind ( rule . rule_number)
. bind ( rule . rule_text)
. execute ( pool )
. await ? ;
ctx . send ( | m | {
m . embed ( | e | {
e . title ( "Regel hinzugefรผgt" );
e . description ( format! ( "Regel {} hinzugefรผgt" , rule . rule_number));
e
})
})
. await ? ;
Ok (())
}
Reference: src/commands/administration.rs:244-290
Post Rules Embed
pub async fn post (
ctx : Context <' _ >,
channel : Option < serenity :: GuildChannel >,
) -> Result <(), Error > {
let pool = & ctx . data () . db;
// Fetch all rules
let rules = sqlx :: query_as :: < sqlx :: Postgres , structs :: Rules >( "SELECT * FROM rules" )
. fetch_all ( pool )
. await ? ;
// Format rule list
let mut rule_list = String :: new ();
for rule in rules {
rule_list . push_str ( & format! ( "{}: {} \n " , rule . rule_number, rule . rule_text));
}
// Determine target channel
let rules_channel = match channel {
Some ( channel ) => channel . id,
None => ctx . data () . config . channels . rules,
};
// Post embed
rules_channel
. send_message ( & ctx , | m | {
m . embed ( | e | {
e . title ( "Regeln" );
e . description ( rule_list );
e
})
})
. await ? ;
Ok (())
}
Reference: src/commands/administration.rs:441-487
Re-verification Campaign
Trigger a mass re-verification for users who joined before a specific date:
pub async fn reverify (
ctx : Context <' _ >,
cutoff_date : String
) -> Result <(), Error > {
let cutoff_date = chrono :: NaiveDate :: parse_from_str ( & cutoff_date , "%Y-%m-%d" ) ? ;
// Get all users that joined before cutoff
let users = ctx . guild () . unwrap () . members ( & ctx , None , None ) . await ? ;
let users_to_reverify = users . iter () . filter_map ( | m | {
if m . joined_at . unwrap () . date_naive () < cutoff_date && ! m . user . bot {
Some ( m )
} else {
None
}
}) . collect :: < Vec < _ >>();
ctx . send ( | m | {
m . content ( "Reverification broadcast started" )
. embed ( | e | {
e . title ( "Reverification Broadcast" );
e . description ( format! (
"Reverification broadcast started for users that joined before {}, messaging {} users" ,
cutoff_date , users_to_reverify . len ()
));
e
})
}) . await ? ;
// Send DM to all users
for user in users_to_reverify {
user . user
. dm ( & ctx , | message | {
message
. content ( "๐ **Reverification Required**" )
. embed ( | embed | {
embed
. title ( "Student Status Verification" )
. description (
"Hello! To confirm that you're still enrolled, please complete the reverification process." ,
)
})
. components ( | c | {
c . create_action_row ( | a | {
a . create_button ( | b | {
b . style ( serenity :: ButtonStyle :: Success )
. label ( "Reverify" )
. custom_id ( "reverify" )
})
})
})
})
. await ? ;
}
Ok (())
}
Reference: src/commands/administration.rs:490-556
Command: /reverify <cutoff_date>
Format: YYYY-MM-DD (e.g., 2023-09-01)
System Commands
Run Shell Command
This command is restricted to bot owners only and can execute arbitrary shell commands.
#[poise :: command(
rename = "run" ,
slash_command,
owners_only,
guild_only
)]
pub async fn run_command (
ctx : Context <' _ >,
command : String ,
) -> Result <(), Error > {
ctx . defer_or_broadcast () . await ? ;
let output = tokio :: process :: Command :: new ( "sh" )
. arg ( "-c" )
. arg ( command )
. output ()
. await ? ;
let stdout = String :: from_utf8_lossy ( & output . stdout);
let stderr = String :: from_utf8_lossy ( & output . stderr);
ctx . send ( | msg | {
msg . embed ( | embed | {
embed
. title ( "Output" )
. field ( "Stdout" , format! ( "``` \n {} \n ```" , stdout ), false )
. field ( "Stderr" , format! ( "``` \n {} \n ```" , stderr ), false )
})
})
. await ? ;
Ok (())
}
Reference: src/commands/administration.rs:73-112
Command Summary
Command Permission Description /getmail <user>MANAGE_GUILD Retrieve userโs verified email /set-xp <user> <xp>Staff/Admin Manually set user XP /force-post-mensaplanMANAGE_GUILD Post meal plan immediately /rule add <text>Staff/Admin Add new rule /rule remove <number>Staff/Admin Delete rule /rule edit <number> <text>Staff/Admin Modify rule /rule listEveryone Show all rules /rule get <number>Everyone Get specific rule /rule post [channel]Staff/Admin Post rules embed /reverify <date>Staff/Admin Start re-verification campaign /run <command>Bot Owner Execute shell command
Security Considerations
Permission Layers Multiple permission checks prevent unauthorized access
Ephemeral Responses Sensitive data shown only to the command executor
Database Validation All queries use parameterized statements
Audit Trail All admin actions can be tracked through Discord audit log