From 2ce6fd239a73ec07e2eb69b6f7e4ae606a8674dc Mon Sep 17 00:00:00 2001 From: "KEI." Date: Fri, 31 Oct 2025 17:34:16 +0800 Subject: [PATCH 1/3] teaching.java --- teaching.java | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++ teaching.py | 75 --------------------- 2 files changed, 176 insertions(+), 75 deletions(-) create mode 100644 teaching.java delete mode 100644 teaching.py diff --git a/teaching.java b/teaching.java new file mode 100644 index 0000000..82ef5c8 --- /dev/null +++ b/teaching.java @@ -0,0 +1,176 @@ +package com.yourdomain; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.session.ReadyEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.Commands; +import net.dv8tion.jda.api.requests.GatewayIntent; +import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; + +import javax.security.auth.login.LoginException; +import java.awt.*; +import java.time.Instant; + +public class CompleteBot extends ListenerAdapter { + + public static void main(String[] args) throws LoginException { + String token = System.getenv("DISCORD_TOKEN"); + + if (token == null || token.isEmpty()) { + System.err.println("DISCORD_TOKEN environment variable is required"); + System.exit(1); + } + + JDA jda = JDABuilder.createDefault(token) + .setActivity(Activity.watching("for commands")) + .addEventListeners(new CompleteBot()) + .enableIntents( + GatewayIntent.MESSAGE_CONTENT, + GatewayIntent.GUILD_MEMBERS + ) + .build(); + + // Register slash commands + jda.updateCommands().addCommands( + Commands.slash("ping", "Check bot latency"), + Commands.slash("info", "Get bot information"), + Commands.slash("help", "Show help information") + ).queue(); + } + + @Override + public void onReady(ReadyEvent event) { + System.out.println("✅ Bot is ready! Connected to " + + event.getJDA().getGuilds().size() + " servers."); + } + + @Override + public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { + switch (event.getName()) { + case "ping": + handlePing(event); + break; + case "info": + handleInfo(event); + break; + case "help": + handleHelp(event); + break; + default: + event.reply("Unknown command").setEphemeral(true).queue(); + } + } + + private void handlePing(SlashCommandInteractionEvent event) { + long ping = event.getJDA().getGatewayPing(); + MessageCreateData message = new MessageCreateBuilder() + .setContent(String.format("🏓 Pong! Latency: %dms", ping)) + .build(); + event.reply(message).queue(); + } + + private void handleInfo(SlashCommandInteractionEvent event) { + JDA jda = event.getJDA(); + + MessageEmbed embed = new net.dv8tion.jda.api.entities.MessageEmbed( + null, + "Bot Information", + "A Java Discord bot built with JDA", + null, + null, + Color.CYAN.getRGB(), + new net.dv8tion.jda.api.entities.MessageEmbed.Thumbnail( + jda.getSelfUser().getEffectiveAvatarUrl(), + null, + 128, + 128 + ), + null, + null, + null, + new net.dv8tion.jda.api.entities.MessageEmbed.Footer( + "Requested by " + event.getUser().getEffectiveName(), + event.getUser().getEffectiveAvatarUrl(), + null + ), + null, + new net.dv8tion.jda.api.entities.MessageEmbed.Field[]{ + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "Servers", + String.valueOf(jda.getGuilds().size()), + true + ), + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "Users", + String.valueOf(jda.getUsers().size()), + true + ), + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "Uptime", + "Online since " + jda.getStatus().toString(), + false + ) + } + ); + + event.replyEmbeds(embed).queue(); + } + + private void handleHelp(SlashCommandInteractionEvent event) { + MessageEmbed embed = new net.dv8tion.jda.api.entities.MessageEmbed( + null, + "Help Guide", + "Available commands for this bot", + null, + null, + Color.ORANGE.getRGB(), + null, + null, + null, + null, + null, + null, + new net.dv8tion.jda.api.entities.MessageEmbed.Field[]{ + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "/ping", + "Check bot latency and response time", + false + ), + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "/info", + "Get information about the bot", + false + ), + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "/help", + "Show this help message", + false + ) + } + ); + + event.replyEmbeds(embed).setEphemeral(true).queue(); + } + + @Override + public void onMessageReceived(MessageReceivedEvent event) { + if (event.getAuthor().isBot()) return; + + String message = event.getMessage().getContentRaw(); + + // Simple response to mentions + if (message.contains(event.getJDA().getSelfUser().getAsMention())) { + event.getChannel().sendMessage( + "Hello! Use `/help` to see my commands." + ).queue(); + } + } +} diff --git a/teaching.py b/teaching.py deleted file mode 100644 index 13e9206..0000000 --- a/teaching.py +++ /dev/null @@ -1,75 +0,0 @@ -import discord -from discord.ext import commands -import os -from dotenv import load_dotenv - -load_dotenv() - -class MyBot(commands.Bot): - def __init__(self): - intents = discord.Intents.default() - intents.message_content = True - intents.members = True - super().__init__(command_prefix='!', intents=intents) - - async def setup_hook(self): - # Load cogs if you have any - # await self.load_extension('cogs.example') - await self.tree.sync() - print("Slash commands synced!") - - async def on_ready(self): - print(f'{self.user} is online!') - await self.change_presence( - activity=discord.Activity( - type=discord.ActivityType.watching, - name="for commands" - ) - ) - -bot = MyBot() - -# Basic commands -@bot.command() -async def ping(ctx): - """Check bot latency""" - latency = round(bot.latency * 1000) - await ctx.send(f'🏓 Pong! {latency}ms') - -@bot.command() -async def userinfo(ctx, member: discord.Member = None): - """Get user information""" - member = member or ctx.author - embed = discord.Embed(title=f"User Info - {member}", color=member.color) - embed.set_thumbnail(url=member.avatar.url) - embed.add_field(name="ID", value=member.id, inline=True) - embed.add_field(name="Joined", value=member.joined_at.strftime("%Y-%m-%d"), inline=True) - embed.add_field(name="Account Created", value=member.created_at.strftime("%Y-%m-%d"), inline=True) - await ctx.send(embed=embed) - -# Slash commands -@bot.tree.command(name="hello", description="Say hello to the bot") -async def hello_command(interaction: discord.Interaction): - await interaction.response.send_message(f"Hello {interaction.user.mention}!") - -@bot.tree.command(name="server", description="Get server information") -async def server_command(interaction: discord.Interaction): - guild = interaction.guild - embed = discord.Embed(title=guild.name, color=0x00ff00) - embed.add_field(name="Members", value=guild.member_count) - embed.add_field(name="Channels", value=len(guild.channels)) - embed.add_field(name="Roles", value=len(guild.roles)) - embed.set_thumbnail(url=guild.icon.url if guild.icon else None) - await interaction.response.send_message(embed=embed) - -# Error handling -@bot.event -async def on_command_error(ctx, error): - if isinstance(error, commands.CommandNotFound): - await ctx.send("Command not found! Use `!help` to see available commands.") - else: - await ctx.send("An error occurred while executing the command.") - print(f"Error: {error}") - -if __name__ == '__main__': - bot.run(os.getenv('DISCORD_TOKEN')) From ef2be845caee9d08d525de25a95f6128dfccf548 Mon Sep 17 00:00:00 2001 From: "KEI." Date: Fri, 31 Oct 2025 17:37:35 +0800 Subject: [PATCH 2/3] java teaching.md java teaching.md --- teaching.md | 1026 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 676 insertions(+), 350 deletions(-) diff --git a/teaching.md b/teaching.md index b3ba754..4fc7f20 100644 --- a/teaching.md +++ b/teaching.md @@ -1,15 +1,15 @@ -Discord Bot Development Tutorial +Discord Bot Development Tutorial - Java Version Table of Contents Introduction Prerequisites - Setting Up Your Bot + Setting Up Your Project Basic Bot Structure - Event Handlers + Event Listeners Commands @@ -19,384 +19,710 @@ Table of Contents Introduction -Discord bots are automated programs that interact with Discord servers. They can perform various tasks like moderating content, playing music, or providing information. This tutorial will guide you through creating your first Discord bot using Python. +This tutorial covers creating Discord bots using Java with JDA (Java Discord API). Java provides strong typing and better performance for complex bot applications. Prerequisites - Python 3.8 or higher + Java 17 or higher - A Discord account - - Basic Python knowledge - -Setting Up Your Bot -1. Create a Discord Application + Maven or Gradle build tool - Go to Discord Developer Portal + A Discord account - Click "New Application" + Basic Java knowledge - Name your application +Setting Up Your Project +Maven Configuration (pom.xml) +xml - Go to the "Bot" section + + + 4.0.0 + + com.yourdomain + discord-bot + 1.0.0 + + + 17 + 17 + 5.0.0-beta.20 + + + + + net.dv8tion + JDA + ${jda.version} + + + ch.qos.logback + logback-classic + 1.4.14 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 17 + 17 + + + + + + +Gradle Configuration (build.gradle) +gradle + +plugins { + id 'java' + id 'application' +} + +group = 'com.yourdomain' +version = '1.0.0' +sourceCompatibility = '17' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'net.dv8tion:JDA:5.0.0-beta.20' + implementation 'ch.qos.logback:logback-classic:1.4.14' +} + +application { + mainClass = 'com.yourdomain.Bot' +} - Click "Add Bot" +Basic Bot Structure +Simple Bot Example (BasicBot.java) +java - Copy the bot token (keep this secret!) +package com.yourdomain; -2. Install Required Libraries -bash +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.requests.GatewayIntent; -pip install discord.py python-dotenv +import javax.security.auth.login.LoginException; -Basic Bot Structure -Simple Bot Example (basic_bot.py) -python - -import discord -from discord.ext import commands -import os -from dotenv import load_dotenv - -# Load environment variables -load_dotenv() - -# Bot setup -intents = discord.Intents.default() -intents.message_content = True -bot = commands.Bot(command_prefix='!', intents=intents) - -@bot.event -async def on_ready(): - print(f'{bot.user} has connected to Discord!') - await bot.change_presence( - activity=discord.Activity( - type=discord.ActivityType.watching, - name="tutorial" - ) - ) - -@bot.command(name='hello') -async def hello_command(ctx): - """Responds with a greeting""" - await ctx.send(f'Hello {ctx.author.mention}!') - -@bot.command(name='ping') -async def ping_command(ctx): - """Checks bot latency""" - latency = round(bot.latency * 1000) - await ctx.send(f'Pong! {latency}ms') - -@bot.event -async def on_message(message): - # Ignore messages from the bot itself - if message.author == bot.user: - return - - # Process commands - await bot.process_commands(message) - -# Run the bot -if __name__ == '__main__': - bot.run(os.getenv('DISCORD_TOKEN')) - -Environment File (.env) -env - -DISCORD_TOKEN=your_bot_token_here - -Event Handlers -Common Event Examples -python - -import discord -from discord.ext import commands - -bot = commands.Bot(command_prefix='!', intents=discord.Intents.all()) - -@bot.event -async def on_ready(): - print(f'Logged in as {bot.user}') - -@bot.event -async def on_member_join(member): - channel = member.guild.system_channel - if channel: - await channel.send(f'Welcome {member.mention}!') - -@bot.event -async def on_member_remove(member): - print(f'{member} left the server') - -@bot.event -async def on_message_delete(message): - # Log deleted messages - print(f'Message deleted: {message.content}') - -@bot.event -async def on_command_error(ctx, error): - if isinstance(error, commands.CommandNotFound): - await ctx.send("Command not found!") - elif isinstance(error, commands.MissingPermissions): - await ctx.send("You don't have permission to use this command!") +public class BasicBot extends ListenerAdapter { + + public static void main(String[] args) throws LoginException { + String token = System.getenv("DISCORD_TOKEN"); + + if (token == null) { + System.out.println("Please set DISCORD_TOKEN environment variable"); + return; + } + + JDA jda = JDABuilder.createDefault(token) + .setActivity(Activity.watching("tutorial")) + .addEventListeners(new BasicBot()) + .enableIntents(GatewayIntent.MESSAGE_CONTENT) + .build(); + } + + @Override + public void onMessageReceived(MessageReceivedEvent event) { + // Ignore messages from bots + if (event.getAuthor().isBot()) return; + + String message = event.getMessage().getContentRaw(); + + // Simple command handling + if (message.equalsIgnoreCase("!ping")) { + event.getChannel().sendMessage("Pong!").queue(); + } else if (message.equalsIgnoreCase("!hello")) { + event.getChannel().sendMessage( + "Hello " + event.getAuthor().getAsMention() + "!" + ).queue(); + } + } +} + +Event Listeners +Comprehensive Event Handling +java + +package com.yourdomain; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.session.ReadyEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.requests.GatewayIntent; + +import javax.security.auth.login.LoginException; + +public class EventBot extends ListenerAdapter { + + public static void main(String[] args) throws LoginException { + String token = System.getenv("DISCORD_TOKEN"); + + JDA jda = JDABuilder.createDefault(token) + .setActivity(Activity.playing("with Java")) + .addEventListeners(new EventBot()) + .enableIntents( + GatewayIntent.MESSAGE_CONTENT, + GatewayIntent.GUILD_MEMBERS + ) + .build(); + } + + @Override + public void onReady(ReadyEvent event) { + System.out.println("Bot is ready! Logged in as: " + + event.getJDA().getSelfUser().getAsTag()); + } + + @Override + public void onGuildMemberJoin(GuildMemberJoinEvent event) { + Member member = event.getMember(); + event.getGuild().getSystemChannel().sendMessage( + "Welcome " + member.getAsMention() + " to the server!" + ).queue(); + } + + @Override + public void onGuildMemberRemove(GuildMemberRemoveEvent event) { + System.out.println("Member left: " + event.getUser().getAsTag()); + } + + @Override + public void onMessageReceived(MessageReceivedEvent event) { + if (event.getAuthor().isBot()) return; + + String message = event.getMessage().getContentRaw(); + + // Echo command + if (message.startsWith("!echo ")) { + String echoMessage = message.substring(6); + event.getChannel().sendMessage(echoMessage).queue(); + } + + // User info command + if (message.equalsIgnoreCase("!userinfo")) { + Member member = event.getMember(); + String response = String.format( + "User: %s\nID: %s\nJoined: %s", + member.getEffectiveName(), + member.getId(), + member.getTimeJoined().toString() + ); + event.getChannel().sendMessage(response).queue(); + } + } +} Commands -Basic Commands -python - -import discord -from discord.ext import commands - -bot = commands.Bot(command_prefix='!', intents=discord.Intents.default()) - -# Simple command -@bot.command() -async def info(ctx): - """Displays bot information""" - embed = discord.Embed( - title="Bot Information", - description="A simple Discord bot", - color=0x00ff00 - ) - embed.add_field(name="Creator", value="Your Name", inline=True) - embed.add_field(name="Server Count", value=len(bot.guilds), inline=True) - await ctx.send(embed=embed) - -# Command with arguments -@bot.command() -async def repeat(ctx, *, message): - """Repeats the given message""" - await ctx.send(message) - -# Command with error handling -@bot.command() -@commands.has_permissions(manage_messages=True) -async def clear(ctx, amount: int = 5): - """Clears specified number of messages""" - if amount > 100: - await ctx.send("Cannot delete more than 100 messages at once!") - return - - deleted = await ctx.channel.purge(limit=amount + 1) - await ctx.send(f'Deleted {len(deleted) - 1} messages', delete_after=5) - -@clear.error -async def clear_error(ctx, error): - if isinstance(error, commands.MissingPermissions): - await ctx.send("You need manage messages permission!") - -Slash Commands (Modern Approach) -python - -import discord -from discord import app_commands - -class MyBot(commands.Bot): - def __init__(self): - intents = discord.Intents.default() - intents.message_content = True - super().__init__(command_prefix='!', intents=intents) - - async def setup_hook(self): - # Sync slash commands - await self.tree.sync() - print("Slash commands synced!") - -bot = MyBot() - -@bot.tree.command(name="greet", description="Greet a user") -@app_commands.describe(user="The user to greet") -async def greet_command(interaction: discord.Interaction, user: discord.Member): - await interaction.response.send_message(f"Hello {user.mention}!") - -@bot.tree.command(name="server_info", description="Get server information") -async def server_info_command(interaction: discord.Interaction): - guild = interaction.guild - embed = discord.Embed(title=f"{guild.name} Info", color=0x00ff00) - embed.add_field(name="Members", value=guild.member_count) - embed.add_field(name="Created", value=guild.created_at.strftime("%Y-%m-%d")) - await interaction.response.send_message(embed=embed) +Advanced Command System +java + +package com.yourdomain; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.Commands; +import net.dv8tion.jda.api.requests.GatewayIntent; +import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; + +import javax.security.auth.login.LoginException; +import java.awt.*; +import java.time.Instant; +import java.util.concurrent.TimeUnit; + +public class CommandBot extends ListenerAdapter { + + public static void main(String[] args) throws LoginException { + String token = System.getenv("DISCORD_TOKEN"); + + JDA jda = JDABuilder.createDefault(token) + .setActivity(Activity.listening("commands")) + .addEventListeners(new CommandBot()) + .enableIntents(GatewayIntent.MESSAGE_CONTENT) + .build(); + + // Register slash commands + jda.updateCommands().addCommands( + Commands.slash("ping", "Check bot latency"), + Commands.slash("server", "Get server information"), + Commands.slash("user", "Get user information") + .addOption(OptionType.USER, "user", "The user to get info about", false), + Commands.slash("clear", "Clear messages") + .addOption(OptionType.INTEGER, "amount", "Number of messages to clear", true) + ).queue(); + } + + @Override + public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { + switch (event.getName()) { + case "ping": + handlePingCommand(event); + break; + case "server": + handleServerCommand(event); + break; + case "user": + handleUserCommand(event); + break; + case "clear": + handleClearCommand(event); + break; + default: + event.reply("Unknown command").setEphemeral(true).queue(); + } + } + + private void handlePingCommand(SlashCommandInteractionEvent event) { + long latency = event.getJDA().getGatewayPing(); + event.replyFormat("Pong! Gateway ping: %dms", latency).queue(); + } + + private void handleServerCommand(SlashCommandInteractionEvent event) { + MessageEmbed embed = new net.dv8tion.jda.api.entities.MessageEmbed( + null, + "Server Information", + null, + null, + null, + Color.GREEN.getRGB(), + null, + null, + null, + null, + new net.dv8tion.jda.api.entities.MessageEmbed.Footer( + "Requested by " + event.getUser().getEffectiveName(), + event.getUser().getEffectiveAvatarUrl(), + null + ), + null, + new net.dv8tion.jda.api.entities.MessageEmbed.Field[]{ + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "Server Name", + event.getGuild().getName(), + true + ), + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "Members", + String.valueOf(event.getGuild().getMemberCount()), + true + ), + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "Created", + event.getGuild().getTimeCreated().toString(), + false + ) + } + ); + + event.replyEmbeds(embed).queue(); + } + + private void handleUserCommand(SlashCommandInteractionEvent event) { + Member member = event.getOption("user") != null + ? event.getOption("user").getAsMember() + : event.getMember(); + + if (member == null) { + event.reply("User not found in this server").setEphemeral(true).queue(); + return; + } + + MessageEmbed embed = new net.dv8tion.jda.api.entities.MessageEmbed( + null, + "User Information: " + member.getEffectiveName(), + null, + null, + null, + Color.BLUE.getRGB(), + null, + null, + null, + null, + null, + null, + new net.dv8tion.jda.api.entities.MessageEmbed.Field[]{ + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "User ID", + member.getId(), + true + ), + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "Account Created", + member.getTimeCreated().toString(), + true + ), + new net.dv8tion.jda.api.entities.MessageEmbed.Field( + "Joined Server", + member.getTimeJoined().toString(), + true + ) + } + ); + + event.replyEmbeds(embed).queue(); + } + + private void handleClearCommand(SlashCommandInteractionEvent event) { + if (!event.getMember().hasPermission(net.dv8tion.jda.api.Permission.MESSAGE_MANAGE)) { + event.reply("You don't have permission to manage messages").setEphemeral(true).queue(); + return; + } + + int amount = event.getOption("amount").getAsInt(); + + if (amount < 1 || amount > 100) { + event.reply("Please provide a number between 1 and 100").setEphemeral(true).queue(); + return; + } + + TextChannel channel = event.getChannel().asTextChannel(); + channel.getHistory().retrievePast(amount + 1).queue(messages -> { + channel.purgeMessages(messages); + event.reply("Deleted " + amount + " messages").setEphemeral(true).queue(); + }); + } + + @Override + public void onMessageReceived(MessageReceivedEvent event) { + if (event.getAuthor().isBot()) return; + + String message = event.getMessage().getContentRaw(); + + // Legacy command support + if (message.equalsIgnoreCase("!legacyping")) { + long latency = event.getJDA().getGatewayPing(); + event.getChannel().sendMessage("Legacy ping: " + latency + "ms").queue(); + } + } +} Advanced Features -Cog System (Modular Structure) - -Create cogs/greetings.py: -python - -import discord -from discord.ext import commands - -class Greetings(commands.Cog): - def __init__(self, bot): - self.bot = bot - - @commands.Cog.listener() - async def on_member_join(self, member): - channel = member.guild.system_channel - if channel: - await channel.send(f'Welcome {member.mention}!') - - @commands.command() - async def hello(self, ctx): - await ctx.send(f'Hello {ctx.author.mention}!') - - @commands.command() - async def goodbye(self, ctx): - await ctx.send(f'Goodbye {ctx.author.mention}!') - -async def setup(bot): - await bot.add_cog(Greetings(bot)) - -Main bot file with cogs: -python - -import discord -from discord.ext import commands -import os -from dotenv import load_dotenv - -load_dotenv() - -class MyBot(commands.Bot): - def __init__(self): - intents = discord.Intents.all() - super().__init__(command_prefix='!', intents=intents) - - async def setup_hook(self): - # Load cogs - await self.load_extension('cogs.greetings') - # Add more cogs here - await self.tree.sync() - - async def on_ready(self): - print(f'{self.user} is ready!') - -bot = MyBot() - -# Run the bot -if __name__ == '__main__': - bot.run(os.getenv('DISCORD_TOKEN')) - -Database Integration Example -python - -import sqlite3 -import discord -from discord.ext import commands - -class DatabaseCog(commands.Cog): - def __init__(self, bot): - self.bot = bot - self.conn = sqlite3.connect('bot_data.db') - self.create_table() - - def create_table(self): - cursor = self.conn.cursor() - cursor.execute(''' - CREATE TABLE IF NOT EXISTS user_data ( - user_id INTEGER PRIMARY KEY, - message_count INTEGER DEFAULT 0 - ) - ''') - self.conn.commit() - - @commands.Cog.listener() - async def on_message(self, message): - if message.author.bot: - return +Database Integration with SQLite +java + +package com.yourdomain; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.session.ReadyEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.requests.GatewayIntent; + +import javax.security.auth.login.LoginException; +import java.sql.*; +import java.util.HashMap; +import java.util.Map; + +public class DatabaseBot extends ListenerAdapter { + private Connection connection; + private Map messageCountCache = new HashMap<>(); + + public static void main(String[] args) throws LoginException { + String token = System.getenv("DISCORD_TOKEN"); + + JDA jda = JDABuilder.createDefault(token) + .setActivity(Activity.playing("with databases")) + .addEventListeners(new DatabaseBot()) + .enableIntents(GatewayIntent.MESSAGE_CONTENT) + .build(); + } + + @Override + public void onReady(ReadyEvent event) { + initializeDatabase(); + System.out.println("Database bot is ready!"); + } + + private void initializeDatabase() { + try { + connection = DriverManager.getConnection("jdbc:sqlite:bot_data.db"); + Statement statement = connection.createStatement(); + + // Create tables if they don't exist + statement.execute(""" + CREATE TABLE IF NOT EXISTS user_stats ( + user_id TEXT PRIMARY KEY, + message_count INTEGER DEFAULT 0, + last_active TEXT + ) + """); + + statement.close(); + System.out.println("Database initialized successfully"); + } catch (SQLException e) { + System.err.println("Failed to initialize database: " + e.getMessage()); + } + } + + @Override + public void onMessageReceived(MessageReceivedEvent event) { + if (event.getAuthor().isBot()) return; + + String userId = event.getAuthor().getId(); + updateUserStats(userId); + + // Command handling + String message = event.getMessage().getContentRaw(); - cursor = self.conn.cursor() - cursor.execute(''' - INSERT OR REPLACE INTO user_data (user_id, message_count) - VALUES (?, COALESCE((SELECT message_count FROM user_data WHERE user_id = ?), 0) + 1) - ''', (message.author.id, message.author.id)) - self.conn.commit() - - @commands.command() - async def stats(self, ctx): - cursor = self.conn.cursor() - cursor.execute('SELECT message_count FROM user_data WHERE user_id = ?', (ctx.author.id,)) - result = cursor.fetchone() - count = result[0] if result else 0 - await ctx.send(f'You have sent {count} messages!') - -async def setup(bot): - await bot.add_cog(DatabaseCog(bot)) + if (message.equalsIgnoreCase("!mystats")) { + displayUserStats(event, userId); + } else if (message.equalsIgnoreCase("!leaderboard")) { + displayLeaderboard(event); + } + } + + private void updateUserStats(String userId) { + try { + // Update or insert user stats + String query = """ + INSERT OR REPLACE INTO user_stats (user_id, message_count, last_active) + VALUES (?, COALESCE((SELECT message_count FROM user_stats WHERE user_id = ?), 0) + 1, datetime('now')) + """; + + PreparedStatement statement = connection.prepareStatement(query); + statement.setString(1, userId); + statement.setString(2, userId); + statement.executeUpdate(); + statement.close(); + + } catch (SQLException e) { + System.err.println("Database error: " + e.getMessage()); + } + } + + private void displayUserStats(MessageReceivedEvent event, String userId) { + try { + String query = "SELECT message_count FROM user_stats WHERE user_id = ?"; + PreparedStatement statement = connection.prepareStatement(query); + statement.setString(1, userId); + ResultSet result = statement.executeQuery(); + + if (result.next()) { + int count = result.getInt("message_count"); + event.getChannel().sendMessage( + "You have sent " + count + " messages!" + ).queue(); + } else { + event.getChannel().sendMessage("No stats found for you").queue(); + } + + statement.close(); + } catch (SQLException e) { + event.getChannel().sendMessage("Error retrieving stats").queue(); + } + } + + private void displayLeaderboard(MessageReceivedEvent event) { + try { + String query = """ + SELECT user_id, message_count + FROM user_stats + ORDER BY message_count DESC + LIMIT 10 + """; + + Statement statement = connection.createStatement(); + ResultSet result = statement.executeQuery(query); + + StringBuilder leaderboard = new StringBuilder("**Message Leaderboard:**\n"); + int rank = 1; + + while (result.next()) { + String userId = result.getString("user_id"); + int count = result.getInt("message_count"); + + // Get user mention + String mention = "<@" + userId + ">"; + leaderboard.append(rank).append(". ").append(mention) + .append(" - ").append(count).append(" messages\n"); + rank++; + } + + if (rank == 1) { + event.getChannel().sendMessage("No leaderboard data available").queue(); + } else { + event.getChannel().sendMessage(leaderboard.toString()).queue(); + } + + statement.close(); + } catch (SQLException e) { + event.getChannel().sendMessage("Error retrieving leaderboard").queue(); + } + } +} + +Configuration Management +java + +package com.yourdomain; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class BotConfig { + private static final Properties properties = new Properties(); + + static { + try (InputStream input = BotConfig.class.getClassLoader() + .getResourceAsStream("config.properties")) { + if (input != null) { + properties.load(input); + } + } catch (IOException e) { + System.err.println("Failed to load config: " + e.getMessage()); + } + } + + public static String getToken() { + return System.getenv("DISCORD_TOKEN"); + } + + public static String getPrefix() { + return properties.getProperty("bot.prefix", "!"); + } + + public static String getActivity() { + return properties.getProperty("bot.activity", "Java Development"); + } + + public static boolean isDebug() { + return Boolean.parseBoolean(properties.getProperty("bot.debug", "false")); + } +} Best Practices -1. Error Handling -python - -@bot.event -async def on_command_error(ctx, error): - if isinstance(error, commands.CommandOnCooldown): - await ctx.send(f"This command is on cooldown. Try again in {error.retry_after:.2f}s.") - elif isinstance(error, commands.MissingRequiredArgument): - await ctx.send("Missing required arguments!") - elif isinstance(error, commands.BadArgument): - await ctx.send("Invalid arguments provided!") - else: - print(f"Unhandled error: {error}") - -# Command-specific error handling -@clear.error -async def clear_error(ctx, error): - if isinstance(error, commands.MissingPermissions): - await ctx.send("❌ You need manage messages permission!") - -2. Security -python - -# Use environment variables for tokens -import os -from dotenv import load_dotenv -load_dotenv() -TOKEN = os.getenv('DISCORD_TOKEN') - -# Limit bot permissions in Discord Developer Portal -# Use specific intents instead of all intents - -3. Performance -python - -# Use cogs for modular code -# Implement command cooldowns -@bot.command() -@commands.cooldown(1, 30, commands.BucketType.user) -async def slow_command(ctx): - await ctx.send("This command has a 30-second cooldown!") - -# Use tasks for periodic operations -from discord.ext import tasks - -@tasks.loop(minutes=30) -async def update_status(): - await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="the server")) - -@update_status.before_loop -async def before_update_status(): - await bot.wait_until_ready() +1. Proper Resource Management +java +package com.yourdomain; -Next Steps +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.events.session.ShutdownEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.requests.GatewayIntent; - Explore the discord.py documentation: https://discordpy.readthedocs.io/ +import javax.security.auth.login.LoginException; - Join the discord.py community: https://discord.gg/dpy +public class RobustBot extends ListenerAdapter { + private JDA jda; + + public static void main(String[] args) { + new RobustBot().start(); + } + + public void start() { + try { + String token = System.getenv("DISCORD_TOKEN"); + + jda = JDABuilder.createDefault(token) + .setActivity(Activity.playing("safely")) + .addEventListeners(this) + .enableIntents(GatewayIntent.MESSAGE_CONTENT) + .build(); + + // Add shutdown hook for graceful shutdown + Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown)); + + } catch (LoginException e) { + System.err.println("Failed to login: " + e.getMessage()); + } + } + + @Override + public void onShutdown(ShutdownEvent event) { + System.out.println("Bot is shutting down..."); + // Clean up resources + } + + private void shutdown() { + if (jda != null) { + jda.shutdown(); + } + } +} - Practice by adding more features: +2. Error Handling +java + +package com.yourdomain; + +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.hooks.EventListener; +import org.jetbrains.annotations.NotNull; + +public class ErrorHandlingListener implements EventListener { + + @Override + public void onEvent(@NotNull GenericEvent event) { + try { + if (event instanceof MessageReceivedEvent) { + handleMessage((MessageReceivedEvent) event); + } + } catch (Exception e) { + System.err.println("Error handling event: " + e.getMessage()); + e.printStackTrace(); + } + } + + private void handleMessage(MessageReceivedEvent event) { + // Your message handling logic here + if (event.getMessage().getContentRaw().equals("!error")) { + throw new RuntimeException("Test error"); + } + } +} + + +Next Steps - Music commands + Join JDA Community: https://discord.gg/jda - Moderation tools + Learn about: - Games and entertainment + Event systems in JDA - API integrations + Rate limiting and best practices -Remember to always test your bot thoroughly and follow Discord's Terms of Service and API guidelines + Advanced features like audio support -Please refer to teaching.py for the tutorial + Webhook integration +Remember to handle tokens securely and follow Discord's Developer Terms of Service From 77445e34cdc606d55d9deb17572ce94b21fb1fc2 Mon Sep 17 00:00:00 2001 From: "KEI." Date: Fri, 31 Oct 2025 17:38:21 +0800 Subject: [PATCH 3/3] java teaching.md java teaching.md --- teaching.md => java teaching.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename teaching.md => java teaching.md (100%) diff --git a/teaching.md b/java teaching.md similarity index 100% rename from teaching.md rename to java teaching.md