diff --git a/examples/typing_indicator.py b/examples/typing_indicator.py new file mode 100644 index 0000000..26adc03 --- /dev/null +++ b/examples/typing_indicator.py @@ -0,0 +1,114 @@ +# examples/typing_indicator.py + +""" +An example bot demonstrating how to use the typing indicator with the Disagreement library. + +This bot will: +1. Respond to a command `!typing_test`. +2. Send a typing indicator to the channel where the command was invoked. +3. Simulate a long-running task while the typing indicator is active. + +To run this bot: +1. Follow the setup steps in 'basic_bot.py' to set your DISCORD_BOT_TOKEN. +2. Ensure you have the necessary intents (GUILDS, GUILD_MESSAGES, MESSAGE_CONTENT). +3. Run this script: python examples/typing_indicator.py +""" + +import asyncio +import os +import sys +import traceback + +# Add project root to path for local development +if os.path.join(os.getcwd(), "examples") == os.path.dirname(os.path.abspath(__file__)): + sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + +try: + import disagreement + from disagreement.ext import commands +except ImportError: + print( + "Failed to import disagreement. Make sure it's installed or PYTHONPATH is set correctly." + ) + sys.exit(1) + +try: + from dotenv import load_dotenv +except ImportError: # pragma: no cover - example helper + load_dotenv = None + print("python-dotenv is not installed. Environment variables will not be loaded") + +if load_dotenv: + load_dotenv() + +# --- Bot Configuration --- +BOT_TOKEN = os.environ.get("DISCORD_BOT_TOKEN") + +# --- Intents Configuration --- +intents = ( + disagreement.GatewayIntent.GUILDS + | disagreement.GatewayIntent.GUILD_MESSAGES + | disagreement.GatewayIntent.MESSAGE_CONTENT +) + +# --- Initialize the Client --- +if not BOT_TOKEN: + print("Error: The DISCORD_BOT_TOKEN environment variable is not set.") + sys.exit(1) + +client = disagreement.Client(token=BOT_TOKEN, intents=intents, command_prefix="!") + + +# --- Define a Cog for the typing indicator command --- +class TypingCog(commands.Cog): + def __init__(self, bot_client): + super().__init__(bot_client) + + @commands.command(name="typing_test") + async def typing_test_command(self, ctx: commands.CommandContext): + """Shows a typing indicator for 5 seconds.""" + await ctx.reply("Okay, I will pretend to be typing for 5 seconds.") + try: + async with client.typing(ctx.message.channel_id): + print(f"Displaying typing indicator in channel {ctx.message.channel_id} for 5 seconds.") + await asyncio.sleep(5) + print("Typing indicator stopped.") + await ctx.send("Done!") + except disagreement.HTTPException as e: + print(f"Failed to send typing indicator: {e}") + await ctx.reply("I couldn't show the typing indicator. I might be missing permissions.") + + +# --- Event Handlers --- + +@client.event +async def on_ready(): + """Called when the bot is ready and connected to Discord.""" + if client.user: + print(f"Bot is ready! Logged in as {client.user.username}") + else: + print("Bot is ready, but client.user is missing!") + print("------") + print("Typing indicator example bot is operational.") + print("Use the `!typing_test` command in a server channel.") + + +# --- Main Execution --- +async def main(): + print("Starting Typing Indicator Bot...") + try: + client.add_cog(TypingCog(client)) + await client.run() + except disagreement.AuthenticationError: + print("Authentication failed. Check your bot token.") + except Exception as e: + print(f"An unexpected error occurred: {e}") + traceback.print_exc() + finally: + if not client.is_closed(): + await client.close() + print("Bot has been shut down.") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file